coderforlife / ms-compress

Open source implementations of Microsoft compression algorithms
205 stars 46 forks source link

Xpress-huffman can read outside of the provided buffer #20

Closed nemequ closed 8 years ago

nemequ commented 8 years ago

If you attempt to compress a single byte with xpress-huffman it will read outside the buffer you provide to it. Test case:

#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>

#define CODEC MSCOMP_XPRESS_HUFF

#include "include/mscomp.h"

int main(int argc, char *argv[]) {
  uint8_t uncompressed;
  uint8_t compressed[1024];
  uint8_t decompressed;
  size_t compressed_length = sizeof(compressed);
  size_t decompressed_length = 1;

  assert (ms_max_compressed_size (CODEC, 1) <= sizeof(compressed));

  compressed_length = ms_max_compressed_size (CODEC, 1);
  uncompressed = (uint8_t) 42; /* <- doesn't matter */

  MSCompStatus status = ms_compress (CODEC, &uncompressed, 1, compressed, &compressed_length);
  assert (status == MSCOMP_OK);

  status = ms_decompress(CODEC, compressed, compressed_length, &decompressed, &decompressed_length);
  assert (status == MSCOMP_OK);

  assert (decompressed == uncompressed);

  return 0;
}

Sample output from AddressSanitizer:

=================================================================
==17331==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc497e8101 at pc 0x00000041497a bp 0x7ffc496a6fe0 sp 0x7ffc496a6fd0
READ of size 1 at 0x7ffc497e8101 thread T0
    #0 0x414979 in XpressDictionary<65535u, 65536u, 15u, 3u>::Fill(unsigned char const*) src/../include/mscomp/XpressDictionary.h:103
    #1 0x412434 in xh_compress_lz77 src/xpress_huff_compress.cpp:60
    #2 0x4141d5 in xpress_huff_compress src/xpress_huff_compress.cpp:297
    #3 0x408daf in ms_compress src/mscomp.cpp:116
    #4 0x401281 in main /home/nemequ/local/src/ms-compress/compress.c:22
    #5 0x7f12e5bae6ff in __libc_start_main (/lib64/libc.so.6+0x206ff)
    #6 0x401048 in _start (/home/nemequ/local/src/ms-compress/compress+0x401048)

Address 0x7ffc497e8101 is located in stack of thread T0 at offset 33 in frame
    #0 0x401125 in main /home/nemequ/local/src/ms-compress/compress.c:10

  This frame has 5 object(s):
    [32, 33) 'uncompressed' <== Memory access at offset 33 overflows this variable
    [96, 97) 'decompressed'
    [160, 168) 'compressed_length'
    [224, 232) 'decompressed_length'
    [288, 1312) 'compressed'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow src/../include/mscomp/XpressDictionary.h:103 XpressDictionary<65535u, 65536u, 15u, 3u>::Fill(unsigned char const*)
Shadow bytes around the buggy address:
  0x1000092f4fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000092f4fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000092f4ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000092f5000: 00 00 00 00 00 00 00 00 f3 f3 f3 f3 00 00 00 00
  0x1000092f5010: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
=>0x1000092f5020:[01]f4 f4 f4 f2 f2 f2 f2 01 f4 f4 f4 f2 f2 f2 f2
  0x1000092f5030: 00 f4 f4 f4 f2 f2 f2 f2 00 f4 f4 f4 f2 f2 f2 f2
  0x1000092f5040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000092f5050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000092f5060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000092f5070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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 right 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
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==17331==ABORTING