Package: libsbc1 Version: 1.3-1+b2 Followup-For: Bug #856487 Not a stack corruption.
This is miscompilation of sbc_analyze_4b_8s_armv6. gcc appears to look into the asm function and decides that it does not clobber r3 (which the normal ARM ABI says is call clobbered). The last out += out_stride ends up incrementing the pointer by an arbitrary amount. The attached patch works around the bug. I'm not entirely sure whether this is a gcc bug or not, but at best it's surprising behavior from gcc. I've attached a reduced testcase for the toolchain folks to argue over (compile with gcc -O2, tested with gcc 6.3.0-2 from sid). Paul diff -ur clean/sbc/sbc_primitives_armv6.c sbc-1.3/sbc/sbc_primitives_armv6.c --- clean/sbc/sbc_primitives_armv6.c 2013-04-30 17:19:23.000000000 +0100 +++ sbc-1.3/sbc/sbc_primitives_armv6.c 2017-04-17 16:43:49.918809345 +0100 @@ -102,6 +102,7 @@ "pop {r8-r11}\n" "stmia r1, {r4, r5, r6, r7}\n" "pop {r1, r4-r7, pc}\n" + :::"r0", "r2", "r3", "ip" ); } @@ -258,6 +259,7 @@ "pop {r8-r11}\n" "stmia r1!, {r4, r5, r6, r7}\n" "pop {r1, r4-r7, pc}\n" + :::"r0", "r2", "r3", "ip" ); }
/* Compile with -O2 on arm */ #include <stdint.h> #include <stdlib.h> static void __attribute__((naked)) frob(int16_t *a, int32_t *b, const int16_t *c) { /* The explicit clobber of r3 should not be necessary because that it is implied by the function call? gcc6 seems to look into the naked function and assume r3 is preserved accross the call. */ __asm__ volatile ("mov r3, #0x80000000\n\t" "str r3, [r1]\n\t" "bx lr" #if 0 :::"r3" #endif ); } int16_t c[4]; struct sbc_encoder_state; void test(struct sbc_encoder_state *state, int16_t *x, int32_t *out, int out_stride) { frob(x + 24, out, c); out += out_stride; frob(x + 16, out, c); out += out_stride; frob(x + 8, out, c); out += out_stride; frob(x + 0, out, c); } int main() { static int16_t a[32]; static int32_t b[32]; test(NULL, a, b, 8); return 0; }