Skip to content

Commit 9268437

Browse files
committed
Ruby: Generalize SynthHashSplatParameterNode to also work for synthesized methods
1 parent d16a154 commit 9268437

File tree

4 files changed

+212
-193
lines changed

4 files changed

+212
-193
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,12 @@ class DataFlowCallable extends TDataFlowCallable {
6565
string toString() { result = [this.asCallable().toString(), this.asLibraryCallable()] }
6666

6767
/** Gets the location of this callable. */
68-
Location getLocation() { result = this.asCallable().getLocation() }
68+
Location getLocation() {
69+
result = this.asCallable().getLocation()
70+
or
71+
this instanceof TLibraryCallable and
72+
result instanceof EmptyLocation
73+
}
6974
}
7075

7176
/**

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

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ private module Cached {
227227
} or
228228
TSelfParameterNode(MethodBase m) or
229229
TBlockParameterNode(MethodBase m) or
230-
TSynthHashSplatParameterNode(MethodBase m) { m.getAParameter() instanceof KeywordParameter } or
230+
TSynthHashSplatParameterNode(DataFlowCallable c) {
231+
isParameterNode(_, c, any(ParameterPosition p | p.isKeyword(_)))
232+
} or
231233
TExprPostUpdateNode(CfgNodes::ExprCfgNode n) {
232234
n instanceof Argument or
233235
n = any(CfgNodes::ExprNodes::InstanceVariableAccessCfgNode v).getReceiver()
@@ -477,10 +479,13 @@ private module ParameterNodes {
477479
abstract class ParameterNodeImpl extends NodeImpl {
478480
abstract Parameter getParameter();
479481

480-
abstract predicate isSourceParameterOf(Callable c, ParameterPosition pos);
482+
abstract predicate isParameterOf(DataFlowCallable c, ParameterPosition pos);
481483

482-
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
483-
this.isSourceParameterOf(c.asCallable(), pos)
484+
final predicate isSourceParameterOf(Callable c, ParameterPosition pos) {
485+
exists(DataFlowCallable callable |
486+
this.isParameterOf(callable, pos) and
487+
c = callable.asCallable()
488+
)
484489
}
485490
}
486491

@@ -495,21 +500,23 @@ private module ParameterNodes {
495500

496501
override Parameter getParameter() { result = parameter }
497502

498-
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) {
499-
exists(int i | pos.isPositional(i) and c.getParameter(i) = parameter |
500-
parameter instanceof SimpleParameter
503+
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
504+
exists(Callable callable | callable = c.asCallable() |
505+
exists(int i | pos.isPositional(i) and callable.getParameter(i) = parameter |
506+
parameter instanceof SimpleParameter
507+
or
508+
parameter instanceof OptionalParameter
509+
)
510+
or
511+
parameter =
512+
any(KeywordParameter kp |
513+
callable.getAParameter() = kp and
514+
pos.isKeyword(kp.getName())
515+
)
501516
or
502-
parameter instanceof OptionalParameter
517+
parameter = callable.getAParameter().(HashSplatParameter) and
518+
pos.isHashSplat()
503519
)
504-
or
505-
parameter =
506-
any(KeywordParameter kp |
507-
c.getAParameter() = kp and
508-
pos.isKeyword(kp.getName())
509-
)
510-
or
511-
parameter = c.getAParameter().(HashSplatParameter) and
512-
pos.isHashSplat()
513520
}
514521

515522
override CfgScope getCfgScope() { result = parameter.getCallable() }
@@ -532,8 +539,8 @@ private module ParameterNodes {
532539

533540
override Parameter getParameter() { none() }
534541

535-
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) {
536-
method = c and pos.isSelf()
542+
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
543+
method = c.asCallable() and pos.isSelf()
537544
}
538545

539546
override CfgScope getCfgScope() { result = method }
@@ -558,8 +565,8 @@ private module ParameterNodes {
558565
result = method.getAParameter() and result instanceof BlockParameter
559566
}
560567

561-
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) {
562-
c = method and pos.isBlock()
568+
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
569+
c.asCallable() = method and pos.isBlock()
563570
}
564571

565572
override CfgScope getCfgScope() { result = method }
@@ -612,37 +619,36 @@ private module ParameterNodes {
612619
* collapsed anyway.
613620
*/
614621
class SynthHashSplatParameterNode extends ParameterNodeImpl, TSynthHashSplatParameterNode {
615-
private MethodBase method;
622+
private DataFlowCallable callable;
616623

617-
SynthHashSplatParameterNode() { this = TSynthHashSplatParameterNode(method) }
618-
619-
final Callable getMethod() { result = method }
624+
SynthHashSplatParameterNode() { this = TSynthHashSplatParameterNode(callable) }
620625

621626
/**
622627
* Gets a keyword parameter that will be the result of reading `c` out of this
623628
* synthesized node.
624629
*/
625-
NormalParameterNode getAKeywordParameter(ContentSet c) {
626-
exists(KeywordParameter p |
627-
p = result.getParameter() and
628-
p = method.getAParameter()
630+
ParameterNode getAKeywordParameter(ContentSet c) {
631+
exists(string name |
632+
isParameterNode(result, callable, any(ParameterPosition p | p.isKeyword(name)))
629633
|
630-
c = getKeywordContent(p.getName()) or
634+
c = getKeywordContent(name) or
631635
c.isSingleton(TUnknownElementContent())
632636
)
633637
}
634638

635-
override Parameter getParameter() { none() }
639+
final override Parameter getParameter() { none() }
636640

637-
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) {
638-
c = method and pos.isHashSplat()
641+
final override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
642+
c = callable and pos.isHashSplat()
639643
}
640644

641-
override CfgScope getCfgScope() { result = method }
645+
final override CfgScope getCfgScope() { result = callable.asCallable() }
642646

643-
override Location getLocationImpl() { result = method.getLocation() }
647+
final override DataFlowCallable getEnclosingCallable() { result = callable }
644648

645-
override string toStringImpl() { result = "**kwargs" }
649+
final override Location getLocationImpl() { result = callable.getLocation() }
650+
651+
final override string toStringImpl() { result = "**kwargs" }
646652
}
647653

648654
/** A parameter for a library callable with a flow summary. */
@@ -654,8 +660,6 @@ private module ParameterNodes {
654660

655661
override Parameter getParameter() { none() }
656662

657-
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) { none() }
658-
659663
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
660664
sc = c.asLibraryCallable() and pos = pos_
661665
}

0 commit comments

Comments
 (0)