From: Andy Heninger Date: Fri, 9 Mar 2018 18:39:14 +0000 (+0000) Subject: ICU-13632 regex out-of-bounds memory reference fix. X-Git-Tag: release-62-rc~218 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0d32dd8f05e3d7b4f10cdb386b12d4cec84725af;p=icu ICU-13632 regex out-of-bounds memory reference fix. X-SVN-Rev: 41088 --- diff --git a/icu4c/source/i18n/uregex.cpp b/icu4c/source/i18n/uregex.cpp index 0c26bdf656d..12f36894d71 100644 --- a/icu4c/source/i18n/uregex.cpp +++ b/icu4c/source/i18n/uregex.cpp @@ -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(); diff --git a/icu4c/source/test/intltest/regextst.cpp b/icu4c/source/test/intltest/regextst.cpp index b1d75537cfd..4b0a2f43fca 100644 --- a/icu4c/source/test/intltest/regextst.cpp +++ b/icu4c/source/test/intltest/regextst.cpp @@ -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 */ diff --git a/icu4c/source/test/intltest/regextst.h b/icu4c/source/test/intltest/regextst.h index 7e98cd6226f..cfa62d70384 100644 --- a/icu4c/source/test/intltest/regextst.h +++ b/icu4c/source/test/intltest/regextst.h @@ -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);