Skip to content

Commit 5cf5ec1

Browse files
committed
ICU-22549 Add TimeZoneNames fuzzer
1 parent 7775942 commit 5cf5ec1

File tree

3 files changed

+78
-4
lines changed

3 files changed

+78
-4
lines changed

icu4c/source/i18n/tznames_impl.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,11 +1303,16 @@ static void mergeTimeZoneKey(const UnicodeString& mzID, char* result) {
13031303
ZNames*
13041304
TimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID, UErrorCode& status) {
13051305
if (U_FAILURE(status)) { return nullptr; }
1306-
U_ASSERT(mzID.length() <= ZID_KEY_MAX - MZ_PREFIX_LEN);
1306+
if (mzID.length() > ZID_KEY_MAX - MZ_PREFIX_LEN) {
1307+
status = U_INTERNAL_PROGRAM_ERROR;
1308+
return nullptr;
1309+
}
13071310

13081311
char16_t mzIDKey[ZID_KEY_MAX + 1];
13091312
mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
1310-
U_ASSERT(U_SUCCESS(status)); // already checked length above
1313+
if (U_FAILURE(status)) {
1314+
return nullptr;
1315+
}
13111316
mzIDKey[mzID.length()] = 0;
13121317

13131318
void* mznames = uhash_get(fMZNamesMap, mzIDKey);
@@ -1331,7 +1336,10 @@ TimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID, UErrorCode& stat
13311336
ZNames*
13321337
TimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID, UErrorCode& status) {
13331338
if (U_FAILURE(status)) { return nullptr; }
1334-
U_ASSERT(tzID.length() <= ZID_KEY_MAX);
1339+
if (tzID.length() > ZID_KEY_MAX) {
1340+
status = U_INTERNAL_PROGRAM_ERROR;
1341+
return nullptr;
1342+
}
13351343

13361344
char16_t tzIDKey[ZID_KEY_MAX + 1];
13371345
int32_t tzIDKeyLen = tzID.extract(tzIDKey, ZID_KEY_MAX + 1, status);
@@ -2248,7 +2256,9 @@ TZDBTimeZoneNames::getMetaZoneNames(const UnicodeString& mzID, UErrorCode& statu
22482256

22492257
char16_t mzIDKey[ZID_KEY_MAX + 1];
22502258
mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
2251-
U_ASSERT(status == U_ZERO_ERROR); // already checked length above
2259+
if (U_FAILURE(status)) {
2260+
return nullptr;
2261+
}
22522262
mzIDKey[mzID.length()] = 0;
22532263

22542264
static UMutex gTZDBNamesMapLock;

icu4c/source/test/fuzzer/Makefile.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ FUZZER_TARGETS = \
4747
relative_date_time_formatter_fuzzer \
4848
rule_based_break_iterator_fuzzer \
4949
timezone_create_fuzzer \
50+
time_zone_names_fuzzer \
5051
ucasemap_fuzzer \
5152
uloc_canonicalize_fuzzer \
5253
uloc_for_language_tag_fuzzer \
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// © 2023 and later: Unicode, Inc. and others.
2+
// License & terms of use: http://www.unicode.org/copyright.html
3+
4+
// Fuzzer for TimeZoneNames.
5+
6+
#include <cstring>
7+
8+
#include "fuzzer_utils.h"
9+
10+
#include "unicode/tznames.h"
11+
#include "unicode/locid.h"
12+
13+
void TestNames(icu::TimeZoneNames* names, const icu::UnicodeString& text, UDate date, UTimeZoneNameType type) {
14+
UErrorCode status = U_ZERO_ERROR;
15+
std::unique_ptr<icu::StringEnumeration> enumeration(
16+
names->getAvailableMetaZoneIDs(status));
17+
status = U_ZERO_ERROR;
18+
enumeration.reset(
19+
names->getAvailableMetaZoneIDs(text, status));
20+
icu::UnicodeString output;
21+
names->getMetaZoneID(text, date, output);
22+
names->getMetaZoneDisplayName(text, type, output);
23+
names->getTimeZoneDisplayName(text, type, output);
24+
names->getExemplarLocationName(text, output);
25+
names->getDisplayName(text, type, date, output);
26+
}
27+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
28+
uint16_t rnd;
29+
UDate date;
30+
31+
UTimeZoneNameType type;
32+
if (size < sizeof(rnd) + sizeof(date) + sizeof(type)) return 0;
33+
icu::StringPiece fuzzData(reinterpret_cast<const char *>(data), size);
34+
35+
std::memcpy(&rnd, fuzzData.data(), sizeof(rnd));
36+
icu::Locale locale = GetRandomLocale(rnd);
37+
fuzzData.remove_prefix(sizeof(rnd));
38+
39+
std::memcpy(&date, fuzzData.data(), sizeof(date));
40+
fuzzData.remove_prefix(sizeof(date));
41+
42+
std::memcpy(&type, fuzzData.data(), sizeof(type));
43+
fuzzData.remove_prefix(sizeof(type));
44+
45+
size_t len = fuzzData.size() / sizeof(char16_t);
46+
icu::UnicodeString text(false, reinterpret_cast<const char16_t*>(fuzzData.data()), len);
47+
48+
UErrorCode status = U_ZERO_ERROR;
49+
std::unique_ptr<icu::TimeZoneNames> names(
50+
icu::TimeZoneNames::createInstance(locale, status));
51+
if (U_SUCCESS(status)) {
52+
TestNames(names.get(), text, date, type);
53+
}
54+
55+
status = U_ZERO_ERROR;
56+
names.reset(
57+
icu::TimeZoneNames::createTZDBInstance(locale, status));
58+
if (U_SUCCESS(status)) {
59+
TestNames(names.get(), text, date, type);
60+
}
61+
62+
return EXIT_SUCCESS;
63+
}

0 commit comments

Comments
 (0)