@@ -8,17 +8,27 @@ private import codeql.ruby.ApiGraphs
8
8
* in every Ruby object. In addition, its module methods can be called by
9
9
* providing a specific receiver as in `Kernel.exit`.
10
10
*/
11
- class KernelMethodCall extends MethodCall {
11
+ class KernelMethodCall extends DataFlow:: CallNode {
12
+ private MethodCall methodCall ;
13
+
12
14
KernelMethodCall ( ) {
13
- this = API:: getTopLevelMember ( "Kernel" ) .getAMethodCall ( _) .asExpr ( ) .getExpr ( )
14
- or
15
- this instanceof UnknownMethodCall and
15
+ methodCall = this .asExpr ( ) .getExpr ( ) and
16
16
(
17
- this . getReceiver ( ) instanceof Self and isPrivateKernelMethod ( this . getMethodName ( ) )
17
+ this = API :: getTopLevelMember ( "Kernel" ) . getAMethodCall ( _ )
18
18
or
19
- isPublicKernelMethod ( this .getMethodName ( ) )
19
+ methodCall instanceof UnknownMethodCall and
20
+ (
21
+ this .getReceiver ( ) .asExpr ( ) .getExpr ( ) instanceof Self and
22
+ isPrivateKernelMethod ( methodCall .getMethodName ( ) )
23
+ or
24
+ isPublicKernelMethod ( methodCall .getMethodName ( ) )
25
+ )
20
26
)
21
27
}
28
+
29
+ string getMethodName ( ) { result = methodCall .getMethodName ( ) }
30
+
31
+ int getNumberOfArguments ( ) { result = methodCall .getNumberOfArguments ( ) }
22
32
}
23
33
24
34
/**
@@ -161,19 +171,14 @@ class SubshellHeredocExecution extends SystemCommandExecution::Range {
161
171
* ```
162
172
* Ruby documentation: https://docs.ruby-lang.org/en/3.0.0/Kernel.html#method-i-system
163
173
*/
164
- class KernelSystemCall extends SystemCommandExecution:: Range {
165
- KernelMethodCall methodCall ;
174
+ class KernelSystemCall extends SystemCommandExecution:: Range , KernelMethodCall {
175
+ KernelSystemCall ( ) { this . getMethodName ( ) = "system" }
166
176
167
- KernelSystemCall ( ) {
168
- methodCall .getMethodName ( ) = "system" and
169
- this .asExpr ( ) .getExpr ( ) = methodCall
170
- }
171
-
172
- override DataFlow:: Node getAnArgument ( ) { result .asExpr ( ) .getExpr ( ) = methodCall .getAnArgument ( ) }
177
+ override DataFlow:: Node getAnArgument ( ) { result = this .getArgument ( _) }
173
178
174
179
override predicate isShellInterpreted ( DataFlow:: Node arg ) {
175
180
// Kernel.system invokes a subshell if you provide a single string as argument
176
- methodCall .getNumberOfArguments ( ) = 1 and arg . asExpr ( ) . getExpr ( ) = methodCall . getAnArgument ( )
181
+ this .getNumberOfArguments ( ) = 1 and arg = getAnArgument ( )
177
182
}
178
183
}
179
184
@@ -182,19 +187,14 @@ class KernelSystemCall extends SystemCommandExecution::Range {
182
187
* `Kernel.exec` takes the same argument forms as `Kernel.system`. See `KernelSystemCall` for details.
183
188
* Ruby documentation: https://docs.ruby-lang.org/en/3.0.0/Kernel.html#method-i-exec
184
189
*/
185
- class KernelExecCall extends SystemCommandExecution:: Range {
186
- KernelMethodCall methodCall ;
190
+ class KernelExecCall extends SystemCommandExecution:: Range , KernelMethodCall {
191
+ KernelExecCall ( ) { this . getMethodName ( ) = "exec" }
187
192
188
- KernelExecCall ( ) {
189
- methodCall .getMethodName ( ) = "exec" and
190
- this .asExpr ( ) .getExpr ( ) = methodCall
191
- }
192
-
193
- override DataFlow:: Node getAnArgument ( ) { result .asExpr ( ) .getExpr ( ) = methodCall .getAnArgument ( ) }
193
+ override DataFlow:: Node getAnArgument ( ) { result = this .getArgument ( _) }
194
194
195
195
override predicate isShellInterpreted ( DataFlow:: Node arg ) {
196
196
// Kernel.exec invokes a subshell if you provide a single string as argument
197
- methodCall .getNumberOfArguments ( ) = 1 and arg . asExpr ( ) . getExpr ( ) = methodCall . getAnArgument ( )
197
+ this .getNumberOfArguments ( ) = 1 and arg = getAnArgument ( )
198
198
}
199
199
}
200
200
@@ -208,19 +208,14 @@ class KernelExecCall extends SystemCommandExecution::Range {
208
208
* spawn([env,] command... [,options]) -> pid
209
209
* ```
210
210
*/
211
- class KernelSpawnCall extends SystemCommandExecution:: Range {
212
- KernelMethodCall methodCall ;
211
+ class KernelSpawnCall extends SystemCommandExecution:: Range , KernelMethodCall {
212
+ KernelSpawnCall ( ) { this . getMethodName ( ) = "spawn" }
213
213
214
- KernelSpawnCall ( ) {
215
- methodCall .getMethodName ( ) = "spawn" and
216
- this .asExpr ( ) .getExpr ( ) = methodCall
217
- }
218
-
219
- override DataFlow:: Node getAnArgument ( ) { result .asExpr ( ) .getExpr ( ) = methodCall .getAnArgument ( ) }
214
+ override DataFlow:: Node getAnArgument ( ) { result = this .getArgument ( _) }
220
215
221
216
override predicate isShellInterpreted ( DataFlow:: Node arg ) {
222
217
// Kernel.spawn invokes a subshell if you provide a single string as argument
223
- methodCall .getNumberOfArguments ( ) = 1 and arg . asExpr ( ) . getExpr ( ) = methodCall . getAnArgument ( )
218
+ this .getNumberOfArguments ( ) = 1 and arg = getAnArgument ( )
224
219
}
225
220
}
226
221
@@ -284,14 +279,10 @@ class Open3PipelineCall extends SystemCommandExecution::Range {
284
279
* a # => 2
285
280
* ```
286
281
*/
287
- class EvalCallCodeExecution extends CodeExecution:: Range {
288
- KernelMethodCall methodCall ;
289
-
290
- EvalCallCodeExecution ( ) {
291
- this .asExpr ( ) .getExpr ( ) = methodCall and methodCall .getMethodName ( ) = "eval"
292
- }
282
+ class EvalCallCodeExecution extends CodeExecution:: Range , KernelMethodCall {
283
+ EvalCallCodeExecution ( ) { this .getMethodName ( ) = "eval" }
293
284
294
- override DataFlow:: Node getCode ( ) { result . asExpr ( ) . getExpr ( ) = methodCall .getArgument ( 0 ) }
285
+ override DataFlow:: Node getCode ( ) { result = this .getArgument ( 0 ) }
295
286
}
296
287
297
288
/**
@@ -302,51 +293,41 @@ class EvalCallCodeExecution extends CodeExecution::Range {
302
293
* arr # => [1]
303
294
* ```
304
295
*/
305
- class SendCallCodeExecution extends CodeExecution:: Range {
306
- KernelMethodCall methodCall ;
296
+ class SendCallCodeExecution extends CodeExecution:: Range , KernelMethodCall {
297
+ SendCallCodeExecution ( ) { this . getMethodName ( ) = "send" }
307
298
308
- SendCallCodeExecution ( ) {
309
- this .asExpr ( ) .getExpr ( ) = methodCall and methodCall .getMethodName ( ) = "send"
310
- }
311
-
312
- override DataFlow:: Node getCode ( ) { result .asExpr ( ) .getExpr ( ) = methodCall .getArgument ( 0 ) }
299
+ override DataFlow:: Node getCode ( ) { result = this .getArgument ( 0 ) }
313
300
}
314
301
315
302
/**
316
303
* A call to `BasicObject#instance_eval`, which executes its first argument as Ruby code.
317
304
*/
318
- class InstanceEvalCallCodeExecution extends CodeExecution:: Range {
319
- BasicObjectInstanceMethodCall methodCall ;
320
-
305
+ class InstanceEvalCallCodeExecution extends CodeExecution:: Range , DataFlow:: CallNode {
321
306
InstanceEvalCallCodeExecution ( ) {
322
- this .asExpr ( ) .getExpr ( ) = methodCall and methodCall .getMethodName ( ) = "instance_eval"
307
+ this .asExpr ( ) .getExpr ( ) . ( UnknownMethodCall ) .getMethodName ( ) = "instance_eval"
323
308
}
324
309
325
- override DataFlow:: Node getCode ( ) { result . asExpr ( ) . getExpr ( ) = methodCall .getArgument ( 0 ) }
310
+ override DataFlow:: Node getCode ( ) { result = this .getArgument ( 0 ) }
326
311
}
327
312
328
313
/**
329
314
* A call to `Module#class_eval`, which executes its first argument as Ruby code.
330
315
*/
331
- class ClassEvalCallCodeExecution extends CodeExecution:: Range {
332
- UnknownMethodCall methodCall ;
333
-
316
+ class ClassEvalCallCodeExecution extends CodeExecution:: Range , DataFlow:: CallNode {
334
317
ClassEvalCallCodeExecution ( ) {
335
- this .asExpr ( ) .getExpr ( ) = methodCall and methodCall .getMethodName ( ) = "class_eval"
318
+ this .asExpr ( ) .getExpr ( ) . ( UnknownMethodCall ) .getMethodName ( ) = "class_eval"
336
319
}
337
320
338
- override DataFlow:: Node getCode ( ) { result . asExpr ( ) . getExpr ( ) = methodCall .getArgument ( 0 ) }
321
+ override DataFlow:: Node getCode ( ) { result = this .getArgument ( 0 ) }
339
322
}
340
323
341
324
/**
342
325
* A call to `Module#module_eval`, which executes its first argument as Ruby code.
343
326
*/
344
- class ModuleEvalCallCodeExecution extends CodeExecution:: Range {
345
- UnknownMethodCall methodCall ;
346
-
327
+ class ModuleEvalCallCodeExecution extends CodeExecution:: Range , DataFlow:: CallNode {
347
328
ModuleEvalCallCodeExecution ( ) {
348
- this .asExpr ( ) .getExpr ( ) = methodCall and methodCall .getMethodName ( ) = "module_eval"
329
+ this .asExpr ( ) .getExpr ( ) . ( UnknownMethodCall ) .getMethodName ( ) = "module_eval"
349
330
}
350
331
351
- override DataFlow:: Node getCode ( ) { result . asExpr ( ) . getExpr ( ) = methodCall .getArgument ( 0 ) }
332
+ override DataFlow:: Node getCode ( ) { result = this .getArgument ( 0 ) }
352
333
}
0 commit comments