Skip to content

Commit

Permalink
ICU-22549 Add TimeZoneNames fuzzer
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankYFTang committed Dec 15, 2023
1 parent 7775942 commit 5cf5ec1
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 4 deletions.
18 changes: 14 additions & 4 deletions icu4c/source/i18n/tznames_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1303,11 +1303,16 @@ static void mergeTimeZoneKey(const UnicodeString& mzID, char* result) {
ZNames*
TimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID, UErrorCode& status) {
if (U_FAILURE(status)) { return nullptr; }
U_ASSERT(mzID.length() <= ZID_KEY_MAX - MZ_PREFIX_LEN);
if (mzID.length() > ZID_KEY_MAX - MZ_PREFIX_LEN) {
status = U_INTERNAL_PROGRAM_ERROR;
return nullptr;
}

char16_t mzIDKey[ZID_KEY_MAX + 1];
mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
U_ASSERT(U_SUCCESS(status)); // already checked length above
if (U_FAILURE(status)) {
return nullptr;
}
mzIDKey[mzID.length()] = 0;

void* mznames = uhash_get(fMZNamesMap, mzIDKey);
Expand All @@ -1331,7 +1336,10 @@ TimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID, UErrorCode& stat
ZNames*
TimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID, UErrorCode& status) {
if (U_FAILURE(status)) { return nullptr; }
U_ASSERT(tzID.length() <= ZID_KEY_MAX);
if (tzID.length() > ZID_KEY_MAX) {
status = U_INTERNAL_PROGRAM_ERROR;
return nullptr;
}

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

char16_t mzIDKey[ZID_KEY_MAX + 1];
mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
U_ASSERT(status == U_ZERO_ERROR); // already checked length above
if (U_FAILURE(status)) {
return nullptr;
}
mzIDKey[mzID.length()] = 0;

static UMutex gTZDBNamesMapLock;
Expand Down
1 change: 1 addition & 0 deletions icu4c/source/test/fuzzer/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ FUZZER_TARGETS = \
relative_date_time_formatter_fuzzer \
rule_based_break_iterator_fuzzer \
timezone_create_fuzzer \
time_zone_names_fuzzer \
ucasemap_fuzzer \
uloc_canonicalize_fuzzer \
uloc_for_language_tag_fuzzer \
Expand Down
63 changes: 63 additions & 0 deletions icu4c/source/test/fuzzer/time_zone_names_fuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// © 2023 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

// Fuzzer for TimeZoneNames.

#include <cstring>

#include "fuzzer_utils.h"

#include "unicode/tznames.h"
#include "unicode/locid.h"

void TestNames(icu::TimeZoneNames* names, const icu::UnicodeString& text, UDate date, UTimeZoneNameType type) {
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::StringEnumeration> enumeration(
names->getAvailableMetaZoneIDs(status));
status = U_ZERO_ERROR;
enumeration.reset(
names->getAvailableMetaZoneIDs(text, status));
icu::UnicodeString output;
names->getMetaZoneID(text, date, output);
names->getMetaZoneDisplayName(text, type, output);
names->getTimeZoneDisplayName(text, type, output);
names->getExemplarLocationName(text, output);
names->getDisplayName(text, type, date, output);
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
uint16_t rnd;
UDate date;

UTimeZoneNameType type;
if (size < sizeof(rnd) + sizeof(date) + sizeof(type)) return 0;
icu::StringPiece fuzzData(reinterpret_cast<const char *>(data), size);

std::memcpy(&rnd, fuzzData.data(), sizeof(rnd));
icu::Locale locale = GetRandomLocale(rnd);
fuzzData.remove_prefix(sizeof(rnd));

std::memcpy(&date, fuzzData.data(), sizeof(date));
fuzzData.remove_prefix(sizeof(date));

std::memcpy(&type, fuzzData.data(), sizeof(type));
fuzzData.remove_prefix(sizeof(type));

size_t len = fuzzData.size() / sizeof(char16_t);
icu::UnicodeString text(false, reinterpret_cast<const char16_t*>(fuzzData.data()), len);

UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::TimeZoneNames> names(
icu::TimeZoneNames::createInstance(locale, status));
if (U_SUCCESS(status)) {
TestNames(names.get(), text, date, type);
}

status = U_ZERO_ERROR;
names.reset(
icu::TimeZoneNames::createTZDBInstance(locale, status));
if (U_SUCCESS(status)) {
TestNames(names.get(), text, date, type);
}

return EXIT_SUCCESS;
}

0 comments on commit 5cf5ec1

Please sign in to comment.