Skip to content

Commit faebaee

Browse files
committed
Python: Use concept tests for XML Parsing
I was loosing my mind from looking through those .expected files Just going to take it one file at time, to make reviewing easier
1 parent 4b03f5c commit faebaee

File tree

4 files changed

+73
-90
lines changed

4 files changed

+73
-90
lines changed

python/ql/test/experimental/library-tests/frameworks/XML/ExperimentalXmlConceptsTests.expected

Whitespace-only changes.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import python
2+
import experimental.semmle.python.Concepts
3+
import experimental.semmle.python.frameworks.Xml
4+
import semmle.python.dataflow.new.DataFlow
5+
import TestUtilities.InlineExpectationsTest
6+
private import semmle.python.dataflow.new.internal.PrintNode
7+
8+
class XmlParsingTest extends InlineExpectationsTest {
9+
XmlParsingTest() { this = "XmlParsingTest" }
10+
11+
override string getARelevantTag() { result in ["input", "vuln"] }
12+
13+
override predicate hasActualResult(Location location, string element, string tag, string value) {
14+
exists(location.getFile().getRelativePath()) and
15+
exists(XML::XMLParsing parsing |
16+
exists(DataFlow::Node input |
17+
input = parsing.getAnInput() and
18+
location = input.getLocation() and
19+
element = input.toString() and
20+
value = prettyNodeForInlineTest(input) and
21+
tag = "input"
22+
)
23+
or
24+
exists(XML::XMLVulnerabilityKind kind |
25+
parsing.vulnerable(kind) and
26+
location = parsing.getLocation() and
27+
element = parsing.toString() and
28+
value = "'" + kind + "'" and
29+
tag = "vuln"
30+
)
31+
)
32+
}
33+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from io import StringIO
2+
import lxml.etree
3+
4+
x = "some xml"
5+
6+
# different parsing methods
7+
lxml.etree.fromstring(x) # $ input=x vuln='XXE'
8+
9+
lxml.etree.fromstringlist([x]) # $ input=List vuln='XXE'
10+
11+
lxml.etree.XML(x) # $ input=x vuln='XXE'
12+
13+
lxml.etree.parse(StringIO(x)).getroot() # $ input=StringIO(..) vuln='XXE'
14+
15+
# With default parsers (nothing changed)
16+
parser = lxml.etree.XMLParser()
17+
lxml.etree.fromstring(x, parser=parser) # $ input=x vuln='XXE'
18+
19+
parser = lxml.etree.get_default_parser()
20+
lxml.etree.fromstring(x, parser=parser) # $ input=x vuln='XXE'
21+
22+
# XXE-safe
23+
parser = lxml.etree.XMLParser(resolve_entities=False)
24+
lxml.etree.fromstring(x, parser=parser) # $ input=x
25+
26+
# XXE-vuln
27+
parser = lxml.etree.XMLParser(resolve_entities=True)
28+
lxml.etree.fromstring(x, parser=parser) # $ input=x vuln='XXE'
29+
30+
# Billion laughs vuln (also XXE)
31+
parser = lxml.etree.XMLParser(huge_tree=True)
32+
lxml.etree.fromstring(x, parser=parser) # $ input=x vuln='Billion Laughs' vuln='Quadratic Blowup' vuln='XXE'
33+
34+
# Billion laughs, but not XXE
35+
parser = lxml.etree.XMLParser(resolve_entities=False, huge_tree=True)
36+
lxml.etree.fromstring(x, parser=parser) # $ input=x vuln='Billion Laughs' vuln='Quadratic Blowup'
37+
38+
# DTD retrival vuln (also XXE)
39+
parser = lxml.etree.XMLParser(load_dtd=True, no_network=False)
40+
lxml.etree.fromstring(x, parser=parser) # $ input=x vuln='DTD retrieval' vuln='XXE'

python/ql/test/experimental/query-tests/Security/CWE-611/lxml_etree.py

Lines changed: 0 additions & 90 deletions
This file was deleted.

0 commit comments

Comments
 (0)