Skip to content

Commit 73802cb

Browse files
committed
Ruby: Refactor SummarizedCallable.
1 parent be79f20 commit 73802cb

File tree

5 files changed

+35
-61
lines changed

5 files changed

+35
-61
lines changed

ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -84,37 +84,10 @@ module SummaryComponentStack {
8484
}
8585

8686
/** A callable with a flow summary, identified by a unique string. */
87-
abstract class SummarizedCallable extends LibraryCallable {
87+
abstract class SummarizedCallable extends LibraryCallable, Impl::Public::SummarizedCallable {
8888
bindingset[this]
8989
SummarizedCallable() { any() }
9090

91-
/**
92-
* Holds if data may flow from `input` to `output` through this callable.
93-
*
94-
* `preservesValue` indicates whether this is a value-preserving step
95-
* or a taint-step.
96-
*
97-
* Input specifications are restricted to stacks that end with
98-
* `SummaryComponent::argument(_)`, preceded by zero or more
99-
* `SummaryComponent::return()` or `SummaryComponent::content(_)` components.
100-
*
101-
* Output specifications are restricted to stacks that end with
102-
* `SummaryComponent::return()` or `SummaryComponent::argument(_)`.
103-
*
104-
* Output stacks ending with `SummaryComponent::return()` can be preceded by zero
105-
* or more `SummaryComponent::content(_)` components.
106-
*
107-
* Output stacks ending with `SummaryComponent::argument(_)` can be preceded by an
108-
* optional `SummaryComponent::parameter(_)` component, which in turn can be preceded
109-
* by zero or more `SummaryComponent::content(_)` components.
110-
*/
111-
pragma[nomagic]
112-
predicate propagatesFlow(
113-
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
114-
) {
115-
none()
116-
}
117-
11891
/**
11992
* Same as
12093
*
@@ -143,18 +116,6 @@ abstract class SimpleSummarizedCallable extends SummarizedCallable {
143116
final override MethodCall getACall() { result = mc }
144117
}
145118

146-
private class SummarizedCallableAdapter extends Impl::Public::SummarizedCallable {
147-
private SummarizedCallable sc;
148-
149-
SummarizedCallableAdapter() { this = TLibraryCallable(sc) }
150-
151-
final override predicate propagatesFlow(
152-
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
153-
) {
154-
sc.propagatesFlow(input, output, preservesValue)
155-
}
156-
}
157-
158119
class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack;
159120

160121
private class SummarizedCallableFromModel extends SummarizedCallable {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,11 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
120120
/** Gets the data flow node that this call targets. */
121121
DataFlow::Node getReceiver() { result = receiver }
122122

123-
override DataFlowCallable getEnclosingCallable() { result = c }
123+
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
124124

125125
override string toString() { result = "[summary] call to " + receiver + " in " + c }
126126

127-
override Location getLocation() { result = c.getLocation() }
127+
override EmptyLocation getLocation() { any() }
128128
}
129129

130130
private class NormalCall extends DataFlowCall, TNormalCall {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,12 +530,12 @@ private module ParameterNodes {
530530
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) { none() }
531531

532532
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
533-
sc = c and pos = pos_
533+
sc = c.asLibraryCallable() and pos = pos_
534534
}
535535

536536
override CfgScope getCfgScope() { none() }
537537

538-
override DataFlowCallable getEnclosingCallable() { result = sc }
538+
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = sc }
539539

540540
override EmptyLocation getLocationImpl() { any() }
541541

@@ -554,7 +554,7 @@ class SummaryNode extends NodeImpl, TSummaryNode {
554554

555555
override CfgScope getCfgScope() { none() }
556556

557-
override DataFlowCallable getEnclosingCallable() { result = c }
557+
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
558558

559559
override EmptyLocation getLocationImpl() { any() }
560560

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

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ module Public {
195195
}
196196

197197
/** A callable with a flow summary. */
198-
abstract class SummarizedCallable extends DataFlowCallable {
198+
abstract class SummarizedCallable extends SummarizedCallableBase {
199+
bindingset[this]
200+
SummarizedCallable() { any() }
201+
199202
/**
200203
* Holds if data may flow from `input` to `output` through this callable.
201204
*
@@ -493,7 +496,7 @@ module Private {
493496
or
494497
exists(ParameterPosition pos |
495498
parameterReadState(c, state, pos) and
496-
result.(ParamNode).isParameterOf(c, pos)
499+
result.(ParamNode).isParameterOf(inject(c), pos)
497500
)
498501
)
499502
}
@@ -621,7 +624,7 @@ module Private {
621624
predicate summaryPostUpdateNode(Node post, Node pre) {
622625
exists(SummarizedCallable c, ParameterPosition pos |
623626
isParameterPostUpdate(post, c, pos) and
624-
pre.(ParamNode).isParameterOf(c, pos)
627+
pre.(ParamNode).isParameterOf(inject(c), pos)
625628
)
626629
or
627630
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -644,7 +647,7 @@ module Private {
644647
* node, and back out to `p`.
645648
*/
646649
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
647-
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(c, ppos) |
650+
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
648651
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
649652
summary(c, inputContents, outputContents, _) and
650653
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -748,8 +751,11 @@ module Private {
748751
private predicate viableParam(
749752
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
750753
) {
751-
p.isParameterOf(sc, ppos) and
752-
sc = viableCallable(call)
754+
exists(DataFlowCallable c |
755+
c = inject(sc) and
756+
p.isParameterOf(c, ppos) and
757+
c = viableCallable(call)
758+
)
753759
}
754760

755761
pragma[nomagic]
@@ -1067,16 +1073,18 @@ module Private {
10671073
/** Provides a query predicate for outputting a set of relevant flow summaries. */
10681074
module TestOutput {
10691075
/** A flow summary to include in the `summary/3` query predicate. */
1070-
abstract class RelevantSummarizedCallable extends SummarizedCallable {
1076+
abstract class RelevantSummarizedCallable instanceof SummarizedCallable {
10711077
/** Gets the string representation of this callable used by `summary/1`. */
10721078
abstract string getCallableCsv();
10731079

10741080
/** Holds if flow is propagated between `input` and `output`. */
10751081
predicate relevantSummary(
10761082
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
10771083
) {
1078-
this.propagatesFlow(input, output, preservesValue)
1084+
super.propagatesFlow(input, output, preservesValue)
10791085
}
1086+
1087+
string toString() { result = super.toString() }
10801088
}
10811089

10821090
/** Render the kind in the format used in flow summaries. */
@@ -1087,7 +1095,7 @@ module Private {
10871095
}
10881096

10891097
private string renderGenerated(RelevantSummarizedCallable c) {
1090-
if c.isAutoGenerated() then result = "generated:" else result = ""
1098+
if c.(SummarizedCallable).isAutoGenerated() then result = "generated:" else result = ""
10911099
}
10921100

10931101
/**
@@ -1117,19 +1125,21 @@ module Private {
11171125
*/
11181126
module RenderSummarizedCallable {
11191127
/** A summarized callable to include in the graph. */
1120-
abstract class RelevantSummarizedCallable extends SummarizedCallable { }
1128+
abstract class RelevantSummarizedCallable instanceof SummarizedCallable {
1129+
string toString() { result = super.toString() }
1130+
}
11211131

11221132
private newtype TNodeOrCall =
11231133
MkNode(Node n) {
11241134
exists(RelevantSummarizedCallable c |
11251135
n = summaryNode(c, _)
11261136
or
1127-
n.(ParamNode).isParameterOf(c, _)
1137+
n.(ParamNode).isParameterOf(inject(c), _)
11281138
)
11291139
} or
11301140
MkCall(DataFlowCall call) {
11311141
call = summaryDataFlowCall(_) and
1132-
call.getEnclosingCallable() instanceof RelevantSummarizedCallable
1142+
call.getEnclosingCallable() = inject(any(RelevantSummarizedCallable c))
11331143
}
11341144

11351145
private class NodeOrCall extends TNodeOrCall {

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ private import FlowSummaryImpl::Private
1111
private import FlowSummaryImpl::Public
1212
private import codeql.ruby.dataflow.FlowSummary as FlowSummary
1313

14+
class SummarizedCallableBase = string;
15+
16+
DataFlowCallable inject(SummarizedCallable c) { result.asLibraryCallable() = c }
17+
1418
/** Gets the parameter position of the instance parameter. */
1519
ArgumentPosition instanceParameterPosition() { none() } // disables implicit summary flow to `self` for callbacks
1620

@@ -46,11 +50,10 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) { any() }
4650
* stating whether the summary is autogenerated.
4751
*/
4852
predicate summaryElement(
49-
DataFlowCallable c, string input, string output, string kind, boolean generated
53+
FlowSummary::SummarizedCallable c, string input, string output, string kind, boolean generated
5054
) {
51-
exists(FlowSummary::SummarizedCallable sc, boolean preservesValue |
52-
sc.propagatesFlowExt(input, output, preservesValue) and
53-
c.asLibraryCallable() = sc and
55+
exists(boolean preservesValue |
56+
c.propagatesFlowExt(input, output, preservesValue) and
5457
(if preservesValue = true then kind = "value" else kind = "taint") and
5558
generated = false
5659
)

0 commit comments

Comments
 (0)