diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index 8119d6fc1c8..70e0d1ec4bb 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 8f250ffa101..c12bb4467a2 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -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 @@ -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 = \"') {}\n" + "}\n" + "void bar() {\n" + " foo(\"q\");\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void array_index_multidim() { check("void f()\n" "{\n"