michaelrsweet / htmldoc

HTML Conversion Software
https://www.msweet.org/htmldoc
GNU General Public License v2.0
208 stars 47 forks source link

Heap-buffer-overflow in function parse_paragraph() in ps-pdf.cxx #431

Closed chibataiki closed 3 years ago

chibataiki commented 3 years ago

Hi,

A heap overflow was found in function parse_paragraph() in ps-pdf.cxx at line 5015. Didn't check whether prev->data is vaild.

── source:ps-pdf.cxx+5015 ────
   5010     {
   5011       break;
   5012     }
   5013     else if (prev->markup == MARKUP_NONE)
   5014     {
                     // ch=0x0, prev=0x00007fffffffd058  →  0x000000000098ff10
●→ 5015       int   ch = prev->data[strlen((char *)prev->data) - 1];
   5016
   5017       if (_htmlUTF8)
   5018         ch = _htmlUnicode[ch];
   5019
   5020            if (ch == 173)
────────────────────────────────────
gef➤  p prev
$1 = (tree_t *) 0x98ff10
gef➤  p prev->data
Cannot access memory at address 0x98ff48

potential fix patch

--- ./htmldoc/ps-pdf.cxx        
+++ ./htmldoc/ps-pdf-tryfix.cxx 
@@ -5012,7 +5012,11 @@
        }
        else if (prev->markup == MARKUP_NONE)
        {
-         int   ch = prev->data[strlen((char *)prev->data) - 1];
+         int ch;
+         if (!prev->data[0])
+           break;
+
+         ch = prev->data[strlen((char *)prev->data) - 1];

          if (_htmlUTF8)
            ch = _htmlUnicode[ch];

Version: 1.9.12 commit [ee77825] Env: ubuntu 20.04 x86_64 clang version 11.0.0

reproduce ./configure make ./htmldoc -f ./check.ps [poc]

zipped poc

detail info

==1701892==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000b98f at pc 0x00000055d6fd bp 0x7ffe4c987670 sp 0x7ffe4c987668
READ of size 1 at 0x60200000b98f thread T0
    #0 0x55d6fc in parse_paragraph(tree_str*, float, float, float, float, float*, float*, int*, int) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:5015:13
    #1 0x586fe1 in parse_heading(tree_str*, float, float, float, float, float*, float*, int*, int) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:4663:3
    #2 0x511582 in parse_doc(tree_str*, float*, float*, float*, float*, float*, float*, int*, tree_str*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:4197:11
    #3 0x593fd1 in render_table_row(hdtable_t&, tree_str***, int, unsigned char*, float, float, float, float, float*, float*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:5829:9
    #4 0x584778 in parse_table(tree_str*, float, float, float, float, float*, float*, int*, int) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:7111:5
    #5 0x510e9d in parse_doc(tree_str*, float*, float*, float*, float*, float*, float*, int*, tree_str*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:4169:11
    #6 0x518f08 in parse_doc(tree_str*, float*, float*, float*, float*, float*, float*, int*, tree_str*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:4515:13
    #7 0x518f08 in parse_doc(tree_str*, float*, float*, float*, float*, float*, float*, int*, tree_str*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:4515:13
    #8 0x518f08 in parse_doc(tree_str*, float*, float*, float*, float*, float*, float*, int*, tree_str*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:4515:13
    #9 0x593fd1 in render_table_row(hdtable_t&, tree_str***, int, unsigned char*, float, float, float, float, float*, float*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:5829:9
    #10 0x584b20 in parse_table(tree_str*, float, float, float, float, float*, float*, int*, int) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:7125:9
    #11 0x510e9d in parse_doc(tree_str*, float*, float*, float*, float*, float*, float*, int*, tree_str*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:4169:11
    #12 0x50e351 in parse_doc(tree_str*, float*, float*, float*, float*, float*, float*, int*, tree_str*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:4083:9
    #13 0x50e351 in parse_doc(tree_str*, float*, float*, float*, float*, float*, float*, int*, tree_str*, int*) /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:4083:9
    #14 0x5098a4 in pspdf_export /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:803:3
    #15 0x4e03e3 in main /home/chiba/htmldoc/htmldoc/htmldoc.cxx:1291:3
    #16 0x7fde4d9200b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
    #17 0x41d85d in _start (/home/chiba/htmldoc/check-sani/bin/htmldoc+0x41d85d)

0x60200000b98f is located 1 bytes to the left of 2-byte region [0x60200000b990,0x60200000b992)
allocated by thread T0 here:
    #0 0x4838e4 in strdup (/home/chiba/htmldoc/check-sani/bin/htmldoc+0x4838e4)
    #1 0x5cba34 in insert_space(tree_str*, tree_str*) /home/chiba/htmldoc/htmldoc/htmllib.cxx:2694:28
    #2 0x5c018a in htmlReadFile /home/chiba/htmldoc/htmldoc/htmllib.cxx:959:6
    #3 0x4e3b89 in read_file(char const*, tree_str**, char const*) /home/chiba/htmldoc/htmldoc/htmldoc.cxx:2492:9
    #4 0x4dfb8f in main /home/chiba/htmldoc/htmldoc/htmldoc.cxx:1177:7
    #5 0x7fde4d9200b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/chiba/htmldoc/htmldoc/ps-pdf.cxx:5015:13 in parse_paragraph(tree_str*, float, float, float, float, float*, float*, int*, int)
Shadow bytes around the buggy address:
  0x0c047fff96e0: fa fa 00 07 fa fa fd fd fa fa 06 fa fa fa 03 fa
  0x0c047fff96f0: fa fa 07 fa fa fa 03 fa fa fa 07 fa fa fa 00 02
  0x0c047fff9700: fa fa 03 fa fa fa 03 fa fa fa 05 fa fa fa 06 fa
  0x0c047fff9710: fa fa 00 fa fa fa 00 02 fa fa fd fd fa fa 04 fa
  0x0c047fff9720: fa fa 06 fa fa fa 03 fa fa fa 07 fa fa fa 03 fa
=>0x0c047fff9730: fa[fa]02 fa fa fa 00 fa fa fa 00 07 fa fa 03 fa
  0x0c047fff9740: fa fa 03 fa fa fa 05 fa fa fa 00 03 fa fa 03 fa
  0x0c047fff9750: fa fa 03 fa fa fa 05 fa fa fa 00 04 fa fa 00 06
  0x0c047fff9760: fa fa 05 fa fa fa 00 02 fa fa 03 fa fa fa 04 fa
  0x0c047fff9770: fa fa 05 fa fa fa 00 03 fa fa 03 fa fa fa 04 fa
  0x0c047fff9780: fa fa 05 fa fa fa 00 07 fa fa fd fd fa fa 02 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==1701892==ABORTING
michaelrsweet commented 3 years ago

[master 85fa76d] Fix another crash bug with bogus data (Issue #431)