10b57cec5SDimitry Andric //===- FuzzerTracePC.cpp - PC tracing--------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // Trace PCs. 90b57cec5SDimitry Andric // This module implements __sanitizer_cov_trace_pc_guard[_init], 100b57cec5SDimitry Andric // the callback required for -fsanitize-coverage=trace-pc-guard instrumentation. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "FuzzerTracePC.h" 150b57cec5SDimitry Andric #include "FuzzerBuiltins.h" 160b57cec5SDimitry Andric #include "FuzzerBuiltinsMsvc.h" 170b57cec5SDimitry Andric #include "FuzzerCorpus.h" 180b57cec5SDimitry Andric #include "FuzzerDefs.h" 190b57cec5SDimitry Andric #include "FuzzerDictionary.h" 200b57cec5SDimitry Andric #include "FuzzerExtFunctions.h" 210b57cec5SDimitry Andric #include "FuzzerIO.h" 220b57cec5SDimitry Andric #include "FuzzerUtil.h" 230b57cec5SDimitry Andric #include "FuzzerValueBitMap.h" 240b57cec5SDimitry Andric #include <set> 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric // Used by -fsanitize-coverage=stack-depth to track stack depth 270b57cec5SDimitry Andric ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC uintptr_t __sancov_lowest_stack; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric namespace fuzzer { 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric TracePC TPC; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric size_t TracePC::GetTotalPCCoverage() { 340b57cec5SDimitry Andric return ObservedPCs.size(); 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) { 390b57cec5SDimitry Andric if (Start == Stop) return; 400b57cec5SDimitry Andric if (NumModules && 410b57cec5SDimitry Andric Modules[NumModules - 1].Start() == Start) 420b57cec5SDimitry Andric return; 430b57cec5SDimitry Andric assert(NumModules < 440b57cec5SDimitry Andric sizeof(Modules) / sizeof(Modules[0])); 450b57cec5SDimitry Andric auto &M = Modules[NumModules++]; 460b57cec5SDimitry Andric uint8_t *AlignedStart = RoundUpByPage(Start); 470b57cec5SDimitry Andric uint8_t *AlignedStop = RoundDownByPage(Stop); 480b57cec5SDimitry Andric size_t NumFullPages = AlignedStop > AlignedStart ? 490b57cec5SDimitry Andric (AlignedStop - AlignedStart) / PageSize() : 0; 500b57cec5SDimitry Andric bool NeedFirst = Start < AlignedStart || !NumFullPages; 510b57cec5SDimitry Andric bool NeedLast = Stop > AlignedStop && AlignedStop >= AlignedStart; 520b57cec5SDimitry Andric M.NumRegions = NumFullPages + NeedFirst + NeedLast;; 530b57cec5SDimitry Andric assert(M.NumRegions > 0); 540b57cec5SDimitry Andric M.Regions = new Module::Region[M.NumRegions]; 550b57cec5SDimitry Andric assert(M.Regions); 560b57cec5SDimitry Andric size_t R = 0; 570b57cec5SDimitry Andric if (NeedFirst) 580b57cec5SDimitry Andric M.Regions[R++] = {Start, std::min(Stop, AlignedStart), true, false}; 590b57cec5SDimitry Andric for (uint8_t *P = AlignedStart; P < AlignedStop; P += PageSize()) 600b57cec5SDimitry Andric M.Regions[R++] = {P, P + PageSize(), true, true}; 610b57cec5SDimitry Andric if (NeedLast) 620b57cec5SDimitry Andric M.Regions[R++] = {AlignedStop, Stop, true, false}; 630b57cec5SDimitry Andric assert(R == M.NumRegions); 640b57cec5SDimitry Andric assert(M.Size() == (size_t)(Stop - Start)); 650b57cec5SDimitry Andric assert(M.Stop() == Stop); 660b57cec5SDimitry Andric assert(M.Start() == Start); 670b57cec5SDimitry Andric NumInline8bitCounters += M.Size(); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) { 710b57cec5SDimitry Andric const PCTableEntry *B = reinterpret_cast<const PCTableEntry *>(Start); 720b57cec5SDimitry Andric const PCTableEntry *E = reinterpret_cast<const PCTableEntry *>(Stop); 730b57cec5SDimitry Andric if (NumPCTables && ModulePCTable[NumPCTables - 1].Start == B) return; 740b57cec5SDimitry Andric assert(NumPCTables < sizeof(ModulePCTable) / sizeof(ModulePCTable[0])); 750b57cec5SDimitry Andric ModulePCTable[NumPCTables++] = {B, E}; 760b57cec5SDimitry Andric NumPCsInPCTables += E - B; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric void TracePC::PrintModuleInfo() { 800b57cec5SDimitry Andric if (NumModules) { 810b57cec5SDimitry Andric Printf("INFO: Loaded %zd modules (%zd inline 8-bit counters): ", 820b57cec5SDimitry Andric NumModules, NumInline8bitCounters); 830b57cec5SDimitry Andric for (size_t i = 0; i < NumModules; i++) 840b57cec5SDimitry Andric Printf("%zd [%p, %p), ", Modules[i].Size(), Modules[i].Start(), 850b57cec5SDimitry Andric Modules[i].Stop()); 860b57cec5SDimitry Andric Printf("\n"); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric if (NumPCTables) { 890b57cec5SDimitry Andric Printf("INFO: Loaded %zd PC tables (%zd PCs): ", NumPCTables, 900b57cec5SDimitry Andric NumPCsInPCTables); 910b57cec5SDimitry Andric for (size_t i = 0; i < NumPCTables; i++) { 920b57cec5SDimitry Andric Printf("%zd [%p,%p), ", ModulePCTable[i].Stop - ModulePCTable[i].Start, 930b57cec5SDimitry Andric ModulePCTable[i].Start, ModulePCTable[i].Stop); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric Printf("\n"); 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric if (NumInline8bitCounters && NumInline8bitCounters != NumPCsInPCTables) { 980b57cec5SDimitry Andric Printf("ERROR: The size of coverage PC tables does not match the\n" 990b57cec5SDimitry Andric "number of instrumented PCs. This might be a compiler bug,\n" 1000b57cec5SDimitry Andric "please contact the libFuzzer developers.\n" 1010b57cec5SDimitry Andric "Also check https://bugs.llvm.org/show_bug.cgi?id=34636\n" 1020b57cec5SDimitry Andric "for possible workarounds (tl;dr: don't use the old GNU ld)\n"); 1030b57cec5SDimitry Andric _Exit(1); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric if (size_t NumExtraCounters = ExtraCountersEnd() - ExtraCountersBegin()) 1070b57cec5SDimitry Andric Printf("INFO: %zd Extra Counters\n", NumExtraCounters); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 1110b57cec5SDimitry Andric void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) { 1120b57cec5SDimitry Andric const uintptr_t kBits = 12; 1130b57cec5SDimitry Andric const uintptr_t kMask = (1 << kBits) - 1; 1140b57cec5SDimitry Andric uintptr_t Idx = (Caller & kMask) | ((Callee & kMask) << kBits); 1150b57cec5SDimitry Andric ValueProfileMap.AddValueModPrime(Idx); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric /// \return the address of the previous instruction. 1190b57cec5SDimitry Andric /// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.h` 1200b57cec5SDimitry Andric inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) { 1210b57cec5SDimitry Andric #if defined(__arm__) 1220b57cec5SDimitry Andric // T32 (Thumb) branch instructions might be 16 or 32 bit long, 1230b57cec5SDimitry Andric // so we return (pc-2) in that case in order to be safe. 1240b57cec5SDimitry Andric // For A32 mode we return (pc-4) because all instructions are 32 bit long. 1250b57cec5SDimitry Andric return (PC - 3) & (~1); 1260b57cec5SDimitry Andric #elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__) 1270b57cec5SDimitry Andric // PCs are always 4 byte aligned. 1280b57cec5SDimitry Andric return PC - 4; 1290b57cec5SDimitry Andric #elif defined(__sparc__) || defined(__mips__) 1300b57cec5SDimitry Andric return PC - 8; 1310b57cec5SDimitry Andric #else 1320b57cec5SDimitry Andric return PC - 1; 1330b57cec5SDimitry Andric #endif 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric /// \return the address of the next instruction. 137*68d75effSDimitry Andric /// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cpp` 1380b57cec5SDimitry Andric ALWAYS_INLINE uintptr_t TracePC::GetNextInstructionPc(uintptr_t PC) { 1390b57cec5SDimitry Andric #if defined(__mips__) 1400b57cec5SDimitry Andric return PC + 8; 1410b57cec5SDimitry Andric #elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \ 1420b57cec5SDimitry Andric defined(__aarch64__) 1430b57cec5SDimitry Andric return PC + 4; 1440b57cec5SDimitry Andric #else 1450b57cec5SDimitry Andric return PC + 1; 1460b57cec5SDimitry Andric #endif 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric void TracePC::UpdateObservedPCs() { 1500b57cec5SDimitry Andric Vector<uintptr_t> CoveredFuncs; 1510b57cec5SDimitry Andric auto ObservePC = [&](const PCTableEntry *TE) { 1520b57cec5SDimitry Andric if (ObservedPCs.insert(TE).second && DoPrintNewPCs) { 1530b57cec5SDimitry Andric PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", 1540b57cec5SDimitry Andric GetNextInstructionPc(TE->PC)); 1550b57cec5SDimitry Andric Printf("\n"); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric }; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric auto Observe = [&](const PCTableEntry *TE) { 1600b57cec5SDimitry Andric if (PcIsFuncEntry(TE)) 1610b57cec5SDimitry Andric if (++ObservedFuncs[TE->PC] == 1 && NumPrintNewFuncs) 1620b57cec5SDimitry Andric CoveredFuncs.push_back(TE->PC); 1630b57cec5SDimitry Andric ObservePC(TE); 1640b57cec5SDimitry Andric }; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric if (NumPCsInPCTables) { 1670b57cec5SDimitry Andric if (NumInline8bitCounters == NumPCsInPCTables) { 1680b57cec5SDimitry Andric for (size_t i = 0; i < NumModules; i++) { 1690b57cec5SDimitry Andric auto &M = Modules[i]; 1700b57cec5SDimitry Andric assert(M.Size() == 1710b57cec5SDimitry Andric (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start)); 1720b57cec5SDimitry Andric for (size_t r = 0; r < M.NumRegions; r++) { 1730b57cec5SDimitry Andric auto &R = M.Regions[r]; 1740b57cec5SDimitry Andric if (!R.Enabled) continue; 1750b57cec5SDimitry Andric for (uint8_t *P = R.Start; P < R.Stop; P++) 1760b57cec5SDimitry Andric if (*P) 1770b57cec5SDimitry Andric Observe(&ModulePCTable[i].Start[M.Idx(P)]); 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric for (size_t i = 0, N = Min(CoveredFuncs.size(), NumPrintNewFuncs); i < N; 1840b57cec5SDimitry Andric i++) { 1850b57cec5SDimitry Andric Printf("\tNEW_FUNC[%zd/%zd]: ", i + 1, CoveredFuncs.size()); 1860b57cec5SDimitry Andric PrintPC("%p %F %L", "%p", GetNextInstructionPc(CoveredFuncs[i])); 1870b57cec5SDimitry Andric Printf("\n"); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric uintptr_t TracePC::PCTableEntryIdx(const PCTableEntry *TE) { 1920b57cec5SDimitry Andric size_t TotalTEs = 0; 1930b57cec5SDimitry Andric for (size_t i = 0; i < NumPCTables; i++) { 1940b57cec5SDimitry Andric auto &M = ModulePCTable[i]; 1950b57cec5SDimitry Andric if (TE >= M.Start && TE < M.Stop) 1960b57cec5SDimitry Andric return TotalTEs + TE - M.Start; 1970b57cec5SDimitry Andric TotalTEs += M.Stop - M.Start; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric assert(0); 2000b57cec5SDimitry Andric return 0; 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric const TracePC::PCTableEntry *TracePC::PCTableEntryByIdx(uintptr_t Idx) { 2040b57cec5SDimitry Andric for (size_t i = 0; i < NumPCTables; i++) { 2050b57cec5SDimitry Andric auto &M = ModulePCTable[i]; 2060b57cec5SDimitry Andric size_t Size = M.Stop - M.Start; 2070b57cec5SDimitry Andric if (Idx < Size) return &M.Start[Idx]; 2080b57cec5SDimitry Andric Idx -= Size; 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric return nullptr; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric static std::string GetModuleName(uintptr_t PC) { 2140b57cec5SDimitry Andric char ModulePathRaw[4096] = ""; // What's PATH_MAX in portable C++? 2150b57cec5SDimitry Andric void *OffsetRaw = nullptr; 2160b57cec5SDimitry Andric if (!EF->__sanitizer_get_module_and_offset_for_pc( 2170b57cec5SDimitry Andric reinterpret_cast<void *>(PC), ModulePathRaw, 2180b57cec5SDimitry Andric sizeof(ModulePathRaw), &OffsetRaw)) 2190b57cec5SDimitry Andric return ""; 2200b57cec5SDimitry Andric return ModulePathRaw; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric template<class CallBack> 2240b57cec5SDimitry Andric void TracePC::IterateCoveredFunctions(CallBack CB) { 2250b57cec5SDimitry Andric for (size_t i = 0; i < NumPCTables; i++) { 2260b57cec5SDimitry Andric auto &M = ModulePCTable[i]; 2270b57cec5SDimitry Andric assert(M.Start < M.Stop); 2280b57cec5SDimitry Andric auto ModuleName = GetModuleName(M.Start->PC); 2290b57cec5SDimitry Andric for (auto NextFE = M.Start; NextFE < M.Stop; ) { 2300b57cec5SDimitry Andric auto FE = NextFE; 2310b57cec5SDimitry Andric assert(PcIsFuncEntry(FE) && "Not a function entry point"); 2320b57cec5SDimitry Andric do { 2330b57cec5SDimitry Andric NextFE++; 2340b57cec5SDimitry Andric } while (NextFE < M.Stop && !(PcIsFuncEntry(NextFE))); 2350b57cec5SDimitry Andric CB(FE, NextFE, ObservedFuncs[FE->PC]); 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric void TracePC::SetFocusFunction(const std::string &FuncName) { 2410b57cec5SDimitry Andric // This function should be called once. 2420b57cec5SDimitry Andric assert(!FocusFunctionCounterPtr); 2430b57cec5SDimitry Andric if (FuncName.empty()) 2440b57cec5SDimitry Andric return; 2450b57cec5SDimitry Andric for (size_t M = 0; M < NumModules; M++) { 2460b57cec5SDimitry Andric auto &PCTE = ModulePCTable[M]; 2470b57cec5SDimitry Andric size_t N = PCTE.Stop - PCTE.Start; 2480b57cec5SDimitry Andric for (size_t I = 0; I < N; I++) { 2490b57cec5SDimitry Andric if (!(PcIsFuncEntry(&PCTE.Start[I]))) continue; // not a function entry. 2500b57cec5SDimitry Andric auto Name = DescribePC("%F", GetNextInstructionPc(PCTE.Start[I].PC)); 2510b57cec5SDimitry Andric if (Name[0] == 'i' && Name[1] == 'n' && Name[2] == ' ') 2520b57cec5SDimitry Andric Name = Name.substr(3, std::string::npos); 2530b57cec5SDimitry Andric if (FuncName != Name) continue; 2540b57cec5SDimitry Andric Printf("INFO: Focus function is set to '%s'\n", Name.c_str()); 2550b57cec5SDimitry Andric FocusFunctionCounterPtr = Modules[M].Start() + I; 2560b57cec5SDimitry Andric return; 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric bool TracePC::ObservedFocusFunction() { 2620b57cec5SDimitry Andric return FocusFunctionCounterPtr && *FocusFunctionCounterPtr; 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric void TracePC::PrintCoverage() { 2660b57cec5SDimitry Andric if (!EF->__sanitizer_symbolize_pc || 2670b57cec5SDimitry Andric !EF->__sanitizer_get_module_and_offset_for_pc) { 2680b57cec5SDimitry Andric Printf("INFO: __sanitizer_symbolize_pc or " 2690b57cec5SDimitry Andric "__sanitizer_get_module_and_offset_for_pc is not available," 2700b57cec5SDimitry Andric " not printing coverage\n"); 2710b57cec5SDimitry Andric return; 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric Printf("COVERAGE:\n"); 2740b57cec5SDimitry Andric auto CoveredFunctionCallback = [&](const PCTableEntry *First, 2750b57cec5SDimitry Andric const PCTableEntry *Last, 2760b57cec5SDimitry Andric uintptr_t Counter) { 2770b57cec5SDimitry Andric assert(First < Last); 2780b57cec5SDimitry Andric auto VisualizePC = GetNextInstructionPc(First->PC); 2790b57cec5SDimitry Andric std::string FileStr = DescribePC("%s", VisualizePC); 2800b57cec5SDimitry Andric if (!IsInterestingCoverageFile(FileStr)) 2810b57cec5SDimitry Andric return; 2820b57cec5SDimitry Andric std::string FunctionStr = DescribePC("%F", VisualizePC); 2830b57cec5SDimitry Andric if (FunctionStr.find("in ") == 0) 2840b57cec5SDimitry Andric FunctionStr = FunctionStr.substr(3); 2850b57cec5SDimitry Andric std::string LineStr = DescribePC("%l", VisualizePC); 2860b57cec5SDimitry Andric size_t NumEdges = Last - First; 2870b57cec5SDimitry Andric Vector<uintptr_t> UncoveredPCs; 2880b57cec5SDimitry Andric for (auto TE = First; TE < Last; TE++) 2890b57cec5SDimitry Andric if (!ObservedPCs.count(TE)) 2900b57cec5SDimitry Andric UncoveredPCs.push_back(TE->PC); 2910b57cec5SDimitry Andric Printf("%sCOVERED_FUNC: hits: %zd", Counter ? "" : "UN", Counter); 2920b57cec5SDimitry Andric Printf(" edges: %zd/%zd", NumEdges - UncoveredPCs.size(), NumEdges); 2930b57cec5SDimitry Andric Printf(" %s %s:%s\n", FunctionStr.c_str(), FileStr.c_str(), 2940b57cec5SDimitry Andric LineStr.c_str()); 2950b57cec5SDimitry Andric if (Counter) 2960b57cec5SDimitry Andric for (auto PC : UncoveredPCs) 2970b57cec5SDimitry Andric Printf(" UNCOVERED_PC: %s\n", 2980b57cec5SDimitry Andric DescribePC("%s:%l", GetNextInstructionPc(PC)).c_str()); 2990b57cec5SDimitry Andric }; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric IterateCoveredFunctions(CoveredFunctionCallback); 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric // Value profile. 3050b57cec5SDimitry Andric // We keep track of various values that affect control flow. 3060b57cec5SDimitry Andric // These values are inserted into a bit-set-based hash map. 3070b57cec5SDimitry Andric // Every new bit in the map is treated as a new coverage. 3080b57cec5SDimitry Andric // 3090b57cec5SDimitry Andric // For memcmp/strcmp/etc the interesting value is the length of the common 3100b57cec5SDimitry Andric // prefix of the parameters. 3110b57cec5SDimitry Andric // For cmp instructions the interesting value is a XOR of the parameters. 3120b57cec5SDimitry Andric // The interesting value is mixed up with the PC and is then added to the map. 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 3150b57cec5SDimitry Andric void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, 3160b57cec5SDimitry Andric size_t n, bool StopAtZero) { 3170b57cec5SDimitry Andric if (!n) return; 3180b57cec5SDimitry Andric size_t Len = std::min(n, Word::GetMaxSize()); 3190b57cec5SDimitry Andric const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1); 3200b57cec5SDimitry Andric const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2); 3210b57cec5SDimitry Andric uint8_t B1[Word::kMaxSize]; 3220b57cec5SDimitry Andric uint8_t B2[Word::kMaxSize]; 3230b57cec5SDimitry Andric // Copy the data into locals in this non-msan-instrumented function 3240b57cec5SDimitry Andric // to avoid msan complaining further. 3250b57cec5SDimitry Andric size_t Hash = 0; // Compute some simple hash of both strings. 3260b57cec5SDimitry Andric for (size_t i = 0; i < Len; i++) { 3270b57cec5SDimitry Andric B1[i] = A1[i]; 3280b57cec5SDimitry Andric B2[i] = A2[i]; 3290b57cec5SDimitry Andric size_t T = B1[i]; 3300b57cec5SDimitry Andric Hash ^= (T << 8) | B2[i]; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric size_t I = 0; 3330b57cec5SDimitry Andric uint8_t HammingDistance = 0; 3340b57cec5SDimitry Andric for (; I < Len; I++) { 3350b57cec5SDimitry Andric if (B1[I] != B2[I] || (StopAtZero && B1[I] == 0)) { 3360b57cec5SDimitry Andric HammingDistance = Popcountll(B1[I] ^ B2[I]); 3370b57cec5SDimitry Andric break; 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric size_t PC = reinterpret_cast<size_t>(caller_pc); 3410b57cec5SDimitry Andric size_t Idx = (PC & 4095) | (I << 12); 3420b57cec5SDimitry Andric Idx += HammingDistance; 3430b57cec5SDimitry Andric ValueProfileMap.AddValue(Idx); 3440b57cec5SDimitry Andric TORCW.Insert(Idx ^ Hash, Word(B1, Len), Word(B2, Len)); 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric template <class T> 3480b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT ALWAYS_INLINE 3490b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 3500b57cec5SDimitry Andric void TracePC::HandleCmp(uintptr_t PC, T Arg1, T Arg2) { 3510b57cec5SDimitry Andric uint64_t ArgXor = Arg1 ^ Arg2; 3520b57cec5SDimitry Andric if (sizeof(T) == 4) 3530b57cec5SDimitry Andric TORC4.Insert(ArgXor, Arg1, Arg2); 3540b57cec5SDimitry Andric else if (sizeof(T) == 8) 3550b57cec5SDimitry Andric TORC8.Insert(ArgXor, Arg1, Arg2); 3560b57cec5SDimitry Andric uint64_t HammingDistance = Popcountll(ArgXor); // [0,64] 3570b57cec5SDimitry Andric uint64_t AbsoluteDistance = (Arg1 == Arg2 ? 0 : Clzll(Arg1 - Arg2) + 1); 3580b57cec5SDimitry Andric ValueProfileMap.AddValue(PC * 128 + HammingDistance); 3590b57cec5SDimitry Andric ValueProfileMap.AddValue(PC * 128 + 64 + AbsoluteDistance); 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric static size_t InternalStrnlen(const char *S, size_t MaxLen) { 3630b57cec5SDimitry Andric size_t Len = 0; 3640b57cec5SDimitry Andric for (; Len < MaxLen && S[Len]; Len++) {} 3650b57cec5SDimitry Andric return Len; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric // Finds min of (strlen(S1), strlen(S2)). 3690b57cec5SDimitry Andric // Needed bacause one of these strings may actually be non-zero terminated. 3700b57cec5SDimitry Andric static size_t InternalStrnlen2(const char *S1, const char *S2) { 3710b57cec5SDimitry Andric size_t Len = 0; 3720b57cec5SDimitry Andric for (; S1[Len] && S2[Len]; Len++) {} 3730b57cec5SDimitry Andric return Len; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric void TracePC::ClearInlineCounters() { 3770b57cec5SDimitry Andric IterateCounterRegions([](const Module::Region &R){ 3780b57cec5SDimitry Andric if (R.Enabled) 3790b57cec5SDimitry Andric memset(R.Start, 0, R.Stop - R.Start); 3800b57cec5SDimitry Andric }); 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 3840b57cec5SDimitry Andric void TracePC::RecordInitialStack() { 3850b57cec5SDimitry Andric int stack; 3860b57cec5SDimitry Andric __sancov_lowest_stack = InitialStack = reinterpret_cast<uintptr_t>(&stack); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric uintptr_t TracePC::GetMaxStackOffset() const { 3900b57cec5SDimitry Andric return InitialStack - __sancov_lowest_stack; // Stack grows down 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric void WarnAboutDeprecatedInstrumentation(const char *flag) { 3940b57cec5SDimitry Andric // Use RawPrint because Printf cannot be used on Windows before OutputFile is 3950b57cec5SDimitry Andric // initialized. 3960b57cec5SDimitry Andric RawPrint(flag); 3970b57cec5SDimitry Andric RawPrint( 3980b57cec5SDimitry Andric " is no longer supported by libFuzzer.\n" 3990b57cec5SDimitry Andric "Please either migrate to a compiler that supports -fsanitize=fuzzer\n" 4000b57cec5SDimitry Andric "or use an older version of libFuzzer\n"); 4010b57cec5SDimitry Andric exit(1); 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric } // namespace fuzzer 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric extern "C" { 4070b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4080b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4090b57cec5SDimitry Andric void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) { 4100b57cec5SDimitry Andric fuzzer::WarnAboutDeprecatedInstrumentation( 4110b57cec5SDimitry Andric "-fsanitize-coverage=trace-pc-guard"); 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric // Best-effort support for -fsanitize-coverage=trace-pc, which is available 4150b57cec5SDimitry Andric // in both Clang and GCC. 4160b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4170b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4180b57cec5SDimitry Andric void __sanitizer_cov_trace_pc() { 4190b57cec5SDimitry Andric fuzzer::WarnAboutDeprecatedInstrumentation("-fsanitize-coverage=trace-pc"); 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4230b57cec5SDimitry Andric void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) { 4240b57cec5SDimitry Andric fuzzer::WarnAboutDeprecatedInstrumentation( 4250b57cec5SDimitry Andric "-fsanitize-coverage=trace-pc-guard"); 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4290b57cec5SDimitry Andric void __sanitizer_cov_8bit_counters_init(uint8_t *Start, uint8_t *Stop) { 4300b57cec5SDimitry Andric fuzzer::TPC.HandleInline8bitCountersInit(Start, Stop); 4310b57cec5SDimitry Andric } 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4340b57cec5SDimitry Andric void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, 4350b57cec5SDimitry Andric const uintptr_t *pcs_end) { 4360b57cec5SDimitry Andric fuzzer::TPC.HandlePCsInit(pcs_beg, pcs_end); 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4400b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4410b57cec5SDimitry Andric void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) { 4420b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 4430b57cec5SDimitry Andric fuzzer::TPC.HandleCallerCallee(PC, Callee); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4470b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4480b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 4490b57cec5SDimitry Andric void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) { 4500b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 4510b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4550b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4560b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 4570b57cec5SDimitry Andric // Now the __sanitizer_cov_trace_const_cmp[1248] callbacks just mimic 4580b57cec5SDimitry Andric // the behaviour of __sanitizer_cov_trace_cmp[1248] ones. This, however, 4590b57cec5SDimitry Andric // should be changed later to make full use of instrumentation. 4600b57cec5SDimitry Andric void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2) { 4610b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 4620b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4660b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4670b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 4680b57cec5SDimitry Andric void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) { 4690b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 4700b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4740b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4750b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 4760b57cec5SDimitry Andric void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2) { 4770b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 4780b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4820b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4830b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 4840b57cec5SDimitry Andric void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) { 4850b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 4860b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4900b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4910b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 4920b57cec5SDimitry Andric void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2) { 4930b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 4940b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 4980b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 4990b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 5000b57cec5SDimitry Andric void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) { 5010b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 5020b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 5060b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 5070b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 5080b57cec5SDimitry Andric void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2) { 5090b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 5100b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 5140b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 5150b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 5160b57cec5SDimitry Andric void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) { 5170b57cec5SDimitry Andric uint64_t N = Cases[0]; 5180b57cec5SDimitry Andric uint64_t ValSizeInBits = Cases[1]; 5190b57cec5SDimitry Andric uint64_t *Vals = Cases + 2; 5200b57cec5SDimitry Andric // Skip the most common and the most boring case: all switch values are small. 5210b57cec5SDimitry Andric // We may want to skip this at compile-time, but it will make the 5220b57cec5SDimitry Andric // instrumentation less general. 5230b57cec5SDimitry Andric if (Vals[N - 1] < 256) 5240b57cec5SDimitry Andric return; 5250b57cec5SDimitry Andric // Also skip small inputs values, they won't give good signal. 5260b57cec5SDimitry Andric if (Val < 256) 5270b57cec5SDimitry Andric return; 5280b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 5290b57cec5SDimitry Andric size_t i; 5300b57cec5SDimitry Andric uint64_t Smaller = 0; 5310b57cec5SDimitry Andric uint64_t Larger = ~(uint64_t)0; 5320b57cec5SDimitry Andric // Find two switch values such that Smaller < Val < Larger. 5330b57cec5SDimitry Andric // Use 0 and 0xfff..f as the defaults. 5340b57cec5SDimitry Andric for (i = 0; i < N; i++) { 5350b57cec5SDimitry Andric if (Val < Vals[i]) { 5360b57cec5SDimitry Andric Larger = Vals[i]; 5370b57cec5SDimitry Andric break; 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric if (Val > Vals[i]) Smaller = Vals[i]; 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric // Apply HandleCmp to {Val,Smaller} and {Val, Larger}, 5430b57cec5SDimitry Andric // use i as the PC modifier for HandleCmp. 5440b57cec5SDimitry Andric if (ValSizeInBits == 16) { 5450b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC + 2 * i, static_cast<uint16_t>(Val), 5460b57cec5SDimitry Andric (uint16_t)(Smaller)); 5470b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC + 2 * i + 1, static_cast<uint16_t>(Val), 5480b57cec5SDimitry Andric (uint16_t)(Larger)); 5490b57cec5SDimitry Andric } else if (ValSizeInBits == 32) { 5500b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC + 2 * i, static_cast<uint32_t>(Val), 5510b57cec5SDimitry Andric (uint32_t)(Smaller)); 5520b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC + 2 * i + 1, static_cast<uint32_t>(Val), 5530b57cec5SDimitry Andric (uint32_t)(Larger)); 5540b57cec5SDimitry Andric } else { 5550b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC + 2*i, Val, Smaller); 5560b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC + 2*i + 1, Val, Larger); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 5610b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 5620b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 5630b57cec5SDimitry Andric void __sanitizer_cov_trace_div4(uint32_t Val) { 5640b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 5650b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Val, (uint32_t)0); 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 5690b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 5700b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 5710b57cec5SDimitry Andric void __sanitizer_cov_trace_div8(uint64_t Val) { 5720b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 5730b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Val, (uint64_t)0); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric ATTRIBUTE_INTERFACE 5770b57cec5SDimitry Andric ATTRIBUTE_NO_SANITIZE_ALL 5780b57cec5SDimitry Andric ATTRIBUTE_TARGET_POPCNT 5790b57cec5SDimitry Andric void __sanitizer_cov_trace_gep(uintptr_t Idx) { 5800b57cec5SDimitry Andric uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); 5810b57cec5SDimitry Andric fuzzer::TPC.HandleCmp(PC, Idx, (uintptr_t)0); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY 5850b57cec5SDimitry Andric void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1, 5860b57cec5SDimitry Andric const void *s2, size_t n, int result) { 5870b57cec5SDimitry Andric if (!fuzzer::RunningUserCallback) return; 5880b57cec5SDimitry Andric if (result == 0) return; // No reason to mutate. 5890b57cec5SDimitry Andric if (n <= 1) return; // Not interesting. 5900b57cec5SDimitry Andric fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/false); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY 5940b57cec5SDimitry Andric void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1, 5950b57cec5SDimitry Andric const char *s2, size_t n, int result) { 5960b57cec5SDimitry Andric if (!fuzzer::RunningUserCallback) return; 5970b57cec5SDimitry Andric if (result == 0) return; // No reason to mutate. 5980b57cec5SDimitry Andric size_t Len1 = fuzzer::InternalStrnlen(s1, n); 5990b57cec5SDimitry Andric size_t Len2 = fuzzer::InternalStrnlen(s2, n); 6000b57cec5SDimitry Andric n = std::min(n, Len1); 6010b57cec5SDimitry Andric n = std::min(n, Len2); 6020b57cec5SDimitry Andric if (n <= 1) return; // Not interesting. 6030b57cec5SDimitry Andric fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/true); 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY 6070b57cec5SDimitry Andric void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1, 6080b57cec5SDimitry Andric const char *s2, int result) { 6090b57cec5SDimitry Andric if (!fuzzer::RunningUserCallback) return; 6100b57cec5SDimitry Andric if (result == 0) return; // No reason to mutate. 6110b57cec5SDimitry Andric size_t N = fuzzer::InternalStrnlen2(s1, s2); 6120b57cec5SDimitry Andric if (N <= 1) return; // Not interesting. 6130b57cec5SDimitry Andric fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, N, /*StopAtZero*/true); 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY 6170b57cec5SDimitry Andric void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, 6180b57cec5SDimitry Andric const char *s2, size_t n, int result) { 6190b57cec5SDimitry Andric if (!fuzzer::RunningUserCallback) return; 6200b57cec5SDimitry Andric return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result); 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY 6240b57cec5SDimitry Andric void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, 6250b57cec5SDimitry Andric const char *s2, int result) { 6260b57cec5SDimitry Andric if (!fuzzer::RunningUserCallback) return; 6270b57cec5SDimitry Andric return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY 6310b57cec5SDimitry Andric void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, 6320b57cec5SDimitry Andric const char *s2, char *result) { 6330b57cec5SDimitry Andric if (!fuzzer::RunningUserCallback) return; 6340b57cec5SDimitry Andric fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY 6380b57cec5SDimitry Andric void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, 6390b57cec5SDimitry Andric const char *s2, char *result) { 6400b57cec5SDimitry Andric if (!fuzzer::RunningUserCallback) return; 6410b57cec5SDimitry Andric fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY 6450b57cec5SDimitry Andric void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, 6460b57cec5SDimitry Andric const void *s2, size_t len2, void *result) { 6470b57cec5SDimitry Andric if (!fuzzer::RunningUserCallback) return; 6480b57cec5SDimitry Andric fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), len2); 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric } // extern "C" 651