Skip to content

Commit 63b7e6a

Browse files
authored
Fix 11088: False positive: Array index out of bounds (function pointer parameter is array) (#5200)
1 parent a0c4e20 commit 63b7e6a

2 files changed

Lines changed: 47 additions & 0 deletions

File tree

lib/programmemory.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,36 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
636636
v.tokvalue = nullptr;
637637
return v;
638638
};
639+
functions["strcmp"] = [](const std::vector<ValueFlow::Value>& args) {
640+
if (args.size() != 2)
641+
return ValueFlow::Value::unknown();
642+
const ValueFlow::Value& lhs = args[0];
643+
if (!(lhs.isTokValue() && lhs.tokvalue->tokType() == Token::eString))
644+
return ValueFlow::Value::unknown();
645+
const ValueFlow::Value& rhs = args[1];
646+
if (!(rhs.isTokValue() && rhs.tokvalue->tokType() == Token::eString))
647+
return ValueFlow::Value::unknown();
648+
ValueFlow::Value v(getStringLiteral(lhs.tokvalue->str()).compare(getStringLiteral(rhs.tokvalue->str())));
649+
ValueFlow::combineValueProperties(lhs, rhs, v);
650+
return v;
651+
};
652+
functions["strncmp"] = [](const std::vector<ValueFlow::Value>& args) {
653+
if (args.size() != 3)
654+
return ValueFlow::Value::unknown();
655+
const ValueFlow::Value& lhs = args[0];
656+
if (!(lhs.isTokValue() && lhs.tokvalue->tokType() == Token::eString))
657+
return ValueFlow::Value::unknown();
658+
const ValueFlow::Value& rhs = args[1];
659+
if (!(rhs.isTokValue() && rhs.tokvalue->tokType() == Token::eString))
660+
return ValueFlow::Value::unknown();
661+
const ValueFlow::Value& len = args[2];
662+
if (!len.isIntValue())
663+
return ValueFlow::Value::unknown();
664+
ValueFlow::Value v(getStringLiteral(lhs.tokvalue->str())
665+
.compare(0, len.intvalue, getStringLiteral(rhs.tokvalue->str()), 0, len.intvalue));
666+
ValueFlow::combineValueProperties(lhs, rhs, v);
667+
return v;
668+
};
639669
functions["sin"] = [](const std::vector<ValueFlow::Value>& args) {
640670
if (args.size() != 1)
641671
return ValueFlow::Value::unknown();
@@ -1164,6 +1194,7 @@ static ValueFlow::Value executeImpl(const Token* expr, ProgramMemory& pm, const
11641194
if (expr->hasKnownIntValue() && !expr->isAssignmentOp() && expr->str() != ",")
11651195
return expr->values().front();
11661196
if ((value = expr->getKnownValue(ValueFlow::Value::ValueType::FLOAT)) ||
1197+
(value = expr->getKnownValue(ValueFlow::Value::ValueType::TOK)) ||
11671198
(value = expr->getKnownValue(ValueFlow::Value::ValueType::ITERATOR_START)) ||
11681199
(value = expr->getKnownValue(ValueFlow::Value::ValueType::ITERATOR_END)) ||
11691200
(value = expr->getKnownValue(ValueFlow::Value::ValueType::CONTAINER_SIZE))) {

test/testbufferoverrun.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class TestBufferOverrun : public TestFixture {
176176
TEST_CASE(array_index_71); // #11461
177177
TEST_CASE(array_index_72); // #11784
178178
TEST_CASE(array_index_73); // #11530
179+
TEST_CASE(array_index_74); // #11088
179180
TEST_CASE(array_index_multidim);
180181
TEST_CASE(array_index_switch_in_for);
181182
TEST_CASE(array_index_for_in_for); // FP: #2634
@@ -1952,6 +1953,21 @@ class TestBufferOverrun : public TestFixture {
19521953
ASSERT_EQUALS("", errout.str());
19531954
}
19541955

1956+
// #11088
1957+
void array_index_74()
1958+
{
1959+
check("void foo(const char *keys) {\n"
1960+
" const char *prefix = \"<Shift+\";\n"
1961+
" const size_t prefix_len = strlen(prefix);\n"
1962+
" if (strncmp(keys, prefix, prefix_len)) { return; }\n"
1963+
" if (keys[prefix_len] == '>') {}\n"
1964+
"}\n"
1965+
"void bar() {\n"
1966+
" foo(\"q\");\n"
1967+
"}\n");
1968+
ASSERT_EQUALS("", errout.str());
1969+
}
1970+
19551971
void array_index_multidim() {
19561972
check("void f()\n"
19571973
"{\n"

0 commit comments

Comments
 (0)