miscompile writing to bitfield at -Os

Bug #910363 reported by dn
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
gcc
Invalid
Medium
gcc-4.5 (Ubuntu)
New
Undecided
Unassigned

Bug Description

The attached preprocessed file was extracted out of a file from LLVM. When it was compiled by g++-4.5 at -Os, and LLVM's test suite was run, it resulted in the assert in PointerType's constructor firing:
llvm::PointerType::PointerType(llvm::Type*, unsigned int): Assertion `oldNCT == NumContainedTys && "bitfield written out of bounds?"' failed.

This was the invocation I used:
g++-4.5 -Os -fPIC -g -pedantic -Wno-long-long -fno-exceptions -o lib/VMCore/CMakeFiles/LLVMCore.dir/Type2.cpp.o -c Type2.ii

Further details here:
http://llvm.org/PR11652

ProblemType: Bug
DistroRelease: Ubuntu 11.04
Package: g++-4.5 4.5.2-8ubuntu4
Uname: Linux 3.1.0-custom x86_64
Architecture: amd64
Date: Tue Dec 27 22:11:40 2011
InstallationMedia: Ubuntu 11.04 "Natty Narwhal" - Release amd64 (20110427.1)
ProcEnviron:
 LANGUAGE=en_US:en
 PATH=(custom, user)
 LANG=en_US.UTF-8
 SHELL=/bin/bash
SourcePackage: gcc-4.5
UpgradeStatus: No upgrade log present (probably fresh install)

Revision history for this message
dn (nobled) wrote :
Revision history for this message
dn (nobled) wrote :
Revision history for this message
dn (nobled) wrote :

To be more specific. These two member variables are at offset 0x8:

unsigned ID : 8;
unsigned SubclassData : 24;

When setSubclassData() isn't inlined, it's called with the address of 'SubclassData' in %rdi...:

   0x00007ffff76d684f <+71>: lea 0x9(%rdi),%r12
   0x00007ffff76d6853 <+75>: or $0x1,%esi
   0x00007ffff76d6856 <+78>: mov %r12,%rdi
   0x00007ffff76d6859 <+81>: callq 0x7ffff76d6774 <llvm::Type::setSubclassData(unsigned int)>

...but then, it writes more than 24 bits to that address, writing zeroes into the next member:

   0x00007ffff76d6774 <+0>: mov %esi,%eax
   0x00007ffff76d6776 <+2>: sub $0x8,%rsp
   0x00007ffff76d677a <+6>: and $0xffffff,%eax
   0x00007ffff76d677f <+11>: cmp %esi,%eax
   0x00007ffff76d6781 <+13>: mov %eax,(%rdi) # corruption

Revision history for this message
In , dn (nobled) wrote :

Compiling the attached preprocessed file with this:
g++-4.5 -Os -fPIC -g -pedantic -Wno-long-long -fno-exceptions -o Type2.cpp.o -c Type2.ii

Results in writing 32 bits to a 24-bit bitfield, overwriting the first byte of the next member variable.

These two members of class Type are (on x86_64) at offset 0x8:
  TypeID ID : 8;
  unsigned SubclassData : 24;

When setSubclassData() isn't inlined, it's called (from StructType::setBody() and PointerType's constructor) with the address of 'SubclassData' in %rdi...:

   0x00007ffff76d684f <+71>: lea 0x9(%rdi),%r12
   0x00007ffff76d6853 <+75>: or $0x1,%esi
   0x00007ffff76d6856 <+78>: mov %r12,%rdi
   0x00007ffff76d6859 <+81>: callq 0x7ffff76d6774 <llvm::Type::setSubclassData(unsigned int)>

...but then, setSubclassData writes more than 24 bits to that address:

   0x00007ffff76d6774 <+0>: mov %esi,%eax
   0x00007ffff76d6776 <+2>: sub $0x8,%rsp
   0x00007ffff76d677a <+6>: and $0xffffff,%eax
   0x00007ffff76d677f <+11>: cmp %esi,%eax
   0x00007ffff76d6781 <+13>: mov %eax,(%rdi) # corruption

Revision history for this message
In , dn (nobled) wrote :

Created attachment 26244
output of `gcc -v -save-temps`

Revision history for this message
In , dn (nobled) wrote :

Created attachment 26245
pre-processed file (gzip-compressed)

Revision history for this message
In , Rguenth (rguenth) wrote :

It's a bug in IPA-SRA that creates non-mode-size stores:

void llvm::Type::_ZN4llvm4Type15setSubclassDataEj.clone.1(unsigned int:24*, unsigned int) (<unnamed-unsigned:24> * ISRA.6, unsigned int val)
{
...
<bb 2>:
  D.87358_2 = (<unnamed-unsigned:24>) val_1(D);
  *ISRA.6_8(D) = D.87358_2;

I think this has been fixed in 4.6 (not on the 4.5 branch though) which
no longer performs this substitution. You can work around this using
-fno-ipa-sra.

The following is a simplified testcase:

extern "C" void abort (void);
struct S
{
  void __attribute__((noinline)) set(unsigned val)
    {
      data = val;
      if (data != val)
        abort ();
    }
  int pad0;
  unsigned pad1 : 8;
  unsigned data : 24;
  int pad2;
};
int main()
{
  S s;
  s.pad2 = -1;
  s.set(0);
  if (s.pad2 != -1)
    abort ();
}

Where 4.6 says:

Candidate (2069): this
! Disqualifying this - Encountered a bit-field access.

which hints at what needs backporting.

Martin?

Changed in gcc:
importance: Unknown → Medium
status: Unknown → Confirmed
Revision history for this message
In , Jamborm (jamborm) wrote :

(In reply to comment #3)
> Where 4.6 says:
>
> Candidate (2069): this
> ! Disqualifying this - Encountered a bit-field access.
>
> which hints at what needs backporting.
>
> Martin?

Right, this seems to be PR 45644, for some reason I did not backport
the fix to 4.5. It should be fixed by committing
http://gcc.gnu.org/viewcvs?view=revision&revision=164313
I'll do the backport and test it today.

Revision history for this message
In , Jamborm (jamborm) wrote :

Patch backporting the fix has been posted to the mailing list:
http://gcc.gnu.org/ml/gcc-patches/2012-01/msg00300.html

Changed in gcc:
status: Confirmed → In Progress
Revision history for this message
In , Jamborm (jamborm) wrote :

Author: jamborm
Date: Mon Jan 9 18:40:09 2012
New Revision: 183023

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=183023
Log:
2012-01-09 Martin Jambor <email address hidden>

 PR tree-optimization/51759

 Backport from mainline
 2010-09-15 Martin Jambor <email address hidden>

        PR middle-end/45644
        * tree-sra.c (create_access): Check for bit-fields directly.

        * testsuite/gcc.dg/ipa/pr45644.c: New test.
 * testsuite/g++.dg/ipa/pr51759.C: Likewise.

Added:
    branches/gcc-4_5-branch/gcc/testsuite/g++.dg/ipa/pr51759.C
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/ipa/pr45644.c
Modified:
    branches/gcc-4_5-branch/gcc/ChangeLog
    branches/gcc-4_5-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_5-branch/gcc/tree-sra.c

Revision history for this message
In , Jamborm (jamborm) wrote :

Author: jamborm
Date: Mon Jan 9 19:52:06 2012
New Revision: 183029

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=183029
Log:
2012-01-09 Martin Jambor <email address hidden>

        PR tree-optimization/51759
 * g++.dg/ipa/pr51759.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/ipa/pr51759.C
Modified:
    trunk/gcc/testsuite/ChangeLog

Revision history for this message
In , Jamborm (jamborm) wrote :

Author: jamborm
Date: Mon Jan 9 20:03:08 2012
New Revision: 183031

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=183031
Log:
2012-01-09 Martin Jambor <email address hidden>

        PR tree-optimization/51759
 * g++.dg/ipa/pr51759.C: New test.

Added:
    branches/gcc-4_6-branch/gcc/testsuite/g++.dg/ipa/pr51759.C
Modified:
    branches/gcc-4_6-branch/gcc/testsuite/ChangeLog

Revision history for this message
In , Jamborm (jamborm) wrote :

I have backported the fix to the 4.5 branch and also committed the testcase to the the 4.6 branch and trunk. Still it is a duplicate of PR 45644 and so I'm closing this as such.

*** This bug has been marked as a duplicate of bug 45644 ***

Changed in gcc:
status: In Progress → Invalid
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.