mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-13 08:53:20 +00:00
ICU-12810 Prevent assertion triggered by time zone id including characters other than ASCII invariants initialize/formatting a time zone.
X-SVN-Rev: 39799
This commit is contained in:
parent
9b50ba1c2e
commit
f54d25d286
4 changed files with 47 additions and 1 deletions
|
@ -28,6 +28,7 @@
|
|||
#include "uresimp.h"
|
||||
#include "uhash.h"
|
||||
#include "olsontz.h"
|
||||
#include "uinvchar.h"
|
||||
|
||||
static UMutex gZoneMetaLock = U_MUTEX_INITIALIZER;
|
||||
|
||||
|
@ -255,6 +256,12 @@ ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) {
|
|||
tzid.extract(utzid, ZID_KEY_MAX + 1, tmpStatus);
|
||||
U_ASSERT(tmpStatus == U_ZERO_ERROR); // we checked the length of tzid already
|
||||
|
||||
if (!uprv_isInvariantUString(utzid, -1)) {
|
||||
// All of known tz IDs are only containing ASCII invariant characters.
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check if it was already cached
|
||||
umtx_lock(&gZoneMetaLock);
|
||||
{
|
||||
|
|
|
@ -41,7 +41,11 @@ public:
|
|||
/**
|
||||
* Return the canonical id for this tzid defined by CLDR, which might be the id itself.
|
||||
* This overload method returns a persistent const UChar*, which is guranteed to persist
|
||||
* (a pointer to a resource).
|
||||
* (a pointer to a resource). If the given system tzid is not known, U_ILLEGAL_ARGUMENT_ERROR
|
||||
* is set in the status.
|
||||
* @param tzid Zone ID
|
||||
* @param status Receives the status
|
||||
* @return The canonical ID for the input time zone ID
|
||||
*/
|
||||
static const UChar* U_EXPORT2 getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status);
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ TimeZoneFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name
|
|||
TESTCASE(3, TestISOFormat);
|
||||
TESTCASE(4, TestFormat);
|
||||
TESTCASE(5, TestFormatTZDBNames);
|
||||
TESTCASE(6, TestFormatCustomZone);
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
|
@ -1213,5 +1214,38 @@ TimeZoneFormatTest::TestFormatTZDBNames(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimeZoneFormatTest::TestFormatCustomZone(void) {
|
||||
struct {
|
||||
const char* id;
|
||||
int32_t offset;
|
||||
const char* expected;
|
||||
} TESTDATA[] = {
|
||||
{ "abc", 3600000, "GMT+01:00" }, // unknown ID
|
||||
{ "$abc", -3600000, "GMT-01:00" }, // unknown, with ASCII variant char '$'
|
||||
{ "\\u00c1\\u00df\\u00c7", 5400000, "GMT+01:30"}, // unknown, with non-ASCII chars
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
UDate now = Calendar::getNow();
|
||||
|
||||
for (int32_t i = 0; ; i++) {
|
||||
const char *id = TESTDATA[i].id;
|
||||
if (id == 0) {
|
||||
break;
|
||||
}
|
||||
UnicodeString tzid = UnicodeString(id, -1, US_INV).unescape();
|
||||
SimpleTimeZone tz(TESTDATA[i].offset, tzid);
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(Locale("en"), status));
|
||||
UnicodeString tzstr;
|
||||
UnicodeString expected = UnicodeString(TESTDATA[i].expected, -1, US_INV).unescape();
|
||||
|
||||
tzfmt->format(UTZFMT_STYLE_SPECIFIC_LONG, tz, now, tzstr, NULL);
|
||||
assertEquals(UnicodeString("Format result for ") + tzid, expected, tzstr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -27,6 +27,7 @@ class TimeZoneFormatTest : public IntlTest {
|
|||
void TestISOFormat(void);
|
||||
void TestFormat(void);
|
||||
void TestFormatTZDBNames(void);
|
||||
void TestFormatCustomZone(void);
|
||||
|
||||
void RunTimeRoundTripTests(int32_t threadNumber);
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue