Project: libredwg (libredwg/libredwg), language: c++
Vulnerability instance: libredwg.cve-2018-14524
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/LibreDWG/libredwg/issues/33
## Description:
Issue: LibreDWG/libredwg#33
Title: double free in dwg_free
State: closed
Created by: jinyu00
Created at: 2018-07-20 23:26:33+00:00
Labels: bug

Issue Body:

When open the crafted  `dwg` file , it could tigger `double free` in `dwg2svg2`

Let's see the program error output 

```
15:20 haclh@ubuntu:examples $ ./dwg2svg2 dfree_poc_155 
......................................................................
......................................................................
......................................................................
=================================================================
*** Error in `./dwg2svg2': double free or corruption (fasttop): 0x0000000001336430 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f18b82547e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f18b825d37a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f18b826153c]
./dwg2svg2[0x499e0b]
./dwg2svg2[0x49a31a]
./dwg2svg2[0x4a18e9]
./dwg2svg2[0x4a239d]
./dwg2svg2[0x40d13f]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f18b81fd830]
./dwg2svg2[0x40d3a9]
======= Memory map: ========
00400000-00569000 r-xp 00000000 08:10 1140093                            /home/haclh/vmdk/fuzz_workplace/libredwg-0.5.1048/examples/dwg2svg2
00768000-00769000 r--p 00168000 08:10 1140093                            /home/haclh/vmdk/fuzz_workplace/libredwg-0.5.1048/examples/dwg2svg2
00769000-0076a000 rw-p 00169000 08:10 1140093                            /home/haclh/vmdk/fuzz_workplace/libredwg-0.5.1048/examples/dwg2svg2
0076a000-0076c000 rw-p 00000000 00:00 0 
01319000-0135b000 rw-p 00000000 00:00 0                                  [heap]
7f18b3dea000-7f18b3e00000 r-xp 00000000 08:01 1315919                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7f18b3e00000-7f18b3fff000 ---p 00016000 08:01 1315919                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7f18b3fff000-7f18b4000000 rw-p 00015000 08:01 1315919                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7f18b4000000-7f18b4021000 rw-p 00000000 00:00 0 
7f18b4021000-7f18b8000000 ---p 00000000 00:00 0 
7f18b81dd000-7f18b839d000 r-xp 00000000 08:01 1366856                    /lib/x86_64-linux-gnu/libc-2.23.so
7f18b839d000-7f18b859d000 ---p 001c0000 08:01 1366856                    /lib/x86_64-linux-gnu/libc-2.23.so
7f18b859d000-7f18b85a1000 r--p 001c0000 08:01 1366856                    /lib/x86_64-linux-gnu/libc-2.23.so
7f18b85a1000-7f18b85a3000 rw-p 001c4000 08:01 1366856                    /lib/x86_64-linux-gnu/libc-2.23.so
7f18b85a3000-7f18b85a7000 rw-p 00000000 00:00 0 
7f18b85a7000-7f18b86af000 r-xp 00000000 08:01 1315583                    /lib/x86_64-linux-gnu/libm-2.23.so
7f18b86af000-7f18b88ae000 ---p 00108000 08:01 1315583                    /lib/x86_64-linux-gnu/libm-2.23.so
7f18b88ae000-7f18b88af000 r--p 00107000 08:01 1315583                    /lib/x86_64-linux-gnu/libm-2.23.so
7f18b88af000-7f18b88b0000 rw-p 00108000 08:01 1315583                    /lib/x86_64-linux-gnu/libm-2.23.so
7f18b88b0000-7f18b88d6000 r-xp 00000000 08:01 1366854                    /lib/x86_64-linux-gnu/ld-2.23.so
7f18b8aaf000-7f18b8ab3000 rw-p 00000000 00:00 0 
7f18b8ad4000-7f18b8ad5000 rw-p 00000000 00:00 0 
7f18b8ad5000-7f18b8ad6000 r--p 00025000 08:01 1366854                    /lib/x86_64-linux-gnu/ld-2.23.so
7f18b8ad6000-7f18b8ad7000 rw-p 00026000 08:01 1366854                    /lib/x86_64-linux-gnu/ld-2.23.so
7f18b8ad7000-7f18b8ad8000 rw-p 00000000 00:00 0 
7fff6f0da000-7fff6f0fb000 rw-p 00000000 00:00 0                          [stack]
7fff6f127000-7fff6f12a000 r--p 00000000 00:00 0                          [vvar]
7fff6f12a000-7fff6f12c000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

```

And the output with **asan**

```
15:20 haclh@ubuntu:examples $ ./dwg2svg2 dfree_poc_155 
......................................................................
......................................................................
......................................................................
=================================================================
==101914==ERROR: AddressSanitizer: attempting double-free on 0x60400000dbd0 in thread T0:
    #0 0x7f9dcd3e32ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
    #1 0x642d83 in dwg_free_eed /home/haclh/workplace/libredwg-0.5.1048/src/free.c:283
    #2 0x6513db in dwg_free_UNKNOWN_OBJ /home/haclh/workplace/libredwg-0.5.1048/src/dwg.spec:5437
    #3 0x6513db in dwg_free_BLOCK_HEADER /home/haclh/workplace/libredwg-0.5.1048/src/dwg.spec:2177
    #4 0x664f98 in dwg_free_object /home/haclh/workplace/libredwg-0.5.1048/src/free.c:471
    #5 0x667d2a in dwg_free /home/haclh/workplace/libredwg-0.5.1048/src/free.c:640
    #6 0x42d81d in test_SVG /home/haclh/workplace/libredwg-0.5.1048/examples/dwg2svg2.c:92
    #7 0x42d81d in main /home/haclh/workplace/libredwg-0.5.1048/examples/dwg2svg2.c:482
    #8 0x7f9dccfa182f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #9 0x42de88 in _start (/home/haclh/workplace/libredwg-0.5.1048/examples/dwg2svg2+0x42de88)

0x60400000dbd0 is located 0 bytes inside of 40-byte region [0x60400000dbd0,0x60400000dbf8)
freed by thread T0 here:
    #0 0x7f9dcd3e32ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
    #1 0x47ee9f in dwg_decode_eed /home/haclh/workplace/libredwg-0.5.1048/src/decode.c:2311

previously allocated by thread T0 here:
    #0 0x7f9dcd3e379a in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x9879a)
    #1 0x47e349 in dwg_decode_eed /home/haclh/workplace/libredwg-0.5.1048/src/decode.c:2304

SUMMARY: AddressSanitizer: double-free ??:0 __interceptor_free
==101914==ABORTING

```

According **debuging**,  I found that When open the crafted  `dwg` file ,  `dwg_free` could call `dwg_decode_eed` , in `dwg_free_object`  first,  it could call `dwg_free_BLOCK_HEADER` to free a pointer (for example : `0x789430` )

```
void
dwg_free_object(Dwg_Object *obj)
{
  switch (obj->type)
    {
    case DWG_TYPE_TEXT:
    ........................
    ........................
    ........................
    case DWG_TYPE_BLOCK_HEADER:
      dwg_free_BLOCK_HEADER(dat, obj);
      break;

```

The backtrace are as below

```
   f 0     7ffff77884f0 free
 ► f 1           49a1c4 dwg_free_BLOCK_HEADER.isra.7+68
   f 2           4a18e9 dwg_free_object+1161
   f 3           4a239d dwg_free+157
   f 4           40d13f main+575
   f 5           40d13f main+575
   f 6     7ffff7724830 __libc_start_main+240
```



And then it could call `dwg_free_BLOCK_HEADER` again , it could call `dwg_free_eed` to free `0x789430`  again.

The backtrace are as below

```
pwndbg> bt
#0  __GI___libc_free (mem=0x789430) at malloc.c:2934
#1  0x0000000000499e0b in dwg_free_eed (obj=0x7988e8, obj=0x7988e8) at free.c:283
#2  0x000000000049a31a in dwg_free_BLOCK_HEADER (obj=0x7988e8, _dat=<optimized out>) at dwg.spec:2285
#3  0x00000000004a18e9 in dwg_free_object (obj=0x7988e8) at free.c:471
#4  0x00000000004a239d in dwg_free (dwg=dwg@entry=0x769400 <g_dwg>) at free.c:640
#5  0x000000000040d13f in test_SVG (filename=<optimized out>) at dwg2svg2.c:92
#6  main (argc=argc@entry=2, argv=argv@entry=0x7fffffffe4c8) at dwg2svg2.c:479
#7  0x00007ffff7724830 in __libc_start_main (main=0x40cf00 <main>, argc=2, argv=0x7fffffffe4c8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe4b8) at ../csu/libc-start.c:291
#8  0x000000000040d3a9 in _start ()

```



The poc file

```
https://gitee.com/hac425/fuzz_data/blob/master/double_free_on_libredwg_155
```














Comments:
Comment by jinyu00 on 2018-07-22 07:57:39+00:00:
I found the fix method is to add a line code in `decode.c : 2311`  's  `dwg_decode_eed function`

The orgin code:

```
        LOG_ERROR("No EED[%d].handle", idx);
        obj->num_eed = 0;
        free(obj->eed);
        return error;
      } else {
```
After `obj->eed` ,  the program don't set the `obj->eed=0`, so the code after fix are as below
```
        LOG_ERROR("No EED[%d].handle", idx);
        obj->num_eed = 0;
        free(obj->eed);
	obj->eed = (Dwg_Eed* )0;  // the fixed line
        return error;
      } else {
```




---

Comment by rurban on 2018-07-22 11:44:41+00:00:
Nice

---

Comment by jinyu00 on 2018-07-22 14:05:15+00:00:
Thanks. Why don't you create a commit to fix it?

---

Comment by rurban on 2018-07-22 20:49:11+00:00:
Because I'm just busy with something else

---

Comment by rurban on 2018-08-13 10:13:54+00:00:
And please don't file CVE's for unreleased versions in the future. 0.5.1048 was never a released version, clearly marked as Pre-Release on github.

For releases see https://ftp.gnu.org/gnu/libredwg/

---

Comment by weiyi20100622 on 2019-04-20 07:44:48+00:00:
@jinyu00  hi,jinyu00.  I want to know that in which branch and which tag this bug be found.


---

Comment by rurban on 2019-04-20 08:27:06+00:00:
This bug was in 0.5.1048  and fixed in 0.5.1067 (Jul 2018), master. 

---

Comment by weiyi20100622 on 2019-04-21 05:47:30+00:00:
> This bug was in 0.5.1048 and fixed in 0.5.1067 (Jul 2018), master.

thanks to your reply.

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
sh ./autogen.sh
./configure --disable-shared
make -j$(nproc)

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y autoconf libtool texinfo
RUN git clone https://github.com/libredwg/libredwg libredwg
RUN git -C libredwg checkout 1ef54e1402bcf17e34030e8be74434e085ee4637
WORKDIR $SRC/libredwg
COPY build.sh $SRC/

Additional files:
filename: fuzz_dwg_decode.options
content: [libfuzzer]
detect_leaks=0