]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
[huf] Fix bug in fast C decoders
authorNick Terrell <terrelln@fb.com>
Thu, 26 Jan 2023 20:11:25 +0000 (12:11 -0800)
committerNick Terrell <nickrterrell@gmail.com>
Thu, 26 Jan 2023 22:39:13 +0000 (14:39 -0800)
The input bounds checks were buggy because they were only breaking from
the inner loop, not the outer loop. The fuzzers found this immediately.
The fix is to use `goto _out` instead of `break`.

This condition can happen on corrupted inputs.

I've benchmarked before and after on x86-64 and there were small changes
in performance, some positive, and some negative, and they end up about
balacing out.

Credit to  OSS-Fuzz

lib/decompress/huf_decompress.c

index 0a29f03d422e1249f69fc9c3b11db935fc92f9e2..c2d1f633a49d0a94e27d656dbcf46fa13dd79d52 100644 (file)
@@ -742,7 +742,7 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
              */
             for (stream = 1; stream < 4; ++stream) {
                 if (ip[stream] < ip[stream - 1])
-                    break;
+                    goto _out;
             }
         }
 
@@ -775,6 +775,8 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
         } while (op[3] < olimit);
     }
 
+_out:
+
     /* Save the final values of each of the state variables back to args. */
     ZSTD_memcpy(&args->bits, &bits, sizeof(bits));
     ZSTD_memcpy(&args->ip, &ip, sizeof(ip));
@@ -1535,7 +1537,7 @@ void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
              */
             for (stream = 1; stream < 4; ++stream) {
                 if (ip[stream] < ip[stream - 1])
-                    break;
+                    goto _out;
             }
         }
 
@@ -1593,6 +1595,8 @@ void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
         } while (op[3] < olimit);
     }
 
+_out:
+
     /* Save the final values of each of the state variables back to args. */
     ZSTD_memcpy(&args->bits, &bits, sizeof(bits));
     ZSTD_memcpy(&args->ip, &ip, sizeof(ip));