Heap buffer overflow in Codebook_DecodeSetup
khang06 opened this issue · 0 comments
khang06 commented
i wrote this quick and (very) dirty fuzzer for the vorbis stuff
// this is just a modified version of Music_PlayOgg
// any bugs in that logic *should* appear here
int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size) {
struct Stream source_notptr;
Stream_ReadonlyMemory(&source_notptr, Data, Size);
struct Stream* source = &source_notptr;
uint8_t buffer[OGG_BUFFER_SIZE];
struct Stream stream;
struct VorbisState vorbis = { 0 };
struct AudioFormat fmt;
int chunkSize, samplesPerSecond;
int16_t* data = NULL;
bool completed;
int i, next;
ReturnCode res;
Ogg_MakeStream(&stream, buffer, source);
vorbis.Source = &stream;
if ((res = Vorbis_DecodeHeaders(&vorbis))) goto cleanup;
fmt.Channels = vorbis.Channels;
fmt.SampleRate = vorbis.SampleRate;
fmt.BitsPerSample = 16;
/* largest possible vorbis frame decodes to blocksize1 * channels samples */
/* so we may end up decoding slightly over a second of audio */
chunkSize = fmt.Channels * (fmt.SampleRate + vorbis.BlockSizes[1]);
samplesPerSecond = fmt.Channels * fmt.SampleRate;
data = (int16_t*)Mem_Alloc(chunkSize * AUDIO_MAX_BUFFERS, 2, "Ogg final output");
/* fill up with some samples before playing */
for (i = 0; i < AUDIO_MAX_BUFFERS && !res; i++) {
res = Music_Buffer(i, &data[chunkSize * i], samplesPerSecond, &vorbis);
}
for (;;) {
res = Music_Buffer(next, &data[chunkSize * next], samplesPerSecond, &vorbis);
/* need to specially handle last bit of audio */
if (res) break;
}
cleanup:
Mem_Free(data);
Vorbis_Free(&vorbis);
return 0;
}
also requires a modified function in Audio.c
ReturnCode Music_Buffer(int i, int16_t* data, int maxSamples, struct VorbisState* ctx) {
int samples = 0;
int16_t* cur;
ReturnCode res = 0, res2;
while (samples < maxSamples) {
if ((res = Vorbis_DecodeFrame(ctx))) break;
cur = &data[samples];
samples += Vorbis_OutputFrame(ctx, cur);
}
return res;
}
since i changed a lot in this function, there could be a flaw in my fuzzing logic. but the crash itself doesn't look related
pi@raspberrypi:~/ClassiCube/src $ ./ClassiCube SIGABRT.PC.76afa45c.STACK.badbad0c3cb96303.CODE.-6.ADDR.\(nil\).INSTR.mov_r0\,_r4.2019-06-01.23\:08\:33.25453.fuzz
Accepting input from 'SIGABRT.PC.76afa45c.STACK.badbad0c3cb96303.CODE.-6.ADDR.(nil).INSTR.mov_r0,_r4.2019-06-01.23:08:33.25453.fuzz'
Usage for fuzzing: honggfuzz -P [flags] -- ./ClassiCube
=================================================================
==25612==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6aa01680 at pc 0x002e6ea0 bp 0x7ee200d8 sp 0x7ee200d4
WRITE of size 1 at 0x6aa01680 thread T0
#0 0x2e6e9c in Codebook_DecodeSetup /home/pi/ClassiCube/src/Vorbis.c:321:21
#1 0x2e009c in Vorbis_DecodeSetup /home/pi/ClassiCube/src/Vorbis.c:1197:9
#2 0x2deea4 in Vorbis_DecodeHeaders /home/pi/ClassiCube/src/Vorbis.c:1258:13
#3 0x1dec10 in LLVMFuzzerTestOneInput /home/pi/ClassiCube/src/Program.c:191:16
0x6aa01680 is located 0 bytes to the right of 64-byte region [0x6aa01640,0x6aa01680)
allocated by thread T0 here:
#0 0x10d618 in __interceptor_malloc /home/tcwg-buildslave/workspace/tcwg-llvm-release/tcwg-tk1_32-build/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:146:3
#1 0x330f78 in Mem_Alloc /home/pi/ClassiCube/src/Platform.c:137
#2 0x2e6080 in Codebook_DecodeSetup /home/pi/ClassiCube/src/Vorbis.c:293:27
#3 0x2e009c in Vorbis_DecodeSetup /home/pi/ClassiCube/src/Vorbis.c:1197:9
#4 0x2deea4 in Vorbis_DecodeHeaders /home/pi/ClassiCube/src/Vorbis.c:1258:13
#5 0x1dec10 in LLVMFuzzerTestOneInput /home/pi/ClassiCube/src/Program.c:191:16
#6 0x43c8f8 in HonggfuzzMain (/home/pi/ClassiCube/src/ClassiCube+0x43c8f8)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/pi/ClassiCube/src/Vorbis.c:321:21 in Codebook_DecodeSetup
Shadow bytes around the buggy address:
0x2d540280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x2d540290: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x2d5402a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x2d5402b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x2d5402c0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
=>0x2d5402d0:[fa]fa fa fa 00 00 00 00 00 00 00 04 fa fa fa fa
0x2d5402e0: 00 00 00 00 00 00 00 04 fa fa fa fa fa fa fa fa
0x2d5402f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x2d540300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x2d540310: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x2d540320: 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
==25612==ABORTING