DISTRHO / Nekobi

DISTRHO Nekobi
GNU General Public License v2.0
49 stars 12 forks source link

Segmentation fault (gdb, valgrind,...) #13

Closed Harvie closed 2 years ago

Harvie commented 3 years ago

Hello, i've been doing some tests and found issues in the nekobee-src directory. There is segmentation fault reported by gdb and even more fails reported by valgrind. (obviously, because valgrind prevents app from crashing on segv and continues executing through more subsequent segvs reporting them)

Testing code (i put this in main.c to the nekobee-src directory and build using gcc -g -lm *.c -o go):

#include <stdio.h>
#include "nekobee.h"
#include "nekobee_voice.h"
#include "nekobee_synth.h"
#include "nekobee_types.h"

nekobee_synth_t fSynth;

#define SAMPLE_RATE 44000

int main() {

nekobee_init_tables();

    // init synth
    fSynth.sample_rate = SAMPLE_RATE;
    fSynth.deltat = 1.0f / (float)SAMPLE_RATE;
    fSynth.nugget_remains = 0;

    fSynth.note_id = 0;
    fSynth.polyphony = XSYNTH_DEFAULT_POLYPHONY;
    fSynth.voices = XSYNTH_DEFAULT_POLYPHONY;
    fSynth.monophonic = XSYNTH_MONO_MODE_ONCE;
    fSynth.glide = 0;
    fSynth.last_noteon_pitch = 0.0f;
    fSynth.vcf_accent = 0.0f;
    fSynth.vca_accent = 0.0f;

    for (int i=0; i<8; ++i)
        fSynth.held_keys[i] = -1;

    fSynth.voice = nekobee_voice_new();
    fSynth.voicelist_mutex_grab_failed = 0;
    //pthread_mutex_init(&fSynth.voicelist_mutex, nullptr);

    fSynth.channel_pressure = 0;
    fSynth.pitch_wheel_sensitivity = 0;
    fSynth.pitch_wheel = 0;

    for (int i=0; i<128; ++i)
    {
        fSynth.key_pressure[i] = 0;
        fSynth.cc[i] = 0;
    }
    fSynth.cc[7] = 127; // full volume

    fSynth.mod_wheel  = 1.0f;
    fSynth.pitch_bend = 1.0f;
    fSynth.cc_volume  = 1.0f;

    // Default values
    /*
    fParams.waveform = 0.0f;
    fParams.tuning = 0.0f;
    fParams.cutoff = 25.0f;
    fParams.resonance = 25.0f;
    fParams.envMod = 50.0f;
    fParams.decay  = 75.0f;
    fParams.accent = 25.0f;
    fParams.volume = 75.0f;
    fParams.bypass = false;
    */

    // Internal stuff
    fSynth.waveform  = 0.0f;
    fSynth.tuning    = 1.0f;
    fSynth.cutoff    = 5.0f;
    fSynth.resonance = 0.8f;
    fSynth.envmod    = 0.3f;
    fSynth.decay     = 0.0002f;
    fSynth.accent    = 0.3f;
    fSynth.volume    = 0.75f;

    //nekobee_synth_render_voices(&fSynth, NULL, 0, 1); //Update controls
    nekobee_synth_init_controls(&fSynth);
    nekobee_synth_note_on(&fSynth, 60, 60);

    float out;
    while(1) {
      nekobee_synth_render_voices(&fSynth, &out, 1, 0);
    }

  return 0;
}

GDB backtrace:

Program received signal SIGSEGV, Segmentation fault.
0x00005555555562e9 in blosc_place_step_dd (buffer=0x5555555692f4, index=33603, phase=0.0120628178, w=0.0188774858, scale=-1)
    at nekobee_voice_render.c:139
139         buffer[index] += scale * (step_dd_table[i].value + r * step_dd_table[i].delta);
(gdb) bt
#0  0x00005555555562e9 in blosc_place_step_dd (buffer=0x5555555692f4, index=33603, phase=0.0120628178, w=0.0188774858, scale=-1)
    at nekobee_voice_render.c:139
#1  0x000055555555646b in vco (sample_count=1, voice=0x5555555692a0, osc=0x5555555692b8, index=33556, w=0.0188774858)
    at nekobee_voice_render.c:168
#2  0x0000555555556f53 in nekobee_voice_render (synth=0x5555555677e0 <fSynth>, voice=0x5555555692a0, out=0x7fffffffe12c, sample_count=1, 
    do_control_update=0) at nekobee_voice_render.c:372
#3  0x00005555555558fa in nekobee_synth_render_voices (synth=0x5555555677e0 <fSynth>, out=0x7fffffffe12c, sample_count=1, 
    do_control_update=0) at nekobee_synth.c:235
#4  0x00005555555553bc in main () at main.c:85
(gdb) 

Valgrind report:

$ valgrind ./go 
==87383== Memcheck, a memory error detector
==87383== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==87383== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==87383== Command: ./go
==87383== 
==87383== Invalid read of size 4
==87383==    at 0x10A2E9: blosc_place_step_dd (nekobee_voice_render.c:139)
==87383==    by 0x10A548: vco (nekobee_voice_render.c:181)
==87383==    by 0x10AF52: nekobee_voice_render (nekobee_voice_render.c:372)
==87383==    by 0x1098F9: nekobee_synth_render_voices (nekobee_synth.c:235)
==87383==    by 0x1093BB: main (main.c:85)
==87383==  Address 0x4bb1a94 is 0 bytes after a block of size 2,644 alloc'd
==87383==    at 0x483CB65: calloc (vg_replace_malloc.c:760)
==87383==    by 0x109926: nekobee_voice_new (nekobee_voice.c:45)
==87383==    by 0x10926D: main (main.c:32)
==87383== 
==87383== Invalid write of size 4
==87383==    at 0x10A345: blosc_place_step_dd (nekobee_voice_render.c:139)
==87383==    by 0x10A548: vco (nekobee_voice_render.c:181)
==87383==    by 0x10AF52: nekobee_voice_render (nekobee_voice_render.c:372)
==87383==    by 0x1098F9: nekobee_synth_render_voices (nekobee_synth.c:235)
==87383==    by 0x1093BB: main (main.c:85)
==87383==  Address 0x4bb1a94 is 0 bytes after a block of size 2,644 alloc'd
==87383==    at 0x483CB65: calloc (vg_replace_malloc.c:760)
==87383==    by 0x109926: nekobee_voice_new (nekobee_voice.c:45)
==87383==    by 0x10926D: main (main.c:32)
==87383== 
==87383== Invalid read of size 4
==87383==    at 0x10A2E9: blosc_place_step_dd (nekobee_voice_render.c:139)
==87383==    by 0x10A46A: vco (nekobee_voice_render.c:168)
==87383==    by 0x10AF52: nekobee_voice_render (nekobee_voice_render.c:372)
==87383==    by 0x1098F9: nekobee_synth_render_voices (nekobee_synth.c:235)
==87383==    by 0x1093BB: main (main.c:85)
==87383==  Address 0x4bb1a94 is 0 bytes after a block of size 2,644 alloc'd
==87383==    at 0x483CB65: calloc (vg_replace_malloc.c:760)
==87383==    by 0x109926: nekobee_voice_new (nekobee_voice.c:45)
==87383==    by 0x10926D: main (main.c:32)
==87383== 
==87383== Invalid write of size 4
==87383==    at 0x10A345: blosc_place_step_dd (nekobee_voice_render.c:139)
==87383==    by 0x10A46A: vco (nekobee_voice_render.c:168)
==87383==    by 0x10AF52: nekobee_voice_render (nekobee_voice_render.c:372)
==87383==    by 0x1098F9: nekobee_synth_render_voices (nekobee_synth.c:235)
==87383==    by 0x1093BB: main (main.c:85)
==87383==  Address 0x4bb1a94 is 0 bytes after a block of size 2,644 alloc'd
==87383==    at 0x483CB65: calloc (vg_replace_malloc.c:760)
==87383==    by 0x109926: nekobee_voice_new (nekobee_voice.c:45)
==87383==    by 0x10926D: main (main.c:32)
==87383== 
==87383== Invalid read of size 4
==87383==    at 0x10A5DA: vco (nekobee_voice_render.c:193)
==87383==    by 0x10AF52: nekobee_voice_render (nekobee_voice_render.c:372)
==87383==    by 0x1098F9: nekobee_synth_render_voices (nekobee_synth.c:235)
==87383==    by 0x1093BB: main (main.c:85)
==87383==  Address 0x4bb1a94 is 0 bytes after a block of size 2,644 alloc'd
==87383==    at 0x483CB65: calloc (vg_replace_malloc.c:760)
==87383==    by 0x109926: nekobee_voice_new (nekobee_voice.c:45)
==87383==    by 0x10926D: main (main.c:32)
==87383== 
==87383== Invalid write of size 4
==87383==    at 0x10A5F6: vco (nekobee_voice_render.c:193)
==87383==    by 0x10AF52: nekobee_voice_render (nekobee_voice_render.c:372)
==87383==    by 0x1098F9: nekobee_synth_render_voices (nekobee_synth.c:235)
==87383==    by 0x1093BB: main (main.c:85)
==87383==  Address 0x4bb1a94 is 0 bytes after a block of size 2,644 alloc'd
==87383==    at 0x483CB65: calloc (vg_replace_malloc.c:760)
==87383==    by 0x109926: nekobee_voice_new (nekobee_voice.c:45)
==87383==    by 0x10926D: main (main.c:32)
==87383== 
==87383== Invalid read of size 4
==87383==    at 0x10A842: vcf_4pole (nekobee_voice_render.c:248)
==87383==    by 0x10AFB0: nekobee_voice_render (nekobee_voice_render.c:375)
==87383==    by 0x1098F9: nekobee_synth_render_voices (nekobee_synth.c:235)
==87383==    by 0x1093BB: main (main.c:85)
==87383==  Address 0x4bb1a94 is 0 bytes after a block of size 2,644 alloc'd
==87383==    at 0x483CB65: calloc (vg_replace_malloc.c:760)
==87383==    by 0x109926: nekobee_voice_new (nekobee_voice.c:45)
==87383==    by 0x10926D: main (main.c:32)
==87383== 

==87383== 
==87383== Process terminating with default action of signal 2 (SIGINT)
==87383==    at 0x10A133: volume (nekobee_voice_render.c:105)
==87383==    by 0x10AB0D: nekobee_voice_render (nekobee_voice_render.c:302)
==87383==    by 0x1098F9: nekobee_synth_render_voices (nekobee_synth.c:235)
==87383==    by 0x1093BB: main (main.c:85)
==87383== 
==87383== HEAP SUMMARY:
==87383==     in use at exit: 2,644 bytes in 1 blocks
==87383==   total heap usage: 1 allocs, 0 frees, 2,644 bytes allocated
==87383== 
==87383== LEAK SUMMARY:
==87383==    definitely lost: 0 bytes in 0 blocks
==87383==    indirectly lost: 0 bytes in 0 blocks
==87383==      possibly lost: 0 bytes in 0 blocks
==87383==    still reachable: 2,644 bytes in 1 blocks
==87383==         suppressed: 0 bytes in 0 blocks
==87383== Rerun with --leak-check=full to see details of leaked memory
==87383== 
==87383== For lists of detected and suppressed errors, rerun with: -s
==87383== ERROR SUMMARY: 5856932 errors from 7 contexts (suppressed: 0 from 0)
Harvie commented 3 years ago

It is really weird. It seems that when i change the note_on line to nekobee_synth_note_on(&fSynth, 1, 1); (different note) I get different kind of crash. Also it does not crash when i don't call note_on at all. (keeps happily spitting silence/zeroes in that case)

falkTX commented 2 years ago

This seems like a buffer overflow. Too many notes being played at once, for which there are bounds checks missing and it ends up writing past the allocated array.

falkTX commented 2 years ago

Fixed in 20d62751e09c1893ea69e371e94e8cb147775eaa