Skip to content

Commit a397c65

Browse files
committed
Ruby: Split standard library modeling
Split the classes modeling various standard library concepts into a structured group of multiple files. Things that are part of the core language live in framworks/core and standard libraries (that aren't part of core) live in frameworks/stdlib. This mirrors the structure followed by the Ruby docs (https://docs.ruby-lang.org/en/3.1/). Tests are split in a followup commit.
1 parent a448db1 commit a397c65

File tree

18 files changed

+555
-488
lines changed

18 files changed

+555
-488
lines changed

ruby/ql/lib/codeql/ruby/Frameworks.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
* Helper file that imports all framework modeling.
33
*/
44

5+
private import codeql.ruby.frameworks.Core
56
private import codeql.ruby.frameworks.ActionController
67
private import codeql.ruby.frameworks.ActiveRecord
78
private import codeql.ruby.frameworks.ActiveStorage
89
private import codeql.ruby.frameworks.ActionView
910
private import codeql.ruby.frameworks.ActiveSupport
1011
private import codeql.ruby.frameworks.GraphQL
1112
private import codeql.ruby.frameworks.Rails
12-
private import codeql.ruby.frameworks.StandardLibrary
13+
private import codeql.ruby.frameworks.Stdlib
1314
private import codeql.ruby.frameworks.Files
1415
private import codeql.ruby.frameworks.HttpClients
1516
private import codeql.ruby.frameworks.XmlParsing

ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ private import codeql.ruby.DataFlow
55
private import codeql.ruby.dataflow.internal.DataFlowDispatch
66
private import codeql.ruby.ast.internal.Module
77
private import codeql.ruby.ApiGraphs
8-
private import codeql.ruby.frameworks.StandardLibrary
8+
private import codeql.ruby.frameworks.Stdlib
9+
private import codeql.ruby.frameworks.Core
910

1011
/// See https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html
1112
private string activeRecordPersistenceInstanceMethodName() {
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
private import codeql.ruby.Concepts
2+
private import codeql.ruby.DataFlow
3+
private import codeql.ruby.dataflow.FlowSummary
4+
import core.BasicObject::BasicObject
5+
import core.Object::Object
6+
import core.Kernel::Kernel
7+
import core.Module
8+
import core.Array
9+
import core.Regexp
10+
11+
/**
12+
* A `Method` call that has no known target.
13+
* These will typically be calls to methods inherited from a superclass.
14+
*/
15+
class UnknownMethodCall extends MethodCall {
16+
UnknownMethodCall() { not exists(this.(Call).getATarget()) }
17+
}
18+
19+
/**
20+
* A system command executed via subshell literal syntax.
21+
* E.g.
22+
* ```ruby
23+
* `cat foo.txt`
24+
* %x(cat foo.txt)
25+
* %x[cat foo.txt]
26+
* %x{cat foo.txt}
27+
* %x/cat foo.txt/
28+
* ```
29+
*/
30+
class SubshellLiteralExecution extends SystemCommandExecution::Range {
31+
SubshellLiteral literal;
32+
33+
SubshellLiteralExecution() { this.asExpr().getExpr() = literal }
34+
35+
override DataFlow::Node getAnArgument() { result.asExpr().getExpr() = literal.getComponent(_) }
36+
37+
override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getAnArgument() }
38+
}
39+
40+
/**
41+
* A system command executed via shell heredoc syntax.
42+
* E.g.
43+
* ```ruby
44+
* <<`EOF`
45+
* cat foo.text
46+
* EOF
47+
* ```
48+
*/
49+
class SubshellHeredocExecution extends SystemCommandExecution::Range {
50+
HereDoc heredoc;
51+
52+
SubshellHeredocExecution() { this.asExpr().getExpr() = heredoc and heredoc.isSubShell() }
53+
54+
override DataFlow::Node getAnArgument() { result.asExpr().getExpr() = heredoc.getComponent(_) }
55+
56+
override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getAnArgument() }
57+
}
58+
59+
private class SplatSummary extends SummarizedCallable {
60+
SplatSummary() { this = "*(splat)" }
61+
62+
override SplatExpr getACall() { any() }
63+
64+
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
65+
(
66+
// *1 = [1]
67+
input = "Receiver" and
68+
output = "ArrayElement[0] of ReturnValue"
69+
or
70+
// *[1] = [1]
71+
input = "Receiver" and
72+
output = "ReturnValue"
73+
) and
74+
preservesValue = true
75+
}
76+
}

ruby/ql/lib/codeql/ruby/frameworks/Files.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ private import ruby
66
private import codeql.ruby.Concepts
77
private import codeql.ruby.ApiGraphs
88
private import codeql.ruby.DataFlow
9-
private import codeql.ruby.frameworks.StandardLibrary
9+
private import codeql.ruby.frameworks.Core
1010
private import codeql.ruby.dataflow.FlowSummary
1111

1212
private DataFlow::Node ioInstanceInstantiation() {

0 commit comments

Comments
 (0)