Skip to content

Fix parser out-of-bounds reads - #131

Open
laurikari wants to merge 5 commits into
masterfrom
fix/parser-oob
Open

Fix parser out-of-bounds reads#131
laurikari wants to merge 5 commits into
masterfrom
fix/parser-oob

Conversation

@laurikari

Copy link
Copy Markdown
Owner

Updated retest so regncomp is called with a strictly non‑padded input buffer, rather than passing a NUL terminated buffer. With that in place, AddressSanitizer exposed several out‑of‑bounds reads in the parser.

Added a few additional parser test cases around atoms, bracket expressions, and escapes.

Then fixed the parser, adding explicit bounds checks and better error handling.

@laurikari
laurikari requested a review from dag-erling January 31, 2026 22:07
Comment thread lib/tre-parse.c Outdated
Comment thread lib/tre-parse.c Outdated
@dag-erling

Copy link
Copy Markdown
Collaborator

ping @laurikari

laurikari added 5 commits May 14, 2026 20:51
By passing exact-length unpadded inputs to regncomp, we can catch out-of-bounds
reads using -fsanitize=address.
Many tools expect source files to have some valid encoding (like UTF-8), this
makes them happy.
These were all found with the latest retest.c using the Address Sanitizer with:

  CFLAGS=-O1 -g -fsanitize=address -fno-omit-frame-pointer
  LDFLAGS=-fsanitize=address
Comment thread tests/retest.c
buf = xmalloc(len * sizeof(CHAR_T));
if (buf == NULL)
return REG_ESPACE;
memcpy(buf, data, len * sizeof(CHAR_T));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is likely to still be null-terminated at least some of the time. It would be better to allocate a slightly larger buffer and deliberately set the first out-of-bounds character to something non-zero.

@dag-erling dag-erling May 15, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static int
wrap_regcomp(regex_t *preg, const CHAR_T *data, size_t len, int cflags)
{
#ifdef HAVE_REGNCOMP
  CHAR_T *buf;
  int ret;

  if (use_regncomp)
    {
      buf = xmalloc((len + 1) * sizeof(CHAR_T));
      if (buf == NULL)
	return REG_ESPACE;
      memcpy(buf, data, len * sizeof(CHAR_T));
      buf[len] = (CHAR_T)~0;
      ret = tre_regncomp(preg, buf, len, cflags);
      xfree(buf);
      return ret;
    }
#endif /* HAVE_REGNCOMP */
  return tre_regcomp(preg, data, cflags);
}

@dag-erling dag-erling added the bug label May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants