ICUTimeConversion: Fix buffer overflows and add more error handling.
* Declare databridge buffer lengths in LocaleBackend. * Use strcpy instead of strlcpy when writing to databridge buffers (this is the first fix for #18598.) * Check for overflows and error out when they happen. * Verify that ICU actually knows the timezone in question and fall back to GMT if it does not (this would also fix that crash.) Fixes #18598.
This commit is contained in:
parent
c199c568de
commit
e8d328979c
@ -102,12 +102,14 @@ struct LocaleTimeDataBridge {
|
||||
|
||||
|
||||
struct TimeConversionDataBridge {
|
||||
static const int32 kTZNameLength = 64;
|
||||
|
||||
private:
|
||||
int localDaylight;
|
||||
long localTimezone;
|
||||
char* localTZName[2];
|
||||
char localTZName0[64];
|
||||
char localTZName1[64];
|
||||
char localTZName0[kTZNameLength];
|
||||
char localTZName1[kTZNameLength];
|
||||
|
||||
public:
|
||||
int* addrOfDaylight;
|
||||
|
@ -113,6 +113,10 @@ done:
|
||||
if (fTimeZone == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
UnicodeString temp;
|
||||
if (fTimeZone->getID(temp) == UCAL_UNKNOWN_ZONE_ID)
|
||||
goto error;
|
||||
|
||||
if (offsetHasBeenSet) {
|
||||
fTimeZone->setRawOffset(*fDataBridge->addrOfTimezone * -1 * 1000);
|
||||
} else {
|
||||
@ -121,14 +125,8 @@ done:
|
||||
UDate nowMillis = 1000 * (UDate)time(NULL);
|
||||
UErrorCode icuStatus = U_ZERO_ERROR;
|
||||
fTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, icuStatus);
|
||||
if (!U_SUCCESS(icuStatus)) {
|
||||
*fDataBridge->addrOfTimezone = 0;
|
||||
*fDataBridge->addrOfDaylight = false;
|
||||
strcpy(fDataBridge->addrOfTZName[0], "GMT");
|
||||
strcpy(fDataBridge->addrOfTZName[1], "GMT");
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
if (!U_SUCCESS(icuStatus))
|
||||
goto error;
|
||||
*fDataBridge->addrOfTimezone = -1 * (rawOffset + dstOffset) / 1000;
|
||||
// we want seconds, not the ms that ICU gives us
|
||||
}
|
||||
@ -137,15 +135,19 @@ done:
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (tz != NULL && *tz != ':' && i == 0) {
|
||||
strcpy(fDataBridge->addrOfTZName[0], fTimeZoneID);
|
||||
strlcpy(fDataBridge->addrOfTZName[0], fTimeZoneID,
|
||||
fDataBridge->kTZNameLength);
|
||||
} else {
|
||||
UnicodeString icuString;
|
||||
fTimeZone->getDisplayName(i == 1, TimeZone::SHORT,
|
||||
fTimeData.ICULocaleForStrings(), icuString);
|
||||
CheckedArrayByteSink byteSink(fDataBridge->addrOfTZName[i],
|
||||
sizeof(fTimeZoneID));
|
||||
fDataBridge->kTZNameLength);
|
||||
icuString.toUTF8(byteSink);
|
||||
|
||||
if (byteSink.Overflowed())
|
||||
goto error;
|
||||
|
||||
// make sure to canonicalize "GMT+00:00" to just "GMT"
|
||||
if (strcmp(fDataBridge->addrOfTZName[i], "GMT+00:00") == 0)
|
||||
fDataBridge->addrOfTZName[i][3] = '\0';
|
||||
@ -153,6 +155,14 @@ done:
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
||||
error:
|
||||
*fDataBridge->addrOfTimezone = 0;
|
||||
*fDataBridge->addrOfDaylight = false;
|
||||
strcpy(fDataBridge->addrOfTZName[0], "GMT");
|
||||
strcpy(fDataBridge->addrOfTZName[1], "GMT");
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user