LibreDWG v0.12.4.4608 & commit f2dea29 was discovered to contain a heap use-after-free via bit_copy_chain.
cpe:2.3:a:gnu:libredwg:*:*:*:*:*:*:*:*
0A8152A2-6867-4B31-8F47-A1A655A49EFF
0.12.4.4608
OR
# Vulnerability description
version: [0.12.4.4608](https://github.com/LibreDWG/libredwg/releases/tag/0.12.4.4608) & latest  commit [f2dea29](https://github.com/LibreDWG/libredwg/commit/f2dea296a0a3bb16afdae8d2ca16749a617a4383)
poc: [poc](https://github.com/0xdd96/PoC/raw/main/libredwg/UAF-bit_copy_chain)
command: ./dwgrewrite poc

**_This is similar to issue #364 and others, but it seems that the patch https://github.com/LibreDWG/libredwg/commit/e95cc1eea8744c40e298208679eda14039b9b5d3 has not fully fixed them._**

Here is the trace reported by ASAN:
```
==28024==ERROR: AddressSanitizer: heap-use-after-free on address 0x7ffff3b65800 at pc 0x5555564f67f6 bp 0x7fffffff6760 sp 0x7fffffff6750
READ of size 1 at 0x7ffff3b65800 thread T0
    #0 0x5555564f67f5 in bit_read_RC libredwg/src/bits.c:317
    #1 0x5555564f67f5 in bit_copy_chain libredwg/src/bits.c:3352
    #2 0x555556105ec6 in obj_flush_hdlstream libredwg/src/encode.c:833
    #3 0x555556105ec6 in dwg_encode_PLANESURFACE_private libredwg/src/dwg.spec:9150
    #4 0x5555563a57df in dwg_encode_PLANESURFACE libredwg/src/dwg.spec:9136
    #5 0x5555563a57df in dwg_encode_variable_type libredwg/src/classes.inc:247
    #6 0x5555563ab3d0 in dwg_encode_add_object libredwg/src/encode.c:4432
    #7 0x5555563c914c in dwg_encode libredwg/src/encode.c:2769
    #8 0x55555575ca00 in dwg_write_file libredwg/src/dwg.c:429
    #9 0x555555758a3f in main libredwg/programs/dwgrewrite.c:350
    #10 0x7ffff726f0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2)
    #11 0x55555575924d in _start (libredwg/build-ASAN/dwgrewrite+0x20524d)

0x7ffff3b65800 is located 0 bytes inside of 208896-byte region [0x7ffff3b65800,0x7ffff3b98800)
freed by thread T0 here:
    #0 0x7ffff7699ffe in __interceptor_realloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dffe)
    #1 0x5555564f532c in bit_chain_alloc_size libredwg/src/bits.c:3046
    #2 0x5555564f532c in bit_chain_alloc libredwg/src/bits.c:3062
    #3 0x5555564f532c in bit_copy_chain libredwg/src/bits.c:3339
    #4 0x1900000105  (<unknown module>)

previously allocated by thread T0 here:
    #0 0x7ffff7699ffe in __interceptor_realloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dffe)
    #1 0x5555564f396f in bit_chain_alloc_size libredwg/src/bits.c:3046
    #2 0x5555564f396f in bit_chain_alloc libredwg/src/bits.c:3062
    #3 0x31fff  (<unknown module>)
```

# Vulnerability analysis

When running to `bit_copy_chain`, both `dat->chain` and `tmp_dat->chain` point to `0x7ffff3b65800` (see the gdb output below). 

This will lead to use-after-free, since line 3339 calls `realloc`, which frees the chunk `0x7ffff3b65800`, and line 3352 ties to read from the freed chunk. 

Also note that the comment says `bit_copy_chain` *Copy the whole content of tmp_data to dat, and reset tmp_dat*, so why `dat->chain = tmp_dat->chain` in this PoC should be further investigated.

https://github.com/LibreDWG/libredwg/blob/f2dea296a0a3bb16afdae8d2ca16749a617a4383/src/bits.c#L3333-L3360

```
pwndbg> p *dat
$6 = {
  chain = 0x7ffff3b65800,
  size = 208896,
  byte = 204890,
  bit = 6 '\006',
  opts = 1 '\001',
  version = R_2000,
  from_version = R_2004,
  fh = 0x0
}

pwndbg> p *tmp_dat
$10 = {
  chain = 0x7ffff3b65800,
  size = 208896,
  byte = 204882,
  bit = 6 '\006',
  opts = 1 '\001',
  version = R_2000,
  from_version = R_2004,
  fh = 0x0
}
```

Heap use-after-free still exists in the bit_copy_chain
This is a GitHub Issue
repo:libredwg
owner:LibreDWG
Title : Heap use-after-free still exists in the bit_copy_chain
Issue date:

--- start body ---
# Vulnerability description
version: [0.12.4.4608](https://github.com/LibreDWG/libredwg/releases/tag/0.12.4.4608) & latest  commit [f2dea29](https://github.com/LibreDWG/libredwg/commit/f2dea296a0a3bb16afdae8d2ca16749a617a4383)
poc: [poc](https://github.com/0xdd96/PoC/raw/main/libredwg/UAF-bit_copy_chain)
command: ./dwgrewrite poc

**_This is similar to issue #364 and others, but it seems that the patch https://github.com/LibreDWG/libredwg/commit/e95cc1eea8744c40e298208679eda14039b9b5d3 has not fully fixed them._**

Here is the trace reported by ASAN:
```
==28024==ERROR: AddressSanitizer: heap-use-after-free on address 0x7ffff3b65800 at pc 0x5555564f67f6 bp 0x7fffffff6760 sp 0x7fffffff6750
READ of size 1 at 0x7ffff3b65800 thread T0
    #0 0x5555564f67f5 in bit_read_RC libredwg/src/bits.c:317
    #1 0x5555564f67f5 in bit_copy_chain libredwg/src/bits.c:3352
    #2 0x555556105ec6 in obj_flush_hdlstream libredwg/src/encode.c:833
    #3 0x555556105ec6 in dwg_encode_PLANESURFACE_private libredwg/src/dwg.spec:9150
    #4 0x5555563a57df in dwg_encode_PLANESURFACE libredwg/src/dwg.spec:9136
    #5 0x5555563a57df in dwg_encode_variable_type libredwg/src/classes.inc:247
    #6 0x5555563ab3d0 in dwg_encode_add_object libredwg/src/encode.c:4432
    #7 0x5555563c914c in dwg_encode libredwg/src/encode.c:2769
    #8 0x55555575ca00 in dwg_write_file libredwg/src/dwg.c:429
    #9 0x555555758a3f in main libredwg/programs/dwgrewrite.c:350
    #10 0x7ffff726f0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2)
    #11 0x55555575924d in _start (libredwg/build-ASAN/dwgrewrite+0x20524d)

0x7ffff3b65800 is located 0 bytes inside of 208896-byte region [0x7ffff3b65800,0x7ffff3b98800)
freed by thread T0 here:
    #0 0x7ffff7699ffe in __interceptor_realloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dffe)
    #1 0x5555564f532c in bit_chain_alloc_size libredwg/src/bits.c:3046
    #2 0x5555564f532c in bit_chain_alloc libredwg/src/bits.c:3062
    #3 0x5555564f532c in bit_copy_chain libredwg/src/bits.c:3339
    #4 0x1900000105  (<unknown module>)

previously allocated by thread T0 here:
    #0 0x7ffff7699ffe in __interceptor_realloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dffe)
    #1 0x5555564f396f in bit_chain_alloc_size libredwg/src/bits.c:3046
    #2 0x5555564f396f in bit_chain_alloc libredwg/src/bits.c:3062
    #3 0x31fff  (<unknown module>)
```

# Vulnerability analysis

When running to `bit_copy_chain`, both `dat->chain` and `tmp_dat->chain` point to `0x7ffff3b65800` (see the gdb output below). 

This will lead to use-after-free, since line 3339 calls `realloc`, which frees the chunk `0x7ffff3b65800`, and line 3352 ties to read from the freed chunk. 

Also note that the comment says `bit_copy_chain` *Copy the whole content of tmp_data to dat, and reset tmp_dat*, so why `dat->chain = tmp_dat->chain` in this PoC should be further investigated.

https://github.com/LibreDWG/libredwg/blob/f2dea296a0a3bb16afdae8d2ca16749a617a4383/src/bits.c#L3333-L3360

```
pwndbg> p *dat
$6 = {
  chain = 0x7ffff3b65800,
  size = 208896,
  byte = 204890,
  bit = 6 '\006',
  opts = 1 '\001',
  version = R_2000,
  from_version = R_2004,
  fh = 0x0
}

pwndbg> p *tmp_dat
$10 = {
  chain = 0x7ffff3b65800,
  size = 208896,
  byte = 204882,
  bit = 6 '\006',
  opts = 1 '\001',
  version = R_2000,
  from_version = R_2004,
  fh = 0x0
}
```

--- end body ---

comments :
--- start comments ---

--- end comments ---