[gimp] gif: perform bounds checking for table entries



commit c4b4363dfd77f40bc1eeff042b5295b27b33be68
Author: Andrzej Hunt <andrzej ahunt org>
Date:   Fri Sep 10 19:15:17 2021 +0200

    gif: perform bounds checking for table entries
    
    table is specified to have 2 x (1<<12) entries, this in turn is because table
    entries are specified to be smaller than (1<<12). Therefore we need to check
    that each entry is within the specified range.
    
    Without this check, it's possible to induce a buffer overflow read, see ASAN
    output below. However the value that we read is eventually clamped to a
    safe range before being returned, hence this overflow seems pretty useless:
    
    ==10977==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000010a21c0 at pc 0x00000056187b 
bp 0x7ffec915c550 sp 0x7ffec915c548
    READ of size 4 at 0x0000010a21c0 thread T0
        #0 0x56187a in LZWReadByte /home/ahunt/git/gimp/plug-ins/common/file-gif-load.c:913:19
        #1 0x55fc4d in ReadImage /home/ahunt/git/gimp/plug-ins/common/file-gif-load.c:1183:15
        #2 0x55e447 in load_image /home/ahunt/git/gimp/plug-ins/common/file-gif-load.c
        #3 0x561ef0 in LLVMFuzzerTestOneInput 
/home/ahunt/git/gimp/plug-ins/common/file-gif-load_fuzzer.c:79:17
        #4 0x460e44 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) 
/home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15
        #5 0x46034a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, 
bool, bool*) 
/home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:505:3
        #6 0x462067 in fuzzer::Fuzzer::MutateAndTestOne() 
/home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:745:19
        #7 0x462bf5 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, 
fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) 
/home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:883:5
        #8 0x450ea6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) 
/home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906:6
        #9 0x47ae82 in main 
/home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
        #10 0x7f307beb4349 in __libc_start_main (/lib64/libc.so.6+0x24349)
        #11 0x424259 in _start /home/abuild/rpmbuild/BUILD/glibc-2.26/csu/../sysdeps/x86_64/start.S:120
    
    0x0000010a21c0 is located 1088 bytes to the right of global variable 'table' defined in 
'file-gif-load.c:794:15' (0x1099d80) of size 32768
    SUMMARY: AddressSanitizer: global-buffer-overflow 
/home/ahunt/git/gimp/plug-ins/common/file-gif-load.c:913:19 in LZWReadByte
    Shadow bytes around the buggy address:
      0x00008020c3e0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x00008020c3f0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x00008020c400: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x00008020c410: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x00008020c420: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
    =>0x00008020c430: f9 f9 f9 f9 f9 f9 f9 f9[f9]f9 f9 f9 f9 f9 f9 f9
      0x00008020c440: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x00008020c450: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x00008020c460: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x00008020c470: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
      0x00008020c480: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
    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
    ==10977==ABORTING
    
    ( crash-911d5feb07551dd0313d204db4883838139820f5 )

 plug-ins/common/file-gif-load.c | 4 ++++
 1 file changed, 4 insertions(+)
---
diff --git a/plug-ins/common/file-gif-load.c b/plug-ins/common/file-gif-load.c
index 9708a8af6e..a10438482e 100644
--- a/plug-ins/common/file-gif-load.c
+++ b/plug-ins/common/file-gif-load.c
@@ -914,6 +914,10 @@ LZWReadByte (FILE *fd,
 
       while (code >= clear_code && sp < &(stack[STACK_SIZE]))
         {
+          if (code >= (1 << MAX_LZW_BITS)) {
+              g_message ("Invalid table entry.  Corrupt file.");
+              return -1;
+          }
           *sp++ = table[1][code];
           if (code == table[0][code])
             {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]