michaelrsweet / htmldoc

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

Heap overflow in pspdf_transform_coords() #467

Closed Jorgecmartins closed 2 years ago

Jorgecmartins commented 2 years ago

In pspdf_transform_coords(), in ps-pdf.cxx, there is a heap buffer overflow:

static void
pspdf_transform_coords(page_t *p,   // I - Page
                       float  &x,   // IO - X coordinate
               float  &y)   // IO - Y coordinate
{
  float tx, ty;             // Temporary X and Y

  tx = x;
  ty = y;
  x  = tx * p->outmatrix[0][0] + ty * p->outmatrix[0][1] + p->outmatrix[0][2];
  y  = tx * p->outmatrix[1][0] + ty * p->outmatrix[1][1] + p->outmatrix[1][2];
}

The vulnerability is triggered in pspdf_transform_coords(), when accessing page_t *p, since it points to arbitrary memory. page_t *p is fetched from an array of pages, in the following code:

2850    pspdf_transform_coords(pages + chapter_starts[0], x, y);

In this situation, the variable num_pages = 10, and chapter_starts[0] = 10, so page_t *p points to arbitrary memory, resulting in a heap overflow in p->outmatrix[0][0].

I've attached poc.zip that can trigger the heap overflow.

Steps to reproduce

$ unzip poc.zip
$ # Compiling htmldoc with -fsanitize=address,bounds
$ htmldoc -f output.pdf poc

=================================================================
==154271==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x621000003a6c at pc 0x55f5e8fc61a3 bp 0x7ffe27311790 sp 0x7ffe27311780
READ of size 4 at 0x621000003a6c thread T0
    #0 0x55f5e8fc61a2 in pspdf_transform_coords /home/fuzz/fuzzing/htmldoc/htmldoc/ps-pdf.cxx:1071
    #1 0x55f5e8fd13f9 in pdf_write_contents /home/fuzz/fuzzing/htmldoc/htmldoc/ps-pdf.cxx:2850
    #2 0x55f5e8fd2754 in pdf_write_contents /home/fuzz/fuzzing/htmldoc/htmldoc/ps-pdf.cxx:3002
    #3 0x55f5e8fce8f8 in pdf_write_document /home/fuzz/fuzzing/htmldoc/htmldoc/ps-pdf.cxx:2331
    #4 0x55f5e8fc519b in pspdf_export /home/fuzz/fuzzing/htmldoc/htmldoc/ps-pdf.cxx:910
    #5 0x55f5e8fa6caf in main /home/fuzz/fuzzing/htmldoc/htmldoc/htmldoc.cxx:1291
    #6 0x7f61ac24e0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #7 0x55f5e8f94bed in _start (/home/fuzz/fuzzing/htmldoc/fuzzing/analysis/htmldoc+0x57bed)

0x621000003a6c is located 380 bytes to the right of 4080-byte region [0x621000002900,0x6210000038f0)
allocated by thread T0 here:
    #0 0x7f61ad293bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #1 0x55f5e900eec0 in check_pages /home/fuzz/fuzzing/htmldoc/htmldoc/ps-pdf.cxx:8850
    #2 0x55f5e8fc1ce8 in pspdf_export /home/fuzz/fuzzing/htmldoc/htmldoc/ps-pdf.cxx:636
    #3 0x55f5e8fa6caf in main /home/fuzz/fuzzing/htmldoc/htmldoc/htmldoc.cxx:1291
    #4 0x7f61ac24e0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/fuzz/fuzzing/htmldoc/htmldoc/ps-pdf.cxx:1071 in pspdf_transform_coords
michaelrsweet commented 2 years ago

@Jorgecmartins Seems like the fix for #468 fixed this as well? I can't reproduce with master...

Jorgecmartins commented 2 years ago

@Jorgecmartins Seems like the fix for #468 fixed this as well? I can't reproduce with master...

@michaelrsweet I'm still able to reproduce it in master.

jorge~/htmldoc/analysis$ git pull
Already up to date.
jorge~/htmldoc/analysis$ ./htmldoc -f out.pdf poc
ERR005: Unable to open psglyphs data file!
ERR005: Unable to open character set file iso-8859-1!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Times-Roman.afm!
ERR005: Unable to open psglyphs data file!
ERR005: Unable to open character set file iso-8859-1!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Times-Roman.afm!
ERR005: Unable to open psglyphs data file!
ERR005: Unable to open character set file iso-8859-1!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Times-Roman.afm!
ERR005: Unable to open psglyphs data file!
ERR005: Unable to open character set file iso-8859-1!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Times-Roman.afm!
ERR005: Unable to open psglyphs data file!
ERR005: Unable to open character set file iso-8859-1!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica-Bold.afm!
ERR005: Unable to open psglyphs data file!
ERR005: Unable to open character set file iso-8859-1!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Times-Roman.afm!
ERR005: Unable to open psglyphs data file!
ERR005: Unable to open character set file iso-8859-1!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Times-Roman.afm!
ERR005: Unable to open psglyphs data file!
ERR005: Unable to open character set file iso-8859-1!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Times-Roman.afm!
ERR005: Unable to open psglyphs data file!
ERR005: Unable to open character set file iso-8859-1!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Times-Roman.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Helvetica.afm!
ERR005: Unable to open font width file /usr/local/share/htmldoc/fonts/Times-Bold.afm!
PAGES: 10
ERR005: Unable to open font file /usr/local/share/htmldoc/fonts/Courier.pfa!
ERR005: Unable to open font file /usr/local/share/htmldoc/fonts/Times-Roman.pfa!
ERR005: Unable to open font file /usr/local/share/htmldoc/fonts/Times-Bold.pfa!
ERR005: Unable to open font file /usr/local/share/htmldoc/fonts/Helvetica.pfa!
=================================================================
==39691==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x621000003a6c at pc 0x0000005081d9 bp 0x7fffdfb5b1b0 sp 0x7fffdfb5b1a8
READ of size 8 at 0x621000003a6c thread T0
    #0 0x5081d8 in pspdf_transform_coords(page_t*, float&, float&) /home/jorge/htmldoc/htmldoc/ps-pdf.cxx:1071:13
    #1 0x5081d8 in pdf_write_contents(_IO_FILE*, tree_str*, int, int, int, int*) /home/jorge/htmldoc/htmldoc/ps-pdf.cxx:2850:5
    #2 0x508130 in pdf_write_contents(_IO_FILE*, tree_str*, int, int, int, int*) /home/jorge/htmldoc/htmldoc/ps-pdf.cxx:3004:5
    #3 0x4e96a0 in pdf_write_document(unsigned char*, unsigned char*, unsigned char*, unsigned char*, unsigned char*, unsigned char*, tree_str*, tree_str*) /home/jorge/htmldoc/htmldoc/ps-pdf.cxx:2331:5
    #4 0x4e96a0 in pspdf_export /home/jorge/htmldoc/htmldoc/ps-pdf.cxx:910:7
    #5 0x4d2193 in main /home/jorge/htmldoc/htmldoc/htmldoc.cxx:1291:3
    #6 0x7f5ec8cb40b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
    #7 0x41d87d in _start (/home/jorge/htmldoc/analysis/htmldoc+0x41d87d)

0x621000003a6c is located 380 bytes to the right of 4080-byte region [0x621000002900,0x6210000038f0)
allocated by thread T0 here:
    #0 0x495fbd in malloc (/home/jorge/htmldoc/analysis/htmldoc+0x495fbd)
    #1 0x4f32f3 in check_pages(int) /home/jorge/htmldoc/htmldoc/ps-pdf.cxx:8852:24
    #2 0x4d2193 in main /home/jorge/htmldoc/htmldoc/htmldoc.cxx:1291:3
    #3 0x7f5ec8cb40b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/jorge/htmldoc/htmldoc/ps-pdf.cxx:1071:13 in pspdf_transform_coords(page_t*, float&, float&)
Shadow bytes around the buggy address:
  0x0c427fff86f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fff8700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c427fff8710: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa fa
  0x0c427fff8720: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff8730: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c427fff8740: fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]fa fa
  0x0c427fff8750: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff8760: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff8770: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff8780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c427fff8790: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 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
==39691==ABORTING
michaelrsweet commented 2 years ago

Try this:

[master d6cd712] Fix a potential heap overflow bug with the table-of-contents (Issue #467)