Cyan4973 / Cyan4973/FiniteStateEntropy
heap-buffer-overflow in HUF_decompress4X1 (1-byte OOB write)
- Dominant language
- C
- Stars
- 1.5k
- Forks
- 165
- PR merge metrics
- No merged PRs in 30d
Description
Running a fuzz test for the decompress functions ran into a an out of bounds write.
`HUF_decompress4X1()` writes one byte past the end of the supplied output buffer when `dstSize` is small and not a multiple of 4.
### Steps to reproduce
Create a file `reproducer.c` and insert the following content:
```c
#define HUF_STATIC_LINKING_ONLY
#include
#include
#include
#include "huf.h"
int main() {
static const uint8_t input[] = {
0x05, 0x01, 0x0b, 0xf7, 0x81, 0x21, 0x08, 0x00, 0x12, 0x00, 0x19, 0x00, 0xac,
0x60, 0x00, 0xac, 0xf3, 0xac, 0xac, 0xac, 0x66, 0xac, 0x00, 0xac, 0x00, 0x26,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
0x91, 0x80, 0xe6, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xe1, 0x27, 0x27, 0x27,
0x5b, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0xa4, 0x53, 0xff, 0xff,
0xff, 0xff, 0x53, 0x53, 0xac, 0xff, 0x00, 0xac};
size_t inputSize = sizeof(input);
size_t dstSize = 5;
void *dst = malloc(dstSize);
size_t ret = HUF_decompress4X1(dst, dstSize, input, inputSize);
free(dst);
return 0;
}
```
Compile with AddressSanitizer and run the reproducer binary.
```
$ clang -fsanitize=address -g \
-Ilib \
reproducer.c \
lib/entropy_common.c lib/hist.c \
lib/fse_decompress.c lib/fse_compress.c \
lib/huf_compress.c lib/huf_decompress.c \
-o reproducer && ./reproducer
```
Which produces the following ASAN report:
```
=================================================================
==33550==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000000015 at pc 0x5576ecba1784 bp 0x7ffe807e8350 sp 0x7ffe807e8348
WRITE of size 1 at 0x502000000015 thread T0
#0 0x5576ecba1783 in HUF_decodeStreamX1 /workspace/lib/huf_decompress.c:234:9
#1 0x5576ecba1783 in HUF_decompress4X1_usingDTable_internal_body /workspace/lib/huf_decompress.c:344:9
#2 0x5576ecba1783 in HUF_decompress4X1_usingDTable_internal_default /workspace/lib/huf_decompress.c:363:1
#3 0x5576ecb90f54 in HUF_decompress4X1_usingDTable_internal /workspace/lib/huf_decompress.c:363:1
#4 0x5576ecb9109b in HUF_decompress4X1_DCtx_wksp_bmi2 /workspace/lib/huf_decompress.c:428:12
#5 0x5576ecb90fc3 in HUF_decompress4X1_DCtx_wksp /workspace/lib/huf_decompress.c:435:12
#6 0x5576ecb911fb in HUF_decompress4X1_DCtx /workspace/lib/huf_decompress.c:442:12
#7 0x5576ecb91415 in HUF_decompress4X1 /workspace/lib/huf_decompress.c:448:12
#8 0x5576ecb783d3 in main /workspace/reproducer.c:23:18
#9 0x7ff1779b21c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 8e9fd827446c24067541ac5390e6f527fb5947bb)
#10 0x7ff1779b228a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 8e9fd827446c24067541ac5390e6f527fb5947bb)
#11 0x5576eca9c2e4 in _start (/workspace/reproducer+0x2c2e4) (BuildId: f816dd2279ee8e6c3d47b5c17093cf1bddd132eb)
0x502000000015 is located 0 bytes after 5-byte region [0x502000000010,0x502000000015)
allocated by thread T0 here:
#0 0x5576ecb3a7e2 in malloc (/workspace/reproducer+0xca7e2) (BuildId: f816dd2279ee8e6c3d47b5c17093cf1bddd132eb)
#1 0x5576ecb783b7 in main /workspace/reproducer.c:21:17
#2 0x7ff1779b21c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 8e9fd827446c24067541ac5390e6f527fb5947bb)
#3 0x7ff1779b228a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 8e9fd827446c24067541ac5390e6f527fb5947bb)
#4 0x5576eca9c2e4 in _start (/workspace/reproducer+0x2c2e4) (BuildId: f816dd2279ee8e6c3d47b5c17093cf1bddd132eb)
SUMMARY: AddressSanitizer: heap-buffer-overflow /workspace/lib/huf_decompress.c:234:9 in HUF_decodeStreamX1
Shadow bytes around the buggy address:
0x501ffffffd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501ffffffe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501ffffffe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501fffffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x501fffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x502000000000: fa fa[05]fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x502000000280: 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
==33550==ABORTING
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.