about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile1
-rw-r--r--llvm_mode/afl-clang-fast.c8
-rw-r--r--llvm_mode/compare-transform-pass.so.cc143
-rw-r--r--test/test-compcov.c15
-rw-r--r--test/test-custom-mutator.c19
-rw-r--r--test/test-unsigaction.c50
6 files changed, 185 insertions, 51 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 00b357f9..a3ac2e06 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -360,6 +360,7 @@ code-format:
 	./.custom-format.py -i gcc_plugin/*.cc
 	./.custom-format.py -i examples/*/*.c
 	./.custom-format.py -i examples/*/*.h
+	./.custom-format.py -i test/*.c
 	./.custom-format.py -i qemu_mode/patches/*.h
 	./.custom-format.py -i qemu_mode/libcompcov/*.c
 	./.custom-format.py -i qemu_mode/libcompcov/*.cc
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index 2114ccf3..080c7838 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -401,9 +401,11 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
   }
 
-  if (getenv("AFL_NO_BUILTIN") || (instrument_mode == INSTRUMENT_LTO &&
-                                   (getenv("AFL_LLVM_LTO_AUTODICTIONARY") ||
-                                    getenv("AFL_LLVM_AUTODICTIONARY")))) {
+  if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
+      getenv("LAF_TRANSFORM_COMPARES") ||
+      (instrument_mode == INSTRUMENT_LTO &&
+       (getenv("AFL_LLVM_LTO_AUTODICTIONARY") ||
+        getenv("AFL_LLVM_AUTODICTIONARY")))) {
 
     cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
     cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc
index 2ca70659..84a9b8d9 100644
--- a/llvm_mode/compare-transform-pass.so.cc
+++ b/llvm_mode/compare-transform-pass.so.cc
@@ -112,11 +112,12 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
                                      const bool processStrcasecmp,
                                      const bool processStrncasecmp) {
 
-  std::vector<CallInst *> calls;
-  LLVMContext &           C = M.getContext();
-  IntegerType *           Int8Ty = IntegerType::getInt8Ty(C);
-  IntegerType *           Int32Ty = IntegerType::getInt32Ty(C);
-  IntegerType *           Int64Ty = IntegerType::getInt64Ty(C);
+  DenseMap<Value *, std::string *> valueMap;
+  std::vector<CallInst *>          calls;
+  LLVMContext &                    C = M.getContext();
+  IntegerType *                    Int8Ty = IntegerType::getInt8Ty(C);
+  IntegerType *                    Int32Ty = IntegerType::getInt32Ty(C);
+  IntegerType *                    Int64Ty = IntegerType::getInt64Ty(C);
 
 #if LLVM_VERSION_MAJOR < 9
   Constant *
@@ -263,6 +264,8 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
           bool isStrncmp = processStrncmp;
           bool isStrcasecmp = processStrcasecmp;
           bool isStrncasecmp = processStrncasecmp;
+          bool isIntMemcpy = true;
+          bool indirect = false;
 
           Function *Callee = callInst->getCalledFunction();
           if (!Callee) continue;
@@ -273,9 +276,10 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
           isStrncmp &= !FuncName.compare(StringRef("strncmp"));
           isStrcasecmp &= !FuncName.compare(StringRef("strcasecmp"));
           isStrncasecmp &= !FuncName.compare(StringRef("strncasecmp"));
+          isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
 
           if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
-              !isStrncasecmp)
+              !isStrncasecmp && !isIntMemcpy)
             continue;
 
           /* Verify the strcmp/memcmp/strncmp/strcasecmp/strncasecmp function
@@ -309,7 +313,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
                            FT->getParamType(2)->isIntegerTy();
 
           if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
-              !isStrncasecmp)
+              !isStrncasecmp && !isIntMemcpy)
             continue;
 
           /* is a str{n,}{case,}cmp/memcmp, check if we have
@@ -322,6 +326,97 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
           bool      HasStr1 = getConstantStringInfo(Str1P, Str1);
           bool      HasStr2 = getConstantStringInfo(Str2P, Str2);
 
+          if (isIntMemcpy && HasStr2) {
+
+            valueMap[Str1P] = new std::string(Str2.str());
+            // fprintf(stderr, "saved %s for %p\n", Str2.str().c_str(), Str1P);
+            continue;
+
+          }
+
+          // not literal? maybe global or local variable
+          if (!(HasStr1 ^ HasStr2)) {
+
+            auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
+            if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
+
+              if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
+
+                if (auto *Array =
+                        dyn_cast<ConstantDataArray>(Var->getInitializer())) {
+
+                  HasStr2 = true;
+                  Str2 = Array->getAsString();
+                  valueMap[Str2P] = new std::string(Str2.str());
+                  // fprintf(stderr, "glo2 %s\n", Str2.str().c_str());
+
+                }
+
+              }
+
+            }
+
+            if (!HasStr2) {
+
+              auto *Ptr = dyn_cast<ConstantExpr>(Str1P);
+              if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
+
+                if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
+
+                  if (auto *Array =
+                          dyn_cast<ConstantDataArray>(Var->getInitializer())) {
+
+                    HasStr1 = true;
+                    Str1 = Array->getAsString();
+                    valueMap[Str1P] = new std::string(Str1.str());
+                    // fprintf(stderr, "glo1 %s\n", Str1.str().c_str());
+
+                  }
+
+                }
+
+              }
+
+            } else if (isIntMemcpy) {
+
+              valueMap[Str1P] = new std::string(Str2.str());
+              // fprintf(stderr, "saved\n");
+
+            }
+
+            if ((HasStr1 ^ HasStr2)) indirect = true;
+
+          }
+
+          if (isIntMemcpy) continue;
+
+          if (!(HasStr1 ^ HasStr2)) {
+
+            // do we have a saved local variable initialization?
+            std::string *val = valueMap[Str1P];
+            if (val && !val->empty()) {
+
+              Str1 = StringRef(*val);
+              HasStr1 = true;
+              indirect = true;
+              // fprintf(stderr, "loaded1 %s\n", Str1.str().c_str());
+
+            } else {
+
+              val = valueMap[Str2P];
+              if (val && !val->empty()) {
+
+                Str2 = StringRef(*val);
+                HasStr2 = true;
+                indirect = true;
+                // fprintf(stderr, "loaded2 %s\n", Str2.str().c_str());
+
+              }
+
+            }
+
+          }
+
           /* handle cases of one string is const, one string is variable */
           if (!(HasStr1 ^ HasStr2)) continue;
 
@@ -334,9 +429,8 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
             if (!ilen) continue;
             /* final precaution: if size of compare is larger than constant
              * string skip it*/
-            uint64_t literalLength =
-                HasStr1 ? GetStringLength(Str1P) : GetStringLength(Str2P);
-            if (literalLength < ilen->getZExtValue()) continue;
+            uint64_t literalLength = HasStr1 ? Str1.size() : Str2.size();
+            if (literalLength + 1 < ilen->getZExtValue()) continue;
 
           }
 
@@ -363,9 +457,9 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
     std::string TmpConstStr;
     Value *     VarStr;
     bool        HasStr1 = getConstantStringInfo(Str1P, Str1);
-    getConstantStringInfo(Str2P, Str2);
-    uint64_t constLen, sizedLen;
-    bool     isMemcmp =
+    bool        HasStr2 = getConstantStringInfo(Str2P, Str2);
+    uint64_t    constLen, sizedLen;
+    bool        isMemcmp =
         !callInst->getCalledFunction()->getName().compare(StringRef("memcmp"));
     bool isSizedcmp = isMemcmp ||
                       !callInst->getCalledFunction()->getName().compare(
@@ -389,6 +483,29 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
 
     }
 
+    if (!(HasStr1 ^ HasStr2)) {
+
+      // do we have a saved local or global variable initialization?
+      std::string *val = valueMap[Str1P];
+      if (val && !val->empty()) {
+
+        Str1 = StringRef(*val);
+        HasStr1 = true;
+
+      } else {
+
+        val = valueMap[Str2P];
+        if (val && !val->empty()) {
+
+          Str2 = StringRef(*val);
+          HasStr2 = true;
+
+        }
+
+      }
+
+    }
+
     if (HasStr1) {
 
       TmpConstStr = Str1.str();
diff --git a/test/test-compcov.c b/test/test-compcov.c
index fff9c759..f1743265 100644
--- a/test/test-compcov.c
+++ b/test/test-compcov.c
@@ -6,27 +6,33 @@
 char global_cmpval[] = "GLOBALVARIABLE";
 
 int main(int argc, char **argv) {
+
   char *input = argv[1], *buf, buffer[20];
-  char cmpval[] = "LOCALVARIABLE";
-  char shortval[4] = "abc";
+  char  cmpval[] = "LOCALVARIABLE";
+  char  shortval[4] = "abc";
 
   if (argc < 2) {
+
     ssize_t ret = read(0, buffer, sizeof(buffer) - 1);
     buffer[ret] = 0;
     input = buffer;
+
   }
-  
+
   if (strcmp(input, "LIBTOKENCAP") == 0)
     printf("your string was libtokencap\n");
   else if (strcmp(input, "BUGMENOT") == 0)
     printf("your string was bugmenot\n");
   else if (strcmp(input, "BUFFEROVERFLOW") == 0) {
+
     buf = malloc(16);
     strcpy(buf, "TEST");
     strcat(buf, input);
     printf("This will only crash with libdislocator: %s\n", buf);
     return 0;
-  } else if (*(unsigned int*)input == 0xabadcafe)
+
+  } else if (*(unsigned int *)input == 0xabadcafe)
+
     printf("GG you eat cmp tokens for breakfast!\n");
   else if (memcmp(cmpval, input, 8) == 0)
     printf("local var memcmp works!\n");
@@ -40,3 +46,4 @@ int main(int argc, char **argv) {
   return 0;
 
 }
+
diff --git a/test/test-custom-mutator.c b/test/test-custom-mutator.c
index 83baafab..f868550c 100644
--- a/test/test-custom-mutator.c
+++ b/test/test-custom-mutator.c
@@ -1,5 +1,6 @@
 /**
- * Reference: https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/blob/master/4_libprotobuf_aflpp_custom_mutator/vuln.c
+ * Reference:
+ * https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/blob/master/4_libprotobuf_aflpp_custom_mutator/vuln.c
  */
 
 #include <stdio.h>
@@ -8,12 +9,12 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-int main(int argc, char *argv[])
-{
-    char str[100];
-    read(0, str, 100);
-    if( str[6] == 'A') {
-        abort();
-    }
-    return 0;
+int main(int argc, char *argv[]) {
+
+  char str[100];
+  read(0, str, 100);
+  if (str[6] == 'A') { abort(); }
+  return 0;
+
 }
+
diff --git a/test/test-unsigaction.c b/test/test-unsigaction.c
index 1a5e4b26..8c6c7f41 100644
--- a/test/test-unsigaction.c
+++ b/test/test-unsigaction.c
@@ -1,25 +1,31 @@
-#include <signal.h> /* sigemptyset(), sigaction(), kill(), SIGUSR1 */
-#include <stdlib.h> /* exit() */
-#include <unistd.h> /* getpid() */
-#include <errno.h> /* errno */
-#include <stdio.h> /* fprintf() */
-
-static void mysig_handler(int sig)
-{
-	exit(2);
+#include <signal.h>          /* sigemptyset(), sigaction(), kill(), SIGUSR1 */
+#include <stdlib.h>                                               /* exit() */
+#include <unistd.h>                                             /* getpid() */
+#include <errno.h>                                                 /* errno */
+#include <stdio.h>                                             /* fprintf() */
+
+static void mysig_handler(int sig) {
+
+  exit(2);
+
 }
 
-int main()
-{
-	/* setup sig handler */
-	struct sigaction sa;
-       	sa.sa_handler = mysig_handler;
-	sigemptyset(&sa.sa_mask);
-        sa.sa_flags = 0;	
-	if (sigaction(SIGCHLD, &sa, NULL)) {
-		fprintf(stderr, "could not set signal handler %d, aborted\n", errno);
-		exit(1);
-	}
-	kill(getpid(), SIGCHLD);
-	return 0;
+int main() {
+
+  /* setup sig handler */
+  struct sigaction sa;
+  sa.sa_handler = mysig_handler;
+  sigemptyset(&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction(SIGCHLD, &sa, NULL)) {
+
+    fprintf(stderr, "could not set signal handler %d, aborted\n", errno);
+    exit(1);
+
+  }
+
+  kill(getpid(), SIGCHLD);
+  return 0;
+
 }
+