LibreDWG/libredwg

NULL dereference in header_variables_dxf.spec:26

zodf0055980 opened this issue · 9 comments

I found a NULL dereference in the current master (7f525b9).

Configure

CFLAGS="-g -fsanitize=address" LDFLAGS="-fsanitize=address" ./configure

Command

./dwg2dxf -o /dev/null -m -y ./poc1

ASAN report

➜  ./dwg2dxf -o /dev/null -m -y ./poc1 

Reading DWG file ./poc1
ERROR: bit_read_fixed buffer overflow at pos 128, size 152
ERROR: read_file_header Invalid file_header->header_size 9223091660467011385 > MAX_SIZE
ERROR: read_file_header Invalid file_header->file_size 65362 > MAX_SIZE
ERROR: read_file_header Invalid file_header->pages_maxid 9218588057970734863 > MAX_COUNT
ERROR: read_file_header Invalid file_header->pages_amount 1095652868096 > MAX_COUNT
ERROR: read_file_header Invalid file_header->num_sections 9177492712645984768 > MAX_COUNT
Writing DXF file /dev/null
ASAN:DEADLYSIGNAL
=================================================================
==10341==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000010 (pc 0x7ffff3c883cf bp 0x7fffffffcac0 sp 0x7fffffffc1c0 T0)
==10341==The signal is caused by a READ memory access.
==10341==Hint: address points to the zero page.
    #0 0x7ffff3c883ce in dxf_header_write /home/yuan/afl-target/libredwg-test/src/header_variables_dxf.spec:26
    #1 0x7ffff3cbfc7e in dwg_write_dxf /home/yuan/afl-target/libredwg-test/src/out_dxf.c:3621
    #2 0x5555555589bc in main /home/yuan/afl-target/libredwg-test/programs/dwg2dxf.c:336
    #3 0x7ffff1e6bbf6 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
    #4 0x555555556a89 in _start (/home/yuan/afl-target/libredwg-test/programs/.libs/dwg2dxf+0x2a89)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/yuan/afl-target/libredwg-test/src/header_variables_dxf.spec:26 in dxf_header_write
==10341==ABORTING

POC

poc1.zip

Already fixed with 5d2c75f

@rurban But I test in 8072563, it still have this problem.

I get this

ERROR: bit_read_fixed buffer overflow at pos 128, size 152
seqence_crc64: 0000006D4E0044B8
seqence_key:   7FCB000000004554
compr_crc64:   7F0900FEFE004500
compr_len:     8288
len2:          2130706432
ERROR: Decompression error: offset underflow

num_objects: 0
num_object_refs: 0
ERROR: Failed to read 2007 meta data
ERROR: Failed to decode file: ../test/issues/gh321/poc1.dwg 0x400

READ ERROR 0x400

which is good

I do not get a NULL dereference error without ASAN. Maybe this is asan problem (?).

Dont think so. I'll let it open for a while

I think this problem is about data in read_file_header didn't initialize.
In read_file_header, it creates data[0x3d8] but uninitialized.

BITCODE_RC data[0x3d8]; // 0x400 - 5 long

And in this POC, in bit_read_fixed in read_file_header will detect buffer overflow, so data is still uninitialized.
bit_read_fixed (dat, data, 0x3d8);

libredwg/src/bits.c

Lines 1415 to 1424 in f086e9d

bit_read_fixed (Bit_Chain *restrict dat, BITCODE_RC *restrict dest,
unsigned int length)
{
if (dat->byte + length > dat->size)
{
loglevel = dat->opts & DWG_OPTS_LOGLEVEL;
LOG_ERROR ("%s buffer overflow at pos %lu, size %lu", __FUNCTION__,
dat->byte, dat->size)
return;
}

so pedata may has uninitialized values to let a lot of variable error.

libredwg/src/decode_r2007.c

Lines 1198 to 1213 in 625da7a

bit_read_fixed (dat, data, 0x3d8);
pedata = decode_rs (data, 3, 239, 0x3d8);
if (!pedata)
return DWG_ERR_OUTOFMEM;
// Note: This is unportable to big-endian
seqence_crc = *((uint64_t *)pedata);
seqence_key = *((uint64_t *)&pedata[8]);
compr_crc = *((uint64_t *)&pedata[16]);
compr_len = *((int32_t *)&pedata[24]);
len2 = *((int32_t *)&pedata[28]);
LOG_TRACE ("seqence_crc64: %016lX\n", (unsigned long)seqence_crc);
LOG_TRACE ("seqence_key: %016lX\n", (unsigned long)seqence_key);
LOG_TRACE ("compr_crc64: %016lX\n", (unsigned long)compr_crc);
LOG_TRACE ("compr_len: %d\n", (int)compr_len); // only this is used
LOG_TRACE ("len2: %d\n", (int)len2); // 0 when compressed

I think this is why program execute paths are different.

Yes, a memset is needed. Nice catch

Thanks, Could I try to submit these problems to get CVE IDs in version 0.12.3 ?

Sure you can. But do it now, as they need way too long. Like over 14 days.

I have over 20 such issues in private also