From 63b7e6a283c9a1dfaee87cd1cea539ba793debbb Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Tue, 27 Jun 2023 03:44:11 -0500 Subject: [PATCH] Fix 11088: False positive: Array index out of bounds (function pointer parameter is array) (#5200) --- lib/programmemory.cpp | 31 +++++++++++++++++++++++++++++++ test/testbufferoverrun.cpp | 16 ++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index 8119d6fc1..70e0d1ec4 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -636,6 +636,36 @@ static std::unordered_map createBuiltinLibr v.tokvalue = nullptr; return v; }; + functions["strcmp"] = [](const std::vector& args) { + if (args.size() != 2) + return ValueFlow::Value::unknown(); + const ValueFlow::Value& lhs = args[0]; + if (!(lhs.isTokValue() && lhs.tokvalue->tokType() == Token::eString)) + return ValueFlow::Value::unknown(); + const ValueFlow::Value& rhs = args[1]; + if (!(rhs.isTokValue() && rhs.tokvalue->tokType() == Token::eString)) + return ValueFlow::Value::unknown(); + ValueFlow::Value v(getStringLiteral(lhs.tokvalue->str()).compare(getStringLiteral(rhs.tokvalue->str()))); + ValueFlow::combineValueProperties(lhs, rhs, v); + return v; + }; + functions["strncmp"] = [](const std::vector& args) { + if (args.size() != 3) + return ValueFlow::Value::unknown(); + const ValueFlow::Value& lhs = args[0]; + if (!(lhs.isTokValue() && lhs.tokvalue->tokType() == Token::eString)) + return ValueFlow::Value::unknown(); + const ValueFlow::Value& rhs = args[1]; + if (!(rhs.isTokValue() && rhs.tokvalue->tokType() == Token::eString)) + return ValueFlow::Value::unknown(); + const ValueFlow::Value& len = args[2]; + if (!len.isIntValue()) + return ValueFlow::Value::unknown(); + ValueFlow::Value v(getStringLiteral(lhs.tokvalue->str()) + .compare(0, len.intvalue, getStringLiteral(rhs.tokvalue->str()), 0, len.intvalue)); + ValueFlow::combineValueProperties(lhs, rhs, v); + return v; + }; functions["sin"] = [](const std::vector& args) { if (args.size() != 1) return ValueFlow::Value::unknown(); @@ -1164,6 +1194,7 @@ static ValueFlow::Value executeImpl(const Token* expr, ProgramMemory& pm, const if (expr->hasKnownIntValue() && !expr->isAssignmentOp() && expr->str() != ",") return expr->values().front(); if ((value = expr->getKnownValue(ValueFlow::Value::ValueType::FLOAT)) || + (value = expr->getKnownValue(ValueFlow::Value::ValueType::TOK)) || (value = expr->getKnownValue(ValueFlow::Value::ValueType::ITERATOR_START)) || (value = expr->getKnownValue(ValueFlow::Value::ValueType::ITERATOR_END)) || (value = expr->getKnownValue(ValueFlow::Value::ValueType::CONTAINER_SIZE))) { diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 8f250ffa1..c12bb4467 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -176,6 +176,7 @@ private: TEST_CASE(array_index_71); // #11461 TEST_CASE(array_index_72); // #11784 TEST_CASE(array_index_73); // #11530 + TEST_CASE(array_index_74); // #11088 TEST_CASE(array_index_multidim); TEST_CASE(array_index_switch_in_for); TEST_CASE(array_index_for_in_for); // FP: #2634 @@ -1952,6 +1953,21 @@ private: ASSERT_EQUALS("", errout.str()); } + // #11088 + void array_index_74() + { + check("void foo(const char *keys) {\n" + " const char *prefix = \"') {}\n" + "}\n" + "void bar() {\n" + " foo(\"q\");\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void array_index_multidim() { check("void f()\n" "{\n"