-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Go: Make models-as-data source models for variadic parameters work #18275
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
Changes from all commits
e13c4b7
3f7c37e
26b5207
b58e6eb
3a3e053
e9dcd69
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 |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| category: minorAnalysis | ||
| --- | ||
| * Source models defined using models-as-data now work for variadic parameters. |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -27,11 +27,21 @@ predicate localExprTaint(Expr src, Expr sink) { | |||||||||||||
| * Holds if taint can flow in one local step from `src` to `sink`. | ||||||||||||||
| */ | ||||||||||||||
| predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) { | ||||||||||||||
| DataFlow::localFlowStep(src, sink) or | ||||||||||||||
| localAdditionalTaintStep(src, sink, _) or | ||||||||||||||
| DataFlow::localFlowStep(src, sink) | ||||||||||||||
| or | ||||||||||||||
| localAdditionalTaintStep(src, sink, _) | ||||||||||||||
| or | ||||||||||||||
| // Simple flow through library code is included in the exposed local | ||||||||||||||
| // step relation, even though flow is technically inter-procedural | ||||||||||||||
| FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(src, sink, _) | ||||||||||||||
| or | ||||||||||||||
| // Treat container flow as taint for the local taint flow relation | ||||||||||||||
| exists(DataFlow::Content c | DataFlowPrivate::containerContent(c) | | ||||||||||||||
| DataFlowPrivate::readStep(src, c, sink) or | ||||||||||||||
| DataFlowPrivate::storeStep(src, c, sink) or | ||||||||||||||
| FlowSummaryImpl::Private::Steps::summaryGetterStep(src, c, sink, _) or | ||||||||||||||
| FlowSummaryImpl::Private::Steps::summarySetterStep(src, c, sink, _) | ||||||||||||||
|
Comment on lines
+40
to
+43
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. It shouldn't include store steps, just the reads.
Suggested change
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. Oh wait, I guess this isn't the relation that gets passed to global data flow? Then it's fine. |
||||||||||||||
| ) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| private Type getElementType(Type containerType) { | ||||||||||||||
|
|
@@ -88,12 +98,18 @@ class AdditionalTaintStep extends Unit { | |||||||||||||
| */ | ||||||||||||||
| predicate localAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ, string model) { | ||||||||||||||
| ( | ||||||||||||||
| referenceStep(pred, succ) or | ||||||||||||||
| elementWriteStep(pred, succ) or | ||||||||||||||
| fieldReadStep(pred, succ) or | ||||||||||||||
| elementStep(pred, succ) or | ||||||||||||||
| tupleStep(pred, succ) or | ||||||||||||||
| stringConcatStep(pred, succ) or | ||||||||||||||
| referenceStep(pred, succ) | ||||||||||||||
| or | ||||||||||||||
| elementWriteStep(pred, succ) | ||||||||||||||
|
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. What's this step doing here? I realise it isn't added in this PR, but it looks wrong: store steps shouldn't be taint steps.
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. The QLDoc says "Holds if there is an assignment of the form
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. I can see that you could take a different approach, where only the array element is tainted, and then if the array is used without an array access then hopefully there is an implicit read step that will mean that the whole array is tainted. I could try removing this line and see what effect it has. But I think that shouldn't be part of this PR.
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.
I think that should be attempted, yes.
Agree. |
||||||||||||||
| or | ||||||||||||||
| fieldReadStep(pred, succ) | ||||||||||||||
| or | ||||||||||||||
| elementStep(pred, succ) | ||||||||||||||
| or | ||||||||||||||
| tupleStep(pred, succ) | ||||||||||||||
| or | ||||||||||||||
| stringConcatStep(pred, succ) | ||||||||||||||
| or | ||||||||||||||
| sliceStep(pred, succ) | ||||||||||||||
| ) and | ||||||||||||||
| model = "" | ||||||||||||||
|
|
@@ -163,6 +179,12 @@ predicate elementStep(DataFlow::Node pred, DataFlow::Node succ) { | |||||||||||||
| // only step into the value, not the index | ||||||||||||||
| succ.asInstruction() = IR::extractTupleElement(nextEntry, 1) | ||||||||||||||
| ) | ||||||||||||||
| or | ||||||||||||||
| exists(DataFlow::ImplicitVarargsSlice ivs | | ||||||||||||||
| pred.(DataFlow::PostUpdateNode).getPreUpdateNode() = ivs and | ||||||||||||||
| succ.(DataFlow::PostUpdateNode).getPreUpdateNode() = | ||||||||||||||
| ivs.getCallNode().getAnImplicitVarargsArgument() | ||||||||||||||
| ) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /** Holds if taint flows from `pred` to `succ` via an extract tuple operation. */ | ||||||||||||||
|
|
||||||||||||||
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 is this defined here and not in localAdditionalTaintStep?
Uh oh!
There was an error while loading. Please reload this page.
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.
In increasing order of how good an answer it is:
(a) It's what they do in java.
(b) I copied it before I realised that it wouldn't affect global taint flow at all.
(c) I think it is helpful. Six months ago I tried to convert old-style models for variadic functions to MaD. One of the sticking points was "Some barrier guard definitions use localTaintStep to detect taint flow, but it doesn't work flow through an implicit varargs slice." With this added (for container reads and container writes) we get that
localTaintincludes flow into and out of arrays, including through implicit varargs slices.Uh oh!
There was an error while loading. Please reload this page.
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.
OK, I think I see: you want both reads and stores to appear according to the handy utility
localTaintStep, but only reads to be contributed to the additional-taint-step for global dataflow's purposes?If so, suggest three things:
localAdditionalTaintStepis already included -- instead just comment that the read steps are already taken care ofUh oh!
There was an error while loading. Please reload this page.
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.
summaryGetterStepsaysNote also that something related is included in
readStep(andstoreStep).2. Done.
3. I'm not exactly sure what to say. I've put "Treat container read steps as taint for global taint flow." @aschackmull can you suggest a more detailed explanation?
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 the qldoc that Owen referenced says, the summary-getter step should not be passed to global data flow in any form (neither as a read step nor as a taint step). To elaborate: Container read steps should be passed to data flow as taint steps. But read steps and summary-getter steps are separate things: A read step is atomic, whereas a summary-getter step represents a flow path through a callable with a nested read step, such that the entire thing can be summarized and treated as a read step in those contexts that aren't capable of doing such summarization. And data flow notably is perfectly capable of such summarization, so it only needs to know about the atomic read steps.