Skip to content

Limit resources used by regex_remap to prevent crashes on stack overflow - #5762

Merged
SolidWallOfCode merged 2 commits into
apache:masterfrom
SolidWallOfCode:regex_remap-pcre-fix
Aug 15, 2019
Merged

Limit resources used by regex_remap to prevent crashes on stack overflow#5762
SolidWallOfCode merged 2 commits into
apache:masterfrom
SolidWallOfCode:regex_remap-pcre-fix

Conversation

@SolidWallOfCode

Copy link
Copy Markdown
Member

This was the cause of a production crash. The root using a negative matching regular expression in regex_remap. Because of the nature of such things, this will recurse roughly once for every character in the URL. This consumes roughly 500 bytes (according to the PCRE documentation) so 2000 or so is enough to blow the ATS stack.

With this change, the recursion is limited to protect the stack and an error logged when the regular expression fails to match due to hitting this limit.

This also adds an AuTest to validate the fix (without it, the second request will crash ATS).

@SolidWallOfCode SolidWallOfCode added this to the 9.0.0 milestone Aug 2, 2019
@SolidWallOfCode SolidWallOfCode self-assigned this Aug 2, 2019
@randall

randall commented Aug 2, 2019

Copy link
Copy Markdown
Contributor

[approve ci autest]

@SolidWallOfCode

Copy link
Copy Markdown
Member Author

This is stuck on a bug in AuTest, @macisasandwich is working on it.

tr.Processes.Default.Streams.stdout = "gold/regex_remap_smoke.gold"
tr.StillRunningAfter = ts

# Crash test.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To address the TS failure in Autest, you need to this to test your diags.log
ts.Disk.diags_log.Content = Testers.ContainsExpression(<expression you want>, <description>)

Test.Summary = '''
Test regex_remap
'''

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can add Test.Variables.Autest.NormalizeKill = 0 to work around the -9 sigkill return code on microserver while I try to work up a fix.

_extra = pcre_study(_rex, 0, &error);
if ((_extra == nullptr) && (error != nullptr)) {
_extra = pcre_study(_rex, PCRE_STUDY_EXTRA_NEEDED, &error);
if (error != nullptr) {

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.

Should you still have a test somewhere to return if _extra is nullptr before you dereference it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No. Because of the PCRE_STUDY_EXTRA_NEEDED, the returned value will only be nullptr if memory is exhausted, in which case we're already over the cliff.

@shinrich shinrich left a comment

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.

Looks good save for the nullptr check comment.

@SolidWallOfCode
SolidWallOfCode merged commit 3418b7e into apache:master Aug 15, 2019
bneradt pushed a commit to bneradt/trafficserver that referenced this pull request Sep 9, 2026
Moving regex_remap to the shared Regex context changes JIT stack
behavior beyond the matching-work regression. The original 3 KB
lookahead request already failed before the PCRE2 conversion and is
part of the crash guard from apache#5762, not a new redirect regression.

This patch restores the per-instance context and non-redirecting crash
expectation while retaining the removal of the 1750 work limit. The
independent log assertions identify resource exhaustion for the crash
guard and match-work exhaustion for the separate nested-quantifier
rule. The ordinary long-query coverage and other review improvements
remain in place; the shared-context change belongs in a separate PR.

Co-authored-by: Codex Astra Medium
bneradt added a commit that referenced this pull request Sep 9, 2026
Valid URLs with long query strings can miss regex_remap redirects.
The old PCRE matcher used recursive calls for backtracking, so its
recursion limit was reduced from 2047 to 1750 after stack crashes in
#6819. The PCRE2 conversion in #12575 accidentally reused 1750 as a
matching-work limit, causing ordinary long queries that previously
matched to fail.

This patch removes the work-limit override while retaining the
per-instance match context and existing JIT stack behavior. PCRE2's
normal work default is 10 million, allowing more worst-case CPU time
per match while still bounding excessive backtracking. Its depth and
heap limits remain intact. Since PCRE2 10.30, interpreter backtracking
frames reside on the heap; JIT ignores the depth limit and uses a
separately bounded stack. The old stack-derived value therefore does
not translate into a suitable matching-work budget.

This patch adds long-query redirect and capture-preservation coverage
and extends the excessive-backtracking input to exercise the default
work limit. The original 3 KB lookahead case remains a non-redirecting
crash guard from #5762; its failure predates the PCRE2 conversion.
Independent rule-specific log assertions preserve both checks.

Fixes: #13651
Reported-by: Vinith Bindiganavale
Co-authored-by: Codex Astra Medium
cmcfarlen pushed a commit to cmcfarlen/trafficserver that referenced this pull request Sep 9, 2026
Valid URLs with long query strings can miss regex_remap redirects.
The old PCRE matcher used recursive calls for backtracking, so its
recursion limit was reduced from 2047 to 1750 after stack crashes in
apache#6819. The PCRE2 conversion in apache#12575 accidentally reused 1750 as a
matching-work limit, causing ordinary long queries that previously
matched to fail.

This patch removes the work-limit override while retaining the
per-instance match context and existing JIT stack behavior. PCRE2's
normal work default is 10 million, allowing more worst-case CPU time
per match while still bounding excessive backtracking. Its depth and
heap limits remain intact. Since PCRE2 10.30, interpreter backtracking
frames reside on the heap; JIT ignores the depth limit and uses a
separately bounded stack. The old stack-derived value therefore does
not translate into a suitable matching-work budget.

This patch adds long-query redirect and capture-preservation coverage
and extends the excessive-backtracking input to exercise the default
work limit. The original 3 KB lookahead case remains a non-redirecting
crash guard from apache#5762; its failure predates the PCRE2 conversion.
Independent rule-specific log assertions preserve both checks.

Fixes: apache#13651
Reported-by: Vinith Bindiganavale
Co-authored-by: Codex Astra Medium
(cherry picked from commit 7ed34a3)
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.

4 participants