[libFuzzer] when tracing switch statements, handle only one case at a time (to make...
authorKostya Serebryany <kcc@google.com>
Sat, 17 Dec 2016 02:03:34 +0000 (02:03 +0000)
committerKostya Serebryany <kcc@google.com>
Sat, 17 Dec 2016 02:03:34 +0000 (02:03 +0000)
llvm-svn: 290031

llvm/lib/Fuzzer/FuzzerTracePC.cpp
llvm/lib/Fuzzer/FuzzerTracePC.h
llvm/lib/Fuzzer/test/SwitchTest.cpp

index 6cb1c66..74eb854 100644 (file)
@@ -290,12 +290,22 @@ void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) {
 
 __attribute__((visibility("default")))
 void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) {
+  // Updates the value profile based on the relative position of Val and Cases.
+  // We want to handle one random case at every call (handling all is slow).
+  // Since none of the arguments contain any random bits we use a thread-local
+  // counter to choose the random case to handle.
+  static thread_local size_t Counter;
+  Counter++;
   uint64_t N = Cases[0];
   uint64_t *Vals = Cases + 2;
   char *PC = (char*)__builtin_return_address(0);
-  for (size_t i = 0; i < N; i++)
-    if (Val != Vals[i])
-      fuzzer::TPC.HandleCmp(PC + i, Val, Vals[i]);
+  size_t Idx = Counter % N;
+  uint64_t TwoIn32 = 1ULL << 32;
+  if ((Val | Vals[Idx]) < TwoIn32)
+    fuzzer::TPC.HandleCmp(PC + Idx, static_cast<uint32_t>(Val),
+                          static_cast<uint32_t>(Vals[Idx]));
+  else
+    fuzzer::TPC.HandleCmp(PC + Idx, Val, Vals[Idx]);
 }
 
 __attribute__((visibility("default")))
index e3f6f10..9d41628 100644 (file)
@@ -144,7 +144,7 @@ size_t TracePC::CollectFeatures(Callback CB) {
   }
   if (UseValueProfile)
     ValueProfileMap.ForEach([&](size_t Idx) {
-      if (CB(NumGuards + Idx))
+      if (CB(NumGuards * 8 + Idx))
         Res++;
     });
   return Res;
index 3dc051f..74e86c0 100644 (file)
@@ -20,8 +20,8 @@ bool Switch(const uint8_t *Data, size_t Size) {
     case 101: Sink = __LINE__; break;
     case 1001: Sink = __LINE__; break;
     case 10001: Sink = __LINE__; break;
-    case 100001: Sink = __LINE__; break;
-    case 1000001: Sink = __LINE__; break;
+//    case 100001: Sink = __LINE__; break;
+//    case 1000001: Sink = __LINE__; break;
     case 10000001: Sink = __LINE__; break;
     case 100000001: return true;
   }