moonchen commented on code in PR #13441:
URL: https://github.com/apache/trafficserver/pull/13441#discussion_r3738300533


##########
src/tsutil/Regex.cc:
##########
@@ -205,6 +205,13 @@ RegexMatches::operator[](size_t index) const
   }
 
   PCRE2_SIZE *ovector = 
pcre2_get_ovector_pointer(_MatchData::get(_match_data));
+
+  // A group that did not participate in the match has an unset offset. This 
happens for an optional
+  // group that precedes a participating one, so a valid index is not enough 
to guarantee an offset.
+  if (PCRE2_UNSET == ovector[2 * index]) {
+    return std::string_view();
+  }
+
   return std::string_view(_subject.data() + ovector[2 * index], ovector[2 * 
index + 1] - ovector[2 * index]);

Review Comment:
   Neither case is reachable.
   
   Unset offsets are set as a pair — pcre2api: *"both values in the offset 
pairs corresponding to unused groups are set to PCRE2_UNSET."* Checking the 
start is sufficient.
   
   `end < start` requires `\K` inside a lookaround, which PCRE2 has rejected at 
compile time since 10.38 (`\K is not allowed in lookarounds`) unless 
`PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK` is set; ATS never calls 
`pcre2_set_compile_extra_options`. With the option forced on anyway, PCRE2 
clamps rather than inverting — `foo(?=bar\K)bar` on `"foobar"` yields `[6,6)`, 
not `[6,3)`.
   
   There is a real gap next to this one, though. The index is checked against 
the allocated ovector count, but `pcre2_match()` writes only up to the highest 
participating group, so an index past the pattern's groups reads the 
uninitialized tail of `_buffer` — the UNSET check doesn't catch it. Follow-up: 
#13517.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to