Skip to content

Commit 630ee17

Browse files
committed
Ruby: sync-files and add allowParameterReturnInSelf()
1 parent 0bec898 commit 630ee17

File tree

6 files changed

+228
-93
lines changed

6 files changed

+228
-93
lines changed

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ abstract class Configuration extends string {
110110
/**
111111
* Holds if data may flow from some source to `sink` for this configuration.
112112
*/
113-
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
113+
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
114114

115115
/**
116116
* Holds if data may flow from some source to `sink` for this configuration.
117117
*/
118-
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
118+
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
119119

120120
/**
121121
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
244244
}
245245

246246
int getPosition() { this.isParameterOf(_, result) }
247+
248+
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
247249
}
248250

249251
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
744746
returnFlowCallableNodeCand(c, kind, config) and
745747
p.getEnclosingCallable() = c and
746748
exists(ap) and
747-
// we don't expect a parameter to return stored in itself
748-
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
749+
// we don't expect a parameter to return stored in itself, unless explicitly allowed
750+
(
751+
not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
752+
or
753+
p.allowParameterReturnInSelf()
754+
)
749755
)
750756
}
751757

@@ -1394,8 +1400,12 @@ private module Stage2 {
13941400
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
13951401
kind = ret.getKind() and
13961402
p.getPosition() = pos and
1397-
// we don't expect a parameter to return stored in itself
1398-
not kind.(ParamUpdateReturnKind).getPosition() = pos
1403+
// we don't expect a parameter to return stored in itself, unless explicitly allowed
1404+
(
1405+
not kind.(ParamUpdateReturnKind).getPosition() = pos
1406+
or
1407+
p.allowParameterReturnInSelf()
1408+
)
13991409
)
14001410
}
14011411

@@ -2083,8 +2093,12 @@ private module Stage3 {
20832093
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
20842094
kind = ret.getKind() and
20852095
p.getPosition() = pos and
2086-
// we don't expect a parameter to return stored in itself
2087-
not kind.(ParamUpdateReturnKind).getPosition() = pos
2096+
// we don't expect a parameter to return stored in itself, unless explicitly allowed
2097+
(
2098+
not kind.(ParamUpdateReturnKind).getPosition() = pos
2099+
or
2100+
p.allowParameterReturnInSelf()
2101+
)
20882102
)
20892103
}
20902104

@@ -2843,8 +2857,12 @@ private module Stage4 {
28432857
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
28442858
kind = ret.getKind() and
28452859
p.getPosition() = pos and
2846-
// we don't expect a parameter to return stored in itself
2847-
not kind.(ParamUpdateReturnKind).getPosition() = pos
2860+
// we don't expect a parameter to return stored in itself, unless explicitly allowed
2861+
(
2862+
not kind.(ParamUpdateReturnKind).getPosition() = pos
2863+
or
2864+
p.allowParameterReturnInSelf()
2865+
)
28482866
)
28492867
}
28502868

@@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
29172935

29182936
int getParameterPos() { p.isParameterOf(_, result) }
29192937

2938+
ParamNodeEx getParamNode() { result = p }
2939+
29202940
override string toString() { result = p + ": " + ap }
29212941

29222942
predicate hasLocationInfo(
@@ -3170,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
31703190
}
31713191

31723192
override string toString() {
3173-
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
3193+
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
31743194
or
31753195
result = "[" + this.toStringImpl(false)
31763196
}
@@ -3309,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
33093329
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
33103330
}
33113331

3312-
override string toString() { result = this.getNodeEx().toString() + ppAp() }
3332+
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
33133333

3314-
override string toStringWithContext() { result = this.getNodeEx().toString() + ppAp() + ppCtx() }
3334+
override string toStringWithContext() {
3335+
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
3336+
}
33153337

33163338
override predicate hasLocationInfo(
33173339
string filepath, int startline, int startcolumn, int endline, int endcolumn
@@ -3379,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
33793401

33803402
override PathNodeImpl getASuccessorImpl() {
33813403
// an intermediate step to another intermediate node
3382-
result = getSuccMid()
3404+
result = this.getSuccMid()
33833405
or
33843406
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
33853407
exists(PathNodeMid mid, PathNodeSink sink |
3386-
mid = getSuccMid() and
3408+
mid = this.getSuccMid() and
33873409
mid.getNodeEx() = sink.getNodeEx() and
33883410
mid.getAp() instanceof AccessPathNil and
33893411
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
@@ -3460,7 +3482,7 @@ private predicate pathStep(
34603482
exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
34613483
sc = mid.getSummaryCtx()
34623484
or
3463-
pathIntoCallable(mid, node, _, cc, sc, _) and ap = mid.getAp()
3485+
pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
34643486
or
34653487
pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
34663488
or
@@ -3537,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
35373559
*/
35383560
pragma[noinline]
35393561
private predicate pathIntoArg(
3540-
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
3562+
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
3563+
Configuration config
35413564
) {
35423565
exists(ArgNode arg |
35433566
arg = mid.getNodeEx().asNode() and
35443567
cc = mid.getCallContext() and
35453568
arg.argumentOf(call, i) and
35463569
ap = mid.getAp() and
3547-
apa = ap.getApprox()
3570+
apa = ap.getApprox() and
3571+
config = mid.getConfiguration()
35483572
)
35493573
}
35503574

@@ -3561,12 +3585,14 @@ private predicate parameterCand(
35613585
pragma[nomagic]
35623586
private predicate pathIntoCallable0(
35633587
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
3564-
AccessPath ap
3588+
AccessPath ap, Configuration config
35653589
) {
35663590
exists(AccessPathApprox apa |
3567-
pathIntoArg(mid, i, outercc, call, ap, apa) and
3591+
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
3592+
pragma[only_bind_into](config)) and
35683593
callable = resolveCall(call, outercc) and
3569-
parameterCand(callable, any(int j | j <= i and j >= i), apa, mid.getConfiguration())
3594+
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
3595+
pragma[only_bind_into](config))
35703596
)
35713597
}
35723598

@@ -3575,12 +3601,13 @@ private predicate pathIntoCallable0(
35753601
* before and after entering the callable are `outercc` and `innercc`,
35763602
* respectively.
35773603
*/
3604+
pragma[nomagic]
35783605
private predicate pathIntoCallable(
35793606
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
3580-
DataFlowCall call
3607+
DataFlowCall call, Configuration config
35813608
) {
35823609
exists(int i, DataFlowCallable callable, AccessPath ap |
3583-
pathIntoCallable0(mid, callable, i, outercc, call, ap) and
3610+
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
35843611
p.isParameterOf(callable, i) and
35853612
(
35863613
sc = TSummaryCtxSome(p, ap)
@@ -3610,18 +3637,23 @@ private predicate paramFlowsThrough(
36103637
ap = mid.getAp() and
36113638
apa = ap.getApprox() and
36123639
pos = sc.getParameterPos() and
3613-
not kind.(ParamUpdateReturnKind).getPosition() = pos
3640+
// we don't expect a parameter to return stored in itself, unless explicitly allowed
3641+
(
3642+
not kind.(ParamUpdateReturnKind).getPosition() = pos
3643+
or
3644+
sc.getParamNode().allowParameterReturnInSelf()
3645+
)
36143646
)
36153647
}
36163648

36173649
pragma[nomagic]
36183650
private predicate pathThroughCallable0(
36193651
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
3620-
AccessPathApprox apa
3652+
AccessPathApprox apa, Configuration config
36213653
) {
36223654
exists(CallContext innercc, SummaryCtx sc |
3623-
pathIntoCallable(mid, _, cc, innercc, sc, call) and
3624-
paramFlowsThrough(kind, innercc, sc, ap, apa, unbindConf(mid.getConfiguration()))
3655+
pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
3656+
paramFlowsThrough(kind, innercc, sc, ap, apa, config)
36253657
)
36263658
}
36273659

@@ -3631,9 +3663,9 @@ private predicate pathThroughCallable0(
36313663
*/
36323664
pragma[noinline]
36333665
private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
3634-
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
3635-
pathThroughCallable0(call, mid, kind, cc, ap, apa) and
3636-
out = getAnOutNodeFlow(kind, call, apa, unbindConf(mid.getConfiguration()))
3666+
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
3667+
pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
3668+
out = getAnOutNodeFlow(kind, call, apa, config)
36373669
)
36383670
}
36393671

@@ -3647,10 +3679,11 @@ private module Subpaths {
36473679
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
36483680
NodeEx out, AccessPath apout
36493681
) {
3650-
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
3651-
pathIntoCallable(arg, par, _, innercc, sc, _) and
3652-
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
3653-
unbindConf(arg.getConfiguration()))
3682+
exists(Configuration config |
3683+
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
3684+
pathIntoCallable(arg, par, _, innercc, sc, _, config) and
3685+
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
3686+
)
36543687
}
36553688

36563689
/**

0 commit comments

Comments
 (0)