pcre2posix: do not truncate the subject length to int in regexec by ManoharPaturi · Pull Request #1022 · PCRE2Project/pcre2 · GitHub
Skip to content

pcre2posix: do not truncate the subject length to int in regexec - #1022

Merged
NWilson merged 3 commits into
PCRE2Project:mainfrom
ManoharPaturi:fix-posix-regexec-length
Sep 30, 2026
Merged

NWilson merged 3 commits into
PCRE2Project:mainfrom
ManoharPaturi:fix-posix-regexec-length

Conversation

@ManoharPaturi

Copy link
Copy Markdown
Contributor

Problem

pcre2_regexec() truncates the subject length to int (src/pcre2posix.c):

int rc, so, eo;
...
eo = (int)strlen(string);
...
rc = pcre2_match(..., (PCRE2_SPTR)string + so, (eo - so), 0, options, md, NULL);

For a NUL-terminated subject longer than INT_MAX bytes (the non-REG_STARTEND path), (int)strlen wraps negative and eo - so sign-extends to a huge PCRE2_SIZE, so pcre2_match scans far past the subject end.

Reproduced on an ASan+UBSan build with a >2GiB subject and a non-matching pattern: runtime error: addition of unsigned offset ... overflowed in pcre2_match.c, then SEGV ... READ in _platform_memchr <- pcre2_match_8 <- pcre2_regexec pcre2posix.c:419.

Fix

Hold so/eo as PCRE2_SIZE and drop the cast — two lines. The regmatch_t output fields keep their POSIX-mandated int (offsets beyond 2GiB cannot be represented there anyway); what is fixed is the length passed to the matcher, so over-long subjects now return a clean REG_NOMATCH instead of crashing.

Verification

Full ctest suite passes; the ASan repro above returns REG_NOMATCH after the fix. Companion to #1020 (same int-width class, different file and API, more severe effect).

Copilot AI balanced review requested due to automatic review settings September 29, 2026 16:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@NWilson

NWilson commented Sep 30, 2026

Copy link
Copy Markdown
Member

@ManoharPaturi

Copy link
Copy Markdown
Contributor Author

Thanks! Both points taken. Added the rm_so and rm_eo validation on the REG_STARTEND path and the INT_MAX clamp on the output side so oversized ovector values become minus one instead of wrapping. Suite green, pushed.

Comment thread src/pcre2posix.c Outdated
Comment on lines +435 to +436
pmatch[i].rm_so = (ovector[i * 2] == PCRE2_UNSET || ovector[i * 2] + so > INT_MAX) ? -1 : (int)(ovector[i * 2] + so);
pmatch[i].rm_eo = (ovector[i * 2 + 1] == PCRE2_UNSET || ovector[i * 2 + 1] + so > INT_MAX) ? -1 : (int)(ovector[i * 2 + 1] + so);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ooh, sorry! I'm going to be annoying, and request one more change actually.

If one of the two offsets is out-of-bounds for INT_MAX, then both fields should be set to -1.

(I also like to cast (PCRE2_SIZE)INT_MAX so there isn't a type mismatch on the comparison.)

Suggested change
pmatch[i].rm_so = (ovector[i * 2] == PCRE2_UNSET || ovector[i * 2] + so > INT_MAX) ? -1 : (int)(ovector[i * 2] + so);
pmatch[i].rm_eo = (ovector[i * 2 + 1] == PCRE2_UNSET || ovector[i * 2 + 1] + so > INT_MAX) ? -1 : (int)(ovector[i * 2 + 1] + so);
if (ovector[i * 2] == PCRE2_UNSET || ovector[i * 2] + so > (PCRE2_SIZE)INT_MAX || ovector[i * 2 + 1] == PCRE2_UNSET || ovector[i * 2 + 1] + so > (PCRE2_SIZE)INT_MAX)
{
pmatch[i].rm_so = -1;
pmatch[i].rm_eo = -1;
}
else
{
pmatch[i].rm_so = (int)(ovector[i * 2] + so);
pmatch[i].rm_eo = (int)(ovector[i * 2 + 1] + so);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No worries at all, that is a better shape. Pushed your version, both fields now go to minus one together and the comparisons use the explicit cast. Suite green.

@NWilson

NWilson commented Sep 30, 2026

Copy link
Copy Markdown
Member

I opened #1025 to make my TODO lists a bit more public.

@ManoharPaturi

Copy link
Copy Markdown
Contributor Author

@NWilson
NWilson merged commit 441bf12 into PCRE2Project:main Sep 30, 2026
40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants