ICU-21004 Fix buffer over-read in ucal_open

The issue shows under valgrind or as an Address Sanitizer failure.
This commit is contained in:
Jeff Genovy 2020-03-01 16:31:55 -08:00
parent 0b7f6b1864
commit bd08ba2c5b
2 changed files with 28 additions and 11 deletions

View File

@ -154,25 +154,31 @@ ucal_open( const UChar* zoneID,
UCalendarType caltype,
UErrorCode* status)
{
if(U_FAILURE(*status)) return 0;
if (U_FAILURE(*status)) {
return nullptr;
}
LocalPointer<TimeZone> zone( (zoneID==NULL) ? TimeZone::createDefault()
LocalPointer<TimeZone> zone( (zoneID==nullptr) ? TimeZone::createDefault()
: _createTimeZone(zoneID, len, status), *status);
if (U_FAILURE(*status)) {
return NULL;
return nullptr;
}
if ( caltype == UCAL_GREGORIAN ) {
char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY];
if ( locale == NULL ) {
char localeBuf[ULOC_LOCALE_IDENTIFIER_CAPACITY];
if ( locale == nullptr ) {
locale = uloc_getDefault();
}
uprv_strncpy(localeBuf, locale, ULOC_LOCALE_IDENTIFIER_CAPACITY);
int32_t localeLength = static_cast<int32_t>(uprv_strlen(locale));
if (localeLength >= ULOC_LOCALE_IDENTIFIER_CAPACITY) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
return nullptr;
}
uprv_strcpy(localeBuf, locale);
uloc_setKeywordValue("calendar", "gregorian", localeBuf, ULOC_LOCALE_IDENTIFIER_CAPACITY, status);
if (U_FAILURE(*status)) {
return NULL;
return nullptr;
}
return (UCalendar*)Calendar::createInstance(zone.orphan(), Locale(localeBuf), *status);
}
@ -182,8 +188,9 @@ ucal_open( const UChar* zoneID,
U_CAPI void U_EXPORT2
ucal_close(UCalendar *cal)
{
delete (Calendar*) cal;
if (cal != nullptr) {
delete (Calendar*) cal;
}
}
U_CAPI UCalendar* U_EXPORT2

View File

@ -37,10 +37,10 @@ void TestGregorianChange(void);
void TestFieldDifference(void);
void TestAddRollEra0AndEraBounds(void);
void TestGetTZTransition(void);
void TestGetWindowsTimeZoneID(void);
void TestGetTimeZoneIDByWindowsID(void);
void TestJpnCalAddSetNextEra(void);
void TestUcalOpenBufferRead(void);
void addCalTest(TestNode** root);
@ -64,6 +64,7 @@ void addCalTest(TestNode** root)
addTest(root, &TestGetWindowsTimeZoneID, "tsformat/ccaltst/TestGetWindowsTimeZoneID");
addTest(root, &TestGetTimeZoneIDByWindowsID, "tsformat/ccaltst/TestGetTimeZoneIDByWindowsID");
addTest(root, &TestJpnCalAddSetNextEra, "tsformat/ccaltst/TestJpnCalAddSetNextEra");
addTest(root, &TestUcalOpenBufferRead, "tsformat/ccaltst/TestUcalOpenBufferRead");
}
/* "GMT" */
@ -2543,4 +2544,13 @@ void TestJpnCalAddSetNextEra() {
}
}
void TestUcalOpenBufferRead() {
// ICU-21004: The issue shows under valgrind or as an Address Sanitizer failure.
UErrorCode status = U_ZERO_ERROR;
// string length: 157 + 1 + 100 = 258
const char *localeID = "x-privatebutreallylongtagfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar-foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoorbarfoobarfoo";
UCalendar *cal = ucal_open(NULL, 0, localeID, UCAL_GREGORIAN, &status);
ucal_close(cal);
}
#endif /* #if !UCONFIG_NO_FORMATTING */