This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/15634] New: Structure pointer arithmetic produces incorrect result
- From: "mike dot meyer at ncr dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 24 May 2004 17:55:13 -0000
- Subject: [Bug c/15634] New: Structure pointer arithmetic produces incorrect result
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
Structure pointer arithmetic produces incorrect results. This appears to only
affect pointers to structures which have sizes that are not a power of 2. This
has been seen in GCC versions 3.2.3 and 3.3.2.
The following code illustrates the issue:
typedef struct{
long field1;
long field2;
long filed3;
} test_ptr_t;
char array[4*1024];
int
main(void)
{
test_ptr_t *ptr1;
test_ptr_t *ptr2;
/* Less than 1 structure can fit in this space.
Size is not a multiple of structure size. */
ptr1 = (test_ptr_t *)&array[4];
ptr2 = (test_ptr_t *)&array[sizeof(*ptr1)+2];
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr1, ptr2, ptr1 - ptr2, sizeof(*ptr1));
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr2, ptr1, ptr2 - ptr1, sizeof(*ptr1));
/* 1 structure can fit in this space. Size is not
a multiple of structure size. */
ptr1 = (test_ptr_t *)&array[0];
ptr2 = (test_ptr_t *)&array[sizeof(*ptr1) + 1];
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr1, ptr2, ptr1 - ptr2, sizeof(*ptr1));
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr2, ptr1, ptr2 - ptr1, sizeof(*ptr1));
/* 1 structure can fit in this space. Size is a
multiple of structure size. */
ptr1 = (test_ptr_t *)&array[0];
ptr2 = (test_ptr_t *)&array[sizeof(*ptr1)];
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr1, ptr2, ptr1 - ptr2, sizeof(*ptr1));
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr2, ptr1, ptr2 - ptr1, sizeof(*ptr1));
}
Output from gcc:
gcc -v -save-temps -o ptrtest ptrtest.c
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --
infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-
checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-24)
/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/cpp0 -lang-c -v -D__GNUC__=3 -
D__GNUC_MINOR__=2 -D__GNUC_PATCHLEVEL__=3 -D__GXX_ABI_VERSION=102 -D__ELF__ -
Dunix -D__gnu_linux__ -Dlinux -D__ELF__ -D__unix__ -D__gnu_linux__ -D__linux__ -
D__unix -D__linux -Asystem=posix -D__NO_INLINE__ -D__STDC_HOSTED__=1 -
Acpu=i386 -Amachine=i386 -Di386 -D__i386 -D__i386__ -D__tune_i386__ ptrtest.c
ptrtest.i
GNU CPP version 3.2.3 20030502 (Red Hat Linux 3.2.3-24) (cpplib) (i386
Linux/ELF)
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory "/usr/i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/include
/usr/include
End of search list.
/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/cc1 -fpreprocessed ptrtest.i -quiet -
dumpbase ptrtest.c -version -o ptrtest.s
GNU CPP version 3.2.3 20030502 (Red Hat Linux 3.2.3-24) (cpplib) (i386
Linux/ELF)
GNU C version 3.2.3 20030502 (Red Hat Linux 3.2.3-24) (i386-redhat-linux)
compiled by GNU C version 3.2.3 20030502 (Red Hat Linux 3.2.3-24).
as -V -Qy -o ptrtest.o ptrtest.s
GNU assembler version 2.14.90.0.4 (i386-redhat-linux) using BFD version
2.14.90.0.4 20030523
/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/collect2 --eh-frame-hdr -m elf_i386 -
dynamic-linker /lib/ld-linux.so.2 -o ptrtest /usr/lib/gcc-lib/i386-redhat-
linux/3.2.3/../../../crt1.o /usr/lib/gcc-lib/i386-redhat-
linux/3.2.3/../../../crti.o /usr/lib/gcc-lib/i386-redhat-
linux/3.2.3/crtbegin.o -L/usr/lib/gcc-lib/i386-redhat-linux/3.2.3 -
L/usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../.. ptrtest.o -lgcc -lgcc_eh -
lc -lgcc -lgcc_eh /usr/lib/gcc-lib/i386-redhat-
linux/3.2.3/crtend.o /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/../../../crtn.o
$ ./ptrtest
0x80497a4 - 0x80497ae = -1 (struct size = 12)
0x80497ae - 0x80497a4 = 1431655766 (struct size = 12)
0x80497a0 - 0x80497ad = 1431655764 (struct size = 12)
0x80497ad - 0x80497a0 = 1 (struct size = 12)
0x80497a0 - 0x80497ac = -1 (struct size = 12)
0x80497ac - 0x80497a0 = 1 (struct size = 12)
$
$ cat ptrtest.i
# 1 "ptrtest.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "ptrtest.c"
typedef struct{
long field1;
long field2;
long filed3;
} test_ptr_t;
char array[4*1024];
int
main(void)
{
test_ptr_t *ptr1;
test_ptr_t *ptr2;
ptr1 = (test_ptr_t *)&array[4];
ptr2 = (test_ptr_t *)&array[sizeof(*ptr1)+2];
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr1, ptr2, ptr1 - ptr2, sizeof(*ptr1));
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr2, ptr1, ptr2 - ptr1, sizeof(*ptr1));
ptr1 = (test_ptr_t *)&array[0];
ptr2 = (test_ptr_t *)&array[sizeof(*ptr1) + 1];
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr1, ptr2, ptr1 - ptr2, sizeof(*ptr1));
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr2, ptr1, ptr2 - ptr1, sizeof(*ptr1));
ptr1 = (test_ptr_t *)&array[0];
ptr2 = (test_ptr_t *)&array[sizeof(*ptr1)];
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr1, ptr2, ptr1 - ptr2, sizeof(*ptr1));
printf("0x%x - 0x%x = %d (struct size = %d)\n",
ptr2, ptr1, ptr2 - ptr1, sizeof(*ptr1));
}
$
$ cat ptrtest.s
.file "ptrtest.c"
.section .rodata
.align 32
.LC0:
.string "0x%x - 0x%x = %d (struct size = %d)\n"
.text
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $array+4, -4(%ebp)
movl $array+14, -8(%ebp)
subl $12, %esp
pushl $12
movl -8(%ebp), %edx
movl -4(%ebp), %eax
subl %edx, %eax
movl %eax, %ecx
sarl $2, %ecx
movl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
movl %eax, %edx
sall $8, %edx
addl %edx, %eax
movl %eax, %edx
sall $16, %edx
addl %edx, %eax
sall $1, %eax
addl %ecx, %eax
pushl %eax
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC0
call printf
addl $32, %esp
subl $12, %esp
pushl $12
movl -4(%ebp), %edx
movl -8(%ebp), %eax
subl %edx, %eax
movl %eax, %ecx
sarl $2, %ecx
movl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
movl %eax, %edx
sall $8, %edx
addl %edx, %eax
movl %eax, %edx
sall $16, %edx
addl %edx, %eax
sall $1, %eax
addl %ecx, %eax
pushl %eax
pushl -4(%ebp)
pushl -8(%ebp)
pushl $.LC0
call printf
addl $32, %esp
movl $array, -4(%ebp)
movl $array+13, -8(%ebp)
subl $12, %esp
pushl $12
movl -8(%ebp), %edx
movl -4(%ebp), %eax
subl %edx, %eax
movl %eax, %ecx
sarl $2, %ecx
movl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
movl %eax, %edx
sall $8, %edx
addl %edx, %eax
movl %eax, %edx
sall $16, %edx
addl %edx, %eax
sall $1, %eax
addl %ecx, %eax
pushl %eax
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC0
call printf
addl $32, %esp
subl $12, %esp
pushl $12
movl -4(%ebp), %edx
movl -8(%ebp), %eax
subl %edx, %eax
movl %eax, %ecx
sarl $2, %ecx
movl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
movl %eax, %edx
sall $8, %edx
addl %edx, %eax
movl %eax, %edx
sall $16, %edx
addl %edx, %eax
sall $1, %eax
addl %ecx, %eax
pushl %eax
pushl -4(%ebp)
pushl -8(%ebp)
pushl $.LC0
call printf
addl $32, %esp
movl $array, -4(%ebp)
movl $array+12, -8(%ebp)
subl $12, %esp
pushl $12
movl -8(%ebp), %edx
movl -4(%ebp), %eax
subl %edx, %eax
movl %eax, %ecx
sarl $2, %ecx
movl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
movl %eax, %edx
sall $8, %edx
addl %edx, %eax
movl %eax, %edx
sall $16, %edx
addl %edx, %eax
sall $1, %eax
addl %ecx, %eax
pushl %eax
pushl -8(%ebp)
pushl -4(%ebp)
pushl $.LC0
call printf
addl $32, %esp
subl $12, %esp
pushl $12
movl -4(%ebp), %edx
movl -8(%ebp), %eax
subl %edx, %eax
movl %eax, %ecx
sarl $2, %ecx
movl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
sall $2, %eax
addl %ecx, %eax
movl %eax, %edx
sall $8, %edx
addl %edx, %eax
movl %eax, %edx
sall $16, %edx
addl %edx, %eax
sall $1, %eax
addl %ecx, %eax
pushl %eax
pushl -4(%ebp)
pushl -8(%ebp)
pushl $.LC0
call printf
addl $32, %esp
leave
ret
.Lfe1:
.size main,.Lfe1-main
.comm array,4096,32
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.2.3 20030502 (Red Hat Linux 3.2.3-24)"
$
The results from this same code compiled using the Microsoft C compiler
(VS .net 2003; version 7.1.3088).
0x4284e4 - 0x4284ec = 0 (struct size = 12)
0x4284ec - 0x4284e4 = 0 (struct size = 12)
0x4284e0 - 0x4284ee = -1 (struct size = 12)
0x4284ee - 0x4284e0 = 1 (struct size = 12)
0x4284e0 - 0x4284ec = -1 (struct size = 12)
0x4284ec - 0x4284e0 = 1 (struct size = 12)
The results from a Metaware compiler compiling the same code:
$ cc -V
(cc:) NCR High Performance C Compiler R3.0 (SCDE 3.03.00)
(cc:) No files specified.
$ cc -o ptrtest ptrtest.c
NCR High Performance C Compiler R3.0c
(c) Copyright 1994-98, NCR Corporation
(c) Copyright 1987-98, MetaWare Incorporated
w "ptrtest.c",L11/C1(#72): main: Function has no return statement.
No errors 1 warning
$ ./ptrtest
0x8049774 - 0x804977e = 0 (struct size = 12)
0x804977e - 0x8049774 = 0 (struct size = 12)
0x8049770 - 0x804977d = -1 (struct size = 12)
0x804977d - 0x8049770 = 1 (struct size = 12)
0x8049770 - 0x804977c = -1 (struct size = 12)
0x804977c - 0x8049770 = 1 (struct size = 12)
$
--
Summary: Structure pointer arithmetic produces incorrect result
Product: gcc
Version: 3.2.3
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: mike dot meyer at ncr dot com
CC: gcc-bugs at gcc dot gnu dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15634