From e70ccd73f8517b806d5beff68a6f7bf52abb4252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 12 Nov 2024 09:22:10 +0100 Subject: [PATCH 1/4] fix #13098 & #11685 for C23 --- lib/vf_number.cpp | 3 ++- test/testleakautovar.cpp | 10 ++++++++++ test/testtype.cpp | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/vf_number.cpp b/lib/vf_number.cpp index 9d0c820213b..980c4e7fe43 100644 --- a/lib/vf_number.cpp +++ b/lib/vf_number.cpp @@ -18,6 +18,7 @@ #include "vf_number.h" +#include "settings.h" #include "token.h" #include "tokenlist.h" #include "vfvalue.h" @@ -36,7 +37,7 @@ namespace ValueFlow tok = valueFlowSetConstantValue(tok, settings); } - if (tokenlist.isCPP()) { + if (tokenlist.isCPP() || settings.standards.c >= Standards::C23) { for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { if (tok->isName() && !tok->varId() && Token::Match(tok, "false|true")) { ValueFlow::Value value(tok->str() == "true"); diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 05eee11a21b..05f425c1798 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -2756,6 +2756,16 @@ class TestLeakAutoVar : public TestFixture { " return 'a';\n" "}\n", true); ASSERT_EQUALS("[test.cpp:7]: (error) Memory leak: ptr\n", errout_str()); + + check("char malloc_memleak(void) {\n" + " bool flag = false;\n" + " char *ptr = malloc(10);\n" + " if (flag) {\n" + " free(ptr);\n" + " }\n" + " return 'a';\n" + "}\n", false); + ASSERT_EQUALS("[test.c:7]: (error) Memory leak: ptr\n", errout_str()); } void test1() { diff --git a/test/testtype.cpp b/test/testtype.cpp index f40cd4c0652..f6a2fd36d29 100644 --- a/test/testtype.cpp +++ b/test/testtype.cpp @@ -533,6 +533,21 @@ class TestType : public TestFixture { " return false || f((unsigned short)75000.0);\n" "}\n", settingsDefault); ASSERT_EQUALS("[test.cpp:3]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout_str())); + + checkP("#define TEST(b, f) b ? 5000 : (unsigned short)f\n" // #11685 + "void f()\n" + "{\n" + " unsigned short u = TEST(true, 75000.0);\n" + "}\n", settingsDefault, "test.c"); + ASSERT_EQUALS("", errout_str()); + + checkP("#define TEST(b, f) b ? 5000 : (unsigned short)f\n" + "void f()\n" + "{\n" + " unsigned short u = TEST(false, 75000.0);\n" + "}\n", settingsDefault, "test.c"); + ASSERT_EQUALS("[test.c:4]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout_str())); + } void integerOverflow() { // #11794 From 0f03d177cf8ef0529318bc204f9457cdabf39c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 12 Nov 2024 09:32:39 +0100 Subject: [PATCH 2/4] update Makefile --- Makefile | 2 +- oss-fuzz/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 66703968cc3..2ca50e96293 100644 --- a/Makefile +++ b/Makefile @@ -726,7 +726,7 @@ $(libcppdir)/vf_iteratorinfer.o: lib/vf_iteratorinfer.cpp lib/config.h lib/error $(libcppdir)/vf_iterators.o: lib/vf_iterators.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vf_iterators.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_iterators.cpp -$(libcppdir)/vf_number.o: lib/vf_number.cpp lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vf_common.h lib/vf_number.h lib/vf_settokenvalue.h lib/vfvalue.h +$(libcppdir)/vf_number.o: lib/vf_number.cpp lib/addoninfo.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vf_common.h lib/vf_number.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_number.cpp $(libcppdir)/vf_pointeralias.o: lib/vf_pointeralias.cpp lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vf_pointeralias.h lib/vf_settokenvalue.h lib/vfvalue.h diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index 6603ad927f6..a0d1c2521d1 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -413,7 +413,7 @@ $(libcppdir)/vf_iteratorinfer.o: ../lib/vf_iteratorinfer.cpp ../lib/config.h ../ $(libcppdir)/vf_iterators.o: ../lib/vf_iterators.cpp ../lib/astutils.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vf_iterators.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_iterators.cpp -$(libcppdir)/vf_number.o: ../lib/vf_number.cpp ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vf_common.h ../lib/vf_number.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h +$(libcppdir)/vf_number.o: ../lib/vf_number.cpp ../lib/addoninfo.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vf_common.h ../lib/vf_number.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_number.cpp $(libcppdir)/vf_pointeralias.o: ../lib/vf_pointeralias.cpp ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vf_pointeralias.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h From 5d4f3fcf26ea2492dcff6026dd8cfa270d560929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 12 Nov 2024 10:44:20 +0100 Subject: [PATCH 3/4] add tests for boolean valueflow --- test/testvalueflow.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 3ee34f142e9..34ddf44c79e 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -489,9 +489,9 @@ class TestValueFlow : public TestFixture { } #define tokenValues(...) tokenValues_(__FILE__, __LINE__, __VA_ARGS__) - std::list tokenValues_(const char* file, int line, const char code[], const char tokstr[], const Settings *s = nullptr) { + std::list tokenValues_(const char* file, int line, const char code[], const char tokstr[], const Settings *s = nullptr, bool cpp = true) { SimpleTokenizer tokenizer(s ? *s : settings, *this); - ASSERT_LOC(tokenizer.tokenize(code), file, line); + ASSERT_LOC(tokenizer.tokenize(code, cpp), file, line); const Token *tok = Token::findmatch(tokenizer.tokens(), tokstr); return tok ? tok->values() : std::list(); } @@ -523,9 +523,9 @@ class TestValueFlow : public TestFixture { return result; } -#define valueOfTok(code, tokstr) valueOfTok_(code, tokstr, __FILE__, __LINE__) - ValueFlow::Value valueOfTok_(const char code[], const char tokstr[], const char* file, int line) { - std::list values = removeImpossible(tokenValues_(file, line, code, tokstr)); +#define valueOfTok(...) valueOfTok_(__FILE__, __LINE__, __VA_ARGS__) + ValueFlow::Value valueOfTok_(const char* file, int line, const char code[], const char tokstr[], const Settings *settings = nullptr, bool cpp = true) { + std::list values = removeImpossible(tokenValues_(file, line, code, tokstr, settings, cpp)); return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value(); } @@ -557,6 +557,14 @@ class TestValueFlow : public TestFixture { ASSERT_EQUALS_DOUBLE(16, valueOfTok("x=(double)16;", "(").floatValue, 1e-5); ASSERT_EQUALS_DOUBLE(0.0625, valueOfTok("x=1/(double)16;", "/").floatValue, 1e-5); + const Settings settingsC23 = settingsBuilder().c(Standards::C23).build(); + ASSERT_EQUALS(1, valueOfTok("x=true;", "true", &settingsC23, false).intvalue); + ASSERT_EQUALS(0, valueOfTok("x=false;", "false", &settingsC23, false).intvalue); + + const Settings settingsC17 = settingsBuilder().c(Standards::C17).build(); + ASSERT(!valueOfTok("x=true;", "true", &settingsC17, false).isKnown()); + ASSERT(!valueOfTok("x=false;", "false", &settingsC17, false).isKnown()); + // scope { const char code[] = "namespace N { enum E {e0,e1}; }\n" From c0d990e6e9191c385abfd7c350b193a862699925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 12 Nov 2024 10:51:48 +0100 Subject: [PATCH 4/4] avoid shadowing --- test/testvalueflow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 34ddf44c79e..0c6a5a41605 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -524,8 +524,8 @@ class TestValueFlow : public TestFixture { } #define valueOfTok(...) valueOfTok_(__FILE__, __LINE__, __VA_ARGS__) - ValueFlow::Value valueOfTok_(const char* file, int line, const char code[], const char tokstr[], const Settings *settings = nullptr, bool cpp = true) { - std::list values = removeImpossible(tokenValues_(file, line, code, tokstr, settings, cpp)); + ValueFlow::Value valueOfTok_(const char* file, int line, const char code[], const char tokstr[], const Settings *s = nullptr, bool cpp = true) { + std::list values = removeImpossible(tokenValues_(file, line, code, tokstr, s, cpp)); return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value(); }