Fix undefined behavior front() call
Cherry pick undefined behavior fix from ICU PR3752
Upstream fix https://github.com/unicode-org/icu/pull/3752
Bug: 451657601
Change-Id: I2d7bad25d0c924dd57e63dce342e5e2e08cfe224
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/deps/icu/+/7099182
Reviewed-by: Philip Jägenstedt <foolip@chromium.org>
diff --git a/README.chromium b/README.chromium
index 9e6581d..fd9ca16 100644
--- a/README.chromium
+++ b/README.chromium
@@ -261,3 +261,8 @@
patches/unnecessary_virtual_specifier.patch
- https://issues.chromium.org/issues/403236787
- https://patch-diff.githubusercontent.com/raw/unicode-org/icu/pull/3489.diff
+
+12. Patch incorrect call to front().
+ - patches/uloc.patch
+ - https://g-issues.chromium.org/issues/451657601
+ - https://patch-diff.githubusercontent.com/raw/unicode-org/icu/pull/3752.diff
diff --git a/patches/uloc.patch b/patches/uloc.patch
new file mode 100644
index 0000000..000e852
--- /dev/null
+++ b/patches/uloc.patch
@@ -0,0 +1,50 @@
+diff --git a/source/common/uloc.cpp b/source/common/uloc.cpp
+index bea4827a0..877874142 100644
+--- a/source/common/uloc.cpp
++++ b/source/common/uloc.cpp
+@@ -627,7 +627,7 @@ ulocimp_getKeywords(std::string_view localeID,
+ do {
+ bool duplicate = false;
+ /* skip leading spaces */
+- while (localeID.front() == ' ') {
++ while (!localeID.empty() && localeID.front() == ' ') {
+ localeID.remove_prefix(1);
+ }
+ if (localeID.empty()) { /* handle trailing "; " */
+diff --git a/source/test/intltest/loctest.cpp b/source/test/intltest/loctest.cpp
+index 18887ed4f..44bedd4f8 100644
+--- a/source/test/intltest/loctest.cpp
++++ b/source/test/intltest/loctest.cpp
+@@ -265,6 +265,7 @@ void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, c
+ TESTCASE_AUTO(TestBug13554);
+ TESTCASE_AUTO(TestBug20410);
+ TESTCASE_AUTO(TestBug20900);
++ TESTCASE_AUTO(TestChromiumBug451657601);
+ TESTCASE_AUTO(TestLocaleCanonicalizationFromFile);
+ TESTCASE_AUTO(TestKnownCanonicalizedListCorrect);
+ TESTCASE_AUTO(TestConstructorAcceptsBCP47);
+@@ -5818,6 +5819,12 @@ void LocaleTest::TestBug20900() {
+ }
+ }
+
++void LocaleTest::TestChromiumBug451657601() {
++ // This used to cause a crash in _LIBCPP_HARDENING_MODE.
++ Locale l = Locale("@x=@; ");
++ assertEquals("canonicalized", "@x=@", l.getName());
++}
++
+ U_DEFINE_LOCAL_OPEN_POINTER(LocalStdioFilePointer, FILE, fclose);
+ void LocaleTest::TestLocaleCanonicalizationFromFile()
+ {
+diff --git a/source/test/intltest/loctest.h b/source/test/intltest/loctest.h
+index b3410242e..ce6c78d05 100644
+--- a/source/test/intltest/loctest.h
++++ b/source/test/intltest/loctest.h
+@@ -125,6 +125,7 @@ public:
+ void TestBug13554();
+ void TestBug20410();
+ void TestBug20900();
++ void TestChromiumBug451657601();
+ void TestLocaleCanonicalizationFromFile();
+ void TestKnownCanonicalizedListCorrect();
+ void TestConstructorAcceptsBCP47();
diff --git a/source/common/uloc.cpp b/source/common/uloc.cpp
index bea4827..8778741 100644
--- a/source/common/uloc.cpp
+++ b/source/common/uloc.cpp
@@ -627,7 +627,7 @@
do {
bool duplicate = false;
/* skip leading spaces */
- while (localeID.front() == ' ') {
+ while (!localeID.empty() && localeID.front() == ' ') {
localeID.remove_prefix(1);
}
if (localeID.empty()) { /* handle trailing "; " */
diff --git a/source/test/intltest/loctest.cpp b/source/test/intltest/loctest.cpp
index 18887ed..44bedd4 100644
--- a/source/test/intltest/loctest.cpp
+++ b/source/test/intltest/loctest.cpp
@@ -265,6 +265,7 @@
TESTCASE_AUTO(TestBug13554);
TESTCASE_AUTO(TestBug20410);
TESTCASE_AUTO(TestBug20900);
+ TESTCASE_AUTO(TestChromiumBug451657601);
TESTCASE_AUTO(TestLocaleCanonicalizationFromFile);
TESTCASE_AUTO(TestKnownCanonicalizedListCorrect);
TESTCASE_AUTO(TestConstructorAcceptsBCP47);
@@ -5818,6 +5819,12 @@
}
}
+void LocaleTest::TestChromiumBug451657601() {
+ // This used to cause a crash in _LIBCPP_HARDENING_MODE.
+ Locale l = Locale("@x=@; ");
+ assertEquals("canonicalized", "@x=@", l.getName());
+}
+
U_DEFINE_LOCAL_OPEN_POINTER(LocalStdioFilePointer, FILE, fclose);
void LocaleTest::TestLocaleCanonicalizationFromFile()
{
diff --git a/source/test/intltest/loctest.h b/source/test/intltest/loctest.h
index b341024..ce6c78d 100644
--- a/source/test/intltest/loctest.h
+++ b/source/test/intltest/loctest.h
@@ -125,6 +125,7 @@
void TestBug13554();
void TestBug20410();
void TestBug20900();
+ void TestChromiumBug451657601();
void TestLocaleCanonicalizationFromFile();
void TestKnownCanonicalizedListCorrect();
void TestConstructorAcceptsBCP47();