]> err.no Git - util-linux/commitdiff
fdisk: fix strict-aliasing bugs
authorKarel Zak <kzak@redhat.com>
Fri, 16 Oct 2009 19:49:33 +0000 (21:49 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 16 Oct 2009 22:18:46 +0000 (00:18 +0200)
gcc 4.4 produces tons of

  "dereferencing type-punned pointer will break strict-aliasing rules"

warnings for fdisk code where is

  char buffer[BUFSIZ];

  ((struct disklabel *) MBRBuffer)->foo

There are two ways how fix the problem:

  1/ union {
          char buffer[BUFSIZ], struct disklabel label
     } MBRBuffer;

  2/ use allocated buffer, this way seems less invasive.

This patch implements 2/.

Old version:
  $ make -C fdisk | grep -c warning
  236

New version:
  $ make -C fdisk | grep -c warning
  0

About aliasing:
 - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
 - http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
 - C99

Signed-off-by: Karel Zak <kzak@redhat.com>
fdisk/fdisk.c
fdisk/fdisk.h
fdisk/fdiskaixlabel.c
fdisk/fdiskmaclabel.c
fdisk/fdisksgilabel.c
fdisk/fdisksunlabel.c

index aaa01a84a2719561d8cdd5e0b628a06c132f1195..d0b4c5f897ac0a1a30c646d6bcf51a298f22e920 100644 (file)
@@ -174,7 +174,7 @@ static int type_open = O_RDWR;
  * Raw disk label. For DOS-type partition tables the MBR,
  * with descriptions of the primary partitions.
  */
-unsigned char MBRbuffer[MAX_SECTOR_SIZE];
+unsigned char *MBRbuffer;
 
 /*
  * per partition table entry data
@@ -949,6 +949,27 @@ get_geometry(int fd, struct geom *g) {
        }
 }
 
+/*
+ * Please, always use allocated buffer if you want to cast the buffer to
+ * any struct -- cast non-allocated buffer to any struct is against
+ * strict-aliasing rules.  --kzak 16-Oct-2009
+ */
+static void init_mbr_buffer(void)
+{
+       if (MBRbuffer)
+               return;
+
+       MBRbuffer = calloc(1, MAX_SECTOR_SIZE);
+       if (!MBRbuffer)
+               fatal(out_of_memory);
+}
+
+void zeroize_mbr_buffer(void)
+{
+       if (MBRbuffer)
+               memset(MBRbuffer, 0, MAX_SECTOR_SIZE);
+}
+
 /*
  * Read MBR.  Returns:
  *   -1: no 0xaa55 flag present (possibly entire disk BSD)
@@ -2658,6 +2679,8 @@ main(int argc, char **argv) {
                         " be used with one specified device\n"));
 #endif
 
+       init_mbr_buffer();
+
        if (optl) {
                nowarn = 1;
                type_open = O_RDONLY;
index 6ef68b6e73f38a6c19b6f4d5a82c90a8e1e53597..0286ce0a842bb5f727a11a3096a2d1ab17945d4d 100644 (file)
@@ -76,7 +76,9 @@ extern int valid_part_table_flag(unsigned char *b);
 extern unsigned int read_int(unsigned int low, unsigned int dflt,
                             unsigned int high, unsigned int base, char *mesg);
 
-extern unsigned char MBRbuffer[MAX_SECTOR_SIZE];
+extern unsigned char *MBRbuffer;
+extern void zeroize_mbr_buffer(void);
+
 extern unsigned int heads, cylinders, sector_size;
 extern unsigned long long sectors;
 extern char *partition_type(unsigned char type);
index 4f6167f97ff8280928f0c484fcad1ea784d4953e..e7ee95d1c693b364da0156f8d1eacb2c5ca55218 100644 (file)
@@ -44,7 +44,7 @@ aix_nolabel( void )
     aixlabel->magic = 0;
     aix_label = 0;
     partitions = 4;
-    memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
+    zeroize_mbr_buffer();
     return;
 }
 
index 06d4a6ed2f4aac8e60308c0dc3b4fd9d0abb6329..4e3db20e25c769f6b88db76cac74eccd9c003bbe 100644 (file)
@@ -44,7 +44,7 @@ mac_nolabel( void )
     maclabel->magic = 0;
     mac_label = 0;
     partitions = 4;
-    memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
+    zeroize_mbr_buffer();
     return;
 }
 
index fb2091daff2dccaa4e82b095290c172dd953c180..3707a4cd1b6371ea3606560f4bb643e29ab4358b 100644 (file)
@@ -737,7 +737,7 @@ create_sgilabel(void)
                }
        }
 
-       memset(MBRbuffer, 0, sizeof(MBRbuffer));
+       zeroize_mbr_buffer();
        sgilabel->magic = SSWAP32(SGI_LABEL_MAGIC);
        sgilabel->boot_part = SSWAP16(0);
        sgilabel->swap_part = SSWAP16(1);
index be7b9f6a4eec23a1ee23b2f4b5c1c6fbe1f0083b..2f9fad906222858fd2781dcebc5cdfe165447105 100644 (file)
@@ -203,7 +203,7 @@ void create_sunlabel(void)
 #else
        other_endian = 0;
 #endif
-       memset(MBRbuffer, 0, sizeof(MBRbuffer));
+       zeroize_mbr_buffer();
        sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC);
        sunlabel->sanity = SSWAP32(SUN_LABEL_SANE);
        sunlabel->version = SSWAP32(SUN_LABEL_VERSION);