Trying to check a CPP file having a single #include <iostream> in it triggers a segfault when using Clang-16 parser.
$gdb--args./bin/cppcheck--clang=/usr/bin/clang++-16test.cpp(gdb)r
Startingprogram:/home/aland/cppcheck/build/bin/cppcheck--clang=/usr/bin/clang++-16test.cpp
[Threaddebuggingusinglibthread_dbenabled]
Usinghostlibthread_dblibrary"/lib/x86_64-linux-gnu/libthread_db.so.1".
Checkingtest.cpp...
[Detachingaftervforkfromchildprocess593957]
ProgramreceivedsignalSIGSEGV,Segmentationfault.
Variable::declarationId(this=0x55555762fc60)atlib/symboldatabase.h:318
318returnmNameToken->varId();(gdb)bt
#0 Variable::declarationId (this=0x55555762fc60) at lib/symboldatabase.h:318#1 clangimport::Data::getVariableList (this=0x7fffffffb280) at lib/clangimport.cpp:285#2 clangimport::parseClangAstDump (tokenizer=tokenizer@entry=0x7fffffffb6f0, f=...) at /home/aland/cppcheck/lib/clangimport.cpp:1629#3 0x0000555555786a53 in CppCheck::check (this=0x7fffffffc880, path="test.cpp") at lib/cppcheck.cpp:546#4 0x0000555555636e09 in SingleExecutor::check (this=this@entry=0x7fffffffbca0) at cli/singleexecutor.cpp:60#5 0x0000555555623efc in CppCheckExecutor::check_internal (this=0x7fffffffd860, cppcheck=...) at cli/cppcheckexecutor.cpp:289#6 0x0000555555624fc3 in CppCheckExecutor::check (this=this@entry=0x7fffffffd860, argc=argc@entry=3, argv=argv@entry=0x7fffffffda18) at cli/cppcheckexecutor.cpp:223#7 0x0000555555609e02 in main (argc=3, argv=0x7fffffffda18) at cli/main.cpp:91
A self-containing example triggering a similar segfault, but less reliably:
I can also reproduce this with clang 15.0.7 (Fedora 15.0.7-2.fc37) on CppCheck 5a7c7b9b5a17a8fcd212e7b77f6b5777b6c34479 (current git main). AddressSanitizer says it's a use-after-free:
$cppcheck/build/bin/cppcheck--clang=/usr/bin/clang++-15--cppcheck-build-dir=cppcheck_build_dirtest1.cppCheckingtest1.cpp...===================================================================1021405==ERROR:AddressSanitizer:heap-use-after-freeonaddress0x60c000006dc0atpc0x000000da8b5bbp0x7ffdf6182690sp0x7ffdf6182688READofsize8at0x60c000006dc0threadT0#00xda8b5ainVariable::declarationId()const/tmp/cppcheck_test/cppcheck/lib/symboldatabase.h:302#10x12e551einclangimport::Data::getVariableList()const/tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:284#20x12df477inclangimport::parseClangAstDump(Tokenizer*,std::istream&)/tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:1628#30x134b94dinCppCheck::check(std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>const&)/tmp/cppcheck_test/cppcheck/lib/cppcheck.cpp:542#40xd2e88dinSingleExecutor::check()/tmp/cppcheck_test/cppcheck/cli/singleexecutor.cpp:57#50xc9fdbbinCppCheckExecutor::check_internal(CppCheck&)/tmp/cppcheck_test/cppcheck/cli/cppcheckexecutor.cpp:303#60xc9ecbainCppCheckExecutor::check(int,charconst*const*)/tmp/cppcheck_test/cppcheck/cli/cppcheckexecutor.cpp:237#70xc5f780inmain/tmp/cppcheck_test/cppcheck/cli/main.cpp:91#80x7f7839e4a50fin__libc_start_call_main(/lib64/libc.so.6+0x2750f)#90x7f7839e4a5c8in__libc_start_main@GLIBC_2.2.5(/lib64/libc.so.6+0x275c8)#100xc5f5f4in_start(/tmp/cppcheck_test/cppcheck/build/bin/cppcheck+0xc5f5f4)0x60c000006dc0islocated0bytesinsideof120-byteregion[0x60c000006dc0,0x60c000006e38)freed by thread T0 here: #0 0x7f783a4bbbe8 in operator delete(void*) (/lib64/libasan.so.8+0xbbbe8) #1 0x1148429 in std::__new_allocator<Variable>::deallocate(Variable*, unsigned long) /usr/include/c++/12/bits/new_allocator.h:158 #2 0x1147397 in std::allocator_traits<std::allocator<Variable> >::deallocate(std::allocator<Variable>&, Variable*, unsigned long) /usr/include/c++/12/bits/alloc_traits.h:496 #3 0x114364b in std::__cxx1998::_Vector_base<Variable, std::allocator<Variable> >::_M_deallocate(Variable*, unsigned long) /usr/include/c++/12/bits/stl_vector.h:387 #4 0x1303c29 in std::__cxx1998::vector<Variable, std::allocator<Variable> >::reserve(unsigned long) (/tmp/cppcheck_test/cppcheck/build/bin/cppcheck+0x1303c29) #5 0x12f3248 in std::__debug::vector<Variable, std::allocator<Variable> >::reserve(unsigned long) /usr/include/c++/12/debug/vector:430 #6 0x12d92ff in clangimport::AstNode::createTokensFunctionDecl(TokenList*) /tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:1376 #7 0x12ccfc4 in clangimport::AstNode::createTokens(TokenList*) /tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:837 #8 0x12e67cd in clangimport::AstNode::createTokens1(TokenList*) (/tmp/cppcheck_test/cppcheck/build/bin/cppcheck+0x12e67cd) #9 0x12df245 in clangimport::parseClangAstDump(Tokenizer*, std::istream&) /tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:1618 #10 0x134b94d in CppCheck::check(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /tmp/cppcheck_test/cppcheck/lib/cppcheck.cpp:542 #11 0xd2e88d in SingleExecutor::check() /tmp/cppcheck_test/cppcheck/cli/singleexecutor.cpp:57 #12 0xc9fdbb in CppCheckExecutor::check_internal(CppCheck&) /tmp/cppcheck_test/cppcheck/cli/cppcheckexecutor.cpp:303 #13 0xc9ecba in CppCheckExecutor::check(int, char const* const*) /tmp/cppcheck_test/cppcheck/cli/cppcheckexecutor.cpp:237 #14 0xc5f780 in main /tmp/cppcheck_test/cppcheck/cli/main.cpp:91 #15 0x7f7839e4a50f in __libc_start_call_main (/lib64/libc.so.6+0x2750f)previously allocated by thread T0 here: #0 0x7f783a4bb1a8 in operator new(unsigned long) (/lib64/libasan.so.8+0xbb1a8) #1 0x11491c5 in std::__new_allocator<Variable>::allocate(unsigned long, void const*) /usr/include/c++/12/bits/new_allocator.h:137 #2 0x1148407 in std::allocator_traits<std::allocator<Variable> >::allocate(std::allocator<Variable>&, unsigned long) /usr/include/c++/12/bits/alloc_traits.h:464 #3 0x1147363 in std::__cxx1998::_Vector_base<Variable, std::allocator<Variable> >::_M_allocate(unsigned long) /usr/include/c++/12/bits/stl_vector.h:378 #4 0x131cb4d in Variable* std::__cxx1998::vector<Variable, std::allocator<Variable> >::_M_allocate_and_copy<Variable const*>(unsigned long, Variable const*, Variable const*) /usr/include/c++/12/bits/stl_vector.h:1614 #5 0x1303b2a in std::__cxx1998::vector<Variable, std::allocator<Variable> >::reserve(unsigned long) (/tmp/cppcheck_test/cppcheck/build/bin/cppcheck+0x1303b2a) #6 0x12f3248 in std::__debug::vector<Variable, std::allocator<Variable> >::reserve(unsigned long) /usr/include/c++/12/debug/vector:430 #7 0x12d92ff in clangimport::AstNode::createTokensFunctionDecl(TokenList*) /tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:1376 #8 0x12ccfc4 in clangimport::AstNode::createTokens(TokenList*) /tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:837 #9 0x12c925b in clangimport::AstNode::createScope(TokenList*, Scope::ScopeType, std::__debug::vector<std::shared_ptr<clangimport::AstNode>, std::allocator<std::shared_ptr<clangimport::AstNode> > > const&, Token const*) /tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:700 #10 0x12db6fa in clangimport::AstNode::createTokensForCXXRecord(TokenList*) /tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:1461 #11 0x12ce679 in clangimport::AstNode::createTokens(TokenList*) /tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:918 #12 0x12e67cd in clangimport::AstNode::createTokens1(TokenList*) (/tmp/cppcheck_test/cppcheck/build/bin/cppcheck+0x12e67cd) #13 0x12dee0b in clangimport::parseClangAstDump(Tokenizer*, std::istream&) /tmp/cppcheck_test/cppcheck/lib/clangimport.cpp:1599 #14 0x134b94d in CppCheck::check(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /tmp/cppcheck_test/cppcheck/lib/cppcheck.cpp:542 #15 0xd2e88d in SingleExecutor::check() /tmp/cppcheck_test/cppcheck/cli/singleexecutor.cpp:57 #16 0xc9fdbb in CppCheckExecutor::check_internal(CppCheck&) /tmp/cppcheck_test/cppcheck/cli/cppcheckexecutor.cpp:303 #17 0xc9ecba in CppCheckExecutor::check(int, char const* const*) /tmp/cppcheck_test/cppcheck/cli/cppcheckexecutor.cpp:237 #18 0xc5f780 in main /tmp/cppcheck_test/cppcheck/cli/main.cpp:91 #19 0x7f7839e4a50f in __libc_start_call_main (/lib64/libc.so.6+0x2750f)SUMMARY: AddressSanitizer: heap-use-after-free /tmp/cppcheck_test/cppcheck/lib/symboldatabase.h:302 in Variable::declarationId() constShadow bytes around the buggy address: 0x0c187fff8d60: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa 0x0c187fff8d70: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c187fff8d80: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd 0x0c187fff8d90: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa 0x0c187fff8da0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd=>0x0c187fff8db0: fa fa fa fa fa fa fa fa[fd]fdfdfdfdfdfdfd0x0c187fff8dc0:fdfdfdfdfdfdfdfafafafafafafafafa0x0c187fff8dd0:fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd0x0c187fff8de0:fafafafafafafafa00000000000000000x0c187fff8df0:0000000000000000fafafafafafafafa0x0c187fff8e00:fafafafafafafafafafafafafafafafaShadowbytelegend(oneshadowbyterepresents8applicationbytes):Addressable:00Partiallyaddressable:01020304050607Heapleftredzone:faFreedheapregion:fdStackleftredzone:f1Stackmidredzone:f2Stackrightredzone:f3Stackafterreturn:f5Stackuseafterscope:f8Globalredzone:f9Globalinitorder:f6Poisonedbyuser:f7Containeroverflow:fcArraycookie:acIntraobjectredzone:bbASaninternal:feLeftallocaredzone:caRightallocaredzone:cb==1021405==ABORTING
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Trying to check a CPP file having a single
#include <iostream>
in it triggers a segfault when using Clang-16 parser.A self-containing example triggering a similar segfault, but less reliably:
Tested with CppCheck 3508464c6dadc42162cb618ece6b69763df44b23, Ubuntu clang version 16.0.6
Last edit: Andrey Alekseenko 2023-07-12
I can also reproduce this with clang 15.0.7 (Fedora 15.0.7-2.fc37) on CppCheck 5a7c7b9b5a17a8fcd212e7b77f6b5777b6c34479 (current git main). AddressSanitizer says it's a use-after-free:
WAG: https://github.com/danmar/cppcheck/commit/d81a758850b98c7b7114e6ed89e5245ed4a52b15 changed the type of
argumentList
fromlist
tovector
, so this will dangle after reallocation:mData->varDecl(addr, vartok, &function->argumentList.back());
Fix proposed here: https://github.com/danmar/cppcheck/pull/5367
Out of curiousity, what is your reason to use
--clang
, and how does it work in practice?Last edit: CHR 2023-08-25