From 2a7f00cf9a0b61abc334da67318493b65e1fb9bc Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sat, 21 May 2022 08:33:42 +0200 Subject: [PATCH] Fix #8545 FN Condition '...' is always true ' uint16_t i; ( i <= 0xFFFF)' (#4114) --- lib/checkcondition.cpp | 47 +++++++++++++++++++++++++++++++++-------- test/cfg/googletest.cpp | 4 ++-- test/cfg/runtests.sh | 2 +- test/testcondition.cpp | 42 ++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 12 deletions(-) diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 9baa251bd..7292cd0d6 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -1830,29 +1830,58 @@ void CheckCondition::checkCompareValueOutOfTypeRange() else typeMaxValue = unsignedTypeMaxValue / 2; - bool result; + bool result{}; + const auto kiv = valueTok->getKnownIntValue(); if (tok->str() == "==") result = false; else if (tok->str() == "!=") result = true; else if (tok->str()[0] == '>' && i == 0) // num > var - result = (valueTok->getKnownIntValue() > 0); + result = (kiv > 0); else if (tok->str()[0] == '>' && i == 1) // var > num - result = (valueTok->getKnownIntValue() < 0); + result = (kiv < 0); else if (tok->str()[0] == '<' && i == 0) // num < var - result = (valueTok->getKnownIntValue() < 0); + result = (kiv < 0); else if (tok->str()[0] == '<' && i == 1) // var < num - result = (valueTok->getKnownIntValue() > 0); + result = (kiv > 0); - if (valueTok->getKnownIntValue() < typeMinValue) { - compareValueOutOfTypeRangeError(valueTok, typeTok->valueType()->str(), valueTok->getKnownIntValue(), result); + bool error = false; + if (kiv < typeMinValue || kiv > typeMaxValue) { + error = true; + } else { + switch (i) { + case 0: // num cmp var + if (kiv == typeMinValue) { + if (tok->str() == "<=") { + result = true; + error = true; + } else if (tok->str() == ">") + error = true; + } + else if (kiv == typeMaxValue && (tok->str() == ">=" || tok->str() == "<")) { + error = true; + } + break; + case 1: // var cmp num + if (kiv == typeMinValue) { + if (tok->str() == ">=") { + result = true; + error = true; + } else if (tok->str() == "<") + error = true; + } + else if (kiv == typeMaxValue && (tok->str() == "<=" || tok->str() == ">")) { + error = true; + } + break; + } } - else if (valueTok->getKnownIntValue() > typeMaxValue) - compareValueOutOfTypeRangeError(valueTok, typeTok->valueType()->str(), valueTok->getKnownIntValue(), result); + if (error) + compareValueOutOfTypeRangeError(valueTok, typeTok->valueType()->str(), kiv, result); } } } diff --git a/test/cfg/googletest.cpp b/test/cfg/googletest.cpp index 1e4f71da2..26b671e98 100644 --- a/test/cfg/googletest.cpp +++ b/test/cfg/googletest.cpp @@ -71,8 +71,8 @@ TEST(Test, warning_in_assert_macros) ASSERT_GE(i, i); unsigned int u = errno; - // cppcheck-suppress unsignedPositive + // cppcheck-suppress [unsignedPositive, compareValueOutOfTypeRangeError] ASSERT_GE(u, 0); - // cppcheck-suppress unsignedLessThanZero + // cppcheck-suppress [unsignedLessThanZero, compareValueOutOfTypeRangeError] ASSERT_LT(u, 0); } diff --git a/test/cfg/runtests.sh b/test/cfg/runtests.sh index f53b11a6b..8b0d8b1ed 100755 --- a/test/cfg/runtests.sh +++ b/test/cfg/runtests.sh @@ -23,7 +23,7 @@ CPPCHECK="$DIR"../../cppcheck CFG="$DIR"../../cfg/ # Cppcheck options -CPPCHECK_OPT='--check-library --enable=information --enable=style --error-exitcode=-1 --suppress=missingIncludeSystem --inline-suppr --template="{file}:{line}:{severity}:{id}:{message}"' +CPPCHECK_OPT='--check-library --platform=unix64 --enable=information --enable=style --error-exitcode=-1 --suppress=missingIncludeSystem --inline-suppr --template="{file}:{line}:{severity}:{id}:{message}"' # Compiler settings CXX=g++ diff --git a/test/testcondition.cpp b/test/testcondition.cpp index dbe012a3c..ee09454f7 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -5181,6 +5181,48 @@ private: " if (x < 3000000000) {}\n" "}", &settingsUnix64); ASSERT_EQUALS("[test.cpp:2]: (style) Comparing expression of type 'signed int' against value 3000000000. Condition is always true.\n", errout.str()); + + check("void f(const signed char i) {\n" // #8545 + " if (i > -129) {}\n" // warn + " if (i >= -128) {}\n" // warn + " if (i >= -127) {}\n" + " if (i < +128) {}\n" // warn + " if (i <= +127) {}\n" // warn + " if (i <= +126) {}\n" + "}\n", &settingsUnix64); + ASSERT_EQUALS("[test.cpp:2]: (style) Comparing expression of type 'const signed char' against value -129. Condition is always true.\n" + "[test.cpp:3]: (style) Comparing expression of type 'const signed char' against value -128. Condition is always true.\n" + "[test.cpp:5]: (style) Comparing expression of type 'const signed char' against value 128. Condition is always true.\n" + "[test.cpp:6]: (style) Comparing expression of type 'const signed char' against value 127. Condition is always true.\n", + errout.str()); + + check("void f(const unsigned char u) {\n" + " if (u > 0) {}\n" + " if (u < 0) {}\n" // warn + " if (u >= 0) {}\n" // warn + " if (u <= 0) {}\n" + " if (u > 255) {}\n" // warn + " if (u < 255) {}\n" + " if (u >= 255) {}\n" + " if (u <= 255) {}\n" // warn + " if (0 < u) {}\n" + " if (0 > u) {}\n" // warn + " if (0 <= u) {}\n" // warn + " if (0 >= u) {}\n" + " if (255 < u) {}\n" // warn + " if (255 > u) {}\n" + " if (255 <= u) {}\n" + " if (255 >= u) {}\n" // warn + "}\n", &settingsUnix64); + ASSERT_EQUALS("[test.cpp:3]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false.\n" + "[test.cpp:4]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true.\n" + "[test.cpp:6]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false.\n" + "[test.cpp:9]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true.\n" + "[test.cpp:11]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always false.\n" + "[test.cpp:12]: (style) Comparing expression of type 'const unsigned char' against value 0. Condition is always true.\n" + "[test.cpp:14]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always false.\n" + "[test.cpp:17]: (style) Comparing expression of type 'const unsigned char' against value 255. Condition is always true.\n", + errout.str()); } void knownConditionCast() { // #9976