From 36f2323b98bfd5e060a7657e540eb4714b078496 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 27 May 2024 10:49:23 +0200 Subject: [PATCH 1/8] ValueFlow: extracted valueFlowArrayBool() into separate file --- Makefile | 6 +++- lib/cppcheck.vcxproj | 2 ++ lib/lib.pri | 2 ++ lib/valueflow.cpp | 53 +-------------------------- lib/vf_analyze.h | 1 + lib/vf_arraybool.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++ lib/vf_arraybool.h | 30 ++++++++++++++++ oss-fuzz/Makefile | 6 +++- 8 files changed, 132 insertions(+), 54 deletions(-) create mode 100644 lib/vf_arraybool.cpp create mode 100644 lib/vf_arraybool.h diff --git a/Makefile b/Makefile index e2a15da9dc5..543242f8e17 100644 --- a/Makefile +++ b/Makefile @@ -253,6 +253,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/tokenlist.o \ $(libcppdir)/utils.o \ $(libcppdir)/vf_array.o \ + $(libcppdir)/vf_arraybool.o \ $(libcppdir)/vf_bitand.o \ $(libcppdir)/vf_common.o \ $(libcppdir)/vf_debug.o \ @@ -473,7 +474,7 @@ validateRules: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h @@ -662,6 +663,9 @@ $(libcppdir)/utils.o: lib/utils.cpp lib/config.h lib/utils.h $(libcppdir)/vf_array.o: lib/vf_array.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_array.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_array.cpp +$(libcppdir)/vf_arraybool.o: lib/vf_arraybool.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_arraybool.h lib/vf_settokenvalue.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_arraybool.cpp + $(libcppdir)/vf_bitand.o: lib/vf_bitand.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/sourcelocation.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vf_bitand.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_bitand.cpp diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 78171d08a45..7b75d94fabe 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -88,6 +88,7 @@ + @@ -181,6 +182,7 @@ + diff --git a/lib/lib.pri b/lib/lib.pri index b2bcdf5c70f..9e6746b2433 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -79,6 +79,7 @@ HEADERS += $${PWD}/addoninfo.h \ $${PWD}/version.h \ $${PWD}/vf_analyze.h \ $${PWD}/vf_array.h \ + $${PWD}/vf_arraybool.h \ $${PWD}/vf_bitand.h \ $${PWD}/vf_common.h \ $${PWD}/vf_debug.h \ @@ -157,6 +158,7 @@ SOURCES += $${PWD}/valueflow.cpp \ $${PWD}/tokenlist.cpp \ $${PWD}/utils.cpp \ $${PWD}/vf_array.cpp \ + $${PWD}/vf_arraybool.cpp \ $${PWD}/vf_bitand.cpp \ $${PWD}/vf_common.cpp \ $${PWD}/vf_debug.cpp \ diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index da7ea11a51c..96b3f6f42cb 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -540,57 +540,6 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings, int m return 0; } -static bool isNonZero(const Token *tok) -{ - return tok && (!tok->hasKnownIntValue() || tok->values().front().intvalue != 0); -} - -static const Token *getOtherOperand(const Token *tok) -{ - if (!tok) - return nullptr; - if (!tok->astParent()) - return nullptr; - if (tok->astParent()->astOperand1() != tok) - return tok->astParent()->astOperand1(); - if (tok->astParent()->astOperand2() != tok) - return tok->astParent()->astOperand2(); - return nullptr; -} - -static void valueFlowArrayBool(TokenList &tokenlist, const Settings &settings) -{ - for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { - if (tok->hasKnownIntValue()) - continue; - const Variable *var = nullptr; - bool known = false; - const std::list::const_iterator val = - std::find_if(tok->values().cbegin(), tok->values().cend(), std::mem_fn(&ValueFlow::Value::isTokValue)); - if (val == tok->values().end()) { - var = tok->variable(); - known = true; - } else { - var = val->tokvalue->variable(); - known = val->isKnown(); - } - if (!var) - continue; - if (!var->isArray() || var->isArgument() || var->isStlType()) - continue; - if (isNonZero(getOtherOperand(tok)) && Token::Match(tok->astParent(), "%comp%")) - continue; - // TODO: Check for function argument - if ((astIsBool(tok->astParent()) && !Token::Match(tok->astParent(), "(|%name%")) || - (tok->astParent() && Token::Match(tok->astParent()->previous(), "if|while|for ("))) { - ValueFlow::Value value{1}; - if (known) - value.setKnown(); - setTokenValue(tok, std::move(value), settings); - } - } -} - static void valueFlowArrayElement(TokenList& tokenlist, const Settings& settings) { for (Token* tok = tokenlist.front(); tok; tok = tok->next()) { @@ -8345,7 +8294,7 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowSymbolicOperators(symboldatabase, settings)), VFA(valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), VFA(valueFlowSymbolicInfer(symboldatabase, settings)), - VFA(valueFlowArrayBool(tokenlist, settings)), + VFA(analyzeArrayBool(tokenlist, settings)), VFA(valueFlowArrayElement(tokenlist, settings)), VFA(valueFlowRightShift(tokenlist, settings)), VFA(valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), diff --git a/lib/vf_analyze.h b/lib/vf_analyze.h index 6ad7b910f2b..82a16e48f5d 100644 --- a/lib/vf_analyze.h +++ b/lib/vf_analyze.h @@ -20,6 +20,7 @@ #define vfAnalyzeH #include "vf_array.h" // IWYU pragma: export +#include "vf_arraybool.h" // IWYU pragma: export #include "vf_bitand.h" // IWYU pragma: export #include "vf_debug.h" // IWYU pragma: export #include "vf_enumvalue.h" // IWYU pragma: export diff --git a/lib/vf_arraybool.cpp b/lib/vf_arraybool.cpp new file mode 100644 index 00000000000..41ee4cc0846 --- /dev/null +++ b/lib/vf_arraybool.cpp @@ -0,0 +1,86 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vf_arraybool.h" + +#include "astutils.h" +#include "symboldatabase.h" +#include "token.h" +#include "tokenlist.h" +#include "vfvalue.h" + +#include "vf_settokenvalue.h" + +#include +#include +#include +#include + +namespace ValueFlow +{ + static bool isNonZero(const Token *tok) + { + return tok && (!tok->hasKnownIntValue() || tok->values().front().intvalue != 0); + } + + static const Token *getOtherOperand(const Token *tok) + { + if (!tok) + return nullptr; + if (!tok->astParent()) + return nullptr; + if (tok->astParent()->astOperand1() != tok) + return tok->astParent()->astOperand1(); + if (tok->astParent()->astOperand2() != tok) + return tok->astParent()->astOperand2(); + return nullptr; + } + + void analyzeArrayBool(TokenList &tokenlist, const Settings &settings) + { + for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { + if (tok->hasKnownIntValue()) + continue; + const Variable *var = nullptr; + bool known = false; + const std::list::const_iterator val = + std::find_if(tok->values().cbegin(), tok->values().cend(), std::mem_fn(&Value::isTokValue)); + if (val == tok->values().end()) { + var = tok->variable(); + known = true; + } else { + var = val->tokvalue->variable(); + known = val->isKnown(); + } + if (!var) + continue; + if (!var->isArray() || var->isArgument() || var->isStlType()) + continue; + if (isNonZero(getOtherOperand(tok)) && Token::Match(tok->astParent(), "%comp%")) + continue; + // TODO: Check for function argument + if ((astIsBool(tok->astParent()) && !Token::Match(tok->astParent(), "(|%name%")) || + (tok->astParent() && Token::Match(tok->astParent()->previous(), "if|while|for ("))) { + Value value{1}; + if (known) + value.setKnown(); + setTokenValue(tok, std::move(value), settings); + } + } + } +} diff --git a/lib/vf_arraybool.h b/lib/vf_arraybool.h new file mode 100644 index 00000000000..be35c897bd5 --- /dev/null +++ b/lib/vf_arraybool.h @@ -0,0 +1,30 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef vfArrayBoolH +#define vfArrayBoolH + +class TokenList; +class Settings; + +namespace ValueFlow +{ + void analyzeArrayBool(TokenList &tokenlist, const Settings &settings); +} + +#endif // vfArrayBoolH diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index bd46c392669..ca7d69cd4be 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -96,6 +96,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/tokenlist.o \ $(libcppdir)/utils.o \ $(libcppdir)/vf_array.o \ + $(libcppdir)/vf_arraybool.o \ $(libcppdir)/vf_bitand.o \ $(libcppdir)/vf_common.o \ $(libcppdir)/vf_debug.o \ @@ -152,7 +153,7 @@ simplecpp.o: ../externals/simplecpp/simplecpp.cpp ../externals/simplecpp/simplec tinyxml2.o: ../externals/tinyxml2/tinyxml2.cpp ../externals/tinyxml2/tinyxml2.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ ../externals/tinyxml2/tinyxml2.cpp -$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h +$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: ../lib/tokenize.cpp ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/astutils.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/summaries.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h @@ -341,6 +342,9 @@ $(libcppdir)/utils.o: ../lib/utils.cpp ../lib/config.h ../lib/utils.h $(libcppdir)/vf_array.o: ../lib/vf_array.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_array.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_array.cpp +$(libcppdir)/vf_arraybool.o: ../lib/vf_arraybool.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_arraybool.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h + $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_arraybool.cpp + $(libcppdir)/vf_bitand.o: ../lib/vf_bitand.cpp ../lib/config.h ../lib/errortypes.h ../lib/mathlib.h ../lib/sourcelocation.h ../lib/standards.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vf_bitand.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_bitand.cpp From de9aea1bd4ed27cc325e205a6e2206e0272a7b85 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 27 May 2024 10:53:58 +0200 Subject: [PATCH 2/8] ValueFlow: extracted valueFlowArrayElement() into separate file --- Makefile | 6 ++- lib/cppcheck.vcxproj | 2 + lib/lib.pri | 2 + lib/valueflow.cpp | 79 +--------------------------- lib/vf_analyze.h | 1 + lib/vf_arrayelement.cpp | 113 ++++++++++++++++++++++++++++++++++++++++ lib/vf_arrayelement.h | 30 +++++++++++ oss-fuzz/Makefile | 6 ++- 8 files changed, 159 insertions(+), 80 deletions(-) create mode 100644 lib/vf_arrayelement.cpp create mode 100644 lib/vf_arrayelement.h diff --git a/Makefile b/Makefile index 543242f8e17..0b8a0058865 100644 --- a/Makefile +++ b/Makefile @@ -254,6 +254,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/utils.o \ $(libcppdir)/vf_array.o \ $(libcppdir)/vf_arraybool.o \ + $(libcppdir)/vf_arrayelement.o \ $(libcppdir)/vf_bitand.o \ $(libcppdir)/vf_common.o \ $(libcppdir)/vf_debug.o \ @@ -474,7 +475,7 @@ validateRules: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h @@ -666,6 +667,9 @@ $(libcppdir)/vf_array.o: lib/vf_array.cpp lib/astutils.h lib/config.h lib/errort $(libcppdir)/vf_arraybool.o: lib/vf_arraybool.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_arraybool.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_arraybool.cpp +$(libcppdir)/vf_arrayelement.o: lib/vf_arrayelement.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_arrayelement.h lib/vf_settokenvalue.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_arrayelement.cpp + $(libcppdir)/vf_bitand.o: lib/vf_bitand.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/sourcelocation.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vf_bitand.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_bitand.cpp diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 7b75d94fabe..52b740e9191 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -89,6 +89,7 @@ + @@ -183,6 +184,7 @@ + diff --git a/lib/lib.pri b/lib/lib.pri index 9e6746b2433..97fe180d5dd 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -80,6 +80,7 @@ HEADERS += $${PWD}/addoninfo.h \ $${PWD}/vf_analyze.h \ $${PWD}/vf_array.h \ $${PWD}/vf_arraybool.h \ + $${PWD}/vf_arrayelement.h \ $${PWD}/vf_bitand.h \ $${PWD}/vf_common.h \ $${PWD}/vf_debug.h \ @@ -159,6 +160,7 @@ SOURCES += $${PWD}/valueflow.cpp \ $${PWD}/utils.cpp \ $${PWD}/vf_array.cpp \ $${PWD}/vf_arraybool.cpp \ + $${PWD}/vf_arrayelement.cpp \ $${PWD}/vf_bitand.cpp \ $${PWD}/vf_common.cpp \ $${PWD}/vf_debug.cpp \ diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 96b3f6f42cb..1b48ecd4e00 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -540,83 +540,6 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings, int m return 0; } -static void valueFlowArrayElement(TokenList& tokenlist, const Settings& settings) -{ - for (Token* tok = tokenlist.front(); tok; tok = tok->next()) { - if (tok->hasKnownIntValue()) - continue; - const Token* indexTok = nullptr; - const Token* arrayTok = nullptr; - if (Token::simpleMatch(tok, "[") && tok->isBinaryOp()) { - indexTok = tok->astOperand2(); - arrayTok = tok->astOperand1(); - } else if (Token::Match(tok->tokAt(-2), ". %name% (") && astIsContainer(tok->tokAt(-2)->astOperand1())) { - arrayTok = tok->tokAt(-2)->astOperand1(); - const Library::Container* container = getLibraryContainer(arrayTok); - if (!container || container->stdAssociativeLike) - continue; - const Library::Container::Yield yield = container->getYield(tok->strAt(-1)); - if (yield != Library::Container::Yield::AT_INDEX) - continue; - indexTok = tok->astOperand2(); - } - - if (!indexTok || !arrayTok) - continue; - - for (const ValueFlow::Value& arrayValue : arrayTok->values()) { - if (!arrayValue.isTokValue()) - continue; - if (arrayValue.isImpossible()) - continue; - for (const ValueFlow::Value& indexValue : indexTok->values()) { - if (!indexValue.isIntValue()) - continue; - if (indexValue.isImpossible()) - continue; - if (!arrayValue.isKnown() && !indexValue.isKnown() && arrayValue.varId != 0 && indexValue.varId != 0 && - !(arrayValue.varId == indexValue.varId && arrayValue.varvalue == indexValue.varvalue)) - continue; - - ValueFlow::Value result(0); - result.condition = arrayValue.condition ? arrayValue.condition : indexValue.condition; - result.setInconclusive(arrayValue.isInconclusive() || indexValue.isInconclusive()); - result.varId = (arrayValue.varId != 0) ? arrayValue.varId : indexValue.varId; - result.varvalue = (result.varId == arrayValue.varId) ? arrayValue.intvalue : indexValue.intvalue; - if (arrayValue.valueKind == indexValue.valueKind) - result.valueKind = arrayValue.valueKind; - - result.errorPath.insert(result.errorPath.end(), arrayValue.errorPath.cbegin(), arrayValue.errorPath.cend()); - result.errorPath.insert(result.errorPath.end(), indexValue.errorPath.cbegin(), indexValue.errorPath.cend()); - - const MathLib::bigint index = indexValue.intvalue; - - if (arrayValue.tokvalue->tokType() == Token::eString) { - const std::string s = arrayValue.tokvalue->strValue(); - if (index == s.size()) { - result.intvalue = 0; - setTokenValue(tok, std::move(result), settings); - } else if (index >= 0 && index < s.size()) { - result.intvalue = s[index]; - setTokenValue(tok, std::move(result), settings); - } - } else if (Token::simpleMatch(arrayValue.tokvalue, "{")) { - std::vector args = getArguments(arrayValue.tokvalue); - if (index < 0 || index >= args.size()) - continue; - const Token* arg = args[index]; - if (!arg->hasKnownIntValue()) - continue; - const ValueFlow::Value& v = arg->values().front(); - result.intvalue = v.intvalue; - result.errorPath.insert(result.errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend()); - setTokenValue(tok, std::move(result), settings); - } - } - } - } -} - static bool getExpressionRange(const Token *expr, MathLib::bigint *minvalue, MathLib::bigint *maxvalue) { if (expr->hasKnownIntValue()) { @@ -8295,7 +8218,7 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), VFA(valueFlowSymbolicInfer(symboldatabase, settings)), VFA(analyzeArrayBool(tokenlist, settings)), - VFA(valueFlowArrayElement(tokenlist, settings)), + VFA(analyzeArrayElement(tokenlist, settings)), VFA(valueFlowRightShift(tokenlist, settings)), VFA(valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), VFA_CPP(valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings)), diff --git a/lib/vf_analyze.h b/lib/vf_analyze.h index 82a16e48f5d..6ee676023d8 100644 --- a/lib/vf_analyze.h +++ b/lib/vf_analyze.h @@ -21,6 +21,7 @@ #include "vf_array.h" // IWYU pragma: export #include "vf_arraybool.h" // IWYU pragma: export +#include "vf_arrayelement.h" // IWYU pragma: export #include "vf_bitand.h" // IWYU pragma: export #include "vf_debug.h" // IWYU pragma: export #include "vf_enumvalue.h" // IWYU pragma: export diff --git a/lib/vf_arrayelement.cpp b/lib/vf_arrayelement.cpp new file mode 100644 index 00000000000..90be4b412a9 --- /dev/null +++ b/lib/vf_arrayelement.cpp @@ -0,0 +1,113 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vf_arrayelement.h" + +#include "astutils.h" +#include "library.h" +#include "mathlib.h" +#include "token.h" +#include "tokenlist.h" +#include "vfvalue.h" + +#include "vf_settokenvalue.h" + +#include +#include +#include +#include + +namespace ValueFlow +{ + void analyzeArrayElement(TokenList& tokenlist, const Settings& settings) + { + for (Token* tok = tokenlist.front(); tok; tok = tok->next()) { + if (tok->hasKnownIntValue()) + continue; + const Token* indexTok = nullptr; + const Token* arrayTok = nullptr; + if (Token::simpleMatch(tok, "[") && tok->isBinaryOp()) { + indexTok = tok->astOperand2(); + arrayTok = tok->astOperand1(); + } else if (Token::Match(tok->tokAt(-2), ". %name% (") && astIsContainer(tok->tokAt(-2)->astOperand1())) { + arrayTok = tok->tokAt(-2)->astOperand1(); + const Library::Container* container = getLibraryContainer(arrayTok); + if (!container || container->stdAssociativeLike) + continue; + const Library::Container::Yield yield = container->getYield(tok->strAt(-1)); + if (yield != Library::Container::Yield::AT_INDEX) + continue; + indexTok = tok->astOperand2(); + } + + if (!indexTok || !arrayTok) + continue; + + for (const Value& arrayValue : arrayTok->values()) { + if (!arrayValue.isTokValue()) + continue; + if (arrayValue.isImpossible()) + continue; + for (const Value& indexValue : indexTok->values()) { + if (!indexValue.isIntValue()) + continue; + if (indexValue.isImpossible()) + continue; + if (!arrayValue.isKnown() && !indexValue.isKnown() && arrayValue.varId != 0 && indexValue.varId != 0 && + !(arrayValue.varId == indexValue.varId && arrayValue.varvalue == indexValue.varvalue)) + continue; + + Value result(0); + result.condition = arrayValue.condition ? arrayValue.condition : indexValue.condition; + result.setInconclusive(arrayValue.isInconclusive() || indexValue.isInconclusive()); + result.varId = (arrayValue.varId != 0) ? arrayValue.varId : indexValue.varId; + result.varvalue = (result.varId == arrayValue.varId) ? arrayValue.intvalue : indexValue.intvalue; + if (arrayValue.valueKind == indexValue.valueKind) + result.valueKind = arrayValue.valueKind; + + result.errorPath.insert(result.errorPath.end(), arrayValue.errorPath.cbegin(), arrayValue.errorPath.cend()); + result.errorPath.insert(result.errorPath.end(), indexValue.errorPath.cbegin(), indexValue.errorPath.cend()); + + const MathLib::bigint index = indexValue.intvalue; + + if (arrayValue.tokvalue->tokType() == Token::eString) { + const std::string s = arrayValue.tokvalue->strValue(); + if (index == s.size()) { + result.intvalue = 0; + setTokenValue(tok, std::move(result), settings); + } else if (index >= 0 && index < s.size()) { + result.intvalue = s[index]; + setTokenValue(tok, std::move(result), settings); + } + } else if (Token::simpleMatch(arrayValue.tokvalue, "{")) { + std::vector args = getArguments(arrayValue.tokvalue); + if (index < 0 || index >= args.size()) + continue; + const Token* arg = args[index]; + if (!arg->hasKnownIntValue()) + continue; + const Value& v = arg->values().front(); + result.intvalue = v.intvalue; + result.errorPath.insert(result.errorPath.end(), v.errorPath.cbegin(), v.errorPath.cend()); + setTokenValue(tok, std::move(result), settings); + } + } + } + } + } +} diff --git a/lib/vf_arrayelement.h b/lib/vf_arrayelement.h new file mode 100644 index 00000000000..d924109f875 --- /dev/null +++ b/lib/vf_arrayelement.h @@ -0,0 +1,30 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef vfArrayElementH +#define vfArrayElementH + +class TokenList; +class Settings; + +namespace ValueFlow +{ + void analyzeArrayElement(TokenList& tokenlist, const Settings& settings); +} + +#endif // vfArrayElementH diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index ca7d69cd4be..2f1e12ecb16 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -97,6 +97,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/utils.o \ $(libcppdir)/vf_array.o \ $(libcppdir)/vf_arraybool.o \ + $(libcppdir)/vf_arrayelement.o \ $(libcppdir)/vf_bitand.o \ $(libcppdir)/vf_common.o \ $(libcppdir)/vf_debug.o \ @@ -153,7 +154,7 @@ simplecpp.o: ../externals/simplecpp/simplecpp.cpp ../externals/simplecpp/simplec tinyxml2.o: ../externals/tinyxml2/tinyxml2.cpp ../externals/tinyxml2/tinyxml2.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ ../externals/tinyxml2/tinyxml2.cpp -$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h +$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: ../lib/tokenize.cpp ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/astutils.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/summaries.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h @@ -345,6 +346,9 @@ $(libcppdir)/vf_array.o: ../lib/vf_array.cpp ../lib/astutils.h ../lib/config.h . $(libcppdir)/vf_arraybool.o: ../lib/vf_arraybool.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_arraybool.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_arraybool.cpp +$(libcppdir)/vf_arrayelement.o: ../lib/vf_arrayelement.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_arrayelement.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h + $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_arrayelement.cpp + $(libcppdir)/vf_bitand.o: ../lib/vf_bitand.cpp ../lib/config.h ../lib/errortypes.h ../lib/mathlib.h ../lib/sourcelocation.h ../lib/standards.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vf_bitand.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_bitand.cpp From 07ec149f3d29ea2b1b0f01b0a80506f0f963fdec Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 27 May 2024 10:59:29 +0200 Subject: [PATCH 3/8] ValueFlow: extracted valueFlowRightShift() into separate file --- Makefile | 6 +- lib/cppcheck.vcxproj | 2 + lib/lib.pri | 2 + lib/valueflow.cpp | 106 +------------------------------- lib/vf_analyze.h | 1 + lib/vf_rightshift.cpp | 140 ++++++++++++++++++++++++++++++++++++++++++ lib/vf_rightshift.h | 30 +++++++++ oss-fuzz/Makefile | 6 +- 8 files changed, 186 insertions(+), 107 deletions(-) create mode 100644 lib/vf_rightshift.cpp create mode 100644 lib/vf_rightshift.h diff --git a/Makefile b/Makefile index 0b8a0058865..089b5fd7f7a 100644 --- a/Makefile +++ b/Makefile @@ -263,6 +263,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_globalstaticvar.o \ $(libcppdir)/vf_number.o \ $(libcppdir)/vf_pointeralias.o \ + $(libcppdir)/vf_rightshift.o \ $(libcppdir)/vf_sameexpressions.o \ $(libcppdir)/vf_settokenvalue.o \ $(libcppdir)/vf_string.o \ @@ -475,7 +476,7 @@ validateRules: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h @@ -694,6 +695,9 @@ $(libcppdir)/vf_number.o: lib/vf_number.cpp lib/config.h lib/errortypes.h lib/li $(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 $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_pointeralias.cpp +$(libcppdir)/vf_rightshift.o: lib/vf_rightshift.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_rightshift.h lib/vf_settokenvalue.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_rightshift.cpp + $(libcppdir)/vf_sameexpressions.o: lib/vf_sameexpressions.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_sameexpressions.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_sameexpressions.cpp diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 52b740e9191..1b244fd3ac6 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -98,6 +98,7 @@ + @@ -193,6 +194,7 @@ + diff --git a/lib/lib.pri b/lib/lib.pri index 97fe180d5dd..f2b0dc62672 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -89,6 +89,7 @@ HEADERS += $${PWD}/addoninfo.h \ $${PWD}/vf_globalstaticvar.h \ $${PWD}/vf_number.h \ $${PWD}/vf_pointeralias.h \ + $${PWD}/vf_rightshift.h \ $${PWD}/vf_sameexpressions.h \ $${PWD}/vf_settokenvalue.h \ $${PWD}/vf_string.h \ @@ -169,6 +170,7 @@ SOURCES += $${PWD}/valueflow.cpp \ $${PWD}/vf_globalstaticvar.cpp \ $${PWD}/vf_number.cpp \ $${PWD}/vf_pointeralias.cpp \ + $${PWD}/vf_rightshift.cpp \ $${PWD}/vf_sameexpressions.cpp \ $${PWD}/vf_settokenvalue.cpp \ $${PWD}/vf_string.cpp \ diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 1b48ecd4e00..481467db99a 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -540,110 +540,6 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings, int m return 0; } -static bool getExpressionRange(const Token *expr, MathLib::bigint *minvalue, MathLib::bigint *maxvalue) -{ - if (expr->hasKnownIntValue()) { - if (minvalue) - *minvalue = expr->values().front().intvalue; - if (maxvalue) - *maxvalue = expr->values().front().intvalue; - return true; - } - - if (expr->str() == "&" && expr->astOperand1() && expr->astOperand2()) { - MathLib::bigint vals[4]; - const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]); - const bool rhsHasKnownRange = getExpressionRange(expr->astOperand2(), &vals[2], &vals[3]); - if (!lhsHasKnownRange && !rhsHasKnownRange) - return false; - if (!lhsHasKnownRange || !rhsHasKnownRange) { - if (minvalue) - *minvalue = lhsHasKnownRange ? vals[0] : vals[2]; - if (maxvalue) - *maxvalue = lhsHasKnownRange ? vals[1] : vals[3]; - } else { - if (minvalue) - *minvalue = vals[0] & vals[2]; - if (maxvalue) - *maxvalue = vals[1] & vals[3]; - } - return true; - } - - if (expr->str() == "%" && expr->astOperand1() && expr->astOperand2()) { - MathLib::bigint vals[4]; - if (!getExpressionRange(expr->astOperand2(), &vals[2], &vals[3])) - return false; - if (vals[2] <= 0) - return false; - const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]); - if (lhsHasKnownRange && vals[0] < 0) - return false; - // If lhs has unknown value, it must be unsigned - if (!lhsHasKnownRange && (!expr->astOperand1()->valueType() || expr->astOperand1()->valueType()->sign != ValueType::Sign::UNSIGNED)) - return false; - if (minvalue) - *minvalue = 0; - if (maxvalue) - *maxvalue = vals[3] - 1; - return true; - } - - return false; -} - -static void valueFlowRightShift(TokenList &tokenList, const Settings& settings) -{ - for (Token *tok = tokenList.front(); tok; tok = tok->next()) { - if (tok->str() != ">>") - continue; - - if (tok->hasKnownValue()) - continue; - - if (!tok->astOperand1() || !tok->astOperand2()) - continue; - - if (!tok->astOperand2()->hasKnownValue()) - continue; - - const MathLib::bigint rhsvalue = tok->astOperand2()->values().front().intvalue; - if (rhsvalue < 0) - continue; - - if (!tok->astOperand1()->valueType() || !tok->astOperand1()->valueType()->isIntegral()) - continue; - - if (!tok->astOperand2()->valueType() || !tok->astOperand2()->valueType()->isIntegral()) - continue; - - MathLib::bigint lhsmax=0; - if (!getExpressionRange(tok->astOperand1(), nullptr, &lhsmax)) - continue; - if (lhsmax < 0) - continue; - int lhsbits; - if ((tok->astOperand1()->valueType()->type == ValueType::Type::CHAR) || - (tok->astOperand1()->valueType()->type == ValueType::Type::SHORT) || - (tok->astOperand1()->valueType()->type == ValueType::Type::WCHAR_T) || - (tok->astOperand1()->valueType()->type == ValueType::Type::BOOL) || - (tok->astOperand1()->valueType()->type == ValueType::Type::INT)) - lhsbits = settings.platform.int_bit; - else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONG) - lhsbits = settings.platform.long_bit; - else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONGLONG) - lhsbits = settings.platform.long_long_bit; - else - continue; - if (rhsvalue >= lhsbits || rhsvalue >= MathLib::bigint_bits || (1ULL << rhsvalue) <= lhsmax) - continue; - - ValueFlow::Value val(0); - val.setKnown(); - setTokenValue(tok, std::move(val), settings); - } -} - static std::vector minUnsignedValue(const Token* tok, int depth = 8) { std::vector result; @@ -8219,7 +8115,7 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowSymbolicInfer(symboldatabase, settings)), VFA(analyzeArrayBool(tokenlist, settings)), VFA(analyzeArrayElement(tokenlist, settings)), - VFA(valueFlowRightShift(tokenlist, settings)), + VFA(analyzeRightShift(tokenlist, settings)), VFA(valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), VFA_CPP(valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings)), VFA(valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), diff --git a/lib/vf_analyze.h b/lib/vf_analyze.h index 6ee676023d8..112e4bd411a 100644 --- a/lib/vf_analyze.h +++ b/lib/vf_analyze.h @@ -29,6 +29,7 @@ #include "vf_globalstaticvar.h" // IWYU pragma: export #include "vf_number.h" // IWYU pragma: export #include "vf_pointeralias.h" // IWYU pragma: export +#include "vf_rightshift.h" // IWYU pragma: export #include "vf_sameexpressions.h" // IWYU pragma: export #include "vf_string.h" // IWYU pragma: export #include "vf_unknownfunctionreturn.h" // IWYU pragma: export diff --git a/lib/vf_rightshift.cpp b/lib/vf_rightshift.cpp new file mode 100644 index 00000000000..f27599fbb01 --- /dev/null +++ b/lib/vf_rightshift.cpp @@ -0,0 +1,140 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vf_rightshift.h" + +#include "mathlib.h" +#include "platform.h" +#include "settings.h" +#include "symboldatabase.h" +#include "token.h" +#include "tokenlist.h" +#include "vfvalue.h" + +#include "vf_settokenvalue.h" + +#include +#include +#include + +namespace ValueFlow +{ + static bool getExpressionRange(const Token *expr, MathLib::bigint *minvalue, MathLib::bigint *maxvalue) + { + if (expr->hasKnownIntValue()) { + if (minvalue) + *minvalue = expr->values().front().intvalue; + if (maxvalue) + *maxvalue = expr->values().front().intvalue; + return true; + } + + if (expr->str() == "&" && expr->astOperand1() && expr->astOperand2()) { + MathLib::bigint vals[4]; + const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]); + const bool rhsHasKnownRange = getExpressionRange(expr->astOperand2(), &vals[2], &vals[3]); + if (!lhsHasKnownRange && !rhsHasKnownRange) + return false; + if (!lhsHasKnownRange || !rhsHasKnownRange) { + if (minvalue) + *minvalue = lhsHasKnownRange ? vals[0] : vals[2]; + if (maxvalue) + *maxvalue = lhsHasKnownRange ? vals[1] : vals[3]; + } else { + if (minvalue) + *minvalue = vals[0] & vals[2]; + if (maxvalue) + *maxvalue = vals[1] & vals[3]; + } + return true; + } + + if (expr->str() == "%" && expr->astOperand1() && expr->astOperand2()) { + MathLib::bigint vals[4]; + if (!getExpressionRange(expr->astOperand2(), &vals[2], &vals[3])) + return false; + if (vals[2] <= 0) + return false; + const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]); + if (lhsHasKnownRange && vals[0] < 0) + return false; + // If lhs has unknown value, it must be unsigned + if (!lhsHasKnownRange && (!expr->astOperand1()->valueType() || expr->astOperand1()->valueType()->sign != ValueType::Sign::UNSIGNED)) + return false; + if (minvalue) + *minvalue = 0; + if (maxvalue) + *maxvalue = vals[3] - 1; + return true; + } + + return false; + } + + void analyzeRightShift(TokenList &tokenList, const Settings& settings) + { + for (Token *tok = tokenList.front(); tok; tok = tok->next()) { + if (tok->str() != ">>") + continue; + + if (tok->hasKnownValue()) + continue; + + if (!tok->astOperand1() || !tok->astOperand2()) + continue; + + if (!tok->astOperand2()->hasKnownValue()) + continue; + + const MathLib::bigint rhsvalue = tok->astOperand2()->values().front().intvalue; + if (rhsvalue < 0) + continue; + + if (!tok->astOperand1()->valueType() || !tok->astOperand1()->valueType()->isIntegral()) + continue; + + if (!tok->astOperand2()->valueType() || !tok->astOperand2()->valueType()->isIntegral()) + continue; + + MathLib::bigint lhsmax=0; + if (!getExpressionRange(tok->astOperand1(), nullptr, &lhsmax)) + continue; + if (lhsmax < 0) + continue; + int lhsbits; + if ((tok->astOperand1()->valueType()->type == ValueType::Type::CHAR) || + (tok->astOperand1()->valueType()->type == ValueType::Type::SHORT) || + (tok->astOperand1()->valueType()->type == ValueType::Type::WCHAR_T) || + (tok->astOperand1()->valueType()->type == ValueType::Type::BOOL) || + (tok->astOperand1()->valueType()->type == ValueType::Type::INT)) + lhsbits = settings.platform.int_bit; + else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONG) + lhsbits = settings.platform.long_bit; + else if (tok->astOperand1()->valueType()->type == ValueType::Type::LONGLONG) + lhsbits = settings.platform.long_long_bit; + else + continue; + if (rhsvalue >= lhsbits || rhsvalue >= MathLib::bigint_bits || (1ULL << rhsvalue) <= lhsmax) + continue; + + Value val(0); + val.setKnown(); + setTokenValue(tok, std::move(val), settings); + } + } +} diff --git a/lib/vf_rightshift.h b/lib/vf_rightshift.h new file mode 100644 index 00000000000..cf7c9c61b46 --- /dev/null +++ b/lib/vf_rightshift.h @@ -0,0 +1,30 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef vfRightShiftH +#define vfRightShiftH + +class TokenList; +class Settings; + +namespace ValueFlow +{ + void analyzeRightShift(TokenList &tokenList, const Settings& settings); +} + +#endif // vfRightShiftH diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index 2f1e12ecb16..8a91673df40 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -106,6 +106,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_globalstaticvar.o \ $(libcppdir)/vf_number.o \ $(libcppdir)/vf_pointeralias.o \ + $(libcppdir)/vf_rightshift.o \ $(libcppdir)/vf_sameexpressions.o \ $(libcppdir)/vf_settokenvalue.o \ $(libcppdir)/vf_string.o \ @@ -154,7 +155,7 @@ simplecpp.o: ../externals/simplecpp/simplecpp.cpp ../externals/simplecpp/simplec tinyxml2.o: ../externals/tinyxml2/tinyxml2.cpp ../externals/tinyxml2/tinyxml2.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ ../externals/tinyxml2/tinyxml2.cpp -$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h +$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: ../lib/tokenize.cpp ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/astutils.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/summaries.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h @@ -373,6 +374,9 @@ $(libcppdir)/vf_number.o: ../lib/vf_number.cpp ../lib/config.h ../lib/errortypes $(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 $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_pointeralias.cpp +$(libcppdir)/vf_rightshift.o: ../lib/vf_rightshift.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_rightshift.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h + $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_rightshift.cpp + $(libcppdir)/vf_sameexpressions.o: ../lib/vf_sameexpressions.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_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_sameexpressions.cpp From 9ffe3221030ec239458676bdfec2e90e802eef1d Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 27 May 2024 11:06:28 +0200 Subject: [PATCH 4/8] ValueFlow: extracted valueFlowIteratorInfer() into separate file --- Makefile | 6 +++- lib/cppcheck.vcxproj | 2 ++ lib/lib.pri | 2 ++ lib/valueflow.cpp | 44 +-------------------------- lib/vf_analyze.h | 1 + lib/vf_common.cpp | 10 +++++++ lib/vf_common.h | 2 ++ lib/vf_iteratorinfer.cpp | 65 ++++++++++++++++++++++++++++++++++++++++ lib/vf_iteratorinfer.h | 30 +++++++++++++++++++ oss-fuzz/Makefile | 6 +++- 10 files changed, 123 insertions(+), 45 deletions(-) create mode 100644 lib/vf_iteratorinfer.cpp create mode 100644 lib/vf_iteratorinfer.h diff --git a/Makefile b/Makefile index 089b5fd7f7a..171013c8c00 100644 --- a/Makefile +++ b/Makefile @@ -261,6 +261,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_enumvalue.o \ $(libcppdir)/vf_globalconstvar.o \ $(libcppdir)/vf_globalstaticvar.o \ + $(libcppdir)/vf_iteratorinfer.o \ $(libcppdir)/vf_number.o \ $(libcppdir)/vf_pointeralias.o \ $(libcppdir)/vf_rightshift.o \ @@ -476,7 +477,7 @@ validateRules: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_iteratorinfer.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h @@ -689,6 +690,9 @@ $(libcppdir)/vf_globalconstvar.o: lib/vf_globalconstvar.cpp lib/config.h lib/err $(libcppdir)/vf_globalstaticvar.o: lib/vf_globalstaticvar.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_globalstaticvar.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_globalstaticvar.cpp +$(libcppdir)/vf_iteratorinfer.o: lib/vf_iteratorinfer.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_iteratorinfer.h lib/vf_settokenvalue.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_iteratorinfer.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 $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_number.cpp diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 1b244fd3ac6..c5827f69648 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -96,6 +96,7 @@ + @@ -192,6 +193,7 @@ + diff --git a/lib/lib.pri b/lib/lib.pri index f2b0dc62672..8ae5f2b729d 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -87,6 +87,7 @@ HEADERS += $${PWD}/addoninfo.h \ $${PWD}/vf_enumvalue.h \ $${PWD}/vf_globalconstvar.h \ $${PWD}/vf_globalstaticvar.h \ + $${PWD}/vf_iteratorinfer.h \ $${PWD}/vf_number.h \ $${PWD}/vf_pointeralias.h \ $${PWD}/vf_rightshift.h \ @@ -168,6 +169,7 @@ SOURCES += $${PWD}/valueflow.cpp \ $${PWD}/vf_enumvalue.cpp \ $${PWD}/vf_globalconstvar.cpp \ $${PWD}/vf_globalstaticvar.cpp \ + $${PWD}/vf_iteratorinfer.cpp \ $${PWD}/vf_number.cpp \ $${PWD}/vf_pointeralias.cpp \ $${PWD}/vf_rightshift.cpp \ diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 481467db99a..04092d2b3e7 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -7204,16 +7204,6 @@ static void valueFlowIterators(TokenList &tokenlist, const Settings &settings) } } -static std::list getIteratorValues(std::list values, const ValueFlow::Value::ValueKind* kind = nullptr) -{ - values.remove_if([&](const ValueFlow::Value& v) { - if (kind && v.valueKind != *kind) - return true; - return !v.isIteratorValue(); - }); - return values; -} - struct IteratorConditionHandler : SimpleConditionHandler { std::vector parse(const Token* tok, const Settings& /*settings*/) const override { Condition cond; @@ -7243,38 +7233,6 @@ struct IteratorConditionHandler : SimpleConditionHandler { } }; -static void valueFlowIteratorInfer(TokenList &tokenlist, const Settings &settings) -{ - for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { - if (!tok->scope()) - continue; - if (!tok->scope()->isExecutable()) - continue; - std::list values = getIteratorValues(tok->values()); - values.remove_if([&](const ValueFlow::Value& v) { - if (!v.isImpossible()) - return true; - if (!v.condition) - return true; - if (v.bound != ValueFlow::Value::Bound::Point) - return true; - if (v.isIteratorEndValue() && v.intvalue <= 0) - return true; - if (v.isIteratorStartValue() && v.intvalue >= 0) - return true; - return false; - }); - for (ValueFlow::Value& v:values) { - v.setPossible(); - if (v.isIteratorStartValue()) - v.intvalue++; - if (v.isIteratorEndValue()) - v.intvalue--; - setTokenValue(tok, std::move(v), settings); - } - } -} - static std::vector getContainerValues(const Token* tok) { std::vector values; @@ -8132,7 +8090,7 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA_CPP(valueFlowIterators(tokenlist, settings)), VFA_CPP( valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), - VFA_CPP(valueFlowIteratorInfer(tokenlist, settings)), + VFA_CPP(analyzeIteratorInfer(tokenlist, settings)), VFA_CPP(valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), VFA_CPP( valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), diff --git a/lib/vf_analyze.h b/lib/vf_analyze.h index 112e4bd411a..fbeebb7952c 100644 --- a/lib/vf_analyze.h +++ b/lib/vf_analyze.h @@ -27,6 +27,7 @@ #include "vf_enumvalue.h" // IWYU pragma: export #include "vf_globalconstvar.h" // IWYU pragma: export #include "vf_globalstaticvar.h" // IWYU pragma: export +#include "vf_iteratorinfer.h" // IWYU pragma: export #include "vf_number.h" // IWYU pragma: export #include "vf_pointeralias.h" // IWYU pragma: export #include "vf_rightshift.h" // IWYU pragma: export diff --git a/lib/vf_common.cpp b/lib/vf_common.cpp index a65a173651d..4cf812b3797 100644 --- a/lib/vf_common.cpp +++ b/lib/vf_common.cpp @@ -394,4 +394,14 @@ namespace ValueFlow " => " + local.function_name() + ": " + debugString(v); v.debugPath.emplace_back(tok, std::move(s)); } + + std::list getIteratorValues(std::list values, const Value::ValueKind* kind) + { + values.remove_if([&](const Value& v) { + if (kind && v.valueKind != *kind) + return true; + return !v.isIteratorValue(); + }); + return values; + } } diff --git a/lib/vf_common.h b/lib/vf_common.h index fc9b7e137af..1b6e4610b5a 100644 --- a/lib/vf_common.h +++ b/lib/vf_common.h @@ -49,6 +49,8 @@ namespace ValueFlow SourceLocation ctx, const Token* tok, SourceLocation local = SourceLocation::current()); + + std::list getIteratorValues(std::list values, const Value::ValueKind* kind = nullptr); } #endif // vfCommonH diff --git a/lib/vf_iteratorinfer.cpp b/lib/vf_iteratorinfer.cpp new file mode 100644 index 00000000000..cd1d26b1675 --- /dev/null +++ b/lib/vf_iteratorinfer.cpp @@ -0,0 +1,65 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vf_iteratorinfer.h" + +#include "symboldatabase.h" +#include "token.h" +#include "tokenlist.h" +#include "vfvalue.h" + +#include "vf_common.h" +#include "vf_settokenvalue.h" + +#include +#include + +namespace ValueFlow +{ + void analyzeIteratorInfer(TokenList &tokenlist, const Settings &settings) + { + for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { + if (!tok->scope()) + continue; + if (!tok->scope()->isExecutable()) + continue; + std::list values = getIteratorValues(tok->values()); + values.remove_if([&](const Value& v) { + if (!v.isImpossible()) + return true; + if (!v.condition) + return true; + if (v.bound != Value::Bound::Point) + return true; + if (v.isIteratorEndValue() && v.intvalue <= 0) + return true; + if (v.isIteratorStartValue() && v.intvalue >= 0) + return true; + return false; + }); + for (Value& v:values) { + v.setPossible(); + if (v.isIteratorStartValue()) + v.intvalue++; + if (v.isIteratorEndValue()) + v.intvalue--; + setTokenValue(tok, std::move(v), settings); + } + } + } +} diff --git a/lib/vf_iteratorinfer.h b/lib/vf_iteratorinfer.h new file mode 100644 index 00000000000..a2bc4964886 --- /dev/null +++ b/lib/vf_iteratorinfer.h @@ -0,0 +1,30 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef vfIteratorInferH +#define vfIteratorInferH + +class TokenList; +class Settings; + +namespace ValueFlow +{ + void analyzeIteratorInfer(TokenList &tokenlist, const Settings &settings); +} + +#endif // vfIteratorInferH diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index 8a91673df40..18fdf932aaa 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -104,6 +104,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_enumvalue.o \ $(libcppdir)/vf_globalconstvar.o \ $(libcppdir)/vf_globalstaticvar.o \ + $(libcppdir)/vf_iteratorinfer.o \ $(libcppdir)/vf_number.o \ $(libcppdir)/vf_pointeralias.o \ $(libcppdir)/vf_rightshift.o \ @@ -155,7 +156,7 @@ simplecpp.o: ../externals/simplecpp/simplecpp.cpp ../externals/simplecpp/simplec tinyxml2.o: ../externals/tinyxml2/tinyxml2.cpp ../externals/tinyxml2/tinyxml2.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ ../externals/tinyxml2/tinyxml2.cpp -$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h +$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_iteratorinfer.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: ../lib/tokenize.cpp ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/astutils.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/summaries.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h @@ -368,6 +369,9 @@ $(libcppdir)/vf_globalconstvar.o: ../lib/vf_globalconstvar.cpp ../lib/config.h . $(libcppdir)/vf_globalstaticvar.o: ../lib/vf_globalstaticvar.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_globalstaticvar.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_globalstaticvar.cpp +$(libcppdir)/vf_iteratorinfer.o: ../lib/vf_iteratorinfer.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_iteratorinfer.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h + $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_iteratorinfer.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 $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_number.cpp From 629f11d15f75fa471a916ccd14dc1cb474d070ef Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 27 May 2024 11:10:50 +0200 Subject: [PATCH 5/8] ValueFlow: extracted valueFlowIterators() into separate file --- Makefile | 6 +++- lib/cppcheck.vcxproj | 2 ++ lib/lib.pri | 2 ++ lib/valueflow.cpp | 40 +------------------------ lib/vf_analyze.h | 1 + lib/vf_iterators.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++ lib/vf_iterators.h | 30 +++++++++++++++++++ oss-fuzz/Makefile | 6 +++- 8 files changed, 117 insertions(+), 41 deletions(-) create mode 100644 lib/vf_iterators.cpp create mode 100644 lib/vf_iterators.h diff --git a/Makefile b/Makefile index 171013c8c00..7229b861592 100644 --- a/Makefile +++ b/Makefile @@ -262,6 +262,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_globalconstvar.o \ $(libcppdir)/vf_globalstaticvar.o \ $(libcppdir)/vf_iteratorinfer.o \ + $(libcppdir)/vf_iterators.o \ $(libcppdir)/vf_number.o \ $(libcppdir)/vf_pointeralias.o \ $(libcppdir)/vf_rightshift.o \ @@ -477,7 +478,7 @@ validateRules: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_iteratorinfer.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_iteratorinfer.h lib/vf_iterators.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h @@ -693,6 +694,9 @@ $(libcppdir)/vf_globalstaticvar.o: lib/vf_globalstaticvar.cpp lib/astutils.h lib $(libcppdir)/vf_iteratorinfer.o: lib/vf_iteratorinfer.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_iteratorinfer.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_iteratorinfer.cpp +$(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 $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_number.cpp diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index c5827f69648..f7d1a8daea7 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -97,6 +97,7 @@ + @@ -194,6 +195,7 @@ + diff --git a/lib/lib.pri b/lib/lib.pri index 8ae5f2b729d..22bc5be34b7 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -88,6 +88,7 @@ HEADERS += $${PWD}/addoninfo.h \ $${PWD}/vf_globalconstvar.h \ $${PWD}/vf_globalstaticvar.h \ $${PWD}/vf_iteratorinfer.h \ + $${PWD}/vf_iterators.h \ $${PWD}/vf_number.h \ $${PWD}/vf_pointeralias.h \ $${PWD}/vf_rightshift.h \ @@ -170,6 +171,7 @@ SOURCES += $${PWD}/valueflow.cpp \ $${PWD}/vf_globalconstvar.cpp \ $${PWD}/vf_globalstaticvar.cpp \ $${PWD}/vf_iteratorinfer.cpp \ + $${PWD}/vf_iterators.cpp \ $${PWD}/vf_number.cpp \ $${PWD}/vf_pointeralias.cpp \ $${PWD}/vf_rightshift.cpp \ diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 04092d2b3e7..9b982a6a14e 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -7166,44 +7166,6 @@ static void valueFlowSmartPointer(TokenList &tokenlist, ErrorLogger & errorLogge } } -static Library::Container::Yield findIteratorYield(Token* tok, const Token** ftok, const Settings &settings) -{ - auto yield = astContainerYield(tok, ftok); - if (ftok && *ftok) - return yield; - - if (!tok->astParent()) - return yield; - - //begin/end free functions - return astFunctionYield(tok->astParent()->previous(), settings, ftok); -} - -static void valueFlowIterators(TokenList &tokenlist, const Settings &settings) -{ - for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { - if (!tok->scope()) - continue; - if (!tok->scope()->isExecutable()) - continue; - if (!astIsContainer(tok)) - continue; - Token* ftok = nullptr; - const Library::Container::Yield yield = findIteratorYield(tok, const_cast(&ftok), settings); - if (ftok) { - ValueFlow::Value v(0); - v.setKnown(); - if (yield == Library::Container::Yield::START_ITERATOR) { - v.valueType = ValueFlow::Value::ValueType::ITERATOR_START; - setTokenValue(ftok->next(), std::move(v), settings); - } else if (yield == Library::Container::Yield::END_ITERATOR) { - v.valueType = ValueFlow::Value::ValueType::ITERATOR_END; - setTokenValue(ftok->next(), std::move(v), settings); - } - } - } -} - struct IteratorConditionHandler : SimpleConditionHandler { std::vector parse(const Token* tok, const Settings& /*settings*/) const override { Condition cond; @@ -8087,7 +8049,7 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowUninit(tokenlist, errorLogger, settings)), VFA_CPP(valueFlowAfterMove(tokenlist, symboldatabase, errorLogger, settings)), VFA_CPP(valueFlowSmartPointer(tokenlist, errorLogger, settings)), - VFA_CPP(valueFlowIterators(tokenlist, settings)), + VFA_CPP(analyzeIterators(tokenlist, settings)), VFA_CPP( valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), VFA_CPP(analyzeIteratorInfer(tokenlist, settings)), diff --git a/lib/vf_analyze.h b/lib/vf_analyze.h index fbeebb7952c..e61d946c336 100644 --- a/lib/vf_analyze.h +++ b/lib/vf_analyze.h @@ -28,6 +28,7 @@ #include "vf_globalconstvar.h" // IWYU pragma: export #include "vf_globalstaticvar.h" // IWYU pragma: export #include "vf_iteratorinfer.h" // IWYU pragma: export +#include "vf_iterators.h" // IWYU pragma: export #include "vf_number.h" // IWYU pragma: export #include "vf_pointeralias.h" // IWYU pragma: export #include "vf_rightshift.h" // IWYU pragma: export diff --git a/lib/vf_iterators.cpp b/lib/vf_iterators.cpp new file mode 100644 index 00000000000..1f85a27873a --- /dev/null +++ b/lib/vf_iterators.cpp @@ -0,0 +1,71 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vf_iterators.h" + +#include "astutils.h" +#include "library.h" +#include "symboldatabase.h" +#include "token.h" +#include "tokenlist.h" +#include "vfvalue.h" + +#include "vf_settokenvalue.h" + +#include + +namespace ValueFlow +{ + static Library::Container::Yield findIteratorYield(Token* tok, const Token** ftok, const Settings &settings) + { + auto yield = astContainerYield(tok, ftok); + if (ftok && *ftok) + return yield; + + if (!tok->astParent()) + return yield; + + //begin/end free functions + return astFunctionYield(tok->astParent()->previous(), settings, ftok); + } + + void analyzeIterators(TokenList &tokenlist, const Settings &settings) + { + for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { + if (!tok->scope()) + continue; + if (!tok->scope()->isExecutable()) + continue; + if (!astIsContainer(tok)) + continue; + Token* ftok = nullptr; + const Library::Container::Yield yield = findIteratorYield(tok, const_cast(&ftok), settings); + if (ftok) { + Value v(0); + v.setKnown(); + if (yield == Library::Container::Yield::START_ITERATOR) { + v.valueType = Value::ValueType::ITERATOR_START; + setTokenValue(ftok->next(), std::move(v), settings); + } else if (yield == Library::Container::Yield::END_ITERATOR) { + v.valueType = Value::ValueType::ITERATOR_END; + setTokenValue(ftok->next(), std::move(v), settings); + } + } + } + } +} diff --git a/lib/vf_iterators.h b/lib/vf_iterators.h new file mode 100644 index 00000000000..22b2d6ab87c --- /dev/null +++ b/lib/vf_iterators.h @@ -0,0 +1,30 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef vfIteratorsH +#define vfIteratorsH + +class TokenList; +class Settings; + +namespace ValueFlow +{ + void analyzeIterators(TokenList &tokenlist, const Settings &settings); +} + +#endif // vfIteratorsH diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index 18fdf932aaa..a940b6e8cd7 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -105,6 +105,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_globalconstvar.o \ $(libcppdir)/vf_globalstaticvar.o \ $(libcppdir)/vf_iteratorinfer.o \ + $(libcppdir)/vf_iterators.o \ $(libcppdir)/vf_number.o \ $(libcppdir)/vf_pointeralias.o \ $(libcppdir)/vf_rightshift.o \ @@ -156,7 +157,7 @@ simplecpp.o: ../externals/simplecpp/simplecpp.cpp ../externals/simplecpp/simplec tinyxml2.o: ../externals/tinyxml2/tinyxml2.cpp ../externals/tinyxml2/tinyxml2.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ ../externals/tinyxml2/tinyxml2.cpp -$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_iteratorinfer.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h +$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_iteratorinfer.h ../lib/vf_iterators.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: ../lib/tokenize.cpp ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/astutils.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/summaries.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h @@ -372,6 +373,9 @@ $(libcppdir)/vf_globalstaticvar.o: ../lib/vf_globalstaticvar.cpp ../lib/astutils $(libcppdir)/vf_iteratorinfer.o: ../lib/vf_iteratorinfer.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_iteratorinfer.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_iteratorinfer.cpp +$(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 $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_number.cpp From a3b5fc01443d61a4ec6998aed8aff107bf6f8b73 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 27 May 2024 11:22:17 +0200 Subject: [PATCH 6/8] ValueFlow: extracted valueFlowFunctionReturn() into separate file --- Makefile | 10 ++- lib/cppcheck.vcxproj | 4 ++ lib/lib.pri | 4 ++ lib/valueflow.cpp | 119 +------------------------------- lib/vf_analyze.h | 1 + lib/vf_bailout.cpp | 40 +++++++++++ lib/vf_bailout.h | 39 +++++++++++ lib/vf_functionreturn.cpp | 139 ++++++++++++++++++++++++++++++++++++++ lib/vf_functionreturn.h | 31 +++++++++ oss-fuzz/Makefile | 10 ++- 10 files changed, 278 insertions(+), 119 deletions(-) create mode 100644 lib/vf_bailout.cpp create mode 100644 lib/vf_bailout.h create mode 100644 lib/vf_functionreturn.cpp create mode 100644 lib/vf_functionreturn.h diff --git a/Makefile b/Makefile index 7229b861592..d462f532a9d 100644 --- a/Makefile +++ b/Makefile @@ -255,10 +255,12 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_array.o \ $(libcppdir)/vf_arraybool.o \ $(libcppdir)/vf_arrayelement.o \ + $(libcppdir)/vf_bailout.o \ $(libcppdir)/vf_bitand.o \ $(libcppdir)/vf_common.o \ $(libcppdir)/vf_debug.o \ $(libcppdir)/vf_enumvalue.o \ + $(libcppdir)/vf_functionreturn.o \ $(libcppdir)/vf_globalconstvar.o \ $(libcppdir)/vf_globalstaticvar.o \ $(libcppdir)/vf_iteratorinfer.o \ @@ -478,7 +480,7 @@ validateRules: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_iteratorinfer.h lib/vf_iterators.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bailout.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_functionreturn.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_iteratorinfer.h lib/vf_iterators.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h @@ -673,6 +675,9 @@ $(libcppdir)/vf_arraybool.o: lib/vf_arraybool.cpp lib/astutils.h lib/config.h li $(libcppdir)/vf_arrayelement.o: lib/vf_arrayelement.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_arrayelement.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_arrayelement.cpp +$(libcppdir)/vf_bailout.o: lib/vf_bailout.cpp lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/path.h lib/standards.h lib/tokenlist.h lib/utils.h lib/vf_bailout.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_bailout.cpp + $(libcppdir)/vf_bitand.o: lib/vf_bitand.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/sourcelocation.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vf_bitand.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_bitand.cpp @@ -685,6 +690,9 @@ $(libcppdir)/vf_debug.o: lib/vf_debug.cpp lib/addoninfo.h lib/color.h lib/config $(libcppdir)/vf_enumvalue.o: lib/vf_enumvalue.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/utils.h lib/valueflow.h lib/vf_enumvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_enumvalue.cpp +$(libcppdir)/vf_functionreturn.o: lib/vf_functionreturn.cpp lib/addoninfo.h lib/astutils.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/settings.h lib/smallvector.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_bailout.h lib/vf_functionreturn.h lib/vf_settokenvalue.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_functionreturn.cpp + $(libcppdir)/vf_globalconstvar.o: lib/vf_globalconstvar.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_globalconstvar.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_globalconstvar.cpp diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index f7d1a8daea7..4ba68286efe 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -90,10 +90,12 @@ + + @@ -188,10 +190,12 @@ + + diff --git a/lib/lib.pri b/lib/lib.pri index 22bc5be34b7..aca035c68f0 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -81,10 +81,12 @@ HEADERS += $${PWD}/addoninfo.h \ $${PWD}/vf_array.h \ $${PWD}/vf_arraybool.h \ $${PWD}/vf_arrayelement.h \ + $${PWD}/vf_bailout.h \ $${PWD}/vf_bitand.h \ $${PWD}/vf_common.h \ $${PWD}/vf_debug.h \ $${PWD}/vf_enumvalue.h \ + $${PWD}/vf_functionreturn.h \ $${PWD}/vf_globalconstvar.h \ $${PWD}/vf_globalstaticvar.h \ $${PWD}/vf_iteratorinfer.h \ @@ -164,10 +166,12 @@ SOURCES += $${PWD}/valueflow.cpp \ $${PWD}/vf_array.cpp \ $${PWD}/vf_arraybool.cpp \ $${PWD}/vf_arrayelement.cpp \ + $${PWD}/vf_bailout.cpp \ $${PWD}/vf_bitand.cpp \ $${PWD}/vf_common.cpp \ $${PWD}/vf_debug.cpp \ $${PWD}/vf_enumvalue.cpp \ + $${PWD}/vf_functionreturn.cpp \ $${PWD}/vf_globalconstvar.cpp \ $${PWD}/vf_globalstaticvar.cpp \ $${PWD}/vf_iteratorinfer.cpp \ diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 9b982a6a14e..e3a42389b61 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -89,7 +89,6 @@ #include "infer.h" #include "library.h" #include "mathlib.h" -#include "path.h" #include "platform.h" #include "programmemory.h" #include "reverseanalyzer.h" @@ -106,6 +105,7 @@ #include "vfvalue.h" #include "vf_analyze.h" +#include "vf_bailout.h" #include "vf_common.h" #include "vf_settokenvalue.h" @@ -130,23 +130,6 @@ #include #include -static void bailoutInternal(const std::string& type, const TokenList &tokenlist, ErrorLogger &errorLogger, const Token *tok, const std::string &what, const std::string &file, int line, std::string function) -{ - if (function.find("operator") != std::string::npos) - function = "(valueFlow)"; - ErrorMessage::FileLocation loc(tok, &tokenlist); - const std::string location = Path::stripDirectoryPart(file) + ":" + std::to_string(line) + ":"; - ErrorMessage errmsg({std::move(loc)}, tokenlist.getSourceFilePath(), Severity::debug, - (file.empty() ? "" : location) + function + " bailout: " + what, type, Certainty::normal); - errorLogger.reportErr(errmsg); -} - -#define bailout2(type, tokenlist, errorLogger, tok, what) bailoutInternal((type), (tokenlist), (errorLogger), (tok), (what), __FILE__, __LINE__, __func__) - -#define bailout(tokenlist, errorLogger, tok, what) bailout2("valueFlowBailout", (tokenlist), (errorLogger), (tok), (what)) - -#define bailoutIncompleteVar(tokenlist, errorLogger, tok, what) bailoutInternal("valueFlowBailoutIncompleteVar", (tokenlist), (errorLogger), (tok), (what), "", 0, __func__) - static void changeKnownToPossible(std::list &values, int indirect=-1) { for (ValueFlow::Value& v: values) { @@ -6476,104 +6459,6 @@ static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const } } -static const ValueFlow::Value* getKnownValueFromToken(const Token* tok) -{ - if (!tok) - return nullptr; - auto it = std::find_if(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) { - return (v.isIntValue() || v.isContainerSizeValue() || v.isFloatValue()) && v.isKnown(); - }); - if (it == tok->values().end()) - return nullptr; - return std::addressof(*it); -} - -static const ValueFlow::Value* getKnownValueFromTokens(const std::vector& toks) -{ - if (toks.empty()) - return nullptr; - const ValueFlow::Value* result = getKnownValueFromToken(toks.front()); - if (!result) - return nullptr; - if (!std::all_of(std::next(toks.begin()), toks.end(), [&](const Token* tok) { - return std::any_of(tok->values().begin(), tok->values().end(), [&](const ValueFlow::Value& v) { - return v.equalValue(*result) && v.valueKind == result->valueKind; - }); - })) - return nullptr; - return result; -} - -static void setFunctionReturnValue(const Function* f, Token* tok, ValueFlow::Value v, const Settings& settings) -{ - if (f->hasVirtualSpecifier()) { - if (v.isImpossible()) - return; - v.setPossible(); - } else if (!v.isImpossible()) { - v.setKnown(); - } - v.errorPath.emplace_back(tok, "Calling function '" + f->name() + "' returns " + v.toString()); - setTokenValue(tok, std::move(v), settings); -} - -static void valueFlowFunctionReturn(TokenList &tokenlist, ErrorLogger &errorLogger, const Settings& settings) -{ - for (Token *tok = tokenlist.back(); tok; tok = tok->previous()) { - if (tok->str() != "(" || !tok->astOperand1() || tok->isCast()) - continue; - - const Function* function = nullptr; - if (Token::Match(tok->previous(), "%name% (")) - function = tok->previous()->function(); - else - function = tok->astOperand1()->function(); - if (!function) - continue; - // TODO: Check if member variable is a pointer or reference - if (function->isImplicitlyVirtual() && !function->hasFinalSpecifier()) - continue; - - if (tok->hasKnownValue()) - continue; - - std::vector returns = Function::findReturns(function); - if (returns.empty()) - continue; - - if (const ValueFlow::Value* v = getKnownValueFromTokens(returns)) { - setFunctionReturnValue(function, tok, *v, settings); - continue; - } - - // Arguments.. - std::vector arguments = getArguments(tok); - - ProgramMemory programMemory; - for (std::size_t i = 0; i < arguments.size(); ++i) { - const Variable * const arg = function->getArgumentVar(i); - if (!arg) { - if (settings.debugwarnings) - bailout(tokenlist, errorLogger, tok, "function return; unhandled argument type"); - programMemory.clear(); - break; - } - const ValueFlow::Value* v = getKnownValueFromToken(arguments[i]); - if (!v) - continue; - programMemory.setValue(arg->nameToken(), *v); - } - if (programMemory.empty() && !arguments.empty()) - continue; - std::vector values = execute(function->functionScope, programMemory, settings); - for (const ValueFlow::Value& v : values) { - if (v.isUninitValue()) - continue; - setFunctionReturnValue(function, tok, v, settings); - } - } -} - static bool needsInitialization(const Variable* var) { if (!var) @@ -8043,7 +7928,7 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings)), VFA(valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings)), VFA(valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings)), - VFA(valueFlowFunctionReturn(tokenlist, errorLogger, settings)), + VFA(analyzeFunctionReturn(tokenlist, errorLogger, settings)), VFA(valueFlowLifetime(tokenlist, errorLogger, settings)), VFA(valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, errorLogger, settings)), VFA(valueFlowUninit(tokenlist, errorLogger, settings)), diff --git a/lib/vf_analyze.h b/lib/vf_analyze.h index e61d946c336..98d44619553 100644 --- a/lib/vf_analyze.h +++ b/lib/vf_analyze.h @@ -25,6 +25,7 @@ #include "vf_bitand.h" // IWYU pragma: export #include "vf_debug.h" // IWYU pragma: export #include "vf_enumvalue.h" // IWYU pragma: export +#include "vf_functionreturn.h" // IWYU pragma: export #include "vf_globalconstvar.h" // IWYU pragma: export #include "vf_globalstaticvar.h" // IWYU pragma: export #include "vf_iteratorinfer.h" // IWYU pragma: export diff --git a/lib/vf_bailout.cpp b/lib/vf_bailout.cpp new file mode 100644 index 00000000000..05cb24a3439 --- /dev/null +++ b/lib/vf_bailout.cpp @@ -0,0 +1,40 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vf_bailout.h" + +#include "errorlogger.h" +#include "errortypes.h" +#include "path.h" +#include "tokenlist.h" + +#include + +namespace ValueFlow +{ + void bailoutInternal(const std::string& type, const TokenList &tokenlist, ErrorLogger &errorLogger, const Token *tok, const std::string &what, const std::string &file, int line, std::string function) + { + if (function.find("operator") != std::string::npos) + function = "(valueFlow)"; + ErrorMessage::FileLocation loc(tok, &tokenlist); + const std::string location = Path::stripDirectoryPart(file) + ":" + std::to_string(line) + ":"; + ErrorMessage errmsg({std::move(loc)}, tokenlist.getSourceFilePath(), Severity::debug, + (file.empty() ? "" : location) + function + " bailout: " + what, type, Certainty::normal); + errorLogger.reportErr(errmsg); + } +} diff --git a/lib/vf_bailout.h b/lib/vf_bailout.h new file mode 100644 index 00000000000..5dac1265309 --- /dev/null +++ b/lib/vf_bailout.h @@ -0,0 +1,39 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef vfBailoutH +#define vfBailoutH + +#include + +class TokenList; +class ErrorLogger; +class Token; + +namespace ValueFlow +{ + void bailoutInternal(const std::string& type, const TokenList &tokenlist, ErrorLogger &errorLogger, const Token *tok, const std::string &what, const std::string &file, int line, std::string function); +} + +#define bailout2(type, tokenlist, errorLogger, tok, what) ValueFlow::bailoutInternal((type), (tokenlist), (errorLogger), (tok), (what), __FILE__, __LINE__, __func__) + +#define bailout(tokenlist, errorLogger, tok, what) bailout2("valueFlowBailout", (tokenlist), (errorLogger), (tok), (what)) + +#define bailoutIncompleteVar(tokenlist, errorLogger, tok, what) ValueFlow::bailoutInternal("valueFlowBailoutIncompleteVar", (tokenlist), (errorLogger), (tok), (what), "", 0, __func__) + +#endif // vfBailoutH diff --git a/lib/vf_functionreturn.cpp b/lib/vf_functionreturn.cpp new file mode 100644 index 00000000000..a786dbe1f08 --- /dev/null +++ b/lib/vf_functionreturn.cpp @@ -0,0 +1,139 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vf_functionreturn.h" + +#include "astutils.h" +#include "programmemory.h" +#include "settings.h" +#include "symboldatabase.h" +#include "token.h" +#include "tokenlist.h" +#include "vfvalue.h" + +#include "vf_bailout.h" +#include "vf_settokenvalue.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace ValueFlow +{ + static const Value* getKnownValueFromToken(const Token* tok) + { + if (!tok) + return nullptr; + auto it = std::find_if(tok->values().begin(), tok->values().end(), [&](const Value& v) { + return (v.isIntValue() || v.isContainerSizeValue() || v.isFloatValue()) && v.isKnown(); + }); + if (it == tok->values().end()) + return nullptr; + return std::addressof(*it); + } + + static const Value* getKnownValueFromTokens(const std::vector& toks) + { + if (toks.empty()) + return nullptr; + const Value* result = getKnownValueFromToken(toks.front()); + if (!result) + return nullptr; + if (!std::all_of(std::next(toks.begin()), toks.end(), [&](const Token* tok) { + return std::any_of(tok->values().begin(), tok->values().end(), [&](const Value& v) { + return v.equalValue(*result) && v.valueKind == result->valueKind; + }); + })) + return nullptr; + return result; + } + + static void setFunctionReturnValue(const Function* f, Token* tok, Value v, const Settings& settings) + { + if (f->hasVirtualSpecifier()) { + if (v.isImpossible()) + return; + v.setPossible(); + } else if (!v.isImpossible()) { + v.setKnown(); + } + v.errorPath.emplace_back(tok, "Calling function '" + f->name() + "' returns " + v.toString()); + setTokenValue(tok, std::move(v), settings); + } + + void analyzeFunctionReturn(TokenList &tokenlist, ErrorLogger &errorLogger, const Settings& settings) + { + for (Token *tok = tokenlist.back(); tok; tok = tok->previous()) { + if (tok->str() != "(" || !tok->astOperand1() || tok->isCast()) + continue; + + const Function* function = nullptr; + if (Token::Match(tok->previous(), "%name% (")) + function = tok->previous()->function(); + else + function = tok->astOperand1()->function(); + if (!function) + continue; + // TODO: Check if member variable is a pointer or reference + if (function->isImplicitlyVirtual() && !function->hasFinalSpecifier()) + continue; + + if (tok->hasKnownValue()) + continue; + + std::vector returns = Function::findReturns(function); + if (returns.empty()) + continue; + + if (const Value* v = getKnownValueFromTokens(returns)) { + setFunctionReturnValue(function, tok, *v, settings); + continue; + } + + // Arguments.. + std::vector arguments = getArguments(tok); + + ProgramMemory programMemory; + for (std::size_t i = 0; i < arguments.size(); ++i) { + const Variable * const arg = function->getArgumentVar(i); + if (!arg) { + if (settings.debugwarnings) + bailout(tokenlist, errorLogger, tok, "function return; unhandled argument type"); + programMemory.clear(); + break; + } + const Value* v = getKnownValueFromToken(arguments[i]); + if (!v) + continue; + programMemory.setValue(arg->nameToken(), *v); + } + if (programMemory.empty() && !arguments.empty()) + continue; + std::vector values = execute(function->functionScope, programMemory, settings); + for (const Value& v : values) { + if (v.isUninitValue()) + continue; + setFunctionReturnValue(function, tok, v, settings); + } + } + } +} diff --git a/lib/vf_functionreturn.h b/lib/vf_functionreturn.h new file mode 100644 index 00000000000..b32af39f70b --- /dev/null +++ b/lib/vf_functionreturn.h @@ -0,0 +1,31 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef vfFunctionReturnH +#define vfFunctionReturnH + +class TokenList; +class ErrorLogger; +class Settings; + +namespace ValueFlow +{ + void analyzeFunctionReturn(TokenList &tokenlist, ErrorLogger &errorLogger, const Settings& settings); +} + +#endif // vfFunctionReturnH diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index a940b6e8cd7..e2de79783ea 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -98,10 +98,12 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_array.o \ $(libcppdir)/vf_arraybool.o \ $(libcppdir)/vf_arrayelement.o \ + $(libcppdir)/vf_bailout.o \ $(libcppdir)/vf_bitand.o \ $(libcppdir)/vf_common.o \ $(libcppdir)/vf_debug.o \ $(libcppdir)/vf_enumvalue.o \ + $(libcppdir)/vf_functionreturn.o \ $(libcppdir)/vf_globalconstvar.o \ $(libcppdir)/vf_globalstaticvar.o \ $(libcppdir)/vf_iteratorinfer.o \ @@ -157,7 +159,7 @@ simplecpp.o: ../externals/simplecpp/simplecpp.cpp ../externals/simplecpp/simplec tinyxml2.o: ../externals/tinyxml2/tinyxml2.cpp ../externals/tinyxml2/tinyxml2.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ ../externals/tinyxml2/tinyxml2.cpp -$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_iteratorinfer.h ../lib/vf_iterators.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h +$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bailout.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_functionreturn.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_iteratorinfer.h ../lib/vf_iterators.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: ../lib/tokenize.cpp ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/astutils.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/summaries.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h @@ -352,6 +354,9 @@ $(libcppdir)/vf_arraybool.o: ../lib/vf_arraybool.cpp ../lib/astutils.h ../lib/co $(libcppdir)/vf_arrayelement.o: ../lib/vf_arrayelement.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_arrayelement.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_arrayelement.cpp +$(libcppdir)/vf_bailout.o: ../lib/vf_bailout.cpp ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/path.h ../lib/standards.h ../lib/tokenlist.h ../lib/utils.h ../lib/vf_bailout.h + $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_bailout.cpp + $(libcppdir)/vf_bitand.o: ../lib/vf_bitand.cpp ../lib/config.h ../lib/errortypes.h ../lib/mathlib.h ../lib/sourcelocation.h ../lib/standards.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vf_bitand.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_bitand.cpp @@ -364,6 +369,9 @@ $(libcppdir)/vf_debug.o: ../lib/vf_debug.cpp ../lib/addoninfo.h ../lib/color.h . $(libcppdir)/vf_enumvalue.o: ../lib/vf_enumvalue.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/utils.h ../lib/valueflow.h ../lib/vf_enumvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_enumvalue.cpp +$(libcppdir)/vf_functionreturn.o: ../lib/vf_functionreturn.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/programmemory.h ../lib/settings.h ../lib/smallvector.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_bailout.h ../lib/vf_functionreturn.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h + $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_functionreturn.cpp + $(libcppdir)/vf_globalconstvar.o: ../lib/vf_globalconstvar.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_globalconstvar.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_globalconstvar.cpp From 5d46cee579df3b2ceae79a0a7d900ee2eecebe2d Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 27 May 2024 11:43:32 +0200 Subject: [PATCH 7/8] ValueFlow: extracted valueFlowSymbolicInfer() into separate file --- Makefile | 6 ++- lib/cppcheck.vcxproj | 2 + lib/lib.pri | 2 + lib/valueflow.cpp | 57 ------------------------ lib/vf_analyze.h | 1 + lib/vf_symbolicinfer.cpp | 93 ++++++++++++++++++++++++++++++++++++++++ lib/vf_symbolicinfer.h | 30 +++++++++++++ oss-fuzz/Makefile | 6 ++- 8 files changed, 138 insertions(+), 59 deletions(-) create mode 100644 lib/vf_symbolicinfer.cpp create mode 100644 lib/vf_symbolicinfer.h diff --git a/Makefile b/Makefile index d462f532a9d..09937f8ab25 100644 --- a/Makefile +++ b/Makefile @@ -271,6 +271,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_sameexpressions.o \ $(libcppdir)/vf_settokenvalue.o \ $(libcppdir)/vf_string.o \ + $(libcppdir)/vf_symbolicinfer.o \ $(libcppdir)/vf_unknownfunctionreturn.o \ $(libcppdir)/vfvalue.o @@ -480,7 +481,7 @@ validateRules: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bailout.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_functionreturn.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_iteratorinfer.h lib/vf_iterators.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bailout.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_functionreturn.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_iteratorinfer.h lib/vf_iterators.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_symbolicinfer.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h @@ -723,6 +724,9 @@ $(libcppdir)/vf_settokenvalue.o: lib/vf_settokenvalue.cpp lib/addoninfo.h lib/as $(libcppdir)/vf_string.o: lib/vf_string.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/sourcelocation.h lib/standards.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vf_settokenvalue.h lib/vf_string.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_string.cpp +$(libcppdir)/vf_symbolicinfer.o: lib/vf_symbolicinfer.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/infer.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/utils.h lib/valueptr.h lib/vf_settokenvalue.h lib/vf_symbolicinfer.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_symbolicinfer.cpp + $(libcppdir)/vf_unknownfunctionreturn.o: lib/vf_unknownfunctionreturn.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_settokenvalue.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_unknownfunctionreturn.cpp diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 4ba68286efe..91a65120dbe 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -106,6 +106,7 @@ + @@ -206,6 +207,7 @@ + diff --git a/lib/lib.pri b/lib/lib.pri index aca035c68f0..690944b4b04 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -97,6 +97,7 @@ HEADERS += $${PWD}/addoninfo.h \ $${PWD}/vf_sameexpressions.h \ $${PWD}/vf_settokenvalue.h \ $${PWD}/vf_string.h \ + $${PWD}/vf_symbolicinfer.h \ $${PWD}/vf_unknownfunctionreturn.h \ $${PWD}/vfvalue.h \ $${PWD}/xml.h @@ -182,5 +183,6 @@ SOURCES += $${PWD}/valueflow.cpp \ $${PWD}/vf_sameexpressions.cpp \ $${PWD}/vf_settokenvalue.cpp \ $${PWD}/vf_string.cpp \ + $${PWD}/vf_symbolicinfer.cpp \ $${PWD}/vf_unknownfunctionreturn.cpp \ $${PWD}/vfvalue.cpp diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index e3a42389b61..62e1ba5467e 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4266,63 +4266,6 @@ static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, con } } -struct SymbolicInferModel : InferModel { - const Token* expr; - explicit SymbolicInferModel(const Token* tok) : expr(tok) { - assert(expr->exprId() != 0); - } - bool match(const ValueFlow::Value& value) const override - { - return value.isSymbolicValue() && value.tokvalue && value.tokvalue->exprId() == expr->exprId(); - } - ValueFlow::Value yield(MathLib::bigint value) const override - { - ValueFlow::Value result(value); - result.valueType = ValueFlow::Value::ValueType::SYMBOLIC; - result.tokvalue = expr; - result.setKnown(); - return result; - } -}; - -static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings& settings) -{ - for (const Scope* scope : symboldatabase.functionScopes) { - for (auto* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { - if (!Token::Match(tok, "-|%comp%")) - continue; - if (tok->hasKnownIntValue()) - continue; - if (!tok->astOperand1()) - continue; - if (!tok->astOperand2()) - continue; - if (tok->astOperand1()->exprId() == 0) - continue; - if (tok->astOperand2()->exprId() == 0) - continue; - if (tok->astOperand1()->hasKnownIntValue()) - continue; - if (tok->astOperand2()->hasKnownIntValue()) - continue; - if (astIsFloat(tok->astOperand1(), false)) - continue; - if (astIsFloat(tok->astOperand2(), false)) - continue; - - SymbolicInferModel leftModel{tok->astOperand1()}; - std::vector values = infer(leftModel, tok->str(), 0, tok->astOperand2()->values()); - if (values.empty()) { - SymbolicInferModel rightModel{tok->astOperand2()}; - values = infer(rightModel, tok->str(), tok->astOperand1()->values(), 0); - } - for (ValueFlow::Value& value : values) { - setTokenValue(tok, std::move(value), settings); - } - } - } -} - template static void valueFlowForwardConst(Token* start, const Token* end, diff --git a/lib/vf_analyze.h b/lib/vf_analyze.h index 98d44619553..c584473b89f 100644 --- a/lib/vf_analyze.h +++ b/lib/vf_analyze.h @@ -35,6 +35,7 @@ #include "vf_rightshift.h" // IWYU pragma: export #include "vf_sameexpressions.h" // IWYU pragma: export #include "vf_string.h" // IWYU pragma: export +#include "vf_symbolicinfer.h" // IWYU pragma: export #include "vf_unknownfunctionreturn.h" // IWYU pragma: export #endif // vfAnalyzeH diff --git a/lib/vf_symbolicinfer.cpp b/lib/vf_symbolicinfer.cpp new file mode 100644 index 00000000000..ef933912e21 --- /dev/null +++ b/lib/vf_symbolicinfer.cpp @@ -0,0 +1,93 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vf_symbolicinfer.h" + +#include "astutils.h" +#include "infer.h" +#include "mathlib.h" +#include "symboldatabase.h" +#include "token.h" +#include "valueptr.h" +#include "vfvalue.h" + +#include "vf_settokenvalue.h" + +#include +#include +#include + +namespace ValueFlow +{ + struct SymbolicInferModel : InferModel { + const Token* expr; + explicit SymbolicInferModel(const Token* tok) : expr(tok) { + assert(expr->exprId() != 0); + } + bool match(const Value& value) const override + { + return value.isSymbolicValue() && value.tokvalue && value.tokvalue->exprId() == expr->exprId(); + } + Value yield(MathLib::bigint value) const override + { + Value result(value); + result.valueType = Value::ValueType::SYMBOLIC; + result.tokvalue = expr; + result.setKnown(); + return result; + } + }; + + void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings& settings) + { + for (const Scope* scope : symboldatabase.functionScopes) { + for (auto* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { + if (!Token::Match(tok, "-|%comp%")) + continue; + if (tok->hasKnownIntValue()) + continue; + if (!tok->astOperand1()) + continue; + if (!tok->astOperand2()) + continue; + if (tok->astOperand1()->exprId() == 0) + continue; + if (tok->astOperand2()->exprId() == 0) + continue; + if (tok->astOperand1()->hasKnownIntValue()) + continue; + if (tok->astOperand2()->hasKnownIntValue()) + continue; + if (astIsFloat(tok->astOperand1(), false)) + continue; + if (astIsFloat(tok->astOperand2(), false)) + continue; + + SymbolicInferModel leftModel{tok->astOperand1()}; + std::vector values = infer(leftModel, tok->str(), 0, tok->astOperand2()->values()); + if (values.empty()) { + SymbolicInferModel rightModel{tok->astOperand2()}; + values = infer(rightModel, tok->str(), tok->astOperand1()->values(), 0); + } + for (Value& value : values) { + setTokenValue(tok, std::move(value), settings); + } + } + } + } +} diff --git a/lib/vf_symbolicinfer.h b/lib/vf_symbolicinfer.h new file mode 100644 index 00000000000..6a21e4a9e55 --- /dev/null +++ b/lib/vf_symbolicinfer.h @@ -0,0 +1,30 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef vfSymbolicInferH +#define vfSymbolicInferH + +class SymbolDatabase; +class Settings; + +namespace ValueFlow +{ + void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings& settings); +} + +#endif // vfSymbolicInferH diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index e2de79783ea..f170cef0492 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -114,6 +114,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_sameexpressions.o \ $(libcppdir)/vf_settokenvalue.o \ $(libcppdir)/vf_string.o \ + $(libcppdir)/vf_symbolicinfer.o \ $(libcppdir)/vf_unknownfunctionreturn.o \ $(libcppdir)/vfvalue.o @@ -159,7 +160,7 @@ simplecpp.o: ../externals/simplecpp/simplecpp.cpp ../externals/simplecpp/simplec tinyxml2.o: ../externals/tinyxml2/tinyxml2.cpp ../externals/tinyxml2/tinyxml2.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ ../externals/tinyxml2/tinyxml2.cpp -$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bailout.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_functionreturn.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_iteratorinfer.h ../lib/vf_iterators.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h +$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bailout.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_functionreturn.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_iteratorinfer.h ../lib/vf_iterators.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_symbolicinfer.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: ../lib/tokenize.cpp ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/astutils.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/summaries.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h @@ -402,6 +403,9 @@ $(libcppdir)/vf_settokenvalue.o: ../lib/vf_settokenvalue.cpp ../lib/addoninfo.h $(libcppdir)/vf_string.o: ../lib/vf_string.cpp ../lib/config.h ../lib/errortypes.h ../lib/mathlib.h ../lib/sourcelocation.h ../lib/standards.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenlist.h ../lib/utils.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_string.cpp +$(libcppdir)/vf_symbolicinfer.o: ../lib/vf_symbolicinfer.cpp ../lib/astutils.h ../lib/config.h ../lib/errortypes.h ../lib/infer.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/utils.h ../lib/valueptr.h ../lib/vf_settokenvalue.h ../lib/vf_symbolicinfer.h ../lib/vfvalue.h + $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_symbolicinfer.cpp + $(libcppdir)/vf_unknownfunctionreturn.o: ../lib/vf_unknownfunctionreturn.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_settokenvalue.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_unknownfunctionreturn.cpp From 12075310137fd7baee86bbe6be3115d8c8ebb6a4 Mon Sep 17 00:00:00 2001 From: firewave Date: Tue, 28 May 2024 09:25:02 +0200 Subject: [PATCH 8/8] ValueFlow: extracted valueFlowImpossibleValues() into separate file --- Makefile | 6 +- lib/cppcheck.vcxproj | 2 + lib/lib.pri | 2 + lib/valueflow.cpp | 157 +--------------------------- lib/vf_analyze.h | 1 + lib/vf_impossiblevalues.cpp | 197 ++++++++++++++++++++++++++++++++++++ lib/vf_impossiblevalues.h | 30 ++++++ oss-fuzz/Makefile | 6 +- 8 files changed, 243 insertions(+), 158 deletions(-) create mode 100644 lib/vf_impossiblevalues.cpp create mode 100644 lib/vf_impossiblevalues.h diff --git a/Makefile b/Makefile index 09937f8ab25..506b9ca6c21 100644 --- a/Makefile +++ b/Makefile @@ -263,6 +263,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_functionreturn.o \ $(libcppdir)/vf_globalconstvar.o \ $(libcppdir)/vf_globalstaticvar.o \ + $(libcppdir)/vf_impossiblevalues.o \ $(libcppdir)/vf_iteratorinfer.o \ $(libcppdir)/vf_iterators.o \ $(libcppdir)/vf_number.o \ @@ -481,7 +482,7 @@ validateRules: ###### Build -$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bailout.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_functionreturn.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_iteratorinfer.h lib/vf_iterators.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_symbolicinfer.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h +$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vf_analyze.h lib/vf_array.h lib/vf_arraybool.h lib/vf_arrayelement.h lib/vf_bailout.h lib/vf_bitand.h lib/vf_common.h lib/vf_debug.h lib/vf_enumvalue.h lib/vf_functionreturn.h lib/vf_globalconstvar.h lib/vf_globalstaticvar.h lib/vf_impossiblevalues.h lib/vf_iteratorinfer.h lib/vf_iterators.h lib/vf_number.h lib/vf_pointeralias.h lib/vf_rightshift.h lib/vf_sameexpressions.h lib/vf_settokenvalue.h lib/vf_string.h lib/vf_symbolicinfer.h lib/vf_unknownfunctionreturn.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h @@ -700,6 +701,9 @@ $(libcppdir)/vf_globalconstvar.o: lib/vf_globalconstvar.cpp lib/config.h lib/err $(libcppdir)/vf_globalstaticvar.o: lib/vf_globalstaticvar.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_globalstaticvar.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_globalstaticvar.cpp +$(libcppdir)/vf_impossiblevalues.o: lib/vf_impossiblevalues.cpp lib/astutils.h lib/calculate.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_impossiblevalues.h lib/vf_settokenvalue.h lib/vfvalue.h + $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_impossiblevalues.cpp + $(libcppdir)/vf_iteratorinfer.o: lib/vf_iteratorinfer.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_iteratorinfer.h lib/vf_settokenvalue.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_iteratorinfer.cpp diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 91a65120dbe..9373e394219 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -98,6 +98,7 @@ + @@ -199,6 +200,7 @@ + diff --git a/lib/lib.pri b/lib/lib.pri index 690944b4b04..4dd6782b633 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -89,6 +89,7 @@ HEADERS += $${PWD}/addoninfo.h \ $${PWD}/vf_functionreturn.h \ $${PWD}/vf_globalconstvar.h \ $${PWD}/vf_globalstaticvar.h \ + $${PWD}/vf_impossiblevalues.h \ $${PWD}/vf_iteratorinfer.h \ $${PWD}/vf_iterators.h \ $${PWD}/vf_number.h \ @@ -175,6 +176,7 @@ SOURCES += $${PWD}/valueflow.cpp \ $${PWD}/vf_functionreturn.cpp \ $${PWD}/vf_globalconstvar.cpp \ $${PWD}/vf_globalstaticvar.cpp \ + $${PWD}/vf_impossiblevalues.cpp \ $${PWD}/vf_iteratorinfer.cpp \ $${PWD}/vf_iterators.cpp \ $${PWD}/vf_number.cpp \ diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 62e1ba5467e..86e4e360ff2 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -523,161 +523,6 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings, int m return 0; } -static std::vector minUnsignedValue(const Token* tok, int depth = 8) -{ - std::vector result; - if (!tok) - return result; - if (depth < 0) - return result; - if (tok->hasKnownIntValue()) { - result = {tok->values().front().intvalue}; - } else if (!Token::Match(tok, "-|%|&|^") && tok->isConstOp() && tok->astOperand1() && tok->astOperand2()) { - std::vector op1 = minUnsignedValue(tok->astOperand1(), depth - 1); - std::vector op2 = minUnsignedValue(tok->astOperand2(), depth - 1); - if (!op1.empty() && !op2.empty()) { - result = calculate>(tok->str(), op1.front(), op2.front()); - } - } - if (result.empty() && astIsUnsigned(tok)) - result = {0}; - return result; -} - -static bool isConvertedToIntegral(const Token* tok, const Settings& settings) -{ - if (!tok) - return false; - std::vector parentTypes = getParentValueTypes(tok, settings); - if (parentTypes.empty()) - return false; - const ValueType& vt = parentTypes.front(); - return vt.type != ValueType::UNKNOWN_INT && vt.isIntegral(); -} - -static bool isSameToken(const Token* tok1, const Token* tok2) -{ - if (!tok1 || !tok2) - return false; - if (tok1->exprId() != 0 && tok1->exprId() == tok2->exprId()) - return true; - if (tok1->hasKnownIntValue() && tok2->hasKnownIntValue()) - return tok1->values().front().intvalue == tok2->values().front().intvalue; - return false; -} - -static void valueFlowImpossibleValues(TokenList& tokenList, const Settings& settings) -{ - for (Token* tok = tokenList.front(); tok; tok = tok->next()) { - if (tok->hasKnownIntValue()) - continue; - if (Token::Match(tok, "true|false")) - continue; - if (astIsBool(tok) || Token::Match(tok, "%comp%")) { - ValueFlow::Value lower{-1}; - lower.bound = ValueFlow::Value::Bound::Upper; - lower.setImpossible(); - setTokenValue(tok, std::move(lower), settings); - - ValueFlow::Value upper{2}; - upper.bound = ValueFlow::Value::Bound::Lower; - upper.setImpossible(); - setTokenValue(tok, std::move(upper), settings); - } else if (astIsUnsigned(tok) && !astIsPointer(tok)) { - std::vector minvalue = minUnsignedValue(tok); - if (minvalue.empty()) - continue; - ValueFlow::Value value{std::max(0, minvalue.front()) - 1}; - value.bound = ValueFlow::Value::Bound::Upper; - value.setImpossible(); - setTokenValue(tok, std::move(value), settings); - } - if (Token::simpleMatch(tok, "?") && Token::Match(tok->astOperand1(), "<|<=|>|>=")) { - const Token* condTok = tok->astOperand1(); - const Token* branchesTok = tok->astOperand2(); - - auto tokens = makeArray(condTok->astOperand1(), condTok->astOperand2()); - auto branches = makeArray(branchesTok->astOperand1(), branchesTok->astOperand2()); - bool flipped = false; - if (std::equal(tokens.cbegin(), tokens.cend(), branches.crbegin(), &isSameToken)) - flipped = true; - else if (!std::equal(tokens.cbegin(), tokens.cend(), branches.cbegin(), &isSameToken)) - continue; - const bool isMin = Token::Match(condTok, "<|<=") ^ flipped; - std::vector values; - for (const Token* tok2 : tokens) { - if (tok2->hasKnownIntValue()) { - values.emplace_back(tok2->values().front()); - } else { - ValueFlow::Value symValue{}; - symValue.valueType = ValueFlow::Value::ValueType::SYMBOLIC; - symValue.tokvalue = tok2; - values.push_back(symValue); - std::copy_if(tok2->values().cbegin(), - tok2->values().cend(), - std::back_inserter(values), - [](const ValueFlow::Value& v) { - if (!v.isKnown()) - return false; - return v.isSymbolicValue(); - }); - } - } - for (ValueFlow::Value& value : values) { - value.setImpossible(); - if (isMin) { - value.intvalue++; - value.bound = ValueFlow::Value::Bound::Lower; - } else { - value.intvalue--; - value.bound = ValueFlow::Value::Bound::Upper; - } - setTokenValue(tok, std::move(value), settings); - } - - } else if (Token::simpleMatch(tok, "%") && tok->astOperand2() && tok->astOperand2()->hasKnownIntValue()) { - ValueFlow::Value value{tok->astOperand2()->values().front()}; - value.bound = ValueFlow::Value::Bound::Lower; - value.setImpossible(); - setTokenValue(tok, std::move(value), settings); - } else if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl (")) { - ValueFlow::Value value{-1}; - value.bound = ValueFlow::Value::Bound::Upper; - value.setImpossible(); - setTokenValue(tok->next(), std::move(value), settings); - } else if (Token::Match(tok, ". data|c_str (") && astIsContainerOwned(tok->astOperand1())) { - const Library::Container* container = getLibraryContainer(tok->astOperand1()); - if (!container) - continue; - if (!container->stdStringLike) - continue; - if (container->view) - continue; - ValueFlow::Value value{0}; - value.setImpossible(); - setTokenValue(tok->tokAt(2), std::move(value), settings); - } else if (Token::Match(tok, "make_shared|make_unique <") && Token::simpleMatch(tok->linkAt(1), "> (")) { - ValueFlow::Value value{0}; - value.setImpossible(); - setTokenValue(tok->linkAt(1)->next(), std::move(value), settings); - } else if ((tokenList.isCPP() && Token::simpleMatch(tok, "this")) || tok->isUnaryOp("&")) { - ValueFlow::Value value{0}; - value.setImpossible(); - setTokenValue(tok, std::move(value), settings); - } else if (tok->variable() && tok->variable()->isArray() && !tok->variable()->isArgument() && - !tok->variable()->isStlType()) { - ValueFlow::Value value{0}; - value.setImpossible(); - setTokenValue(tok, std::move(value), settings); - } else if (tok->isIncompleteVar() && tok->astParent() && tok->astParent()->isUnaryOp("-") && - isConvertedToIntegral(tok->astParent(), settings)) { - ValueFlow::Value value{0}; - value.setImpossible(); - setTokenValue(tok, std::move(value), settings); - } - } -} - static ValuePtr makeAnalyzer(const Token* exprTok, ValueFlow::Value value, const Settings& settings); static ValuePtr makeReverseAnalyzer(const Token* exprTok, ValueFlow::Value value, const Settings& settings); @@ -7857,7 +7702,7 @@ void ValueFlow::setValues(TokenList& tokenlist, }); runner.run({ - VFA(valueFlowImpossibleValues(tokenlist, settings)), + VFA(analyzeImpossibleValues(tokenlist, settings)), VFA(valueFlowSymbolicOperators(symboldatabase, settings)), VFA(valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), VFA(valueFlowSymbolicInfer(symboldatabase, settings)), diff --git a/lib/vf_analyze.h b/lib/vf_analyze.h index c584473b89f..97145576da5 100644 --- a/lib/vf_analyze.h +++ b/lib/vf_analyze.h @@ -28,6 +28,7 @@ #include "vf_functionreturn.h" // IWYU pragma: export #include "vf_globalconstvar.h" // IWYU pragma: export #include "vf_globalstaticvar.h" // IWYU pragma: export +#include "vf_impossiblevalues.h" // IWYU pragma: export #include "vf_iteratorinfer.h" // IWYU pragma: export #include "vf_iterators.h" // IWYU pragma: export #include "vf_number.h" // IWYU pragma: export diff --git a/lib/vf_impossiblevalues.cpp b/lib/vf_impossiblevalues.cpp new file mode 100644 index 00000000000..591e0880588 --- /dev/null +++ b/lib/vf_impossiblevalues.cpp @@ -0,0 +1,197 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vf_impossiblevalues.h" + +#include "astutils.h" +#include "calculate.h" +#include "library.h" +#include "mathlib.h" +#include "symboldatabase.h" +#include "token.h" +#include "tokenlist.h" +#include "utils.h" +#include "vfvalue.h" + +#include "vf_settokenvalue.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace ValueFlow +{ + static std::vector minUnsignedValue(const Token* tok, int depth = 8) + { + std::vector result; + if (!tok) + return result; + if (depth < 0) + return result; + if (tok->hasKnownIntValue()) { + result = {tok->values().front().intvalue}; + } else if (!Token::Match(tok, "-|%|&|^") && tok->isConstOp() && tok->astOperand1() && tok->astOperand2()) { + std::vector op1 = minUnsignedValue(tok->astOperand1(), depth - 1); + std::vector op2 = minUnsignedValue(tok->astOperand2(), depth - 1); + if (!op1.empty() && !op2.empty()) { + result = calculate>(tok->str(), op1.front(), op2.front()); + } + } + if (result.empty() && astIsUnsigned(tok)) + result = {0}; + return result; + } + + static bool isSameToken(const Token* tok1, const Token* tok2) + { + if (!tok1 || !tok2) + return false; + if (tok1->exprId() != 0 && tok1->exprId() == tok2->exprId()) + return true; + if (tok1->hasKnownIntValue() && tok2->hasKnownIntValue()) + return tok1->values().front().intvalue == tok2->values().front().intvalue; + return false; + } + + static bool isConvertedToIntegral(const Token* tok, const Settings& settings) + { + if (!tok) + return false; + std::vector parentTypes = getParentValueTypes(tok, settings); + if (parentTypes.empty()) + return false; + const ValueType& vt = parentTypes.front(); + return vt.type != ValueType::UNKNOWN_INT && vt.isIntegral(); + } + + void analyzeImpossibleValues(TokenList& tokenList, const Settings& settings) + { + for (Token* tok = tokenList.front(); tok; tok = tok->next()) { + if (tok->hasKnownIntValue()) + continue; + if (Token::Match(tok, "true|false")) + continue; + if (astIsBool(tok) || Token::Match(tok, "%comp%")) { + Value lower{-1}; + lower.bound = Value::Bound::Upper; + lower.setImpossible(); + setTokenValue(tok, std::move(lower), settings); + + Value upper{2}; + upper.bound = Value::Bound::Lower; + upper.setImpossible(); + setTokenValue(tok, std::move(upper), settings); + } else if (astIsUnsigned(tok) && !astIsPointer(tok)) { + std::vector minvalue = minUnsignedValue(tok); + if (minvalue.empty()) + continue; + Value value{std::max(0, minvalue.front()) - 1}; + value.bound = Value::Bound::Upper; + value.setImpossible(); + setTokenValue(tok, std::move(value), settings); + } + if (Token::simpleMatch(tok, "?") && Token::Match(tok->astOperand1(), "<|<=|>|>=")) { + const Token* condTok = tok->astOperand1(); + const Token* branchesTok = tok->astOperand2(); + + auto tokens = makeArray(condTok->astOperand1(), condTok->astOperand2()); + auto branches = makeArray(branchesTok->astOperand1(), branchesTok->astOperand2()); + bool flipped = false; + if (std::equal(tokens.cbegin(), tokens.cend(), branches.crbegin(), &isSameToken)) + flipped = true; + else if (!std::equal(tokens.cbegin(), tokens.cend(), branches.cbegin(), &isSameToken)) + continue; + const bool isMin = Token::Match(condTok, "<|<=") ^ flipped; + std::vector values; + for (const Token* tok2 : tokens) { + if (tok2->hasKnownIntValue()) { + values.emplace_back(tok2->values().front()); + } else { + Value symValue{}; + symValue.valueType = Value::ValueType::SYMBOLIC; + symValue.tokvalue = tok2; + values.push_back(symValue); + std::copy_if(tok2->values().cbegin(), + tok2->values().cend(), + std::back_inserter(values), + [](const Value& v) { + if (!v.isKnown()) + return false; + return v.isSymbolicValue(); + }); + } + } + for (Value& value : values) { + value.setImpossible(); + if (isMin) { + value.intvalue++; + value.bound = Value::Bound::Lower; + } else { + value.intvalue--; + value.bound = Value::Bound::Upper; + } + setTokenValue(tok, std::move(value), settings); + } + + } else if (Token::simpleMatch(tok, "%") && tok->astOperand2() && tok->astOperand2()->hasKnownIntValue()) { + Value value{tok->astOperand2()->values().front()}; + value.bound = Value::Bound::Lower; + value.setImpossible(); + setTokenValue(tok, std::move(value), settings); + } else if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl (")) { + Value value{-1}; + value.bound = Value::Bound::Upper; + value.setImpossible(); + setTokenValue(tok->next(), std::move(value), settings); + } else if (Token::Match(tok, ". data|c_str (") && astIsContainerOwned(tok->astOperand1())) { + const Library::Container* container = getLibraryContainer(tok->astOperand1()); + if (!container) + continue; + if (!container->stdStringLike) + continue; + if (container->view) + continue; + Value value{0}; + value.setImpossible(); + setTokenValue(tok->tokAt(2), std::move(value), settings); + } else if (Token::Match(tok, "make_shared|make_unique <") && Token::simpleMatch(tok->linkAt(1), "> (")) { + Value value{0}; + value.setImpossible(); + setTokenValue(tok->linkAt(1)->next(), std::move(value), settings); + } else if ((tokenList.isCPP() && Token::simpleMatch(tok, "this")) || tok->isUnaryOp("&")) { + Value value{0}; + value.setImpossible(); + setTokenValue(tok, std::move(value), settings); + } else if (tok->variable() && tok->variable()->isArray() && !tok->variable()->isArgument() && + !tok->variable()->isStlType()) { + Value value{0}; + value.setImpossible(); + setTokenValue(tok, std::move(value), settings); + } else if (tok->isIncompleteVar() && tok->astParent() && tok->astParent()->isUnaryOp("-") && + isConvertedToIntegral(tok->astParent(), settings)) { + Value value{0}; + value.setImpossible(); + setTokenValue(tok, std::move(value), settings); + } + } + } +} diff --git a/lib/vf_impossiblevalues.h b/lib/vf_impossiblevalues.h new file mode 100644 index 00000000000..018976ec605 --- /dev/null +++ b/lib/vf_impossiblevalues.h @@ -0,0 +1,30 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2024 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef vfImpossibleValuesH +#define vfImpossibleValuesH + +class TokenList; +class Settings; + +namespace ValueFlow +{ + void analyzeImpossibleValues(TokenList& tokenList, const Settings& settings); +} + +#endif // vfImpossibleValuesH diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index f170cef0492..b7dee5fd426 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -106,6 +106,7 @@ LIBOBJ = $(libcppdir)/valueflow.o \ $(libcppdir)/vf_functionreturn.o \ $(libcppdir)/vf_globalconstvar.o \ $(libcppdir)/vf_globalstaticvar.o \ + $(libcppdir)/vf_impossiblevalues.o \ $(libcppdir)/vf_iteratorinfer.o \ $(libcppdir)/vf_iterators.o \ $(libcppdir)/vf_number.o \ @@ -160,7 +161,7 @@ simplecpp.o: ../externals/simplecpp/simplecpp.cpp ../externals/simplecpp/simplec tinyxml2.o: ../externals/tinyxml2/tinyxml2.cpp ../externals/tinyxml2/tinyxml2.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -w -c -o $@ ../externals/tinyxml2/tinyxml2.cpp -$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bailout.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_functionreturn.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_iteratorinfer.h ../lib/vf_iterators.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_symbolicinfer.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h +$(libcppdir)/valueflow.o: ../lib/valueflow.cpp ../lib/addoninfo.h ../lib/analyzer.h ../lib/astutils.h ../lib/calculate.h ../lib/check.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/findtoken.h ../lib/forwardanalyzer.h ../lib/infer.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/programmemory.h ../lib/reverseanalyzer.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/valueptr.h ../lib/vf_analyze.h ../lib/vf_array.h ../lib/vf_arraybool.h ../lib/vf_arrayelement.h ../lib/vf_bailout.h ../lib/vf_bitand.h ../lib/vf_common.h ../lib/vf_debug.h ../lib/vf_enumvalue.h ../lib/vf_functionreturn.h ../lib/vf_globalconstvar.h ../lib/vf_globalstaticvar.h ../lib/vf_impossiblevalues.h ../lib/vf_iteratorinfer.h ../lib/vf_iterators.h ../lib/vf_number.h ../lib/vf_pointeralias.h ../lib/vf_rightshift.h ../lib/vf_sameexpressions.h ../lib/vf_settokenvalue.h ../lib/vf_string.h ../lib/vf_symbolicinfer.h ../lib/vf_unknownfunctionreturn.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp $(libcppdir)/tokenize.o: ../lib/tokenize.cpp ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/astutils.h ../lib/color.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/summaries.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h @@ -379,6 +380,9 @@ $(libcppdir)/vf_globalconstvar.o: ../lib/vf_globalconstvar.cpp ../lib/config.h . $(libcppdir)/vf_globalstaticvar.o: ../lib/vf_globalstaticvar.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_globalstaticvar.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_globalstaticvar.cpp +$(libcppdir)/vf_impossiblevalues.o: ../lib/vf_impossiblevalues.cpp ../lib/astutils.h ../lib/calculate.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_impossiblevalues.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h + $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_impossiblevalues.cpp + $(libcppdir)/vf_iteratorinfer.o: ../lib/vf_iteratorinfer.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_iteratorinfer.h ../lib/vf_settokenvalue.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vf_iteratorinfer.cpp