From b2f15782a71fd7d89bed7b3e1f799358779ee828 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 16 Oct 2009 21:49:33 +0200 Subject: [PATCH] fdisk: fix strict-aliasing bugs 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 --- fdisk/fdisk.c | 25 ++++++++++++++++++++++++- fdisk/fdisk.h | 4 +++- fdisk/fdiskaixlabel.c | 2 +- fdisk/fdiskmaclabel.c | 2 +- fdisk/fdisksgilabel.c | 2 +- fdisk/fdisksunlabel.c | 2 +- 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index aaa01a84..d0b4c5f8 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -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; diff --git a/fdisk/fdisk.h b/fdisk/fdisk.h index 6ef68b6e..0286ce0a 100644 --- a/fdisk/fdisk.h +++ b/fdisk/fdisk.h @@ -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); diff --git a/fdisk/fdiskaixlabel.c b/fdisk/fdiskaixlabel.c index 4f6167f9..e7ee95d1 100644 --- a/fdisk/fdiskaixlabel.c +++ b/fdisk/fdiskaixlabel.c @@ -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; } diff --git a/fdisk/fdiskmaclabel.c b/fdisk/fdiskmaclabel.c index 06d4a6ed..4e3db20e 100644 --- a/fdisk/fdiskmaclabel.c +++ b/fdisk/fdiskmaclabel.c @@ -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; } diff --git a/fdisk/fdisksgilabel.c b/fdisk/fdisksgilabel.c index fb2091da..3707a4cd 100644 --- a/fdisk/fdisksgilabel.c +++ b/fdisk/fdisksgilabel.c @@ -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); diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c index be7b9f6a..2f9fad90 100644 --- a/fdisk/fdisksunlabel.c +++ b/fdisk/fdisksunlabel.c @@ -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); -- 2.39.5