From 5f09d535dbad502171247797061e578b1b86ea8e Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Thu, 11 Jul 2024 23:37:36 +0200 Subject: [PATCH] Fix #9657 FP on missing va_end() after non-returning function --- lib/checkvaarg.cpp | 19 +++++++++++++++++-- test/testvaarg.cpp | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/checkvaarg.cpp b/lib/checkvaarg.cpp index 7ad381e16d0..8b0f3d87145 100644 --- a/lib/checkvaarg.cpp +++ b/lib/checkvaarg.cpp @@ -144,9 +144,24 @@ void CheckVaarg::va_list_usage() } open = nopen; tok = tok->linkAt(1); - } else if (Token::Match(tok, "throw|return")) + } else if (Token::Match(tok, "throw|return") || (Token::Match(tok, "%name% (") && mSettings->library.isnoreturn(tok))) { exitOnEndOfStatement = true; - else if (tok->str() == "break") { + if (var->scope() == tok->scope()) { + if (const Token* tok3 = Token::findmatch(tok->next(), "%varid%|;", var->declarationId())) { + bool bail = tok3->str() == ";"; + if (!bail) { + int argn{}; + if (const Token* ftok = getTokenArgumentFunction(tok3, argn)) { + bail = ftok->str() != "va_arg"; + } + } + if (bail) { + open = false; + break; + } + } + } + } else if (tok->str() == "break") { tok = findNextTokenFromBreak(tok); if (!tok) return; diff --git a/test/testvaarg.cpp b/test/testvaarg.cpp index f4a42a4a111..7d94ff2cb75 100644 --- a/test/testvaarg.cpp +++ b/test/testvaarg.cpp @@ -309,6 +309,22 @@ class TestVaarg : public TestFixture { "format_err:\n" "}"); ASSERT_EQUALS("", errout_str()); + + // #9657 + check("static void __attribute__((__noreturn__)) __attribute__((__format__(__printf__, 1, 0)))\n" + " notreturning(const char* fmt, va_list args) {\n" + " va_list args_copy;\n" + " va_copy(args_copy, args);\n" + " vprintf(fmt, args_copy);\n" + " va_end(args_copy);\n" + " exit(1);\n" + "}\n" + "static void check_noret_va_end(const char* fmt, ...) {\n" + " va_list args;\n" + " va_start(args, fmt);\n" + " notreturning(fmt, args);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void va_start_subsequentCalls() {