[PATCH v2] Silence misguided GCC warning about alignment issues

Johannes Schindelin johannes.schindelin at gmx.de
Mon Aug 7 20:58:16 UTC 2017


When compiling xz_dec_stream.c with GCC (at least with versions 5.4.0
and 7.1.0), it complains thusly:

	In function 'dec_stream_footer':
	error: dereferencing type-punned pointer will break
	      strict-aliasing rules [-Werror=strict-aliasing]
	   if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf))
	       ^~

Despite the arrow pointing to the xz_crc32() call, the actual problem is
the get_le32() macro expansion.

The thing is, the `buf` field was put just after two fields of type
size_t for the express purpose of avoiding alignment issues, as per the
comment above the `temp` struct.

Meaning: GCC gets this all wrong and should not complain.

An earlier attempt to fix (76b65624b (unxz: get_le32
macro is obviously wrong, 2017-08-07)) this by simply forcing
get_unaligned_32() (which is unnecessarily slow because it rebuilds a
32-bit int from accessing already-aligned bytes one by one) was a bit
heavy-handed.

But we can help GCC by turning the get_le32() macro into an inline
function. So let's do that, it also helps compile time safety by making
the code a little bit stricter.

Signed-off-by: Johannes Schindelin <johannes.schindelin at gmx.de>
---
Published-As: https://github.com/dscho/busybox-w32/releases/tag/busybox-type-punned-warning-v2
Fetch-It-Via: git fetch https://github.com/dscho/busybox-w32 busybox-type-punned-warning-v2

Interdiff vs v1:
 diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c
 index 0be85500c..e24cff98b 100644
 --- a/archival/libarchive/decompress_unxz.c
 +++ b/archival/libarchive/decompress_unxz.c
 @@ -37,6 +37,11 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
   || !defined(put_unaligned_be32)
  # error get_unaligned_le32 accessors are not defined
  #endif
 +static ALWAYS_INLINE uint32_t get_le32_fast(const void *p)
 +{
 +  return *(uint32_t *)p;
 +}
 +#define get_le32 get_le32_fast
  
  #include "unxz/xz_dec_bcj.c"
  #include "unxz/xz_dec_lzma2.c"
 diff --git a/archival/libarchive/unxz/xz_dec_stream.c b/archival/libarchive/unxz/xz_dec_stream.c
 index 8131ee30a..bf791055b 100644
 --- a/archival/libarchive/unxz/xz_dec_stream.c
 +++ b/archival/libarchive/unxz/xz_dec_stream.c
 @@ -423,15 +423,6 @@ static enum xz_ret XZ_FUNC dec_stream_footer(struct xz_dec *s)
  	if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
  		return XZ_DATA_ERROR;
  
 -#if defined(__GNUC__)
 -	/*
 -	 * The temp.buf field is put just after two fields of type size_t for
 -	 * the express purpose of avoiding alignment issues. But GCC complains
 -	 * about it nevertheless... so: shut GCC up for a few lines.
 -	 */
 -#pragma GCC diagnostic push
 -#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 -#endif
  	if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf))
  		return XZ_DATA_ERROR;
  
 @@ -442,9 +433,6 @@ static enum xz_ret XZ_FUNC dec_stream_footer(struct xz_dec *s)
  	 */
  	if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
  		return XZ_DATA_ERROR;
 -#if defined(__GNUC__)
 -#pragma GCC diagnostic pop
 -#endif
  
  	if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type)
  		return XZ_DATA_ERROR;
 archival/libarchive/decompress_unxz.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c
index 0be85500c..e24cff98b 100644
--- a/archival/libarchive/decompress_unxz.c
+++ b/archival/libarchive/decompress_unxz.c
@@ -37,6 +37,11 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
  || !defined(put_unaligned_be32)
 # error get_unaligned_le32 accessors are not defined
 #endif
+static ALWAYS_INLINE uint32_t get_le32_fast(const void *p)
+{
+  return *(uint32_t *)p;
+}
+#define get_le32 get_le32_fast
 
 #include "unxz/xz_dec_bcj.c"
 #include "unxz/xz_dec_lzma2.c"

base-commit: a907b828d6e9f1357fc2e1db09d3eb1d3fb9b826
-- 
2.14.0.windows.1.2.g0f3342804fc


More information about the busybox mailing list