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

[analyzer] Crashes when analyzing a call to a user-defined function named strerror #88181

Closed
iillyyaa opened this issue Apr 9, 2024 · 1 comment
Labels
clang:static analyzer crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@iillyyaa
Copy link

iillyyaa commented Apr 9, 2024

Use of a function named strerror in a private namespace causes clang-tidy to crash.
If the function is renamed to anything else (e.g. strerrorX) the crash disappears.

Minimal program that shows this issue:

#include <string>

namespace other {
std::string strerror(int errnum);

void test() {
    (void)strerror(0);
}
} // namespace other

Running this through clang-tidy in LLVM 18.1.2 leads to:

Error running 'clang-tidy': PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: clang-tidy -warnings-as-errors=* -header-filter=/home/ilyak/veo/crux -extra-arg=-Wpedantic -extra-arg=-Wno-sign-conversion -extra-arg=-Wno-unknown-pragmas -extra-arg-before=--target=x86_64-oe-linux -p=/home/ilyak/veo/crux/release.scarthgap --extra-arg-before=--driver-mode=g++ /home/ilyak/veo/crux/lib/thread/attrib.cpp -- /home/ilyak/veo/oe-scarthgap/tmp/build-glibc/sysroots/x86_64/usr/bin/x86_64-oe-linux/x86_64-oe-linux-g++ -m64 -march=x86-64-v3 --sysroot=/home/ilyak/veo/oe-scarthgap/tmp/build-glibc/sysroots/intel-skylake-64 --sysroot=/home/ilyak/veo/oe-scarthgap/tmp/build-glibc/sysroots/intel-skylake-64 -DBACKWARD_HAS_BACKTRACE=0 -DBACKWARD_HAS_BACKTRACE_SYMBOL=0 -DBACKWARD_HAS_BFD=0 -DBACKWARD_HAS_DW=1 -DBACKWARD_HAS_DWARF=0 -DBACKWARD_HAS_LIBUNWIND=0 -DBACKWARD_HAS_UNWIND=1 -DFMT_SHARED -Dthread_EXPORTS -I/home/ilyak/veo/crux/lib/thread/include -I/home/ilyak/veo/crux/lib/log/include -I/home/ilyak/veo/oe-scarthgap/tmp/build-glibc/sysroots/intel-skylake-64/usr/lib/backward -I/home/ilyak/veo/crux/lib/veofmt/include -O2 -pipe -g -feliminate-unused-debug-types -O3 -DNDEBUG -std=c++20 -fPIC -Wall -Wpedantic -Wconversion -Werror -Wextra -Wno-psabi -MD -MT lib/thread/CMakeFiles/thread.dir/attrib.cpp.o -MF CMakeFiles/thread.dir/attrib.cpp.o.d -o CMakeFiles/thread.dir/attrib.cpp.o -c /home/ilyak/veo/crux/lib/thread/attrib.cpp
1.	<eof> parser at end of file
2.	While analyzing stack: 
	#0 Calling other::test()
3.	/home/ilyak/veo/crux/lib/thread/attrib.cpp:7:11: Error evaluating statement
4.	/home/ilyak/veo/crux/lib/thread/attrib.cpp:7:11: Error evaluating statement
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  libLLVM.so.18.1      0x00007ef329b2c1a4 llvm::sys::RunSignalHandlers() + 52
1  libLLVM.so.18.1      0x00007ef329b2c456
2  libc.so.6            0x00007ef328a57270
3  libclang-cpp.so.18.1 0x00007ef331f62f43 clang::ento::MemRegion::getBaseRegion() const + 3
4  libclang-cpp.so.18.1 0x00007ef3320fd519
5  libclang-cpp.so.18.1 0x00007ef3320feb15
6  libclang-cpp.so.18.1 0x00007ef331edf053
7  libclang-cpp.so.18.1 0x00007ef331edf4aa clang::ento::CheckerManager::runCheckersForCallEvent(bool, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&, clang::ento::CallEvent const&, clang::ento::ExprEngine&, bool) + 90
8  libclang-cpp.so.18.1 0x00007ef331f40384 clang::ento::ExprEngine::evalCall(clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNode*, clang::ento::CallEvent const&) + 740
9  libclang-cpp.so.18.1 0x00007ef331f40c2a clang::ento::ExprEngine::VisitCallExpr(clang::CallExpr const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) + 506
10 libclang-cpp.so.18.1 0x00007ef331f16fe6 clang::ento::ExprEngine::Visit(clang::Stmt const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) + 1270
11 libclang-cpp.so.18.1 0x00007ef331f19ceb clang::ento::ExprEngine::ProcessStmt(clang::Stmt const*, clang::ento::ExplodedNode*) + 635
12 libclang-cpp.so.18.1 0x00007ef331f25572 clang::ento::ExprEngine::processCFGElement(clang::CFGElement, clang::ento::ExplodedNode*, unsigned int, clang::ento::NodeBuilderContext*) + 242
13 libclang-cpp.so.18.1 0x00007ef331ee7a1e clang::ento::CoreEngine::HandlePostStmt(clang::CFGBlock const*, unsigned int, clang::ento::ExplodedNode*) + 78
14 libclang-cpp.so.18.1 0x00007ef331ee7d9f clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) + 223
15 libclang-cpp.so.18.1 0x00007ef332300347
16 libclang-cpp.so.18.1 0x00007ef33230e65f
17 libclang-cpp.so.18.1 0x00007ef331cbf668 clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&) + 40
18 libclang-cpp.so.18.1 0x00007ef32feacefd clang::ParseAST(clang::Sema&, bool, bool) + 1165
19 libclang-cpp.so.18.1 0x00007ef331c841b9 clang::FrontendAction::Execute() + 153
20 libclang-cpp.so.18.1 0x00007ef331c0e5b0 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 288
21 libclang-cpp.so.18.1 0x00007ef331e45204 clang::tooling::FrontendActionFactory::runInvocation(std::shared_ptr<clang::CompilerInvocation>, clang::FileManager*, std::shared_ptr<clang::PCHContainerOperations>, clang::DiagnosticConsumer*) + 340
22 clang-tidy           0x000000000169c685
23 libclang-cpp.so.18.1 0x00007ef331e3d905 clang::tooling::ToolInvocation::runInvocation(char const*, clang::driver::Compilation*, std::shared_ptr<clang::CompilerInvocation>, std::shared_ptr<clang::PCHContainerOperations>) + 101
24 libclang-cpp.so.18.1 0x00007ef331e4065d clang::tooling::ToolInvocation::run() + 1325
25 libclang-cpp.so.18.1 0x00007ef331e42610 clang::tooling::ClangTool::run(clang::tooling::ToolAction*) + 2080
26 clang-tidy           0x00000000016a7569 clang::tidy::runClangTidy(clang::tidy::ClangTidyContext&, clang::tooling::CompilationDatabase const&, llvm::ArrayRef<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>, bool, bool, llvm::StringRef) + 1001
27 clang-tidy           0x00000000008171c5 clang::tidy::clangTidyMain(int, char const**) + 2869
28 libc.so.6            0x00007ef328a41f3b
29 libc.so.6            0x00007ef328a41ff9 __libc_start_main + 137
30 clang-tidy           0x0000000000810c65 _start + 37
Segmentation fault

Note that this stack trace was produced when compiling exactly the minimal example in place of the original source that exhibited the issue. However, the same issue is currently also reproducible in clang-tidy (trunk) on godbolt.org:

https://godbolt.org/z/93Tqv4n8x

As an explanatory aside: our project uses a thread-safe wrapper for strerror in a custom namespace that is implemented in terms of std::generic_category().message(errnum) to appease concurrency-mt-unsafe check.

@EugeneZelenko EugeneZelenko added clang:static analyzer crash Prefer [crash-on-valid] or [crash-on-invalid] and removed clang-tidy labels Apr 9, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Apr 9, 2024

@llvm/issue-subscribers-clang-static-analyzer

Author: Ilya A. Kriveshko (iillyyaa)

Use of a function named `strerror` in a private namespace causes clang-tidy to crash. If the function is renamed to anything else (e.g. `strerrorX`) the crash disappears.

Minimal program that shows this issue:

#include &lt;string&gt;

namespace other {
std::string strerror(int errnum);

void test() {
    (void)strerror(0);
}
} // namespace other

Running this through clang-tidy in LLVM 18.1.2 leads to:

Error running 'clang-tidy': PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: clang-tidy -warnings-as-errors=* -header-filter=/home/ilyak/veo/crux -extra-arg=-Wpedantic -extra-arg=-Wno-sign-conversion -extra-arg=-Wno-unknown-pragmas -extra-arg-before=--target=x86_64-oe-linux -p=/home/ilyak/veo/crux/release.scarthgap --extra-arg-before=--driver-mode=g++ /home/ilyak/veo/crux/lib/thread/attrib.cpp -- /home/ilyak/veo/oe-scarthgap/tmp/build-glibc/sysroots/x86_64/usr/bin/x86_64-oe-linux/x86_64-oe-linux-g++ -m64 -march=x86-64-v3 --sysroot=/home/ilyak/veo/oe-scarthgap/tmp/build-glibc/sysroots/intel-skylake-64 --sysroot=/home/ilyak/veo/oe-scarthgap/tmp/build-glibc/sysroots/intel-skylake-64 -DBACKWARD_HAS_BACKTRACE=0 -DBACKWARD_HAS_BACKTRACE_SYMBOL=0 -DBACKWARD_HAS_BFD=0 -DBACKWARD_HAS_DW=1 -DBACKWARD_HAS_DWARF=0 -DBACKWARD_HAS_LIBUNWIND=0 -DBACKWARD_HAS_UNWIND=1 -DFMT_SHARED -Dthread_EXPORTS -I/home/ilyak/veo/crux/lib/thread/include -I/home/ilyak/veo/crux/lib/log/include -I/home/ilyak/veo/oe-scarthgap/tmp/build-glibc/sysroots/intel-skylake-64/usr/lib/backward -I/home/ilyak/veo/crux/lib/veofmt/include -O2 -pipe -g -feliminate-unused-debug-types -O3 -DNDEBUG -std=c++20 -fPIC -Wall -Wpedantic -Wconversion -Werror -Wextra -Wno-psabi -MD -MT lib/thread/CMakeFiles/thread.dir/attrib.cpp.o -MF CMakeFiles/thread.dir/attrib.cpp.o.d -o CMakeFiles/thread.dir/attrib.cpp.o -c /home/ilyak/veo/crux/lib/thread/attrib.cpp
1.	&lt;eof&gt; parser at end of file
2.	While analyzing stack: 
	#<!-- -->0 Calling other::test()
3.	/home/ilyak/veo/crux/lib/thread/attrib.cpp:7:11: Error evaluating statement
4.	/home/ilyak/veo/crux/lib/thread/attrib.cpp:7:11: Error evaluating statement
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  libLLVM.so.18.1      0x00007ef329b2c1a4 llvm::sys::RunSignalHandlers() + 52
1  libLLVM.so.18.1      0x00007ef329b2c456
2  libc.so.6            0x00007ef328a57270
3  libclang-cpp.so.18.1 0x00007ef331f62f43 clang::ento::MemRegion::getBaseRegion() const + 3
4  libclang-cpp.so.18.1 0x00007ef3320fd519
5  libclang-cpp.so.18.1 0x00007ef3320feb15
6  libclang-cpp.so.18.1 0x00007ef331edf053
7  libclang-cpp.so.18.1 0x00007ef331edf4aa clang::ento::CheckerManager::runCheckersForCallEvent(bool, clang::ento::ExplodedNodeSet&amp;, clang::ento::ExplodedNodeSet const&amp;, clang::ento::CallEvent const&amp;, clang::ento::ExprEngine&amp;, bool) + 90
8  libclang-cpp.so.18.1 0x00007ef331f40384 clang::ento::ExprEngine::evalCall(clang::ento::ExplodedNodeSet&amp;, clang::ento::ExplodedNode*, clang::ento::CallEvent const&amp;) + 740
9  libclang-cpp.so.18.1 0x00007ef331f40c2a clang::ento::ExprEngine::VisitCallExpr(clang::CallExpr const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&amp;) + 506
10 libclang-cpp.so.18.1 0x00007ef331f16fe6 clang::ento::ExprEngine::Visit(clang::Stmt const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&amp;) + 1270
11 libclang-cpp.so.18.1 0x00007ef331f19ceb clang::ento::ExprEngine::ProcessStmt(clang::Stmt const*, clang::ento::ExplodedNode*) + 635
12 libclang-cpp.so.18.1 0x00007ef331f25572 clang::ento::ExprEngine::processCFGElement(clang::CFGElement, clang::ento::ExplodedNode*, unsigned int, clang::ento::NodeBuilderContext*) + 242
13 libclang-cpp.so.18.1 0x00007ef331ee7a1e clang::ento::CoreEngine::HandlePostStmt(clang::CFGBlock const*, unsigned int, clang::ento::ExplodedNode*) + 78
14 libclang-cpp.so.18.1 0x00007ef331ee7d9f clang::ento::CoreEngine::ExecuteWorkList(clang::LocationContext const*, unsigned int, llvm::IntrusiveRefCntPtr&lt;clang::ento::ProgramState const&gt;) + 223
15 libclang-cpp.so.18.1 0x00007ef332300347
16 libclang-cpp.so.18.1 0x00007ef33230e65f
17 libclang-cpp.so.18.1 0x00007ef331cbf668 clang::MultiplexConsumer::HandleTranslationUnit(clang::ASTContext&amp;) + 40
18 libclang-cpp.so.18.1 0x00007ef32feacefd clang::ParseAST(clang::Sema&amp;, bool, bool) + 1165
19 libclang-cpp.so.18.1 0x00007ef331c841b9 clang::FrontendAction::Execute() + 153
20 libclang-cpp.so.18.1 0x00007ef331c0e5b0 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&amp;) + 288
21 libclang-cpp.so.18.1 0x00007ef331e45204 clang::tooling::FrontendActionFactory::runInvocation(std::shared_ptr&lt;clang::CompilerInvocation&gt;, clang::FileManager*, std::shared_ptr&lt;clang::PCHContainerOperations&gt;, clang::DiagnosticConsumer*) + 340
22 clang-tidy           0x000000000169c685
23 libclang-cpp.so.18.1 0x00007ef331e3d905 clang::tooling::ToolInvocation::runInvocation(char const*, clang::driver::Compilation*, std::shared_ptr&lt;clang::CompilerInvocation&gt;, std::shared_ptr&lt;clang::PCHContainerOperations&gt;) + 101
24 libclang-cpp.so.18.1 0x00007ef331e4065d clang::tooling::ToolInvocation::run() + 1325
25 libclang-cpp.so.18.1 0x00007ef331e42610 clang::tooling::ClangTool::run(clang::tooling::ToolAction*) + 2080
26 clang-tidy           0x00000000016a7569 clang::tidy::runClangTidy(clang::tidy::ClangTidyContext&amp;, clang::tooling::CompilationDatabase const&amp;, llvm::ArrayRef&lt;std::__cxx11::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;&gt;, llvm::IntrusiveRefCntPtr&lt;llvm::vfs::OverlayFileSystem&gt;, bool, bool, llvm::StringRef) + 1001
27 clang-tidy           0x00000000008171c5 clang::tidy::clangTidyMain(int, char const**) + 2869
28 libc.so.6            0x00007ef328a41f3b
29 libc.so.6            0x00007ef328a41ff9 __libc_start_main + 137
30 clang-tidy           0x0000000000810c65 _start + 37
Segmentation fault

Note that this stack trace was produced when compiling exactly the minimal example in place of the original source that exhibited the issue. However, the same issue is currently also reproducible in clang-tidy (trunk) on godbolt.org:

https://godbolt.org/z/93Tqv4n8x

As an explanatory aside: our project uses a thread-safe wrapper for strerror in a custom namespace that is implemented in terms of std::generic_category().message(errnum) to appease concurrency-mt-unsafe check.

@steakhal steakhal changed the title LLVM 18 clang-tidy crashes when analyzing a call to a function named strerror [analyzer] Crashes when analyzing a call to a user-defined function named strerror Apr 13, 2024
steakhal added a commit to steakhal/llvm-project that referenced this issue Apr 17, 2024
tstellar pushed a commit to steakhal/llvm-project that referenced this issue Apr 23, 2024
NagyDonat added a commit to Ericsson/llvm-project that referenced this issue May 16, 2024
This commit deletes the "simple" constructor of `CallDescription` which
did not require a `CallDescription::Mode` argument and always used the
"wildcard" mode `CDM::Unspecified`.

A few months ago, this vague matching mode was used by many checkers,
which caused bugs like llvm#81597 and llvm#88181. Since then, my commits
improved the available matching modes and ensured that all checkers
explicitly specify the right matching mode.

After those commits, the only remaining references to the "simple"
constructor were some unit tests; this commit updates them to use an
explicitly specified matching mode (often `CDM::SimpleFunc`).

The mode `CDM::Unspecified` was not deleted in this commit because it's
still a reasonable choice in `GenericTaintChecker` and a few unit tests.
NagyDonat added a commit that referenced this issue May 17, 2024
…92454)

This commit deletes the "simple" constructor of `CallDescription` which
did not require a `CallDescription::Mode` argument and always used the
"wildcard" mode `CDM::Unspecified`.

A few months ago, this vague matching mode was used by many checkers,
which caused bugs like #81597
and #88181. Since then, my
commits improved the available matching modes and ensured that all
checkers explicitly specify the right matching mode.

After those commits, the only remaining references to the "simple"
constructor were some unit tests; this commit updates them to use an
explicitly specified matching mode (often `CDM::SimpleFunc`).

The mode `CDM::Unspecified` was not deleted in this commit because it's
still a reasonable choice in `GenericTaintChecker` and a few unit tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:static analyzer crash Prefer [crash-on-valid] or [crash-on-invalid]
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants