User account creation filtered due to spam.

Bug 8404 - arguments/stack corrupted when passing non-byte aligned struct with attribute packed
Summary: arguments/stack corrupted when passing non-byte aligned struct with attribute...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 3.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2002-10-30 08:46 UTC by fredlwm
Modified: 2003-07-25 17:33 UTC (History)
1 user (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description fredlwm 2002-10-30 08:46:03 UTC

Release:
3.2

Environment:
System: Linux pervalidus 2.4.19 #1 Sat Aug 17 13:14:00 BRT 2002 i686 unknown unknown GNU/Linux
Architecture: i686

	
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: /usr/local/src/GNU/gcc-3.2/configure --prefix=/usr --libdir=/usr/lib --with-slibdir=/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-threads --enable-__cxa_atexit --enable-languages=c++ --disable-nls

How-To-Repeat:
// GCC 3.2 BUG REPORT
//
// This program demonstrates a bug in gcc version 3.2, when passing a
// structure with the "packed" attribute comtaining misaligned data.
// The data structure is actually from the ATA/ATAPI SMART data
// structures.  I was working on some legacy code that passed these
// structures (not pointers to them!) as arguments.  For myself, there
// is no urgency in this because I have modified the code to do what
// it should have done in the first place -- pass pointers.  But it's
// a serious bug.

// Bruce Allen   ballen@uwm.edu
// F.L.W. Meunier <0@pervalidus.net>

//  Compile like this:  cc -o bug bug.c

//  It SHOULD print "These two values should be equal: 16 16
//  GCC 3.2 output  "These two values should be equal: 62104  16
//  System is modified slackware


#include <stdio.h>
#define NUMBER_ATA_SMART_ATTRIBUTES 30

struct ata_smart_attribute {
  unsigned char id;
  union {
    unsigned short all; 
    struct {
      unsigned prefailure:1;   
      unsigned online:1; 
      unsigned performance:1;
      unsigned errorrate:1;	
      unsigned eventcount:1 ;
      unsigned selfperserving:1;
      unsigned reserved:10;	
    } __attribute__ ((packed)) flag;
  } status ; 
  unsigned char current;
  unsigned char worst;
  unsigned char raw[6];
  unsigned char reserv;
} __attribute__ ((packed));


struct ata_smart_values {
  unsigned short int revnumber;
  struct ata_smart_attribute vendor_attributes [NUMBER_ATA_SMART_ATTRIBUTES];
  unsigned char offline_data_collection_status;
  unsigned char self_test_exec_status;  
  unsigned short int total_time_to_complete_off_line; 
  unsigned char vendor_specific_366; 
  unsigned char offline_data_collection_capability;
  unsigned short int smart_capability;
  unsigned char errorlog_capability;
  unsigned char vendor_specific_371; 
  unsigned char short_test_completion_time;
  unsigned char extend_test_completion_time;
  unsigned char reserved_374_385 [12];
  unsigned char vendor_specific_386_509 [125];
  unsigned char chksum;
} __attribute__ ((packed));


struct ata_smart_threshold_entry {
  unsigned char id;
  unsigned char threshold;
  unsigned char reserved[10];
} __attribute__ ((packed));


struct ata_smart_thresholds {
  unsigned short int revnumber;
  struct ata_smart_threshold_entry thres_entries[NUMBER_ATA_SMART_ATTRIBUTES];
  unsigned char reserved[149];
  unsigned char chksum;
} __attribute__ ((packed));



// This function is the problem.  When it gets it's arguments passsd
// (a total of 2x512+4 bytes or 1028 bytes of argument!) the first
// seven bytes get messed up (according to ddd/gdb)

void problem(struct ata_smart_values data, 
	     struct ata_smart_thresholds thresholds,
	     int onlyfailed){
  printf("These two values should be equal: %d  %d\n",
	 data.revnumber,onlyfailed);
  return;
}


// Define two of these data structures
struct ata_smart_values smartval;
struct ata_smart_thresholds smartthres;


// Should print "16 16" but doesn't
int main(int argc, char **argv){
  unsigned short i=16;

  smartval.revnumber=smartthres.revnumber=16;

  problem(smartval, smartthres, i);
 
  return 0;
}
Comment 1 fredlwm 2002-10-30 08:46:03 UTC
Fix:
	don't pass strutures, pass pointers.  Seriously, don't know.
Comment 2 Wolfgang Bangerth 2002-12-02 13:12:14 UTC
State-Changed-From-To: open->closed
State-Changed-Why: Confirmed with 3.2, but is fixed in 3.2.2pre and 3.3CVS.
    Maybe it was even fixed in 3.2.1, you might want to try it.