sahaRatul / sela

SimplE Lossless Audio
https://seladoc.netlify.com/
MIT License
209 stars 23 forks source link

stack-buffer-overflow in varible keys_inst #12

Closed EnchantedJohn closed 6 years ago

EnchantedJohn commented 6 years ago

Hello,I use my company tools to fuzz test on sela.I first found the crash.Then I want to show error information to your guys.

EnchantedJohn commented 6 years ago
SimplE Lossless Audio Encoder
Copyright (c) 2015-2016. Ratul Saha
Released under MIT license

Input : /home/lx/DIVE/Trunk/bin/hfl/output/1DB330B333783C25CD43B04F3D4C575680C3C2/hfl-crash-1-{rva_0x1BEF}{code_0x8}{selaenc}
Output : output.sela
=================================================================
==108908==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd1ff49260 at pc 0x40c6af bp 0x7ffd1ff27380 sp 0x7ffd1ff27378
WRITE of size 1 at 0x7ffd1ff49260 thread T0
    #0 0x40c6ae in init_apev2_keys (/home/lx/5_29/SELA/AFL/sela-latest/selaenc+0x40c6ae)
    #1 0x401716 in main (/home/lx/5_29/SELA/AFL/sela-latest/selaenc+0x401716)
    #2 0x7f39b5b8ef44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
    #3 0x402cb4 (/home/lx/5_29/SELA/AFL/sela-latest/selaenc+0x402cb4)

Address 0x7ffd1ff49260 is located in stack of thread T0 at offset 138848 in frame
    #0 0x40124f in main (/home/lx/5_29/SELA/AFL/sela-latest/selaenc+0x40124f)

  This frame has 36 object(s):
    [32, 33) 'opt_lpc_order'
    [96, 97) 'rice_param_ref'
    [160, 161) 'rice_param_residue'
    [224, 226) 'channels'
    [288, 290) 'bps'
    [352, 354) 'req_int_ref'
    [416, 418) 'req_int_residues'
    [480, 482) 'samples_per_channel'
    [544, 548) 'i'
    [608, 612) 'sample_rate'
    [672, 676) 'metadata_sync'
    [736, 740) 'metadata_size'
    [800, 804) 'frame_sync'
    [864, 868) 'req_bits_ref'
    [928, 932) 'req_bits_residues'
    [992, 996) 'samples'
    [1056, 1060) 'estimated_frames'
    [1120, 1140) 'state'
    [1184, 1208) 'ape_list'
    [1248, 1344) 'tags'
    [1376, 1776) 'qtz_ref_coeffs'
    [1824, 2224) 'unsigned_ref'
    [2272, 2672) 'encoded_ref'
    [2720, 3520) 'ref'
    [3552, 4360) 'lpc'
    [4416, 5224) 'autocorr'
    [5280, 9376) 'short_samples'
    [9408, 17600) 'int_samples'
    [17632, 25824) 'residues'
    [25856, 34048) 'u_residues'
    [34080, 42272) 'encoded_residues'
    [42304, 58688) 'qtz_samples'
    [58720, 138720) 'lpc_mat'
    [138752, 138756) 'magic_number'
    [138816, 138848) 'keys_inst' <== Memory access at offset 138848 overflows this variable
    [138880, 138912) 'header'
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 ??:0 init_apev2_keys
Shadow bytes around the buggy address:
  0x100023fe11f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023fe1200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023fe1210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023fe1220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023fe1230: 00 00 00 00 00 00 00 00 00 00 00 00 f2 f2 f2 f2
=>0x100023fe1240: 04 f4 f4 f4 f2 f2 f2 f2 00 00 00 00[f2]f2 f2 f2
  0x100023fe1250: 00 00 00 00 f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00
  0x100023fe1260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023fe1270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023fe1280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100023fe1290: 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
  Contiguous container OOB:fc
  ASan internal:           fe
==108908==ABORTING
EnchantedJohn commented 6 years ago

Then it is GDB information:

SimplE Lossless Audio Encoder
Copyright (c) 2015-2016. Ratul Saha
Released under MIT license

Input : /home/lx/DIVE/Trunk/bin/hfl/output/1DB330B333783C25CD43B04F3D4C575680C3C2/hfl-crash-1-{rva_0x1BEF}{code_0x8}{selaenc}
Output : output.sela
WAV file detected

Stream Information
------------------
Sampling Rate : 44100 Hz
Bits per sample : 16
Channels : 1 (Monoaural)

Metadata
--------
No metadata found.
[                         ]

Statistics
----------
15 frames written (0min 0sec)
Compression Ratio : 35.97%

Program received signal SIGFPE, Arithmetic exception.
0x0000000000401bef in main ()
(gdb) bt
#0  0x0000000000401bef in main ()
EnchantedJohn commented 6 years ago
(gdb) i r
rax            0x2b028  176168
rbx            0x0  0
rcx            0x0  0
rdx            0x0  0
rsi            0x1  1
rdi            0x7ffff7ace1c0   140737348690368
rbp            0x5605   0x5605
rsp            0x7ffffffdc940   0x7ffffffdc940
r8             0x7ffff7fc7740   140737353905984
r9             0x7fffffff   2147483647
r10            0x1  1
r11            0x246    582
r12            0xef2c   61228
r13            0x60a490 6333584
r14            0x60a250 6333008
r15            0x60a010 6332432
rip            0x401bef 0x401bef <main+4063>
eflags         0x10246  [ PF ZF IF RF ]
cs             0x33 51
ss             0x2b 43
ds             0x0  0
es             0x0  0
fs             0x0  0
gs             0x0  0
(gdb) x/10i $pc
=> 0x401bef <main+4063>:    div    %rcx
   0x401bf2 <main+4066>:    mov    $0x406905,%edx
   0x401bf7 <main+4071>:    mov    %rax,%rcx
   0x401bfa <main+4074>:    xor    %eax,%eax
   0x401bfc <main+4076>:    callq  0x400be0 <__fprintf_chk@plt>
   0x401c01 <main+4081>:    mov    %r13,%rdi
   0x401c04 <main+4084>:    callq  0x400a80 <free@plt>
   0x401c09 <main+4089>:    lea    0xf0(%rsp),%rdi
   0x401c11 <main+4097>:    callq  0x4058e0 <destroy_wav_tags>
   0x401c16 <main+4102>:    lea    0xd0(%rsp),%rsi
EnchantedJohn commented 6 years ago

I think stack-buffer-overflow is due to varible keys_inst. and finally div zero. then I want to show the encode.c:

85 
 86         //Metadata data structures
 87         wav_tags tags;
 88         apev2_state state;
 89         apev2_keys keys_inst;    //I think it is the key problem 
 90         apev2_hdr_ftr header;
 91         apev2_item_list ape_list;
 92 
 93         //Init wav tags
 94         init_wav_tags(&tags);
 95 
 96         //Init apev2 state
 97         init_apev2(&state);
 98 
 99         //Init apev2 keys
100         init_apev2_keys(&state,&keys_inst);
101 
102         //Init apev2 header
103         init_apev2_header(&state,&header);
104 
105         //Init apev2 item link list
106         init_apev2_item_list(&state,&ape_list);
107 
108         //Check the wav file
109         int32_t is_wav = check_wav_file(infile,&sample_rate,&channels,&bps,&samples,&tags);
110         uint32_t estimated_frames = ceil((float)samples/(channels * BLOCK_SIZE * sizeof(int16_t)));
sahaRatul commented 6 years ago

Please provide the input file.

EnchantedJohn commented 6 years ago

okay,you can use empty file.then sela will crash.

EnchantedJohn commented 6 years ago

It is due to ArrayIndexOutOfBoundsException in stack-buffer-overflow core/apev2.c:99 init_apev2_keys apev2_keys define :

typedef struct apev2_keys
 51 {
 52         char title[5];
 53         char artist[6];
 54         char album[6];
 55         char year[4];
 56         char genre[5];
 57         char comment[6];
 58 }apev2_keys;
92         //Comment key
 93         inst->comment[0] = 'C';
 94         inst->comment[1] = 'o';
 95         inst->comment[2] = 'm';
 96         inst->comment[3] = 'm';
 97         inst->comment[4] = 'e';
 98         inst->comment[5] = 'n';
 99         inst->comment[6] = 't';
100 
101         state->ape_last_state = APE_KEYS_INIT_SUCCESS;
102         return APE_KEYS_INIT_SUCCESS;
sahaRatul commented 6 years ago

Increased size of comment array from 6 to 7. Should be fixed now.

sahaRatul commented 6 years ago

Please confirm if you are still getting error on your tests.

EnchantedJohn commented 6 years ago

yes, I also change this Bug.But I find another. I want to show you my process

EnchantedJohn commented 6 years ago

In calc_residue() function:

...
for(k = ord + 1; k < N; k++)
    {
        y = corr;

        y += (int64_t)(coff[0] * samples[k - 0]);
        y += (int64_t)(coff[1] * samples[k - 1]);
        y += (int64_t)(coff[2] * samples[k - 2]);
        y += (int64_t)(coff[3] * samples[k - 3]);
        y += (int64_t)(coff[4] * samples[k - 4]);
        y += (int64_t)(coff[5] * samples[k - 5]);
        y += (int64_t)(coff[6] * samples[k - 6]);
        y += (int64_t)(coff[7] * samples[k - 7]);
        y += (int64_t)(coff[8] * samples[k - 8]);
        y += (int64_t)(coff[9] * samples[k - 9]);
        y += (int64_t)(coff[10] * samples[k - 10]);
        y += (int64_t)(coff[11] * samples[k - 11]);
        y += (int64_t)(coff[12] * samples[k - 12]);
        y += (int64_t)(coff[13] * samples[k - 13]);
        y += (int64_t)(coff[14] * samples[k - 14]);
        y += (int64_t)(coff[15] * samples[k - 15]);
        y += (int64_t)(coff[16] * samples[k - 16]);
        y += (int64_t)(coff[17] * samples[k - 17]);
        y += (int64_t)(coff[18] * samples[k - 18]);
        y += (int64_t)(coff[19] * samples[k - 19]);
        y += (int64_t)(coff[20] * samples[k - 20]);
        y += (int64_t)(coff[21] * samples[k - 21]);
        y += (int64_t)(coff[22] * samples[k - 22]);
        y += (int64_t)(coff[23] * samples[k - 23]);
        y += (int64_t)(coff[24] * samples[k - 24]);
        y += (int64_t)(coff[25] * samples[k - 25]);
        y += (int64_t)(coff[26] * samples[k - 26]);
        y += (int64_t)(coff[27] * samples[k - 27]);
        y += (int64_t)(coff[28] * samples[k - 28]);
        y += (int64_t)(coff[29] * samples[k - 29]);
        y += (int64_t)(coff[30] * samples[k - 30]);
        y += (int64_t)(coff[31] * samples[k - 31]);
        y += (int64_t)(coff[32] * samples[k - 32]);
        y += (int64_t)(coff[33] * samples[k - 33]);
        y += (int64_t)(coff[34] * samples[k - 34]);
        y += (int64_t)(coff[35] * samples[k - 35]);
        y += (int64_t)(coff[36] * samples[k - 36]);
        y += (int64_t)(coff[37] * samples[k - 37]);
        y += (int64_t)(coff[38] * samples[k - 38]);
        y += (int64_t)(coff[39] * samples[k - 39]);
        y += (int64_t)(coff[40] * samples[k - 40]);
        y += (int64_t)(coff[41] * samples[k - 41]);
        y += (int64_t)(coff[42] * samples[k - 42]);
        y += (int64_t)(coff[43] * samples[k - 43]);
        y += (int64_t)(coff[44] * samples[k - 44]);
        y += (int64_t)(coff[45] * samples[k - 45]);
        y += (int64_t)(coff[46] * samples[k - 46]);
        y += (int64_t)(coff[47] * samples[k - 47]);
        y += (int64_t)(coff[48] * samples[k - 48]);
        y += (int64_t)(coff[49] * samples[k - 49]);
        y += (int64_t)(coff[50] * samples[k - 50]);
        y += (int64_t)(coff[51] * samples[k - 51]);
        y += (int64_t)(coff[52] * samples[k - 52]);
        y += (int64_t)(coff[53] * samples[k - 53]);
        y += (int64_t)(coff[54] * samples[k - 54]);
        y += (int64_t)(coff[55] * samples[k - 55]);
        y += (int64_t)(coff[56] * samples[k - 56]);
        y += (int64_t)(coff[57] * samples[k - 57]);
        y += (int64_t)(coff[58] * samples[k - 58]);
        y += (int64_t)(coff[59] * samples[k - 59]);
        y += (int64_t)(coff[60] * samples[k - 60]);
        y += (int64_t)(coff[61] * samples[k - 61]);
        y += (int64_t)(coff[62] * samples[k - 62]);
        y += (int64_t)(coff[63] * samples[k - 63]);
        y += (int64_t)(coff[64] * samples[k - 64]);
        y += (int64_t)(coff[65] * samples[k - 65]);
        y += (int64_t)(coff[66] * samples[k - 66]);
        y += (int64_t)(coff[67] * samples[k - 67]);
        y += (int64_t)(coff[68] * samples[k - 68]);
        y += (int64_t)(coff[69] * samples[k - 69]);
        y += (int64_t)(coff[70] * samples[k - 70]);
        y += (int64_t)(coff[71] * samples[k - 71]);
        y += (int64_t)(coff[72] * samples[k - 72]);
        y += (int64_t)(coff[73] * samples[k - 73]);
        y += (int64_t)(coff[74] * samples[k - 74]);
        y += (int64_t)(coff[75] * samples[k - 75]);
        y += (int64_t)(coff[76] * samples[k - 76]);
        y += (int64_t)(coff[77] * samples[k - 77]);
        y += (int64_t)(coff[78] * samples[k - 78]);
        y += (int64_t)(coff[79] * samples[k - 79]);
        y += (int64_t)(coff[80] * samples[k - 80]);
        y += (int64_t)(coff[81] * samples[k - 81]);
        y += (int64_t)(coff[82] * samples[k - 82]);
        y += (int64_t)(coff[83] * samples[k - 83]);
        y += (int64_t)(coff[84] * samples[k - 84]);
        y += (int64_t)(coff[85] * samples[k - 85]);
        y += (int64_t)(coff[86] * samples[k - 86]);
        y += (int64_t)(coff[87] * samples[k - 87]);
        y += (int64_t)(coff[88] * samples[k - 88]);
        y += (int64_t)(coff[89] * samples[k - 89]);
        y += (int64_t)(coff[90] * samples[k - 90]);
        y += (int64_t)(coff[91] * samples[k - 91]);
        y += (int64_t)(coff[92] * samples[k - 92]);
        y += (int64_t)(coff[93] * samples[k - 93]);
        y += (int64_t)(coff[94] * samples[k - 94]);
        y += (int64_t)(coff[95] * samples[k - 95]);
        y += (int64_t)(coff[96] * samples[k - 96]);
        y += (int64_t)(coff[97] * samples[k - 97]);
        y += (int64_t)(coff[98] * samples[k - 98]);
        y += (int64_t)(coff[99] * samples[k - 99]);
        y += (int64_t)(coff[100] * samples[k - 100]);

        //for(i = 0; i <= ord; i++)
            //y += (int64_t)(coff[i] * samples[k-i]);
        residues[k] = samples[k] - (int32_t)(y >> Q);
    }

    return;

when my testcase k=91,then crash caused by ArrayIndexOutOfBoundsException.

EnchantedJohn commented 6 years ago

then there is my GDB information:

(gdb) print k
$1 = 91
(gdb)

but when y += (int64_t)(coff[92] * samples[k - 92]); ,crash was created.

sahaRatul commented 6 years ago

@EnchantedJohn

https://github.com/sahaRatul/sela/commit/19b07d28e380cb51d701b331044968b91d347a84

Should fix this issue.

EnchantedJohn commented 6 years ago

Ok,I will close it.Thanks again!

sahaRatul commented 6 years ago

Is it causing buffer overflow exceptions now in your test cases?