-
Notifications
You must be signed in to change notification settings - Fork 1.8k
C++: alias and side effect info for pure functions #1566
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
C++: alias and side effect info for pure functions #1566
Conversation
| } | ||
|
|
||
| override predicate parameterEscapesOnlyViaReturn(int i) { | ||
| none() |
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.
The strstr family of functions return a pointer that's derived from (and may be equal to) their first parameter.
| or name = "strnlen" | ||
| or name = "strrchr" | ||
| or name = "strspn" | ||
| or name = "strstr" |
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.
By strstr family I meant also strcasestr, strchr, strchrnul, and strrchr. Instead of enumerating them, you can consider matching them by signature: it's all the functions on this list that return a pointer type.
jbj
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.
Sorry for torturing this PR so much. I've just been involved in fixing many hard-to-debug bugs that were caused by inaccurate modelling of standard-library functions. It looks like we'll be modelling many more of those functions in Q3, so I'd like the foundation to be robust.
| ) and | ||
| ( | ||
| output.isOutReturnValue() or | ||
| output.isOutReturnPointer() |
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 think the previous version of this was right:
... and
(
(
output.isOutReturnPointer() and
getUnspecifiedType() instanceof PointerType
) or
output.isOutReturnValue()
)
The new version claims that taint flows to the return pointer even if the return value is int.
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.
Fixed
|
|
||
| override predicate parameterEscapesOnlyViaReturn(int i) { | ||
| i = 0 and | ||
| getType().getUnspecifiedType() instanceof PointerType |
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.
Didn't we get rid of getType().getUnspecifiedType() chains?
| not ( | ||
| i = 0 and | ||
| getType().getUnspecifiedType() instanceof PointerType | ||
| ) |
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.
Can not ( ... ) be simplified to not parameterEscapesOnlyViaReturn(i)? That should make it more robust against future changes. Hard-coding i = 0 only once makes me only half as nervous about it.
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.
Done.
| class PureFunction extends TaintFunction, SideEffectFunction { | ||
| PureFunction() { | ||
| exists(string name | | ||
| hasName(name) and |
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 know it's independent of this PR, but this use of hasName has bitten us several times, and I don't want it to bite us again. It's just very likely that class member functions have short names like abs. See, for example, #1023.
Please switch to hasGlobalName here and in PureStrFunction. If you want to make sure that std::abs is also matched, then it's time to implement the hasGlobalOrStdName predicate we've been talking about.
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'll switch to hasGlobalName for now, and do hasGlobalOrStdName as a separate PR (since it should involve a pass through most of the library)
| override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { | ||
| exists (ParameterIndex i | | ||
| input.isInParameter(i) | ||
| ) and |
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.
If there's a function in the snapshot with 20 parameters, then this predicate claims that parameter 19 of abs flows to its return value. That seems wasteful and confusing.
I'd much prefer that we only define taint flow for parameters that actually exist. The same issue is in PureStrFunction.
To make this easier to detect in the future, we could make ParameterIndex private and put a bindingset annotation on isInParameter etc. But that's probably not for this PR.
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've narrowed it to only report parameters that actually exist
| int PureFunctions(char *str1, char *str2, int x) { | ||
| int ret = strcmp(str1, str2); | ||
| ret += abs(x); | ||
| return ret; |
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.
You wrote in #1542 (comment) that this PR was about the side effects of strlen, so shouldn't that be included in the test?
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.
Added.
No description provided.