Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clang crash with HWASan after D159172 #66934

Closed
thurstond opened this issue Sep 20, 2023 · 1 comment
Closed

clang crash with HWASan after D159172 #66934

thurstond opened this issue Sep 20, 2023 · 1 comment
Assignees
Labels
compiler-rt:hwasan Hardware-assisted address sanitizer

Comments

@thurstond
Copy link
Contributor

N.B. I think I have a fix/workaround for this. This bug report is largely for recordkeeping, instead of dumping all the details in the git commit message.

Reproducer

clang tip-of-tree (9/20/23) crashes with:

/my/path/to/clang \
    --target=aarch64-linux-gnu \
    -flto=thin \
    -fsanitize=hwaddress \
    -O1 \
    -c crash.c \
    -o /tmp/crash.o
void a();

void b(char *c, char e) {
  int d;
  while (e) {
    if (c[d]) {
      while (1) {
      }
    }

    d++;
  }
}

void f() {
  char g[1];

  a(g);
}

Backtrace

clang: /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/ScalarEvolution.cpp:6392: llvm::ConstantRange llvm::ScalarEvolution::getRangeForUnknownRecurrence(const llvm::SCEVUnknown *): Assertion `L && L->getHeader() == P->getParent()' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /usr/local/google/home/thurston/llvm-projectC/build/bin/clang --target=aarch64-linux-gnu -flto=thin -fsanitize=hwaddress -O1 -c comp-interesting2-preproc.c -o /tmp/comp-interesting2-preproc.bc
1.      <eof> parser at end of file
2.      Optimizer
 #0 0x00005557a6d1413d llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Support/Unix/Signals.inc:723:11
 #1 0x00005557a6d1462b PrintStackTraceSignalHandler(void*) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Support/Unix/Signals.inc:798:1
 #2 0x00005557a6d12656 llvm::sys::RunSignalHandlers() /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Support/Signals.cpp:105:5
 #3 0x00005557a6d139ae llvm::sys::CleanupOnSignal(unsigned long) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Support/Unix/Signals.inc:368:1
 #4 0x00005557a6c3c364 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Support/CrashRecoveryContext.cpp:0:7
 #5 0x00005557a6c3c722 CrashRecoverySignalHandler(int) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Support/CrashRecoveryContext.cpp:391:1
 #6 0x00007f628b25a540 (/lib/x86_64-linux-gnu/libc.so.6+0x3c540)
 #7 0x00007f628b2a812c __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #8 0x00007f628b25a4a2 raise ./signal/../sysdeps/posix/raise.c:27:6
 #9 0x00007f628b2444b2 abort ./stdlib/abort.c:81:7
#10 0x00007f628b2443d5 _nl_load_domain ./intl/loadmsgcat.c:1177:9
#11 0x00007f628b2533a2 (/lib/x86_64-linux-gnu/libc.so.6+0x353a2)
#12 0x00005557a5878d8c llvm::ScalarEvolution::getRangeForUnknownRecurrence(llvm::SCEVUnknown const*) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/ScalarEvolution.cpp:6393:8
#13 0x00005557a587b216 llvm::ScalarEvolution::getRangeRef(llvm::SCEV const*, llvm::ScalarEvolution::RangeSignHint, unsigned int) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/ScalarEvolution.cpp:6794:45
#14 0x00005557a58b76e3 llvm::ScalarEvolution::getSignedRangeMin(llvm::SCEV const*) /usr/local/google/home/thurston/llvm-projectC/llvm/include/llvm/Analysis/ScalarEvolution.h:996:12
#15 0x00005557a586b961 llvm::ScalarEvolution::isKnownNonNegative(llvm::SCEV const*) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/ScalarEvolution.cpp:10723:32
#16 0x00005557a586f59d llvm::ScalarEvolution::getGEPExpr(llvm::GEPOperator*, llvm::SmallVectorImpl<llvm::SCEV const*> const&) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/ScalarEvolution.cpp:3806:55
#17 0x00005557a58780c3 llvm::ScalarEvolution::createNodeForGEP(llvm::GEPOperator*) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/ScalarEvolution.cpp:6229:10
#18 0x00005557a58808f4 llvm::ScalarEvolution::createSCEV(llvm::Value*) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/ScalarEvolution.cpp:8016:5
#19 0x00005557a587285f llvm::ScalarEvolution::createSCEVIter(llvm::Value*) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/ScalarEvolution.cpp:7397:19
#20 0x00005557a586cd06 llvm::ScalarEvolution::getSCEV(llvm::Value*) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/ScalarEvolution.cpp:4518:15
#21 0x00005557a5919e2d (anonymous namespace)::StackSafetyLocalAnalysis::offsetFrom(llvm::Value*, llvm::Value*) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/StackSafetyAnalysis.cpp:276:55
#22 0x00005557a5917a20 (anonymous namespace)::StackSafetyLocalAnalysis::analyzeAllUses(llvm::Value*, (anonymous namespace)::UseInfo<llvm::GlobalValue>&, llvm::StackLifetime const&) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/StackSafetyAnalysis.cpp:517:13
#23 0x00005557a5912bd1 (anonymous namespace)::StackSafetyLocalAnalysis::run() /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/StackSafetyAnalysis.cpp:550:3
#24 0x00005557a59126bf llvm::StackSafetyInfo::getInfo() const /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/StackSafetyAnalysis.cpp:876:32
#25 0x00005557a59132d1 llvm::StackSafetyGlobalInfo::getInfo() const /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/StackSafetyAnalysis.cpp:891:29
#26 0x00005557a5914d29 llvm::StackSafetyGlobalInfo::isSafe(llvm::AllocaInst const&) const /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Analysis/StackSafetyAnalysis.cpp:977:15
#27 0x00005557a6e67421 llvm::memtag::StackInfoBuilder::isInterestingAlloca(llvm::AllocaInst const&) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp:172:24
#28 0x00005557a6e670a7 llvm::memtag::StackInfoBuilder::visit(llvm::Instruction&) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp:119:9
#29 0x00005557a8e98631 (anonymous namespace)::HWAddressSanitizer::sanitizeFunction(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp:0:11
#30 0x00005557a8e98162 llvm::HWAddressSanitizerPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp:433:20
#31 0x00005557a70d64a7 llvm::detail::PassModel<llvm::Module, llvm::HWAddressSanitizerPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /usr/local/google/home/thurston/llvm-projectC/llvm/include/llvm/IR/PassManagerInternal.h:89:17
#32 0x00005557a64937ea llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /usr/local/google/home/thurston/llvm-projectC/llvm/include/llvm/IR/PassManager.h:521:7
#33 0x00005557a70c06f1 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&) /usr/local/google/home/thurston/llvm-projectC/clang/lib/CodeGen/BackendUtil.cpp:1109:5
#34 0x00005557a70ba5b5 (anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>) /usr/local/google/home/thurston/llvm-projectC/clang/lib/CodeGen/BackendUtil.cpp:1173:3
#35 0x00005557a70b9a77 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>) /usr/local/google/home/thurston/llvm-projectC/clang/lib/CodeGen/BackendUtil.cpp:1336:3
#36 0x00005557a88c4ce4 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) /usr/local/google/home/thurston/llvm-projectC/clang/lib/CodeGen/CodeGenAction.cpp:386:7
#37 0x00005557aae23a23 clang::ParseAST(clang::Sema&, bool, bool) /usr/local/google/home/thurston/llvm-projectC/clang/lib/Parse/ParseAST.cpp:183:12
#38 0x00005557a7d88a01 clang::ASTFrontendAction::ExecuteAction() /usr/local/google/home/thurston/llvm-projectC/clang/lib/Frontend/FrontendAction.cpp:1186:1
#39 0x00005557a88bfe36 clang::CodeGenAction::ExecuteAction() /usr/local/google/home/thurston/llvm-projectC/clang/lib/CodeGen/CodeGenAction.cpp:1208:5
#40 0x00005557a7d883fc clang::FrontendAction::Execute() /usr/local/google/home/thurston/llvm-projectC/clang/lib/Frontend/FrontendAction.cpp:1074:7
#41 0x00005557a7ca6f28 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /usr/local/google/home/thurston/llvm-projectC/clang/lib/Frontend/CompilerInstance.cpp:1054:23
#42 0x00005557a7f52f78 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /usr/local/google/home/thurston/llvm-projectC/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:272:8
#43 0x00005557a31e010f cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /usr/local/google/home/thurston/llvm-projectC/clang/tools/driver/cc1_main.cpp:286:13
#44 0x00005557a31cfcaa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) /usr/local/google/home/thurston/llvm-projectC/clang/tools/driver/driver.cpp:366:5
#45 0x00005557a31d161d clang_main(int, char**, llvm::ToolContext const&)::$_0::operator()(llvm::SmallVectorImpl<char const*>&) const /usr/local/google/home/thurston/llvm-projectC/clang/tools/driver/driver.cpp:506:7
#46 0x00005557a31d15ed int llvm::function_ref<int (llvm::SmallVectorImpl<char const*>&)>::callback_fn<clang_main(int, char**, llvm::ToolContext const&)::$_0>(long, llvm::SmallVectorImpl<char const*>&) /usr/local/google/home/thurston/llvm-projectC/llvm/include/llvm/ADT/STLFunctionalExtras.h:45:5
#47 0x00005557a7b46dd9 llvm::function_ref<int (llvm::SmallVectorImpl<char const*>&)>::operator()(llvm::SmallVectorImpl<char const*>&) const /usr/local/google/home/thurston/llvm-projectC/llvm/include/llvm/ADT/STLFunctionalExtras.h:68:5
#48 0x00005557a7b43558 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::$_1::operator()() const /usr/local/google/home/thurston/llvm-projectC/clang/lib/Driver/Job.cpp:440:34
#49 0x00005557a7b43525 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::$_1>(long) /usr/local/google/home/thurston/llvm-projectC/llvm/include/llvm/ADT/STLFunctionalExtras.h:45:5
#50 0x00005557a59b5b89 llvm::function_ref<void ()>::operator()() const /usr/local/google/home/thurston/llvm-projectC/llvm/include/llvm/ADT/STLFunctionalExtras.h:68:5
#51 0x00005557a6c3c17a llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) /usr/local/google/home/thurston/llvm-projectC/llvm/lib/Support/CrashRecoveryContext.cpp:427:3
#52 0x00005557a7b42e77 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const /usr/local/google/home/thurston/llvm-projectC/clang/lib/Driver/Job.cpp:440:7
#53 0x00005557a7adfe3f clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const /usr/local/google/home/thurston/llvm-projectC/clang/lib/Driver/Compilation.cpp:199:15
#54 0x00005557a7ae0047 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const /usr/local/google/home/thurston/llvm-projectC/clang/lib/Driver/Compilation.cpp:253:13
#55 0x00005557a7afac32 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) /usr/local/google/home/thurston/llvm-projectC/clang/lib/Driver/Driver.cpp:1883:7
#56 0x00005557a31cf768 clang_main(int, char**, llvm::ToolContext const&) /usr/local/google/home/thurston/llvm-projectC/clang/tools/driver/driver.cpp:542:9
#57 0x00005557a3204d2d main /usr/local/google/home/thurston/llvm-projectC/build/tools/clang/tools/driver/clang-driver.cpp:15:3
#58 0x00007f628b2456ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3
#59 0x00007f628b245785 call_init ./csu/../csu/libc-start.c:128:20
#60 0x00007f628b245785 __libc_start_main ./csu/../csu/libc-start.c:347:5
#61 0x00005557a31ce401 _start (/usr/local/google/home/thurston/llvm-projectC/build/bin/clang+0x1d46401)
clang: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 18.0.0 (https://github.com/llvm/llvm-project.git 903a7e487b4b3ee0f52f5675a5fc4ca188c1a3c0)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/google/home/thurston/llvm-projectC/build/bin
clang: note: diagnostic msg: 
********************

Theory

This first started happening after "[HWASAN] Inline fast pass of instrumentMemAccessOutline" (https://reviews.llvm.org/D159172) landed. Some of the blocks end up being split by insertShadowTagCheck, which results in some cached analyses becoming invalid. Per the backtrace above, HWASan relies on a global stack safety analysis, which may use some stale analysis results, leading to the crash.

Tentative fix

The tentative fix (pull request coming very soon) is to invalidate the DominatorTreeAnalysis after each function is sanitized.

@thurstond thurstond added the compiler-rt:hwasan Hardware-assisted address sanitizer label Sep 20, 2023
@thurstond thurstond self-assigned this Sep 20, 2023
thurstond added a commit to thurstond/llvm-project that referenced this issue Sep 20, 2023
…tized

HWAddressSanitizerPass::run sanitizes functions one by one. The sanitization of each function - which may split blocks via insertShadowTagCheck - may result in some cached analyses are invalid. This matters because sanitizeFunction(F', FAM) may indirectly call the global stack safety analysis, hence we need to make sure the analyses of F are up to date.

Bug report: llvm#66934
@fmayer
Copy link
Contributor

fmayer commented Sep 20, 2023

We should probably also check whether we can teach the StackSafetyAnalysis not to revisit every function in a module for every function we sanitize. With your fix we will have quadratic number of dominator tree calculations for every module.

thurstond added a commit to thurstond/llvm-project that referenced this issue Sep 21, 2023
This patch incrementally updates the DominatorTreeAnalysis and
LoopAnalysis whenever SplitBlockAndInsertIfThen is called, which fixes
the following issue:
  Suppose we have two functions, F and G. HWAddressSanitizerPass::run
  will first sanitize F, which potentially makes the analyses of F out of
  date. When G is then sanitized, it may call the global stack safety
  analysis, which can crash if the analysis of F is stale.

Additionally, since the DominatorTreeAnalysis and LoopAnalysis are now
incrementally updated, they do not need to be abandoned at the end of
the pass.

Bug report: llvm#66934
thurstond added a commit to thurstond/llvm-project that referenced this issue Sep 21, 2023
This patch incrementally updates the DominatorTreeAnalysis and
LoopAnalysis whenever SplitBlockAndInsertIfThen is called, which fixes
the following issue:
  Suppose we have two functions, F and G. HWAddressSanitizerPass::run
  will first sanitize F, which potentially makes the analyses of F out of
  date. When G is then sanitized, it may call the global stack safety
  analysis, which can crash if the analysis of F is stale.

Additionally, since the DominatorTreeAnalysis and LoopAnalysis are now
incrementally updated, they do not need to be abandoned at the end of
the pass.

Bug report: llvm#66934
thurstond added a commit to thurstond/llvm-project that referenced this issue Sep 21, 2023
…ntally

This patch incrementally updates the DominatorTreeAnalysis,
PostDominatorTreeAnalysis and LoopAnalysis whenever
SplitBlockAndInsertIfThen is called, which fixes the following issue:
  Suppose we have two functions, F and G. HWAddressSanitizerPass::run
  will first sanitize F, which potentially makes the analyses of F out of
  date. When G is then sanitized, it may call the global stack safety
  analysis, which can crash if the analysis of F is stale.

Additionally, since the DominatorTreeAnalysis, PostDominatorTreeAnalysis
and LoopAnalysis are now incrementally updated, they do not need to be
abandoned at the end of the pass.

Bug report: llvm#66934
thurstond added a commit to thurstond/llvm-project that referenced this issue Sep 26, 2023
…ntally

This patch incrementally updates the DominatorTreeAnalysis,
PostDominatorTreeAnalysis and LoopAnalysis whenever
SplitBlockAndInsertIfThen is called, which fixes the following issue:
    Suppose we have two functions, F and G. HWAddressSanitizerPass::run
    will first sanitize F, which potentially makes the analyses of F out of
    date. When G is then sanitized, it may call the global stack safety
    analysis, which can crash if the analysis of F is stale.

Additionally, since the DominatorTreeAnalysis, PostDominatorTreeAnalysis
and LoopAnalysis are now incrementally updated, they do not need to be
abandoned at the end of the pass.

Bug report: llvm#66934
thurstond added a commit that referenced this issue Sep 28, 2023
…ntally (#66935)

HWAddressSanitizerPass::run sanitizes functions one by one. The
sanitization of each function - which may split blocks via
insertShadowTagCheck - may result in some cached analyses are invalid.
This matters because sanitizeFunction(F', FAM) may indirectly call the
global stack safety analysis, hence we need to make sure the analyses of
F are up to date.

Bug report: #66934
legrosbuffle pushed a commit to legrosbuffle/llvm-project that referenced this issue Sep 29, 2023
…ntally (llvm#66935)

HWAddressSanitizerPass::run sanitizes functions one by one. The
sanitization of each function - which may split blocks via
insertShadowTagCheck - may result in some cached analyses are invalid.
This matters because sanitizeFunction(F', FAM) may indirectly call the
global stack safety analysis, hence we need to make sure the analyses of
F are up to date.

Bug report: llvm#66934
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler-rt:hwasan Hardware-assisted address sanitizer
Projects
None yet
Development

No branches or pull requests

2 participants