[libFuzzer]Add a test for defeating a hash sum.
authorIvan Krasin <krasin@chromium.org>
Tue, 8 Sep 2015 21:22:52 +0000 (21:22 +0000)
committerIvan Krasin <krasin@chromium.org>
Tue, 8 Sep 2015 21:22:52 +0000 (21:22 +0000)
Summary:
Add a test for a data followed by 4-byte hash value.
I use a slightly modified Jenkins hash function,
as described in https://en.wikipedia.org/wiki/Jenkins_hash_function

The modification is to ensure that hash(zeros) != 0.

Reviewers: kcc

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D12648

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247076 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Fuzzer/test/CMakeLists.txt
lib/Fuzzer/test/SimpleHashTest.cpp [new file with mode: 0644]
lib/Fuzzer/test/fuzzer.test

index a9e65708edefdc596192e793d5a4ec73f69f9277..2e3081b896015e150bfe705b0ae6dacef933a4f5 100644 (file)
@@ -22,6 +22,7 @@ set(Tests
   NullDerefTest
   SimpleCmpTest
   SimpleDictionaryTest
+  SimpleHashTest
   SimpleTest
   StrcmpTest
   StrncmpTest
diff --git a/lib/Fuzzer/test/SimpleHashTest.cpp b/lib/Fuzzer/test/SimpleHashTest.cpp
new file mode 100644 (file)
index 0000000..a541d68
--- /dev/null
@@ -0,0 +1,36 @@
+// This test computes a checksum of the data (all but the last 4 bytes),
+// and then compares the last 4 bytes with the computed value.
+// A fuzzer with cmp traces is expected to defeat this check.
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+
+// A modified jenkins_one_at_a_time_hash initialized by non-zero,
+// so that simple_hash(0) != 0. See also
+// https://en.wikipedia.org/wiki/Jenkins_hash_function
+static uint32_t simple_hash(const uint8_t *Data, size_t Size) {
+  uint32_t Hash = 0x12039854;
+  for (uint32_t i = 0; i < Size; i++) {
+    Hash += Data[i];
+    Hash += (Hash << 10);
+    Hash ^= (Hash >> 6);
+  }
+  Hash += (Hash << 3);
+  Hash ^= (Hash >> 11);
+  Hash += (Hash << 15);
+  return Hash;
+}
+
+extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  if (Size < 14)
+    return;
+
+  uint32_t Hash = simple_hash(&Data[0], Size - 4);
+  uint32_t Want = reinterpret_cast<const uint32_t *>(&Data[Size - 4])[0];
+  if (Hash != Want)
+    return;
+  fprintf(stderr, "BINGO; simple_hash defeated: %x == %x\n", (unsigned int)Hash,
+          (unsigned int)Want);
+  exit(1);
+}
index d5bd9a39230fd26c0d92b69dfb99087c214ecbea..70dbce805542246d3b11775973aae96bf009627b 100644 (file)
@@ -40,3 +40,6 @@ RUN:     LLVMFuzzer-SwitchTest               -seed=1 -runs=1000000  2>&1 | FileC
 
 RUN: not LLVMFuzzer-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000000  2>&1 | FileCheck %s
 RUN:     LLVMFuzzer-SimpleDictionaryTest                    -seed=1 -runs=1000000  2>&1 | FileCheck %s --check-prefix=Done1000000
+
+RUN: not LLVMFuzzer-SimpleHashTest -use_traces=1 -seed=1 -runs=100000  2>&1 | FileCheck %s
+RUN:     LLVMFuzzer-SimpleHashTest               -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000