@@ -10,22 +10,65 @@ private import semmle.python.ApiGraphs
1010
1111private module XmlEtree {
1212 /**
13- * A call to `xml.etree.ElementTree.XMLParser`.
13+ * Provides models for `xml.etree` parsers
14+ *
15+ * See
16+ * - https://docs.python.org/3.10/library/xml.etree.elementtree.html#xml.etree.ElementTree.XMLParser
17+ * - https://docs.python.org/3.10/library/xml.etree.elementtree.html#xml.etree.ElementTree.XMLPullParser
1418 */
15- private class XMLEtreeParser extends DataFlow:: CallCfgNode , XML:: XMLParser:: Range {
16- XMLEtreeParser ( ) {
17- this =
18- API:: moduleImport ( "xml" )
19- .getMember ( "etree" )
20- .getMember ( "ElementTree" )
21- .getMember ( "XMLParser" )
22- .getACall ( )
19+ module XMLParser {
20+ /**
21+ * A source of instances of `xml.etree` parsers, extend this class to model new instances.
22+ *
23+ * This can include instantiations of the class, return values from function
24+ * calls, or a special parameter that will be set when functions are called by an external
25+ * library.
26+ *
27+ * Use the predicate `XMLParser::instance()` to get references to instances of `xml.etree` parsers.
28+ */
29+ abstract class InstanceSource extends DataFlow:: LocalSourceNode { }
30+
31+ /** A direct instantiation of `xml.etree` parsers. */
32+ private class ClassInstantiation extends InstanceSource , DataFlow:: CallCfgNode {
33+ ClassInstantiation ( ) {
34+ this =
35+ API:: moduleImport ( "xml" )
36+ .getMember ( "etree" )
37+ .getMember ( "ElementTree" )
38+ .getMember ( "XMLParser" )
39+ .getACall ( )
40+ or
41+ this =
42+ API:: moduleImport ( "xml" )
43+ .getMember ( "etree" )
44+ .getMember ( "ElementTree" )
45+ .getMember ( "XMLPullParser" )
46+ .getACall ( )
47+ }
2348 }
2449
25- override DataFlow:: Node getAnInput ( ) { none ( ) }
50+ /** Gets a reference to an `xml.etree` parser instance. */
51+ private DataFlow:: TypeTrackingNode instance ( DataFlow:: TypeTracker t ) {
52+ t .start ( ) and
53+ result instanceof InstanceSource
54+ or
55+ exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
56+ }
2657
27- override predicate vulnerable ( XML:: XMLVulnerabilityKind kind ) {
28- kind .isBillionLaughs ( ) or kind .isQuadraticBlowup ( )
58+ /** Gets a reference to an `xml.etree` parser instance. */
59+ DataFlow:: Node instance ( ) { instance ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
60+
61+ /**
62+ * A call to the `feed` method of an `xml.etree` parser.
63+ */
64+ private class XMLEtreeParserFeedCall extends DataFlow:: MethodCallNode , XML:: XMLParsing:: Range {
65+ XMLEtreeParserFeedCall ( ) { this .calls ( instance ( ) , "feed" ) }
66+
67+ override DataFlow:: Node getAnInput ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "data" ) ] }
68+
69+ override predicate vulnerable ( XML:: XMLVulnerabilityKind kind ) {
70+ kind .isBillionLaughs ( ) or kind .isQuadraticBlowup ( )
71+ }
2972 }
3073 }
3174
@@ -61,33 +104,8 @@ private module XmlEtree {
61104 }
62105
63106 override predicate vulnerable ( XML:: XMLVulnerabilityKind kind ) {
64- not exists ( this .getArgByName ( "parser" ) ) and
65- ( kind .isBillionLaughs ( ) or kind .isQuadraticBlowup ( ) )
66- or
67- exists ( XML:: XMLParser xmlParser |
68- xmlParser = this .getArgByName ( "parser" ) .getALocalSource ( ) and xmlParser .vulnerable ( kind )
69- )
70- }
71- }
72-
73- /**
74- * A call to the `feed` method of an `xml.etree` parser.
75- */
76- private class XMLEtreeParserFeedCall extends DataFlow:: CallCfgNode , XML:: XMLParsing:: Range {
77- XMLEtreeParserFeedCall ( ) {
78- this =
79- API:: moduleImport ( "xml" )
80- .getMember ( "etree" )
81- .getMember ( "ElementTree" )
82- .getMember ( "XMLParser" )
83- .getReturn ( )
84- .getMember ( "feed" )
85- .getACall ( )
86- }
87-
88- override DataFlow:: Node getAnInput ( ) { result in [ this .getArg ( 0 ) , this .getArgByName ( "data" ) ] }
89-
90- override predicate vulnerable ( XML:: XMLVulnerabilityKind kind ) {
107+ // note: it does not matter what `xml.etree` parser you are using, you cannot
108+ // change the security features anyway :|
91109 kind .isBillionLaughs ( ) or kind .isQuadraticBlowup ( )
92110 }
93111 }
0 commit comments