]> granicus.if.org Git - icu/commitdiff
ICU-13632 regex out-of-bounds memory reference fix.
authorAndy Heninger <andy.heninger@gmail.com>
Fri, 9 Mar 2018 18:39:14 +0000 (18:39 +0000)
committerAndy Heninger <andy.heninger@gmail.com>
Fri, 9 Mar 2018 18:39:14 +0000 (18:39 +0000)
X-SVN-Rev: 41088

icu4c/source/i18n/uregex.cpp
icu4c/source/test/intltest/regextst.cpp
icu4c/source/test/intltest/regextst.h

index 0c26bdf656d8c0942e71bdc21f45b2aa1233c2f8..12f36894d71c4e45ee0de38c0ed1ffba210a2ca4 100644 (file)
@@ -1465,8 +1465,10 @@ int32_t RegexCImpl::appendReplacement(RegularExpression    *regexp,
 
         int32_t groupNum  = 0;
         U_ASSERT(c == DOLLARSIGN);
-        UChar32 c32;
-        U16_GET(replacementText, 0, replIdx, replacementLength, c32);
+        UChar32 c32 = -1;
+        if (replIdx < replacementLength) {
+            U16_GET(replacementText, 0, replIdx, replacementLength, c32);
+        }
         if (u_isdigit(c32)) {
             int32_t numDigits = 0;
             int32_t numCaptureGroups = m->fPattern->fGroupMap->size();
index b1d75537cfdc20bbfca56ef61ec7bb396282e5a1..4b0a2f43fca2891bb94cb5d8007a4abd12b3aae0 100644 (file)
@@ -103,6 +103,7 @@ void RegexTest::runIndexedTest( int32_t index, UBool exec, const char* &name, ch
     TESTCASE_AUTO(NamedCaptureLimits);
     TESTCASE_AUTO(TestBug12884);
     TESTCASE_AUTO(TestBug13631);
+    TESTCASE_AUTO(TestBug13632);
     TESTCASE_AUTO_END;
 }
 
@@ -5831,5 +5832,23 @@ void RegexTest::TestBug13631() {
     }
 }
 
+// Bug 13632 Out of bounds memory reference if a replacement string ends with a '$',
+//           where a following group specification would be expected.
+//           Failure shows when running the test under Clang's Address Sanitizer.
+
+void RegexTest::TestBug13632() {
+    UErrorCode status = U_ZERO_ERROR;
+    URegularExpression *re = uregex_openC(" ", 0, nullptr, &status);
+    const char16_t *sourceString = u"Hello, world.";
+    uregex_setText(re, sourceString, u_strlen(sourceString), &status);
+
+    const int32_t destCap = 20;
+    char16_t dest[destCap] = {};
+    const char16_t replacement[] = {u'x', u'$'};    // Not nul terminated string.
+    uregex_replaceAll(re, replacement, 2, dest, destCap, &status);
+
+    assertEquals("", U_REGEX_INVALID_CAPTURE_GROUP_NAME, status);
+    uregex_close(re);
+}
 
 #endif  /* !UCONFIG_NO_REGULAR_EXPRESSIONS  */
index 7e98cd6226fb4491a9fe4bf94215191bc5c4c516..cfa62d70384ba9cc731d517314cd1fd60a54c473 100644 (file)
@@ -58,7 +58,8 @@ public:
     virtual void TestBug11480();
     virtual void TestBug12884();
     virtual void TestBug13631();
-    
+    virtual void TestBug13632();
+
     // The following functions are internal to the regexp tests.
     virtual void assertUText(const char *expected, UText *actual, const char *file, int line);
     virtual void assertUTextInvariant(const char *invariant, UText *actual, const char *file, int line);