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

Inlay-hints cause segmentation fault in some special cases. #1120

Closed
lightmelodies opened this issue Apr 23, 2022 · 1 comment
Closed

Inlay-hints cause segmentation fault in some special cases. #1120

lightmelodies opened this issue Apr 23, 2022 · 1 comment

Comments

@lightmelodies
Copy link

lightmelodies commented Apr 23, 2022

clangd crashed with linux kernel code due to segmentation fault:

#0 0x00007f9c689b0061 PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
#1 0x00007f9c689ad814 SignalHandler(int) Signals.cpp:0:0
#2 0x00007f9c67cfd560 __restore_rt libc_sigaction.c:0:0
#3 0x000055adce5764ad clang::RecursiveASTVisitor<clang::clangd::(anonymous namespace)::InlayHintVisitor>::TraverseFunctionDecl(clang::FunctionDecl*) InlayHints.cpp:0:0
#4 0x000055adce579e65 clang::RecursiveASTVisitor<clang::clangd::(anonymous namespace)::InlayHintVisitor>::TraverseTranslationUnitDecl(clang::TranslationUnitDecl*) InlayHints.cpp:0:0
#5 0x000055adce575830 clang::clangd::inlayHints(clang::clangd::ParsedAST&, llvm::Optionalclang::clangd::Range) (/home/frost/llvm-project/build/bin/clangd+0x1611830)
#6 0x000055adce45e6b0 void llvm::detail::UniqueFunctionBase<void, llvm::Expectedclang::clangd::InputsAndAST >::CallImpl<clang::clangd::ClangdServer::inlayHints(llvm::StringRef, llvm::Optionalclang::clangd::Range, llvm::unique_function<void (llvm::Expected<std::vector<clang::clangd::InlayHint, std::allocatorclang::clangd::InlayHint > >)>)::'lambda'(llvm::Expectedclang::clangd::InputsAndAST)>(void*, llvm::Expectedclang::clangd::InputsAndAST&) ClangdServer.cpp:0:0
#7 0x000055adce61d1ba clang::clangd::(anonymous namespace)::ASTWorker::runWithAST(llvm::StringRef, llvm::unique_function<void (llvm::Expectedclang::clangd::InputsAndAST)>, clang::clangd::TUScheduler::ASTActionInvalidation)::'lambda'()::operator()() TUScheduler.cpp:0:0
#8 0x000055adce6137f1 clang::clangd::(anonymous namespace)::ASTWorker::runTask(llvm::StringRef, llvm::function_ref<void ()>) (.constprop.0) TUScheduler.cpp:0:0
#9 0x000055adce615492 clang::clangd::(anonymous namespace)::ASTWorker::run() TUScheduler.cpp:0:0
#10 0x000055adce7ce832 void* llvm::thread::ThreadProxy<std::tuple<clang::clangd::AsyncTaskRunner::runAsync(llvm::Twine const&, llvm::unique_function<void ()>)::'lambda0'()> >(void*) Threading.cpp:0:0
#11 0x00007f9c67d485c2 start_thread pthread_create.c:0:0
#12 0x00007f9c67dcd584 __clone (/usr/lib/libc.so.6+0x112584)
Signalled during AST worker action: InlayHints

By debugging clangd code I found the EXPORT_SYMBOL macro in linux kernel expand to something like this:

// hello.c
void hello(void) {}
typeof(hello) hello;

which cause D->getFunctionTypeLoc() return an empty location and null pointer dereference occured with getRParenLoc().

https://github.com/llvm/llvm-project/blob/d43c083ab692ef0fc0dc5ede970ba4b3541fe5bd/clang-tools-extra/clangd/InlayHints.cpp#L257-L264

Something weird is that the same code does not crash if I change the source language to cpp.

// hello.cpp
void hello(void) {}
typeof(hello) hello;

or define hello without void in parameters:

// hello.c
void hello() {}
typeof(hello) hello;

The simplest fix is adding a check beforce calling getRParenLoc:

bool VisitFunctionDecl(FunctionDecl *D) {
  if (auto *FPT =
          llvm::dyn_cast<FunctionProtoType>(D->getType().getTypePtr())) {
    if (!FPT->hasTrailingReturn())
      if (auto Loc = D->getFunctionTypeLoc())
        addReturnTypeHint(D, Loc.getRParenLoc());
  }
  return true;
}
@sam-mccall
Copy link
Member

Thanks! You're spot on, I've committed this fix as llvm/llvm-project@6385c03

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants