-
Notifications
You must be signed in to change notification settings - Fork 1.5k
ExprEngine: Handle pointer assignments in loops without bailout #2949
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
Conversation
The following source code:
```
void foo(int *a)
{
while (1)
*a = 42;
*a == 42;
}
```
Before this commit generates a redundant "bailout" value on the assigment:
15:12: 0:memory:{a=($2,[$1],[:]=?,[0]=bailout,[0]=42)}
After this commit:
15:12: 0:memory:{a=($2,[$1],[:]=?,[0]=42)}
The added tests are redundant and can't detect this error, but they
increase the number of similar cases to handle possible regressions in
the future.
danmar
left a comment
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.
great work! It is not easy to understand this code.
|
I'm not sure how this CI error can be related to my commits. Other github actions are green. |
|
sorry I caused that CI error .. I've tried to fix it now with ecfabbc |
|
After some more thinking.. I think it makes sense to assign a bailout value. I think we want to have something like this: could you look at |
danmar
left a comment
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.
I would suggest that we drop this work path.. I changed my mind and don't think assigning a BailoutValue is bad. The assignment happens before the loop is executed.
| changedVariables.insert(varid); | ||
| auto oldValue = data.getValue(varid, nullptr, nullptr); | ||
| if (oldValue && oldValue->isUninit()) | ||
| call(data.callbacks, varToken, oldValue, &data); |
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.
We are not trying to execute the loop yet. We should call callbacks later when the loop is executed. We also do not know if the variable will still have the oldValue when this code is reached (it will if this is unconditionally executed).
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.
Then why do we call them in variable assignments here?
| // Unknown pointer, array or struct | ||
| auto arrayValue = std::dynamic_pointer_cast<ExprEngine::ArrayValue>(val); | ||
| assert(arrayValue); | ||
| data.assignValue(tok2, varid, val); |
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.
as far as I see this assignment is redundant.. it assigns the same value as we already have.
That is, you suggest to replace bailout values later, when we assign a new value? But how do we know that the loop has been executed? Do we want generate two equations after the loop, like for conditional statements? For example: int foo(int *arr) {
// memory:{arr=($2,[$1],[:]=?,[0]=bailout) a=2 b=$3}
int b = 24;
while (1) {
*arr = 0;
// memory:{arr=($2,[$1],[:]=?,[0]=0) a=2 b=24}
}
// memory:{arr=($2,[$1],[:]=?,[0]=0) b=24} constraints:{1}
// memory:{arr=($3,[$1],[:]=?,[0]=bailout,) b=24} constraints:{(1)==(0)}
}Something like this, right? |
|
I expanded a bit.. EDIT: I thought it was unfortunate that your code before the while loop had a bailout value. I guess your example is right but it's not clear where the "bailout" after the loop comes from. |
|
One more thing.. if the loop condition is |
|
It feels like we can find more and more issues :-) it's never ending. I've tried to look into merging "same" execution paths this evening to speedup analysis.. I have a work in progress will see if I can finish that. |
Maybe we should create helper functions |
Yes, I implemented them while working on condition branches for the loops right now. This will take some more time. |
The following source code:
Before this commit generates a redundant "bailout" value on the assigment:
15:12: 0:memory:{a=($2,[$1],[:]=?,[0]=bailout,[0]=42)}After this commit:
15:12: 0:memory:{a=($2,[$1],[:]=?,[0]=42)}The added tests are redundant and can't detect this error, but they increase the number of similar cases to handle possible regressions in the future.