Merge branch 'master' into objectapi-to-valueapi-expectedmappingforformatstring

This commit is contained in:
Rebecca Valentine
2020-03-10 07:51:48 -07:00
591 changed files with 18712 additions and 6877 deletions

View File

@@ -1,2 +1 @@
semmle-extractor-options: --lang=2 --max-import-depth=4
optimize: true

View File

@@ -1,2 +1,2 @@
| TruncatedDivision_test.py:8:12:8:16 | BinaryExpr | Result of division may be truncated as its $@ and $@ arguments may both be integers. | TruncatedDivision_test.py:8:12:8:12 | TruncatedDivision_test.py:8 | left | TruncatedDivision_test.py:8:16:8:16 | TruncatedDivision_test.py:8 | right |
| TruncatedDivision_test.py:11:12:11:40 | BinaryExpr | Result of division may be truncated as its $@ and $@ arguments may both be integers. | TruncatedDivision_test.py:2:12:2:12 | TruncatedDivision_test.py:2 | left | TruncatedDivision_test.py:5:12:5:12 | TruncatedDivision_test.py:5 | right |
| TruncatedDivision_test.py:65:7:65:11 | BinaryExpr | Result of division may be truncated as its $@ and $@ arguments may both be integers. | TruncatedDivision_test.py:65:7:65:7 | TruncatedDivision_test.py:65 | left | TruncatedDivision_test.py:65:11:65:11 | TruncatedDivision_test.py:65 | right |
| TruncatedDivision_test.py:72:7:72:35 | BinaryExpr | Result of division may be truncated as its $@ and $@ arguments may both be integers. | TruncatedDivision_test.py:25:12:25:12 | TruncatedDivision_test.py:25 | left | TruncatedDivision_test.py:28:12:28:12 | TruncatedDivision_test.py:28 | right |

View File

@@ -1,24 +1,88 @@
#### TruncatedDivision.ql
# NOTE: The following test case will only work under Python 2.
# Truncated division occurs when two integers are divided. This causes the
# fractional part, if there is one, to be discared. So for example, `2 / 3` will
# evaluate to `0` instead of `0.666...`.
## Negative Cases
# This case is good, and is a minimal obvious case that should be good. It
# SHOULD NOT be found by the query.
print(3.0 / 2.0)
# This case is good, because it explicitly converts the possibly-truncated
# value to an integer. It SHOULD NOT be found by the query.
def return_three():
return 3
def return_two():
return 2
def f1():
return 3 / 2
print(int(return_three() / return_two()))
def f2():
return return_three() / return_two()
def f3(x):
# These cases are good, because `halve` checks the type, and if the type would
# truncate, it explicitly converts to a float first before doing the division.
# These SHOULD NOT be found by the query.
def halve(x):
if isinstance(x, float):
return x / 2
else:
return (1.0 * x) / 2
def f4():
do_stuff(f3(1))
do_stuff(f3(1.0))
print(halve(1))
print(halve(1.0))
def f5():
return int(return_three() / return_two())
# This case is good, because the sum is `3.0`, which is a float, and will not
# truncate. This case SHOULD NOT be found by the query.
print(average([1.0, 2.0]))
## Positive Cases
# This case is bad, and is a minimal obvious case that should be bad. It
# SHOULD be found by the query.
print(3 / 2)
# This case is bad. It uses indirect returns of integers through function calls
# to produce the problem. I
print(return_three() / return_two())
# This case is bad, because the sum is `3`, which is an integer, and will
# truncate when divided by the length `2`. This case SHOULD be found by the
# query.
# NOTE (2020-02-20):
# The current version of the Value/pointsTo API doesn't permit this detection,
# unfortunately, but we preserve this example in the hopes that future
# versions will catch it. That will necessitate changing the expected results.
def average(l):
return sum(l) / len(l)
print(average([1,2]))

View File

@@ -1 +1,2 @@
| UseofApply.py:19:3:19:17 | ControlFlowNode for apply() | Call to the obsolete builtin function 'apply'. |
| expressions_test.py:3:5:3:21 | ControlFlowNode for apply() | Call to the obsolete builtin function 'apply'. |

View File

@@ -0,0 +1,30 @@
#### UseofApply.ql
# Use of the builtin function `apply` is generally considered bad now that the
# ability to destructure lists of arguments is possible, but we should not flag
# cases where the function is merely named `apply` rather than being the actual
# builtin `apply` function.
def useofapply():
def foo():
pass
# Positive Cases
# This use of `apply` is a reference to the builtin function and so SHOULD be
# caught by the query.
apply(foo, [1])
# Negative Cases
# This use of `apply` is a reference to the locally defined function inside of
# `local`, and so SHOULD NOT be caught by the query.
def local():
def apply(f):
pass
apply(foo)([1])

View File

@@ -1 +1 @@
| expressions_test.py:6:12:6:18 | ControlFlowNode for input() | The unsafe built-in function 'input' is used. |
| expressions_test.py:6:12:6:18 | ControlFlowNode for input() | The unsafe built-in function 'input' is used in Python 2. |

View File

@@ -1,2 +1 @@
semmle-extractor-options: --lang=3 -p ../../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --lang=3 --max-import-depth=4
optimize: true

View File

@@ -1,9 +1,9 @@
| test.py:11 | extended_unpacking | first | externally controlled string |
| test.py:11 | extended_unpacking | last | externally controlled string |
| test.py:11 | extended_unpacking | rest | [externally controlled string] |
| test.py:16 | also_allowed | a | [externally controlled string] |
| test.py:11 | extended_unpacking | first | NO TAINT |
| test.py:11 | extended_unpacking | last | NO TAINT |
| test.py:11 | extended_unpacking | rest | NO TAINT |
| test.py:16 | also_allowed | a | NO TAINT |
| test.py:24 | also_allowed | b | NO TAINT |
| test.py:24 | also_allowed | c | NO TAINT |
| test.py:31 | nested | x | externally controlled string |
| test.py:31 | nested | xs | [externally controlled string] |
| test.py:31 | nested | ys | [externally controlled string] |
| test.py:31 | nested | x | NO TAINT |
| test.py:31 | nested | xs | NO TAINT |
| test.py:31 | nested | ys | NO TAINT |

View File

@@ -0,0 +1,30 @@
#### UseofApply.ql
# Use of the builtin function `apply` is generally considered bad now that the
# ability to destructure lists of arguments is possible, but we should not flag
# cases where the function is merely named `apply` rather than being the actual
# builtin `apply` function.
def useofapply():
def foo():
pass
# Positive Cases
# This use of `apply` is a reference to the builtin function and so SHOULD be
# caught by the query.
apply(foo, [1])
# Negative Cases
# This use of `apply` is a reference to the locally defined function inside of
# `local`, and so SHOULD NOT be caught by the query.
def local():
def apply(f):
pass
apply(foo)([1])

View File

@@ -0,0 +1 @@
Expressions/UseofApply.ql

View File

@@ -0,0 +1,7 @@
123456789
223456789
323456789
423456789
5234567ø9
623456789
723456789

View File

@@ -0,0 +1 @@
Imports/EncodingError.ql

View File

@@ -0,0 +1 @@
| bad_encoding.py:11:19:11:19 | Encoding Error | 'utf-8' codec can't decode byte 0x82 in position 82: invalid start byte |

View File

@@ -0,0 +1 @@
Imports/EncodingError.ql

View File

@@ -0,0 +1 @@
| nonsense.py:1:2:1:2 | Syntax Error | Syntax Error (in Python 3.5). |

View File

@@ -0,0 +1 @@
Imports/SyntaxError.ql

View File

@@ -0,0 +1,12 @@
"""Multi-line docstring
"""
# encoding:shift-jis
def f():
print "Python <20>̊J<CC8A><4A><EFBFBD>́A1990 <20>N<EFBFBD><4E><EFBFBD><EFBFBD><EB82A9><EFBFBD>J<EFBFBD>n<EFBFBD><6E><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD>"
"""

View File

@@ -0,0 +1,37 @@
`Twas brillig, and the slithy toves
Did gyre and gimble in the wabe:
All mimsy were the borogoves,
And the mome raths outgrabe.
"Beware the Jabberwock, my son!
The jaws that bite, the claws that catch!
Beware the Jubjub bird, and shun
The frumious Bandersnatch!"
He took his vorpal sword in hand:
Long time the manxome foe he sought --
So rested he by the Tumtum tree,
And stood awhile in thought.
And, as in uffish thought he stood,
The Jabberwock, with eyes of flame,
Came whiffling through the tulgey wood,
And burbled as it came!
One, two! One, two! And through and through
The vorpal blade went snicker-snack!
He left it dead, and with its head
He went galumphing back.
"And, has thou slain the Jabberwock?
Come to my arms, my beamish boy!
O frabjous day! Callooh! Callay!'
He chortled in his joy.
`Twas brillig, and the slithy toves
Did gyre and gimble in the wabe;
All mimsy were the borogoves,
And the mome raths outgrabe.

View File

@@ -0,0 +1 @@
print "Hello World"

View File

@@ -0,0 +1 @@
This directory contains tests for [experimental](../../../../docs/experimental.md) CodeQL queries and libraries.

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=4
optimize: true

View File

@@ -0,0 +1,3 @@
| test.py:5:7:5:9 | ControlFlowNode for foo | int 42 |
| test.py:11:11:11:13 | ControlFlowNode for foo | int 1 |
| test.py:17:11:17:13 | ControlFlowNode for foo | <MISSING pointsTo()> |

View File

@@ -0,0 +1,10 @@
import python
from NameNode name, CallNode call, string debug
where
call.getAnArg() = name and
call.getFunction().(NameNode).getId() = "check" and
if exists(name.pointsTo())
then debug = name.pointsTo().toString()
else debug = "<MISSING pointsTo()>"
select name, debug

View File

@@ -0,0 +1 @@
semmle-extractor-options: --max-import-depth=1 --lang=3

View File

@@ -0,0 +1,17 @@
# Only a problem in Python 3
from urllib.parse import urlsplit
foo = 42
check(foo)
def func(url):
parts = urlsplit(url)
foo = 1
check(foo)
if parts.path: # using `urlsplit(url).path` here is equivalent
return # using `pass` here instead makes points-to work
foo = 2
check(foo) # no points-to information

View File

@@ -0,0 +1 @@
| test.py:5:7:5:13 | ControlFlowNode for PATTERN | <MISSING pointsTo()> |

View File

@@ -0,0 +1,10 @@
import python
from NameNode name, CallNode call, string debug
where
call.getAnArg() = name and
call.getFunction().(NameNode).getId() = "check" and
if exists(name.pointsTo())
then debug = name.pointsTo().toString()
else debug = "<MISSING pointsTo()>"
select name, debug

View File

@@ -0,0 +1,5 @@
import re
PATTERN = re.compile("a|b")
check(PATTERN)

View File

@@ -1 +0,0 @@
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: -R .
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=3
optimize: true

View File

@@ -26,9 +26,6 @@
| Taint [externally controlled string] | test.py:29 | test.py:29:9:29:25 | Subscript | | --> | Taint [externally controlled string] | test.py:32 | test.py:32:16:32:16 | c | |
| Taint [externally controlled string] | test.py:30 | test.py:30:9:30:20 | tainted_list | | --> | Taint [externally controlled string] | test.py:30 | test.py:30:9:30:27 | Attribute() | |
| Taint [externally controlled string] | test.py:30 | test.py:30:9:30:27 | Attribute() | | --> | Taint [externally controlled string] | test.py:32 | test.py:32:19:32:19 | d | |
| Taint [externally controlled string] | test.py:31 | test.py:31:15:31:26 | tainted_list | | --> | Taint externally controlled string | test.py:32 | test.py:32:22:32:22 | e | |
| Taint [externally controlled string] | test.py:31 | test.py:31:15:31:26 | tainted_list | | --> | Taint externally controlled string | test.py:32 | test.py:32:25:32:25 | f | |
| Taint [externally controlled string] | test.py:31 | test.py:31:15:31:26 | tainted_list | | --> | Taint externally controlled string | test.py:32 | test.py:32:28:32:28 | g | |
| Taint [externally controlled string] | test.py:33 | test.py:33:14:33:25 | tainted_list | | --> | Taint externally controlled string | test.py:33 | test.py:33:5:33:26 | For | |
| Taint [externally controlled string] | test.py:35 | test.py:35:14:35:35 | reversed() | | --> | Taint externally controlled string | test.py:35 | test.py:35:5:35:36 | For | |
| Taint [externally controlled string] | test.py:35 | test.py:35:23:35:34 | tainted_list | | --> | Taint [externally controlled string] | test.py:35 | test.py:35:14:35:35 | reversed() | |

View File

@@ -10,9 +10,9 @@
| test.py:32 | test_access | b | externally controlled string |
| test.py:32 | test_access | c | [externally controlled string] |
| test.py:32 | test_access | d | [externally controlled string] |
| test.py:32 | test_access | e | externally controlled string |
| test.py:32 | test_access | f | externally controlled string |
| test.py:32 | test_access | g | externally controlled string |
| test.py:32 | test_access | e | NO TAINT |
| test.py:32 | test_access | f | NO TAINT |
| test.py:32 | test_access | g | NO TAINT |
| test.py:34 | test_access | h | externally controlled string |
| test.py:36 | test_access | i | externally controlled string |
| test.py:43 | test_dict_access | a | externally controlled string |

View File

@@ -0,0 +1,7 @@
| UrlsplitUrlparseTempSanitizer | [externally controlled string] | test.py:21 | Pi(urlsplit_res_0) [true] |
| UrlsplitUrlparseTempSanitizer | [externally controlled string] | test.py:24 | Pi(urlsplit_res_3) [true] |
| UrlsplitUrlparseTempSanitizer | [externally controlled string] | test.py:27 | Pi(urlsplit_res_6) [true] |
| UrlsplitUrlparseTempSanitizer | [externally controlled string] | test.py:30 | Pi(urlsplit_res_9) [true] |
| string equality sanitizer | externally controlled string | test.py:21 | Pi(urlsplit_res_0) [true] |
| string equality sanitizer | externally controlled string | test.py:24 | Pi(urlsplit_res_3) [true] |
| string equality sanitizer | externally controlled string | test.py:27 | Pi(urlsplit_res_6) [true] |

View File

@@ -0,0 +1,6 @@
import python
import Taint
from Sanitizer s, TaintKind taint, PyEdgeRefinement test
where s.sanitizingEdge(taint, test)
select s, taint, test.getTest().getLocation().toString(), test.getRepresentation()

View File

@@ -0,0 +1,47 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
class SimpleSource extends TaintSource {
SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "taint source" }
}
class ListSource extends TaintSource {
ListSource() { this.(NameNode).getId() = "TAINTED_LIST" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind }
override string toString() { result = "list taint source" }
}
class DictSource extends TaintSource {
DictSource() { this.(NameNode).getId() = "TAINTED_DICT" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind }
override string toString() { result = "dict taint source" }
}
class TestConfig extends TaintTracking::Configuration {
TestConfig() { this = "TestConfig" }
override predicate isSanitizer(Sanitizer sanitizer) {
sanitizer instanceof UrlsplitUrlparseTempSanitizer
}
override predicate isSource(TaintTracking::Source source) {
source instanceof SimpleSource
or
source instanceof ListSource
or
source instanceof DictSource
}
override predicate isSink(TaintTracking::Sink sink) {
none()
}
}

View File

@@ -0,0 +1,15 @@
| test.py:13 | test_basic | a | externally controlled string |
| test.py:13 | test_basic | b | externally controlled string |
| test.py:13 | test_basic | c | externally controlled string |
| test.py:13 | test_basic | d | NO TAINT |
| test.py:13 | test_basic | urlsplit_res | [externally controlled string] |
| test.py:19 | test_sanitizer | Attribute | externally controlled string |
| test.py:22 | test_sanitizer | Attribute | NO TAINT |
| test.py:25 | test_sanitizer | Subscript | NO TAINT |
| test.py:28 | test_sanitizer | Attribute | NO TAINT |
| test.py:31 | test_sanitizer | Attribute | NO TAINT |
| test.py:34 | test_sanitizer | Attribute | externally controlled string |
| test.py:44 | test_namedtuple | a | NO TAINT |
| test.py:44 | test_namedtuple | b | NO TAINT |
| test.py:44 | test_namedtuple | c | NO TAINT |
| test.py:44 | test_namedtuple | d | NO TAINT |

View File

@@ -0,0 +1,18 @@
import python
import semmle.python.security.TaintTracking
import Taint
from Call call, Expr arg, string taint_string
where
call.getLocation().getFile().getShortName() = "test.py" and
call.getFunc().(Name).getId() = "test" and
arg = call.getAnArg() and
(
not exists(TaintedNode tainted | tainted.getAstNode() = arg) and
taint_string = "NO TAINT"
or
exists(TaintedNode tainted | tainted.getAstNode() = arg |
taint_string = tainted.getTaintKind().toString()
)
)
select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string

View File

@@ -0,0 +1,44 @@
from six.moves.urllib.parse import urlsplit
# Currently we don't have support for namedtuples in general, but do have special support
# for `urlsplit` (and `urlparse`)
def test_basic():
tainted_string = TAINTED_STRING
urlsplit_res = urlsplit(tainted_string)
a = urlsplit_res.netloc # field access
b = urlsplit_res.hostname # property
c = urlsplit_res[3] # indexing
_, _, d, _, _ = urlsplit(tainted_string) # unpacking
test(a, b, c, d, urlsplit_res)
def test_sanitizer():
tainted_string = TAINTED_STRING
urlsplit_res = urlsplit(tainted_string)
test(urlsplit_res.netloc) # should be tainted
if urlsplit_res.netloc == "OK":
test(urlsplit_res.netloc)
if urlsplit_res[2] == "OK":
test(urlsplit_res[0])
if urlsplit_res.netloc == "OK":
test(urlsplit_res.path) # FN
if urlsplit_res.netloc in ["OK"]:
test(urlsplit_res.netloc)
if urlsplit_res.netloc in ["OK", non_constant()]:
test(urlsplit_res.netloc) # should be tainted
def test_namedtuple():
tainted_string = TAINTED_STRING
Point = namedtuple('Point', ['x', 'y'])
p = Point('safe', tainted_string)
a = p.x
b = p.y
c = p[0]
d = p[1]
test(a, b, c, d) # TODO: FN, at least p.y and p[1] should be tainted

View File

@@ -1,16 +0,0 @@
| Taint exception.info | test.py:41 | test.py:41:22:41:26 | taint | p1 = exception.info |
| Taint exception.info | test.py:42 | test.py:42:12:42:22 | func() | p1 = exception.info |
| Taint exception.info | test.py:42 | test.py:42:17:42:21 | taint | p1 = exception.info |
| Taint exception.info | test.py:45 | test.py:45:12:45:33 | TAINTED_EXCEPTION_INFO | |
| Taint exception.info | test.py:46 | test.py:46:11:46:41 | cross_over() | |
| Taint exception.info | test.py:46 | test.py:46:37:46:40 | info | |
| Taint exception.info | test.py:48 | test.py:48:19:48:21 | arg | p0 = exception.info |
| Taint exception.info | test.py:49 | test.py:49:12:49:14 | arg | p0 = exception.info |
| Taint externally controlled string | test.py:41 | test.py:41:22:41:26 | taint | p1 = externally controlled string |
| Taint externally controlled string | test.py:42 | test.py:42:12:42:22 | func() | p1 = externally controlled string |
| Taint externally controlled string | test.py:42 | test.py:42:17:42:21 | taint | p1 = externally controlled string |
| Taint externally controlled string | test.py:48 | test.py:48:19:48:21 | arg | p0 = externally controlled string |
| Taint externally controlled string | test.py:49 | test.py:49:12:49:14 | arg | p0 = externally controlled string |
| Taint externally controlled string | test.py:52 | test.py:52:11:52:33 | TAINTED_EXTERNAL_STRING | |
| Taint externally controlled string | test.py:53 | test.py:53:11:53:41 | cross_over() | |
| Taint externally controlled string | test.py:53 | test.py:53:38:53:40 | ext | |

View File

@@ -1,37 +0,0 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.security.Exceptions
import semmle.python.security.strings.Untrusted
class ExceptionInfoSource extends TaintSource {
ExceptionInfoSource() { this.(NameNode).getId() = "TAINTED_EXCEPTION_INFO" }
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExceptionInfo
}
override string toString() {
result = "Exception info source"
}
}
class ExternalStringSource extends TaintSource {
ExternalStringSource() { this.(NameNode).getId() = "TAINTED_EXTERNAL_STRING" }
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExternalStringKind
}
override string toString() {
result = "Untrusted string source"
}
}
from TaintedNode n
where n.getLocation().getFile().getShortName() = "test.py"
select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getAstNode(), n.getContext()

View File

@@ -1,11 +1,12 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.Exceptions
class SimpleSource extends TaintSource {
SimpleSource() { this.(NameNode).getId() = "TAINTED" }
SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" }
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExternalStringKind
@@ -46,3 +47,16 @@ class DictSource extends TaintSource {
}
class ExceptionInfoSource extends TaintSource {
ExceptionInfoSource() { this.(NameNode).getId() = "TAINTED_EXCEPTION_INFO" }
override predicate isSourceOf(TaintKind kind) {
kind instanceof ExceptionInfo
}
override string toString() {
result = "Exception info source"
}
}

View File

@@ -1,43 +0,0 @@
| Taint externally controlled string | test.py:5 | test.py:5:22:5:28 | TAINTED | |
| Taint externally controlled string | test.py:6 | test.py:6:31:6:44 | tainted_string | |
| Taint externally controlled string | test.py:7 | test.py:7:9:7:25 | Subscript | |
| Taint externally controlled string | test.py:8 | test.py:8:9:8:9 | a | |
| Taint externally controlled string | test.py:8 | test.py:8:9:8:18 | Attribute() | |
| Taint externally controlled string | test.py:9 | test.py:9:9:9:9 | b | |
| Taint externally controlled string | test.py:9 | test.py:9:9:9:14 | Subscript | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | |
| Taint externally controlled string | test.py:13 | test.py:13:9:13:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:9:13:31 | Attribute() | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:29 | Attribute() | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:25 | Subscript | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:27 | Subscript | |
| Taint externally controlled string | test.py:17 | test.py:17:9:17:32 | reversed() | |
| Taint externally controlled string | test.py:17 | test.py:17:18:17:31 | tainted_string | |
| Taint externally controlled string | test.py:18 | test.py:18:9:18:28 | copy() | |
| Taint externally controlled string | test.py:18 | test.py:18:14:18:27 | tainted_string | |
| Taint externally controlled string | test.py:19 | test.py:19:9:19:22 | tainted_string | |
| Taint externally controlled string | test.py:19 | test.py:19:9:19:30 | Attribute() | |
| Taint externally controlled string | test.py:22 | test.py:22:22:22:28 | TAINTED | |
| Taint externally controlled string | test.py:23 | test.py:23:8:23:21 | tainted_string | |
| Taint externally controlled string | test.py:26 | test.py:26:23:26:36 | tainted_string | |
| Taint externally controlled string | test.py:29 | test.py:29:22:29:28 | TAINTED | |
| Taint externally controlled string | test.py:30 | test.py:30:8:30:21 | tainted_string | |
| Taint externally controlled string | test.py:30 | test.py:30:34:30:47 | tainted_string | |
| Taint externally controlled string | test.py:33 | test.py:33:23:33:36 | tainted_string | |
| Taint externally controlled string | test.py:36 | test.py:36:22:36:28 | TAINTED | |
| Taint externally controlled string | test.py:37 | test.py:37:9:37:27 | str() | |
| Taint externally controlled string | test.py:37 | test.py:37:13:37:26 | tainted_string | |
| Taint externally controlled string | test.py:38 | test.py:38:9:38:29 | bytes() | |
| Taint externally controlled string | test.py:38 | test.py:38:15:38:28 | tainted_string | |
| Taint externally controlled string | test.py:39 | test.py:39:9:39:46 | bytes() | |
| Taint externally controlled string | test.py:39 | test.py:39:15:39:28 | tainted_string | |
| Taint json[externally controlled string] | test.py:6 | test.py:6:20:6:45 | Attribute() | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:25 | Subscript | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:9 | a | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:18 | Attribute() | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:9 | b | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:14 | Subscript | |

View File

@@ -1,8 +0,0 @@
import python
import semmle.python.security.TaintTracking
import Taint
from TaintedNode n
where n.getLocation().getFile().getShortName() = "test.py"
select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getCfgNode().getNode(), n.getContext()

View File

@@ -1,38 +1,76 @@
| Taint externally controlled string | test.py:5 | test.py:5:22:5:28 | TAINTED | | --> | Taint externally controlled string | test.py:6 | test.py:6:31:6:44 | tainted_string | |
| Taint [externally controlled string] | test.py:67 | test.py:67:20:67:43 | urlsplit() | | --> | Taint [externally controlled string] | test.py:69 | test.py:69:10:69:21 | urlsplit_res | |
| Taint [externally controlled string] | test.py:68 | test.py:68:20:68:43 | urlparse() | | --> | Taint [externally controlled string] | test.py:69 | test.py:69:24:69:35 | urlparse_res | |
| Taint exception.info | test.py:44 | test.py:44:22:44:26 | taint | p1 = exception.info | --> | Taint exception.info | test.py:45 | test.py:45:17:45:21 | taint | p1 = exception.info |
| Taint exception.info | test.py:45 | test.py:45:17:45:21 | taint | p1 = exception.info | --> | Taint exception.info | test.py:45 | test.py:45:12:45:22 | func() | p1 = exception.info |
| Taint exception.info | test.py:45 | test.py:45:17:45:21 | taint | p1 = exception.info | --> | Taint exception.info | test.py:52 | test.py:52:19:52:21 | arg | p0 = exception.info |
| Taint exception.info | test.py:48 | test.py:48:12:48:33 | TAINTED_EXCEPTION_INFO | | --> | Taint exception.info | test.py:49 | test.py:49:37:49:40 | info | |
| Taint exception.info | test.py:49 | test.py:49:11:49:41 | cross_over() | | --> | Taint exception.info | test.py:50 | test.py:50:10:50:12 | res | |
| Taint exception.info | test.py:49 | test.py:49:37:49:40 | info | | --> | Taint exception.info | test.py:44 | test.py:44:22:44:26 | taint | p1 = exception.info |
| Taint exception.info | test.py:49 | test.py:49:37:49:40 | info | | --> | Taint exception.info | test.py:49 | test.py:49:11:49:41 | cross_over() | |
| Taint exception.info | test.py:52 | test.py:52:19:52:21 | arg | p0 = exception.info | --> | Taint exception.info | test.py:53 | test.py:53:12:53:14 | arg | p0 = exception.info |
| Taint externally controlled string | test.py:5 | test.py:5:22:5:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:6 | test.py:6:31:6:44 | tainted_string | |
| Taint externally controlled string | test.py:6 | test.py:6:31:6:44 | tainted_string | | --> | Taint json[externally controlled string] | test.py:6 | test.py:6:20:6:45 | Attribute() | |
| Taint externally controlled string | test.py:7 | test.py:7:9:7:25 | Subscript | | --> | Taint externally controlled string | test.py:8 | test.py:8:9:8:9 | a | |
| Taint externally controlled string | test.py:7 | test.py:7:9:7:25 | Subscript | | --> | Taint externally controlled string | test.py:10 | test.py:10:10:10:10 | a | |
| Taint externally controlled string | test.py:8 | test.py:8:9:8:18 | Attribute() | | --> | Taint externally controlled string | test.py:9 | test.py:9:9:9:9 | b | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:13 | test.py:13:9:13:22 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:17 | test.py:17:18:17:31 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:18 | test.py:18:14:18:27 | tainted_string | |
| Taint externally controlled string | test.py:12 | test.py:12:22:12:28 | TAINTED | | --> | Taint externally controlled string | test.py:19 | test.py:19:9:19:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:9:13:22 | tainted_string | | --> | Taint externally controlled string | test.py:13 | test.py:13:9:13:31 | Attribute() | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | | --> | Taint externally controlled string | test.py:14 | test.py:14:9:14:29 | Attribute() | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | | --> | Taint externally controlled string | test.py:15 | test.py:15:9:15:25 | Subscript | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | | --> | Taint externally controlled string | test.py:16 | test.py:16:9:16:27 | Subscript | |
| Taint externally controlled string | test.py:17 | test.py:17:18:17:31 | tainted_string | | --> | Taint externally controlled string | test.py:17 | test.py:17:9:17:32 | reversed() | |
| Taint externally controlled string | test.py:18 | test.py:18:14:18:27 | tainted_string | | --> | Taint externally controlled string | test.py:18 | test.py:18:9:18:28 | copy() | |
| Taint externally controlled string | test.py:19 | test.py:19:9:19:22 | tainted_string | | --> | Taint externally controlled string | test.py:19 | test.py:19:9:19:30 | Attribute() | |
| Taint externally controlled string | test.py:22 | test.py:22:22:22:28 | TAINTED | | --> | Taint externally controlled string | test.py:23 | test.py:23:8:23:21 | tainted_string | |
| Taint externally controlled string | test.py:22 | test.py:22:22:22:28 | TAINTED | | --> | Taint externally controlled string | test.py:26 | test.py:26:23:26:36 | tainted_string | |
| Taint externally controlled string | test.py:29 | test.py:29:22:29:28 | TAINTED | | --> | Taint externally controlled string | test.py:30 | test.py:30:8:30:21 | tainted_string | |
| Taint externally controlled string | test.py:29 | test.py:29:22:29:28 | TAINTED | | --> | Taint externally controlled string | test.py:30 | test.py:30:34:30:47 | tainted_string | |
| Taint externally controlled string | test.py:29 | test.py:29:22:29:28 | TAINTED | | --> | Taint externally controlled string | test.py:33 | test.py:33:23:33:36 | tainted_string | |
| Taint externally controlled string | test.py:36 | test.py:36:22:36:28 | TAINTED | | --> | Taint externally controlled string | test.py:37 | test.py:37:13:37:26 | tainted_string | |
| Taint externally controlled string | test.py:36 | test.py:36:22:36:28 | TAINTED | | --> | Taint externally controlled string | test.py:38 | test.py:38:15:38:28 | tainted_string | |
| Taint externally controlled string | test.py:36 | test.py:36:22:36:28 | TAINTED | | --> | Taint externally controlled string | test.py:39 | test.py:39:15:39:28 | tainted_string | |
| Taint externally controlled string | test.py:37 | test.py:37:13:37:26 | tainted_string | | --> | Taint externally controlled string | test.py:37 | test.py:37:9:37:27 | str() | |
| Taint externally controlled string | test.py:38 | test.py:38:15:38:28 | tainted_string | | --> | Taint externally controlled string | test.py:38 | test.py:38:9:38:29 | bytes() | |
| Taint externally controlled string | test.py:39 | test.py:39:15:39:28 | tainted_string | | --> | Taint externally controlled string | test.py:39 | test.py:39:9:39:46 | bytes() | |
| Taint externally controlled string | test.py:8 | test.py:8:9:8:18 | Attribute() | | --> | Taint externally controlled string | test.py:10 | test.py:10:13:10:13 | b | |
| Taint externally controlled string | test.py:9 | test.py:9:9:9:14 | Subscript | | --> | Taint externally controlled string | test.py:10 | test.py:10:16:10:16 | c | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:17 | test.py:17:9:17:22 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:18 | test.py:18:18:18:31 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:19 | test.py:19:14:19:27 | tainted_string | |
| Taint externally controlled string | test.py:13 | test.py:13:22:13:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:20 | test.py:20:9:20:22 | tainted_string | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:22 | tainted_string | | --> | Taint externally controlled string | test.py:14 | test.py:14:9:14:31 | Attribute() | |
| Taint externally controlled string | test.py:14 | test.py:14:9:14:31 | Attribute() | | --> | Taint externally controlled string | test.py:21 | test.py:21:10:21:10 | a | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:22 | tainted_string | | --> | Taint externally controlled string | test.py:15 | test.py:15:9:15:29 | Attribute() | |
| Taint externally controlled string | test.py:15 | test.py:15:9:15:29 | Attribute() | | --> | Taint externally controlled string | test.py:21 | test.py:21:13:21:13 | b | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:22 | tainted_string | | --> | Taint externally controlled string | test.py:16 | test.py:16:9:16:25 | Subscript | |
| Taint externally controlled string | test.py:16 | test.py:16:9:16:25 | Subscript | | --> | Taint externally controlled string | test.py:21 | test.py:21:16:21:16 | c | |
| Taint externally controlled string | test.py:17 | test.py:17:9:17:22 | tainted_string | | --> | Taint externally controlled string | test.py:17 | test.py:17:9:17:27 | Subscript | |
| Taint externally controlled string | test.py:17 | test.py:17:9:17:27 | Subscript | | --> | Taint externally controlled string | test.py:21 | test.py:21:19:21:19 | d | |
| Taint externally controlled string | test.py:18 | test.py:18:9:18:32 | reversed() | | --> | Taint externally controlled string | test.py:21 | test.py:21:22:21:22 | e | |
| Taint externally controlled string | test.py:18 | test.py:18:18:18:31 | tainted_string | | --> | Taint externally controlled string | test.py:18 | test.py:18:9:18:32 | reversed() | |
| Taint externally controlled string | test.py:19 | test.py:19:9:19:28 | copy() | | --> | Taint externally controlled string | test.py:21 | test.py:21:25:21:25 | f | |
| Taint externally controlled string | test.py:19 | test.py:19:14:19:27 | tainted_string | | --> | Taint externally controlled string | test.py:19 | test.py:19:9:19:28 | copy() | |
| Taint externally controlled string | test.py:20 | test.py:20:9:20:22 | tainted_string | | --> | Taint externally controlled string | test.py:20 | test.py:20:9:20:30 | Attribute() | |
| Taint externally controlled string | test.py:20 | test.py:20:9:20:30 | Attribute() | | --> | Taint externally controlled string | test.py:21 | test.py:21:28:21:28 | g | |
| Taint externally controlled string | test.py:24 | test.py:24:22:24:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:25 | test.py:25:8:25:21 | tainted_string | |
| Taint externally controlled string | test.py:24 | test.py:24:22:24:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:28 | test.py:28:14:28:27 | tainted_string | |
| Taint externally controlled string | test.py:31 | test.py:31:22:31:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:32 | test.py:32:8:32:21 | tainted_string | |
| Taint externally controlled string | test.py:31 | test.py:31:22:31:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:32 | test.py:32:34:32:47 | tainted_string | |
| Taint externally controlled string | test.py:31 | test.py:31:22:31:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:35 | test.py:35:14:35:27 | tainted_string | |
| Taint externally controlled string | test.py:38 | test.py:38:22:38:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:39 | test.py:39:13:39:26 | tainted_string | |
| Taint externally controlled string | test.py:38 | test.py:38:22:38:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:40 | test.py:40:15:40:28 | tainted_string | |
| Taint externally controlled string | test.py:38 | test.py:38:22:38:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:41 | test.py:41:15:41:28 | tainted_string | |
| Taint externally controlled string | test.py:39 | test.py:39:9:39:27 | str() | | --> | Taint externally controlled string | test.py:42 | test.py:42:10:42:10 | a | |
| Taint externally controlled string | test.py:39 | test.py:39:13:39:26 | tainted_string | | --> | Taint externally controlled string | test.py:39 | test.py:39:9:39:27 | str() | |
| Taint externally controlled string | test.py:40 | test.py:40:9:40:29 | bytes() | | --> | Taint externally controlled string | test.py:42 | test.py:42:13:42:13 | b | |
| Taint externally controlled string | test.py:40 | test.py:40:15:40:28 | tainted_string | | --> | Taint externally controlled string | test.py:40 | test.py:40:9:40:29 | bytes() | |
| Taint externally controlled string | test.py:41 | test.py:41:9:41:46 | bytes() | | --> | Taint externally controlled string | test.py:42 | test.py:42:16:42:16 | c | |
| Taint externally controlled string | test.py:41 | test.py:41:15:41:28 | tainted_string | | --> | Taint externally controlled string | test.py:41 | test.py:41:9:41:46 | bytes() | |
| Taint externally controlled string | test.py:44 | test.py:44:22:44:26 | taint | p1 = externally controlled string | --> | Taint externally controlled string | test.py:45 | test.py:45:17:45:21 | taint | p1 = externally controlled string |
| Taint externally controlled string | test.py:45 | test.py:45:17:45:21 | taint | p1 = externally controlled string | --> | Taint externally controlled string | test.py:45 | test.py:45:12:45:22 | func() | p1 = externally controlled string |
| Taint externally controlled string | test.py:45 | test.py:45:17:45:21 | taint | p1 = externally controlled string | --> | Taint externally controlled string | test.py:52 | test.py:52:19:52:21 | arg | p0 = externally controlled string |
| Taint externally controlled string | test.py:52 | test.py:52:19:52:21 | arg | p0 = externally controlled string | --> | Taint externally controlled string | test.py:53 | test.py:53:12:53:14 | arg | p0 = externally controlled string |
| Taint externally controlled string | test.py:56 | test.py:56:11:56:24 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:57 | test.py:57:38:57:40 | ext | |
| Taint externally controlled string | test.py:57 | test.py:57:11:57:41 | cross_over() | | --> | Taint externally controlled string | test.py:58 | test.py:58:10:58:12 | res | |
| Taint externally controlled string | test.py:57 | test.py:57:38:57:40 | ext | | --> | Taint externally controlled string | test.py:44 | test.py:44:22:44:26 | taint | p1 = externally controlled string |
| Taint externally controlled string | test.py:57 | test.py:57:38:57:40 | ext | | --> | Taint externally controlled string | test.py:57 | test.py:57:11:57:41 | cross_over() | |
| Taint externally controlled string | test.py:66 | test.py:66:22:66:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:67 | test.py:67:29:67:42 | tainted_string | |
| Taint externally controlled string | test.py:66 | test.py:66:22:66:35 | TAINTED_STRING | | --> | Taint externally controlled string | test.py:68 | test.py:68:29:68:42 | tainted_string | |
| Taint externally controlled string | test.py:67 | test.py:67:29:67:42 | tainted_string | | --> | Taint [externally controlled string] | test.py:67 | test.py:67:20:67:43 | urlsplit() | |
| Taint externally controlled string | test.py:68 | test.py:68:29:68:42 | tainted_string | | --> | Taint [externally controlled string] | test.py:68 | test.py:68:20:68:43 | urlparse() | |
| Taint json[externally controlled string] | test.py:6 | test.py:6:20:6:45 | Attribute() | | --> | Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | | --> | Taint externally controlled string | test.py:7 | test.py:7:9:7:25 | Subscript | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:20 | tainted_json | | --> | Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:25 | Subscript | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:25 | Subscript | | --> | Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:9 | a | |
| Taint json[externally controlled string] | test.py:7 | test.py:7:9:7:25 | Subscript | | --> | Taint json[externally controlled string] | test.py:10 | test.py:10:10:10:10 | a | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:9 | a | | --> | Taint externally controlled string | test.py:8 | test.py:8:9:8:18 | Attribute() | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:9 | a | | --> | Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:18 | Attribute() | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:18 | Attribute() | | --> | Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:9 | b | |
| Taint json[externally controlled string] | test.py:8 | test.py:8:9:8:18 | Attribute() | | --> | Taint json[externally controlled string] | test.py:10 | test.py:10:13:10:13 | b | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:9 | b | | --> | Taint externally controlled string | test.py:9 | test.py:9:9:9:14 | Subscript | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:9 | b | | --> | Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:14 | Subscript | |
| Taint json[externally controlled string] | test.py:9 | test.py:9:9:9:14 | Subscript | | --> | Taint json[externally controlled string] | test.py:10 | test.py:10:16:10:16 | c | |

View File

@@ -0,0 +1,24 @@
| test.py:10 | test_json | a | externally controlled string |
| test.py:10 | test_json | a | json[externally controlled string] |
| test.py:10 | test_json | b | externally controlled string |
| test.py:10 | test_json | b | json[externally controlled string] |
| test.py:10 | test_json | c | externally controlled string |
| test.py:10 | test_json | c | json[externally controlled string] |
| test.py:21 | test_str | a | externally controlled string |
| test.py:21 | test_str | b | externally controlled string |
| test.py:21 | test_str | c | externally controlled string |
| test.py:21 | test_str | d | externally controlled string |
| test.py:21 | test_str | e | externally controlled string |
| test.py:21 | test_str | f | externally controlled string |
| test.py:21 | test_str | g | externally controlled string |
| test.py:26 | test_const_sanitizer1 | tainted_string | NO TAINT |
| test.py:28 | test_const_sanitizer1 | tainted_string | externally controlled string |
| test.py:33 | test_const_sanitizer2 | tainted_string | NO TAINT |
| test.py:35 | test_const_sanitizer2 | tainted_string | externally controlled string |
| test.py:42 | test_str2 | a | externally controlled string |
| test.py:42 | test_str2 | b | externally controlled string |
| test.py:42 | test_str2 | c | externally controlled string |
| test.py:50 | test_exc_info | res | exception.info |
| test.py:58 | test_untrusted | res | externally controlled string |
| test.py:69 | test_urlsplit_urlparse | urlparse_res | [externally controlled string] |
| test.py:69 | test_urlsplit_urlparse | urlsplit_res | [externally controlled string] |

View File

@@ -0,0 +1,18 @@
import python
import semmle.python.security.TaintTracking
import Taint
from Call call, Expr arg, string taint_string
where
call.getLocation().getFile().getShortName() = "test.py" and
call.getFunc().(Name).getId() = "test" and
arg = call.getAnArg() and
(
not exists(TaintedNode tainted | tainted.getAstNode() = arg) and
taint_string = "NO TAINT"
or
exists(TaintedNode tainted | tainted.getAstNode() = arg |
taint_string = tainted.getTaintKind().toString()
)
)
select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string

View File

@@ -2,41 +2,44 @@ import json
from copy import copy
def test_json():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
tainted_json = json.loads(tainted_string)
a = tainted_json["x"]
b = a.get("y")
c = b["z"]
test(a, b, c)
def test_str():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
a = tainted_string.ljust(8)
b = tainted_string.copy()
c = tainted_string[:]
d = tainted_string[::2]
e = reversed(tainted_string)
f = copy(tainted_string)
h = tainted_string.strip()
g = tainted_string.strip()
test(a, b, c, d, e, f, g)
def test_const_sanitizer1():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
if tainted_string == "OK":
not_tainted(tainted_string)
test(tainted_string) # not tainted
else:
still_tainted(tainted_string)
test(tainted_string) # still tainted
def test_const_sanitizer2():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
if tainted_string == "OK" or tainted_string == "ALSO_OK":
not_tainted(tainted_string)
test(tainted_string) # not tainted
else:
still_tainted(tainted_string)
test(tainted_string) # still tainted
def test_str2():
tainted_string = TAINTED
tainted_string = TAINTED_STRING
a = str(tainted_string)
b = bytes(tainted_string) # This is an error in Python 3
c = bytes(tainted_string, encoding="utf8") # This is an error in Python 2
test(a, b, c)
def cross_over(func, taint):
return func(taint)
@@ -44,13 +47,23 @@ def cross_over(func, taint):
def test_exc_info():
info = TAINTED_EXCEPTION_INFO
res = cross_over(exc_info_call, info)
test(res)
def exc_info_call(arg):
return arg
def test_untrusted():
ext = TAINTED_EXTERNAL_STRING
ext = TAINTED_STRING
res = cross_over(untrusted_call, ext)
test(res)
def exc_untrusted_call(arg):
return arg
from six.moves.urllib.parse import urlsplit, urlparse
def test_urlsplit_urlparse():
tainted_string = TAINTED_STRING
urlsplit_res = urlsplit(tainted_string)
urlparse_res = urlparse(tainted_string)
test(urlsplit_res, urlparse_res)

View File

@@ -1,35 +1,8 @@
| Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | | --> | Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | |
| Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | | --> | Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | |
| Taint [[externally controlled string]] | test.py:19 | test.py:19:10:19:18 | List | | --> | Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint [externally controlled string] | test.py:23 | test.py:23:22:23:22 | b | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint [externally controlled string] | test.py:23 | test.py:23:25:23:25 | c | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint externally controlled string | test.py:23 | test.py:23:10:23:11 | a1 | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint externally controlled string | test.py:23 | test.py:23:14:23:15 | a2 | |
| Taint [[externally controlled string]] | test.py:22 | test.py:22:28:22:29 | ll | | --> | Taint externally controlled string | test.py:23 | test.py:23:18:23:19 | a3 | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint [externally controlled string] | test.py:27 | test.py:27:22:27:22 | b | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint [externally controlled string] | test.py:27 | test.py:27:25:27:25 | c | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint externally controlled string | test.py:27 | test.py:27:10:27:11 | a1 | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint externally controlled string | test.py:27 | test.py:27:14:27:15 | a2 | |
| Taint [[externally controlled string]] | test.py:26 | test.py:26:28:26:29 | ll | | --> | Taint externally controlled string | test.py:27 | test.py:27:18:27:19 | a3 | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint [externally controlled string] | test.py:31 | test.py:31:22:31:22 | b | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint [externally controlled string] | test.py:31 | test.py:31:25:31:25 | c | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint externally controlled string | test.py:31 | test.py:31:10:31:11 | a1 | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint externally controlled string | test.py:31 | test.py:31:14:31:15 | a2 | |
| Taint [[externally controlled string]] | test.py:30 | test.py:30:28:30:29 | ll | | --> | Taint externally controlled string | test.py:31 | test.py:31:18:31:19 | a3 | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:10:48:10 | a | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:13:48:13 | b | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:16:48:16 | c | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:19:48:19 | d | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:22:48:22 | e | |
| Taint [[externally controlled string]] | test.py:47 | test.py:47:28:47:54 | Tuple | | --> | Taint externally controlled string | test.py:48 | test.py:48:25:48:25 | f | |
| Taint [externally controlled string] | test.py:6 | test.py:6:9:6:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:7 | test.py:7:15:7:15 | l | |
| Taint [externally controlled string] | test.py:7 | test.py:7:15:7:15 | l | | --> | Taint externally controlled string | test.py:8 | test.py:8:10:8:10 | a | |
| Taint [externally controlled string] | test.py:7 | test.py:7:15:7:15 | l | | --> | Taint externally controlled string | test.py:8 | test.py:8:13:8:13 | b | |
| Taint [externally controlled string] | test.py:7 | test.py:7:15:7:15 | l | | --> | Taint externally controlled string | test.py:8 | test.py:8:16:8:16 | c | |
| Taint [externally controlled string] | test.py:12 | test.py:12:9:12:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:13 | test.py:13:17:13:17 | l | |
| Taint [externally controlled string] | test.py:13 | test.py:13:17:13:17 | l | | --> | Taint externally controlled string | test.py:14 | test.py:14:10:14:10 | a | |
| Taint [externally controlled string] | test.py:13 | test.py:13:17:13:17 | l | | --> | Taint externally controlled string | test.py:14 | test.py:14:13:14:13 | b | |
| Taint [externally controlled string] | test.py:13 | test.py:13:17:13:17 | l | | --> | Taint externally controlled string | test.py:14 | test.py:14:16:14:16 | c | |
| Taint [externally controlled string] | test.py:18 | test.py:18:9:18:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:19 | test.py:19:11:19:11 | l | |
| Taint [externally controlled string] | test.py:18 | test.py:18:9:18:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:19 | test.py:19:14:19:14 | l | |
| Taint [externally controlled string] | test.py:18 | test.py:18:9:18:20 | TAINTED_LIST | | --> | Taint [externally controlled string] | test.py:19 | test.py:19:17:19:17 | l | |

View File

@@ -1,33 +1,33 @@
| test.py:8 | unpacking | a | externally controlled string |
| test.py:8 | unpacking | b | externally controlled string |
| test.py:8 | unpacking | c | externally controlled string |
| test.py:14 | unpacking_to_list | a | externally controlled string |
| test.py:14 | unpacking_to_list | b | externally controlled string |
| test.py:14 | unpacking_to_list | c | externally controlled string |
| test.py:23 | nested | a1 | externally controlled string |
| test.py:23 | nested | a2 | externally controlled string |
| test.py:23 | nested | a3 | externally controlled string |
| test.py:23 | nested | b | [externally controlled string] |
| test.py:23 | nested | c | [externally controlled string] |
| test.py:27 | nested | a1 | externally controlled string |
| test.py:27 | nested | a2 | externally controlled string |
| test.py:27 | nested | a3 | externally controlled string |
| test.py:27 | nested | b | [externally controlled string] |
| test.py:27 | nested | c | [externally controlled string] |
| test.py:31 | nested | a1 | externally controlled string |
| test.py:31 | nested | a2 | externally controlled string |
| test.py:31 | nested | a3 | externally controlled string |
| test.py:31 | nested | b | [externally controlled string] |
| test.py:31 | nested | c | [externally controlled string] |
| test.py:8 | unpacking | a | NO TAINT |
| test.py:8 | unpacking | b | NO TAINT |
| test.py:8 | unpacking | c | NO TAINT |
| test.py:14 | unpacking_to_list | a | NO TAINT |
| test.py:14 | unpacking_to_list | b | NO TAINT |
| test.py:14 | unpacking_to_list | c | NO TAINT |
| test.py:23 | nested | a1 | NO TAINT |
| test.py:23 | nested | a2 | NO TAINT |
| test.py:23 | nested | a3 | NO TAINT |
| test.py:23 | nested | b | NO TAINT |
| test.py:23 | nested | c | NO TAINT |
| test.py:27 | nested | a1 | NO TAINT |
| test.py:27 | nested | a2 | NO TAINT |
| test.py:27 | nested | a3 | NO TAINT |
| test.py:27 | nested | b | NO TAINT |
| test.py:27 | nested | c | NO TAINT |
| test.py:31 | nested | a1 | NO TAINT |
| test.py:31 | nested | a2 | NO TAINT |
| test.py:31 | nested | a3 | NO TAINT |
| test.py:31 | nested | b | NO TAINT |
| test.py:31 | nested | c | NO TAINT |
| test.py:38 | unpack_from_set | a | NO TAINT |
| test.py:38 | unpack_from_set | b | NO TAINT |
| test.py:38 | unpack_from_set | c | NO TAINT |
| test.py:48 | contrived_1 | a | externally controlled string |
| test.py:48 | contrived_1 | b | externally controlled string |
| test.py:48 | contrived_1 | c | externally controlled string |
| test.py:48 | contrived_1 | d | externally controlled string |
| test.py:48 | contrived_1 | e | externally controlled string |
| test.py:48 | contrived_1 | f | externally controlled string |
| test.py:48 | contrived_1 | a | NO TAINT |
| test.py:48 | contrived_1 | b | NO TAINT |
| test.py:48 | contrived_1 | c | NO TAINT |
| test.py:48 | contrived_1 | d | NO TAINT |
| test.py:48 | contrived_1 | e | NO TAINT |
| test.py:48 | contrived_1 | f | NO TAINT |
| test.py:56 | contrived_2 | a | NO TAINT |
| test.py:56 | contrived_2 | b | NO TAINT |
| test.py:56 | contrived_2 | c | NO TAINT |

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=3 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=3 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -0,0 +1,2 @@
| test.py:3:1:3:27 | ControlFlowNode for Attribute() | test.py:3:14:3:26 | ControlFlowNode for Str | GET |
| test.py:4:1:4:28 | ControlFlowNode for Attribute() | test.py:4:15:4:27 | ControlFlowNode for Str | POST |

View File

@@ -0,0 +1,11 @@
import python
import semmle.python.web.Http
import semmle.python.web.ClientHttpRequest
from Client::HttpRequest req, string method
where
if exists(req.getMethodUpper())
then method = req.getMethodUpper()
else method = "<NO METHOD>"
select req, req.getAUrlPart(), method

View File

@@ -0,0 +1 @@
semmle-extractor-options: -p ../../../../query-tests/Security/lib/ --max-import-depth=1

View File

@@ -0,0 +1,4 @@
import requests
requests.get('example.com')
requests.post('example.com')

View File

@@ -0,0 +1,10 @@
| test.py:6:5:6:32 | ControlFlowNode for Attribute() | test.py:5:27:5:39 | ControlFlowNode for Str | GET |
| test.py:6:5:6:32 | ControlFlowNode for Attribute() | test.py:6:25:6:31 | ControlFlowNode for Str | GET |
| test.py:15:5:15:33 | ControlFlowNode for Attribute() | test.py:10:28:10:40 | ControlFlowNode for Str | POST |
| test.py:15:5:15:33 | ControlFlowNode for Attribute() | test.py:15:26:15:32 | ControlFlowNode for Str | POST |
| test.py:20:5:20:33 | ControlFlowNode for Attribute() | test.py:19:27:19:39 | ControlFlowNode for Str | <NO METHOD> |
| test.py:20:5:20:33 | ControlFlowNode for Attribute() | test.py:20:26:20:32 | ControlFlowNode for Str | <NO METHOD> |
| test.py:30:5:30:32 | ControlFlowNode for Attribute() | test.py:28:27:28:30 | ControlFlowNode for fake | GET |
| test.py:30:5:30:32 | ControlFlowNode for Attribute() | test.py:30:25:30:31 | ControlFlowNode for Str | GET |
| test.py:37:5:37:29 | ControlFlowNode for req_meth() | test.py:35:27:35:39 | ControlFlowNode for Str | HEAD |
| test.py:37:5:37:29 | ControlFlowNode for req_meth() | test.py:37:22:37:28 | ControlFlowNode for Str | HEAD |

View File

@@ -0,0 +1,11 @@
import python
import semmle.python.web.Http
import semmle.python.web.ClientHttpRequest
from Client::HttpRequest req, string method
where
if exists(req.getMethodUpper())
then method = req.getMethodUpper()
else method = "<NO METHOD>"
select req, req.getAUrlPart(), method

View File

@@ -0,0 +1,2 @@
semmle-extractor-options: --max-import-depth=2
optimize: true

View File

@@ -0,0 +1,37 @@
from six.moves.http_client import HTTPConnection, HTTPSConnection
def basic():
conn = HTTPConnection('example.com')
conn.request('GET', '/path')
def indirect_caller():
conn = HTTPSConnection('example.com')
indirect_callee(conn)
def indirect_callee(conn):
conn.request('POST', '/path')
def method_not_known(method):
conn = HTTPConnection('example.com')
conn.request(method, '/path')
def sneaky_setting_host():
# We don't handle that the host is overwritten directly.
# A contrived example; you're not supposed to do this, but you certainly can.
fake = 'fakehost.com'
real = 'realhost.com'
conn = HTTPConnection(fake)
conn.host = real
conn.request('GET', '/path')
def tricky_not_attribute_node():
# A contrived example; you're not supposed to do this, but you certainly can.
conn = HTTPConnection('example.com')
req_meth = conn.request
req_meth('HEAD', '/path')

View File

@@ -0,0 +1,10 @@
| test.py:13:5:13:32 | ControlFlowNode for Attribute() | test.py:12:27:12:39 | ControlFlowNode for Str | GET |
| test.py:13:5:13:32 | ControlFlowNode for Attribute() | test.py:13:25:13:31 | ControlFlowNode for Str | GET |
| test.py:22:5:22:33 | ControlFlowNode for Attribute() | test.py:17:28:17:40 | ControlFlowNode for Str | POST |
| test.py:22:5:22:33 | ControlFlowNode for Attribute() | test.py:22:26:22:32 | ControlFlowNode for Str | POST |
| test.py:27:5:27:33 | ControlFlowNode for Attribute() | test.py:26:27:26:39 | ControlFlowNode for Str | <NO METHOD> |
| test.py:27:5:27:33 | ControlFlowNode for Attribute() | test.py:27:26:27:32 | ControlFlowNode for Str | <NO METHOD> |
| test.py:37:5:37:32 | ControlFlowNode for Attribute() | test.py:35:27:35:30 | ControlFlowNode for fake | GET |
| test.py:37:5:37:32 | ControlFlowNode for Attribute() | test.py:37:25:37:31 | ControlFlowNode for Str | GET |
| test.py:44:5:44:29 | ControlFlowNode for req_meth() | test.py:42:27:42:39 | ControlFlowNode for Str | HEAD |
| test.py:44:5:44:29 | ControlFlowNode for req_meth() | test.py:44:22:44:28 | ControlFlowNode for Str | HEAD |

View File

@@ -0,0 +1,11 @@
import python
import semmle.python.web.Http
import semmle.python.web.ClientHttpRequest
from Client::HttpRequest req, string method
where
if exists(req.getMethodUpper())
then method = req.getMethodUpper()
else method = "<NO METHOD>"
select req, req.getAUrlPart(), method

View File

@@ -0,0 +1 @@
semmle-extractor-options: --max-import-depth=1

View File

@@ -0,0 +1,44 @@
import sys
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
if PY2:
from httplib import HTTPConnection, HTTPSConnection
if PY3:
from http.client import HTTPConnection, HTTPSConnection
def basic():
conn = HTTPConnection('example.com')
conn.request('GET', '/path')
def indirect_caller():
conn = HTTPSConnection('example.com')
indirect_callee(conn)
def indirect_callee(conn):
conn.request('POST', '/path')
def method_not_known(method):
conn = HTTPConnection('example.com')
conn.request(method, '/path')
def sneaky_setting_host():
# We don't handle that the host is overwritten directly.
# A contrived example; you're not supposed to do this, but you certainly can.
fake = 'fakehost.com'
real = 'realhost.com'
conn = HTTPConnection(fake)
conn.host = real
conn.request('GET', '/path')
def tricky_not_attribute_node():
# A contrived example; you're not supposed to do this, but you certainly can.
conn = HTTPConnection('example.com')
req_meth = conn.request
req_meth('HEAD', '/path')

View File

@@ -1,2 +1 @@
semmle-extractor-options: --lang=3 --max-import-depth=3 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=3 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=3 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=2 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=2 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=3 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=1 -p ../../../query-tests/Security/lib/
optimize: true

View File

@@ -242,3 +242,40 @@ from types import MappingProxyType
def mpt_arg(d=MappingProxyType({})):
return 1 in d
#### UseofApply.ql
# Use of the builtin function `apply` is generally considered bad now that the
# ability to destructure lists of arguments is possible, but we should not flag
# cases where the function is merely named `apply` rather than being the actual
# builtin `apply` function.
def useofapply():
def foo():
pass
# Positive Cases
# This use of `apply` is a reference to the builtin function and so SHOULD be
# caught by the query.
apply(foo, [1])
# Negative Cases
# This use of `apply` is a reference to the locally defined function inside of
# `local`, and so SHOULD NOT be caught by the query.
def local():
def apply(f):
pass
apply(foo)([1])

View File

@@ -1,9 +1,9 @@
| om_test.py:59:5:59:28 | Function __div__ | Too many parameters for special method __div__, which has 3 parameters, but should have 2, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:62:5:62:22 | Function __mul__ | Too few parameters for special method __mul__, which has 1 parameter, but should have 2, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:65:5:65:29 | Function __neg__ | Too many parameters for special method __neg__, which has 2 parameters, but should have 1, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:68:5:68:35 | Function __exit__ | Too few parameters for special method __exit__, which has 3 parameters, but should have 4, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:71:5:71:19 | Function __repr__ | Too few parameters for special method __repr__, which has no parameters, but should have 1, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:74:5:74:46 | Function __add__ | 1 default values(s) will never be used for special method __add__, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:97:15:97:34 | Function lambda | Too few parameters for special method __sub__, which has 1 parameter, but should have 2, in class $@. | om_test.py:95:1:95:28 | class NotOKSpecials | NotOKSpecials |
| om_test.py:59:5:59:28 | Function WrongSpecials.__div__ | Too many parameters for special method __div__, which has 3 parameters, but should have 2, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:62:5:62:22 | Function WrongSpecials.__mul__ | Too few parameters for special method __mul__, which has 1 parameter, but should have 2, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:65:5:65:29 | Function WrongSpecials.__neg__ | Too many parameters for special method __neg__, which has 2 parameters, but should have 1, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:68:5:68:35 | Function WrongSpecials.__exit__ | Too few parameters for special method __exit__, which has 3 parameters, but should have 4, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:71:5:71:19 | Function WrongSpecials.__repr__ | Too few parameters for special method __repr__, which has no parameters, but should have 1, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:74:5:74:46 | Function WrongSpecials.__add__ | 1 default values(s) will never be used for special method __add__, in class $@. | om_test.py:57:1:57:28 | class WrongSpecials | WrongSpecials |
| om_test.py:97:15:97:34 | Function NotOKSpecials.lambda | Too few parameters for special method __sub__, which has 1 parameter, but should have 2, in class $@. | om_test.py:95:1:95:28 | class NotOKSpecials | NotOKSpecials |
| protocols.py:104:1:104:12 | Function f | Too few parameters for special method __add__, which has 1 parameter, but should have 2, in class $@. | protocols.py:107:1:107:29 | class MissingMethods | MissingMethods |
| protocols.py:104:1:104:12 | Function f | Too few parameters for special method __set__, which has 1 parameter, but should have 3, in class $@. | protocols.py:107:1:107:29 | class MissingMethods | MissingMethods |

View File

@@ -1,2 +1 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=2 -p ../lib
optimize: true

View File

@@ -1,2 +1 @@
semmle-extractor-options: --max-import-depth=2 -p ../lib
optimize: true

View File

@@ -1 +0,0 @@
optimize: true