@@ -16,6 +16,7 @@ import cpp
1616import semmle.code.cpp.ir.dataflow.DataFlow
1717import DataFlow:: PathGraph
1818import semmle.code.cpp.ir.IR
19+ import semmle.code.cpp.valuenumbering.GlobalValueNumbering
1920
2021/**
2122 * A flow state representing a possible configuration of an XML object.
@@ -57,42 +58,51 @@ class XercesDOMParserClass extends Class {
5758}
5859
5960/**
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.
6169 *
62- * These flow states take the form `XercesDOM -A-B`, where:
70+ * These flow states take the form `Xerces -A-B`, where:
6371 * - A is 1 if `setDisableDefaultEntityResolution` is `true`, 0 otherwise.
6472 * - B is 1 if `setCreateEntityReferenceNodes` is `true`, 0 otherwise.
6573 */
66- predicate encodeXercesDOMFlowState (
74+ predicate encodeXercesFlowState (
6775 string flowstate , int disabledDefaultEntityResolution , int createEntityReferenceNodes
6876) {
69- flowstate = "XercesDOM -0-0" and
77+ flowstate = "Xerces -0-0" and
7078 disabledDefaultEntityResolution = 0 and
7179 createEntityReferenceNodes = 0
7280 or
73- flowstate = "XercesDOM -0-1" and
81+ flowstate = "Xerces -0-1" and
7482 disabledDefaultEntityResolution = 0 and
7583 createEntityReferenceNodes = 1
7684 or
77- flowstate = "XercesDOM -1-0" and
85+ flowstate = "Xerces -1-0" and
7886 disabledDefaultEntityResolution = 1 and
7987 createEntityReferenceNodes = 0
8088 or
81- flowstate = "XercesDOM -1-1" and
89+ flowstate = "Xerces -1-1" and
8290 disabledDefaultEntityResolution = 1 and
8391 createEntityReferenceNodes = 1
8492}
8593
8694/**
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.
8897 */
89- class XercesDOMParserFlowState extends XXEFlowState {
90- XercesDOMParserFlowState ( ) { encodeXercesDOMFlowState ( this , _, _) }
98+ class XercesFlowState extends XXEFlowState {
99+ XercesFlowState ( ) { encodeXercesFlowState ( this , _, _) }
91100}
92101
93102/**
94103 * A flow state transformer for a call to
95- * `AbstractDOMParser.setDisableDefaultEntityResolution`. Transforms the flow
104+ * `AbstractDOMParser.setDisableDefaultEntityResolution` or
105+ * `SAXParser.setDisableDefaultEntityResolution`. Transforms the flow
96106 * state through the qualifier according to the setting in the parameter.
97107 */
98108class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
@@ -101,7 +111,10 @@ class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
101111 DisableDefaultEntityResolutionTranformer ( ) {
102112 exists ( Call call , Function f |
103113 call .getTarget ( ) = f and
104- f .getDeclaringType ( ) instanceof AbstractDOMParserClass and
114+ (
115+ f .getDeclaringType ( ) instanceof AbstractDOMParserClass or
116+ f .getDeclaringType ( ) instanceof SAXParserClass
117+ ) and
105118 f .hasName ( "setDisableDefaultEntityResolution" ) and
106119 this = call .getQualifier ( ) and
107120 newValue = call .getArgument ( 0 )
@@ -110,13 +123,13 @@ class DisableDefaultEntityResolutionTranformer extends XXEFlowStateTranformer {
110123
111124 final override XXEFlowState transform ( XXEFlowState flowstate ) {
112125 exists ( int createEntityReferenceNodes |
113- encodeXercesDOMFlowState ( flowstate , _, createEntityReferenceNodes ) and
126+ encodeXercesFlowState ( flowstate , _, createEntityReferenceNodes ) and
114127 (
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 )
117130 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 )
120133 )
121134 )
122135 }
@@ -142,27 +155,31 @@ class CreateEntityReferenceNodesTranformer extends XXEFlowStateTranformer {
142155
143156 final override XXEFlowState transform ( XXEFlowState flowstate ) {
144157 exists ( int disabledDefaultEntityResolution |
145- encodeXercesDOMFlowState ( flowstate , disabledDefaultEntityResolution , _) and
158+ encodeXercesFlowState ( flowstate , disabledDefaultEntityResolution , _) and
146159 (
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 )
149162 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 )
152165 )
153166 )
154167 }
155168}
156169
157170/**
158- * The `AbstractDOMParser.parse` method.
171+ * The `AbstractDOMParser.parse` or `SAXParser.parse` method.
159172 */
160173class 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+ }
162178}
163179
164180/**
165- * The `createLSParser` function that returns a newly created `LSParser` object.
181+ * The `createLSParser` function that returns a newly created `DOMLSParser`
182+ * object.
166183 */
167184class CreateLSParser extends Function {
168185 CreateLSParser ( ) {
@@ -184,14 +201,23 @@ class XXEConfiguration extends DataFlow::Configuration {
184201 call .getStaticCallTarget ( ) = any ( XercesDOMParserClass c ) .getAConstructor ( ) and
185202 node .asInstruction ( ) .( WriteSideEffectInstruction ) .getDestinationAddress ( ) =
186203 call .getThisArgument ( ) and
187- encodeXercesDOMFlowState ( flowstate , 0 , 1 ) // default configuration
204+ encodeXercesFlowState ( flowstate , 0 , 1 ) // default configuration
188205 )
189206 or
190207 // source is the result of a call to `createLSParser`.
191208 exists ( Call call |
192209 call .getTarget ( ) instanceof CreateLSParser and
193210 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
195221 )
196222 }
197223
@@ -201,8 +227,8 @@ class XXEConfiguration extends DataFlow::Configuration {
201227 call .getTarget ( ) instanceof ParseFunction and
202228 call .getQualifier ( ) = node .asConvertedExpr ( )
203229 ) 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
206232 }
207233
208234 override predicate isAdditionalFlowStep (
0 commit comments