[Pkg-bluetooth-maintainers] Bug#856487: libsbc1: compiling with gcc > 4.9 causes stack corruption

Paul Brook paul at nowt.org
Mon Apr 17 16:02:32 UTC 2017


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"
 	);
 }
 
-------------- next part --------------
/* 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;
}


More information about the Pkg-bluetooth-maintainers mailing list