]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Prevent unaligned double word accesses on ARMv7 in chunkset_c
authorNiLuJe <ninuje@gmail.com>
Sun, 2 Aug 2020 18:20:56 +0000 (20:20 +0200)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Thu, 20 Aug 2020 10:04:56 +0000 (12:04 +0200)
Requires some mild trickery to walk the edge between readability and
doing what it needs to.

chunkset.c

index 2e48dda90f04b6ba1719110b94408a9020773cc6..2aa8d4e47feca9681904a3d7e0d118f257bf303a 100644 (file)
@@ -5,10 +5,13 @@
 #include "zbuild.h"
 #include "zutil.h"
 
-#ifdef UNALIGNED_OK
+// We need sizeof(chunk_t) to be 8, no matter what.
+#if defined(UNALIGNED64_OK)
 typedef uint64_t chunk_t;
+#elif defined(UNALIGNED_OK)
+typedef struct chunk_t { uint32_t u32[2]; } chunk_t;
 #else
-typedef uint8_t chunk_t[8];
+typedef struct chunk_t { uint8_t u8[8]; } chunk_t;
 #endif
 
 #define HAVE_CHUNKMEMSET_1
@@ -16,18 +19,24 @@ typedef uint8_t chunk_t[8];
 #define HAVE_CHUNKMEMSET_8
 
 static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) {
-#ifdef UNALIGNED_OK
+#if defined(UNALIGNED64_OK)
     *chunk = 0x0101010101010101 * (uint8_t)*from;
+#elif defined(UNALIGNED_OK)
+    chunk->u32[0] = 0x01010101 * (uint8_t)*from;
+    chunk->u32[1] = chunk->u32[0];
 #else
     memset(chunk, *from, sizeof(chunk_t));
 #endif
 }
 
 static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) {
-#ifdef UNALIGNED_OK
+#if defined(UNALIGNED64_OK)
     uint32_t half_chunk;
     half_chunk = *(uint32_t *)from;
     *chunk = 0x0000000100000001 * (uint64_t)half_chunk;
+#elif defined(UNALIGNED_OK)
+    chunk->u32[0] = *(uint32_t *)from;
+    chunk->u32[1] = chunk->u32[0];
 #else
     uint8_t *chunkptr = (uint8_t *)chunk;
     memcpy(chunkptr, from, 4);
@@ -36,8 +45,12 @@ static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) {
 }
 
 static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) {
-#ifdef UNALIGNED_OK
+#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];
 #else
     memcpy(chunk, from, sizeof(chunk_t));
 #endif
@@ -48,11 +61,13 @@ static inline void loadchunk(uint8_t const *s, chunk_t *chunk) {
 }
 
 static inline void storechunk(uint8_t *out, chunk_t *chunk) {
-#ifdef UNALIGNED_OK
+#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
-    /* Cast to chunk_t pointer to avoid compiler error on MSVC ARM */
-    memcpy((chunk_t *)out, chunk, sizeof(chunk_t ));
+    memcpy(out, chunk, sizeof(chunk_t));
 #endif
 }