Bug 58746

Summary: 32-bit integer array indices improperly promoted to 64-bit in c++
Product: [Retired] Red Hat Linux Reporter: Andrew Schultz <ajschult784>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED ERRATA QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.1   
Target Milestone: ---   
Target Release: ---   
Hardware: alphaev6   
OS: Linux   
URL: http://bugzilla.mozilla.org/show_bug.cgi?id=119042#c57
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2002-07-26 21:47:27 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Andrew Schultz 2002-01-23 23:40:57 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux alpha; en-US; rv:0.9.7) Gecko/20011226

Description of problem:
this showed up in Mozilla builds.  at some point a negative 32-bit intermediate
was improperly promoted to a 64 number.  see code below and the given URL.

relevant rpms:
gcc-2.96-87
gcc-c++-2.96-87
gcc-objc-2.96-87
glibc-2.2.4-19.3
kernel-2.4.3-12
kernel-headers-2.4.3-12
libstdc++-2.96-87
libstdc++-devel-2.96-87


Version-Release number of selected component (if applicable):
2.96-87

How reproducible:
Always

Steps to Reproduce:
1.save code to file
2.compile (gcc -o test test.cpp)
3.run
	

Actual Results:
es[1] = 0
&es[1] = 0x11ffff889
expand-1-j = 1
&es[expand-1-j] = 0x21ffff889
sL = &es[expand-1-j] - &es[1]
   = 4294967296
&es[expand-1-j] - &es[1] = 0
es[expand-j-1]=0
Segmentation fault


Expected Results:
&es[1] = 0x11ffff889
expand-1-j = 1
&es[expand-1-j] = 0x11ffff889
sL = &es[expand-1-j] - &es[1]
   = 0
&es[expand-1-j] - &es[1] = 0
es[expand-j-1]=0
es[expand-1-j]=0

Additional info:

// test.cpp

#include <stdio.h>

int main ()
{
   unsigned char *es;
   unsigned char exp_buffer[2];

   long sL;

   unsigned int j;
   int expand;

   es=exp_buffer;
   j=0;
   expand=2;
   es[0]=0;
   es[1]=0;

   printf ("es[1] = %d\n", es[1]);
   printf ("&es[1] = %p\n", &es[1]);
   printf ("expand-1-j = %d\n", expand-1-j);
   printf ("&es[expand-1-j] = %p\n", &es[expand-1-j]);
   sL = &es[expand-1-j] - &es[1];
   printf ("sL = &es[expand-1-j] - &es[1]\n   = %ld\n", sL);
   printf ("&es[expand-1-j] - &es[1] = %d\n", &es[expand-1-j]-&es[1]);
   printf ("es[expand-j-1]=%d\n",es[expand-j-1]);
   printf ("es[expand-1-j]=%d\n",es[expand-1-j]);
   return 0;
}

Comment 1 Christopher Blizzard 2002-01-24 16:37:42 UTC
This test case don't provide show the bug with gcc-2.96-98.

Comment 2 Andrew Schultz 2002-02-25 22:55:41 UTC
this has come up again in Mozilla (bug 127455), this time with pointer arithmetic.
http://bugzilla.mozilla.org/show_bug.cgi?id=127455

Comment 3 Andrew Schultz 2002-02-26 21:16:36 UTC
Simpler case showing more extereme behavior from Mozilla bug 127455:
------------------------------------------
#include <stdio.h>
int main()
{
   unsigned int j=1, i, *p;
   p = &i;
   p += -j;
   printf ("%p\n%p\n%ld\n", &i, p, p-&i);
}
------------------------------------------
> 0x11ffff884
> 0x51ffff880
> 4294967295

Comment 4 Jakub Jelinek 2002-02-26 23:07:52 UTC
If this is C++ only, then it is likely GCC PR c++/4401 which I've fixed
in gcc 3.1 6 days ago. Will try to verify the patch in 2.96 and include it
in next rpm...

Comment 5 Andrew Schultz 2002-02-26 23:20:51 UTC
The original report (with array indices) was c++ only.  The one with pointer
arithmetic is both c and c++.  I figured they were the same underlying problem,
so I didn't file a new bug.

Thanks for working on this.

Comment 6 Jakub Jelinek 2002-02-27 11:26:18 UTC
The difference between the two is that the former is a compiler bug while
the latter is correct behaviour.
p += -j
where -j is unsigned int is the same as
p = p + ((unsigned int) (-j));
you need to cast it to some signed type before it is converted to ptrdiff_t.

Comment 7 Andrew Schultz 2002-02-27 15:15:13 UTC
The second case works ok on gcc-i686:
> 0xbffff8d0
> 0xbffff8cc
> -1

similar code in Mozilla worked on platforms other than Linux-Alpha
(I'm not disagreeing, just confused)

Comment 8 Jakub Jelinek 2002-02-27 15:19:27 UTC
Yeah, but i686 is 32-bit target where sizeof(int) == sizeof(void *).
That's not the case on Alpha, nor IA-64, nor Sparc64, ...

Comment 9 Andrew Schultz 2002-02-27 15:37:43 UTC
yup.  Compaq's cc compiler on OSF does the same as gcc on Linux

Comment 10 Jakub Jelinek 2002-03-04 14:24:13 UTC
*** Bug 60443 has been marked as a duplicate of this bug. ***

Comment 11 Bill Nottingham 2002-07-26 21:47:27 UTC
An errata has been issued which should help the problem described in this bug report. 
This report is therefore being closed with a resolution of ERRATA. For more information
on the solution and/or where to find the updated files, please follow the link below. You may reopen 
this bug report if the solution does not work for you.

http://rhn.redhat.com/errata/RHBA-2002-055.html