This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/20182] New: Improper code generation causes stack corruption
- From: "jay at systech dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 23 Feb 2005 23:02:05 -0000
- Subject: [Bug c/20182] New: Improper code generation causes stack corruption
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
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__GNUC_MINOR__=2 -D__GNUC_PATCHLEVEL__=1 -D__GXX_ABI_VERSION=102 -D__ELF__ -
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-
elf/3.2.1/include"
ignoring duplicate directory "/home/tools/gnu-3.2.1/arm-elf/include"
#include "..." search starts here:
#include <...> search starts here:
/home/tools/gnu-tools/lib/gcc-lib/arm-elf/3.2.1/include
/home/tools/gnu-tools/arm-elf/include
/home/tools/gnu-3.2.1/include
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'
/home/tools/gnu-tools/bin/../lib/gcc-lib/arm-elf/3.2.1/../../../../arm-
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;
} HPI_INFO;
# 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
ChannelID,
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 &
0x00000001)?0:hpi->ChannelID,
sizeof(V42Parms)/sizeof(uint16), (uint16 *)&V42Parms) != 0)
{
return 0;
}
return 1;
}
Portion of HPIDrv.s file showing invalid code generation in HPIDrv_SendMessage
() function:
.Lfe2:
.size testit,.Lfe2-testit
.section .text.HPIDrv_SendMessage,"ax",%progbits
.align 2
.global HPIDrv_SendMessage
.type HPIDrv_SendMessage,function
HPIDrv_SendMessage:
.LFB3:
.LSM25:
@ args = 4, pretend = 0, frame = 4
@ frame_needed = 1, uses_anonymous_args = 0
mov ip, sp
.LCFI8:
stmfd sp!, {fp, ip, lr, pc}
.LCFI9:
mov r3, r3, asl #16
sub fp, ip, #4
.LCFI10:
mov r3, r3, asr #16
sub lr, fp, #12
strh r3, [fp, #-14] @ movhi <-- This instruction is redundant
.LSM26:
mov r1, r1, asl #16
.LSM27:
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).
.LSM28:
mov r2, r2, asl #16
.LSM29:
sub sp, sp, #12 <-- Stack frame allocated.
.LCFI11:
.LSM30:
add ip, fp, #4
.LSM31:
.LSM32:
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}
.LFE3:
--
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
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20182