@@ -16,6 +16,7 @@ import cpp
16
16
import semmle.code.cpp.ir.dataflow.DataFlow
17
17
import DataFlow:: PathGraph
18
18
import semmle.code.cpp.ir.IR
19
+ import semmle.code.cpp.valuenumbering.GlobalValueNumbering
19
20
20
21
/**
21
22
* A flow state representing a possible configuration of an XML object.
@@ -57,42 +58,51 @@ class XercesDOMParserClass extends Class {
57
58
}
58
59
59
60
/**
60
- * Gets a valid flow state for `XercesDOMParser` flow.
61
+ * The `SAXParser` class.
62
+ */
63
+ class SAXParserClass extends Class {
64
+ SAXParserClass ( ) { this .hasName ( "SAXParser" ) }
65
+ }
66
+
67
+ /**
68
+ * Gets a valid flow state for `AbstractDOMParser` or `SAXParser` flow.
61
69
*
62
- * These flow states take the form `XercesDOM -A-B`, where:
70
+ * These flow states take the form `Xerces -A-B`, where:
63
71
* - A is 1 if `setDisableDefaultEntityResolution` is `true`, 0 otherwise.
64
72
* - B is 1 if `setCreateEntityReferenceNodes` is `true`, 0 otherwise.
65
73
*/
66
- predicate encodeXercesDOMFlowState (
74
+ predicate encodeXercesFlowState (
67
75
string flowstate , int disabledDefaultEntityResolution , int createEntityReferenceNodes
68
76
) {
69
- flowstate = "XercesDOM -0-0" and
77
+ flowstate = "Xerces -0-0" and
70
78
disabledDefaultEntityResolution = 0 and
71
79
createEntityReferenceNodes = 0
72
80
or
73
- flowstate = "XercesDOM -0-1" and
81
+ flowstate = "Xerces -0-1" and
74
82
disabledDefaultEntityResolution = 0 and
75
83
createEntityReferenceNodes = 1
76
84
or
77
- flowstate = "XercesDOM -1-0" and
85
+ flowstate = "Xerces -1-0" and
78
86
disabledDefaultEntityResolution = 1 and
79
87
createEntityReferenceNodes = 0
80
88
or
81
- flowstate = "XercesDOM -1-1" and
89
+ flowstate = "Xerces -1-1" and
82
90
disabledDefaultEntityResolution = 1 and
83
91
createEntityReferenceNodes = 1
84
92
}
85
93
86
94
/**
87
- * A flow state representing the configuration of a `XercesDOMParser` object.
95
+ * A flow state representing the configuration of an `AbstractDOMParser` or
96
+ * `SAXParser` object.
88
97
*/
89
- class XercesDOMParserFlowState extends XXEFlowState {
90
- XercesDOMParserFlowState ( ) { encodeXercesDOMFlowState ( this , _, _) }
98
+ class XercesFlowState extends XXEFlowState {
99
+ XercesFlowState ( ) { encodeXercesFlowState ( this , _, _) }
91
100
}
92
101
93
102
/**
94
103
* A flow state transformer for a call to
95
- * `AbstractDOMParser.setDisableDefaultEntityResolution`. Transforms the flow
104
+ * `AbstractDOMParser.setDisableDefaultEntityResolution` or
105
+ * `SAXParser.setDisableDefaultEntityResolution`. Transforms the flow
96
106
* state through the qualifier according to the setting in the parameter.
97
107
*/
98
108
class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
@@ -101,7 +111,10 @@ class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
101
111
DisableDefaultEntityResolutionTranformer ( ) {
102
112
exists ( Call call , Function f |
103
113
call .getTarget ( ) = f and
104
- f .getDeclaringType ( ) instanceof AbstractDOMParserClass and
114
+ (
115
+ f .getDeclaringType ( ) instanceof AbstractDOMParserClass or
116
+ f .getDeclaringType ( ) instanceof SAXParserClass
117
+ ) and
105
118
f .hasName ( "setDisableDefaultEntityResolution" ) and
106
119
this = call .getQualifier ( ) and
107
120
newValue = call .getArgument ( 0 )
@@ -110,13 +123,13 @@ class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
110
123
111
124
final override XXEFlowState transform ( XXEFlowState flowstate ) {
112
125
exists ( int createEntityReferenceNodes |
113
- encodeXercesDOMFlowState ( flowstate , _, createEntityReferenceNodes ) and
126
+ encodeXercesFlowState ( flowstate , _, createEntityReferenceNodes ) and
114
127
(
115
- newValue .getValue ( ) .toInt ( ) = 1 and // true
116
- encodeXercesDOMFlowState ( result , 1 , createEntityReferenceNodes )
128
+ globalValueNumber ( newValue ) . getAnExpr ( ) .getValue ( ) .toInt ( ) = 1 and // true
129
+ encodeXercesFlowState ( result , 1 , createEntityReferenceNodes )
117
130
or
118
- not newValue .getValue ( ) .toInt ( ) = 1 and // false or unknown
119
- encodeXercesDOMFlowState ( result , 0 , createEntityReferenceNodes )
131
+ not globalValueNumber ( newValue ) . getAnExpr ( ) .getValue ( ) .toInt ( ) = 1 and // false or unknown
132
+ encodeXercesFlowState ( result , 0 , createEntityReferenceNodes )
120
133
)
121
134
)
122
135
}
@@ -142,27 +155,31 @@ class CreateEntityReferenceNodesTranformer extends XXEFlowStateTranformer {
142
155
143
156
final override XXEFlowState transform ( XXEFlowState flowstate ) {
144
157
exists ( int disabledDefaultEntityResolution |
145
- encodeXercesDOMFlowState ( flowstate , disabledDefaultEntityResolution , _) and
158
+ encodeXercesFlowState ( flowstate , disabledDefaultEntityResolution , _) and
146
159
(
147
- newValue .getValue ( ) .toInt ( ) = 1 and // true
148
- encodeXercesDOMFlowState ( result , disabledDefaultEntityResolution , 1 )
160
+ globalValueNumber ( newValue ) . getAnExpr ( ) .getValue ( ) .toInt ( ) = 1 and // true
161
+ encodeXercesFlowState ( result , disabledDefaultEntityResolution , 1 )
149
162
or
150
- not newValue .getValue ( ) .toInt ( ) = 1 and // false or unknown
151
- encodeXercesDOMFlowState ( result , disabledDefaultEntityResolution , 0 )
163
+ not globalValueNumber ( newValue ) . getAnExpr ( ) .getValue ( ) .toInt ( ) = 1 and // false or unknown
164
+ encodeXercesFlowState ( result , disabledDefaultEntityResolution , 0 )
152
165
)
153
166
)
154
167
}
155
168
}
156
169
157
170
/**
158
- * The `AbstractDOMParser.parse` method.
171
+ * The `AbstractDOMParser.parse` or `SAXParser.parse` method.
159
172
*/
160
173
class ParseFunction extends Function {
161
- ParseFunction ( ) { this .getClassAndName ( "parse" ) instanceof AbstractDOMParserClass }
174
+ ParseFunction ( ) {
175
+ this .getClassAndName ( "parse" ) instanceof AbstractDOMParserClass or
176
+ this .getClassAndName ( "parse" ) instanceof SAXParserClass
177
+ }
162
178
}
163
179
164
180
/**
165
- * The `createLSParser` function that returns a newly created `LSParser` object.
181
+ * The `createLSParser` function that returns a newly created `DOMLSParser`
182
+ * object.
166
183
*/
167
184
class CreateLSParser extends Function {
168
185
CreateLSParser ( ) {
@@ -184,14 +201,23 @@ class XXEConfiguration extends DataFlow::Configuration {
184
201
call .getStaticCallTarget ( ) = any ( XercesDOMParserClass c ) .getAConstructor ( ) and
185
202
node .asInstruction ( ) .( WriteSideEffectInstruction ) .getDestinationAddress ( ) =
186
203
call .getThisArgument ( ) and
187
- encodeXercesDOMFlowState ( flowstate , 0 , 1 ) // default configuration
204
+ encodeXercesFlowState ( flowstate , 0 , 1 ) // default configuration
188
205
)
189
206
or
190
207
// source is the result of a call to `createLSParser`.
191
208
exists ( Call call |
192
209
call .getTarget ( ) instanceof CreateLSParser and
193
210
call = node .asExpr ( ) and
194
- encodeXercesDOMFlowState ( flowstate , 0 , 1 ) // default configuration
211
+ encodeXercesFlowState ( flowstate , 0 , 1 ) // default configuration
212
+ )
213
+ or
214
+ // source is the write on `this` of a call to the `SAXParser`
215
+ // constructor.
216
+ exists ( CallInstruction call |
217
+ call .getStaticCallTarget ( ) = any ( SAXParserClass c ) .getAConstructor ( ) and
218
+ node .asInstruction ( ) .( WriteSideEffectInstruction ) .getDestinationAddress ( ) =
219
+ call .getThisArgument ( ) and
220
+ encodeXercesFlowState ( flowstate , 0 , 1 ) // default configuration
195
221
)
196
222
}
197
223
@@ -201,8 +227,8 @@ class XXEConfiguration extends DataFlow::Configuration {
201
227
call .getTarget ( ) instanceof ParseFunction and
202
228
call .getQualifier ( ) = node .asConvertedExpr ( )
203
229
) and
204
- flowstate instanceof XercesDOMParserFlowState and
205
- not encodeXercesDOMFlowState ( flowstate , 1 , 1 ) // safe configuration
230
+ flowstate instanceof XercesFlowState and
231
+ not encodeXercesFlowState ( flowstate , 1 , 1 ) // safe configuration
206
232
}
207
233
208
234
override predicate isAdditionalFlowStep (
0 commit comments