libucl icon indicating copy to clipboard operation
libucl copied to clipboard

possible SEGV in ucl_hash.c

Open Anza2001 opened this issue 8 months ago • 1 comments

Hello, I found a SEGV when running the following fuzz driver in OSS-Fuzz environment.

#include "ucl.h"
#include "ucl_internal.h"
#include <stdint.h>
#include <stddef.h>

// Fuzz driver for int ucl_parser_process_object_element(struct ucl_parser *, ucl_object_t *)
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    // Step 1: Check if data and size are valid
    if (data == NULL || size == 0) {
        return 0; // Exit early if input is invalid
    }

    // Step 2: Create and initialize a ucl_parser object
    struct ucl_parser *parser = ucl_parser_new(0);
    if (parser == NULL) {
        return 0; // Exit if memory allocation for parser fails
    }

    // Step 3: Add the input data to the parser
    ucl_parser_add_string(parser, (char *)data, size);

    // Step 4: Create and initialize a ucl_object_t object
    ucl_object_t *obj = ucl_object_typed_new(UCL_OBJECT);
    if (obj == NULL) {
        ucl_parser_free(parser); // Clean up parser before exiting
        return 0;
    }

    // Step 5: Optionally create another object to simulate real-world flow
    ucl_object_t *cur = ucl_object_fromstring_common("value1", 6, UCL_STRING_TRIM);
    if (cur != NULL) {
        ucl_object_insert_key(obj, cur, "key1", 4, false); // Add key-value pair to obj
    }

    // Step 6: Call the target function with the initialized parameters
    ucl_parser_process_object_element(parser, obj);

    // Step 7: Clean up allocated resources
    ucl_object_unref(obj); // Free the ucl_object_t instance
    //ucl_parser_free(parser); // Free the ucl_parser instance

    return 0; // Return 0 to indicate successful execution
}

Here is the asan log:

==12==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000001 (pc 0x55d209cc29eb bp 0x7ffdc134b650 sp 0x7ffdc134b590 T0)
==12==The signal is caused by a READ memory access.
==12==Hint: address points to the zero page.
SCARINESS: 10 (null-deref)
    #0 0x55d209cc29eb in kh_get_ucl_hash_caseless_node /src/libucl/src/ucl_hash.c:229:1
    #1 0x55d209cc254d in ucl_hash_search /src/libucl/src/ucl_hash.c:464:7
    #2 0x55d209c836a3 in ucl_hash_search_obj /src/libucl/src/./ucl_internal.h:464:31
    #3 0x55d209c836a3 in ucl_parser_process_object_element /src/libucl/src/ucl_parser.c:1249:10
    #4 0x55d209c8189c in LLVMFuzzerTestOneInput /src/libucl/tests/fuzzers/ucl_parser_1239_1_fuzzer.c:36:5
    #5 0x55d209b36330 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13
    #6 0x55d209b35b55 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:516:7
    #7 0x55d209b37335 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:760:19
    #8 0x55d209b380c5 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile>>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:905:5
    #9 0x55d209b26f0b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6
    #10 0x55d209b522e2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #11 0x7f6490561082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 0323ab4806bee6f846d9ad4bccfc29afdca49a58)
    #12 0x55d209b1978d in _start (/out/ucl_parser_1239_1_fuzzer+0x5978d)

DEDUP_TOKEN: kh_get_ucl_hash_caseless_node--ucl_hash_search--ucl_hash_search_obj
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /src/libucl/src/ucl_hash.c:229:1 in kh_get_ucl_hash_caseless_node
==12==ABORTING
MS: 4 EraseBytes-CrossOver-ShuffleBytes-InsertByte-; base unit: b40ba5a36dccbea2f1a9b9ebcc5b77a8be9e5d1b
0x5b,0xff,0xff,
[\377\377
artifact_prefix='ucl_parser_1239_1_fuzzer_'; Test unit written to ucl_parser_1239_1_fuzzer_crash-30694c0933825dd53abe96d8adc057937a1b84c3
Base64: W///

Anza2001 avatar Mar 25 '25 08:03 Anza2001

It's quite apparent that ucl_parser_process_object_element is not intended for such a usage.

vstakhov avatar Mar 26 '25 08:03 vstakhov