]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Fix a bug on the 32k and greater chorba specializations
authorAdam Stylinski <kungfujesus06@gmail.com>
Tue, 25 Mar 2025 21:58:19 +0000 (17:58 -0400)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Fri, 28 Mar 2025 14:29:11 +0000 (15:29 +0100)
In testing a SIMD vectorization for this, I wrote a gtest which stumbled
onto the fact that this had a bug on big endian. Before the initial CRC
had been mixed in it needed to be byte swapped.

arch/generic/crc32_chorba_c.c
test/test_crc32.cc

index 35f8d410f260feeaedc0570a181211b4700585cc..604e39f8382cfdaba25677ba0f196b97d22890d2 100644 (file)
@@ -30,7 +30,12 @@ Z_INTERNAL uint32_t crc32_chorba_118960_nondestructive (uint32_t crc, const z_wo
 
     size_t i = 0;
 
+#if BYTE_ORDER == LITTLE_ENDIAN
     z_word_t next1 = crc;
+#else
+    z_word_t next1 = ZSWAP64(crc);
+#endif
+
     z_word_t next2 = 0;
     z_word_t next3 = 0;
     z_word_t next4 = 0;
@@ -484,7 +489,12 @@ Z_INTERNAL uint32_t crc32_chorba_32768_nondestructive (uint32_t crc, const uint6
     uint64_t bitbuffer[32768 / sizeof(uint64_t)];
     const uint8_t* bitbufferbytes = (const uint8_t*) bitbuffer;
     memset(bitbuffer, 0, 32768);
-    bitbuffer[0] ^= crc;
+#if BYTE_ORDER == LITTLE_ENDIAN
+    bitbuffer[0] = crc;
+#else
+    bitbuffer[0] = ZSWAP64(crc);
+#endif
+
     crc = 0;
 
     size_t i = 0;
@@ -634,9 +644,10 @@ Z_INTERNAL uint32_t crc32_chorba_32768_nondestructive (uint32_t crc, const uint6
 
     uint8_t* final_bytes = (uint8_t*) final;
 
-    for(size_t j = 0; j < (len-i); j++) {
+    for (size_t j = 0; j < (len-i); j++) {
         crc = crc_table[(crc ^ final_bytes[j] ^ bitbufferbytes[(j+i)]) & 0xff] ^ (crc >> 8);
     }
+
     return crc;
 }
 
index d2eb44d358d75af88165b1a835879355ebef0170..ee301ef6027b69aa27b38f63aaab1b6de86fa15e 100644 (file)
@@ -26,6 +26,19 @@ typedef struct {
     unsigned long expect;
 } crc32_test;
 
+ALIGNED_(16) uint8_t fullwin_buf[32768];
+
+uint8_t* setup_buf() {
+    for (int i = 0; i < 32768; ++i) {
+        unsigned char ic = (unsigned char)(i % 256);
+        fullwin_buf[i] = ic;
+    }
+
+    return fullwin_buf;
+}
+
+static uint8_t *buf32k = setup_buf();
+
 static const crc32_test tests[] = {
   {0x0, (const uint8_t *)0x0, 0, 0x0},
   {0xffffffff, (const uint8_t *)0x0, 0, 0x0},
@@ -179,7 +192,8 @@ static const crc32_test tests[] = {
     "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&"
     "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&"
     "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&"
-    "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 600, 0x888AFA5B}
+    "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 600, 0x888AFA5B},
+  {0x0, buf32k, 32768, 0x217726B2}
 };
 
 class crc32_variant : public ::testing::TestWithParam<crc32_test> {