about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-09-05 15:49:10 +0200
committervan Hauser <vh@thc.org>2020-09-05 15:49:10 +0200
commit250892228888277262958d1b01b005e14440274e (patch)
tree1cb4f890b706af58bd4fe7439a69ee3b73095276
parent39c020ec747a21fd4728f363fef63a75973aa646 (diff)
downloadafl++-250892228888277262958d1b01b005e14440274e.tar.gz
cmp dict for LTO
-rw-r--r--GNUmakefile2
-rw-r--r--docs/Changelog.md3
-rw-r--r--include/xxhash.h39
-rw-r--r--instrumentation/SanitizerCoverageLTO.so.cc93
-rw-r--r--instrumentation/afl-llvm-lto-instrumentation.so.cc93
5 files changed, 214 insertions, 16 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 7455483c..bcdc10eb 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -533,7 +533,7 @@ endif
 deepclean:	clean
 	rm -rf qemu_mode/qemu-3.1.1.tar.xz
 	rm -rf unicorn_mode/unicornafl
-	# NEVER EVER ACTIVATE THAT!!!!! git reset --hard >/dev/null 2>&1 || true
+# NEVER EVER ACTIVATE THAT!!!!! git reset --hard >/dev/null 2>&1 || true
 
 .PHONY: distrib
 distrib: all
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 9de03e78..f86c0b61 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -18,9 +18,10 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
     - allow up to 4 -x command line options
     - loaded extras now have a duplicate protection
   - instrumentation
+    - not overriding -Ox or -fno-unroll-loops anymore
     - new llvm pass: dict2file via AFL_LLVM_DICT2FILE, create afl-fuzz
       -x dictionary of string comparisons found during compilation
-    - not overriding -Ox or -fno-unroll-loops anymore
+    - LTO autodict now also collects interesting cmp comparisons
 
 
 ### Version ++2.68c (release)
diff --git a/include/xxhash.h b/include/xxhash.h
index 0472f881..006d3f3d 100644
--- a/include/xxhash.h
+++ b/include/xxhash.h
@@ -660,7 +660,7 @@ XXH128_hashFromCanonical(const XXH128_canonical_t *src);
  * These declarations should only be used with static linking.
  * Never use them in association with dynamic linking!
  *****************************************************************************
-*/
+ */
 
 /*
  * These definitions are only present to allow static allocation
@@ -1189,7 +1189,7 @@ static int XXH_isLittleEndian(void) {
   return one.c[0];
 
 }
-\
+
       #define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian()
     #endif
   #endif
@@ -1397,7 +1397,9 @@ static xxh_u32 XXH32_avalanche(xxh_u32 h32) {
 
 static xxh_u32 XXH32_finalize(xxh_u32 h32, const xxh_u8 *ptr, size_t len,
                               XXH_alignment align) {
-\
+
+  /* dummy comment */
+
   #define XXH_PROCESS1                           \
     do {                                         \
                                                  \
@@ -1950,16 +1952,21 @@ XXH_FORCE_INLINE xxh_u64 XXH_readLE64_align(const void *  ptr,
 
 /*******   xxh64   *******/
 
-static const xxh_u64 XXH_PRIME64_1 = 0x9E3779B185EBCA87ULL; /* 0b1001111000110111011110011011000110000101111010111100101010000111
-                                                             */
-static const xxh_u64 XXH_PRIME64_2 = 0xC2B2AE3D27D4EB4FULL; /* 0b1100001010110010101011100011110100100111110101001110101101001111
-                                                             */
-static const xxh_u64 XXH_PRIME64_3 = 0x165667B19E3779F9ULL; /* 0b0001011001010110011001111011000110011110001101110111100111111001
-                                                             */
-static const xxh_u64 XXH_PRIME64_4 = 0x85EBCA77C2B2AE63ULL; /* 0b1000010111101011110010100111011111000010101100101010111001100011
-                                                             */
-static const xxh_u64 XXH_PRIME64_5 = 0x27D4EB2F165667C5ULL; /* 0b0010011111010100111010110010111100010110010101100110011111000101
-                                                             */
+static const xxh_u64 XXH_PRIME64_1 =
+    0x9E3779B185EBCA87ULL; /* 0b1001111000110111011110011011000110000101111010111100101010000111
+                            */
+static const xxh_u64 XXH_PRIME64_2 =
+    0xC2B2AE3D27D4EB4FULL; /* 0b1100001010110010101011100011110100100111110101001110101101001111
+                            */
+static const xxh_u64 XXH_PRIME64_3 =
+    0x165667B19E3779F9ULL; /* 0b0001011001010110011001111011000110011110001101110111100111111001
+                            */
+static const xxh_u64 XXH_PRIME64_4 =
+    0x85EBCA77C2B2AE63ULL; /* 0b1000010111101011110010100111011111000010101100101010111001100011
+                            */
+static const xxh_u64 XXH_PRIME64_5 =
+    0x27D4EB2F165667C5ULL; /* 0b0010011111010100111010110010111100010110010101100110011111000101
+                            */
 
     #ifdef XXH_OLD_NAMES
       #define PRIME64_1 XXH_PRIME64_1
@@ -2002,7 +2009,9 @@ static xxh_u64 XXH64_avalanche(xxh_u64 h64) {
 
 static xxh_u64 XXH64_finalize(xxh_u64 h64, const xxh_u8 *ptr, size_t len,
                               XXH_alignment align) {
-\
+
+    /* dummy comment */
+
     #define XXH_PROCESS1_64                        \
       do {                                         \
                                                    \
@@ -2752,6 +2761,7 @@ XXH64_hashFromCanonical(const XXH64_canonical_t *src) {
             (outHi) = vget_high_u32(vreinterpretq_u32_u64(in));                                        \
                                                                                                        \
           } while (0)
+
       #else
         #define XXH_SPLIT_IN_PLACE(in, outLo, outHi) \
           do {                                       \
@@ -2760,6 +2770,7 @@ XXH64_hashFromCanonical(const XXH64_canonical_t *src) {
             (outHi) = vshrn_n_u64((in), 32);         \
                                                      \
           } while (0)
+
       #endif
     #endif                                        /* XXH_VECTOR == XXH_NEON */
 
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index 1dd65188..f4958d80 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -12,6 +12,7 @@
 #include <string>
 #include <fstream>
 #include <set>
+#include <iostream>
 
 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -249,6 +250,7 @@ class ModuleSanitizerCoverage {
   GlobalVariable *                 AFLMapPtr = NULL;
   Value *                          MapPtrFixed = NULL;
   FILE *                           documentFile = NULL;
+  size_t                           found = 0;
   // afl++ END
 
 };
@@ -513,6 +515,92 @@ bool ModuleSanitizerCoverage::instrumentModule(
         for (auto &IN : BB) {
 
           CallInst *callInst = nullptr;
+          CmpInst * cmpInst = nullptr;
+
+          if ((cmpInst = dyn_cast<CmpInst>(&IN))) {
+
+            Value *      op = cmpInst->getOperand(1);
+            ConstantInt *ilen = dyn_cast<ConstantInt>(op);
+
+            if (ilen) {
+
+              u64 val2 = 0, val = ilen->getZExtValue();
+              u32 len = 0;
+              if (val > 0x10000 && val < 0xffffffff) len = 4;
+              if (val > 0x100000001 && val < 0xffffffffffffffff) len = 8;
+
+              if (len) {
+
+                auto c = cmpInst->getPredicate();
+
+                switch (c) {
+
+                  case CmpInst::FCMP_OGT:  // fall through
+                  case CmpInst::FCMP_OLE:  // fall through
+                  case CmpInst::ICMP_SLE:  // fall through
+                  case CmpInst::ICMP_SGT:
+
+                    // signed comparison and it is a negative constant
+                    if ((len == 4 && (val & 80000000)) ||
+                        (len == 8 && (val & 8000000000000000))) {
+
+                      if ((val & 0xffff) != 1) val2 = val - 1;
+                      break;
+
+                    }
+
+                    // fall through
+
+                  case CmpInst::FCMP_UGT:  // fall through
+                  case CmpInst::FCMP_ULE:  // fall through
+                  case CmpInst::ICMP_UGT:  // fall through
+                  case CmpInst::ICMP_ULE:
+                    if ((val & 0xffff) != 0xfffe) val2 = val + 1;
+                    break;
+
+                  case CmpInst::FCMP_OLT:  // fall through
+                  case CmpInst::FCMP_OGE:  // fall through
+                  case CmpInst::ICMP_SLT:  // fall through
+                  case CmpInst::ICMP_SGE:
+
+                    // signed comparison and it is a negative constant
+                    if ((len == 4 && (val & 80000000)) ||
+                        (len == 8 && (val & 8000000000000000))) {
+
+                      if ((val & 0xffff) != 1) val2 = val - 1;
+                      break;
+
+                    }
+
+                    // fall through
+
+                  case CmpInst::FCMP_ULT:  // fall through
+                  case CmpInst::FCMP_UGE:  // fall through
+                  case CmpInst::ICMP_ULT:  // fall through
+                  case CmpInst::ICMP_UGE:
+                    if ((val & 0xffff) != 1) val2 = val - 1;
+                    break;
+
+                  default:
+                    val2 = 0;
+
+                }
+
+                dictionary.push_back(std::string((char *)&val, len));
+                found++;
+
+                if (val2) {
+
+                  dictionary.push_back(std::string((char *)&val2, len));
+                  found++;
+
+                }
+
+              }
+
+            }
+
+          }
 
           if ((callInst = dyn_cast<CallInst>(&IN))) {
 
@@ -917,6 +1005,11 @@ bool ModuleSanitizerCoverage::instrumentModule(
       size_t memlen = 0, count = 0, offset = 0;
       char * ptr;
 
+      // sort and unique the dictionary
+      std::sort(dictionary.begin(), dictionary.end());
+      auto last = std::unique(dictionary.begin(), dictionary.end());
+      dictionary.erase(last, dictionary.end());
+
       for (auto token : dictionary) {
 
         memlen += token.length();
diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc
index 125db229..9632c319 100644
--- a/instrumentation/afl-llvm-lto-instrumentation.so.cc
+++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc
@@ -31,6 +31,7 @@
 #include <string>
 #include <fstream>
 #include <set>
+#include <iostream>
 
 #include "llvm/Config/llvm-config.h"
 #include "llvm/ADT/Statistic.h"
@@ -106,6 +107,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
   std::vector<BasicBlock *>        BlockList;
   char *                           ptr;
   FILE *                           documentFile = NULL;
+  size_t                           found = 0;
 
   srand((unsigned int)time(NULL));
 
@@ -284,6 +286,92 @@ bool AFLLTOPass::runOnModule(Module &M) {
         for (auto &IN : BB) {
 
           CallInst *callInst = nullptr;
+          CmpInst * cmpInst = nullptr;
+
+          if ((cmpInst = dyn_cast<CmpInst>(&IN))) {
+
+            Value *      op = cmpInst->getOperand(1);
+            ConstantInt *ilen = dyn_cast<ConstantInt>(op);
+
+            if (ilen) {
+
+              u64 val2 = 0, val = ilen->getZExtValue();
+              u32 len = 0;
+              if (val > 0x10000 && val < 0xffffffff) len = 4;
+              if (val > 0x100000001 && val < 0xffffffffffffffff) len = 8;
+
+              if (len) {
+
+                auto c = cmpInst->getPredicate();
+
+                switch (c) {
+
+                  case CmpInst::FCMP_OGT:  // fall through
+                  case CmpInst::FCMP_OLE:  // fall through
+                  case CmpInst::ICMP_SLE:  // fall through
+                  case CmpInst::ICMP_SGT:
+
+                    // signed comparison and it is a negative constant
+                    if ((len == 4 && (val & 80000000)) ||
+                        (len == 8 && (val & 8000000000000000))) {
+
+                      if ((val & 0xffff) != 1) val2 = val - 1;
+                      break;
+
+                    }
+
+                    // fall through
+
+                  case CmpInst::FCMP_UGT:  // fall through
+                  case CmpInst::FCMP_ULE:  // fall through
+                  case CmpInst::ICMP_UGT:  // fall through
+                  case CmpInst::ICMP_ULE:
+                    if ((val & 0xffff) != 0xfffe) val2 = val + 1;
+                    break;
+
+                  case CmpInst::FCMP_OLT:  // fall through
+                  case CmpInst::FCMP_OGE:  // fall through
+                  case CmpInst::ICMP_SLT:  // fall through
+                  case CmpInst::ICMP_SGE:
+
+                    // signed comparison and it is a negative constant
+                    if ((len == 4 && (val & 80000000)) ||
+                        (len == 8 && (val & 8000000000000000))) {
+
+                      if ((val & 0xffff) != 1) val2 = val - 1;
+                      break;
+
+                    }
+
+                    // fall through
+
+                  case CmpInst::FCMP_ULT:  // fall through
+                  case CmpInst::FCMP_UGE:  // fall through
+                  case CmpInst::ICMP_ULT:  // fall through
+                  case CmpInst::ICMP_UGE:
+                    if ((val & 0xffff) != 1) val2 = val - 1;
+                    break;
+
+                  default:
+                    val2 = 0;
+
+                }
+
+                dictionary.push_back(std::string((char *)&val, len));
+                found++;
+
+                if (val2) {
+
+                  dictionary.push_back(std::string((char *)&val2, len));
+                  found++;
+
+                }
+
+              }
+
+            }
+
+          }
 
           if ((callInst = dyn_cast<CallInst>(&IN))) {
 
@@ -842,6 +930,11 @@ bool AFLLTOPass::runOnModule(Module &M) {
       size_t memlen = 0, count = 0, offset = 0;
       char * ptr;
 
+      // sort and unique the dictionary
+      std::sort(dictionary.begin(), dictionary.end());
+      auto last = std::unique(dictionary.begin(), dictionary.end());
+      dictionary.erase(last, dictionary.end());
+
       for (auto token : dictionary) {
 
         memlen += token.length();