Skip to content

Set a hard limit on input length - #129

Merged
laurikari merged 2 commits into
laurikari:masterfrom
dag-erling:des/limits
Jan 7, 2026
Merged

Set a hard limit on input length#129
laurikari merged 2 commits into
laurikari:masterfrom
dag-erling:des/limits

Conversation

@dag-erling

Copy link
Copy Markdown
Collaborator

If given input longer than INT_MAX, we will happily accept it and then crash when we increment our position beyond INT_MAX and it rolls around to INT_MIN. This pull request adds checks to the matching engines to force them to stop before overflowing, cleans up the outer API layers to prepare for a more thorough overhaul of the internals later, and adds tests of both this input limit and the regular expression length limit we introduced earlier.

In theory, there is no limit on the size of the input given to our tnfa.
In practice, we need to be able to report the boundaries of matches and
capture groups, and store checkpoints for backtracking, so the length of
our input (or rather, the position of the last character) needs to fit
in the data types we use for these purposes:

* Matches are reported using `regoff_t`, which we currently define to
  `int` (although it is usually defined to `off_t` or equivalent in
  system `<regex.h>`).

* TRE internals consistently use `int` rather than `size_t` for
  position-related information.

The practical consequence of this is that inputs larger than `INT_MAX`
result in integer overflow, which cause the matching function to either
return an incorrect result or crash.  This may have been acceptable
when TRE was first written and memory sizes were measured in megabytes
rather than gigabytes, but that is no longer the case.

In the long term, we should switch to `off_t` for `regoff_t` and `size_t`
(or `ssize_t` since TRE internals occasionally use -1 as a sentinel) for
everything else.  For now, we start by switching from `int` to `ssize_t`
at the edges and setting a hard limit on the string length.  If the
length of the input is known in advance, we clip it to the maximum;
otherwise, we treat reaching the maximum the same as we would treat
encountering a terminating null character.
This new test program attempts to a) compile regular expressions of
increasing lengths and b) match a small regular expression against
inputs of increasing lengths and verifies that we get the expected
result (`REG_OK`, `REG_ESPACE`, or `REG_NOMATCH`) depending on the
exact length being tested.

This allows us to drop the `toolong` tests in `retest` and reduce
`MAXSTRSIZE` back down to only what `retest` itself needs.
@dag-erling

dag-erling commented Jan 7, 2026

Copy link
Copy Markdown
Collaborator Author

@laurikari have you had a chance to take a look at this?

@laurikari

Copy link
Copy Markdown
Owner

In tre-match-utils.h, max changes from int to size_t. That means max <= 0 will never and I suspect tre_mbrtowc will read past the intended length. I think max needs to stay signed here.

@dag-erling

Copy link
Copy Markdown
Collaborator Author

In tre-match-utils.h, max changes from int to size_t. That means max <= 0 will never and I suspect tre_mbrtowc will read past the intended length. I think max needs to stay signed here.

I'm not sure this is a problem. If we assume that pos <= len then max cannot start out negative anyway. If pos can exceed len then we should deal with that before we get to max = len - pos.

@laurikari

Copy link
Copy Markdown
Owner

I'm not sure this is a problem. If we assume that pos <= len then max cannot start out negative anyway. If pos can exceed len then we should deal with that before we get to max = len - pos.

Agreed, I was not looking at the full picture.

@laurikari
laurikari merged commit 5ac2805 into laurikari:master Jan 7, 2026
3 checks passed
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