Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICU-22549 Add TimeZoneNames fuzzer #2741

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -46,6 +46,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;
}
Loading