damus-io / nostrdb

The unfairly fast embedded nostr database backed by lmdb
Other
87 stars 15 forks source link

Global buffer overflow in char_to_hex() #10

Closed geeknik closed 11 months ago

geeknik commented 11 months ago

This error is occurring because the hex_table array is being accessed with an index that is outside its bounds.

==34840==ERROR: AddressSanitizer: global-buffer-overflow on address 0x00000038f47f at pc 0x000000512353 bp 0x7ff980f5b050 sp 0x7ff980f5b048
READ of size 1 at 0x00000038f47f thread T2
    #0 0x512352 in char_to_hex /root/nostrdb/./hex.h:18:6
    #1 0x512352 in hex_decode /root/nostrdb/./hex.h:31:37
    #2 0x512352 in ndb_ingester_json_controller /root/nostrdb/nostrdb.c:317:2
    #3 0x512cf1 in ndb_json_parser_parse /root/nostrdb/nostrdb.c:1046:11
    #4 0x512cf1 in ndb_ws_event_from_json /root/nostrdb/nostrdb.c:1621:13
    #5 0x500597 in ndb_ingester_process_event /root/nostrdb/nostrdb.c:386:3
    #6 0x500597 in ndb_ingester_thread /root/nostrdb/nostrdb.c:673:9
    #7 0x7ff98926c608 in start_thread /build/glibc-SzIz7B/glibc-2.31/nptl/pthread_create.c:477:8
    #8 0x7ff989017132 in clone /build/glibc-SzIz7B/glibc-2.31/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95

0x00000038f47f is located 1 bytes to the left of global variable 'hex_table' defined in './hex.h:7:19' (0x38f480) of size 256
0x00000038f47f is located 60 bytes to the right of global variable '<string literal>' defined in 'nostrdb.c:1091:48' (0x38f440) of size 3
  '<string literal>' is ascii string '\t'
SUMMARY: AddressSanitizer: global-buffer-overflow /root/nostrdb/./hex.h:18:6 in char_to_hex
static inline int char_to_hex(unsigned char *val, int c)
{
    if (hex_table[(int)c] || c == '0') {
        *val = hex_table[c];
        return 1;
    }
    return 0;
}

If I'm reading the code correctly, c is being used as an index into hex_table, but there is no guarantee that c is within the valid range of indices for hex_table. Since hex_table has 256 elements, valid indices are in the range [0, 255]. If c is outside this range, it will result in undefined behavior, such as the buffer overflow indicated above.

Here's a base64 representation of the bad data which triggers this:

ImlkIiIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDD/MDAwMDAw
MDAwMDAwMDAwMDAwIg==