Skip to content

Commit 51a25e4

Browse files
committed
Python: Use shared prettyExpr in ConceptsTest.qll
This required quite some changes in the expected output. I think it's much more clear what the selected nodes are now 👍 (but it was a bit boring work to fix this up)
1 parent 1af6d97 commit 51a25e4

File tree

12 files changed

+77
-89
lines changed

12 files changed

+77
-89
lines changed

python/ql/test/experimental/meta/ConceptsTest.qll

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,7 @@ import python
22
import semmle.python.dataflow.new.DataFlow
33
import semmle.python.Concepts
44
import TestUtilities.InlineExpectationsTest
5-
6-
string value_from_expr(Expr e) {
7-
// TODO: This one is starting to look like `repr` predicate from TestTaintLib
8-
result =
9-
e.(StrConst).getPrefix() + e.(StrConst).getText() +
10-
e.(StrConst).getPrefix().regexpReplaceAll("[a-zA-Z]+", "")
11-
or
12-
result = e.(Name).getId()
13-
or
14-
not e instanceof StrConst and
15-
not e instanceof Name and
16-
result = e.toString()
17-
}
5+
import experimental.dataflow.TestUtil.PrintNode
186

197
class SystemCommandExecutionTest extends InlineExpectationsTest {
208
SystemCommandExecutionTest() { this = "SystemCommandExecutionTest" }
@@ -27,7 +15,7 @@ class SystemCommandExecutionTest extends InlineExpectationsTest {
2715
command = sce.getCommand() and
2816
location = command.getLocation() and
2917
element = command.toString() and
30-
value = value_from_expr(command.asExpr()) and
18+
value = prettyExpr(command.asExpr()) and
3119
tag = "getCommand"
3220
)
3321
}
@@ -46,7 +34,7 @@ class DecodingTest extends InlineExpectationsTest {
4634
exists(DataFlow::Node data |
4735
location = data.getLocation() and
4836
element = data.toString() and
49-
value = value_from_expr(data.asExpr()) and
37+
value = prettyExpr(data.asExpr()) and
5038
(
5139
data = d.getAnInput() and
5240
tag = "decodeInput"
@@ -84,7 +72,7 @@ class EncodingTest extends InlineExpectationsTest {
8472
exists(DataFlow::Node data |
8573
location = data.getLocation() and
8674
element = data.toString() and
87-
value = value_from_expr(data.asExpr()) and
75+
value = prettyExpr(data.asExpr()) and
8876
(
8977
data = e.getAnInput() and
9078
tag = "encodeInput"
@@ -117,7 +105,7 @@ class CodeExecutionTest extends InlineExpectationsTest {
117105
code = ce.getCode() and
118106
location = code.getLocation() and
119107
element = code.toString() and
120-
value = value_from_expr(code.asExpr()) and
108+
value = prettyExpr(code.asExpr()) and
121109
tag = "getCode"
122110
)
123111
}
@@ -135,7 +123,7 @@ class SqlExecutionTest extends InlineExpectationsTest {
135123
sql = e.getSql() and
136124
location = e.getLocation() and
137125
element = sql.toString() and
138-
value = value_from_expr(sql.asExpr()) and
126+
value = prettyExpr(sql.asExpr()) and
139127
tag = "getSql"
140128
)
141129
}
@@ -218,7 +206,7 @@ class HttpServerHttpResponseTest extends InlineExpectationsTest {
218206
exists(HTTP::Server::HttpResponse response |
219207
location = response.getLocation() and
220208
element = response.toString() and
221-
value = value_from_expr(response.getBody().asExpr()) and
209+
value = prettyExpr(response.getBody().asExpr()) and
222210
tag = "responseBody"
223211
)
224212
or
@@ -257,7 +245,7 @@ class HttpServerHttpRedirectResponseTest extends InlineExpectationsTest {
257245
exists(HTTP::Server::HttpRedirectResponse redirect |
258246
location = redirect.getLocation() and
259247
element = redirect.toString() and
260-
value = value_from_expr(redirect.getRedirectLocation().asExpr()) and
248+
value = prettyExpr(redirect.getRedirectLocation().asExpr()) and
261249
tag = "redirectLocation"
262250
)
263251
)
@@ -275,7 +263,7 @@ class FileSystemAccessTest extends InlineExpectationsTest {
275263
path = a.getAPathArgument() and
276264
location = a.getLocation() and
277265
element = path.toString() and
278-
value = value_from_expr(path.asExpr()) and
266+
value = prettyExpr(path.asExpr()) and
279267
tag = "getAPathArgument"
280268
)
281269
}
@@ -309,7 +297,7 @@ class SafeAccessCheckTest extends InlineExpectationsTest {
309297
location = c.getLocation() and
310298
(
311299
element = checks.toString() and
312-
value = value_from_expr(checks.asExpr()) and
300+
value = prettyExpr(checks.asExpr()) and
313301
tag = "checks"
314302
or
315303
element = branch.toString() and
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import dill
22

3-
dill.loads(payload) # $decodeInput=payload decodeOutput=Attribute() decodeFormat=dill decodeMayExecuteInput
3+
dill.loads(payload) # $decodeInput=payload decodeOutput=dill.loads(..) decodeFormat=dill decodeMayExecuteInput

python/ql/test/library-tests/frameworks/django-v2-v3/response_test.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,28 +74,28 @@ def get_redirect_url(self, foo): # $ requestHandler routedParameter=foo
7474

7575
# Ensure that simple subclasses are still vuln to XSS
7676
def xss__not_found(request):
77-
return HttpResponseNotFound(request.GET.get("name")) # $HttpResponse mimetype=text/html responseBody=Attribute()
77+
return HttpResponseNotFound(request.GET.get("name")) # $HttpResponse mimetype=text/html responseBody=request.GET.get(..)
7878

7979
# Ensure we still have an XSS sink when manually setting the content_type to HTML
8080
def xss__manual_response_type(request):
81-
return HttpResponse(request.GET.get("name"), content_type="text/html; charset=utf-8") # $HttpResponse mimetype=text/html responseBody=Attribute()
81+
return HttpResponse(request.GET.get("name"), content_type="text/html; charset=utf-8") # $HttpResponse mimetype=text/html responseBody=request.GET.get(..)
8282

8383
def xss__write(request):
8484
response = HttpResponse() # $HttpResponse mimetype=text/html
85-
response.write(request.GET.get("name")) # $HttpResponse mimetype=text/html responseBody=Attribute()
85+
response.write(request.GET.get("name")) # $HttpResponse mimetype=text/html responseBody=request.GET.get(..)
8686

8787
# This is safe but probably a bug if the argument to `write` is not a result of `json.dumps` or similar.
8888
def safe__write_json(request):
8989
response = JsonResponse() # $HttpResponse mimetype=application/json
90-
response.write(request.GET.get("name")) # $HttpResponse mimetype=application/json responseBody=Attribute()
90+
response.write(request.GET.get("name")) # $HttpResponse mimetype=application/json responseBody=request.GET.get(..)
9191

9292
# Ensure manual subclasses are vulnerable
9393
class CustomResponse(HttpResponse):
9494
def __init__(self, banner, content, *args, **kwargs):
9595
super().__init__(content, *args, content_type="text/html", **kwargs)
9696

9797
def xss__custom_response(request):
98-
return CustomResponse("ACME Responses", request.GET("name")) # $HttpResponse MISSING: mimetype=text/html responseBody=Attribute() SPURIOUS: responseBody="ACME Responses"
98+
return CustomResponse("ACME Responses", request.GET("name")) # $HttpResponse MISSING: mimetype=text/html responseBody=request.GET.get(..) SPURIOUS: responseBody="ACME Responses"
9999

100100
class CustomJsonResponse(JsonResponse):
101101
def __init__(self, banner, content, *args, **kwargs):

python/ql/test/library-tests/frameworks/django-v2-v3/testproj/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from pathlib import Path
1414

1515
# Build paths inside the project like this: BASE_DIR / 'subdir'.
16-
BASE_DIR = Path(__file__).resolve().parent.parent #$ getAPathArgument=Path()
16+
BASE_DIR = Path(__file__).resolve().parent.parent #$ getAPathArgument=Path(..)
1717

1818

1919
# Quick-start development settings - unsuitable for production

python/ql/test/library-tests/frameworks/idna/taint_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ def test_idna():
55
tb = TAINTED_BYTES
66

77
ensure_tainted(
8-
idna.encode(ts), # $ tainted encodeInput=ts encodeOutput=Attribute() encodeFormat=IDNA
9-
idna.encode(s=ts), # $ tainted encodeInput=ts encodeOutput=Attribute() encodeFormat=IDNA
8+
idna.encode(ts), # $ tainted encodeInput=ts encodeOutput=idna.encode(..) encodeFormat=IDNA
9+
idna.encode(s=ts), # $ tainted encodeInput=ts encodeOutput=idna.encode(..) encodeFormat=IDNA
1010

11-
idna.decode(tb), # $ tainted decodeInput=tb decodeOutput=Attribute() decodeFormat=IDNA
12-
idna.decode(s=tb), # $ tainted decodeInput=tb decodeOutput=Attribute() decodeFormat=IDNA
11+
idna.decode(tb), # $ tainted decodeInput=tb decodeOutput=idna.decode(..) decodeFormat=IDNA
12+
idna.decode(s=tb), # $ tainted decodeInput=tb decodeOutput=idna.decode(..) decodeFormat=IDNA
1313
)

python/ql/test/library-tests/frameworks/simplejson/taint_test.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ def test():
55
ts = TAINTED_STRING
66
tainted_obj = {"foo": ts}
77

8-
encoded = simplejson.dumps(tainted_obj) # $ encodeOutput=Attribute() encodeFormat=JSON encodeInput=tainted_obj
8+
encoded = simplejson.dumps(tainted_obj) # $ encodeOutput=simplejson.dumps(..) encodeFormat=JSON encodeInput=tainted_obj
99

1010
ensure_tainted(
1111
encoded, # $ tainted
12-
simplejson.dumps(tainted_obj), # $ tainted encodeOutput=Attribute() encodeFormat=JSON encodeInput=tainted_obj
13-
simplejson.dumps(obj=tainted_obj), # $ tainted encodeOutput=Attribute() encodeFormat=JSON encodeInput=tainted_obj
14-
simplejson.loads(encoded), # $ tainted decodeOutput=Attribute() decodeFormat=JSON decodeInput=encoded
15-
simplejson.loads(s=encoded), # $ tainted decodeOutput=Attribute() decodeFormat=JSON decodeInput=encoded
12+
simplejson.dumps(tainted_obj), # $ tainted encodeOutput=simplejson.dumps(..) encodeFormat=JSON encodeInput=tainted_obj
13+
simplejson.dumps(obj=tainted_obj), # $ tainted encodeOutput=simplejson.dumps(..) encodeFormat=JSON encodeInput=tainted_obj
14+
simplejson.loads(encoded), # $ tainted decodeOutput=simplejson.loads(..) decodeFormat=JSON decodeInput=encoded
15+
simplejson.loads(s=encoded), # $ tainted decodeOutput=simplejson.loads(..) decodeFormat=JSON decodeInput=encoded
1616
)
1717

1818
# load/dump with file-like
@@ -22,7 +22,7 @@ def test():
2222
tainted_filelike.seek(0)
2323
ensure_tainted(
2424
tainted_filelike, # $ MISSING: tainted
25-
simplejson.load(tainted_filelike), # $ decodeOutput=Attribute() decodeFormat=JSON decodeInput=tainted_filelike MISSING: tainted
25+
simplejson.load(tainted_filelike), # $ decodeOutput=simplejson.load(..) decodeFormat=JSON decodeInput=tainted_filelike MISSING: tainted
2626
)
2727

2828
# load/dump with file-like using keyword-args
@@ -32,7 +32,7 @@ def test():
3232
tainted_filelike.seek(0)
3333
ensure_tainted(
3434
tainted_filelike, # $ MISSING: tainted
35-
simplejson.load(fp=tainted_filelike), # $ decodeOutput=Attribute() decodeFormat=JSON decodeInput=tainted_filelike MISSING: tainted
35+
simplejson.load(fp=tainted_filelike), # $ decodeOutput=simplejson.load(..) decodeFormat=JSON decodeInput=tainted_filelike MISSING: tainted
3636
)
3737

3838
# To make things runable
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import base64
22

33
# TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_string.py
4-
base64.a85decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Ascii85
5-
base64.b85decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base85
6-
base64.decodebytes(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64
4+
base64.a85decode(payload) # $ decodeInput=payload decodeOutput=base64.a85decode(..) decodeFormat=Ascii85
5+
base64.b85decode(payload) # $ decodeInput=payload decodeOutput=base64.b85decode(..) decodeFormat=Base85
6+
base64.decodebytes(payload) # $ decodeInput=payload decodeOutput=base64.decodebytes(..) decodeFormat=Base64
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import base64
22

33
# TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_string.py
4-
base64.a85encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Ascii85
5-
base64.b85encode(bs)# $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base85
6-
base64.encodebytes(bs)# $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64
4+
base64.a85encode(bs) # $ encodeInput=bs encodeOutput=base64.a85encode(..) encodeFormat=Ascii85
5+
base64.b85encode(bs)# $ encodeInput=bs encodeOutput=base64.b85encode(..) encodeFormat=Base85
6+
base64.encodebytes(bs)# $ encodeInput=bs encodeOutput=base64.encodebytes(..) encodeFormat=Base64

python/ql/test/library-tests/frameworks/stdlib/Decoding.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import marshal
33
import base64
44

5-
pickle.loads(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=pickle decodeMayExecuteInput
6-
marshal.loads(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=marshal decodeMayExecuteInput
5+
pickle.loads(payload) # $ decodeInput=payload decodeOutput=pickle.loads(..) decodeFormat=pickle decodeMayExecuteInput
6+
marshal.loads(payload) # $ decodeInput=payload decodeOutput=marshal.loads(..) decodeFormat=marshal decodeMayExecuteInput
77

88
# TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py
9-
base64.b64decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64
10-
base64.standard_b64decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64
11-
base64.urlsafe_b64decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64
12-
base64.b32decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base32
13-
base64.b16decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base16
9+
base64.b64decode(payload) # $ decodeInput=payload decodeOutput=base64.b64decode(..) decodeFormat=Base64
10+
base64.standard_b64decode(payload) # $ decodeInput=payload decodeOutput=base64.standard_b64decode(..) decodeFormat=Base64
11+
base64.urlsafe_b64decode(payload) # $ decodeInput=payload decodeOutput=base64.urlsafe_b64decode(..) decodeFormat=Base64
12+
base64.b32decode(payload) # $ decodeInput=payload decodeOutput=base64.b32decode(..) decodeFormat=Base32
13+
base64.b16decode(payload) # $ decodeInput=payload decodeOutput=base64.b16decode(..) decodeFormat=Base16
1414
# deprecated since Python 3.1, but still works
15-
base64.decodestring(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64
15+
base64.decodestring(payload) # $ decodeInput=payload decodeOutput=base64.decodestring(..) decodeFormat=Base64

python/ql/test/library-tests/frameworks/stdlib/Encoding.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import marshal
33
import base64
44

5-
pickle.dumps(obj) # $ MISSING: encodeInput=obj encodeOutput=Attribute() encodeFormat=pickle encodeMayExecuteInput
6-
marshal.dumps(obj) # $ MISSING: encodeInput=obj encodeOutput=Attribute() encodeFormat=marshal encodeMayExecuteInput
5+
pickle.dumps(obj) # $ MISSING: encodeInput=obj encodeOutput=pickle.dumps(..) encodeFormat=pickle encodeMayExecuteInput
6+
marshal.dumps(obj) # $ MISSING: encodeInput=obj encodeOutput=marshal.dumps(..) encodeFormat=marshal encodeMayExecuteInput
77

88
# TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py
9-
base64.b64encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64
10-
base64.standard_b64encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64
11-
base64.urlsafe_b64encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64
12-
base64.b32encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base32
13-
base64.b16encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base16
9+
base64.b64encode(bs) # $ encodeInput=bs encodeOutput=base64.b64encode(..) encodeFormat=Base64
10+
base64.standard_b64encode(bs) # $ encodeInput=bs encodeOutput=base64.standard_b64encode(..) encodeFormat=Base64
11+
base64.urlsafe_b64encode(bs) # $ encodeInput=bs encodeOutput=base64.urlsafe_b64encode(..) encodeFormat=Base64
12+
base64.b32encode(bs) # $ encodeInput=bs encodeOutput=base64.b32encode(..) encodeFormat=Base32
13+
base64.b16encode(bs) # $ encodeInput=bs encodeOutput=base64.b16encode(..) encodeFormat=Base16
1414
# deprecated since Python 3.1, but still works
15-
base64.encodestring(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64
15+
base64.encodestring(bs) # $ encodeInput=bs encodeOutput=base64.encodestring(..) encodeFormat=Base64

0 commit comments

Comments
 (0)