about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--docs/Changelog.md2
-rw-r--r--instrumentation/afl-compiler-rt.o.c69
-rw-r--r--instrumentation/cmplog-routines-pass.cc216
-rw-r--r--src/afl-fuzz-init.c2
4 files changed, 281 insertions, 8 deletions
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 97f816b6..062dd785 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -32,6 +32,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
     - fixed endless loop for allow/blocklist lines starting with a
       comment (thanks to Zherya for reporting)
     - cmplog/redqueen now also tracks floating point, _ExtInt() + 128bit
+    - cmplog/redqueen can now process basic libc++ and libstdc++
+      std::string comparisons (though no position or length type variants)
     - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard
       support (less performant than our own), GCC for old afl-gcc and
       CLANG for old afl-clang
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index 14da4caa..433a1d89 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -1549,10 +1549,10 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
     u32 i;
     if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return;
     fprintf(stderr, "rtn arg0=");
-    for (i = 0; i < 8; i++)
+    for (i = 0; i < 24; i++)
       fprintf(stderr, "%02x", ptr1[i]);
     fprintf(stderr, " arg1=");
-    for (i = 0; i < 8; i++)
+    for (i = 0; i < 24; i++)
       fprintf(stderr, "%02x", ptr2[i]);
     fprintf(stderr, "\n");
   */
@@ -1594,6 +1594,71 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
 
 }
 
+// gcc libstdc++
+// _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE7compareEPKc
+static u8 *get_gcc_stdstring(u8 *string) {
+
+  u32 *len = (u32 *)(string + 8);
+
+  if (*len < 16) {  // in structure
+
+    return (string + 16);
+
+  } else {  // in memory
+
+    u8 **ptr = (u8 **)string;
+    return (*ptr);
+
+  }
+
+}
+
+// llvm libc++ _ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocator
+//             IcEEE7compareEmmPKcm
+static u8 *get_llvm_stdstring(u8 *string) {
+
+  // length is in: if ((string[0] & 1) == 0) u8 len = (string[0] >> 1);
+  // or: if (string[0] & 1) u32 *len = (u32 *) (string + 8);
+
+  if (string[0] & 1) {  // in memory
+
+    u8 **ptr = (u8 **)(string + 16);
+    return (*ptr);
+
+  } else {  // in structure
+
+    return (string + 1);
+
+  }
+
+}
+
+void __cmplog_rtn_gcc_stdstring_cstring(u8 *stdstring, u8 *cstring) {
+
+  __cmplog_rtn_hook(get_gcc_stdstring(stdstring), cstring);
+
+}
+
+void __cmplog_rtn_gcc_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) {
+
+  __cmplog_rtn_hook(get_gcc_stdstring(stdstring1),
+                    get_gcc_stdstring(stdstring2));
+
+}
+
+void __cmplog_rtn_llvm_stdstring_cstring(u8 *stdstring, u8 *cstring) {
+
+  __cmplog_rtn_hook(get_llvm_stdstring(stdstring), cstring);
+
+}
+
+void __cmplog_rtn_llvm_stdstring_stdstring(u8 *stdstring1, u8 *stdstring2) {
+
+  __cmplog_rtn_hook(get_llvm_stdstring(stdstring1),
+                    get_llvm_stdstring(stdstring2));
+
+}
+
 /* COVERAGE manipulation features */
 
 // this variable is then used in the shm setup to create an additional map
diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc
index e92883ae..a5992c9a 100644
--- a/instrumentation/cmplog-routines-pass.cc
+++ b/instrumentation/cmplog-routines-pass.cc
@@ -87,7 +87,7 @@ char CmpLogRoutines::ID = 0;
 
 bool CmpLogRoutines::hookRtns(Module &M) {
 
-  std::vector<CallInst *> calls;
+  std::vector<CallInst *> calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC;
   LLVMContext &           C = M.getContext();
 
   Type *VoidTy = Type::getVoidTy(C);
@@ -112,6 +112,78 @@ bool CmpLogRoutines::hookRtns(Module &M) {
   FunctionCallee cmplogHookFn = c;
 #endif
 
+#if LLVM_VERSION_MAJOR < 9
+  Constant *
+#else
+  FunctionCallee
+#endif
+      c1 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_stdstring",
+                                 VoidTy, i8PtrTy, i8PtrTy
+#if LLVM_VERSION_MAJOR < 5
+                                 ,
+                                 NULL
+#endif
+      );
+#if LLVM_VERSION_MAJOR < 9
+  Function *cmplogLlvmStdStd = cast<Function>(c1);
+#else
+  FunctionCallee cmplogLlvmStdStd = c1;
+#endif
+
+#if LLVM_VERSION_MAJOR < 9
+  Constant *
+#else
+  FunctionCallee
+#endif
+      c2 = M.getOrInsertFunction("__cmplog_rtn_llvm_stdstring_cstring", VoidTy,
+                                 i8PtrTy, i8PtrTy
+#if LLVM_VERSION_MAJOR < 5
+                                 ,
+                                 NULL
+#endif
+      );
+#if LLVM_VERSION_MAJOR < 9
+  Function *cmplogLlvmStdC = cast<Function>(c2);
+#else
+  FunctionCallee cmplogLlvmStdC = c2;
+#endif
+
+#if LLVM_VERSION_MAJOR < 9
+  Constant *
+#else
+  FunctionCallee
+#endif
+      c3 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_stdstring", VoidTy,
+                                 i8PtrTy, i8PtrTy
+#if LLVM_VERSION_MAJOR < 5
+                                 ,
+                                 NULL
+#endif
+      );
+#if LLVM_VERSION_MAJOR < 9
+  Function *cmplogGccStdStd = cast<Function>(c3);
+#else
+  FunctionCallee cmplogGccStdStd = c3;
+#endif
+
+#if LLVM_VERSION_MAJOR < 9
+  Constant *
+#else
+  FunctionCallee
+#endif
+      c4 = M.getOrInsertFunction("__cmplog_rtn_gcc_stdstring_cstring", VoidTy,
+                                 i8PtrTy, i8PtrTy
+#if LLVM_VERSION_MAJOR < 5
+                                 ,
+                                 NULL
+#endif
+      );
+#if LLVM_VERSION_MAJOR < 9
+  Function *cmplogGccStdC = cast<Function>(c4);
+#else
+  FunctionCallee cmplogGccStdC = c4;
+#endif
+
   /* iterate over all functions, bbs and instruction and add suitable calls */
   for (auto &F : M) {
 
@@ -136,9 +208,64 @@ bool CmpLogRoutines::hookRtns(Module &M) {
                           FT->getParamType(0) == FT->getParamType(1) &&
                           FT->getParamType(0)->isPointerTy();
 
-          if (!isPtrRtn) continue;
-
-          calls.push_back(callInst);
+          bool isGccStdStringStdString =
+              Callee->getName().find("__is_charIT_EE7__value") !=
+                  std::string::npos &&
+              Callee->getName().find(
+                  "St7__cxx1112basic_stringIS2_St11char_traits") !=
+                  std::string::npos &&
+              FT->getNumParams() >= 2 &&
+              FT->getParamType(0) == FT->getParamType(1) &&
+              FT->getParamType(0)->isPointerTy();
+
+          bool isGccStdStringCString =
+              Callee->getName().find(
+                  "St7__cxx1112basic_stringIcSt11char_"
+                  "traitsIcESaIcEE7compareEPK") != std::string::npos &&
+              FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() &&
+              FT->getParamType(1)->isPointerTy();
+
+          bool isLlvmStdStringStdString =
+              Callee->getName().find("_ZNSt3__1eqI") != std::string::npos &&
+              Callee->getName().find("_12basic_stringI") != std::string::npos &&
+              Callee->getName().find("_11char_traits") != std::string::npos &&
+              FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() &&
+              FT->getParamType(1)->isPointerTy();
+
+          bool isLlvmStdStringCString =
+              Callee->getName().find("_ZNSt3__1eqI") != std::string::npos &&
+              Callee->getName().find("_12basic_stringI") != std::string::npos &&
+              FT->getNumParams() >= 2 && FT->getParamType(0)->isPointerTy() &&
+              FT->getParamType(1)->isPointerTy();
+
+          /*
+                    {
+
+                       fprintf(stderr, "F:%s C:%s argc:%u\n",
+                       F.getName().str().c_str(),
+             Callee->getName().str().c_str(), FT->getNumParams());
+                       fprintf(stderr, "ptr0:%u ptr1:%u ptr2:%u\n",
+                              FT->getParamType(0)->isPointerTy(),
+                              FT->getParamType(1)->isPointerTy(),
+                              FT->getNumParams() > 2 ?
+             FT->getParamType(2)->isPointerTy() : 22 );
+
+                    }
+
+          */
+
+          if (isGccStdStringCString || isGccStdStringStdString ||
+              isLlvmStdStringStdString || isLlvmStdStringCString) {
+
+            isPtrRtn = false;
+
+          }
+
+          if (isPtrRtn) { calls.push_back(callInst); }
+          if (isGccStdStringStdString) { gccStdStd.push_back(callInst); }
+          if (isGccStdStringCString) { gccStdC.push_back(callInst); }
+          if (isLlvmStdStringStdString) { llvmStdStd.push_back(callInst); }
+          if (isLlvmStdStringCString) { llvmStdC.push_back(callInst); }
 
         }
 
@@ -148,7 +275,10 @@ bool CmpLogRoutines::hookRtns(Module &M) {
 
   }
 
-  if (!calls.size()) return false;
+  if (!calls.size() && !gccStdStd.size() && !gccStdC.size() &&
+      !llvmStdStd.size() && !llvmStdC.size())
+    return false;
+
   /*
     if (!be_quiet)
       errs() << "Hooking " << calls.size()
@@ -174,6 +304,82 @@ bool CmpLogRoutines::hookRtns(Module &M) {
 
   }
 
+  for (auto &callInst : gccStdStd) {
+
+    Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
+
+    IRBuilder<> IRB(callInst->getParent());
+    IRB.SetInsertPoint(callInst);
+
+    std::vector<Value *> args;
+    Value *              v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
+    Value *              v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
+    args.push_back(v1Pcasted);
+    args.push_back(v2Pcasted);
+
+    IRB.CreateCall(cmplogGccStdStd, args);
+
+    // errs() << callInst->getCalledFunction()->getName() << "\n";
+
+  }
+
+  for (auto &callInst : gccStdC) {
+
+    Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
+
+    IRBuilder<> IRB(callInst->getParent());
+    IRB.SetInsertPoint(callInst);
+
+    std::vector<Value *> args;
+    Value *              v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
+    Value *              v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
+    args.push_back(v1Pcasted);
+    args.push_back(v2Pcasted);
+
+    IRB.CreateCall(cmplogGccStdC, args);
+
+    // errs() << callInst->getCalledFunction()->getName() << "\n";
+
+  }
+
+  for (auto &callInst : llvmStdStd) {
+
+    Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
+
+    IRBuilder<> IRB(callInst->getParent());
+    IRB.SetInsertPoint(callInst);
+
+    std::vector<Value *> args;
+    Value *              v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
+    Value *              v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
+    args.push_back(v1Pcasted);
+    args.push_back(v2Pcasted);
+
+    IRB.CreateCall(cmplogLlvmStdStd, args);
+
+    // errs() << callInst->getCalledFunction()->getName() << "\n";
+
+  }
+
+  for (auto &callInst : llvmStdC) {
+
+    Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
+
+    IRBuilder<> IRB(callInst->getParent());
+    IRB.SetInsertPoint(callInst);
+
+    std::vector<Value *> args;
+    Value *              v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
+    Value *              v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
+    args.push_back(v1Pcasted);
+    args.push_back(v2Pcasted);
+
+    IRB.CreateCall(cmplogLlvmStdC, args);
+
+    // errs() << callInst->getCalledFunction()->getName() << "\n";
+
+  }
+
   return true;
 
 }
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index cbff6d7e..b1a24f2f 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -810,7 +810,7 @@ void perform_dry_run(afl_state_t *afl) {
 
   while (q) {
 
-    u8  use_mem[MAX_FILE];
+    u8  *use_mem = afl_realloc(AFL_BUF_PARAM(in), MAX_FILE);
     u8  res;
     s32 fd;