From: Nathan Moinvaziri Date: Mon, 27 Dec 2021 03:56:12 +0000 (-0800) Subject: Use memcpy for unaligned reads. X-Git-Tag: 2.1.0-beta1~454 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bc87f1581c4475669427a57b1a3b60bf9d145f2;p=thirdparty%2Fzlib-ng.git Use memcpy for unaligned reads. Co-authored-by: Matija Skala --- diff --git a/chunkset.c b/chunkset.c index b07e6f482..48cdd9df6 100644 --- a/chunkset.c +++ b/chunkset.c @@ -5,7 +5,7 @@ #include "zbuild.h" #include "zutil.h" -// We need sizeof(chunk_t) to be 8, no matter what. +/* Define 8 byte chunks differently depending on unaligned support */ #if defined(UNALIGNED64_OK) typedef uint64_t chunk_t; #elif defined(UNALIGNED_OK) @@ -34,27 +34,24 @@ static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { #if defined(UNALIGNED64_OK) uint32_t half_chunk; - half_chunk = *(uint32_t *)from; + memcpy(&half_chunk, from, sizeof(half_chunk)); *chunk = 0x0000000100000001 * (uint64_t)half_chunk; #elif defined(UNALIGNED_OK) - chunk->u32[0] = *(uint32_t *)from; + memcpy(&chunk->u32[0], from, sizeof(chunk->u32[0])); chunk->u32[1] = chunk->u32[0]; #else uint8_t *chunkptr = (uint8_t *)chunk; - memcpy(chunkptr, from, 4); - memcpy(chunkptr+4, from, 4); + memcpy(chunkptr, from, sizeof(uint32_t)); + memcpy(chunkptr+4, from, sizeof(uint32_t)); #endif } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - *chunk = *(uint64_t *)from; -#elif defined(UNALIGNED_OK) - uint32_t* p = (uint32_t *)from; - chunk->u32[0] = p[0]; - chunk->u32[1] = p[1]; +#if defined(UNALIGNED_OK) && !defined(UNALIGNED64_OK) + memcpy(&chunk->u32[0], from, sizeof(chunk->u32[0])); + memcpy(&chunk->u32[1], from+4, sizeof(chunk->u32[1])); #else - memcpy(chunk, from, sizeof(chunk_t)); + memcpy(chunk, from, sizeof(uint64_t)); #endif } @@ -63,14 +60,7 @@ static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { } static inline void storechunk(uint8_t *out, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - *(uint64_t *)out = *chunk; -#elif defined(UNALIGNED_OK) - ((uint32_t *)out)[0] = chunk->u32[0]; - ((uint32_t *)out)[1] = chunk->u32[1]; -#else - memcpy(out, chunk, sizeof(chunk_t)); -#endif + memcpy(out, chunk, sizeof(uint64_t)); } #define CHUNKSIZE chunksize_c diff --git a/compare258.c b/compare258.c index f4f1936c4..e6e63f249 100644 --- a/compare258.c +++ b/compare258.c @@ -123,10 +123,12 @@ static inline uint32_t compare256_unaligned_32_static(const unsigned char *src0, uint32_t len = 0; do { - uint32_t sv = *(uint32_t *)src0; - uint32_t mv = *(uint32_t *)src1; - uint32_t diff = sv ^ mv; + uint32_t sv, mv, diff; + memcpy(&sv, src0, sizeof(sv)); + memcpy(&mv, src1, sizeof(mv)); + + diff = sv ^ mv; if (diff) { uint32_t match_byte = __builtin_ctz(diff) / 8; return len + match_byte; @@ -170,10 +172,12 @@ static inline uint32_t compare256_unaligned_64_static(const unsigned char *src0, uint32_t len = 0; do { - uint64_t sv = *(uint64_t *)src0; - uint64_t mv = *(uint64_t *)src1; - uint64_t diff = sv ^ mv; + uint64_t sv, mv, diff; + + memcpy(&sv, src0, sizeof(sv)); + memcpy(&mv, src1, sizeof(mv)); + diff = sv ^ mv; if (diff) { uint64_t match_byte = __builtin_ctzll(diff) / 8; return len + (uint32_t)match_byte; diff --git a/deflate.h b/deflate.h index 94ff239ce..030db4f09 100644 --- a/deflate.h +++ b/deflate.h @@ -302,13 +302,11 @@ typedef enum { * IN assertion: there is enough room in pending_buf. */ static inline void put_short(deflate_state *s, uint16_t w) { -#if defined(UNALIGNED_OK) - *(uint16_t *)(&s->pending_buf[s->pending]) = w; - s->pending += 2; -#else - put_byte(s, (w & 0xff)); - put_byte(s, ((w >> 8) & 0xff)); +#if BYTE_ORDER == BIG_ENDIAN + w = ZSWAP16(w); #endif + memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); + s->pending += 2; } /* =========================================================================== @@ -316,8 +314,11 @@ static inline void put_short(deflate_state *s, uint16_t w) { * IN assertion: there is enough room in pending_buf. */ static inline void put_short_msb(deflate_state *s, uint16_t w) { - put_byte(s, ((w >> 8) & 0xff)); - put_byte(s, (w & 0xff)); +#if BYTE_ORDER == LITTLE_ENDIAN + w = ZSWAP16(w); +#endif + memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); + s->pending += 2; } /* =========================================================================== @@ -325,15 +326,11 @@ static inline void put_short_msb(deflate_state *s, uint16_t w) { * IN assertion: there is enough room in pending_buf. */ static inline void put_uint32(deflate_state *s, uint32_t dw) { -#if defined(UNALIGNED_OK) - *(uint32_t *)(&s->pending_buf[s->pending]) = dw; - s->pending += 4; -#else - put_byte(s, (dw & 0xff)); - put_byte(s, ((dw >> 8) & 0xff)); - put_byte(s, ((dw >> 16) & 0xff)); - put_byte(s, ((dw >> 24) & 0xff)); +#if BYTE_ORDER == BIG_ENDIAN + dw = ZSWAP32(dw); #endif + memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); + s->pending += 4; } /* =========================================================================== @@ -341,15 +338,11 @@ static inline void put_uint32(deflate_state *s, uint32_t dw) { * IN assertion: there is enough room in pending_buf. */ static inline void put_uint32_msb(deflate_state *s, uint32_t dw) { -#if defined(UNALIGNED_OK) - *(uint32_t *)(&s->pending_buf[s->pending]) = ZSWAP32(dw); - s->pending += 4; -#else - put_byte(s, ((dw >> 24) & 0xff)); - put_byte(s, ((dw >> 16) & 0xff)); - put_byte(s, ((dw >> 8) & 0xff)); - put_byte(s, (dw & 0xff)); +#if BYTE_ORDER == LITTLE_ENDIAN + dw = ZSWAP32(dw); #endif + memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); + s->pending += 4; } /* =========================================================================== @@ -357,24 +350,11 @@ static inline void put_uint32_msb(deflate_state *s, uint32_t dw) { * IN assertion: there is enough room in pending_buf. */ static inline void put_uint64(deflate_state *s, uint64_t lld) { -#if defined(UNALIGNED64_OK) - *(uint64_t *)(&s->pending_buf[s->pending]) = lld; - s->pending += 8; -#elif defined(UNALIGNED_OK) - *(uint32_t *)(&s->pending_buf[s->pending]) = lld & 0xffffffff; - s->pending += 4; - *(uint32_t *)(&s->pending_buf[s->pending]) = (lld >> 32) & 0xffffffff; - s->pending += 4; -#else - put_byte(s, (lld & 0xff)); - put_byte(s, ((lld >> 8) & 0xff)); - put_byte(s, ((lld >> 16) & 0xff)); - put_byte(s, ((lld >> 24) & 0xff)); - put_byte(s, ((lld >> 32) & 0xff)); - put_byte(s, ((lld >> 40) & 0xff)); - put_byte(s, ((lld >> 48) & 0xff)); - put_byte(s, ((lld >> 56) & 0xff)); +#if BYTE_ORDER == BIG_ENDIAN + lld = ZSWAP64(lld); #endif + memcpy(&s->pending_buf[s->pending], &lld, sizeof(lld)); + s->pending += 8; } #define MIN_LOOKAHEAD (STD_MAX_MATCH + STD_MIN_MATCH + 1) diff --git a/insert_string_tpl.h b/insert_string_tpl.h index ad88275bf..7d3e46c89 100644 --- a/insert_string_tpl.h +++ b/insert_string_tpl.h @@ -31,7 +31,7 @@ #ifndef HASH_CALC_READ # ifdef UNALIGNED_OK # define HASH_CALC_READ \ - val = *(uint32_t *)(strstart); + memcpy(&val, strstart, sizeof(val)); # else # define HASH_CALC_READ \ val = ((uint32_t)(strstart[0])); \ diff --git a/match_tpl.h b/match_tpl.h index e4e31e981..e11abfbb7 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -85,11 +85,11 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { } #endif - scan_end = *(bestcmp_t *)(scan+offset); + memcpy(&scan_end, scan+offset, sizeof(bestcmp_t)); #ifndef UNALIGNED_OK - scan_end0 = *(bestcmp_t *)(scan+offset+1); + memcpy(&scan_end0, scan+offset+1, sizeof(bestcmp_t)); #else - scan_start = *(bestcmp_t *)(scan); + memcpy(&scan_start, scan, sizeof(bestcmp_t)); #endif mbase_end = (mbase_start+offset); @@ -207,9 +207,9 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #endif } #endif - scan_end = *(bestcmp_t *)(scan+offset); + memcpy(&scan_end, scan+offset, sizeof(bestcmp_t)); #ifndef UNALIGNED_OK - scan_end0 = *(bestcmp_t *)(scan+offset+1); + memcpy(&scan_end0, scan+offset+1, sizeof(bestcmp_t)); #endif #ifdef LONGEST_MATCH_SLOW /* Look for a better string offset */