Skip to content

Commit

Permalink
Fix 11088: False positive: Array index out of bounds (function pointe…
Browse files Browse the repository at this point in the history
…r parameter is array) (#5200)
  • Loading branch information
pfultz2 committed Jun 27, 2023
1 parent a0c4e20 commit 63b7e6a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
31 changes: 31 additions & 0 deletions lib/programmemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,36 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
v.tokvalue = nullptr;
return v;
};
functions["strcmp"] = [](const std::vector<ValueFlow::Value>& 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<ValueFlow::Value>& 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<ValueFlow::Value>& args) {
if (args.size() != 1)
return ValueFlow::Value::unknown();
Expand Down Expand Up @@ -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))) {
Expand Down
16 changes: 16 additions & 0 deletions test/testbufferoverrun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ class TestBufferOverrun : public TestFixture {
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
Expand Down Expand Up @@ -1952,6 +1953,21 @@ class TestBufferOverrun : public TestFixture {
ASSERT_EQUALS("", errout.str());
}

// #11088
void array_index_74()
{
check("void foo(const char *keys) {\n"
" const char *prefix = \"<Shift+\";\n"
" const size_t prefix_len = strlen(prefix);\n"
" if (strncmp(keys, prefix, prefix_len)) { return; }\n"
" if (keys[prefix_len] == '>') {}\n"
"}\n"
"void bar() {\n"
" foo(\"q\");\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}

void array_index_multidim() {
check("void f()\n"
"{\n"
Expand Down

0 comments on commit 63b7e6a

Please sign in to comment.