ICU-13327 Fixing buffer overflow in NumberingSystem constructor.

X-SVN-Rev: 40494
This commit is contained in:
Shane Carr 2017-09-28 01:00:43 +00:00
parent 1599dabb7c
commit 5c711e36e8
3 changed files with 30 additions and 0 deletions

View file

@ -25,6 +25,7 @@
#include "unicode/schriter.h"
#include "unicode/numsys.h"
#include "cstring.h"
#include "uassert.h"
#include "uresimp.h"
#include "numsys_impl.h"
@ -115,7 +116,13 @@ NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) {
UBool usingFallback = FALSE;
char buffer[ULOC_KEYWORDS_CAPACITY];
int32_t count = inLocale.getKeywordValue("numbers",buffer, sizeof(buffer),status);
if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
// the "numbers" keyword exceeds ULOC_KEYWORDS_CAPACITY; ignore and use default.
count = 0;
status = U_ZERO_ERROR;
}
if ( count > 0 ) { // @numbers keyword was specified in the locale
U_ASSERT(count < ULOC_KEYWORDS_CAPACITY);
buffer[count] = '\0'; // Make sure it is null terminated.
if ( !uprv_strcmp(buffer,gDefault) || !uprv_strcmp(buffer,gNative) ||
!uprv_strcmp(buffer,gTraditional) || !uprv_strcmp(buffer,gFinance)) {

View file

@ -621,6 +621,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
TESTCASE_AUTO(Test11475_signRecognition);
TESTCASE_AUTO(Test11640_getAffixes);
TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
TESTCASE_AUTO_END;
}
@ -8785,6 +8786,27 @@ void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
}
void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
UErrorCode status;
for (int runId = 0; runId < 2; runId++) {
// Construct a locale string with a very long "numbers" value.
// The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
// The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
int extraLength = (runId == 0) ? 0 : 5;
CharString localeId("en@numbers=", status);
for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
localeId.append('x', status);
}
assertSuccess("Constructing locale string", status);
Locale locale(localeId.data());
NumberingSystem* ns = NumberingSystem::createInstance(locale, status);
assertFalse("Should not be null", ns == nullptr);
assertSuccess("Should create with no error", status);
}
}
void NumberFormatTest::verifyFieldPositionIterator(
NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {

View file

@ -215,6 +215,7 @@ class NumberFormatTest: public CalendarTimeZoneTest {
void Test11475_signRecognition();
void Test11640_getAffixes();
void Test11649_toPatternWithMultiCurrency();
void Test13327_numberingSystemBufferOverflow();
void checkExceptionIssue11735();