prefetch: don't drop replacements for non-participating optional capture groups#13352
Draft
moonchen wants to merge 1 commit into
Draft
prefetch: don't drop replacements for non-participating optional capture groups#13352moonchen wants to merge 1 commit into
moonchen wants to merge 1 commit into
Conversation
Pattern::replace() rejected any replacement reference $N whose index was >= the value returned by the match. But that value is one past the highest capture group that *participated* in the match, not the number of groups the pattern defines. A trailing optional group such as "(\?.*)?" that does not participate -- e.g. a request with no query string -- lowers that count and makes a valid $N look out of range, so every such request logged "invalid reference in replacement string: $N" and silently dropped the prefetch. Validate $N references once at config-load time against the pattern's actual capture-group count (Regex::get_capture_count()), and at match time substitute an empty string for a group that did not participate instead of failing the whole replacement -- the documented PCRE2 semantics for an unmatched group. Also treat an unusable fetch-path-pattern, and invalid --fetch-count / --fetch-max / --fetch-overflow values, as configuration errors so the remap rule is refused at load rather than silently running with prefetch disabled; skip an empty expanded path instead of self-prefetching the original request path; and remove the now-dead process()/capture() helpers. Adds autests for the non-participating-group fix, the rejected over-limit pattern, and the empty-replacement skip.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Pattern::replace()in the prefetch plugin rejects any replacement reference$Nwhose index is>=the value returned by the match. But that value is one past the highest capture group that participated in the match, not the number of groups the pattern defines. A trailing optional group such as(\?.*)?that does not participate — e.g. a request with no query string — lowers that count and makes a perfectly valid$Nlook out of range.Concretely, with a remap like:
every matching request without a query string logs:
and the prefetch is silently dropped (the client is still served).
Fix
replace(): at match time, substitute an empty string for a group that did not participate instead of failing the whole replacement — the documented PCRE2 semantics for an unmatched group.compile(): validate$Nreferences once, at config-load time, against the pattern's actual capture-group count (Regex::get_capture_count()) — the correct place to catch a genuinely out-of-range reference such as$5against a 3-group pattern, and a pattern defining more groups than can be captured ($0..$9).Additional hardening
--fetch-path-pattern, and invalid--fetch-count/--fetch-max/--fetch-overflowvalues, as configuration errors: the remap instance fails to load instead of silently running with prefetch disabled. On a running server,traffic_ctl config reloadsafely rejects the bad config and keeps the current one.BgFetchturns into a self-prefetch of the original request path).Pattern::process()/Pattern::capture()helpers (no callers).Tests
Adds three autests under
tests/gold_tests/pluginTest/prefetch/:prefetch_optional_group— the non-participating optional-group case (fails on the pre-fix code).prefetch_bad_pattern_refused— an over-limit (10-group) pattern makes ATS refuse to load the remap.prefetch_empty_replacement— an empty-collapsing replacement is logged and skipped, not self-prefetched.Built locally (macOS, PCRE2); all prefetch autests pass. Draft pending CI.