Skip to content

Commit 00bf352

Browse files
committed
Ruby: fix some flow summary join orders
The flow summaries that are implemented with an abstract base class restricting the method name, and child classes using that method name, had unfortunate join orders: r1 = JOIN Call::MethodCall::getMethodName#dispred#f0820431#ff WITH Call::MethodCall::getMethodName#dispred#f0820431#ff ON FIRST 1 OUTPUT Lhs.0, (Lhs.1 ++ "_arg"), Rhs.1
1 parent 58a2677 commit 00bf352

File tree

1 file changed

+45
-20
lines changed
  • ruby/ql/lib/codeql/ruby/frameworks/core

1 file changed

+45
-20
lines changed

ruby/ql/lib/codeql/ruby/frameworks/core/Array.qll

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,17 @@ module Array {
192192
}
193193
}
194194

195+
private class ElementReferenceReadMethodName extends string {
196+
ElementReferenceReadMethodName() { this = ["[]", "slice"] }
197+
}
198+
195199
/** A call to `[]`, or its alias, `slice`. */
196200
abstract private class ElementReferenceReadSummary extends SummarizedCallable {
197201
MethodCall mc;
202+
ElementReferenceReadMethodName methodName;
198203

199204
bindingset[this]
200-
ElementReferenceReadSummary() { mc.getMethodName() = ["[]", "slice"] }
205+
ElementReferenceReadSummary() { mc.getMethodName() = methodName }
201206

202207
override MethodCall getACall() { result = mc }
203208
}
@@ -207,7 +212,7 @@ module Array {
207212
private ConstantValue cv;
208213

209214
ElementReferenceReadKnownSummary() {
210-
this = mc.getMethodName() + "(" + cv.serialize() + ")" and
215+
this = methodName + "(" + cv.serialize() + ")" and
211216
mc.getNumberOfArguments() = 1 and
212217
cv = getKnownElementIndex(mc.getArgument(0))
213218
}
@@ -225,7 +230,7 @@ module Array {
225230
*/
226231
private class ElementReferenceReadUnknownSummary extends ElementReferenceReadSummary {
227232
ElementReferenceReadUnknownSummary() {
228-
this = mc.getMethodName() + "(index)" and
233+
this = methodName + "(index)" and
229234
mc.getNumberOfArguments() = 1 and
230235
isUnknownElementIndex(mc.getArgument(0))
231236
}
@@ -267,7 +272,7 @@ module Array {
267272
or
268273
rl.isExclusive() and end = e - 1
269274
) and
270-
this = "[](" + start + ".." + end + ")"
275+
this = methodName + "(" + start + ".." + end + ")"
271276
)
272277
}
273278

@@ -291,7 +296,7 @@ module Array {
291296
*/
292297
private class ElementReferenceRangeReadUnknownSummary extends ElementReferenceReadSummary {
293298
ElementReferenceRangeReadUnknownSummary() {
294-
this = "[](range_unknown)" and
299+
this = methodName + "(range_unknown)" and
295300
(
296301
mc.getNumberOfArguments() = 2 and
297302
(
@@ -2007,17 +2012,22 @@ module Enumerable {
20072012
}
20082013
}
20092014

2015+
private class GrepMethodName extends string {
2016+
GrepMethodName() { this = ["grep", "grep_v"] }
2017+
}
2018+
20102019
abstract private class GrepSummary extends SummarizedCallable {
20112020
MethodCall mc;
2021+
GrepMethodName methodName;
20122022

20132023
bindingset[this]
2014-
GrepSummary() { mc.getMethodName() = ["grep", "grep_v"] }
2024+
GrepSummary() { mc.getMethodName() = methodName }
20152025

20162026
override MethodCall getACall() { result = mc }
20172027
}
20182028

20192029
private class GrepBlockSummary extends GrepSummary {
2020-
GrepBlockSummary() { this = mc.getMethodName() + "(block)" and exists(mc.getBlock()) }
2030+
GrepBlockSummary() { this = methodName + "(block)" and exists(mc.getBlock()) }
20212031

20222032
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
20232033
(
@@ -2032,7 +2042,7 @@ module Enumerable {
20322042
}
20332043

20342044
private class GrepNoBlockSummary extends GrepSummary {
2035-
GrepNoBlockSummary() { this = mc.getMethodName() + "(no_block)" and not exists(mc.getBlock()) }
2045+
GrepNoBlockSummary() { this = methodName + "(no_block)" and not exists(mc.getBlock()) }
20362046

20372047
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
20382048
input = "Argument[self].Element[any]" and
@@ -2052,18 +2062,23 @@ module Enumerable {
20522062
}
20532063
}
20542064

2065+
private class InjectMethodName extends string {
2066+
// `reduce` is an alias for `inject`.
2067+
InjectMethodName() { this = ["inject", "reduce"] }
2068+
}
2069+
20552070
abstract private class InjectSummary extends SummarizedCallable {
20562071
MethodCall mc;
2072+
InjectMethodName methodName; // adding this as a field helps give a better join order
20572073

2058-
// `reduce` is an alias for `inject`.
20592074
bindingset[this]
2060-
InjectSummary() { mc.getMethodName() = ["inject", "reduce"] }
2075+
InjectSummary() { mc.getMethodName() = methodName }
20612076

20622077
override MethodCall getACall() { result = mc }
20632078
}
20642079

20652080
private class InjectNoArgSummary extends InjectSummary {
2066-
InjectNoArgSummary() { this = mc.getMethodName() + "_no_arg" and mc.getNumberOfArguments() = 0 }
2081+
InjectNoArgSummary() { this = methodName + "_no_arg" and mc.getNumberOfArguments() = 0 }
20672082

20682083
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
20692084
// The no-argument variant of inject passes element 0 to the first block
@@ -2083,7 +2098,7 @@ module Enumerable {
20832098
}
20842099

20852100
private class InjectArgSummary extends InjectSummary {
2086-
InjectArgSummary() { this = mc.getMethodName() + "_arg" and mc.getNumberOfArguments() > 0 }
2101+
InjectArgSummary() { this = methodName + "_arg" and mc.getNumberOfArguments() > 0 }
20872102

20882103
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
20892104
(
@@ -2101,18 +2116,23 @@ module Enumerable {
21012116
}
21022117
}
21032118

2119+
private class MinOrMaxByMethodName extends string {
2120+
MinOrMaxByMethodName() { this = ["min_by", "max_by"] }
2121+
}
2122+
21042123
abstract private class MinOrMaxBySummary extends SummarizedCallable {
21052124
MethodCall mc;
2125+
MinOrMaxByMethodName methodName; // adding this as a field helps give a better join order
21062126

21072127
bindingset[this]
2108-
MinOrMaxBySummary() { mc.getMethodName() = ["min_by", "max_by"] }
2128+
MinOrMaxBySummary() { mc.getMethodName() = methodName }
21092129

21102130
override MethodCall getACall() { result = mc }
21112131
}
21122132

21132133
private class MinOrMaxByNoArgSummary extends MinOrMaxBySummary {
21142134
MinOrMaxByNoArgSummary() {
2115-
this = mc.getMethodName() + "_no_arg" and
2135+
this = methodName + "_no_arg" and
21162136
mc.getNumberOfArguments() = 0
21172137
}
21182138

@@ -2125,7 +2145,7 @@ module Enumerable {
21252145

21262146
private class MinOrMaxByArgSummary extends MinOrMaxBySummary {
21272147
MinOrMaxByArgSummary() {
2128-
this = mc.getMethodName() + "_arg" and
2148+
this = methodName + "_arg" and
21292149
mc.getNumberOfArguments() > 0
21302150
}
21312151

@@ -2136,18 +2156,23 @@ module Enumerable {
21362156
}
21372157
}
21382158

2159+
private class MinOrMaxMethodName extends string {
2160+
MinOrMaxMethodName() { this = ["min", "max"] }
2161+
}
2162+
21392163
abstract private class MinOrMaxSummary extends SummarizedCallable {
21402164
MethodCall mc;
2165+
MinOrMaxMethodName methodName;
21412166

21422167
bindingset[this]
2143-
MinOrMaxSummary() { mc.getMethodName() = ["min", "max"] }
2168+
MinOrMaxSummary() { mc.getMethodName() = methodName }
21442169

21452170
override MethodCall getACall() { result = mc }
21462171
}
21472172

21482173
private class MinOrMaxNoArgNoBlockSummary extends MinOrMaxSummary {
21492174
MinOrMaxNoArgNoBlockSummary() {
2150-
this = mc.getMethodName() + "_no_arg_no_block" and
2175+
this = methodName + "_no_arg_no_block" and
21512176
mc.getNumberOfArguments() = 0 and
21522177
not exists(mc.getBlock())
21532178
}
@@ -2161,7 +2186,7 @@ module Enumerable {
21612186

21622187
private class MinOrMaxArgNoBlockSummary extends MinOrMaxSummary {
21632188
MinOrMaxArgNoBlockSummary() {
2164-
this = mc.getMethodName() + "_arg_no_block" and
2189+
this = methodName + "_arg_no_block" and
21652190
mc.getNumberOfArguments() > 0 and
21662191
not exists(mc.getBlock())
21672192
}
@@ -2175,7 +2200,7 @@ module Enumerable {
21752200

21762201
private class MinOrMaxNoArgBlockSummary extends MinOrMaxSummary {
21772202
MinOrMaxNoArgBlockSummary() {
2178-
this = mc.getMethodName() + "_no_arg_block" and
2203+
this = methodName + "_no_arg_block" and
21792204
mc.getNumberOfArguments() = 0 and
21802205
exists(mc.getBlock())
21812206
}
@@ -2189,7 +2214,7 @@ module Enumerable {
21892214

21902215
private class MinOrMaxArgBlockSummary extends MinOrMaxSummary {
21912216
MinOrMaxArgBlockSummary() {
2192-
this = mc.getMethodName() + "_arg_block" and
2217+
this = methodName + "_arg_block" and
21932218
mc.getNumberOfArguments() > 0 and
21942219
exists(mc.getBlock())
21952220
}

0 commit comments

Comments
 (0)