Skip to content

ICU-23335 Fix undefined behavior and null-deref in date_format_fuzzer#3888

Open
OwenSanzas wants to merge 1 commit intounicode-org:mainfrom
OwenSanzas:fix/date-format-fuzzer-enum-validation-null-check
Open

ICU-23335 Fix undefined behavior and null-deref in date_format_fuzzer#3888
OwenSanzas wants to merge 1 commit intounicode-org:mainfrom
OwenSanzas:fix/date-format-fuzzer-enum-validation-null-check

Conversation

@OwenSanzas
Copy link
Copy Markdown

@OwenSanzas OwenSanzas commented Mar 5, 2026

Summary

Fix two issues in icu4c/source/test/fuzzer/date_format_fuzzer.cpp:

1. Undefined behavior: invalid enum values

dateStyle and timeStyle are read from fuzz data via memcpy directly into EStyle enum variables without validation. The EStyle enum has only 13 valid values, so arbitrary 32-bit values are undefined behavior per the C++ standard.

Confirmed with UndefinedBehaviorSanitizer:

runtime error: load of value -559038737, which is not a valid value for type 'icu::DateFormat::EStyle'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior

The harness already has the correct pattern for dateStyle2/timeStyle2 — they use styles[rnd2 % numStyles]. The first pair was an oversight.

Fix: Use styles[rnd2 % numStyles] for all style variables, consistent with the existing pattern.

2. Missing null checks before df->format()

df->format(date, appendTo) is called without checking if df is nullptr after createDateTimeInstance. While createDateTimeInstance rarely returns nullptr in practice, the missing null checks are inconsistent with the later createInstanceForSkeleton calls which do check for success.

Fix: Add null checks (if (df)) before all df->format() calls.

Before/After Comparison (60-second fuzzing, AddressSanitizer)

Metric Original Fixed Change
Edge cov 7106 8029 +13.0%
Features 21463 25788 +20.2%
Corpus 813 1052 +29.4%
Exec/s 375 380 +1.3%

The fixed version achieves 13% more edge coverage because valid EStyle enum values trigger more DateFormat internal code paths (e.g., RelativeDateFormat, various style combinations) instead of always falling through to the default fallback path.

Changes

  • Read dateStyle/timeStyle as uint8_t + modulo index into styles[] (same as dateStyle2/timeStyle2)
  • Adjust minimum input size accordingly (4 × uint8_t instead of 2 × uint8_t + 2 × sizeof(EStyle))
  • Add null checks before all df->format() calls
  • Reset status before udat_open call

Two issues in the date_format_fuzzer fuzz harness:

1. dateStyle and timeStyle are read from fuzz data via memcpy directly
   into EStyle enum variables without validation. The EStyle enum has
   only 13 valid values, so arbitrary 32-bit values are undefined
   behavior. UBSan confirms: "load of value -559038737, which is not
   a valid value for type 'icu::DateFormat::EStyle'".

   Fix: use styles[rnd2 % numStyles] for all style variables,
   consistent with how dateStyle2/timeStyle2 are already handled.

2. df->format() is called without checking if df is nullptr. While
   createDateTimeInstance rarely returns nullptr in practice, the
   missing null checks are inconsistent with the later
   createInstanceForSkeleton calls which do check.

   Fix: add null checks before all df->format() calls.
@OwenSanzas OwenSanzas changed the title ICU-22999 Fix undefined behavior and null-deref in date_format_fuzzer Fix undefined behavior and null-deref in date_format_fuzzer Mar 5, 2026
@OwenSanzas OwenSanzas changed the title Fix undefined behavior and null-deref in date_format_fuzzer ICU-23335 Fix undefined behavior and null-deref in date_format_fuzzer Mar 7, 2026
@markusicu markusicu self-assigned this Mar 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants