Index: clang/lib/Driver/SanitizerArgs.cpp =================================================================== --- clang/lib/Driver/SanitizerArgs.cpp +++ clang/lib/Driver/SanitizerArgs.cpp @@ -290,10 +290,11 @@ if (Add & Fuzzer) Add |= FuzzerNoLink; - // Enable coverage if the fuzzing flag is set. + // Enable coverage and stack depth tracking if the fuzzing flag is set. if (Add & FuzzerNoLink) CoverageFeatures |= CoverageTracePCGuard | CoverageIndirCall | - CoverageTraceCmp | CoveragePCTable; + CoverageTraceCmp | CoveragePCTable | + CoverageStackDepth; Kinds |= Add; } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { Index: compiler-rt/test/fuzzer/deep-recursion.test =================================================================== --- compiler-rt/test/fuzzer/deep-recursion.test +++ compiler-rt/test/fuzzer/deep-recursion.test @@ -1,4 +1,4 @@ # Test that we can find a stack overflow -RUN: %cpp_compiler -fsanitize-coverage=stack-depth %S/DeepRecursionTest.cpp -o %t +RUN: %cpp_compiler %S/DeepRecursionTest.cpp -o %t RUN: not %t -seed=1 -runs=100000000 2>&1 | FileCheck %s CHECK: ERROR: libFuzzer: deadly signal Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -25,6 +25,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" @@ -173,6 +174,13 @@ return Options; } +bool IsLeafFunc(const Function &F) { + for (const BasicBlock &BB : F.getBasicBlockList()) + for (const Instruction &Insn : BB.getInstList()) + if (isa(Insn) && !isa(Insn)) return false; + return true; +} + class SanitizerCoverageModule : public ModulePass { public: SanitizerCoverageModule( @@ -731,6 +739,22 @@ IRBuilder<> IRB(&*IP); IRB.SetCurrentDebugLocation(EntryLoc); + if (Options.StackDepth && IsEntryBB && !IsLeafFunc(F)) { + // Check stack depth. If it's the deepest so far, record it. + Function *GetFrameAddr = + Intrinsic::getDeclaration(F.getParent(), Intrinsic::frameaddress); + auto FrameAddrPtr = + IRB.CreateCall(GetFrameAddr, {Constant::getNullValue(Int32Ty)}); + auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy); + auto LowestStack = IRB.CreateLoad(SanCovLowestStack); + auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); + auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false); + IRBuilder<> ThenIRB(ThenTerm); + auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); + SetNoSanitizeMetadata(LowestStack); + SetNoSanitizeMetadata(Store); + IRB.SetInsertPoint(&*IP); + } if (Options.TracePC) { IRB.CreateCall(SanCovTracePC); // gets the PC using GET_CALLER_PC. IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge. @@ -753,19 +777,6 @@ SetNoSanitizeMetadata(Load); SetNoSanitizeMetadata(Store); } - if (Options.StackDepth && IsEntryBB) { - // Check stack depth. If it's the deepest so far, record it. - Function *GetFrameAddr = - Intrinsic::getDeclaration(F.getParent(), Intrinsic::frameaddress); - auto FrameAddrPtr = - IRB.CreateCall(GetFrameAddr, {Constant::getNullValue(Int32Ty)}); - auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy); - auto LowestStack = IRB.CreateLoad(SanCovLowestStack); - auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); - auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false); - IRBuilder<> ThenIRB(ThenTerm); - ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); - } } std::string Index: llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll =================================================================== --- llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll +++ llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll @@ -1,9 +1,9 @@ ; This check verifies that stack depth instrumentation works correctly. ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 \ -; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s --enable-var-scope +; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 \ ; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \ -; RUN: -S | FileCheck %s --enable-var-scope +; RUN: -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -14,13 +14,8 @@ define i32 @foo() { entry: ; CHECK-LABEL: define i32 @foo -; CHECK: [[framePtr:%[^ \t]+]] = call i8* @llvm.frameaddress(i32 0) -; CHECK: [[frameInt:%[^ \t]+]] = ptrtoint i8* [[framePtr]] to [[$intType:i[0-9]+]] -; CHECK: [[lowest:%[^ \t]+]] = load [[$intType]], [[$intType]]* @__sancov_lowest_stack -; CHECK: [[cmp:%[^ \t]+]] = icmp ult [[$intType]] [[frameInt]], [[lowest]] -; CHECK: br i1 [[cmp]], label %[[ifLabel:[^ \t]+]], label -; CHECK: