-
Notifications
You must be signed in to change notification settings - Fork 2k
C++: Fix indirect taint #14571
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++: Fix indirect taint #14571
Changes from all commits
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 |
|---|---|---|
|
|
@@ -32,25 +32,34 @@ DataFlow::Node callInput(CallInstruction call, FunctionInput input) { | |
| } | ||
|
|
||
| /** | ||
| * Gets the instruction that holds the `output` for `call`. | ||
| * Gets the node that represents the output of `call` with kind `output` at | ||
| * indirection index `indirectionIndex`. | ||
| */ | ||
| Node callOutput(CallInstruction call, FunctionOutput output) { | ||
| private Node callOutputWithIndirectionIndex( | ||
| CallInstruction call, FunctionOutput output, int indirectionIndex | ||
| ) { | ||
| // The return value | ||
| simpleOutNode(result, call) and | ||
| output.isReturnValue() | ||
| output.isReturnValue() and | ||
| indirectionIndex = 0 | ||
| or | ||
| // The side effect of a call on the value pointed to by an argument or qualifier | ||
| exists(int index, int indirectionIndex | | ||
| exists(int index | | ||
| result.(IndirectArgumentOutNode).getArgumentIndex() = index and | ||
| result.(IndirectArgumentOutNode).getIndirectionIndex() = indirectionIndex and | ||
| result.(IndirectArgumentOutNode).getIndirectionIndex() = indirectionIndex - 1 and | ||
| result.(IndirectArgumentOutNode).getCallInstruction() = call and | ||
| output.isParameterDerefOrQualifierObject(index, indirectionIndex) | ||
| output.isParameterDerefOrQualifierObject(index, indirectionIndex - 1) | ||
| ) | ||
| or | ||
| exists(int ind | | ||
| result = getIndirectReturnOutNode(call, ind) and | ||
| output.isReturnValueDeref(ind) | ||
| ) | ||
| result = getIndirectReturnOutNode(call, indirectionIndex) and | ||
| output.isReturnValueDeref(indirectionIndex) | ||
| } | ||
|
|
||
| /** | ||
| * Gets the instruction that holds the `output` for `call`. | ||
| */ | ||
| Node callOutput(CallInstruction call, FunctionOutput output) { | ||
| result = callOutputWithIndirectionIndex(call, output, _) | ||
| } | ||
|
|
||
| DataFlow::Node callInput(CallInstruction call, FunctionInput input, int d) { | ||
|
|
@@ -76,19 +85,15 @@ private IndirectReturnOutNode getIndirectReturnOutNode(CallInstruction call, int | |
| */ | ||
| bindingset[d] | ||
| Node callOutput(CallInstruction call, FunctionOutput output, int d) { | ||
| exists(DataFlow::Node n | n = callOutput(call, output) and d > 0 | | ||
| exists(DataFlow::Node n, int indirectionIndex | | ||
| n = callOutputWithIndirectionIndex(call, output, indirectionIndex) and d > 0 | ||
| | | ||
| // The return value | ||
| result = getIndirectReturnOutNode(n.asInstruction(), d) | ||
| result = callOutputWithIndirectionIndex(call, output, indirectionIndex + d) | ||
| or | ||
| // If there isn't an indirect out node for the call with indirection `d` then | ||
| // we conflate this with the underlying `CallInstruction`. | ||
| not exists(getIndirectReturnOutNode(call, d)) and | ||
| not exists(getIndirectReturnOutNode(call, indirectionIndex + d)) and | ||
| n = result | ||
| or | ||
| // The side effect of a call on the value pointed to by an argument or qualifier | ||
| exists(Operand operand, int indirectionIndex | | ||
| Ssa::outNodeHasAddressAndIndex(n, operand, indirectionIndex) and | ||
| Ssa::outNodeHasAddressAndIndex(result, operand, indirectionIndex + d) | ||
| ) | ||
|
Comment on lines
-88
to
-92
Contributor
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. Why is this no longer needed?
Contributor
Author
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 is now handled by the n = callOutputWithIndirectionIndex(call, output, indirectionIndex) and
result = callOutputWithIndirectionIndex(call, output, indirectionIndex + d)in Does that make sense?
Contributor
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. Partially. My main problem is, that it's rather hard for me to map the old code on the new code, because it uses different predicates.
Contributor
Author
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. Yeah, it's not an easy commit to review as it's not a clear line-for-line mapping 😢. The main point of the commit is to get an indirection index out of |
||
| ) | ||
| } | ||
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.
Why are the subtractions needed here?
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.
Yeah, I'm not quite happy with that. The indirection index of
IndirectArgumentOutNodeis defined to be[1 .. n](up to some number of indirections), but in the caller of this predicate (callOutput/3) thenot exists(getIndirectReturnOutNode(call, indirectionIndex + d))predicate expects the indirection index to be defined[0 .. n - 1](because that's the indirection index range ofIndirectReturnOutNodesince it can be both a "direct return" with indirection index being 0, or an indirect return with indirection index being >= 1).So while it's very difficult to reason about this indirection index, it's very easy to see when they're wrong since any other offsets added here breaks some of our tests 😂. I'd like to clean up this so that we don't need these subtractions at some point, but I'd rather not add too much more onto this PR.