From 8569a970b41e6323a58f78d6d415c6f26103355a Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Wed, 10 Feb 2021 01:11:06 -0600 Subject: [PATCH] Fix issue 10147: False positive: Out of bounds access in expression 'v[0]' because 'v' is empty. (#3123) --- lib/programmemory.cpp | 31 ++++++++++++++----------------- test/testvalueflow.cpp | 12 ++++++++++++ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index d8680a7d1..d5ec2dced 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -403,6 +403,20 @@ void execute(const Token *expr, *error = true; } + else if (Token::Match(expr->tokAt(-3), "%var% . %name% (") && astIsContainer(expr->tokAt(-3))) { + const Token* containerTok = expr->tokAt(-3); + Library::Container::Yield yield = containerTok->valueType()->container->getYield(expr->strAt(-1)); + if (yield == Library::Container::Yield::SIZE) { + if (!programMemory->getContainerSizeValue(containerTok->exprId(), result)) + *error = true; + } else if (yield == Library::Container::Yield::EMPTY) { + if (!programMemory->getContainerEmptyValue(containerTok->exprId(), result)) + *error = true; + } else { + *error = true; + } + } + else if (expr->exprId() > 0 && programMemory->hasValue(expr->exprId())) { if (!programMemory->getIntValue(expr->exprId(), result)) *error = true; @@ -570,24 +584,7 @@ void execute(const Token *expr, *result = 0; else *error = true; - } else if (Token::Match(expr->tokAt(-3), "%var% . %name% (")) { - const Token* containerTok = expr->tokAt(-3); - if (astIsContainer(containerTok)) { - Library::Container::Yield yield = containerTok->valueType()->container->getYield(expr->strAt(-1)); - if (yield == Library::Container::Yield::SIZE) { - if (!programMemory->getContainerSizeValue(containerTok->exprId(), result)) - *error = true; - } else if (yield == Library::Container::Yield::EMPTY) { - if (!programMemory->getContainerEmptyValue(containerTok->exprId(), result)) - *error = true; - } else { - *error = true; - } - } else { - *error = true; - } } - else *error = true; } diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 22d19157a..456807edc 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -5069,6 +5069,18 @@ private: " return a.size();\n" "}\n"; ASSERT_EQUALS(true, tokenValues(code, "a . size", ValueFlow::Value::ValueType::CONTAINER_SIZE).empty()); + + code = "std::vector g();\n" + "std::vector f() {\n" + " std::vector v = g();\n" + " if (!v.empty()) {\n" + " if (v[0] != 0)\n" + " v.clear();\n" + " }\n" + " if (!v.empty() && v[0] != 0) {}\n" + " return v;\n" + "}\n"; + ASSERT_EQUALS(true, tokenValues(code, "v [ 0 ] != 0 ) { }", ValueFlow::Value::ValueType::CONTAINER_SIZE).empty()); } void valueFlowDynamicBufferSize() {