-
Notifications
You must be signed in to change notification settings - Fork 151
Open
Description
Summary
Feeding a crafted input to ucl_add_string_fuzzer causes libucl to read uninitialized memory in the hash table implementation and then crash with a NULL pointer dereference in ucl_hash_destroy() while freeing the parser state.
Environment
- Tooling:
valgrind --tool=memcheck --track-origins=yes - Target:
ucl_add_string_fuzzer - OS: Ubuntu 20.04.6 LTS focal x86_64
- libucl version:
v0.9.2(a6b5cac1121103984ee2035081b7467725d68ed7)
Reproducer
Artifacts:
- Fuzzer binary (
ucl_add_string_fuzzer) - Single testcase
Repro with OSS-Fuzz helpers:
git clone https://github.com/google/oss-fuzz.git
cd oss-fuzz
python3 infra/helper.py build_image libucl
python3 infra/helper.py build_fuzzers --sanitizer=none libucl
python3 infra/helper.py shell libucl
apt update && apt install -y valgrind
ulimit -n 65535
valgrind --tool=memcheck --track-origins=yes /out/ucl_add_string_fuzzer /path/to/pocValgrind Trace (top frames):
==170== Use of uninitialised value of size 8
==170== at 0x215E8C: ucl_hash_destroy (in /out/ucl_add_string_fuzzer)
==170== by 0x2058E2: ucl_object_free_internal (in /out/ucl_add_string_fuzzer)
==170== by 0x2069BA: ucl_parser_free (in /out/ucl_add_string_fuzzer)
==170== by 0x200341: ucl_state_machine (in /out/ucl_add_string_fuzzer)
==170== by 0x1FCCE9: ucl_parser_add_chunk_full (in /out/ucl_add_string_fuzzer)
==170== Uninitialised value was created by a heap allocation at 0x483B723: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)UBSan Trace:
ERROR: SEGV on address 0x0 (READ)
#0 ucl_hash_destroy /src/libucl/src/ucl_hash.c:272:29
#1 ucl_object_free_internal /src/libucl/src/ucl_util.c:278
#2 ucl_parser_free /src/libucl/src/ucl_util.c:646
#3 ucl_state_machine /src/libucl/src/ucl_parser.c:2664
#4 ucl_parser_add_chunk_full /src/libucl/src/ucl_parser.c:3062Likely root cause (from symptoms):
- During insertion,
kh_resize_ucl_hash_node()reallocs internal arrays but does not fully initialize new slots / flags, or error/partial-insert paths leave the table in an inconsistent state. - On teardown,
ucl_hash_destroy()iterates the table using slot flags that contain uninitialized bytes, treats garbage as “occupied”, and accesses entry fields (or frees them), leading to a read from NULL (and potentially other invalid pointers).
Impact
- Denial of service via crash in consumers that parse untrusted UCL input.
- Depending on allocator state, teardown could attempt to free/walk garbage pointers (risking invalid free). No controlled memory corruption demonstrated here.
Additional testcase — same root cause via a different path
I’m attaching a second PoC (archive1.zip) that hits the same underlying defect (uninitialized slot/flag state leading to NULL/garbage deref in ucl_hash_destroy) but via a slightly different mutation path.
Credit: Aldo Ristori
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels