Skip to content

Commit d3a1d0a

Browse files
authored
Merge pull request #294 from github/bump-codeql
Bump `codeql` submodule
2 parents 12723f0 + 9e67382 commit d3a1d0a

File tree

9 files changed

+153
-37
lines changed

9 files changed

+153
-37
lines changed

codeql

Submodule codeql updated 1187 files

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

Lines changed: 123 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -923,28 +923,29 @@ private module Stage2 {
923923

924924
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
925925

926-
class Cc = boolean;
927-
928-
class CcCall extends Cc {
929-
CcCall() { this = true }
926+
class Cc = CallContext;
930927

931-
/** Holds if this call context may be `call`. */
932-
predicate matchesCall(DataFlowCall call) { any() }
933-
}
928+
class CcCall = CallContextCall;
934929

935-
class CcNoCall extends Cc {
936-
CcNoCall() { this = false }
937-
}
930+
class CcNoCall = CallContextNoCall;
938931

939-
Cc ccNone() { result = false }
932+
Cc ccNone() { result instanceof CallContextAny }
940933

941934
private class LocalCc = Unit;
942935

943936
bindingset[call, c, outercc]
944-
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
937+
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
938+
checkCallContextCall(outercc, call, c) and
939+
if recordDataFlowCallSiteDispatch(call, c)
940+
then result = TSpecificCall(call)
941+
else result = TSomeCall()
942+
}
945943

946944
bindingset[call, c, innercc]
947-
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
945+
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
946+
checkCallContextReturn(innercc, c, call) and
947+
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
948+
}
948949

949950
bindingset[node, cc, config]
950951
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1172,7 +1173,8 @@ private module Stage2 {
11721173
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
11731174
pragma[only_bind_into](config)) and
11741175
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
1175-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
1176+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
1177+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
11761178
pragma[only_bind_into](config))
11771179
)
11781180
}
@@ -1860,7 +1862,8 @@ private module Stage3 {
18601862
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
18611863
pragma[only_bind_into](config)) and
18621864
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
1863-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
1865+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
1866+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
18641867
pragma[only_bind_into](config))
18651868
)
18661869
}
@@ -2117,7 +2120,7 @@ private module Stage3 {
21172120
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
21182121
exists(AccessPathFront apf |
21192122
Stage3::revFlow(node, true, _, apf, config) and
2120-
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
2123+
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
21212124
)
21222125
}
21232126

@@ -2618,7 +2621,8 @@ private module Stage4 {
26182621
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
26192622
pragma[only_bind_into](config)) and
26202623
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
2621-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
2624+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
2625+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
26222626
pragma[only_bind_into](config))
26232627
)
26242628
}
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
32583262
/** Gets the associated configuration. */
32593263
Configuration getConfiguration() { none() }
32603264

3261-
private predicate isHidden() {
3262-
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
3263-
not this.isSource() and
3264-
not this instanceof PathNodeSink
3265-
or
3266-
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
3267-
}
3268-
32693265
private PathNode getASuccessorIfHidden() {
3270-
this.isHidden() and
3266+
this.(PathNodeImpl).isHidden() and
32713267
result = this.(PathNodeImpl).getASuccessorImpl()
32723268
}
32733269

32743270
/** Gets a successor of this node, if any. */
32753271
final PathNode getASuccessor() {
32763272
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
3277-
not this.isHidden() and
3278-
not result.isHidden()
3273+
not this.(PathNodeImpl).isHidden() and
3274+
not result.(PathNodeImpl).isHidden()
32793275
}
32803276

32813277
/** Holds if this node is a source. */
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
32873283

32883284
abstract NodeEx getNodeEx();
32893285

3286+
predicate isHidden() {
3287+
hiddenNode(this.getNodeEx().asNode()) and
3288+
not this.isSource() and
3289+
not this instanceof PathNodeSink
3290+
or
3291+
this.getNodeEx() instanceof TNodeImplicitRead
3292+
}
3293+
32903294
private string ppAp() {
32913295
this instanceof PathNodeSink and result = ""
32923296
or
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
33133317
}
33143318

33153319
/** Holds if `n` can reach a sink. */
3316-
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
3320+
private predicate directReach(PathNode n) {
3321+
n instanceof PathNodeSink or directReach(n.getASuccessor())
3322+
}
33173323

3318-
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
3319-
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
3324+
/** Holds if `n` can reach a sink or is used in a subpath. */
3325+
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
3326+
3327+
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
3328+
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
33203329

33213330
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
33223331

@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
33253334
*/
33263335
module PathGraph {
33273336
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
3328-
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
3337+
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
33293338

33303339
/** Holds if `n` is a node in the graph of data flow path explanations. */
33313340
query predicate nodes(PathNode n, string key, string val) {
33323341
reach(n) and key = "semmle.label" and val = n.toString()
33333342
}
3343+
3344+
query predicate subpaths = Subpaths::subpaths/4;
33343345
}
33353346

33363347
/**
@@ -3622,6 +3633,86 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
36223633
)
36233634
}
36243635

3636+
private module Subpaths {
3637+
/**
3638+
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
3639+
* `kind`, `sc`, `apout`, and `innercc`.
3640+
*/
3641+
pragma[nomagic]
3642+
private predicate subpaths01(
3643+
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
3644+
NodeEx out, AccessPath apout
3645+
) {
3646+
pathThroughCallable(arg, out, _, apout) and
3647+
pathIntoCallable(arg, par, _, innercc, sc, _) and
3648+
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
3649+
}
3650+
3651+
/**
3652+
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
3653+
* `kind`, `sc`, `apout`, and `innercc`.
3654+
*/
3655+
pragma[nomagic]
3656+
private predicate subpaths02(
3657+
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
3658+
NodeEx out, AccessPath apout
3659+
) {
3660+
subpaths01(arg, par, sc, innercc, kind, out, apout) and
3661+
out.asNode() = kind.getAnOutNode(_)
3662+
}
3663+
3664+
pragma[nomagic]
3665+
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
3666+
3667+
/**
3668+
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
3669+
*/
3670+
pragma[nomagic]
3671+
private predicate subpaths03(
3672+
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
3673+
) {
3674+
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
3675+
subpaths02(arg, par, sc, innercc, kind, out, apout) and
3676+
ret.getNodeEx() = retnode and
3677+
kind = retnode.getKind() and
3678+
innercc = ret.getCallContext() and
3679+
sc = ret.getSummaryCtx() and
3680+
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
3681+
apout = ret.getAp() and
3682+
not ret.isHidden()
3683+
)
3684+
}
3685+
3686+
/**
3687+
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
3688+
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
3689+
* `ret -> out` is summarized as the edge `arg -> out`.
3690+
*/
3691+
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
3692+
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
3693+
arg.getASuccessor() = par and
3694+
arg.getASuccessor() = out and
3695+
subpaths03(arg, p, ret, o, apout) and
3696+
par.getNodeEx() = p and
3697+
out.getNodeEx() = o and
3698+
out.getAp() = apout
3699+
)
3700+
}
3701+
3702+
/**
3703+
* Holds if `n` can reach a return node in a summarized subpath.
3704+
*/
3705+
predicate retReach(PathNode n) {
3706+
subpaths(_, _, n, _)
3707+
or
3708+
exists(PathNode mid |
3709+
retReach(mid) and
3710+
n.getASuccessor() = mid and
3711+
not subpaths(_, mid, _, _)
3712+
)
3713+
}
3714+
}
3715+
36253716
/**
36263717
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
36273718
*

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -786,13 +786,18 @@ private module Cached {
786786
}
787787

788788
/**
789-
* Holds if the call context `call` either improves virtual dispatch in
790-
* `callable` or if it allows us to prune unreachable nodes in `callable`.
789+
* Holds if the call context `call` improves virtual dispatch in `callable`.
791790
*/
792791
cached
793-
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
792+
predicate recordDataFlowCallSiteDispatch(DataFlowCall call, DataFlowCallable callable) {
794793
reducedViableImplInCallContext(_, callable, call)
795-
or
794+
}
795+
796+
/**
797+
* Holds if the call context `call` allows us to prune unreachable nodes in `callable`.
798+
*/
799+
cached
800+
predicate recordDataFlowCallSiteUnreachable(DataFlowCall call, DataFlowCallable callable) {
796801
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
797802
}
798803

@@ -846,6 +851,15 @@ private module Cached {
846851
TAccessPathFrontSome(AccessPathFront apf)
847852
}
848853

854+
/**
855+
* Holds if the call context `call` either improves virtual dispatch in
856+
* `callable` or if it allows us to prune unreachable nodes in `callable`.
857+
*/
858+
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
859+
recordDataFlowCallSiteDispatch(call, callable) or
860+
recordDataFlowCallSiteUnreachable(call, callable)
861+
}
862+
849863
/**
850864
* A `Node` at which a cast can occur such that the type should be checked.
851865
*/

ql/test/library-tests/dataflow/call-sensitivity/call-sensitivity.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ nodes
2828
| call_sensitivity.rb:36:23:36:23 | x : | semmle.label | x : |
2929
| call_sensitivity.rb:36:31:36:31 | x | semmle.label | x |
3030
| call_sensitivity.rb:37:25:37:31 | "taint" : | semmle.label | "taint" : |
31+
subpaths
3132
#select
3233
| call_sensitivity.rb:5:6:5:12 | "taint" | call_sensitivity.rb:5:6:5:12 | "taint" | call_sensitivity.rb:5:6:5:12 | "taint" | $@ | call_sensitivity.rb:5:6:5:12 | "taint" | "taint" |
3334
| call_sensitivity.rb:15:28:15:28 | x | call_sensitivity.rb:15:9:15:15 | "taint" : | call_sensitivity.rb:15:28:15:28 | x | $@ | call_sensitivity.rb:15:9:15:15 | "taint" : | "taint" : |

ql/test/query-tests/security/cwe-089/SqlInjection.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ nodes
3838
| ActiveRecordInjection.rb:68:21:68:33 | ... + ... | semmle.label | ... + ... |
3939
| ActiveRecordInjection.rb:101:22:101:27 | call to params : | semmle.label | call to params : |
4040
| ActiveRecordInjection.rb:101:22:101:45 | ...[...] : | semmle.label | ...[...] : |
41+
subpaths
4142
#select
4243
| ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | ActiveRecordInjection.rb:56:23:56:28 | call to params : | ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | This SQL query depends on $@. | ActiveRecordInjection.rb:56:23:56:28 | call to params | a user-provided value |
4344
| ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | ActiveRecordInjection.rb:56:38:56:43 | call to params : | ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | This SQL query depends on $@. | ActiveRecordInjection.rb:56:38:56:43 | call to params | a user-provided value |

ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ nodes
4040
| PolynomialReDoS.rb:30:5:30:5 | b | semmle.label | b |
4141
| PolynomialReDoS.rb:31:9:31:14 | call to params : | semmle.label | call to params : |
4242
| PolynomialReDoS.rb:32:5:32:5 | c | semmle.label | c |
43+
subpaths
4344
#select
4445
| PolynomialReDoS.rb:10:5:10:17 | ... =~ ... | PolynomialReDoS.rb:4:12:4:17 | call to params : | PolynomialReDoS.rb:10:5:10:8 | name | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:4:12:4:17 | call to params | a user-provided value |
4546
| PolynomialReDoS.rb:11:5:11:17 | ... !~ ... | PolynomialReDoS.rb:4:12:4:17 | call to params : | PolynomialReDoS.rb:11:5:11:8 | name | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:4:12:4:17 | call to params | a user-provided value |

ql/test/query-tests/security/cwe-601/UrlRedirect.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ edges
33
| UrlRedirect.rb:14:17:14:22 | call to params : | UrlRedirect.rb:14:17:14:43 | call to fetch |
44
| UrlRedirect.rb:19:17:19:22 | call to params : | UrlRedirect.rb:19:17:19:37 | call to to_unsafe_hash |
55
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:24:17:24:37 | call to filter_params |
6+
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:56:21:56:32 | input_params : |
67
| UrlRedirect.rb:34:20:34:25 | call to params : | UrlRedirect.rb:34:17:34:37 | "#{...}/foo" |
8+
| UrlRedirect.rb:56:21:56:32 | input_params : | UrlRedirect.rb:57:5:57:29 | call to permit : |
79
nodes
810
| UrlRedirect.rb:4:17:4:22 | call to params | semmle.label | call to params |
911
| UrlRedirect.rb:9:17:9:22 | call to params : | semmle.label | call to params : |
@@ -16,6 +18,10 @@ nodes
1618
| UrlRedirect.rb:24:31:24:36 | call to params : | semmle.label | call to params : |
1719
| UrlRedirect.rb:34:17:34:37 | "#{...}/foo" | semmle.label | "#{...}/foo" |
1820
| UrlRedirect.rb:34:20:34:25 | call to params : | semmle.label | call to params : |
21+
| UrlRedirect.rb:56:21:56:32 | input_params : | semmle.label | input_params : |
22+
| UrlRedirect.rb:57:5:57:29 | call to permit : | semmle.label | call to permit : |
23+
subpaths
24+
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:56:21:56:32 | input_params : | UrlRedirect.rb:57:5:57:29 | call to permit : | UrlRedirect.rb:24:17:24:37 | call to filter_params : |
1925
#select
2026
| UrlRedirect.rb:4:17:4:22 | call to params | UrlRedirect.rb:4:17:4:22 | call to params | UrlRedirect.rb:4:17:4:22 | call to params | Untrusted URL redirection due to $@. | UrlRedirect.rb:4:17:4:22 | call to params | a user-provided value |
2127
| UrlRedirect.rb:9:17:9:28 | ...[...] | UrlRedirect.rb:9:17:9:22 | call to params : | UrlRedirect.rb:9:17:9:28 | ...[...] | Untrusted URL redirection due to $@. | UrlRedirect.rb:9:17:9:22 | call to params | a user-provided value |

ql/test/query-tests/security/cwe-732/WeakFilePermissions.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ nodes
1616
| FilePermissions.rb:51:19:51:29 | "u=rwx,o+r" | semmle.label | "u=rwx,o+r" |
1717
| FilePermissions.rb:53:19:53:24 | "a+rw" | semmle.label | "a+rw" |
1818
| FilePermissions.rb:57:16:57:19 | 0755 | semmle.label | 0755 |
19+
subpaths
1920
#select
2021
| FilePermissions.rb:4:19:4:22 | 0222 | FilePermissions.rb:4:19:4:22 | 0222 | FilePermissions.rb:4:19:4:22 | 0222 | Overly permissive mask in $@ sets file to $@. | FilePermissions.rb:4:3:4:32 | call to chmod | call to chmod | FilePermissions.rb:4:19:4:22 | 0222 | 0222 |
2122
| FilePermissions.rb:5:19:5:22 | 0622 | FilePermissions.rb:5:19:5:22 | 0622 | FilePermissions.rb:5:19:5:22 | 0622 | Overly permissive mask in $@ sets file to $@. | FilePermissions.rb:5:3:5:32 | call to chmod | call to chmod | FilePermissions.rb:5:19:5:22 | 0622 | 0622 |

ql/test/query-tests/security/cwe-798/HardcodedCredentials.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ nodes
1919
| HardcodedCredentials.rb:23:19:23:20 | pw : | semmle.label | pw : |
2020
| HardcodedCredentials.rb:31:18:31:23 | passwd | semmle.label | passwd |
2121
| HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." : | semmle.label | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." : |
22+
subpaths
2223
#select
2324
| HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | Use of $@. | HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | hardcoded credentials |
2425
| HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | Use of $@. | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | hardcoded credentials |

0 commit comments

Comments
 (0)