From 7a75aa084b5abff894a737056581e992347e1efb Mon Sep 17 00:00:00 2001 From: Ken-Patrick Lehrmann Date: Sun, 1 Sep 2019 14:51:40 +0200 Subject: [PATCH] Fix crash in CheckUninitVar (#2129) http://cppcheck.osuosl.org:8000/ycmd ``` 2019-08-30 23:21 ftp://ftp.se.debian.org/debian/pool/main/y/ycmd/ycmd_0+20181101+git600f54d.orig.tar.gz cppcheck-options: -j1 --library=posix --library=gnu --library=qt --library=python --library=googletest --library=boost -D__GNUC__ --check-library --inconclusive --enable=style,information --platform=unix64 --template=daca2 -rp=temp temp platform: Linux-4.15.0-58-generic-x86_64-with-Ubuntu-18.04-bionic python: 2.7.15+ client-version: 1.1.31 cppcheck: head 1.88 count: Crash! 83 elapsed-time: -11.0 61.2 head results: Checking temp/ycmd-0+20181101+git600f54d/ycmd/tests/clang/testdata/completion_fixit.cc: __GNUC__=1... Program received signal SIGSEGV, Segmentation fault. CheckUninitVar::valueFlowUninit (this=this@entry=0x7fffffffb350) at build/checkuninitvar.cpp:2376 2376 if (!tok->variable()) #0 CheckUninitVar::valueFlowUninit (this=this@entry=0x7fffffffb350) at build/checkuninitvar.cpp:2376 #1 0x00005555556901ac in CheckUninitVar::runChecks (this=, tokenizer=0x7fffffffbcb0, settings=0x7fffffffcd10, errorLogger=) at lib/checkuninitvar.h:68 #2 0x00005555556a2210 in CppCheck::checkNormalTokens (this=this@entry=0x7fffffffcaf0, tokenizer=...) at build/cppcheck.cpp:730 #3 0x00005555556a6ee2 in CppCheck::checkFile (this=this@entry=0x7fffffffcaf0, filename="temp/ycmd-0+20181101+git600f54d/ycmd/tests/clang/testdata/completion_fixit.cc", cfgname="", fileStream=...) at build/cppcheck.cpp:540 #4 0x00005555556aad4c in CppCheck::check (this=this@entry=0x7fffffffcaf0, path="temp/ycmd-0+20181101+git600f54d/ycmd/tests/clang/testdata/completion_fixit.cc") at build/cppcheck.cpp:195 #5 0x00005555557ef167 in CppCheckExecutor::check_internal (this=this@entry=0x7fffffffd880, cppcheck=..., argv=argv@entry=0x7fffffffdc08) at cli/cppcheckexecutor.cpp:884 #6 0x00005555557efa9a in CppCheckExecutor::check (this=0x7fffffffd880, argc=17, argv=0x7fffffffdc08) at cli/cppcheckexecutor.cpp:198 #7 0x00005555555b1d1b in main (argc=17, argv=0x7fffffffdc08) at cli/main.cpp:95 ``` --- lib/checkuninitvar.cpp | 2 +- test/testuninitvar.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 7dc76b3ca..d0a03f7c5 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1333,7 +1333,7 @@ void CheckUninitVar::valueFlowUninit() for (const Scope &scope : symbolDatabase->scopeList) { if (!scope.isExecutable()) continue; - for (const Token* tok = scope.bodyStart; tok != scope.bodyEnd; tok = tok->next()) { + for (const Token* tok = scope.bodyStart; tok && tok != scope.bodyEnd; tok = tok->next()) { if (Token::simpleMatch(tok, "sizeof (")) { tok = tok->linkAt(1); continue; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 8914e55a8..c4982854d 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -83,6 +83,7 @@ private: TEST_CASE(valueFlowUninit); TEST_CASE(uninitvar_ipa); TEST_CASE(uninitvar_memberfunction); + TEST_CASE(uninitvar_nonmember); // crash in ycmd test TEST_CASE(isVariableUsageDeref); // *p @@ -4441,6 +4442,18 @@ private: ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: c\n", errout.str()); } + void uninitvar_nonmember() { + valueFlowUninit( "struct Foo {\n" + " int bar;\n" + "};\n" + "\n" + "int main() {\n" + " Foo* foo;\n" + " foo.b\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: foo\n", errout.str()); + } + void isVariableUsageDeref() { // *p checkUninitVar("void f() {\n"