Refuse to rewrite when MaxSubmatch() is too large. Change-Id: I76f1d92586c3e0f4895ceb16fb019951843497f8 Reviewed-on: https://code-review.googlesource.com/c/re2/+/56870 Reviewed-by: Paul Wankadia <junyer@google.com>
diff --git a/re2/re2.cc b/re2/re2.cc index 69258af..35fd1cc 100644 --- a/re2/re2.cc +++ b/re2/re2.cc
@@ -405,6 +405,8 @@ const StringPiece& rewrite) { StringPiece vec[kVecSize]; int nvec = 1 + MaxSubmatch(rewrite); + if (nvec > 1 + re.NumberOfCapturingGroups()) + return false; if (nvec > static_cast<int>(arraysize(vec))) return false; if (!re.Match(*str, 0, str->size(), UNANCHORED, vec, nvec)) @@ -425,6 +427,8 @@ const StringPiece& rewrite) { StringPiece vec[kVecSize]; int nvec = 1 + MaxSubmatch(rewrite); + if (nvec > 1 + re.NumberOfCapturingGroups()) + return false; if (nvec > static_cast<int>(arraysize(vec))) return false; @@ -497,9 +501,10 @@ std::string* out) { StringPiece vec[kVecSize]; int nvec = 1 + MaxSubmatch(rewrite); + if (nvec > 1 + re.NumberOfCapturingGroups()) + return false; if (nvec > static_cast<int>(arraysize(vec))) return false; - if (!re.Match(text, 0, text.size(), UNANCHORED, vec, nvec)) return false; @@ -1012,8 +1017,8 @@ int n = (c - '0'); if (n >= veclen) { if (options_.log_errors()) { - LOG(ERROR) << "requested group " << n - << " in regexp " << rewrite.data(); + LOG(ERROR) << "invalid substitution \\" << n + << " from " << veclen << " groups"; } return false; }
diff --git a/re2/testing/re2_test.cc b/re2/testing/re2_test.cc index 52e1f6f..ec457fb 100644 --- a/re2/testing/re2_test.cc +++ b/re2/testing/re2_test.cc
@@ -224,6 +224,15 @@ ASSERT_EQ(s, "'foo'"); } +TEST(RE2, MaxSubmatchTooLarge) { + std::string s; + ASSERT_FALSE(RE2::Extract("foo", "f(o+)", "\\1\\2", &s)); + s = "foo"; + ASSERT_FALSE(RE2::Replace(&s, "f(o+)", "\\1\\2")); + s = "foo"; + ASSERT_FALSE(RE2::GlobalReplace(&s, "f(o+)", "\\1\\2")); +} + TEST(RE2, Consume) { RE2 r("\\s*(\\w+)"); // matches a word, possibly proceeded by whitespace std::string word;