Skip to content

Commit c1c16e4

Browse files
authored
Merge pull request #10559 from aibaars/cve-2019-3881
Ruby: some improvements
2 parents d69a658 + 88b5d4d commit c1c16e4

29 files changed

+5767
-722
lines changed

config/identical-files.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@
3333
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
3434
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
3535
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
36-
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForLibraries.qll",
36+
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll",
3737
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll",
38+
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll",
3839
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll"
3940
],
4041
"DataFlow Java/C++/C#/Python Common": [
@@ -69,7 +70,7 @@
6970
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
7071
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll",
7172
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
72-
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforlibraries/TaintTrackingImpl.qll",
73+
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingImpl.qll",
7374
"swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
7475
],
7576
"DataFlow Java/C++/C#/Python Consistency checks": [

ruby/ql/lib/codeql/ruby/Regexp.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class StdLibRegExpInterpretation extends RegExpInterpretation::Range {
114114
mce.getMethodName() = ["match", "match?"] and
115115
this = mce.getArgument(0) and
116116
// exclude https://ruby-doc.org/core-2.4.0/Regexp.html#method-i-match
117-
not mce.getReceiver().asExpr().getExpr() instanceof Ast::RegExpLiteral
117+
not mce.getReceiver() = trackRegexpType()
118118
)
119119
}
120120
}

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

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,30 @@ private DataFlowCallable viableLibraryCallable(DataFlowCall call) {
294294
)
295295
}
296296

297+
/** Holds if there is a call like `receiver.extend(M)`. */
298+
pragma[nomagic]
299+
private predicate extendCall(DataFlow::ExprNode receiver, Module m) {
300+
exists(DataFlow::CallNode extendCall |
301+
extendCall.getMethodName() = "extend" and
302+
exists(DataFlow::LocalSourceNode sourceNode | sourceNode.flowsTo(extendCall.getArgument(_)) |
303+
selfInModule(sourceNode.(SsaSelfDefinitionNode).getVariable(), m) or
304+
m = resolveConstantReadAccess(sourceNode.asExpr().getExpr())
305+
) and
306+
receiver = extendCall.getReceiver()
307+
)
308+
}
309+
310+
/** Holds if there is a call like `M.extend(N)` */
311+
pragma[nomagic]
312+
private predicate extendCallModule(Module m, Module n) {
313+
exists(DataFlow::LocalSourceNode receiver, DataFlow::ExprNode e |
314+
receiver.flowsTo(e) and extendCall(e, n)
315+
|
316+
selfInModule(receiver.(SsaSelfDefinitionNode).getVariable(), m) or
317+
m = resolveConstantReadAccess(receiver.asExpr().getExpr())
318+
)
319+
}
320+
297321
cached
298322
private module Cached {
299323
cached
@@ -340,12 +364,29 @@ private module Cached {
340364
// def c.singleton; end # <- result
341365
// c.singleton # <- call
342366
// ```
367+
// or an `extend`ed instance, e.g.
368+
// ```rb
369+
// c = C.new
370+
// module M
371+
// def instance; end # <- result
372+
// end
373+
// c.extend M
374+
// c.instance # <- call
375+
// ```
343376
exists(DataFlow::Node receiver |
344377
methodCall(call, receiver, method) and
345378
receiver = trackSingletonMethodOnInstance(result, method)
346379
)
347380
or
348381
// singleton method defined on a module
382+
// or an `extend`ed module, e.g.
383+
// ```rb
384+
// module M
385+
// def instance; end # <- result
386+
// end
387+
// M.extend(M)
388+
// M.instance # <- call
389+
// ```
349390
exists(DataFlow::Node sourceNode, Module m |
350391
flowsToMethodCall(call, sourceNode, method) and
351392
singletonMethodOnModule(result, method, m)
@@ -664,6 +705,12 @@ private predicate flowsToSingletonMethodObject(
664705
* class << c
665706
* def m6; end # not included
666707
* end
708+
*
709+
* module M
710+
* def instance; end # included in `N` via `extend` call below
711+
* end
712+
* N.extend(M)
713+
* N.instance
667714
* ```
668715
*/
669716
pragma[nomagic]
@@ -674,6 +721,11 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module
674721
)
675722
or
676723
flowsToSingletonMethodObject(trackModuleAccess(m), method, name)
724+
or
725+
exists(Module other |
726+
extendCallModule(m, other) and
727+
method = lookupMethod(other, name)
728+
)
677729
}
678730

679731
/**
@@ -700,6 +752,11 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module
700752
* class << c
701753
* def m6; end # included
702754
* end
755+
*
756+
* module M
757+
* def instance; end # included in `c` via `extend` call below
758+
* end
759+
* c.extend(M)
703760
* ```
704761
*/
705762
pragma[nomagic]
@@ -708,6 +765,12 @@ predicate singletonMethodOnInstance(MethodBase method, string name, Expr object)
708765
not selfInModule(object.(SelfVariableReadAccess).getVariable(), _) and
709766
// cannot use `trackModuleAccess` because of negative recursion
710767
not exists(resolveConstantReadAccess(object))
768+
or
769+
exists(DataFlow::ExprNode receiver, Module other |
770+
extendCall(receiver, other) and
771+
object = receiver.getExprNode().getExpr() and
772+
method = lookupMethod(other, name)
773+
)
711774
}
712775

713776
/**

0 commit comments

Comments
 (0)