Hi,
This was found on git master, commit cb85cee9c10efdb5662831c011daa740e9ebb6d5.
I found this file with afl-fuzz. It produces the following crash.
$ ./util/giffix giffix-crash.gif
Following error occurred (and ignored):GIF-LIB error: Image is defective, decoding aborted.
Segmentation fault
When compiled with ASAN:
$ ./util/giffix giffix-crash.gif
Following error occurred (and ignored):GIF-LIB error: Image is defective, decoding aborted.
=================================================================
==12690== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x607a00019d30 at pc 0x4039cd bp 0x7fff9bbd5700 sp 0x7fff9bbd56f8
WRITE of size 1 at 0x607a00019d30 thread T0
#0 0x4039cc in main /root/giflib-code/util/giffix.c:149
#1 0x7fcf80b18ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
#2 0x403ecc in _start (/root/giflib-code/util/.libs/lt-giffix+0x403ecc)
0x607a00019d30 is located 0 bytes to the right of 12336-byte region [0x607a00016d00,0x607a00019d30)
allocated by thread T0 here:
#0 0x7fcf810f941a (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x1541a)
#1 0x401a0f in main /root/giflib-code/util/giffix.c:94
SUMMARY: AddressSanitizer: heap-buffer-overflow /root/giflib-code/util/giffix.c:170 main
Shadow bytes around the buggy address:
0x0c0fbfffb350: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c0fbfffb360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c0fbfffb370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c0fbfffb380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c0fbfffb390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c0fbfffb3a0: 00 00 00 00 00 00[fa]fa fa fa fa fa fa fa fa fa
0x0c0fbfffb3b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0fbfffb3c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0fbfffb3d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0fbfffb3e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0fbfffb3f0: 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
Heap righ redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==12690== ABORTING
Aborted
The file is:
$ xxd -g 1 giffix-crash.gif
0000000: 47 49 46 30 30 30 30 30 30 30 f2 30 30 30 30 30 GIF0000000.00000
0000010: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000
0000020: 30 30 30 30 30 2c 30 30 30 30 30 e0 30 30 30 30 00000,00000.0000
Another file with the same root cause leads to overwriting a pointer that is later free'd.
$ ./util/giffix giffix-free.gif
Following error occurred (and ignored):GIF-LIB error: Image is defective, decoding aborted.
Following unrecoverable error occured:GIF-LIB error: Failed to read from given file.
GIF-LIB undefined error 0.
*** Error in `/root/giflib-code/util/.libs/lt-giffix': free(): invalid pointer: 0x0000000002130a20 ***
Aborted
Under ASAN:
$ ./util/giffix giffix-free.gif
Following error occurred (and ignored):GIF-LIB error: Image is defective, decoding aborted.
=================================================================
==12017== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60080000c000 at pc 0x4039cd bp 0x7ffcfd30fe10 sp 0x7ffcfd30fe08
WRITE of size 1 at 0x60080000c000 thread T0
#0 0x4039cc in main /root/giflib-code/util/giffix.c:149
#1 0x7fec3d650ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
#2 0x403ecc in _start (/root/giflib-code/util/.libs/lt-giffix+0x403ecc)
0x60080000c000 is located 0 bytes to the right of 48-byte region [0x60080000bfd0,0x60080000c000)
allocated by thread T0 here:
#0 0x7fec3dc3141a (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x1541a)
#1 0x401a0f in main /root/giflib-code/util/giffix.c:94
SUMMARY: AddressSanitizer: heap-buffer-overflow /root/giflib-code/util/giffix.c:170 main
Shadow bytes around the buggy address:
0x0c017fff97b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c017fff97c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c017fff97d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c017fff97e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c017fff97f0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00 00
=>0x0c017fff9800:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c017fff9810: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c017fff9820: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c017fff9830: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c017fff9840: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c017fff9850: 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
Heap righ redzone: fb
Freed Heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==12017== ABORTING
Aborted
The second file is:
$ xxd -g 1 giffix-free.gif
0000000: 47 49 46 30 30 30 30 00 30 30 f2 30 30 30 30 30 GIF0000.00.00000
0000010: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000
0000020: 30 30 30 30 30 2c 30 30 30 30 30 03 30 18 ba 30 00000,00000.0..0
0000030: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 0000000000000000
0000040: 30 30 30 30 30 30 30 30 00000000
With both of these files, these images have a corrupt image section within the gif file which has a width greater than the total width (SWidth).
I've made a patch to fix this, as follows:
diff --git a/util/giffix.c b/util/giffix.c
index 6fba84a..04f56fb 100644
--- a/util/giffix.c
+++ b/util/giffix.c
@@ -144,6 +144,9 @@ int main(int argc, char **argv)
fprintf(stderr,"\nFollowing error occurred (and ignored):");
PrintGifError(GifFileIn->Error);
+ if (Width > GifFileIn->SWidth)
+ GIF_EXIT("Image is wider than total");
+
/* Fill in with the darkest color in color map. */
for (j = 0; j < Width; j++)
LineBuffer[j] = DarkestColor;
Hope that helps, let me know if you need any more info.
Cheers,
Hugh
Added first crash file.
Added second crash file (causes bad memory to be free'd when not compiled with ASAN).
Added patch to fix.
Forgot to attache the gdb outputs...
And some when running the first file under ASAN:
I guessed the SWidth thing, because LineBuffer is initialized on line 94
So that shows that with this file, the Width is a lot more than the allocated space, leading to almost instant segfault. The other file the gap isn't as large, so doesn't segfault until free is called at the end. This could be used to build a custom exploit to get remote code execution potentially.
Cheers,
Hugh
Ok, so fuzzing found more with that patch, so I believe you have to move the width check closer to when width is set.
A new patch, also attached.
Hi, Just checking whether anyone has seen this?
Cheers,
Hugh