From a48c8abcda5e322de295e76cd9c50dc2c06ae98c Mon Sep 17 00:00:00 2001 From: rikardfalkeborn Date: Thu, 10 Jan 2019 18:32:17 +0100 Subject: [PATCH] Fix 8124: False positive va_end missing with lambda (#1577) Skip lambdas, to avoid false positives due to possible return statements in lambdas. Also, run dmake. --- Makefile | 2 +- lib/checkvaarg.cpp | 5 +++++ test/testvaarg.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ce5690cb3..b887e10b9 100644 --- a/Makefile +++ b/Makefile @@ -430,7 +430,7 @@ $(SRCDIR)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp lib/checkunusedfu $(SRCDIR)/checkunusedvar.o: lib/checkunusedvar.cpp lib/checkunusedvar.h lib/check.h lib/config.h lib/errorlogger.h lib/suppressions.h lib/settings.h lib/importproject.h lib/platform.h lib/utils.h lib/library.h lib/mathlib.h lib/standards.h lib/timer.h lib/token.h lib/valueflow.h lib/templatesimplifier.h lib/tokenize.h lib/tokenlist.h lib/astutils.h lib/symboldatabase.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/checkunusedvar.o $(SRCDIR)/checkunusedvar.cpp -$(SRCDIR)/checkvaarg.o: lib/checkvaarg.cpp lib/checkvaarg.h lib/check.h lib/config.h lib/errorlogger.h lib/suppressions.h lib/settings.h lib/importproject.h lib/platform.h lib/utils.h lib/library.h lib/mathlib.h lib/standards.h lib/timer.h lib/token.h lib/valueflow.h lib/templatesimplifier.h lib/tokenize.h lib/tokenlist.h lib/symboldatabase.h +$(SRCDIR)/checkvaarg.o: lib/checkvaarg.cpp lib/checkvaarg.h lib/check.h lib/config.h lib/errorlogger.h lib/suppressions.h lib/settings.h lib/importproject.h lib/platform.h lib/utils.h lib/library.h lib/mathlib.h lib/standards.h lib/timer.h lib/token.h lib/valueflow.h lib/templatesimplifier.h lib/tokenize.h lib/tokenlist.h lib/astutils.h lib/symboldatabase.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/checkvaarg.o $(SRCDIR)/checkvaarg.cpp $(SRCDIR)/cppcheck.o: lib/cppcheck.cpp lib/cppcheck.h lib/analyzerinfo.h lib/config.h lib/errorlogger.h lib/suppressions.h lib/importproject.h lib/platform.h lib/utils.h lib/check.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/timer.h lib/token.h lib/valueflow.h lib/templatesimplifier.h lib/tokenize.h lib/tokenlist.h lib/checkunusedfunctions.h lib/ctu.h lib/path.h lib/preprocessor.h lib/version.h diff --git a/lib/checkvaarg.cpp b/lib/checkvaarg.cpp index 5a6e205ab..b775b02d1 100644 --- a/lib/checkvaarg.cpp +++ b/lib/checkvaarg.cpp @@ -18,6 +18,7 @@ #include "checkvaarg.h" +#include "astutils.h" #include "errorlogger.h" #include "settings.h" #include "symboldatabase.h" @@ -107,6 +108,10 @@ void CheckVaarg::va_list_usage() const Token* tok = var->nameToken()->next(); for (; tok && tok != var->scope()->bodyEnd; tok = tok->next()) { + // Skip lambdas + const Token* tok2 = findLambdaEndToken(tok); + if (tok2) + tok = tok2; if (Token::Match(tok, "va_start ( %varid%", var->declarationId())) { if (open) va_start_subsequentCallsError(tok, var->name()); diff --git a/test/testvaarg.cpp b/test/testvaarg.cpp index 3040a4588..9d089ba76 100644 --- a/test/testvaarg.cpp +++ b/test/testvaarg.cpp @@ -155,6 +155,32 @@ private: " va_end(arg_ptr);\n" "}"); ASSERT_EQUALS("[test.cpp:4]: (error) va_list 'arg_ptr' was opened but not closed by va_end().\n", errout.str()); + + // #8124 + check("void f(int n, ...)\n" + "{\n" + " va_list ap;\n" + " va_start(ap, n);\n" + " std::vector v(n);\n" + " std::generate_n(v.begin(), n, [&ap]()\n" + " {\n" + " return va_arg(ap, const char*);\n" + " });\n" + " va_end(ap);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void f(int n, ...)\n" + "{\n" + " va_list ap;\n" + " va_start(ap, n);\n" + " std::vector v(n);\n" + " std::generate_n(v.begin(), n, [&ap]()\n" + " {\n" + " return va_arg(ap, const char*);\n" + " });\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:10]: (error) va_list 'ap' was opened but not closed by va_end().\n", errout.str()); } void va_list_usedBeforeStarted() {