6
6
private import ruby
7
7
private import codeql.ruby.Concepts
8
8
private import codeql.ruby.DataFlow
9
+ private import codeql.ruby.dataflow.FlowSummary
10
+ private import codeql.ruby.Concepts
11
+ private import codeql.ruby.ApiGraphs
12
+ private import codeql.ruby.frameworks.stdlib.Logger:: Logger as StdlibLogger
9
13
10
14
/**
11
15
* Modeling for `ActiveSupport`.
@@ -32,6 +36,107 @@ module ActiveSupport {
32
36
33
37
override DataFlow:: Node getCode ( ) { result = this .getReceiver ( ) }
34
38
}
39
+
40
+ /**
41
+ * Flow summary for methods which transform the receiver in some way, possibly preserving taint.
42
+ */
43
+ private class StringTransformSummary extends SummarizedCallable {
44
+ // We're modelling a lot of different methods, so we make up a name for this summary.
45
+ StringTransformSummary ( ) { this = "ActiveSupportStringTransform" }
46
+
47
+ override MethodCall getACall ( ) {
48
+ result .getMethodName ( ) =
49
+ [
50
+ "camelize" , "camelcase" , "classify" , "dasherize" , "deconstantize" , "demodulize" ,
51
+ "foreign_key" , "humanize" , "indent" , "parameterize" , "pluralize" , "singularize" ,
52
+ "squish" , "strip_heredoc" , "tableize" , "titlecase" , "titleize" , "underscore" ,
53
+ "upcase_first"
54
+ ]
55
+ }
56
+
57
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
58
+ input = "Argument[self]" and output = "ReturnValue" and preservesValue = false
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Extensions to the `Enumerable` module.
65
+ */
66
+ module Enumerable {
67
+ private class ArrayIndex extends int {
68
+ ArrayIndex ( ) { this = any ( DataFlow:: Content:: KnownElementContent c ) .getIndex ( ) .getInt ( ) }
69
+ }
70
+
71
+ private class CompactBlankSummary extends SimpleSummarizedCallable {
72
+ CompactBlankSummary ( ) { this = "compact_blank" }
73
+
74
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
75
+ input = "Argument[self].Element[any]" and
76
+ output = "ReturnValue.Element[?]" and
77
+ preservesValue = true
78
+ }
79
+ }
80
+
81
+ private class ExcludingSummary extends SimpleSummarizedCallable {
82
+ ExcludingSummary ( ) { this = [ "excluding" , "without" ] }
83
+
84
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
85
+ input = "Argument[self].Element[any]" and
86
+ output = "ReturnValue.Element[?]" and
87
+ preservesValue = true
88
+ }
89
+ }
90
+
91
+ private class InOrderOfSummary extends SimpleSummarizedCallable {
92
+ InOrderOfSummary ( ) { this = "in_order_of" }
93
+
94
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
95
+ input = "Argument[self].Element[any]" and
96
+ output = "ReturnValue.Element[?]" and
97
+ preservesValue = true
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Like `Array#push` but doesn't update the receiver.
103
+ */
104
+ private class IncludingSummary extends SimpleSummarizedCallable {
105
+ IncludingSummary ( ) { this = "including" }
106
+
107
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
108
+ (
109
+ exists ( ArrayIndex i |
110
+ input = "Argument[self].Element[" + i + "]" and
111
+ output = "ReturnValue.Element[" + i + "]"
112
+ )
113
+ or
114
+ input = "Argument[self].Element[?]" and
115
+ output = "ReturnValue.Element[?]"
116
+ or
117
+ exists ( int i | i in [ 0 .. ( mc .getNumberOfArguments ( ) - 1 ) ] |
118
+ input = "Argument[" + i + "]" and
119
+ output = "ReturnValue.Element[?]"
120
+ )
121
+ ) and
122
+ preservesValue = true
123
+ }
124
+ }
125
+ // TODO: index_by, index_with, pick, pluck (they require Hash dataflow)
126
+ }
127
+ }
128
+
129
+ /**
130
+ * `ActiveSupport::Logger`
131
+ */
132
+ module Logger {
133
+ private class ActiveSupportLoggerInstantiation extends StdlibLogger:: LoggerInstantiation {
134
+ ActiveSupportLoggerInstantiation ( ) {
135
+ this =
136
+ API:: getTopLevelMember ( "ActiveSupport" )
137
+ .getMember ( [ "Logger" , "TaggedLogging" ] )
138
+ .getAnInstantiation ( )
139
+ }
35
140
}
36
141
}
37
142
}
0 commit comments