[Bug c/20182] New: Improper code generation causes stack corruption

jay at systech dot com gcc-bugzilla@gcc.gnu.org
Thu Feb 24 12:28:00 GMT 2005

The generated code copies an argument to a local (new) stack frame before 
allocating that stack frame (adjusting the stack pointer), allowing an 
interrupt to corrupt that value.  The argument is copied to memory, so that the 
argument's address can be passed to another function.  As long as an interrupt 
doesn't occur within the 2 instruction window between copying the argument and 
adjusting the stack pointer, everything works fine.

Compiler command line:

arm-elf-gcc -v -save-temps -c -mcpu=arm7tdmi -mbig-endian -Wall -Wpointer-
arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -
ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-
priority -D__ECOS -Wp,-MD,HPIDrv.tmp -o HPIDrv.o HPIDrv.c > HPIDrv.out 2>&1

Compiler output:

Reading specs from /home/tools/gnu-tools/bin/../lib/gcc-lib/arm-elf/3.2.1/specs
Configured with: ../../gcc-3.2.1/configure --prefix=/home/tools/gnu-3.2.1 --
target=arm-elf -v --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-
newlib --with-gxx-include-dir=/home/tools/gnu-3.2.1/arm-elf/include
Thread model: single
gcc version 3.2.1
 /home/tools/gnu-tools/bin/../lib/gcc-lib/arm-elf/3.2.1/cpp0 -lang-c -v -
iprefix /home/tools/gnu-tools/bin/../lib/gcc-lib/arm-elf/3.2.1/ -D__GNUC__=3 -
D__ELF__ -D__OPTIMIZE__ -D__STDC_HOSTED__=1 -Acpu=arm -Amachine=arm -
D__ARM_ARCH_4T__ -D__APCS_32__ -D__ARMEB__ -D__ELF__ -D__USES_INITFINI__ -
D__arm__ -D__ECOS -MD HPIDrv.tmp HPIDrv.c -Wall -Wpointer-arith -Wstrict-
prototypes -Winline -Wundef -Woverloaded-virtual HPIDrv.i
GNU CPP version 3.2.1 (cpplib) (ARM/ELF)
ignoring nonexistent directory "/home/tools/gnu-tools/arm-elf/sys-include"
ignoring nonexistent directory "/home/tools/gnu-3.2.1/arm-elf/sys-include"
ignoring duplicate directory "/home/tools/gnu-3.2.1/lib/gcc-lib/arm-
ignoring duplicate directory "/home/tools/gnu-3.2.1/arm-elf/include"
#include "..." search starts here:
#include <...> search starts here:
End of search list.
 /home/tools/gnu-tools/bin/../lib/gcc-lib/arm-elf/3.2.1/cc1 -fpreprocessed 
HPIDrv.i -quiet -dumpbase HPIDrv.c -mcpu=arm7tdmi -mbig-endian -g -O2 -Wall -
Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -
version -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-
gc -finit-priority -o HPIDrv.s
GNU CPP version 3.2.1 (cpplib) (ARM/ELF)
GNU C version 3.2.1 (arm-elf)
	compiled by GNU C version 3.2.2 20030222 (Red Hat Linux 3.2.2-5).
HPIDrv.c:20: warning: conflicting types for built-in function `memset'
elf/bin/as -EB -marm7tdmi -o HPIDrv.o HPIDrv.s

HPIDrv.i file:

# 1 "HPIDrv.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "HPIDrv.c"

typedef unsigned char uint8;
typedef unsigned short uint16;
typedef void tHPIDrv;
typedef struct hpi_info
        tHPIDrv *HPIDrv;
        unsigned int CfgMask;
        uint16 ChannelID;
# 19 "HPIDrv.c"
extern int diag_printf(const char *fmt, ...);
extern void memset(void *, int, unsigned int);

int HPIDrv_SendMessages(tHPIDrv *const pDrv, const uint16 Type, const uint16 
        const uint8 NumBlocks, const uint16 *const pSize, const uint16 *const 
*const ppData)

        diag_printf("pDrv=0x%08X, Type=0x%04X, ChannelID=%d, NumBlocks=%d, 
Size=%d, pData=0x%08X\n",
                        pDrv, Type, ChannelID, NumBlocks, *pSize, *ppData);
        return 0;

inline int HPIDrv_SendMessage(tHPIDrv *const pDrv, const uint16 Type, const 
uint16 ChannelID,
        const uint16 Size, const uint16 *const pData)
        return HPIDrv_SendMessages(pDrv, Type, ChannelID, 1, &Size, &pData);

int testit(HPI_INFO *hpi)
        typedef struct parm
                uint16 a;
                uint16 b;
                uint16 c[8];
        } parm_t;
        parm_t V42Parms;

        memset(&V42Parms, 0, sizeof(V42Parms));

        if (HPIDrv_SendMessage(hpi->HPIDrv, 0x0800|0x0002, (hpi->CfgMask & 
                sizeof(V42Parms)/sizeof(uint16), (uint16 *)&V42Parms) != 0)
                return 0;

        return 1;

Portion of HPIDrv.s file showing invalid code generation in HPIDrv_SendMessage
() function:

	.size	testit,.Lfe2-testit
	.section	.text.HPIDrv_SendMessage,"ax",%progbits
	.align	2
	.global	HPIDrv_SendMessage
	.type	HPIDrv_SendMessage,function
	@ args = 4, pretend = 0, frame = 4
	@ frame_needed = 1, uses_anonymous_args = 0
	mov	ip, sp
	stmfd	sp!, {fp, ip, lr, pc}
	mov	r3, r3, asl #16
	sub	fp, ip, #4
	mov	r3, r3, asr #16
	sub	lr, fp, #12
	strh	r3, [fp, #-14]	@ movhi <-- This instruction is redundant
	mov	r1, r1, asl #16
	strh	r3, [lr, #-2]!	@ movhi <-- The 'Size' argument (register r3)
                                        is copied to the local stack frame
                                        here, BEFORE the stack frame is
                                        allocated (below).
	mov	r2, r2, asl #16
	sub	sp, sp, #12  <-- Stack frame allocated.
	add	ip, fp, #4
	mov	r1, r1, lsr #16
	mov	r2, r2, lsr #16
	mov	r3, #1
	str	lr, [sp, #0]
	str	ip, [sp, #4]
	bl	HPIDrv_SendMessages
	ldmea	fp, {fp, sp, pc}

           Summary: Improper code generation causes stack corruption
           Product: gcc
           Version: 3.2.1
            Status: UNCONFIRMED
          Severity: critical
          Priority: P2
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: jay at systech dot com
                CC: gcc-bugs at gcc dot gnu dot org
  GCC host triplet: i386-redhat-linux
GCC target triplet: arm-elf


More information about the Gcc-bugs mailing list