-
-
Notifications
You must be signed in to change notification settings - Fork 48
Description
Hi, there is two integer overflow bugs in the latest version of htmldoc.
They are similar to CVE-2021-20308.
os: ubuntu 20.04
version: 1.9.16(the latest)
First
First, in image_load_jpeg function, image.cxx.
When it calls malloc,'img->width' and 'img->height' are enough large to cause an integer overflow
So, the malloc function may return a heap block smaller than the expected size, and it will cause a buffer overflow/Address boundary error in the jpeg_read_scanlines function.
Lines 1390 to 1395 in cb4cdee
| static int /* O - 0 = success, -1 = fail */ | |
| image_load_jpeg(image_t *img, /* I - Image pointer */ | |
| FILE *fp, /* I - File to load from */ | |
| int gray, /* I - 0 = color, 1 = grayscale */ | |
| int load_data)/* I - 1 = load image data, 0 = just info */ | |
| { |
Lines 1452 to 1466 in cb4cdee
| img->pixels = (uchar *)malloc((size_t)(img->width * img->height * img->depth)); | |
| if (img->pixels == NULL) | |
| { | |
| jpeg_destroy_decompress(&cinfo); | |
| return (-1); | |
| } | |
| jpeg_start_decompress(&cinfo); | |
| while (cinfo.output_scanline < cinfo.output_height) | |
| { | |
| row = (JSAMPROW)(img->pixels + (size_t)cinfo.output_scanline * (size_t)cinfo.output_width * (size_t)cinfo.output_components); | |
| jpeg_read_scanlines(&cinfo, &row, (JDIMENSION)1); | |
| } |
Asan report:
./htmldoc --webpage -f out.pdf ./test.html
PAGES: 4
Corrupt JPEG data: premature end of data segment
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1326478==ERROR: AddressSanitizer: SEGV on unknown address 0x621000020000 (pc 0x7f0bd38812e1 bp 0x7ffd6a49c500 sp 0x7ffd6a49c460 T0)
==1326478==The signal is caused by a WRITE memory access.
#0 0x7f0bd38812e1 (/lib/x86_64-linux-gnu/libjpeg.so.8+0x422e1)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libjpeg.so.8+0x422e1)
==1326478==ABORTING
And this is the poc file:
poc1.zip
Second
There is another integer overflow bug in image_load_png function, image.cxx, similar to the first one.
Lines 1631 to 1647 in cb4cdee
| img->pixels = (uchar *)calloc(1, (size_t)(img->width * img->height * depth)); | |
| /* | |
| * Allocate pointers... | |
| */ | |
| rows = (png_bytep *)calloc(png_get_image_height(pp, info), sizeof(png_bytep)); | |
| for (i = 0; i < (int)png_get_image_height(pp, info); i ++) | |
| rows[i] = img->pixels + i * img->width * depth; | |
| /* | |
| * Read the image, handling interlacing as needed... | |
| */ | |
| for (i = png_set_interlace_handling(pp); i > 0; i --) | |
| png_read_rows(pp, rows, NULL, (png_uint_32)img->height); |
It calls calloc to get heap block.
However, the width and height of the png file are both four bytes long, so 'img->width' and 'img->height' are enough large to cause an integer overflow.
The calloc function may return a heap block smaller than the expected size, and finally cause a heap overflow in the png_read_rows function when memcpy.
This is the Asan report:
./htmldoc --webpage -f out.pdf ./test.html
PAGES: 4
=================================================================
==1327797==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000008631 at pc 0x000000434be3 bp 0x7ffc5424be70 sp 0x7ffc5424b630
WRITE of size 196608 at 0x602000008631 thread T0
#0 0x434be2 in memcpy (/root/fuzz_workdir/htmldoc/install/bin/htmldoc+0x434be2)
#1 0x7f847c9e379c (/lib/x86_64-linux-gnu/libpng16.so.16+0x1d79c)
#2 0x7f847c9d680b in png_read_row (/lib/x86_64-linux-gnu/libpng16.so.16+0x1080b)
#3 0x7f847c9d81d8 in png_read_rows (/lib/x86_64-linux-gnu/libpng16.so.16+0x121d8)
#4 0x5e8c0b in image_load_png(image_t*, _IO_FILE*, int, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/image.cxx:1647:5
#5 0x5e169d in image_load /root/fuzz_workdir/tmp/htmldoc/htmldoc/image.cxx:845:14
#6 0x54314f in write_image(_IO_FILE*, render_str*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:10305:5
#7 0x55015e in pdf_write_page(_IO_FILE*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:2695:13
#8 0x5175c6 in pdf_write_outpage(_IO_FILE*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:2607:9
#9 0x5175c6 in pdf_write_document(unsigned char*, unsigned char*, unsigned char*, unsigned char*, unsigned char*, unsigned char*, tree_str*, tree_str*) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:2321:5
#10 0x5175c6 in pspdf_export /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:910:7
#11 0x4e30ca in main /root/fuzz_workdir/tmp/htmldoc/htmldoc/htmldoc.cxx:1291:3
#12 0x7f847c3d60b2 in __libc_start_main /build/glibc-sMfBJT/glibc-2.31/csu/../csu/libc-start.c:308:16
#13 0x41e86d in _start (/root/fuzz_workdir/htmldoc/install/bin/htmldoc+0x41e86d)
0x602000008631 is located 0 bytes to the right of 1-byte region [0x602000008630,0x602000008631)
allocated by thread T0 here:
#0 0x499c42 in calloc (/root/fuzz_workdir/htmldoc/install/bin/htmldoc+0x499c42)
#1 0x5e897d in image_load_png(image_t*, _IO_FILE*, int, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/image.cxx:1631:26
#2 0x5e169d in image_load /root/fuzz_workdir/tmp/htmldoc/htmldoc/image.cxx:845:14
#3 0x54314f in write_image(_IO_FILE*, render_str*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:10305:5
#4 0x55015e in pdf_write_page(_IO_FILE*, int) /root/fuzz_workdir/tmp/htmldoc/htmldoc/ps-pdf.cxx:2695:13
SUMMARY: AddressSanitizer: heap-buffer-overflow (/root/fuzz_workdir/htmldoc/install/bin/htmldoc+0x434be2) in memcpy
Shadow bytes around the buggy address:
0x0c047fff9070: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
0x0c047fff9080: fa fa 00 02 fa fa 06 fa fa fa 06 fa fa fa 07 fa
0x0c047fff9090: fa fa 06 fa fa fa 02 fa fa fa 00 07 fa fa fd fd
0x0c047fff90a0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fd
0x0c047fff90b0: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fa
=>0x0c047fff90c0: fa fa fd fa fa fa[01]fa fa fa fa fa fa fa fa fa
0x0c047fff90d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff90e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff90f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9110: 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
==1327797==ABORTING
And this is the poc file:
poc2.zip
(wrong poc)
This is the correct poc:
real_poc2.zip