CVE-2017-15396.patch 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. Combined backport of:
  2. <https://github.com/unicode-org/icu/commit/5c711e36e>
  3. ~~~
  4. From 5c711e36e8e6a9810bb689ace16f698d1d3ab9ce Mon Sep 17 00:00:00 2001
  5. From: Shane Carr <shane@unicode.org>
  6. Date: Thu, 28 Sep 2017 01:00:43 +0000
  7. Subject: [PATCH] ICU-13327 Fixing buffer overflow in NumberingSystem
  8. constructor.
  9. X-SVN-Rev: 40494
  10. ---
  11. icu4c/source/i18n/numsys.cpp | 7 +++++++
  12. icu4c/source/test/intltest/numfmtst.cpp | 22 ++++++++++++++++++++++
  13. icu4c/source/test/intltest/numfmtst.h | 1 +
  14. 3 files changed, 30 insertions(+)
  15. ~~~
  16. <https://github.com/unicode-org/icu/commit/1c794eb11>
  17. ~~~
  18. From 1c794eb111bb9c146375038dd66806aaa26f35ce Mon Sep 17 00:00:00 2001
  19. From: Andy Heninger <andy.heninger@gmail.com>
  20. Date: Wed, 11 Oct 2017 22:22:45 +0000
  21. Subject: [PATCH] ICU-13394 nul-terminated buffer handling fixed from Chromium.
  22. X-SVN-Rev: 40615
  23. ---
  24. icu4c/source/common/locdispnames.cpp | 2 ++
  25. icu4c/source/common/locdspnm.cpp | 3 ++-
  26. icu4c/source/common/ucurr.cpp | 1 +
  27. icu4c/source/i18n/ucol_sit.cpp | 11 +++++++++--
  28. 4 files changed, 14 insertions(+), 3 deletions(-)
  29. ~~~
  30. --- source/common/locdispnames.cpp
  31. +++ source/common/locdispnames.cpp
  32. @@ -821,6 +821,8 @@ uloc_getDisplayKeywordValue( const char* locale,
  33. /* get the keyword value */
  34. keywordValue[0]=0;
  35. keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue, capacity, status);
  36. + if (*status == U_STRING_NOT_TERMINATED_WARNING)
  37. + *status = U_BUFFER_OVERFLOW_ERROR;
  38. /*
  39. * if the keyword is equal to currency .. then to get the display name
  40. --- source/common/locdspnm.cpp
  41. +++ source/common/locdspnm.cpp
  42. @@ -635,8 +635,9 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale,
  43. char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY
  44. const char* key;
  45. while ((key = e->next((int32_t *)0, status)) != NULL) {
  46. + value[0] = 0;
  47. locale.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status);
  48. - if (U_FAILURE(status)) {
  49. + if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
  50. return result;
  51. }
  52. keyDisplayName(key, temp, TRUE);
  53. --- source/common/ucurr.cpp
  54. +++ source/common/ucurr.cpp
  55. @@ -2215,6 +2215,7 @@ ucurr_countCurrencies(const char* locale,
  56. UErrorCode localStatus = U_ZERO_ERROR;
  57. char id[ULOC_FULLNAME_CAPACITY];
  58. uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus);
  59. +
  60. // get country or country_variant in `id'
  61. /*uint32_t variantType =*/ idForLocale(locale, id, sizeof(id), ec);
  62. --- source/i18n/numsys.cpp
  63. +++ source/i18n/numsys.cpp
  64. @@ -25,6 +25,7 @@
  65. #include "unicode/schriter.h"
  66. #include "unicode/numsys.h"
  67. #include "cstring.h"
  68. +#include "uassert.h"
  69. #include "uresimp.h"
  70. #include "numsys_impl.h"
  71. @@ -115,7 +116,13 @@ NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) {
  72. UBool usingFallback = FALSE;
  73. char buffer[ULOC_KEYWORDS_CAPACITY];
  74. int32_t count = inLocale.getKeywordValue("numbers",buffer, sizeof(buffer),status);
  75. + if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
  76. + // the "numbers" keyword exceeds ULOC_KEYWORDS_CAPACITY; ignore and use default.
  77. + count = 0;
  78. + status = U_ZERO_ERROR;
  79. + }
  80. if ( count > 0 ) { // @numbers keyword was specified in the locale
  81. + U_ASSERT(count < ULOC_KEYWORDS_CAPACITY);
  82. buffer[count] = '\0'; // Make sure it is null terminated.
  83. if ( !uprv_strcmp(buffer,gDefault) || !uprv_strcmp(buffer,gNative) ||
  84. !uprv_strcmp(buffer,gTraditional) || !uprv_strcmp(buffer,gFinance)) {
  85. --- source/i18n/ucol_sit.cpp
  86. +++ source/i18n/ucol_sit.cpp
  87. @@ -465,8 +465,15 @@ ucol_prepareShortStringOpen( const char *definition,
  88. UResourceBundle *collElem = NULL;
  89. char keyBuffer[256];
  90. // if there is a keyword, we pick it up and try to get elements
  91. - if(!uloc_getKeywordValue(buffer, "collation", keyBuffer, 256, status)) {
  92. - // no keyword. we try to find the default setting, which will give us the keyword value
  93. + int32_t keyLen = uloc_getKeywordValue(buffer, "collation", keyBuffer, sizeof(keyBuffer), status);
  94. + // Treat too long a value as no keyword.
  95. + if(keyLen >= (int32_t)sizeof(keyBuffer)) {
  96. + keyLen = 0;
  97. + *status = U_ZERO_ERROR;
  98. + }
  99. + if(keyLen == 0) {
  100. + // no keyword
  101. + // we try to find the default setting, which will give us the keyword value
  102. UResourceBundle *defaultColl = ures_getByKeyWithFallback(collations, "default", NULL, status);
  103. if(U_SUCCESS(*status)) {
  104. int32_t defaultKeyLen = 0;
  105. --- source/test/intltest/numfmtst.cpp
  106. +++ source/test/intltest/numfmtst.cpp
  107. @@ -581,6 +581,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
  108. TESTCASE_AUTO(Test11475_signRecognition);
  109. TESTCASE_AUTO(Test11640_getAffixes);
  110. TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
  111. + TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
  112. TESTCASE_AUTO_END;
  113. }
  114. @@ -8717,6 +8718,27 @@ void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
  115. assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
  116. }
  117. +void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
  118. + UErrorCode status;
  119. + for (int runId = 0; runId < 2; runId++) {
  120. + // Construct a locale string with a very long "numbers" value.
  121. + // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
  122. + // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
  123. + int extraLength = (runId == 0) ? 0 : 5;
  124. +
  125. + CharString localeId("en@numbers=", status);
  126. + for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
  127. + localeId.append('x', status);
  128. + }
  129. + assertSuccess("Constructing locale string", status);
  130. + Locale locale(localeId.data());
  131. +
  132. + NumberingSystem* ns = NumberingSystem::createInstance(locale, status);
  133. + assertFalse("Should not be null", ns == nullptr);
  134. + assertSuccess("Should create with no error", status);
  135. + }
  136. +}
  137. +
  138. void NumberFormatTest::verifyFieldPositionIterator(
  139. NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
  140. --- source/test/intltest/numfmtst.h
  141. +++ source/test/intltest/numfmtst.h
  142. @@ -215,6 +215,7 @@ class NumberFormatTest: public CalendarTimeZoneTest {
  143. void Test11475_signRecognition();
  144. void Test11640_getAffixes();
  145. void Test11649_toPatternWithMultiCurrency();
  146. + void Test13327_numberingSystemBufferOverflow();
  147. void checkExceptionIssue11735();