Repository navigation
Fix #15034 FN arrayIndexOutOfBounds (ternary in subfunction) #8856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
50b9a36
67eb159
86f316f
55d8250
1406a57
bbd2441
72fa075
c9716c6
dff6214
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3633,7 +3633,7 @@ class TestSymbolDatabase : public TestFixture { | |
| ASSERT(fredScope != nullptr); | ||
|
|
||
| // The struct Fred has two functions, a constructor and a destructor | ||
| ASSERT_EQUALS(2U, fredScope->functionList.size()); | ||
| ASSERT_EQUALS(2U, fredScope->functionList.size()); // cppcheck-suppress nullPointer // see ticket #9747 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This suppression is only needed because of the valueflow change, so selfcheck now reports a new |
||
|
|
||
| // Get linenumbers where the bodies for the constructor and destructor are.. | ||
| unsigned int constructor = 0; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4325,6 +4325,45 @@ class TestValueFlow : public TestFixture { | |
| "}\n"; | ||
| auto values = tokenValues(code, "s :", ValueFlow::Value::ValueType::FLOAT); | ||
| ASSERT_EQUALS(0, values.size()); | ||
|
|
||
| code = "int a[5];\n" // 15034 | ||
| "int g(int i) {\n" | ||
| " return a[i < 0 ? -i : i];\n" | ||
| "}\n" | ||
| "int f() {\n" | ||
| " return g(-5);\n" | ||
| "}\n"; | ||
| values = tokenValues(code, "?"); | ||
| ASSERT_EQUALS(2, values.size()); | ||
| auto it = values.begin(); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueType::INT, it->valueType); | ||
| ASSERT_EQUALS(0, it->intvalue); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::Bound::Lower, it->bound); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Possible, it->valueKind); | ||
| ++it; | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueType::INT, it->valueType); | ||
| ASSERT_EQUALS(5, it->intvalue); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::Bound::Point, it->bound); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Possible, it->valueKind); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The ticket is about an |
||
|
|
||
| code = "int f(int a, int b) {\n" | ||
| " if (b <= 0)\n" | ||
| " return b;\n" | ||
| " int a = (a > 0) ? a : -a;\n" | ||
| " return 1 / (a < b ? b : a);\n" | ||
| "}\n"; | ||
| values = tokenValues(code, "? b"); | ||
| ASSERT_EQUALS(2, values.size()); | ||
| it = values.begin(); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueType::SYMBOLIC, it->valueType); | ||
| ASSERT_EQUALS(-1, it->intvalue); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::Bound::Upper, it->bound); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Impossible, it->valueKind); | ||
| ++it; | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueType::SYMBOLIC, it->valueType); | ||
| ASSERT_EQUALS(-1, it->intvalue); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::Bound::Upper, it->bound); | ||
| ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Impossible, it->valueKind); | ||
| } | ||
|
|
||
| void valueFlowForwardLambda() { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an AI review. Take it with a grain of salt and feel free to reject it by resolving the comment.
I confirmed that this suppression is needed because of the PR. With selfcheck's options (
--check-level=exhaustive --library=cppcheck-lib ...), the merge base gives no warning here, while this PR givesPossible null pointer dereference: fredScope. It is a false positive, sinceassert_()throws when the condition fails. The cause is that the removed "condition depends on only one variable" guard insetTokenValue()used to drop thenullptrfrom(it == db->scopeList.end()) ? nullptr : &*it, because the condition contains a function call. So user code with the same "ternary + throwing check" pattern will now also hit #9747.To get a feel for how often that happens, I compared warnings for the merge base and the PR on lib/, cli/, test/cfg/, samples/, testsymboldatabase.cpp and testvalueflow.cpp (normal check level, style/warning/portability/performance, inconclusive). Both gave exactly the same 2407 warnings, so it doesn't look widespread. Some correlated-ternary probes such as
d = (a > b) ? 0 : a - b; if (a > b) return 0; return 10 / d;also stayed silent. Just mentioning it so the trade-off is a conscious one.