Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,31 @@ class Node = DataFlowPublic::Node;

class TypeTrackingNode = DataFlowPublic::LocalSourceNode;

/** Holds if there is a simple local flow step from `nodeFrom` to `nodeTo` */
predicate simpleLocalFlowStep = DataFlowPrivate::localFlowStepTypeTracker/2;

/**
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
predicate jumpStep = DataFlowPrivate::jumpStep/2;

/** Holds if there is a level step from `pred` to `succ`. */
predicate levelStep(Node pred, Node succ) { none() }
/**
* Holds if there is a summarized local flow step from `nodeFrom` to `nodeTo`,
* because there is direct flow from a parameter to a return. That is, summarized
* steps are not applied recursively.
*/
pragma[nomagic]
private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) {
exists(DataFlowPublic::ParameterNode param, DataFlowPrivate::ReturningNode returnNode |
DataFlowPrivate::LocalFlow::getParameterDefNode(param.getParameter())
.(TypeTrackingNode)
.flowsTo(returnNode) and
callStep(nodeTo.asExpr(), nodeFrom, param)
)
}

/** Holds if there is a level step from `nodeFrom` to `nodeTo`. */
predicate levelStep(Node nodeFrom, Node nodeTo) { summarizedLocalStep(nodeFrom, nodeTo) }

/**
* Gets the name of a possible piece of content. This will usually include things like
Expand Down Expand Up @@ -48,6 +67,13 @@ private predicate viableParam(
)
}

private predicate callStep(ExprNodes::CallCfgNode call, Node nodeFrom, Node nodeTo) {
exists(DataFlowDispatch::ParameterPosition pos |
argumentPositionMatch(call, nodeFrom, pos) and
viableParam(call, nodeTo, pos)
)
}

/**
* Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call.
*
Expand All @@ -56,10 +82,7 @@ private predicate viableParam(
* methods is done using API graphs (which uses type tracking).
*/
predicate callStep(Node nodeFrom, Node nodeTo) {
exists(ExprNodes::CallCfgNode call, DataFlowDispatch::ParameterPosition pos |
argumentPositionMatch(call, nodeFrom, pos) and
viableParam(call, nodeTo, pos)
)
callStep(_, nodeFrom, nodeTo)
or
// In normal data-flow, this will be a local flow step. But for type tracking
// we model it as a call step, in order to avoid computing a potential
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ track
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps with content field | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:14:17:14:23 | "hello" |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps with content field | type_tracker.rb:14:5:14:7 | [post] var |
Expand All @@ -72,19 +73,29 @@ trackEnd
| type_tracker.rb:2:5:5:7 | return return in field= | type_tracker.rb:2:5:5:7 | return return in field= |
| type_tracker.rb:2:5:5:7 | return return in field= | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:2:5:5:7 | self (field=) |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:3:9:3:23 | self |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:3:14:3:17 | self |
| type_tracker.rb:2:5:5:7 | self (field=) | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:2:5:5:7 | self in field= |
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:3:9:3:23 | self |
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:3:14:3:17 | self |
| type_tracker.rb:2:5:5:7 | self in field= | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:5:5:7 | return return in field= |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:4:9:4:20 | ... = ... |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:4:9:4:20 | ... = ... |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:4:18:4:20 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:4:18:4:20 | val |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:3:9:3:23 | [post] self | type_tracker.rb:3:9:3:23 | [post] self |
| type_tracker.rb:3:9:3:23 | [post] self | type_tracker.rb:3:14:3:17 | self |
| type_tracker.rb:3:9:3:23 | [post] self | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:3:9:3:23 | call to puts | type_tracker.rb:3:9:3:23 | call to puts |
| type_tracker.rb:3:9:3:23 | self | type_tracker.rb:3:9:3:23 | self |
| type_tracker.rb:3:9:3:23 | self | type_tracker.rb:3:14:3:17 | self |
| type_tracker.rb:3:9:3:23 | self | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:3:14:3:17 | [post] self | type_tracker.rb:3:14:3:17 | [post] self |
| type_tracker.rb:3:14:3:17 | self | type_tracker.rb:3:14:3:17 | self |
Expand All @@ -93,9 +104,11 @@ trackEnd
| type_tracker.rb:3:14:3:23 | call to field | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:4:9:4:14 | @field | type_tracker.rb:4:9:4:14 | @field |
| type_tracker.rb:4:18:4:20 | val | type_tracker.rb:2:5:5:7 | return return in field= |
| type_tracker.rb:4:18:4:20 | val | type_tracker.rb:4:9:4:20 | ... = ... |
| type_tracker.rb:4:18:4:20 | val | type_tracker.rb:4:18:4:20 | val |
| type_tracker.rb:4:18:4:20 | val | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:7:5:9:7 | &block | type_tracker.rb:7:5:9:7 | &block |
| type_tracker.rb:7:5:9:7 | field | type_tracker.rb:1:1:10:3 | Container |
| type_tracker.rb:7:5:9:7 | field | type_tracker.rb:7:5:9:7 | field |
| type_tracker.rb:7:5:9:7 | return return in field | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:7:5:9:7 | return return in field | type_tracker.rb:7:5:9:7 | return return in field |
Expand All @@ -109,20 +122,36 @@ trackEnd
| type_tracker.rb:12:1:16:3 | m | type_tracker.rb:12:1:16:3 | m |
| type_tracker.rb:12:1:16:3 | return return in m | type_tracker.rb:12:1:16:3 | return return in m |
| type_tracker.rb:12:1:16:3 | self (m) | type_tracker.rb:12:1:16:3 | self (m) |
| type_tracker.rb:12:1:16:3 | self (m) | type_tracker.rb:15:5:15:18 | self |
| type_tracker.rb:12:1:16:3 | self in m | type_tracker.rb:12:1:16:3 | self in m |
| type_tracker.rb:12:1:16:3 | self in m | type_tracker.rb:15:5:15:18 | self |
| type_tracker.rb:13:5:13:7 | var | type_tracker.rb:13:5:13:7 | var |
| type_tracker.rb:13:11:13:19 | Container | type_tracker.rb:13:11:13:19 | Container |
| type_tracker.rb:13:11:13:19 | [post] Container | type_tracker.rb:13:11:13:19 | [post] Container |
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:2:5:5:7 | self in field= |
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:3:9:3:23 | self |
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:3:14:3:17 | self |
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:13:5:13:23 | ... = ... |
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:13:5:13:23 | ... = ... |
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:13:11:13:23 | call to new |
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:14:5:14:7 | var |
| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:15:10:15:12 | var |
| type_tracker.rb:14:5:14:7 | [post] var | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:14:5:14:7 | [post] var | type_tracker.rb:14:5:14:7 | [post] var |
| type_tracker.rb:14:5:14:7 | [post] var | type_tracker.rb:15:10:15:12 | var |
| type_tracker.rb:14:5:14:13 | [post] ... = ... | type_tracker.rb:14:5:14:13 | [post] ... = ... |
| type_tracker.rb:14:5:14:13 | __synth__0 | type_tracker.rb:14:5:14:13 | __synth__0 |
| type_tracker.rb:14:5:14:13 | call to field= | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:4:9:4:20 | ... = ... |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:4:18:4:20 | val |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:5:14:13 | ... = ... |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:5:14:13 | ... = ... |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:5:14:13 | __synth__0 |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:5:14:23 | ... |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:17:14:23 | "hello" |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:15:5:15:18 | [post] self | type_tracker.rb:15:5:15:18 | [post] self |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ query predicate track(LocalSourceNode src, TypeTracker t, LocalSourceNode dst) {
exists(TypeTracker t2, LocalSourceNode mid | track(src, t2, mid) and dst = mid.track(t2, t))
}

query predicate trackEnd(LocalSourceNode src, LocalSourceNode dst) {
track(src, TypeTracker::end(), dst)
query predicate trackEnd(LocalSourceNode src, DataFlow::Node dst) {
exists(LocalSourceNode end |
track(src, TypeTracker::end(), end) and
end.flowsTo(dst)
)
}