From 8541e0503e349eb4e07db77159287cdc8ea6607f Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Sat, 22 May 2021 16:33:13 -0500 Subject: [PATCH] Fix 10290: false negative: container out of bounds (#3269) --- lib/forwardanalyzer.cpp | 6 ++++-- lib/valueflow.cpp | 4 ++-- test/teststl.cpp | 7 +++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index 85a0610ef..7f078a333 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -111,8 +111,10 @@ struct ForwardTraversal { return Progress::Skip; T* firstOp = tok->astOperand1(); T* secondOp = tok->astOperand2(); - // Evaluate RHS of assignment before LHS - if (tok->isAssignmentOp()) + // Evaluate: + // 1. RHS of assignment before LHS + // 2. Unary op before operand + if (tok->isAssignmentOp() || !secondOp) std::swap(firstOp, secondOp); if (firstOp && traverseRecursive(firstOp, f, traverseUnknown, recursion+1) == Progress::Break) return Break(); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 42866e137..8d8c497f2 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1244,7 +1244,7 @@ static void valueFlowPointerAlias(TokenList *tokenlist) } } -static void valueFlowPointerAliasDeref(TokenList *tokenlist) +static void valueFlowUninitPointerAliasDeref(TokenList *tokenlist) { for (Token *tok = tokenlist->front(); tok; tok = tok->next()) { if (!tok->isUnaryOp("*")) @@ -6869,7 +6869,6 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, while (n > 0 && values < getTotalValues(tokenlist)) { values = getTotalValues(tokenlist); valueFlowImpossibleValues(tokenlist, settings); - valueFlowPointerAliasDeref(tokenlist); valueFlowArrayBool(tokenlist); valueFlowRightShift(tokenlist, settings); valueFlowAfterMove(tokenlist, symboldatabase, errorLogger, settings); @@ -6883,6 +6882,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings); valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, errorLogger, settings); valueFlowUninit(tokenlist, symboldatabase, errorLogger, settings); + valueFlowUninitPointerAliasDeref(tokenlist); if (tokenlist->isCPP()) { valueFlowSmartPointer(tokenlist, errorLogger, settings); valueFlowIterators(tokenlist, settings); diff --git a/test/teststl.cpp b/test/teststl.cpp index bc522ef80..5059e6162 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -440,6 +440,13 @@ private: " (*PArr)[i] = 1;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + checkNormal("int f() {\n" + " std::vector v;\n" + " std::vector * pv = &v;\n" + " return (*pv).at(42);\n" + "}\n"); + ASSERT_EQUALS("test.cpp:4:error:Out of bounds access in expression '(*pv).at(42)' because '*pv' is empty and 'at' may be non-zero.\n", errout.str()); } void outOfBoundsIndexExpression() {