mirror of
https://github.com/github/codeql.git
synced 2026-03-30 20:28:15 +02:00
Merge branch 'main' of https://github.com/github/codeql into oscarsj/merge-back-rc-3.21
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Inline expectations test comments, which are of the form `# $ tag` or `# $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the `$` symbol.
|
||||
@@ -5,7 +5,7 @@ class SOURCE(object):
|
||||
@staticmethod
|
||||
def block_flow(): pass
|
||||
|
||||
check("SOURCE", SOURCE, SOURCE, globals()) #$ prints=SOURCE
|
||||
check("SOURCE", SOURCE, SOURCE, globals()) # $ prints=SOURCE
|
||||
|
||||
SOURCE.block_flow()
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ foo_attr = "foo_attr"
|
||||
__private_foo_attr = "__private_foo_attr"
|
||||
|
||||
# A reexport of bar under a new name. Used in main.py
|
||||
import bar as bar_reexported #$ imports=bar as=bar_reexported
|
||||
check("bar_reexported.bar_attr", bar_reexported.bar_attr, "bar_attr", globals()) #$ prints=bar_attr
|
||||
import bar as bar_reexported # $ imports=bar as=bar_reexported
|
||||
check("bar_reexported.bar_attr", bar_reexported.bar_attr, "bar_attr", globals()) # $ prints=bar_attr
|
||||
|
||||
exit(__file__)
|
||||
|
||||
@@ -5,7 +5,7 @@ class SOURCE(object):
|
||||
@staticmethod
|
||||
def block_flow(): pass
|
||||
|
||||
check("SOURCE", SOURCE, SOURCE, globals()) #$ prints=SOURCE
|
||||
check("SOURCE", SOURCE, SOURCE, globals()) # $ prints=SOURCE
|
||||
|
||||
if eval("False"):
|
||||
# With our current import resolution, this value for SOURCE will be considered to be
|
||||
|
||||
@@ -14,6 +14,6 @@ else:
|
||||
|
||||
src.foo = 42
|
||||
|
||||
check("src", src, src, globals()) #$ prints=SOURCE
|
||||
check("src", src, src, globals()) # $ prints=SOURCE
|
||||
|
||||
exit(__file__)
|
||||
|
||||
@@ -24,76 +24,76 @@ from trace import *
|
||||
enter(__file__)
|
||||
|
||||
# A simple import. Binds foo to the foo module
|
||||
import foo #$ imports=foo as=foo
|
||||
check("foo.foo_attr", foo.foo_attr, "foo_attr", globals()) #$ prints=foo_attr
|
||||
import foo # $ imports=foo as=foo
|
||||
check("foo.foo_attr", foo.foo_attr, "foo_attr", globals()) # $ prints=foo_attr
|
||||
|
||||
# Private attributes are still accessible.
|
||||
check("foo.__private_foo_attr", foo.__private_foo_attr, "__private_foo_attr", globals()) #$ prints=__private_foo_attr
|
||||
check("foo.__private_foo_attr", foo.__private_foo_attr, "__private_foo_attr", globals()) # $ prints=__private_foo_attr
|
||||
|
||||
# An aliased import, binding foo to foo_alias
|
||||
import foo as foo_alias #$ imports=foo as=foo_alias
|
||||
check("foo_alias.foo_attr", foo_alias.foo_attr, "foo_attr", globals()) #$ prints=foo_attr
|
||||
import foo as foo_alias # $ imports=foo as=foo_alias
|
||||
check("foo_alias.foo_attr", foo_alias.foo_attr, "foo_attr", globals()) # $ prints=foo_attr
|
||||
|
||||
# A reference to a reexported module
|
||||
check("foo.bar_reexported", foo.bar_reexported, "<module bar>", globals()) #$ prints="<module bar>"
|
||||
check("foo.bar_reexported.bar_attr", foo.bar_reexported.bar_attr, "bar_attr", globals()) #$ prints=bar_attr
|
||||
check("foo.bar_reexported", foo.bar_reexported, "<module bar>", globals()) # $ prints="<module bar>"
|
||||
check("foo.bar_reexported.bar_attr", foo.bar_reexported.bar_attr, "bar_attr", globals()) # $ prints=bar_attr
|
||||
|
||||
# A simple "import from" statement.
|
||||
from bar import bar_attr
|
||||
check("bar_attr", bar_attr, "bar_attr", globals()) #$ prints=bar_attr
|
||||
check("bar_attr", bar_attr, "bar_attr", globals()) # $ prints=bar_attr
|
||||
|
||||
# Importing an attribute from a subpackage of a package.
|
||||
from package.subpackage import subpackage_attr
|
||||
check("subpackage_attr", subpackage_attr, "subpackage_attr", globals()) #$ prints=subpackage_attr
|
||||
check("subpackage_attr", subpackage_attr, "subpackage_attr", globals()) # $ prints=subpackage_attr
|
||||
|
||||
# Importing a package attribute under an alias.
|
||||
from package import package_attr as package_attr_alias
|
||||
check("package_attr_alias", package_attr_alias, "package_attr", globals()) #$ prints=package_attr
|
||||
check("package_attr_alias", package_attr_alias, "package_attr", globals()) # $ prints=package_attr
|
||||
|
||||
# Importing a subpackage under an alias.
|
||||
from package import subpackage as aliased_subpackage #$ imports=package.subpackage.__init__ as=aliased_subpackage
|
||||
check("aliased_subpackage.subpackage_attr", aliased_subpackage.subpackage_attr, "subpackage_attr", globals()) #$ prints=subpackage_attr
|
||||
from package import subpackage as aliased_subpackage # $ imports=package.subpackage.__init__ as=aliased_subpackage
|
||||
check("aliased_subpackage.subpackage_attr", aliased_subpackage.subpackage_attr, "subpackage_attr", globals()) # $ prints=subpackage_attr
|
||||
|
||||
def local_import():
|
||||
# Same as above, but in a local scope.
|
||||
import package.subpackage as local_subpackage #$ imports=package.subpackage.__init__ as=local_subpackage
|
||||
check("local_subpackage.subpackage_attr", local_subpackage.subpackage_attr, "subpackage_attr", locals()) #$ prints=subpackage_attr
|
||||
import package.subpackage as local_subpackage # $ imports=package.subpackage.__init__ as=local_subpackage
|
||||
check("local_subpackage.subpackage_attr", local_subpackage.subpackage_attr, "subpackage_attr", locals()) # $ prints=subpackage_attr
|
||||
|
||||
local_import()
|
||||
|
||||
# Importing a subpacking using `import` and binding it to a name.
|
||||
import package.subpackage as aliased_subpackage #$ imports=package.subpackage.__init__ as=aliased_subpackage
|
||||
check("aliased_subpackage.subpackage_attr", aliased_subpackage.subpackage_attr, "subpackage_attr", globals()) #$ prints=subpackage_attr
|
||||
import package.subpackage as aliased_subpackage # $ imports=package.subpackage.__init__ as=aliased_subpackage
|
||||
check("aliased_subpackage.subpackage_attr", aliased_subpackage.subpackage_attr, "subpackage_attr", globals()) # $ prints=subpackage_attr
|
||||
|
||||
# Importing without binding instead binds the top level name.
|
||||
import package.subpackage #$ imports=package.__init__ as=package
|
||||
check("package.package_attr", package.package_attr, "package_attr", globals()) #$ prints=package_attr
|
||||
import package.subpackage # $ imports=package.__init__ as=package
|
||||
check("package.package_attr", package.package_attr, "package_attr", globals()) # $ prints=package_attr
|
||||
|
||||
# Deep imports
|
||||
import package.subpackage.submodule #$ imports=package.__init__ as=package
|
||||
check("package.subpackage.submodule.submodule_attr", package.subpackage.submodule.submodule_attr, "submodule_attr", globals()) #$ prints=submodule_attr
|
||||
import package.subpackage.submodule # $ imports=package.__init__ as=package
|
||||
check("package.subpackage.submodule.submodule_attr", package.subpackage.submodule.submodule_attr, "submodule_attr", globals()) # $ prints=submodule_attr
|
||||
|
||||
|
||||
if sys.version_info[0] == 3:
|
||||
# Importing from a namespace module.
|
||||
from namespace_package.namespace_module import namespace_module_attr
|
||||
check("namespace_module_attr", namespace_module_attr, "namespace_module_attr", globals()) #$ prints3=namespace_module_attr
|
||||
check("namespace_module_attr", namespace_module_attr, "namespace_module_attr", globals()) # $ prints3=namespace_module_attr
|
||||
|
||||
|
||||
from attr_clash import clashing_attr, non_clashing_submodule #$ imports=attr_clash.clashing_attr as=clashing_attr imports=attr_clash.non_clashing_submodule as=non_clashing_submodule
|
||||
check("clashing_attr", clashing_attr, "clashing_attr", globals()) #$ prints=clashing_attr SPURIOUS: prints="<module attr_clash.clashing_attr>"
|
||||
check("non_clashing_submodule", non_clashing_submodule, "<module attr_clash.non_clashing_submodule>", globals()) #$ prints="<module attr_clash.non_clashing_submodule>"
|
||||
from attr_clash import clashing_attr, non_clashing_submodule # $ imports=attr_clash.clashing_attr as=clashing_attr imports=attr_clash.non_clashing_submodule as=non_clashing_submodule
|
||||
check("clashing_attr", clashing_attr, "clashing_attr", globals()) # $ prints=clashing_attr SPURIOUS: prints="<module attr_clash.clashing_attr>"
|
||||
check("non_clashing_submodule", non_clashing_submodule, "<module attr_clash.non_clashing_submodule>", globals()) # $ prints="<module attr_clash.non_clashing_submodule>"
|
||||
|
||||
import attr_clash.clashing_attr as _doesnt_matter #$ imports=attr_clash.clashing_attr as=_doesnt_matter
|
||||
from attr_clash import clashing_attr, non_clashing_submodule #$ imports=attr_clash.clashing_attr as=clashing_attr imports=attr_clash.non_clashing_submodule as=non_clashing_submodule
|
||||
check("clashing_attr", clashing_attr, "<module attr_clash.clashing_attr>", globals()) #$ prints="<module attr_clash.clashing_attr>" SPURIOUS: prints=clashing_attr
|
||||
import attr_clash.clashing_attr as _doesnt_matter # $ imports=attr_clash.clashing_attr as=_doesnt_matter
|
||||
from attr_clash import clashing_attr, non_clashing_submodule # $ imports=attr_clash.clashing_attr as=clashing_attr imports=attr_clash.non_clashing_submodule as=non_clashing_submodule
|
||||
check("clashing_attr", clashing_attr, "<module attr_clash.clashing_attr>", globals()) # $ prints="<module attr_clash.clashing_attr>" SPURIOUS: prints=clashing_attr
|
||||
|
||||
# check that import * only imports the __all__ attributes
|
||||
from has_defined_all import *
|
||||
check("all_defined_foo", all_defined_foo, "all_defined_foo", globals()) #$ prints=all_defined_foo
|
||||
check("all_defined_foo", all_defined_foo, "all_defined_foo", globals()) # $ prints=all_defined_foo
|
||||
|
||||
try:
|
||||
check("all_defined_bar", all_defined_bar, "all_defined_bar", globals()) #$ SPURIOUS: prints=all_defined_bar
|
||||
check("all_defined_bar", all_defined_bar, "all_defined_bar", globals()) # $ SPURIOUS: prints=all_defined_bar
|
||||
raise Exception("Did not get expected NameError")
|
||||
except NameError as e:
|
||||
if "all_defined_bar" in str(e):
|
||||
@@ -102,15 +102,15 @@ except NameError as e:
|
||||
raise
|
||||
|
||||
import has_defined_all # $ imports=has_defined_all as=has_defined_all
|
||||
check("has_defined_all.all_defined_foo", has_defined_all.all_defined_foo, "all_defined_foo", globals()) #$ prints=all_defined_foo
|
||||
check("has_defined_all.all_defined_bar", has_defined_all.all_defined_bar, "all_defined_bar", globals()) #$ prints=all_defined_bar
|
||||
check("has_defined_all.all_defined_foo", has_defined_all.all_defined_foo, "all_defined_foo", globals()) # $ prints=all_defined_foo
|
||||
check("has_defined_all.all_defined_bar", has_defined_all.all_defined_bar, "all_defined_bar", globals()) # $ prints=all_defined_bar
|
||||
|
||||
# same check as above, but going through one level of indirection (which can make a difference)
|
||||
from has_defined_all_indirection import *
|
||||
check("all_defined_foo_copy", all_defined_foo_copy, "all_defined_foo_copy", globals()) #$ prints=all_defined_foo_copy
|
||||
check("all_defined_foo_copy", all_defined_foo_copy, "all_defined_foo_copy", globals()) # $ prints=all_defined_foo_copy
|
||||
|
||||
try:
|
||||
check("all_defined_bar_copy", all_defined_bar_copy, "all_defined_bar_copy", globals()) #$ SPURIOUS: prints=all_defined_bar_copy
|
||||
check("all_defined_bar_copy", all_defined_bar_copy, "all_defined_bar_copy", globals()) # $ SPURIOUS: prints=all_defined_bar_copy
|
||||
raise Exception("Did not get expected NameError")
|
||||
except NameError as e:
|
||||
if "all_defined_bar_copy" in str(e):
|
||||
@@ -120,7 +120,7 @@ except NameError as e:
|
||||
|
||||
# same check as above, but going through one level of indirection (which can make a difference)
|
||||
import has_defined_all_indirection # $ imports=has_defined_all_indirection as=has_defined_all_indirection
|
||||
check("has_defined_all_indirection.all_defined_foo_copy", has_defined_all_indirection.all_defined_foo_copy, "all_defined_foo_copy", globals()) #$ prints=all_defined_foo_copy
|
||||
check("has_defined_all_indirection.all_defined_foo_copy", has_defined_all_indirection.all_defined_foo_copy, "all_defined_foo_copy", globals()) # $ prints=all_defined_foo_copy
|
||||
|
||||
try:
|
||||
check("has_defined_all_indirection.all_defined_bar_copy", has_defined_all_indirection.all_defined_bar_copy, "all_defined_bar_copy", globals())
|
||||
@@ -133,30 +133,30 @@ except AttributeError as e:
|
||||
|
||||
# check that import * from an __init__ file works
|
||||
from package.subpackage2 import *
|
||||
check("subpackage2_attr", subpackage2_attr, "subpackage2_attr", globals()) #$ prints=subpackage2_attr
|
||||
check("subpackage2_attr", subpackage2_attr, "subpackage2_attr", globals()) # $ prints=subpackage2_attr
|
||||
|
||||
# check that definitions from within if-then-else are found
|
||||
from if_then_else import if_then_else_defined
|
||||
check("if_then_else_defined", if_then_else_defined, "if_defined", globals()) #$ prints=if_defined prints=else_defined_1 prints=else_defined_2
|
||||
check("if_then_else_defined", if_then_else_defined, "if_defined", globals()) # $ prints=if_defined prints=else_defined_1 prints=else_defined_2
|
||||
|
||||
# check that refined definitions are handled correctly
|
||||
import refined # $ imports=refined as=refined
|
||||
check("refined.SOURCE", refined.SOURCE, refined.SOURCE, globals()) #$ prints=SOURCE
|
||||
check("refined.SOURCE", refined.SOURCE, refined.SOURCE, globals()) # $ prints=SOURCE
|
||||
|
||||
import if_then_else_refined # $ imports=if_then_else_refined as=if_then_else_refined
|
||||
check("if_then_else_refined.src", if_then_else_refined.src, if_then_else_refined.src, globals()) #$ prints=SOURCE
|
||||
check("if_then_else_refined.src", if_then_else_refined.src, if_then_else_refined.src, globals()) # $ prints=SOURCE
|
||||
|
||||
import simplistic_reexport # $ imports=simplistic_reexport as=simplistic_reexport
|
||||
check("simplistic_reexport.bar_attr", simplistic_reexport.bar_attr, "overwritten", globals()) #$ prints=overwritten SPURIOUS: prints=bar_attr
|
||||
check("simplistic_reexport.baz_attr", simplistic_reexport.baz_attr, "overwritten", globals()) #$ prints=overwritten SPURIOUS: prints=baz_attr
|
||||
check("simplistic_reexport.bar_attr", simplistic_reexport.bar_attr, "overwritten", globals()) # $ prints=overwritten SPURIOUS: prints=bar_attr
|
||||
check("simplistic_reexport.baz_attr", simplistic_reexport.baz_attr, "overwritten", globals()) # $ prints=overwritten SPURIOUS: prints=baz_attr
|
||||
|
||||
# check that we don't treat all assignments as being exports
|
||||
import block_flow_check #$ imports=block_flow_check as=block_flow_check
|
||||
import block_flow_check # $ imports=block_flow_check as=block_flow_check
|
||||
check("block_flow_check.SOURCE", block_flow_check.SOURCE, block_flow_check.SOURCE, globals())
|
||||
|
||||
# show that import resolution is a bit too generous with definitions
|
||||
import generous_export #$ imports=generous_export as=generous_export
|
||||
check("generous_export.SOURCE", generous_export.SOURCE, generous_export.SOURCE, globals()) #$ SPURIOUS: prints=SOURCE
|
||||
import generous_export # $ imports=generous_export as=generous_export
|
||||
check("generous_export.SOURCE", generous_export.SOURCE, generous_export.SOURCE, globals()) # $ SPURIOUS: prints=SOURCE
|
||||
|
||||
exit(__file__)
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ subpackage_attr = "subpackage_attr"
|
||||
|
||||
# Importing an attribute from the parent package.
|
||||
from .. import attr_used_in_subpackage as imported_attr
|
||||
check("imported_attr", imported_attr, "attr_used_in_subpackage", globals()) #$ prints=attr_used_in_subpackage
|
||||
check("imported_attr", imported_attr, "attr_used_in_subpackage", globals()) # $ prints=attr_used_in_subpackage
|
||||
|
||||
# Importing an irrelevant attribute from a sibling module binds the name to the module.
|
||||
from .submodule import irrelevant_attr
|
||||
check("submodule.submodule_attr", submodule.submodule_attr, "submodule_attr", globals()) #$ MISSING:prints=submodule_attr
|
||||
check("submodule.submodule_attr", submodule.submodule_attr, "submodule_attr", globals()) # $ MISSING:prints=submodule_attr
|
||||
|
||||
exit(__file__)
|
||||
|
||||
@@ -3,12 +3,12 @@ enter(__file__)
|
||||
|
||||
class SOURCE(object): pass
|
||||
|
||||
check("SOURCE", SOURCE, SOURCE, globals()) #$ prints=SOURCE
|
||||
check("SOURCE", SOURCE, SOURCE, globals()) # $ prints=SOURCE
|
||||
|
||||
SOURCE.foo = 42
|
||||
SOURCE.bar = 43
|
||||
SOURCE.baz = 44
|
||||
|
||||
check("SOURCE", SOURCE, SOURCE, globals()) #$ prints=SOURCE
|
||||
check("SOURCE", SOURCE, SOURCE, globals()) # $ prints=SOURCE
|
||||
|
||||
exit(__file__)
|
||||
|
||||
@@ -4,16 +4,16 @@ from trace import *
|
||||
enter(__file__)
|
||||
|
||||
from bar import bar_attr
|
||||
check("bar_attr", bar_attr, "bar_attr", globals()) #$ prints=bar_attr
|
||||
check("bar_attr", bar_attr, "bar_attr", globals()) # $ prints=bar_attr
|
||||
|
||||
bar_attr = "overwritten"
|
||||
check("bar_attr", bar_attr, "overwritten", globals()) #$ prints=overwritten
|
||||
check("bar_attr", bar_attr, "overwritten", globals()) # $ prints=overwritten
|
||||
|
||||
|
||||
from baz import *
|
||||
check("baz_attr", baz_attr, "baz_attr", globals()) #$ MISSING: prints=baz_attr
|
||||
check("baz_attr", baz_attr, "baz_attr", globals()) # $ MISSING: prints=baz_attr
|
||||
|
||||
baz_attr = "overwritten"
|
||||
check("baz_attr", baz_attr, "overwritten", globals()) #$ prints=overwritten
|
||||
check("baz_attr", baz_attr, "overwritten", globals()) # $ prints=overwritten
|
||||
|
||||
exit(__file__)
|
||||
|
||||
@@ -3,7 +3,7 @@ class Foo:
|
||||
pass
|
||||
|
||||
def test_parameter_annotation(x: Foo):
|
||||
x.method() #$ tt=Foo.method
|
||||
x.method() # $ tt=Foo.method
|
||||
|
||||
def test_no_parameter_annotation(x):
|
||||
x.method()
|
||||
@@ -12,21 +12,21 @@ def function_with_return_annotation() -> Foo:
|
||||
return eval("Foo()")
|
||||
|
||||
def test_return_annotation():
|
||||
x = function_with_return_annotation() #$ pt,tt=function_with_return_annotation
|
||||
x.method() #$ tt=Foo.method
|
||||
x = function_with_return_annotation() # $ pt,tt=function_with_return_annotation
|
||||
x.method() # $ tt=Foo.method
|
||||
|
||||
def function_without_return_annotation():
|
||||
return eval("Foo()")
|
||||
|
||||
def test_no_return_annotation():
|
||||
x = function_without_return_annotation() #$ pt,tt=function_without_return_annotation
|
||||
x = function_without_return_annotation() # $ pt,tt=function_without_return_annotation
|
||||
x.method()
|
||||
|
||||
def test_variable_annotation():
|
||||
x = eval("Foo()")
|
||||
x : Foo
|
||||
# Currently fails because there is no flow from the class definition to the type annotation.
|
||||
x.method() #$ MISSING: tt=Foo.method
|
||||
x.method() # $ MISSING: tt=Foo.method
|
||||
|
||||
def test_no_variable_annotation():
|
||||
x = eval("Foo()")
|
||||
|
||||
@@ -24,7 +24,7 @@ class A(Base):
|
||||
self.bar() # $ pt,tt=A.bar
|
||||
|
||||
def not_called(self):
|
||||
self.bar() #$ pt,tt=A.bar
|
||||
self.bar() # $ pt,tt=A.bar
|
||||
|
||||
def bar(self):
|
||||
print("A.bar")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import requests
|
||||
import shutil
|
||||
import os
|
||||
import os
|
||||
|
||||
from flask import Flask, request
|
||||
app = Flask(__name__)
|
||||
@@ -16,8 +16,8 @@ def download_from_url():
|
||||
with open(tarpath, "wb") as f:
|
||||
f.write(response.raw.read())
|
||||
untarredpath = "/tmp/tmp123"
|
||||
shutil.unpack_archive(tarpath, untarredpath) # $result=BAD
|
||||
|
||||
shutil.unpack_archive(tarpath, untarredpath) # $ result=BAD
|
||||
|
||||
|
||||
# A source catching an S3 filename download
|
||||
# see boto3: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.download_file
|
||||
@@ -31,7 +31,7 @@ bucket_name = "mybucket"
|
||||
|
||||
s3 = boto3.client('s3')
|
||||
s3.download_file(bucket_name, remote_ziped_name, local_ziped_path)
|
||||
shutil.unpack_archive(local_ziped_path, base_dir) # $result=BAD
|
||||
shutil.unpack_archive(local_ziped_path, base_dir) # $ result=BAD
|
||||
|
||||
|
||||
# wget
|
||||
@@ -45,11 +45,11 @@ base_dir = "/tmp/basedir"
|
||||
|
||||
# download(url, out, bar) contains out parameter
|
||||
wget.download(url, compressed_file)
|
||||
shutil.unpack_archive(compressed_file, base_dir) # $result=BAD
|
||||
shutil.unpack_archive(compressed_file, base_dir) # $ result=BAD
|
||||
|
||||
# download(url) returns filename
|
||||
compressed_file = wget.download(url)
|
||||
shutil.unpack_archive(compressed_file, base_dir) # $result=BAD
|
||||
shutil.unpack_archive(compressed_file, base_dir) # $ result=BAD
|
||||
|
||||
|
||||
# A source coming from a CLI argparse module
|
||||
@@ -63,7 +63,7 @@ parser.add_argument('filename', help='filename to be provided')
|
||||
|
||||
args = parser.parse_args()
|
||||
compressed_file = args.filename
|
||||
shutil.unpack_archive(compressed_file, base_dir) # $result=BAD
|
||||
shutil.unpack_archive(compressed_file, base_dir) # $ result=BAD
|
||||
|
||||
|
||||
# A source coming from a CLI and downloaded
|
||||
@@ -83,8 +83,8 @@ response = requests.get(url_filename, stream=True)
|
||||
tarpath = "/tmp/tmp456/tarball.tar.gz"
|
||||
with open(tarpath, "wb") as f:
|
||||
f.write(response.raw.read())
|
||||
|
||||
shutil.unpack_archive(tarpath, base_dir) # $result=BAD
|
||||
|
||||
shutil.unpack_archive(tarpath, base_dir) # $ result=BAD
|
||||
|
||||
# the django upload functionality
|
||||
# see HttpRequest.FILES: https://docs.djangoproject.com/en/4.1/ref/request-response/#django.http.HttpRequest.FILES
|
||||
@@ -97,19 +97,19 @@ def simple_upload(request):
|
||||
base_dir = "/tmp/baase_dir"
|
||||
if request.method == 'POST':
|
||||
# Read uploaded files by chunks of data
|
||||
# see chunks(): https://docs.djangoproject.com/en/4.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks
|
||||
# see chunks(): https://docs.djangoproject.com/en/4.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks
|
||||
savepath = os.path.join(base_dir, "tarball_compressed.tar.gz")
|
||||
with open(savepath, 'wb+') as wfile:
|
||||
for chunk in request.FILES["ufile1"].chunks():
|
||||
wfile.write(chunk)
|
||||
shutil.unpack_archive(savepath, base_dir) # $result=BAD
|
||||
shutil.unpack_archive(savepath, base_dir) # $ result=BAD
|
||||
|
||||
# Write in binary the uploaded tarball
|
||||
myfile = request.FILES.get("ufile1")
|
||||
file_path = os.path.join(base_dir, "tarball.tar")
|
||||
with file_path.open('wb') as f:
|
||||
f.write(myfile.read())
|
||||
shutil.unpack_archive(file_path, base_dir) # $result=BAD
|
||||
shutil.unpack_archive(file_path, base_dir) # $ result=BAD
|
||||
|
||||
# Save uploaded files using FileSystemStorage Django API
|
||||
# see FileSystemStorage: https://docs.djangoproject.com/en/4.1/ref/files/storage/#django.core.files.storage.FileSystemStorage
|
||||
@@ -117,8 +117,8 @@ def simple_upload(request):
|
||||
fs = FileSystemStorage()
|
||||
filename = fs.save(ufile.name, ufile)
|
||||
uploaded_file_path = fs.path(filename)
|
||||
shutil.unpack_archive(uploaded_file_path, base_dir) # $result=BAD
|
||||
|
||||
shutil.unpack_archive(uploaded_file_path, base_dir) # $ result=BAD
|
||||
|
||||
return render(request, 'simple_upload.html')
|
||||
|
||||
elif request.method == 'GET':
|
||||
@@ -126,7 +126,7 @@ def simple_upload(request):
|
||||
|
||||
|
||||
import shutil
|
||||
import os
|
||||
import os
|
||||
import tarfile
|
||||
import tempfile
|
||||
import argparse
|
||||
@@ -139,8 +139,8 @@ parser.add_argument('filename', help='filename to be provided')
|
||||
args = parser.parse_args()
|
||||
unsafe_filename_tar = args.filename
|
||||
with tarfile.TarFile(unsafe_filename_tar, mode="r") as tar:
|
||||
tar.extractall(path="/tmp/unpack/", members=tar) # $result=BAD
|
||||
tar = tarfile.open(unsafe_filename_tar)
|
||||
tar.extractall(path="/tmp/unpack/", members=tar) # $ result=BAD
|
||||
tar = tarfile.open(unsafe_filename_tar)
|
||||
|
||||
|
||||
from django.shortcuts import render
|
||||
@@ -152,7 +152,7 @@ def simple_upload(request):
|
||||
base_dir = "/tmp/baase_dir"
|
||||
if request.method == 'POST':
|
||||
# Read uploaded files by chunks of data
|
||||
# see chunks(): https://docs.djangoproject.com/en/4.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks
|
||||
# see chunks(): https://docs.djangoproject.com/en/4.1/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks
|
||||
savepath = os.path.join(base_dir, "tarball_compressed.tar.gz")
|
||||
with open(savepath, 'wb+') as wfile:
|
||||
for chunk in request.FILES["ufile1"].chunks():
|
||||
@@ -160,11 +160,11 @@ def simple_upload(request):
|
||||
|
||||
tar = tarfile.open(savepath)
|
||||
result = []
|
||||
for member in tar:
|
||||
if member.issym():
|
||||
raise ValueError("But it is a symlink")
|
||||
result.append(member)
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=result) # $result=BAD
|
||||
for member in tar:
|
||||
if member.issym():
|
||||
raise ValueError("But it is a symlink")
|
||||
result.append(member)
|
||||
tar.extractall(path=tempfile.mkdtemp(), members=result) # $ result=BAD
|
||||
tar.close()
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ tarpath = "/tmp/tmp456/tarball.tar.gz"
|
||||
with open(tarpath, "wb") as f:
|
||||
f.write(response.raw.read())
|
||||
target_dir = "/tmp/unpack"
|
||||
tarfile.TarFile(tarpath, mode="r").extractall(path=target_dir) # $result=BAD
|
||||
tarfile.TarFile(tarpath, mode="r").extractall(path=target_dir) # $ result=BAD
|
||||
|
||||
|
||||
from pathlib import Path
|
||||
@@ -183,7 +183,7 @@ import boto3
|
||||
def default_session() -> boto3.Session:
|
||||
_SESSION = None
|
||||
if _SESSION is None:
|
||||
_SESSION = boto3.Session()
|
||||
_SESSION = boto3.Session()
|
||||
return _SESSION
|
||||
|
||||
cache = False
|
||||
@@ -198,4 +198,4 @@ with tempfile.NamedTemporaryFile(suffix=".tar.gz") as tmp:
|
||||
target = cache_dir
|
||||
else:
|
||||
target = Path(tempfile.mkdtemp())
|
||||
shutil.unpack_archive(tmp.name, target) # $result=BAD
|
||||
shutil.unpack_archive(tmp.name, target) # $ result=BAD
|
||||
|
||||
@@ -6,7 +6,7 @@ app = Flask(__name__)
|
||||
def get_input1():
|
||||
input = request.args.get("input")
|
||||
|
||||
agent = Agent(name="Assistant", instructions="This prompt is customized for " + input) # $Alert[py/prompt-injection]
|
||||
agent = Agent(name="Assistant", instructions="This prompt is customized for " + input) # $ Alert[py/prompt-injection]
|
||||
|
||||
result = Runner.run_sync(agent, "This is a user message.")
|
||||
print(result.final_output)
|
||||
@@ -22,9 +22,9 @@ def get_input2():
|
||||
input=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": input, # $Alert[py/prompt-injection]
|
||||
"content": input, # $ Alert[py/prompt-injection]
|
||||
}
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
result2 = Runner.run_sync(
|
||||
@@ -32,7 +32,7 @@ def get_input2():
|
||||
[
|
||||
{
|
||||
"role": "user",
|
||||
"content": input, # $Alert[py/prompt-injection]
|
||||
"content": input, # $ Alert[py/prompt-injection]
|
||||
}
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ app = Flask(__name__)
|
||||
@app.route("/unsafe1")
|
||||
def unsafe1():
|
||||
user_input = escape(request.args.get("ui"))
|
||||
normalized_user_input = unicodedata.normalize("NFKC", user_input) # $result=BAD
|
||||
normalized_user_input = unicodedata.normalize("NFKC", user_input) # $ result=BAD
|
||||
return render_template("result.html", normalized_user_input=normalized_user_input)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ def unsafe1bis():
|
||||
if user_input.isascii():
|
||||
normalized_user_input = user_input
|
||||
else:
|
||||
normalized_user_input = unicodedata.normalize("NFC", user_input) # $result=BAD
|
||||
normalized_user_input = unicodedata.normalize("NFC", user_input) # $ result=BAD
|
||||
return render_template("result.html", normalized_user_input=normalized_user_input)
|
||||
|
||||
|
||||
@@ -25,6 +25,6 @@ def unsafe1bis():
|
||||
def safe1():
|
||||
normalized_user_input = unicodedata.normalize(
|
||||
"NFKC", request.args.get("ui")
|
||||
) # $result=OK
|
||||
) # $ result=OK
|
||||
user_input = escape(normalized_user_input)
|
||||
return render_template("result.html", normalized_user_input=user_input)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
def python2_style():
|
||||
from __builtin__ import open #$ use=moduleImport("builtins").getMember("open")
|
||||
open("hello.txt") #$ use=moduleImport("builtins").getMember("open").getReturn()
|
||||
from __builtin__ import open # $ use=moduleImport("builtins").getMember("open")
|
||||
open("hello.txt") # $ use=moduleImport("builtins").getMember("open").getReturn()
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
from mypkg import foo #$ use=moduleImport("mypkg").getMember("foo")
|
||||
from mypkg import foo # $ use=moduleImport("mypkg").getMember("foo")
|
||||
|
||||
def callback(x): #$ use=moduleImport("mypkg").getMember("foo").getMember("bar").getParameter(0).getParameter(0)
|
||||
x.baz() #$ use=moduleImport("mypkg").getMember("foo").getMember("bar").getParameter(0).getParameter(0).getMember("baz").getReturn()
|
||||
def callback(x): # $ use=moduleImport("mypkg").getMember("foo").getMember("bar").getParameter(0).getParameter(0)
|
||||
x.baz() # $ use=moduleImport("mypkg").getMember("foo").getMember("bar").getParameter(0).getParameter(0).getMember("baz").getReturn()
|
||||
|
||||
foo.bar(callback) #$ def=moduleImport("mypkg").getMember("foo").getMember("bar").getParameter(0) use=moduleImport("mypkg").getMember("foo").getMember("bar").getReturn()
|
||||
foo.bar(callback) # $ def=moduleImport("mypkg").getMember("foo").getMember("bar").getParameter(0) use=moduleImport("mypkg").getMember("foo").getMember("bar").getReturn()
|
||||
|
||||
def callback2(x): #$ use=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getASubscript().getParameter(0)
|
||||
x.baz2() #$ use=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getASubscript().getParameter(0).getMember("baz2").getReturn()
|
||||
def callback2(x): # $ use=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getASubscript().getParameter(0)
|
||||
x.baz2() # $ use=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getASubscript().getParameter(0).getMember("baz2").getReturn()
|
||||
|
||||
mydict = {
|
||||
"c": callback2, #$ def=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getASubscript()
|
||||
"other": "whatever" #$ def=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getASubscript()
|
||||
"c": callback2, # $ def=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getASubscript()
|
||||
"other": "whatever" # $ def=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getASubscript()
|
||||
}
|
||||
|
||||
foo.baz(mydict) #$ def=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0) use=moduleImport("mypkg").getMember("foo").getMember("baz").getReturn()
|
||||
foo.baz(mydict) # $ def=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0) use=moduleImport("mypkg").getMember("foo").getMember("baz").getReturn()
|
||||
|
||||
def callback3(x): #$ use=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getMember("third").getParameter(0)
|
||||
x.baz3() #$ use=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getMember("third").getParameter(0).getMember("baz3").getReturn()
|
||||
def callback3(x): # $ use=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getMember("third").getParameter(0)
|
||||
x.baz3() # $ use=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getMember("third").getParameter(0).getMember("baz3").getReturn()
|
||||
|
||||
mydict.third = callback3 #$ def=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getMember("third")
|
||||
mydict.third = callback3 # $ def=moduleImport("mypkg").getMember("foo").getMember("baz").getParameter(0).getMember("third")
|
||||
|
||||
foo.blab(mydict) #$ def=moduleImport("mypkg").getMember("foo").getMember("blab").getParameter(0) use=moduleImport("mypkg").getMember("foo").getMember("blab").getReturn()
|
||||
foo.blab(mydict) # $ def=moduleImport("mypkg").getMember("foo").getMember("blab").getParameter(0) use=moduleImport("mypkg").getMember("foo").getMember("blab").getReturn()
|
||||
|
||||
def callback4(x): #$ use=moduleImport("mypkg").getMember("foo").getMember("quack").getParameter(0).getParameter(0)
|
||||
x.baz4() #$ use=moduleImport("mypkg").getMember("foo").getMember("quack").getParameter(0).getParameter(0).getMember("baz4").getReturn()
|
||||
def callback4(x): # $ use=moduleImport("mypkg").getMember("foo").getMember("quack").getParameter(0).getParameter(0)
|
||||
x.baz4() # $ use=moduleImport("mypkg").getMember("foo").getMember("quack").getParameter(0).getParameter(0).getMember("baz4").getReturn()
|
||||
|
||||
otherDict = {
|
||||
# TODO: Backtracking through a property set using a dict doesn't work, but I can backtrack through explicit property writes, e.g. the `otherDict.fourth` below.
|
||||
@@ -32,30 +32,30 @@ otherDict = {
|
||||
}
|
||||
otherDict.fourth = callback4
|
||||
|
||||
foo.quack(otherDict.fourth) #$ def=moduleImport("mypkg").getMember("foo").getMember("quack").getParameter(0) use=moduleImport("mypkg").getMember("foo").getMember("quack").getReturn()
|
||||
foo.quack(otherDict.fourth) # $ def=moduleImport("mypkg").getMember("foo").getMember("quack").getParameter(0) use=moduleImport("mypkg").getMember("foo").getMember("quack").getReturn()
|
||||
|
||||
def namedCallback(myName, otherName):
|
||||
# Using named parameters:
|
||||
myName() #$ use=moduleImport("mypkg").getMember("foo").getMember("blob").getParameter(0).getKeywordParameter("myName").getReturn()
|
||||
otherName() #$ use=moduleImport("mypkg").getMember("foo").getMember("blob").getParameter(0).getKeywordParameter("otherName").getReturn()
|
||||
myName() # $ use=moduleImport("mypkg").getMember("foo").getMember("blob").getParameter(0).getKeywordParameter("myName").getReturn()
|
||||
otherName() # $ use=moduleImport("mypkg").getMember("foo").getMember("blob").getParameter(0).getKeywordParameter("otherName").getReturn()
|
||||
# Using numbered parameters:
|
||||
myName() #$ use=moduleImport("mypkg").getMember("foo").getMember("blob").getParameter(0).getParameter(0).getReturn()
|
||||
otherName() #$ use=moduleImport("mypkg").getMember("foo").getMember("blob").getParameter(0).getParameter(1).getReturn()
|
||||
myName() # $ use=moduleImport("mypkg").getMember("foo").getMember("blob").getParameter(0).getParameter(0).getReturn()
|
||||
otherName() # $ use=moduleImport("mypkg").getMember("foo").getMember("blob").getParameter(0).getParameter(1).getReturn()
|
||||
|
||||
foo.blob(namedCallback) #$ use=moduleImport("mypkg").getMember("foo").getMember("blob").getReturn()
|
||||
foo.blob(namedCallback) # $ use=moduleImport("mypkg").getMember("foo").getMember("blob").getReturn()
|
||||
|
||||
foo.named(myName = 2) #$ def=moduleImport("mypkg").getMember("foo").getMember("named").getKeywordParameter("myName")
|
||||
foo.named(myName = 2) # $ def=moduleImport("mypkg").getMember("foo").getMember("named").getKeywordParameter("myName")
|
||||
|
||||
|
||||
def recusisionCallback(x):
|
||||
x.recursion() #$ use=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0).getMember("callback").getParameter(0).getMember("recursion").getReturn()
|
||||
x.recursion() #$ use=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0).getMember("rec1").getMember("callback").getParameter(0).getMember("recursion").getReturn()
|
||||
x.recursion() #$ use=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0).getMember("rec1").getMember("rec2").getMember("callback").getParameter(0).getMember("recursion").getReturn()
|
||||
x.recursion() #$ use=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0).getMember("rec1").getMember("rec2").getMember("rec1").getMember("callback").getParameter(0).getMember("recursion").getReturn()
|
||||
x.recursion() # $ use=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0).getMember("callback").getParameter(0).getMember("recursion").getReturn()
|
||||
x.recursion() # $ use=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0).getMember("rec1").getMember("callback").getParameter(0).getMember("recursion").getReturn()
|
||||
x.recursion() # $ use=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0).getMember("rec1").getMember("rec2").getMember("callback").getParameter(0).getMember("recursion").getReturn()
|
||||
x.recursion() # $ use=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0).getMember("rec1").getMember("rec2").getMember("rec1").getMember("callback").getParameter(0).getMember("recursion").getReturn()
|
||||
|
||||
recursiveDict = {};
|
||||
recursiveDict.callback = recusisionCallback;
|
||||
recursiveDict.rec1 = recursiveDict;
|
||||
recursiveDict.rec2 = recursiveDict;
|
||||
|
||||
foo.rec(recursiveDict); #$ def=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0)
|
||||
foo.rec(recursiveDict); # $ def=moduleImport("mypkg").getMember("foo").getMember("rec").getParameter(0)
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# Subclasses
|
||||
|
||||
from flask.views import View #$ use=moduleImport("flask").getMember("views").getMember("View")
|
||||
from flask.views import View # $ use=moduleImport("flask").getMember("views").getMember("View")
|
||||
|
||||
class MyView(View): #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass()
|
||||
myvar = 45 #$ def=moduleImport("flask").getMember("views").getMember("View").getASubclass().getMember("myvar")
|
||||
def my_method(self): #$ def=moduleImport("flask").getMember("views").getMember("View").getASubclass().getMember("my_method")
|
||||
return 3 #$ def=moduleImport("flask").getMember("views").getMember("View").getASubclass().getMember("my_method").getReturn()
|
||||
class MyView(View): # $ use=moduleImport("flask").getMember("views").getMember("View").getASubclass()
|
||||
myvar = 45 # $ def=moduleImport("flask").getMember("views").getMember("View").getASubclass().getMember("myvar")
|
||||
def my_method(self): # $ def=moduleImport("flask").getMember("views").getMember("View").getASubclass().getMember("my_method")
|
||||
return 3 # $ def=moduleImport("flask").getMember("views").getMember("View").getASubclass().getMember("my_method").getReturn()
|
||||
|
||||
instance = MyView() #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getReturn()
|
||||
instance = MyView() # $ use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getReturn()
|
||||
|
||||
def internal():
|
||||
from pflask.views import View #$ use=moduleImport("pflask").getMember("views").getMember("View")
|
||||
class IntMyView(View): #$ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass()
|
||||
my_internal_var = 35 #$ def=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getMember("my_internal_var")
|
||||
def my_internal_method(self): #$ def=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getMember("my_internal_method")
|
||||
from pflask.views import View # $ use=moduleImport("pflask").getMember("views").getMember("View")
|
||||
class IntMyView(View): # $ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass()
|
||||
my_internal_var = 35 # $ def=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getMember("my_internal_var")
|
||||
def my_internal_method(self): # $ def=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getMember("my_internal_method")
|
||||
pass
|
||||
|
||||
int_instance = IntMyView() #$ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getReturn()
|
||||
int_instance = IntMyView() # $ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getReturn()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Class decorator
|
||||
@@ -27,8 +27,8 @@ def my_class_decorator(cls):
|
||||
return cls
|
||||
|
||||
@my_class_decorator
|
||||
class MyViewWithDecorator(View): #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass()
|
||||
class MyViewWithDecorator(View): # $ use=moduleImport("flask").getMember("views").getMember("View").getASubclass()
|
||||
pass
|
||||
|
||||
class SubclassFromDecorated(MyViewWithDecorator): #$ use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getASubclass()
|
||||
class SubclassFromDecorated(MyViewWithDecorator): # $ use=moduleImport("flask").getMember("views").getMember("View").getASubclass().getASubclass()
|
||||
pass
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
import a1 #$ use=moduleImport("a1")
|
||||
import a1 # $ use=moduleImport("a1")
|
||||
|
||||
x = a1.blah1 #$ use=moduleImport("a1").getMember("blah1")
|
||||
x = a1.blah1 # $ use=moduleImport("a1").getMember("blah1")
|
||||
|
||||
import a2 as m2 #$ use=moduleImport("a2")
|
||||
import a2 as m2 # $ use=moduleImport("a2")
|
||||
|
||||
x2 = m2.blah2 #$ use=moduleImport("a2").getMember("blah2")
|
||||
x2 = m2.blah2 # $ use=moduleImport("a2").getMember("blah2")
|
||||
|
||||
import a3.b3 as m3 #$ use=moduleImport("a3").getMember("b3")
|
||||
import a3.b3 as m3 # $ use=moduleImport("a3").getMember("b3")
|
||||
|
||||
x3 = m3.blah3 #$ use=moduleImport("a3").getMember("b3").getMember("blah3")
|
||||
x3 = m3.blah3 # $ use=moduleImport("a3").getMember("b3").getMember("blah3")
|
||||
|
||||
from a4.b4 import c4 as m4 #$ use=moduleImport("a4").getMember("b4").getMember("c4")
|
||||
from a4.b4 import c4 as m4 # $ use=moduleImport("a4").getMember("b4").getMember("c4")
|
||||
|
||||
x4 = m4.blah4 #$ use=moduleImport("a4").getMember("b4").getMember("c4").getMember("blah4")
|
||||
x4 = m4.blah4 # $ use=moduleImport("a4").getMember("b4").getMember("c4").getMember("blah4")
|
||||
|
||||
import a.b.c.d #$ use=moduleImport("a")
|
||||
import a.b.c.d # $ use=moduleImport("a")
|
||||
|
||||
ab = a.b #$ use=moduleImport("a").getMember("b")
|
||||
ab = a.b # $ use=moduleImport("a").getMember("b")
|
||||
|
||||
abc = ab.c #$ use=moduleImport("a").getMember("b").getMember("c")
|
||||
abc = ab.c # $ use=moduleImport("a").getMember("b").getMember("c")
|
||||
|
||||
abcd = abc.d #$ use=moduleImport("a").getMember("b").getMember("c").getMember("d")
|
||||
abcd = abc.d # $ use=moduleImport("a").getMember("b").getMember("c").getMember("d")
|
||||
|
||||
x5 = abcd.method() #$ use=moduleImport("a").getMember("b").getMember("c").getMember("d").getMember("method").getReturn()
|
||||
x5 = abcd.method() # $ use=moduleImport("a").getMember("b").getMember("c").getMember("d").getMember("method").getReturn()
|
||||
|
||||
from a.b.c.d import method
|
||||
x5_alt = method() #$ use=moduleImport("a").getMember("b").getMember("c").getMember("d").getMember("method").getReturn()
|
||||
x5_alt = method() # $ use=moduleImport("a").getMember("b").getMember("c").getMember("d").getMember("method").getReturn()
|
||||
|
||||
from a6 import m6 #$ use=moduleImport("a6").getMember("m6")
|
||||
from a6 import m6 # $ use=moduleImport("a6").getMember("m6")
|
||||
|
||||
x6 = m6().foo().bar() #$ use=moduleImport("a6").getMember("m6").getReturn().getMember("foo").getReturn().getMember("bar").getReturn()
|
||||
x6 = m6().foo().bar() # $ use=moduleImport("a6").getMember("m6").getReturn().getMember("foo").getReturn().getMember("bar").getReturn()
|
||||
|
||||
import foo.baz.baz as fbb #$ use=moduleImport("foo").getMember("baz").getMember("baz")
|
||||
from foo.bar.baz import quux as fbbq #$ use=moduleImport("foo").getMember("bar").getMember("baz").getMember("quux")
|
||||
from ham.bar.eggs import spam as hbes #$ use=moduleImport("ham").getMember("bar").getMember("eggs").getMember("spam")
|
||||
fbb.quux #$ use=moduleImport("foo").getMember("baz").getMember("baz").getMember("quux")
|
||||
fbbq #$ use=moduleImport("foo").getMember("bar").getMember("baz").getMember("quux")
|
||||
hbes #$ use=moduleImport("ham").getMember("bar").getMember("eggs").getMember("spam")
|
||||
import foo.baz.baz as fbb # $ use=moduleImport("foo").getMember("baz").getMember("baz")
|
||||
from foo.bar.baz import quux as fbbq # $ use=moduleImport("foo").getMember("bar").getMember("baz").getMember("quux")
|
||||
from ham.bar.eggs import spam as hbes # $ use=moduleImport("ham").getMember("bar").getMember("eggs").getMember("spam")
|
||||
fbb.quux # $ use=moduleImport("foo").getMember("baz").getMember("baz").getMember("quux")
|
||||
fbbq # $ use=moduleImport("foo").getMember("bar").getMember("baz").getMember("quux")
|
||||
hbes # $ use=moduleImport("ham").getMember("bar").getMember("eggs").getMember("spam")
|
||||
|
||||
import foo.bar.baz #$ use=moduleImport("foo")
|
||||
import foo.bar.baz # $ use=moduleImport("foo")
|
||||
|
||||
# Relative imports. These are ignored
|
||||
|
||||
@@ -50,51 +50,51 @@ from ..foobar import baz
|
||||
# Use of imports across scopes
|
||||
|
||||
def use_m4():
|
||||
x = m4.blah4 #$ use=moduleImport("a4").getMember("b4").getMember("c4").getMember("blah4")
|
||||
x = m4.blah4 # $ use=moduleImport("a4").getMember("b4").getMember("c4").getMember("blah4")
|
||||
|
||||
def local_import_use():
|
||||
from foo import bar #$ use=moduleImport("foo").getMember("bar")
|
||||
from foo import bar # $ use=moduleImport("foo").getMember("bar")
|
||||
|
||||
x = bar() #$ use=moduleImport("foo").getMember("bar").getReturn()
|
||||
x = bar() # $ use=moduleImport("foo").getMember("bar").getReturn()
|
||||
|
||||
from eggs import ham as spam #$ use=moduleImport("eggs").getMember("ham")
|
||||
from eggs import ham as spam # $ use=moduleImport("eggs").getMember("ham")
|
||||
|
||||
def bbb():
|
||||
f = spam #$ use=moduleImport("eggs").getMember("ham")
|
||||
f = spam # $ use=moduleImport("eggs").getMember("ham")
|
||||
|
||||
from danger import SOURCE #$ use=moduleImport("danger").getMember("SOURCE")
|
||||
from danger import SOURCE # $ use=moduleImport("danger").getMember("SOURCE")
|
||||
|
||||
foo = SOURCE #$ use=moduleImport("danger").getMember("SOURCE")
|
||||
foo = SOURCE # $ use=moduleImport("danger").getMember("SOURCE")
|
||||
|
||||
def change_foo():
|
||||
global foo
|
||||
foo = SOURCE #$ use=moduleImport("danger").getMember("SOURCE")
|
||||
foo = SOURCE # $ use=moduleImport("danger").getMember("SOURCE")
|
||||
|
||||
def f():
|
||||
global foo
|
||||
sink(foo) #$ use=moduleImport("danger").getMember("SOURCE")
|
||||
sink(foo) # $ use=moduleImport("danger").getMember("SOURCE")
|
||||
foo = NONSOURCE
|
||||
change_foo()
|
||||
sink(foo) #$ use=moduleImport("danger").getMember("SOURCE")
|
||||
sink(foo) # $ use=moduleImport("danger").getMember("SOURCE")
|
||||
|
||||
|
||||
# Built-ins
|
||||
|
||||
def use_of_builtins():
|
||||
for x in range(5): #$ use=moduleImport("builtins").getMember("range").getReturn()
|
||||
if x < len([]): #$ use=moduleImport("builtins").getMember("len").getReturn()
|
||||
print("Hello") #$ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
raise Exception("Farewell") #$ use=moduleImport("builtins").getMember("Exception").getReturn()
|
||||
for x in range(5): # $ use=moduleImport("builtins").getMember("range").getReturn()
|
||||
if x < len([]): # $ use=moduleImport("builtins").getMember("len").getReturn()
|
||||
print("Hello") # $ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
raise Exception("Farewell") # $ use=moduleImport("builtins").getMember("Exception").getReturn()
|
||||
|
||||
def imported_builtins():
|
||||
import builtins #$ use=moduleImport("builtins")
|
||||
import builtins # $ use=moduleImport("builtins")
|
||||
def open(f):
|
||||
return builtins.open(f) #$ use=moduleImport("builtins").getMember("open").getReturn()
|
||||
return builtins.open(f) # $ use=moduleImport("builtins").getMember("open").getReturn()
|
||||
|
||||
def redefine_print():
|
||||
def my_print(x):
|
||||
import builtins #$ use=moduleImport("builtins")
|
||||
builtins.print("I'm printing", x) #$ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
import builtins # $ use=moduleImport("builtins")
|
||||
builtins.print("I'm printing", x) # $ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
print = my_print
|
||||
print("these words")
|
||||
|
||||
@@ -109,13 +109,13 @@ def global_redefine_chr():
|
||||
|
||||
def what_is_chr_now():
|
||||
# If global_redefine_chr has been run, then the following is _not_ a reference to the built-in chr
|
||||
return chr(123) #$ MISSING: use=moduleImport("builtins").getMember("chr").getReturn()
|
||||
return chr(123) # $ MISSING: use=moduleImport("builtins").getMember("chr").getReturn()
|
||||
|
||||
def obscured_print():
|
||||
p = print #$ use=moduleImport("builtins").getMember("print")
|
||||
p("Can you see me?") #$ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
p = print # $ use=moduleImport("builtins").getMember("print")
|
||||
p("Can you see me?") # $ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
|
||||
def python2_style():
|
||||
# In Python 3, `__builtin__` has no special meaning.
|
||||
from __builtin__ import open #$ use=moduleImport("__builtin__").getMember("open")
|
||||
open("hello.txt") #$ use=moduleImport("__builtin__").getMember("open").getReturn()
|
||||
from __builtin__ import open # $ use=moduleImport("__builtin__").getMember("open")
|
||||
open("hello.txt") # $ use=moduleImport("__builtin__").getMember("open").getReturn()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import mypkg #$ use=moduleImport("mypkg")
|
||||
print(mypkg.foo) #$ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
import mypkg # $ use=moduleImport("mypkg")
|
||||
print(mypkg.foo) # $ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
try:
|
||||
print(mypkg.bar) #$ use=moduleImport("mypkg").getMember("bar")
|
||||
except AttributeError as e: #$ use=moduleImport("builtins").getMember("AttributeError")
|
||||
print(e) #$ use=moduleImport("builtins").getMember("print").getReturn() // module 'mypkg' has no attribute 'bar'
|
||||
print(mypkg.bar) # $ use=moduleImport("mypkg").getMember("bar")
|
||||
except AttributeError as e: # $ use=moduleImport("builtins").getMember("AttributeError")
|
||||
print(e) # $ use=moduleImport("builtins").getMember("print").getReturn() // module 'mypkg' has no attribute 'bar'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from mypkg import foo #$ use=moduleImport("mypkg").getMember("foo")
|
||||
from mypkg import bar #$ use=moduleImport("mypkg").getMember("bar")
|
||||
print(foo) #$ use=moduleImport("mypkg").getMember("foo")
|
||||
print(bar) #$ use=moduleImport("mypkg").getMember("bar")
|
||||
from mypkg import foo # $ use=moduleImport("mypkg").getMember("foo")
|
||||
from mypkg import bar # $ use=moduleImport("mypkg").getMember("bar")
|
||||
print(foo) # $ use=moduleImport("mypkg").getMember("foo")
|
||||
print(bar) # $ use=moduleImport("mypkg").getMember("bar")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import mypkg.foo #$ use=moduleImport("mypkg")
|
||||
import mypkg.bar #$ use=moduleImport("mypkg")
|
||||
print(mypkg.foo) #$ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
print(mypkg.bar) #$ use=moduleImport("mypkg").getMember("bar") // <module 'mypkg.bar' ...
|
||||
import mypkg.foo # $ use=moduleImport("mypkg")
|
||||
import mypkg.bar # $ use=moduleImport("mypkg")
|
||||
print(mypkg.foo) # $ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
print(mypkg.bar) # $ use=moduleImport("mypkg").getMember("bar") // <module 'mypkg.bar' ...
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import mypkg.foo as _foo #$ use=moduleImport("mypkg").getMember("foo")
|
||||
import mypkg.bar as _bar #$ use=moduleImport("mypkg").getMember("bar")
|
||||
print(_foo) #$ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
print(_bar) #$ use=moduleImport("mypkg").getMember("bar") // <module 'mypkg.bar' ...
|
||||
import mypkg.foo as _foo # $ use=moduleImport("mypkg").getMember("foo")
|
||||
import mypkg.bar as _bar # $ use=moduleImport("mypkg").getMember("bar")
|
||||
print(_foo) # $ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
print(_bar) # $ use=moduleImport("mypkg").getMember("bar") // <module 'mypkg.bar' ...
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import mypkg #$ use=moduleImport("mypkg")
|
||||
import mypkg # $ use=moduleImport("mypkg")
|
||||
|
||||
print(mypkg.foo) #$ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
print(mypkg.foo) # $ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
try:
|
||||
print(mypkg.bar) #$ use=moduleImport("mypkg").getMember("bar")
|
||||
except AttributeError as e: #$ use=moduleImport("builtins").getMember("AttributeError")
|
||||
print(e) #$ use=moduleImport("builtins").getMember("print").getReturn() // module 'mypkg' has no attribute 'bar'
|
||||
print(mypkg.bar) # $ use=moduleImport("mypkg").getMember("bar")
|
||||
except AttributeError as e: # $ use=moduleImport("builtins").getMember("AttributeError")
|
||||
print(e) # $ use=moduleImport("builtins").getMember("print").getReturn() // module 'mypkg' has no attribute 'bar'
|
||||
|
||||
from mypkg import bar as _bar #$ use=moduleImport("mypkg").getMember("bar")
|
||||
print(mypkg.bar) #$ use=moduleImport("mypkg").getMember("bar") // <module 'mypkg.bar' ...
|
||||
from mypkg import bar as _bar # $ use=moduleImport("mypkg").getMember("bar")
|
||||
print(mypkg.bar) # $ use=moduleImport("mypkg").getMember("bar") // <module 'mypkg.bar' ...
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import mypkg #$ use=moduleImport("mypkg")
|
||||
import mypkg # $ use=moduleImport("mypkg")
|
||||
|
||||
print(mypkg.foo) #$ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
print(mypkg.foo) # $ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
|
||||
import mypkg.foo #$ use=moduleImport("mypkg")
|
||||
print(mypkg.foo) #$ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
import mypkg.foo # $ use=moduleImport("mypkg")
|
||||
print(mypkg.foo) # $ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from mypkg import foo #$ use=moduleImport("mypkg").getMember("foo")
|
||||
from mypkg import foo # $ use=moduleImport("mypkg").getMember("foo")
|
||||
|
||||
print(foo) #$ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
print(foo) # $ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
|
||||
import mypkg.foo #$ use=moduleImport("mypkg")
|
||||
print(foo) #$ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
print(mypkg.foo) #$ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
import mypkg.foo # $ use=moduleImport("mypkg")
|
||||
print(foo) # $ use=moduleImport("mypkg").getMember("foo") // 42
|
||||
print(mypkg.foo) # $ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
|
||||
from mypkg import foo #$ use=moduleImport("mypkg").getMember("foo")
|
||||
print(foo) #$ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
from mypkg import foo # $ use=moduleImport("mypkg").getMember("foo")
|
||||
print(foo) # $ use=moduleImport("mypkg").getMember("foo") // <module 'mypkg.foo' ...
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
from types import AssignmentAnnotation, ParameterAnnotation
|
||||
|
||||
def test_annotated_assignment():
|
||||
local_x : AssignmentAnnotation = create_x() #$ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
local_x #$ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
local_x : AssignmentAnnotation = create_x() # $ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
local_x # $ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
|
||||
global_x : AssignmentAnnotation #$ use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
global_x #$ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
global_x : AssignmentAnnotation # $ use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
global_x # $ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
|
||||
def test_parameter_annotation(parameter_y: ParameterAnnotation): #$ use=moduleImport("types").getMember("ParameterAnnotation")
|
||||
parameter_y #$ use=moduleImport("types").getMember("ParameterAnnotation").getAnnotatedInstance()
|
||||
def test_parameter_annotation(parameter_y: ParameterAnnotation): # $ use=moduleImport("types").getMember("ParameterAnnotation")
|
||||
parameter_y # $ use=moduleImport("types").getMember("ParameterAnnotation").getAnnotatedInstance()
|
||||
|
||||
type Alias = AssignmentAnnotation
|
||||
|
||||
global_z : Alias #$ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
global_z #$ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
global_z : Alias # $ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
global_z # $ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
|
||||
def test_parameter_alias(parameter_z: Alias): #$ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
parameter_z #$ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
def test_parameter_alias(parameter_z: Alias): # $ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
parameter_z # $ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
|
||||
# local type aliases
|
||||
def test_local_type_alias():
|
||||
type LocalAlias = AssignmentAnnotation
|
||||
local_alias : LocalAlias = create_value() #$ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
local_alias #$ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
local_alias : LocalAlias = create_value() # $ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation")
|
||||
local_alias # $ MISSING: use=moduleImport("types").getMember("AssignmentAnnotation").getAnnotatedInstance()
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
from html import escape
|
||||
|
||||
def p(x):
|
||||
return escape(x) #$ use=moduleImport("html").getMember("escape").getReturn()
|
||||
return escape(x) # $ use=moduleImport("html").getMember("escape").getReturn()
|
||||
|
||||
def p_list(l):
|
||||
return ", ".join(p(x) for x in l) #$ use=moduleImport("html").getMember("escape").getReturn()
|
||||
return ", ".join(p(x) for x in l) # $ use=moduleImport("html").getMember("escape").getReturn()
|
||||
|
||||
def pp_list(l):
|
||||
def pp(x):
|
||||
return escape(x) #$ use=moduleImport("html").getMember("escape").getReturn()
|
||||
return escape(x) # $ use=moduleImport("html").getMember("escape").getReturn()
|
||||
|
||||
def pp_list_inner(l):
|
||||
return ", ".join(pp(x) for x in l) #$ use=moduleImport("html").getMember("escape").getReturn()
|
||||
return ", ".join(pp(x) for x in l) # $ use=moduleImport("html").getMember("escape").getReturn()
|
||||
|
||||
@@ -4,11 +4,11 @@ from flask_user import UserMixin
|
||||
|
||||
def create_app():
|
||||
app = Flask(__name__)
|
||||
db = SQLAlchemy(app) #$ use=moduleImport("flask_sqlalchemy").getMember("SQLAlchemy").getReturn()
|
||||
db = SQLAlchemy(app) # $ use=moduleImport("flask_sqlalchemy").getMember("SQLAlchemy").getReturn()
|
||||
|
||||
class Users(db.Model, UserMixin): #$ use=moduleImport("flask_sqlalchemy").getMember("SQLAlchemy").getReturn().getMember("Model").getASubclass()
|
||||
class Users(db.Model, UserMixin): # $ use=moduleImport("flask_sqlalchemy").getMember("SQLAlchemy").getReturn().getMember("Model").getASubclass()
|
||||
__tablename__ = 'users'
|
||||
|
||||
@app.route('/v2/user/<int:id>', methods=['GET','PUT'])
|
||||
def users(id):
|
||||
Users.query.filter_by(id=id).first() #$ use=moduleImport("flask_sqlalchemy").getMember("SQLAlchemy").getReturn().getMember("Model").getASubclass().getMember("query").getMember("filter_by")
|
||||
Users.query.filter_by(id=id).first() # $ use=moduleImport("flask_sqlalchemy").getMember("SQLAlchemy").getReturn().getMember("Model").getASubclass().getMember("query").getMember("filter_by")
|
||||
|
||||
@@ -10,17 +10,17 @@ def func():
|
||||
class Bar(B): pass
|
||||
|
||||
class Baz(A): pass
|
||||
|
||||
|
||||
def other_func():
|
||||
print(Foo) #$ use=moduleImport("foo").getMember("A").getASubclass() use=moduleImport("foo").getMember("B").getASubclass()
|
||||
print(Foo) # $ use=moduleImport("foo").getMember("A").getASubclass() use=moduleImport("foo").getMember("B").getASubclass()
|
||||
# On the next line, we wish to express that it is not possible for `Bar` to be a subclass of `A`.
|
||||
# However, we have no "true negative" annotation, so we use the MISSING annotation instead.
|
||||
# (Normally, "true negative" is not needed as all applicable annotations must be present,
|
||||
# but these API graph tests work differently, since having all results recorded in annotations
|
||||
# but these API graph tests work differently, since having all results recorded in annotations
|
||||
# would be excessive)
|
||||
print(Bar) #$ use=moduleImport("foo").getMember("B").getASubclass() MISSING: use=moduleImport("foo").getMember("A").getASubclass()
|
||||
print(Baz) #$ use=moduleImport("foo").getMember("B").getASubclass() SPURIOUS: use=moduleImport("foo").getMember("A").getASubclass()
|
||||
print(Bar) # $ use=moduleImport("foo").getMember("B").getASubclass() MISSING: use=moduleImport("foo").getMember("A").getASubclass()
|
||||
print(Baz) # $ use=moduleImport("foo").getMember("B").getASubclass() SPURIOUS: use=moduleImport("foo").getMember("A").getASubclass()
|
||||
|
||||
class Baz(B): pass
|
||||
|
||||
other_func()
|
||||
other_func()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from start.middle.end import foo #$ use=moduleImport("start").getMember("middle").getMember("end").getMember("foo")
|
||||
from start.middle.end import bar #$ use=moduleImport("start").getMember("middle").getMember("end").getMember("bar")
|
||||
print(foo) #$ use=moduleImport("start").getMember("middle").getMember("end").getMember("foo")
|
||||
print(bar) #$ use=moduleImport("start").getMember("middle").getMember("end").getMember("bar")
|
||||
from start.middle.end import foo # $ use=moduleImport("start").getMember("middle").getMember("end").getMember("foo")
|
||||
from start.middle.end import bar # $ use=moduleImport("start").getMember("middle").getMember("end").getMember("bar")
|
||||
print(foo) # $ use=moduleImport("start").getMember("middle").getMember("end").getMember("foo")
|
||||
print(bar) # $ use=moduleImport("start").getMember("middle").getMember("end").getMember("bar")
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
"magic_string".foo.bar #$ use=entryPoint("CustomEntryPoint").getMember("foo").getMember("bar")
|
||||
"magic_string".foo.bar # $ use=entryPoint("CustomEntryPoint").getMember("foo").getMember("bar")
|
||||
"magic_string2".foo.bar
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Star imports
|
||||
|
||||
from unknown import * #$ use=moduleImport("unknown")
|
||||
from unknown import * # $ use=moduleImport("unknown")
|
||||
|
||||
# This used to be missing, as we did not consider `hello` to be a `LocalSourceNode`,
|
||||
# since it has flow going into it from its corresponding `GlobalSsaVariable`.
|
||||
hello() #$ use=moduleImport("unknown").getMember("hello").getReturn()
|
||||
hello() # $ use=moduleImport("unknown").getMember("hello").getReturn()
|
||||
|
||||
print(const_from_unknown) #$ use=moduleImport("unknown").getMember("const_from_unknown")
|
||||
print(const_from_unknown) # $ use=moduleImport("unknown").getMember("const_from_unknown")
|
||||
|
||||
# We don't want our analysis to think that either `non_module_member` or `outer_bar` can
|
||||
# come from `from unknown import *`
|
||||
@@ -16,23 +16,23 @@ outer_bar = 5
|
||||
outer_bar
|
||||
|
||||
def foo():
|
||||
world() #$ use=moduleImport("unknown").getMember("world").getReturn()
|
||||
world() # $ use=moduleImport("unknown").getMember("world").getReturn()
|
||||
bar = 5
|
||||
bar
|
||||
non_module_member
|
||||
print(bar) #$ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
print(bar) # $ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
|
||||
def quux():
|
||||
global non_module_member
|
||||
non_module_member = 5
|
||||
|
||||
def func1():
|
||||
var() #$ use=moduleImport("unknown").getMember("var").getReturn()
|
||||
var() # $ use=moduleImport("unknown").getMember("var").getReturn()
|
||||
def func2():
|
||||
var = "FOO"
|
||||
|
||||
def func3():
|
||||
var2 = print #$ use=moduleImport("builtins").getMember("print")
|
||||
var2 = print # $ use=moduleImport("builtins").getMember("print")
|
||||
def func4():
|
||||
var2() #$ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
var2() # $ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
func4()
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Star imports in local scope
|
||||
|
||||
hello2()
|
||||
hello2()
|
||||
|
||||
def foo():
|
||||
from unknown2 import * #$ use=moduleImport("unknown2")
|
||||
world2() #$ use=moduleImport("unknown2").getMember("world2").getReturn()
|
||||
from unknown2 import * # $ use=moduleImport("unknown2")
|
||||
world2() # $ use=moduleImport("unknown2").getMember("world2").getReturn()
|
||||
bar2 = 5
|
||||
bar2
|
||||
non_module_member2
|
||||
print(bar2) #$ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
print(bar2) # $ use=moduleImport("builtins").getMember("print").getReturn()
|
||||
|
||||
def quux2():
|
||||
global non_module_member2
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import mypkg
|
||||
|
||||
def test_subscript():
|
||||
bar = mypkg.foo()["bar"] #$ use=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
mypkg.foo()["baz"] = 42 #$ def=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
mypkg.foo()["qux"] += 42 #$ use=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
mypkg.foo()["qux"] += 42 #$ def=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
mypkg.foo()[mypkg.index] = mypkg.value #$ def=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
bar = mypkg.foo()["bar"] # $ use=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
mypkg.foo()["baz"] = 42 # $ def=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
mypkg.foo()["qux"] += 42 # $ use=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
mypkg.foo()["qux"] += 42 # $ def=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
mypkg.foo()[mypkg.index] = mypkg.value # $ def=moduleImport("mypkg").getMember("foo").getReturn().getASubscript()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
def obfuscated_id(x): #$ step="FunctionExpr -> obfuscated_id"
|
||||
y = x #$ step="x -> y" step="x, l:-1 -> x"
|
||||
z = y #$ step="y -> z" step="y, l:-1 -> y"
|
||||
return z #$ flow="42, l:+2 -> z" step="z, l:-1 -> z"
|
||||
def obfuscated_id(x): # $ step="FunctionExpr -> obfuscated_id"
|
||||
y = x # $ step="x -> y" step="x, l:-1 -> x"
|
||||
z = y # $ step="y -> z" step="y, l:-1 -> y"
|
||||
return z # $ flow="42, l:+2 -> z" step="z, l:-1 -> z"
|
||||
|
||||
a = 42 #$ step="42 -> a"
|
||||
b = obfuscated_id(a) #$ flow="42, l:-1 -> b" flow="FunctionExpr, l:-6 -> obfuscated_id" step="obfuscated_id(..) -> b" step="obfuscated_id, l:-6 -> obfuscated_id" step="a, l:-1 -> a"
|
||||
a = 42 # $ step="42 -> a"
|
||||
b = obfuscated_id(a) # $ flow="42, l:-1 -> b" flow="FunctionExpr, l:-6 -> obfuscated_id" step="obfuscated_id(..) -> b" step="obfuscated_id, l:-6 -> obfuscated_id" step="a, l:-1 -> a"
|
||||
|
||||
@@ -50,5 +50,5 @@ class With_index:
|
||||
def test_index():
|
||||
import operator
|
||||
|
||||
with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__
|
||||
with_index = With_index() # $ MISSING: arg1="SSA variable with_index" func=With_index.__index__
|
||||
operator.index(with_index)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| classes.py:54:44:54:107 | Comment #$ arg1="with_length_hint" func=With_length_hint.__length_hint__ | Missing result: arg1="with_length_hint" |
|
||||
| classes.py:54:44:54:107 | Comment #$ arg1="with_length_hint" func=With_length_hint.__length_hint__ | Missing result: func=With_length_hint.__length_hint__ |
|
||||
| classes.py:71:32:71:77 | Comment #$ arg1="with_index" func=With_index.__index__ | Missing result: arg1="with_index" |
|
||||
| classes.py:71:32:71:77 | Comment #$ arg1="with_index" func=With_index.__index__ | Missing result: func=With_index.__index__ |
|
||||
| classes.py:54:44:54:108 | Comment # $ arg1="with_length_hint" func=With_length_hint.__length_hint__ | Missing result: arg1="with_length_hint" |
|
||||
| classes.py:54:44:54:108 | Comment # $ arg1="with_length_hint" func=With_length_hint.__length_hint__ | Missing result: func=With_length_hint.__length_hint__ |
|
||||
| classes.py:71:32:71:78 | Comment # $ arg1="with_index" func=With_index.__index__ | Missing result: arg1="with_index" |
|
||||
| classes.py:71:32:71:78 | Comment # $ arg1="with_index" func=With_index.__index__ | Missing result: func=With_index.__index__ |
|
||||
|
||||
@@ -51,7 +51,7 @@ class With_length_hint:
|
||||
def test_length_hint():
|
||||
import operator
|
||||
|
||||
with_length_hint = With_length_hint() #$ arg1="with_length_hint" func=With_length_hint.__length_hint__
|
||||
with_length_hint = With_length_hint() # $ arg1="with_length_hint" func=With_length_hint.__length_hint__
|
||||
operator.length_hint(with_length_hint)
|
||||
|
||||
|
||||
@@ -68,5 +68,5 @@ class With_index:
|
||||
def test_index():
|
||||
import operator
|
||||
|
||||
with_index = With_index() #$ arg1="with_index" func=With_index.__index__
|
||||
with_index = With_index() # $ arg1="with_index" func=With_index.__index__
|
||||
operator.index(with_index)
|
||||
|
||||
@@ -53,9 +53,9 @@ def argument_passing(
|
||||
b,
|
||||
/,
|
||||
c,
|
||||
d=arg4, #$ arg4 func=argument_passing
|
||||
d=arg4, # $ arg4 func=argument_passing
|
||||
*,
|
||||
e=arg5, #$ arg5 func=argument_passing
|
||||
e=arg5, # $ arg5 func=argument_passing
|
||||
f,
|
||||
**g,
|
||||
):
|
||||
@@ -73,12 +73,12 @@ def argument_passing(
|
||||
|
||||
@expects(7)
|
||||
def test_argument_passing1():
|
||||
argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7}) #$ arg1 arg5 arg6 arg7 func=argument_passing MISSING: arg2 arg3 arg4
|
||||
argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7}) # $ arg1 arg5 arg6 arg7 func=argument_passing MISSING: arg2 arg3 arg4
|
||||
|
||||
|
||||
@expects(7)
|
||||
def test_argument_passing2():
|
||||
argument_passing(arg1, arg2, arg3, f=arg6) #$ arg1 arg2 arg3 arg6
|
||||
argument_passing(arg1, arg2, arg3, f=arg6) # $ arg1 arg2 arg3 arg6
|
||||
|
||||
|
||||
def with_pos_only(a, /, b):
|
||||
@@ -88,9 +88,9 @@ def with_pos_only(a, /, b):
|
||||
|
||||
@expects(6)
|
||||
def test_pos_only():
|
||||
with_pos_only(arg1, arg2) #$ arg1 arg2
|
||||
with_pos_only(arg1, b=arg2) #$ arg1 arg2
|
||||
with_pos_only(arg1, *(arg2,)) #$ arg1 MISSING: arg2
|
||||
with_pos_only(arg1, arg2) # $ arg1 arg2
|
||||
with_pos_only(arg1, b=arg2) # $ arg1 arg2
|
||||
with_pos_only(arg1, *(arg2,)) # $ arg1 MISSING: arg2
|
||||
|
||||
|
||||
def with_multiple_kw_args(a, b, c):
|
||||
@@ -101,13 +101,13 @@ def with_multiple_kw_args(a, b, c):
|
||||
|
||||
@expects(12)
|
||||
def test_multiple_kw_args():
|
||||
with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1 arg2 arg3
|
||||
with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1 MISSING: arg2 arg3
|
||||
with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1 arg2 arg3 func=with_multiple_kw_args
|
||||
with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) #$ arg1 arg2 arg3 func=with_multiple_kw_args
|
||||
with_multiple_kw_args(b=arg2, c=arg3, a=arg1) # $ arg1 arg2 arg3
|
||||
with_multiple_kw_args(arg1, *(arg2,), arg3) # $ arg1 MISSING: arg2 arg3
|
||||
with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) # $ arg1 arg2 arg3 func=with_multiple_kw_args
|
||||
with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) # $ arg1 arg2 arg3 func=with_multiple_kw_args
|
||||
|
||||
|
||||
def with_default_arguments(a=arg1, b=arg2, c=arg3): #$ arg1 arg2 arg3 func=with_default_arguments
|
||||
def with_default_arguments(a=arg1, b=arg2, c=arg3): # $ arg1 arg2 arg3 func=with_default_arguments
|
||||
SINK1(a)
|
||||
SINK2(b)
|
||||
SINK3(c)
|
||||
@@ -116,9 +116,9 @@ def with_default_arguments(a=arg1, b=arg2, c=arg3): #$ arg1 arg2 arg3 func=with
|
||||
@expects(12)
|
||||
def test_default_arguments():
|
||||
with_default_arguments()
|
||||
with_default_arguments(arg1) #$ arg1
|
||||
with_default_arguments(b=arg2) #$ arg2
|
||||
with_default_arguments(**{"c": arg3}) #$ arg3 func=with_default_arguments
|
||||
with_default_arguments(arg1) # $ arg1
|
||||
with_default_arguments(b=arg2) # $ arg2
|
||||
with_default_arguments(**{"c": arg3}) # $ arg3 func=with_default_arguments
|
||||
|
||||
|
||||
# All combinations
|
||||
@@ -126,14 +126,14 @@ def test_pos_pos():
|
||||
def with_pos(a):
|
||||
SINK1(a)
|
||||
|
||||
with_pos(arg1) #$ arg1 func=test_pos_pos.with_pos
|
||||
with_pos(arg1) # $ arg1 func=test_pos_pos.with_pos
|
||||
|
||||
|
||||
def test_pos_pos_only():
|
||||
def with_pos_only(a, /):
|
||||
SINK1(a)
|
||||
|
||||
with_pos_only(arg1) #$ arg1 func=test_pos_pos_only.with_pos_only
|
||||
with_pos_only(arg1) # $ arg1 func=test_pos_pos_only.with_pos_only
|
||||
|
||||
|
||||
def test_pos_star():
|
||||
@@ -141,35 +141,35 @@ def test_pos_star():
|
||||
if len(a) > 0:
|
||||
SINK1(a[0])
|
||||
|
||||
with_star(arg1) #$ arg1 func=test_pos_star.with_star
|
||||
with_star(arg1) # $ arg1 func=test_pos_star.with_star
|
||||
|
||||
|
||||
def test_pos_kw():
|
||||
def with_kw(a=""):
|
||||
SINK1(a)
|
||||
|
||||
with_kw(arg1) #$ arg1 func=test_pos_kw.with_kw
|
||||
with_kw(arg1) # $ arg1 func=test_pos_kw.with_kw
|
||||
|
||||
|
||||
def test_kw_pos():
|
||||
def with_pos(a):
|
||||
SINK1(a)
|
||||
|
||||
with_pos(a=arg1) #$ arg1 func=test_kw_pos.with_pos
|
||||
with_pos(a=arg1) # $ arg1 func=test_kw_pos.with_pos
|
||||
|
||||
|
||||
def test_kw_kw():
|
||||
def with_kw(a=""):
|
||||
SINK1(a)
|
||||
|
||||
with_kw(a=arg1) #$ arg1 func=test_kw_kw.with_kw
|
||||
with_kw(a=arg1) # $ arg1 func=test_kw_kw.with_kw
|
||||
|
||||
|
||||
def test_kw_doublestar():
|
||||
def with_doublestar(**kwargs):
|
||||
SINK1(kwargs["a"])
|
||||
|
||||
with_doublestar(a=arg1) #$ arg1 func=test_kw_doublestar.with_doublestar
|
||||
with_doublestar(a=arg1) # $ arg1 func=test_kw_doublestar.with_doublestar
|
||||
|
||||
|
||||
def only_kwargs(**kwargs):
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -58,7 +58,7 @@ SINK7 = functools.partial(SINK, expected=arg7)
|
||||
def f(a, b):
|
||||
return a
|
||||
|
||||
SINK(f(SOURCE, 3)) #$ flow="SOURCE -> f(..)"
|
||||
SINK(f(SOURCE, 3)) # $ flow="SOURCE -> f(..)"
|
||||
|
||||
# Instance methods
|
||||
# An instance method object combines a class, a class instance and any callable object (normally a user-defined function).
|
||||
@@ -236,10 +236,10 @@ class Customized:
|
||||
|
||||
# testing __new__ and __init__
|
||||
customized = Customized()
|
||||
SINK(Customized.a) #$ MISSING:flow="SOURCE, l:-8 -> customized.a"
|
||||
SINK(Customized.a) # $ MISSING:flow="SOURCE, l:-8 -> customized.a"
|
||||
SINK_F(Customized.b)
|
||||
SINK(customized.a) #$ MISSING: flow="SOURCE, l:-10 -> customized.a"
|
||||
SINK(customized.b) #$ flow="SOURCE, l:-7 -> customized.b"
|
||||
SINK(customized.a) # $ MISSING: flow="SOURCE, l:-10 -> customized.a"
|
||||
SINK(customized.b) # $ flow="SOURCE, l:-7 -> customized.b"
|
||||
|
||||
|
||||
class Test2:
|
||||
|
||||
@@ -38,7 +38,7 @@ def test_while():
|
||||
n = 2
|
||||
while n > 0:
|
||||
if n == 1:
|
||||
SINK(x) #$ flow="SOURCE, l:+1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:+1 -> x"
|
||||
x = SOURCE
|
||||
n -= 1
|
||||
|
||||
@@ -54,14 +54,14 @@ def test_while_obj():
|
||||
n = 2
|
||||
while n > 0:
|
||||
if n == 1:
|
||||
SINK(myobj.foo) #$ flow="SOURCE, l:+1 -> myobj.foo"
|
||||
SINK(myobj.foo) # $ flow="SOURCE, l:+1 -> myobj.foo"
|
||||
setFoo(myobj, SOURCE)
|
||||
n -= 1
|
||||
|
||||
def setAndTestFoo(obj, x, test):
|
||||
if test:
|
||||
# This flow is not found, if self-loops are broken at the SSA level.
|
||||
SINK(obj.foo) #$ flow="SOURCE, l:+7 -> obj.foo"
|
||||
SINK(obj.foo) # $ flow="SOURCE, l:+7 -> obj.foo"
|
||||
obj.foo = x
|
||||
|
||||
def test_while_obj_sink():
|
||||
@@ -70,4 +70,3 @@ def test_while_obj_sink():
|
||||
while n > 0:
|
||||
setAndTestFoo(myobj, SOURCE, n == 1)
|
||||
n -= 1
|
||||
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
|
||||
t = (SOURCE, NONSOURCE)
|
||||
a, b = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK(a) # $ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
|
||||
@@ -41,7 +41,7 @@ def SINK_F(x):
|
||||
def test_tuple_with_local_flow():
|
||||
x = (NONSOURCE, SOURCE)
|
||||
y = x[1]
|
||||
SINK(y) #$ flow="SOURCE, l:-2 -> y"
|
||||
SINK(y) # $ flow="SOURCE, l:-2 -> y"
|
||||
|
||||
|
||||
def test_tuple_negative():
|
||||
@@ -53,45 +53,45 @@ def test_tuple_negative():
|
||||
# 6.2.1. Identifiers (Names)
|
||||
def test_names():
|
||||
x = SOURCE
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
|
||||
|
||||
# 6.2.2. Literals
|
||||
def test_string_literal():
|
||||
x = "source"
|
||||
SINK(x) #$ flow="'source', l:-1 -> x"
|
||||
SINK(x) # $ flow="'source', l:-1 -> x"
|
||||
|
||||
|
||||
def test_bytes_literal():
|
||||
x = b"source"
|
||||
SINK(x) #$ flow="b'source', l:-1 -> x"
|
||||
SINK(x) # $ flow="b'source', l:-1 -> x"
|
||||
|
||||
|
||||
def test_integer_literal():
|
||||
x = 42
|
||||
SINK(x) #$ flow="42, l:-1 -> x"
|
||||
SINK(x) # $ flow="42, l:-1 -> x"
|
||||
|
||||
|
||||
def test_floatnumber_literal():
|
||||
x = 42.0
|
||||
SINK(x) #$ flow="42.0, l:-1 -> x"
|
||||
SINK(x) # $ flow="42.0, l:-1 -> x"
|
||||
|
||||
|
||||
def test_imagnumber_literal():
|
||||
x = 42j
|
||||
SINK(x) #$ MISSING:flow="42j, l:-1 -> x"
|
||||
SINK(x) # $ MISSING:flow="42j, l:-1 -> x"
|
||||
|
||||
|
||||
# 6.2.3. Parenthesized forms
|
||||
def test_parenthesized_form():
|
||||
x = (SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
|
||||
|
||||
# 6.2.5. List displays
|
||||
def test_list_display():
|
||||
x = [SOURCE]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_list_display_negative():
|
||||
@@ -101,23 +101,23 @@ def test_list_display_negative():
|
||||
|
||||
def test_list_comprehension():
|
||||
x = [SOURCE for y in [NONSOURCE]]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_list_comprehension_flow():
|
||||
x = [y for y in [SOURCE]]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_list_comprehension_inflow():
|
||||
l = [SOURCE]
|
||||
x = [y for y in l]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-2 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-2 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_list_display():
|
||||
x = [*[SOURCE]]
|
||||
SINK(x[0]) #$ MISSING:flow="SOURCE, l:-1 -> x[0]"
|
||||
SINK(x[0]) # $ MISSING:flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
@expects(6)
|
||||
@@ -144,98 +144,98 @@ def test_list_comprehension_with_tuple_result():
|
||||
# 6.2.6. Set displays
|
||||
def test_set_display():
|
||||
x = {SOURCE}
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()"
|
||||
SINK(x.pop()) # $ flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension():
|
||||
x = {SOURCE for y in [NONSOURCE]}
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()"
|
||||
SINK(x.pop()) # $ flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension_flow():
|
||||
x = {y for y in [SOURCE]}
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()"
|
||||
SINK(x.pop()) # $ flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_set_comprehension_inflow():
|
||||
l = {SOURCE}
|
||||
x = {y for y in l}
|
||||
SINK(x.pop()) #$ flow="SOURCE, l:-2 -> x.pop()"
|
||||
SINK(x.pop()) # $ flow="SOURCE, l:-2 -> x.pop()"
|
||||
|
||||
|
||||
def test_nested_set_display():
|
||||
x = {*{SOURCE}}
|
||||
SINK(x.pop()) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
SINK(x.pop()) # $ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
# 6.2.7. Dictionary displays
|
||||
def test_dict_display():
|
||||
x = {"s": SOURCE}
|
||||
SINK(x["s"]) #$ flow="SOURCE, l:-1 -> x['s']"
|
||||
SINK(x["s"]) # $ flow="SOURCE, l:-1 -> x['s']"
|
||||
|
||||
|
||||
def test_dict_display_pop():
|
||||
x = {"s": SOURCE}
|
||||
SINK(x.pop("s")) #$ flow="SOURCE, l:-1 -> x.pop(..)"
|
||||
SINK(x.pop("s")) # $ flow="SOURCE, l:-1 -> x.pop(..)"
|
||||
|
||||
|
||||
def test_dict_comprehension():
|
||||
x = {y: SOURCE for y in ["s"]}
|
||||
SINK(x["s"]) #$ MISSING:flow="SOURCE, l:-1 -> x['s']"
|
||||
SINK(x["s"]) # $ MISSING:flow="SOURCE, l:-1 -> x['s']"
|
||||
|
||||
|
||||
def test_dict_comprehension_pop():
|
||||
x = {y: SOURCE for y in ["s"]}
|
||||
SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
SINK(x.pop("s")) # $ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
def test_nested_dict_display():
|
||||
x = {**{"s": SOURCE}}
|
||||
SINK(x["s"]) #$ MISSING:flow="SOURCE, l:-1 -> x['s']"
|
||||
SINK(x["s"]) # $ MISSING:flow="SOURCE, l:-1 -> x['s']"
|
||||
|
||||
|
||||
def test_nested_dict_display_pop():
|
||||
x = {**{"s": SOURCE}}
|
||||
SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
SINK(x.pop("s")) # $ MISSING:flow="SOURCE, l:-1 -> x.pop()"
|
||||
|
||||
|
||||
# Nested comprehensions
|
||||
def test_nested_comprehension():
|
||||
x = [y for z in [[SOURCE]] for y in z]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_comprehension_deep_with_local_flow():
|
||||
x = [y for v in [[[[SOURCE]]]] for u in v for z in u for y in z]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_comprehension_dict():
|
||||
d = {"s": [SOURCE]}
|
||||
x = [y for k, v in d.items() for y in v]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-2 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-2 -> x[0]"
|
||||
|
||||
|
||||
def test_nested_comprehension_paren():
|
||||
x = [y for y in (z for z in [SOURCE])]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
# Iterable unpacking in comprehensions
|
||||
def test_unpacking_comprehension():
|
||||
x = [a for (a, b) in [(SOURCE, NONSOURCE)]]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
def test_star_unpacking_comprehension():
|
||||
x = [a[0] for (*a, b) in [(SOURCE, NONSOURCE)]]
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]"
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-1 -> x[0]"
|
||||
|
||||
|
||||
# 6.2.8. Generator expressions
|
||||
def test_generator():
|
||||
x = (SOURCE for y in [NONSOURCE])
|
||||
SINK([*x][0]) #$ MISSING:flow="SOURCE, l:-1 -> List[0]"
|
||||
SINK([*x][0]) # $ MISSING:flow="SOURCE, l:-1 -> List[0]"
|
||||
|
||||
|
||||
# 6.2.9. Yield expressions
|
||||
@@ -245,7 +245,7 @@ def gen(x):
|
||||
|
||||
def test_yield():
|
||||
g = gen(SOURCE)
|
||||
SINK(next(g)) #$ flow="SOURCE, l:-1 -> next(..)"
|
||||
SINK(next(g)) # $ flow="SOURCE, l:-1 -> next(..)"
|
||||
|
||||
|
||||
def gen_from(x):
|
||||
@@ -254,19 +254,19 @@ def gen_from(x):
|
||||
|
||||
def test_yield_from():
|
||||
g = gen_from(SOURCE)
|
||||
SINK(next(g)) #$ MISSING:flow="SOURCE, l:-1 -> next()"
|
||||
SINK(next(g)) # $ MISSING:flow="SOURCE, l:-1 -> next()"
|
||||
|
||||
|
||||
# a statement rather than an expression, but related to generators
|
||||
def test_for():
|
||||
for x in gen(SOURCE):
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
|
||||
|
||||
# 6.2.9.1. Generator-iterator methods
|
||||
def test___next__():
|
||||
g = gen(SOURCE)
|
||||
SINK(g.__next__()) #$ MISSING:flow="SOURCE, l:-1 -> g.__next__()"
|
||||
SINK(g.__next__()) # $ MISSING:flow="SOURCE, l:-1 -> g.__next__()"
|
||||
|
||||
|
||||
def gen2(x):
|
||||
@@ -278,7 +278,7 @@ def gen2(x):
|
||||
def test_send():
|
||||
g = gen2(NONSOURCE)
|
||||
n = next(g)
|
||||
SINK(g.send(SOURCE)) #$ MISSING:flow="SOURCE -> g.send()"
|
||||
SINK(g.send(SOURCE)) # $ MISSING:flow="SOURCE -> g.send()"
|
||||
|
||||
|
||||
def gen_ex(x):
|
||||
@@ -291,7 +291,7 @@ def gen_ex(x):
|
||||
def test_throw():
|
||||
g = gen_ex(SOURCE)
|
||||
n = next(g)
|
||||
SINK(g.throw(TypeError)) #$ MISSING:flow="SOURCE, l:-2 -> g.throw()"
|
||||
SINK(g.throw(TypeError)) # $ MISSING:flow="SOURCE, l:-2 -> g.throw()"
|
||||
|
||||
|
||||
# no `test_close` as `close` involves no data flow
|
||||
@@ -312,7 +312,7 @@ def runa(a):
|
||||
|
||||
async def atest___anext__():
|
||||
g = agen(SOURCE)
|
||||
SINK(await g.__anext__()) #$ MISSING:flow="SOURCE, l:-1 -> g.__anext__()"
|
||||
SINK(await g.__anext__()) # $ MISSING:flow="SOURCE, l:-1 -> g.__anext__()"
|
||||
|
||||
|
||||
def test___anext__():
|
||||
@@ -328,7 +328,7 @@ async def agen2(x):
|
||||
async def atest_asend():
|
||||
g = agen2(NONSOURCE)
|
||||
n = await g.__anext__()
|
||||
SINK(await g.asend(SOURCE)) #$ MISSING:flow="SOURCE -> g.asend()"
|
||||
SINK(await g.asend(SOURCE)) # $ MISSING:flow="SOURCE -> g.asend()"
|
||||
|
||||
|
||||
def test_asend():
|
||||
@@ -345,7 +345,7 @@ async def agen_ex(x):
|
||||
async def atest_athrow():
|
||||
g = agen_ex(SOURCE)
|
||||
n = await g.__anext__()
|
||||
SINK(await g.athrow(TypeError)) #$ MISSING:flow="SOURCE, l:-2 -> g.athrow()"
|
||||
SINK(await g.athrow(TypeError)) # $ MISSING:flow="SOURCE, l:-2 -> g.athrow()"
|
||||
|
||||
|
||||
def test_athrow():
|
||||
@@ -367,15 +367,15 @@ def test_attribute_reference():
|
||||
|
||||
# 6.3.2. Subscriptions
|
||||
def test_subscription_tuple():
|
||||
SINK((SOURCE,)[0]) #$ flow="SOURCE -> Tuple[0]"
|
||||
SINK((SOURCE,)[0]) # $ flow="SOURCE -> Tuple[0]"
|
||||
|
||||
|
||||
def test_subscription_list():
|
||||
SINK([SOURCE][0]) #$ flow="SOURCE -> List[0]"
|
||||
SINK([SOURCE][0]) # $ flow="SOURCE -> List[0]"
|
||||
|
||||
|
||||
def test_subscription_mapping():
|
||||
SINK({"s": SOURCE}["s"]) #$ flow="SOURCE -> Dict['s']"
|
||||
SINK({"s": SOURCE}["s"]) # $ flow="SOURCE -> Dict['s']"
|
||||
|
||||
|
||||
# overriding __getitem__ should be tested by the class coverage tests
|
||||
@@ -387,7 +387,7 @@ l = [SOURCE]
|
||||
|
||||
def test_slicing():
|
||||
s = l[0:1:1]
|
||||
SINK(s[0]) #$ MISSING:flow="SOURCE -> s[0]"
|
||||
SINK(s[0]) # $ MISSING:flow="SOURCE -> s[0]"
|
||||
|
||||
|
||||
# The grammar seems to allow `l[0:1:1, 0:1]`, but the interpreter does not like it
|
||||
@@ -398,7 +398,7 @@ def second(a, b):
|
||||
|
||||
|
||||
def test_call_positional():
|
||||
SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)"
|
||||
SINK(second(NONSOURCE, SOURCE)) # $ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_call_positional_negative():
|
||||
@@ -406,15 +406,15 @@ def test_call_positional_negative():
|
||||
|
||||
|
||||
def test_call_keyword():
|
||||
SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)"
|
||||
SINK(second(NONSOURCE, b=SOURCE)) # $ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_call_unpack_iterable():
|
||||
SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)"
|
||||
SINK(second(NONSOURCE, *[SOURCE])) # $ MISSING:flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_call_unpack_mapping():
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)"
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) # $ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def f_extra_pos(a, *b):
|
||||
@@ -422,7 +422,7 @@ def f_extra_pos(a, *b):
|
||||
|
||||
|
||||
def test_call_extra_pos():
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)"
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) # $ flow="SOURCE -> f_extra_pos(..)"
|
||||
|
||||
|
||||
def f_extra_keyword(a, **b):
|
||||
@@ -430,7 +430,7 @@ def f_extra_keyword(a, **b):
|
||||
|
||||
|
||||
def test_call_extra_keyword():
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)"
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) # $ flow="SOURCE -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
# return the name of the first extra keyword argument
|
||||
@@ -440,34 +440,34 @@ def f_extra_keyword_flow(**a):
|
||||
|
||||
# call the function with our source as the name of the keyword arguemnt
|
||||
def test_call_extra_keyword_flow():
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)"
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) # $ MISSING:flow="SOURCE -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
# 6.11. Boolean operations
|
||||
|
||||
def test_or(x = False):
|
||||
# if we don't know the value of the lhs, we should always add flow
|
||||
SINK(x or SOURCE) #$ flow="SOURCE -> BoolExpr"
|
||||
SINK(x or SOURCE) # $ flow="SOURCE -> BoolExpr"
|
||||
|
||||
|
||||
def test_and(x = True):
|
||||
# if we don't know the value of the lhs, we should always add flow
|
||||
SINK(x and SOURCE) #$ flow="SOURCE -> BoolExpr"
|
||||
SINK(x and SOURCE) # $ flow="SOURCE -> BoolExpr"
|
||||
|
||||
|
||||
# 6.12. Assignment expressions
|
||||
def test_assignment_expression_flow_lhs():
|
||||
x = NONSOURCE
|
||||
if x := SOURCE:
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
|
||||
def test_assignment_expression_flow_out():
|
||||
x = NONSOURCE
|
||||
SINK(x := SOURCE) #$ flow="SOURCE -> AssignExpr"
|
||||
SINK(x := SOURCE) # $ flow="SOURCE -> AssignExpr"
|
||||
|
||||
# 6.13. Conditional expressions
|
||||
def test_conditional_true():
|
||||
SINK(SOURCE if True else NONSOURCE) #$ flow="SOURCE -> IfExp"
|
||||
SINK(SOURCE if True else NONSOURCE) # $ flow="SOURCE -> IfExp"
|
||||
|
||||
|
||||
def test_conditional_true_guards():
|
||||
@@ -475,7 +475,7 @@ def test_conditional_true_guards():
|
||||
|
||||
|
||||
def test_conditional_false():
|
||||
SINK(NONSOURCE if False else SOURCE) #$ flow="SOURCE -> IfExp"
|
||||
SINK(NONSOURCE if False else SOURCE) # $ flow="SOURCE -> IfExp"
|
||||
|
||||
|
||||
def test_conditional_false_guards():
|
||||
@@ -485,13 +485,13 @@ def test_conditional_false_guards():
|
||||
# Condition is evaluated first, so x is SOURCE once chosen
|
||||
def test_conditional_evaluation_true():
|
||||
x = NONSOURCE
|
||||
SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) #$ flow="SOURCE -> IfExp"
|
||||
SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) # $ flow="SOURCE -> IfExp"
|
||||
|
||||
|
||||
# Condition is evaluated first, so x is SOURCE once chosen
|
||||
def test_conditional_evaluation_false():
|
||||
x = NONSOURCE
|
||||
SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) #$ flow="SOURCE -> IfExp"
|
||||
SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) # $ flow="SOURCE -> IfExp"
|
||||
|
||||
|
||||
# 6.14. Lambdas
|
||||
@@ -499,14 +499,14 @@ def test_lambda():
|
||||
def f(x):
|
||||
return x
|
||||
|
||||
SINK(f(SOURCE)) #$ flow="SOURCE -> f(..)"
|
||||
SINK(f(SOURCE)) # $ flow="SOURCE -> f(..)"
|
||||
|
||||
|
||||
def test_lambda_positional():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)"
|
||||
SINK(second(NONSOURCE, SOURCE)) # $ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_lambda_positional_negative():
|
||||
@@ -520,57 +520,57 @@ def test_lambda_keyword():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)"
|
||||
SINK(second(NONSOURCE, b=SOURCE)) # $ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_lambda_unpack_iterable():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" # Flow missing
|
||||
SINK(second(NONSOURCE, *[SOURCE])) # $ MISSING:flow="SOURCE -> second(..)" # Flow missing
|
||||
|
||||
|
||||
def test_lambda_unpack_mapping():
|
||||
def second(a, b):
|
||||
return b
|
||||
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)"
|
||||
SINK(second(NONSOURCE, **{"b": SOURCE})) # $ flow="SOURCE -> second(..)"
|
||||
|
||||
|
||||
def test_lambda_extra_pos():
|
||||
f_extra_pos = lambda a, *b: b[0]
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)"
|
||||
SINK(f_extra_pos(NONSOURCE, SOURCE)) # $ flow="SOURCE -> f_extra_pos(..)"
|
||||
|
||||
|
||||
def test_lambda_extra_keyword():
|
||||
f_extra_keyword = lambda a, **b: b["b"]
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)"
|
||||
SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) # $ flow="SOURCE -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
# call the function with our source as the name of the keyword argument
|
||||
def test_lambda_extra_keyword_flow():
|
||||
# return the name of the first extra keyword argument
|
||||
f_extra_keyword_flow = lambda **a: [*a][0]
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)"
|
||||
SINK(f_extra_keyword_flow(**{SOURCE: None})) # $ MISSING:flow="SOURCE -> f_extra_keyword(..)"
|
||||
|
||||
|
||||
@expects(4)
|
||||
def test_swap():
|
||||
a = SOURCE
|
||||
b = NONSOURCE
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK(a) # $ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
|
||||
a, b = b, a
|
||||
SINK_F(a)
|
||||
SINK(b) #$ flow="SOURCE, l:-7 -> b"
|
||||
SINK(b) # $ flow="SOURCE, l:-7 -> b"
|
||||
|
||||
|
||||
@expects(2)
|
||||
def test_unpacking_assignment():
|
||||
t = (SOURCE, NONSOURCE)
|
||||
a, b = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK(a) # $ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
|
||||
|
||||
@@ -578,16 +578,16 @@ def test_unpacking_assignment():
|
||||
def test_nested_unpacking_assignment():
|
||||
t = (SOURCE, (NONSOURCE, SOURCE))
|
||||
a, (b, c) = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK(a) # $ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
SINK(c) #$ flow="SOURCE, l:-4 -> c"
|
||||
SINK(c) # $ flow="SOURCE, l:-4 -> c"
|
||||
|
||||
|
||||
@expects(2)
|
||||
def test_deeply_nested_unpacking_assignment():
|
||||
t = [[[[SOURCE]]], NONSOURCE]
|
||||
[[[a]]], b = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK(a) # $ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
|
||||
|
||||
@@ -595,19 +595,19 @@ def test_deeply_nested_unpacking_assignment():
|
||||
def test_iterated_unpacking_assignment():
|
||||
t = (SOURCE, SOURCE, NONSOURCE)
|
||||
a, *b, c = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK(a) # $ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
SINK(b[0]) #$ flow="SOURCE, l:-4 -> b[0]"
|
||||
SINK_F(c) #$ SPURIOUS: flow="SOURCE, l:-5 -> c" # We do not track tuple sizes
|
||||
SINK(b[0]) # $ flow="SOURCE, l:-4 -> b[0]"
|
||||
SINK_F(c) # $ SPURIOUS: flow="SOURCE, l:-5 -> c" # We do not track tuple sizes
|
||||
|
||||
|
||||
@expects(3)
|
||||
def test_iterated_unpacking_assignment_shrink():
|
||||
t = (SOURCE, SOURCE)
|
||||
a, *b, c = t
|
||||
SINK(a) #$ flow="SOURCE, l:-2 -> a"
|
||||
SINK(a) # $ flow="SOURCE, l:-2 -> a"
|
||||
SINK_F(b)
|
||||
SINK(c) #$ flow="SOURCE, l:-4 -> c"
|
||||
SINK(c) # $ flow="SOURCE, l:-4 -> c"
|
||||
|
||||
|
||||
@expects(15)
|
||||
@@ -616,25 +616,25 @@ def test_unpacking_assignment_conversion():
|
||||
|
||||
# tuple
|
||||
((a1, a2, a3), b, c) = ll
|
||||
SINK(a1) #$ flow="SOURCE, l:-4 -> a1"
|
||||
SINK_F(a2) #$ SPURIOUS: flow="SOURCE, l:-5 -> a2" # We expect an FP as all elements are tainted
|
||||
SINK(a3) #$ flow="SOURCE, l:-6 -> a3"
|
||||
SINK(a1) # $ flow="SOURCE, l:-4 -> a1"
|
||||
SINK_F(a2) # $ SPURIOUS: flow="SOURCE, l:-5 -> a2" # We expect an FP as all elements are tainted
|
||||
SINK(a3) # $ flow="SOURCE, l:-6 -> a3"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(c)
|
||||
|
||||
# mixed
|
||||
[(a1, a2, a3), b, c] = ll
|
||||
SINK(a1) #$ flow="SOURCE, l:-12 -> a1"
|
||||
SINK_F(a2) #$ SPURIOUS: flow="SOURCE, l:-13 -> a2" # We expect an FP as all elements are tainted
|
||||
SINK(a3) #$ flow="SOURCE, l:-14 -> a3"
|
||||
SINK(a1) # $ flow="SOURCE, l:-12 -> a1"
|
||||
SINK_F(a2) # $ SPURIOUS: flow="SOURCE, l:-13 -> a2" # We expect an FP as all elements are tainted
|
||||
SINK(a3) # $ flow="SOURCE, l:-14 -> a3"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(c)
|
||||
|
||||
# mixed differently
|
||||
([a1, a2, a3], b, c) = ll
|
||||
SINK(a1) #$ flow="SOURCE, l:-20 -> a1"
|
||||
SINK_F(a2) #$ SPURIOUS: flow="SOURCE, l:-21 -> a2" # We expect an FP as all elements are tainted
|
||||
SINK(a3) #$ flow="SOURCE, l:-22 -> a3"
|
||||
SINK(a1) # $ flow="SOURCE, l:-20 -> a1"
|
||||
SINK_F(a2) # $ SPURIOUS: flow="SOURCE, l:-21 -> a2" # We expect an FP as all elements are tainted
|
||||
SINK(a3) # $ flow="SOURCE, l:-22 -> a3"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(c)
|
||||
|
||||
@@ -644,37 +644,37 @@ def test_iterated_unpacking_assignment_conversion():
|
||||
|
||||
# list
|
||||
[[a1, *a2], *b] = tt
|
||||
SINK(a1) #$ flow="SOURCE, l:-4 -> a1"
|
||||
SINK(a1) # $ flow="SOURCE, l:-4 -> a1"
|
||||
SINK_F(a2) # The list itself is not tainted
|
||||
SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-6 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) #$ flow="SOURCE, l:-7 -> a2[1]"
|
||||
SINK_F(a2[0]) # $ SPURIOUS: flow="SOURCE, l:-6 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) # $ flow="SOURCE, l:-7 -> a2[1]"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(b[0])
|
||||
|
||||
# tuple
|
||||
((a1, *a2), *b) = tt
|
||||
SINK(a1) #$ flow="SOURCE, l:-13 -> a1"
|
||||
SINK(a1) # $ flow="SOURCE, l:-13 -> a1"
|
||||
SINK_F(a2) # The list itself is not tainted
|
||||
SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-15 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) #$ flow="SOURCE, l:-16 -> a2[1]"
|
||||
SINK_F(a2[0]) # $ SPURIOUS: flow="SOURCE, l:-15 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) # $ flow="SOURCE, l:-16 -> a2[1]"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(b[0])
|
||||
|
||||
# mixed
|
||||
[(a1, *a2), *b] = tt
|
||||
SINK(a1) #$ flow="SOURCE, l:-22 -> a1"
|
||||
SINK(a1) # $ flow="SOURCE, l:-22 -> a1"
|
||||
SINK_F(a2) # The list itself is not tainted
|
||||
SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-24 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) #$ flow="SOURCE, l:-25 -> a2[1]"
|
||||
SINK_F(a2[0]) # $ SPURIOUS: flow="SOURCE, l:-24 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) # $ flow="SOURCE, l:-25 -> a2[1]"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(b[0])
|
||||
|
||||
# mixed differently
|
||||
([a1, *a2], *b) = tt
|
||||
SINK(a1) #$ flow="SOURCE, l:-31 -> a1"
|
||||
SINK(a1) # $ flow="SOURCE, l:-31 -> a1"
|
||||
SINK_F(a2) # The list itself is not tainted
|
||||
SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-33 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) #$ flow="SOURCE, l:-34 -> a2[1]"
|
||||
SINK_F(a2[0]) # $ SPURIOUS: flow="SOURCE, l:-33 -> a2[0]" # FP here due to list abstraction
|
||||
SINK(a2[1]) # $ flow="SOURCE, l:-34 -> a2[1]"
|
||||
SINK_F(b) # The list itself is not tainted
|
||||
SINK_F(b[0])
|
||||
|
||||
@@ -682,16 +682,16 @@ def test_iterated_unpacking_assignment_conversion():
|
||||
@expects(3)
|
||||
def test_iterable_repacking():
|
||||
a, *(b, c) = (SOURCE, NONSOURCE, SOURCE)
|
||||
SINK(a) #$ flow="SOURCE, l:-1 -> a"
|
||||
SINK(a) # $ flow="SOURCE, l:-1 -> a"
|
||||
SINK_F(b)
|
||||
SINK(c) #$ MISSING: flow="SOURCE, l:-3 -> c"
|
||||
SINK(c) # $ MISSING: flow="SOURCE, l:-3 -> c"
|
||||
|
||||
|
||||
@expects(4)
|
||||
def test_iterable_unpacking_in_for():
|
||||
tl = [(SOURCE, NONSOURCE), (SOURCE, NONSOURCE)]
|
||||
for x,y in tl:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y)
|
||||
|
||||
|
||||
@@ -700,21 +700,21 @@ def test_iterable_star_unpacking_in_for():
|
||||
tl = [(SOURCE, NONSOURCE), (SOURCE, NONSOURCE)]
|
||||
for *x,y in tl:
|
||||
SINK_F(x)
|
||||
SINK(x[0]) #$ flow="SOURCE, l:-3 -> x[0]"
|
||||
SINK_F(y) #$ SPURIOUS: flow="SOURCE, l:-4 -> y" # FP here since we do not track the tuple lenght and so `*x` could be empty
|
||||
SINK(x[0]) # $ flow="SOURCE, l:-3 -> x[0]"
|
||||
SINK_F(y) # $ SPURIOUS: flow="SOURCE, l:-4 -> y" # FP here since we do not track the tuple lenght and so `*x` could be empty
|
||||
|
||||
|
||||
@expects(6)
|
||||
def test_iterable_star_unpacking_in_for_2():
|
||||
tl = [(SOURCE, NONSOURCE), (SOURCE, NONSOURCE)]
|
||||
for x,*y,z in tl:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y) # The list itself is not tainted (and is here empty)
|
||||
SINK_F(z)
|
||||
|
||||
def iterate_star_args(first, second, *args):
|
||||
for arg in args:
|
||||
SINK(arg) #$ flow="SOURCE, l:+5 -> arg" flow="SOURCE, l:+6 -> arg"
|
||||
SINK(arg) # $ flow="SOURCE, l:+5 -> arg" flow="SOURCE, l:+6 -> arg"
|
||||
|
||||
# FP reported here: https://github.com/github/codeql-python-team/issues/49
|
||||
@expects(2)
|
||||
@@ -751,17 +751,17 @@ def test_deep_callgraph():
|
||||
return f5(arg)
|
||||
|
||||
x = f6(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = f5(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = f4(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = f3(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = f2(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = f1(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
|
||||
|
||||
def wat_f1(arg):
|
||||
@@ -785,17 +785,17 @@ def wat_f6(arg):
|
||||
@expects(6)
|
||||
def test_deep_callgraph_defined_in_module():
|
||||
x = wat_f6(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = wat_f5(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = wat_f4(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = wat_f3(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = wat_f2(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
x = wat_f1(SOURCE)
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
|
||||
@expects(2)
|
||||
def test_dynamic_tuple_creation_1():
|
||||
@@ -803,7 +803,7 @@ def test_dynamic_tuple_creation_1():
|
||||
tup += (SOURCE,)
|
||||
tup += (NONSOURCE,)
|
||||
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-3 -> tup[0]"
|
||||
SINK(tup[0]) # $ MISSING:flow="SOURCE, l:-3 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
|
||||
@@ -813,7 +813,7 @@ def test_dynamic_tuple_creation_2():
|
||||
tup += (SOURCE,)
|
||||
tup += (NONSOURCE,)
|
||||
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-3 -> tup[0]"
|
||||
SINK(tup[0]) # $ MISSING:flow="SOURCE, l:-3 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
|
||||
@@ -823,7 +823,7 @@ def test_dynamic_tuple_creation_3():
|
||||
tup2 = (NONSOURCE,)
|
||||
tup = tup1 + tup2
|
||||
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-4 -> tup[0]"
|
||||
SINK(tup[0]) # $ MISSING:flow="SOURCE, l:-4 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
|
||||
@@ -834,7 +834,7 @@ def test_dynamic_tuple_creation_4():
|
||||
for item in [SOURCE, NONSOURCE]:
|
||||
tup += (item,)
|
||||
|
||||
SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-3 -> tup[0]"
|
||||
SINK(tup[0]) # $ MISSING:flow="SOURCE, l:-3 -> tup[0]"
|
||||
SINK_F(tup[1])
|
||||
|
||||
def return_from_inner_scope(x):
|
||||
@@ -844,7 +844,7 @@ def return_from_inner_scope(x):
|
||||
return SOURCE
|
||||
|
||||
def test_return_from_inner_scope():
|
||||
SINK(return_from_inner_scope([])) #$ flow="SOURCE, l:-3 -> return_from_inner_scope(..)"
|
||||
SINK(return_from_inner_scope([])) # $ flow="SOURCE, l:-3 -> return_from_inner_scope(..)"
|
||||
|
||||
|
||||
# Inspired by reverse read inconsistency check
|
||||
@@ -855,13 +855,13 @@ def test_reverse_read_subscript():
|
||||
d = {"a": NONSOURCE}
|
||||
l = [d]
|
||||
insertAtA(l[0])
|
||||
SINK(d["a"]) #$ MISSING:flow="SOURCE, l-6 -> d['a']""
|
||||
SINK(d["a"]) # $ MISSING:flow="SOURCE, l-6 -> d['a']""
|
||||
|
||||
def test_reverse_read_dict_arg():
|
||||
d = {"a": NONSOURCE}
|
||||
dd = {"d": d}
|
||||
insertAtA(**dd)
|
||||
SINK(d["a"]) #$ MISSING:flow="SOURCE, l-12 -> d['a']""
|
||||
SINK(d["a"]) # $ MISSING:flow="SOURCE, l-12 -> d['a']""
|
||||
|
||||
|
||||
class WithA:
|
||||
@@ -876,10 +876,10 @@ def test_reverse_read_subscript_cls():
|
||||
withA = WithA()
|
||||
l = [withA]
|
||||
l[0].setA(SOURCE)
|
||||
SINK(withA.a) #$ MISSING:flow="SOURCE, l:-1 -> self.a"
|
||||
SINK(withA.a) # $ MISSING:flow="SOURCE, l:-1 -> self.a"
|
||||
|
||||
@expects(3)
|
||||
def test_with_default_param_value(x=SOURCE, /, y=SOURCE, *, z=SOURCE):
|
||||
SINK(x) #$ flow="SOURCE, l:-1 -> x"
|
||||
SINK(y) #$ flow="SOURCE, l:-2 -> y"
|
||||
SINK(z) #$ flow="SOURCE, l:-3 -> z"
|
||||
SINK(x) # $ flow="SOURCE, l:-1 -> x"
|
||||
SINK(y) # $ flow="SOURCE, l:-2 -> y"
|
||||
SINK(z) # $ flow="SOURCE, l:-3 -> z"
|
||||
|
||||
@@ -41,8 +41,8 @@ def SINK_F(x):
|
||||
def test_list_from_list():
|
||||
l1 = [SOURCE, NONSOURCE]
|
||||
l2 = list(l1)
|
||||
SINK(l2[0]) #$ flow="SOURCE, l:-2 -> l2[0]"
|
||||
SINK_F(l2[1]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l2[1]"
|
||||
SINK(l2[0]) # $ flow="SOURCE, l:-2 -> l2[0]"
|
||||
SINK_F(l2[1]) # $ SPURIOUS: flow="SOURCE, l:-3 -> l2[1]"
|
||||
|
||||
# -- skip list_from_string
|
||||
|
||||
@@ -50,19 +50,19 @@ def test_list_from_list():
|
||||
def test_list_from_tuple():
|
||||
t = (SOURCE, NONSOURCE)
|
||||
l = list(t)
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK_F(l[1]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l[1]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK_F(l[1]) # $ SPURIOUS: flow="SOURCE, l:-3 -> l[1]"
|
||||
|
||||
def test_list_from_set():
|
||||
s = {SOURCE}
|
||||
l = list(s)
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-2 -> l[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_list_from_dict():
|
||||
d = {SOURCE: 'v', NONSOURCE: 'v2'}
|
||||
l = list(d)
|
||||
SINK(l[0]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK(l[0]) # $ MISSING: flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK_F(l[1]) # expecting FP due to imprecise flow
|
||||
|
||||
### Tuple
|
||||
@@ -71,26 +71,26 @@ def test_list_from_dict():
|
||||
def test_tuple_from_list():
|
||||
l = [SOURCE, NONSOURCE]
|
||||
t = tuple(l)
|
||||
SINK(t[0]) #$ MISSING: flow="SOURCE, l:-2 -> t[0]"
|
||||
SINK(t[0]) # $ MISSING: flow="SOURCE, l:-2 -> t[0]"
|
||||
SINK_F(t[1])
|
||||
|
||||
@expects(2)
|
||||
def test_tuple_from_tuple():
|
||||
t0 = (SOURCE, NONSOURCE)
|
||||
t = tuple(t0)
|
||||
SINK(t[0]) #$ flow="SOURCE, l:-2 -> t[0]"
|
||||
SINK(t[0]) # $ flow="SOURCE, l:-2 -> t[0]"
|
||||
SINK_F(t[1])
|
||||
|
||||
def test_tuple_from_set():
|
||||
s = {SOURCE}
|
||||
t = tuple(s)
|
||||
SINK(t[0]) #$ MISSING: flow="SOURCE, l:-2 -> t[0]"
|
||||
SINK(t[0]) # $ MISSING: flow="SOURCE, l:-2 -> t[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_tuple_from_dict():
|
||||
d = {SOURCE: "v1", NONSOURCE: "v2"}
|
||||
t = tuple(d)
|
||||
SINK(t[0]) #$ MISSING: flow="SOURCE, l:-2 -> t[0]"
|
||||
SINK(t[0]) # $ MISSING: flow="SOURCE, l:-2 -> t[0]"
|
||||
SINK_F(t[1])
|
||||
|
||||
|
||||
@@ -100,25 +100,25 @@ def test_set_from_list():
|
||||
l = [SOURCE]
|
||||
s = set(l)
|
||||
v = s.pop()
|
||||
SINK(v) #$ flow="SOURCE, l:-3 -> v"
|
||||
SINK(v) # $ flow="SOURCE, l:-3 -> v"
|
||||
|
||||
def test_set_from_tuple():
|
||||
t = (SOURCE,)
|
||||
s = set(t)
|
||||
v = s.pop()
|
||||
SINK(v) #$ flow="SOURCE, l:-3 -> v"
|
||||
SINK(v) # $ flow="SOURCE, l:-3 -> v"
|
||||
|
||||
def test_set_from_set():
|
||||
s0 = {SOURCE}
|
||||
s = set(s0)
|
||||
v = s.pop()
|
||||
SINK(v) #$ flow="SOURCE, l:-3 -> v"
|
||||
SINK(v) # $ flow="SOURCE, l:-3 -> v"
|
||||
|
||||
def test_set_from_dict():
|
||||
d = {SOURCE: "val"}
|
||||
s = set(d)
|
||||
v = s.pop()
|
||||
SINK(v) #$ MISSING: flow="SOURCE, l:-3 -> v"
|
||||
SINK(v) # $ MISSING: flow="SOURCE, l:-3 -> v"
|
||||
|
||||
|
||||
### Dict
|
||||
@@ -126,29 +126,29 @@ def test_set_from_dict():
|
||||
@expects(2)
|
||||
def test_dict_from_keyword():
|
||||
d = dict(k = SOURCE, k1 = NONSOURCE)
|
||||
SINK(d["k"]) #$ flow="SOURCE, l:-1 -> d['k']"
|
||||
SINK(d["k"]) # $ flow="SOURCE, l:-1 -> d['k']"
|
||||
SINK_F(d["k1"])
|
||||
|
||||
@expects(2)
|
||||
def test_dict_from_list():
|
||||
d = dict([("k", SOURCE), ("k1", NONSOURCE)])
|
||||
SINK(d["k"]) #$ flow="SOURCE, l:-1 -> d['k']"
|
||||
SINK_F(d["k1"]) #$ SPURIOUS: flow="SOURCE, l:-2 -> d['k1']" // due to imprecise list content
|
||||
SINK(d["k"]) # $ flow="SOURCE, l:-1 -> d['k']"
|
||||
SINK_F(d["k1"]) # $ SPURIOUS: flow="SOURCE, l:-2 -> d['k1']" // due to imprecise list content
|
||||
|
||||
@expects(2)
|
||||
def test_dict_from_dict():
|
||||
d1 = {'k': SOURCE, 'k1': NONSOURCE}
|
||||
d2 = dict(d1)
|
||||
SINK(d2["k"]) #$ flow="SOURCE, l:-2 -> d2['k']"
|
||||
SINK(d2["k"]) # $ flow="SOURCE, l:-2 -> d2['k']"
|
||||
SINK_F(d2["k1"])
|
||||
|
||||
@expects(4)
|
||||
def test_dict_from_multiple_args():
|
||||
d = dict([("k", SOURCE), ("k1", NONSOURCE)], k2 = SOURCE, k3 = NONSOURCE)
|
||||
SINK(d["k"]) #$ flow="SOURCE, l:-1 -> d['k']"
|
||||
SINK_F(d["k1"]) #$ SPURIOUS: flow="SOURCE, l:-2 -> d['k1']" // due to imprecise list content
|
||||
SINK(d["k2"]) #$ flow="SOURCE, l:-3 -> d['k2']"
|
||||
SINK_F(d["k3"]) #$ SPURIOUS: flow="SOURCE, l:-4 -> d['k3']" // due to imprecise list content
|
||||
SINK(d["k"]) # $ flow="SOURCE, l:-1 -> d['k']"
|
||||
SINK_F(d["k1"]) # $ SPURIOUS: flow="SOURCE, l:-2 -> d['k1']" // due to imprecise list content
|
||||
SINK(d["k2"]) # $ flow="SOURCE, l:-3 -> d['k2']"
|
||||
SINK_F(d["k3"]) # $ SPURIOUS: flow="SOURCE, l:-4 -> d['k3']" // due to imprecise list content
|
||||
|
||||
## Container methods
|
||||
|
||||
@@ -157,46 +157,46 @@ def test_dict_from_multiple_args():
|
||||
def test_list_pop():
|
||||
l = [SOURCE]
|
||||
v = l.pop()
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) # $ flow="SOURCE, l:-2 -> v"
|
||||
|
||||
def test_list_pop_index():
|
||||
l = [SOURCE]
|
||||
v = l.pop(0)
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) # $ flow="SOURCE, l:-2 -> v"
|
||||
|
||||
def test_list_pop_index_imprecise():
|
||||
l = [SOURCE, NONSOURCE]
|
||||
v = l.pop(1)
|
||||
SINK_F(v) #$ SPURIOUS: flow="SOURCE, l:-2 -> v"
|
||||
SINK_F(v) # $ SPURIOUS: flow="SOURCE, l:-2 -> v"
|
||||
|
||||
@expects(2)
|
||||
def test_list_copy():
|
||||
l0 = [SOURCE, NONSOURCE]
|
||||
l = l0.copy()
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK_F(l[1]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l[1]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK_F(l[1]) # $ SPURIOUS: flow="SOURCE, l:-3 -> l[1]"
|
||||
|
||||
def test_list_append():
|
||||
l = [NONSOURCE]
|
||||
l.append(SOURCE)
|
||||
SINK(l[1]) #$ flow="SOURCE, l:-1 -> l[1]"
|
||||
SINK(l[1]) # $ flow="SOURCE, l:-1 -> l[1]"
|
||||
|
||||
### Set
|
||||
|
||||
def test_set_pop():
|
||||
s = {SOURCE}
|
||||
v = s.pop()
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) # $ flow="SOURCE, l:-2 -> v"
|
||||
|
||||
def test_set_copy():
|
||||
s0 = {SOURCE}
|
||||
s = s0.copy()
|
||||
SINK(s.pop()) #$ flow="SOURCE, l:-2 -> s.pop()"
|
||||
SINK(s.pop()) # $ flow="SOURCE, l:-2 -> s.pop()"
|
||||
|
||||
def test_set_add():
|
||||
s = set([])
|
||||
s.add(SOURCE)
|
||||
SINK(s.pop()) #$ flow="SOURCE, l:-1 -> s.pop()"
|
||||
SINK(s.pop()) # $ flow="SOURCE, l:-1 -> s.pop()"
|
||||
|
||||
### Dict
|
||||
|
||||
@@ -204,13 +204,13 @@ def test_dict_keys():
|
||||
d = {SOURCE: "value"}
|
||||
keys = d.keys()
|
||||
key_list = list(keys)
|
||||
SINK(key_list[0]) #$ MISSING: flow="SOURCE, l:-3 -> key_list[0]"
|
||||
SINK(key_list[0]) # $ MISSING: flow="SOURCE, l:-3 -> key_list[0]"
|
||||
|
||||
def test_dict_values():
|
||||
d = {'k': SOURCE}
|
||||
vals = d.values()
|
||||
val_list = list(vals)
|
||||
SINK(val_list[0]) #$ flow="SOURCE, l:-3 -> val_list[0]"
|
||||
SINK(val_list[0]) # $ flow="SOURCE, l:-3 -> val_list[0]"
|
||||
|
||||
@expects(4)
|
||||
def test_dict_items():
|
||||
@@ -218,43 +218,43 @@ def test_dict_items():
|
||||
items = d.items()
|
||||
item_list = list(items)
|
||||
SINK_F(item_list[0][0]) # expecting FP due to imprecise flow
|
||||
SINK(item_list[0][1]) #$ flow="SOURCE, l:-4 -> item_list[0][1]"
|
||||
SINK(item_list[1][0]) #$ MISSING: flow="SOURCE, l:-5 -> item_list[1][0]"
|
||||
SINK_F(item_list[1][1]) #$ SPURIOUS: flow="SOURCE, l:-6 -> item_list[1][1]"
|
||||
SINK(item_list[0][1]) # $ flow="SOURCE, l:-4 -> item_list[0][1]"
|
||||
SINK(item_list[1][0]) # $ MISSING: flow="SOURCE, l:-5 -> item_list[1][0]"
|
||||
SINK_F(item_list[1][1]) # $ SPURIOUS: flow="SOURCE, l:-6 -> item_list[1][1]"
|
||||
|
||||
@expects(3)
|
||||
def test_dict_pop():
|
||||
d = {'k': SOURCE}
|
||||
v = d.pop("k")
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) # $ flow="SOURCE, l:-2 -> v"
|
||||
v1 = d.pop("k", NONSOURCE)
|
||||
SINK_F(v1) #$ SPURIOUS: flow="SOURCE, l:-4 -> v1"
|
||||
SINK_F(v1) # $ SPURIOUS: flow="SOURCE, l:-4 -> v1"
|
||||
v2 = d.pop("non-existing", SOURCE)
|
||||
SINK(v2) #$ flow="SOURCE, l:-1 -> v2"
|
||||
SINK(v2) # $ flow="SOURCE, l:-1 -> v2"
|
||||
|
||||
@expects(3)
|
||||
def test_dict_get():
|
||||
d = {'k': SOURCE}
|
||||
v = d.get("k")
|
||||
SINK(v) #$ flow="SOURCE, l:-2 -> v"
|
||||
SINK(v) # $ flow="SOURCE, l:-2 -> v"
|
||||
v1 = d.get("non-existing", SOURCE)
|
||||
SINK(v1) #$ flow="SOURCE, l:-1 -> v1"
|
||||
SINK(v1) # $ flow="SOURCE, l:-1 -> v1"
|
||||
k = "k"
|
||||
v2 = d.get(k)
|
||||
SINK(v2) #$ flow="SOURCE, l:-7 -> v2"
|
||||
SINK(v2) # $ flow="SOURCE, l:-7 -> v2"
|
||||
|
||||
@expects(2)
|
||||
def test_dict_popitem():
|
||||
d = {'k': SOURCE}
|
||||
t = d.popitem() # could be any pair (before 3.7), but we only have one
|
||||
SINK_F(t[0])
|
||||
SINK(t[1]) #$ flow="SOURCE, l:-3 -> t[1]"
|
||||
SINK(t[1]) # $ flow="SOURCE, l:-3 -> t[1]"
|
||||
|
||||
@expects(2)
|
||||
def test_dict_copy():
|
||||
d = {'k': SOURCE, 'k1': NONSOURCE}
|
||||
d1 = d.copy()
|
||||
SINK(d1["k"]) #$ flow="SOURCE, l:-2 -> d1['k']"
|
||||
SINK(d1["k"]) # $ flow="SOURCE, l:-2 -> d1['k']"
|
||||
SINK_F(d1["k1"])
|
||||
|
||||
|
||||
@@ -265,22 +265,22 @@ def test_dict_copy():
|
||||
def test_sorted_list():
|
||||
l0 = [SOURCE]
|
||||
l = sorted(l0)
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-2 -> l[0]"
|
||||
|
||||
def test_sorted_tuple():
|
||||
t = (SOURCE,)
|
||||
l = sorted(t)
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-2 -> l[0]"
|
||||
|
||||
def test_sorted_set():
|
||||
s = {SOURCE}
|
||||
l = sorted(s)
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-2 -> l[0]"
|
||||
|
||||
def test_sorted_dict():
|
||||
d = {SOURCE: "val"}
|
||||
l = sorted(d)
|
||||
SINK(l[0]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
|
||||
SINK(l[0]) # $ MISSING: flow="SOURCE, l:-2 -> l[0]"
|
||||
|
||||
### reversed
|
||||
|
||||
@@ -289,16 +289,16 @@ def test_reversed_list():
|
||||
l0 = [SOURCE, NONSOURCE]
|
||||
r = reversed(l0)
|
||||
l = list(r)
|
||||
SINK_F(l[0]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l[0]"
|
||||
SINK(l[1]) #$ flow="SOURCE, l:-4 -> l[1]"
|
||||
SINK_F(l[0]) # $ SPURIOUS: flow="SOURCE, l:-3 -> l[0]"
|
||||
SINK(l[1]) # $ flow="SOURCE, l:-4 -> l[1]"
|
||||
|
||||
@expects(2)
|
||||
def test_reversed_tuple():
|
||||
t = (SOURCE, NONSOURCE)
|
||||
r = reversed(t)
|
||||
l = list(r)
|
||||
SINK_F(l[0]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l[0]"
|
||||
SINK(l[1]) #$ flow="SOURCE, l:-4 -> l[1]"
|
||||
SINK_F(l[0]) # $ SPURIOUS: flow="SOURCE, l:-3 -> l[0]"
|
||||
SINK(l[1]) # $ flow="SOURCE, l:-4 -> l[1]"
|
||||
|
||||
@expects(2)
|
||||
def test_reversed_dict():
|
||||
@@ -306,7 +306,7 @@ def test_reversed_dict():
|
||||
r = reversed(d)
|
||||
l = list(r)
|
||||
SINK_F(l[0])
|
||||
SINK(l[1]) #$ MISSING: flow="SOURCE, l:-4 -> l[1]"
|
||||
SINK(l[1]) # $ MISSING: flow="SOURCE, l:-4 -> l[1]"
|
||||
|
||||
### iter
|
||||
|
||||
@@ -314,32 +314,32 @@ def test_iter_list():
|
||||
l0 = [SOURCE]
|
||||
i = iter(l0)
|
||||
l = list(i)
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-3 -> l[0]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-3 -> l[0]"
|
||||
|
||||
def test_iter_tuple():
|
||||
t = (SOURCE,)
|
||||
i = iter(t)
|
||||
l = list(i)
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-3 -> l[0]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-3 -> l[0]"
|
||||
|
||||
def test_iter_set():
|
||||
t = {SOURCE}
|
||||
i = iter(t)
|
||||
l = list(i)
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-3 -> l[0]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-3 -> l[0]"
|
||||
|
||||
def test_iter_dict():
|
||||
d = {SOURCE: "val"}
|
||||
i = iter(d)
|
||||
l = list(i)
|
||||
SINK(l[0]) #$ MISSING: flow="SOURCE, l:-3 -> l[0]"
|
||||
SINK(l[0]) # $ MISSING: flow="SOURCE, l:-3 -> l[0]"
|
||||
|
||||
def test_iter_iter():
|
||||
# applying iter() to the result of iter() is basically a no-op
|
||||
l0 = [SOURCE]
|
||||
i = iter(iter(l0))
|
||||
l = list(i)
|
||||
SINK(l[0]) #$ flow="SOURCE, l:-3 -> l[0]"
|
||||
SINK(l[0]) # $ flow="SOURCE, l:-3 -> l[0]"
|
||||
|
||||
### next
|
||||
|
||||
@@ -347,25 +347,25 @@ def test_next_list():
|
||||
l = [SOURCE]
|
||||
i = iter(l)
|
||||
n = next(i)
|
||||
SINK(n) #$ flow="SOURCE, l:-3 -> n"
|
||||
SINK(n) # $ flow="SOURCE, l:-3 -> n"
|
||||
|
||||
def test_next_tuple():
|
||||
t = (SOURCE,)
|
||||
i = iter(t)
|
||||
n = next(i)
|
||||
SINK(n) #$ flow="SOURCE, l:-3 -> n"
|
||||
SINK(n) # $ flow="SOURCE, l:-3 -> n"
|
||||
|
||||
def test_next_set():
|
||||
s = {SOURCE}
|
||||
i = iter(s)
|
||||
n = next(i)
|
||||
SINK(n) #$ flow="SOURCE, l:-3 -> n"
|
||||
SINK(n) # $ flow="SOURCE, l:-3 -> n"
|
||||
|
||||
def test_next_dict():
|
||||
d = {SOURCE: "val"}
|
||||
i = iter(d)
|
||||
n = next(i)
|
||||
SINK(n) #$ MISSING: flow="SOURCE, l:-3 -> n"
|
||||
SINK(n) # $ MISSING: flow="SOURCE, l:-3 -> n"
|
||||
|
||||
### map
|
||||
|
||||
@@ -375,13 +375,13 @@ def test_map_list():
|
||||
l2 = [NONSOURCE]
|
||||
|
||||
def f(p1,p2):
|
||||
SINK(p1) #$ flow="SOURCE, l:-4 -> p1"
|
||||
SINK(p1) # $ flow="SOURCE, l:-4 -> p1"
|
||||
SINK_F(p2)
|
||||
|
||||
return p1,p2
|
||||
|
||||
rl = list(map(f, l1, l2))
|
||||
SINK(rl[0][0]) #$ flow="SOURCE, l:-10 -> rl[0][0]"
|
||||
SINK(rl[0][0]) # $ flow="SOURCE, l:-10 -> rl[0][0]"
|
||||
SINK_F(rl[0][1])
|
||||
|
||||
@expects(4)
|
||||
@@ -390,13 +390,13 @@ def test_map_set():
|
||||
s2 = {NONSOURCE}
|
||||
|
||||
def f(p1,p2):
|
||||
SINK(p1) #$ flow="SOURCE, l:-4 -> p1"
|
||||
SINK(p1) # $ flow="SOURCE, l:-4 -> p1"
|
||||
SINK_F(p2)
|
||||
|
||||
return p1,p2
|
||||
|
||||
rl = list(map(f, s1, s2))
|
||||
SINK(rl[0][0]) #$ flow="SOURCE, l:-10 -> rl[0][0]"
|
||||
SINK(rl[0][0]) # $ flow="SOURCE, l:-10 -> rl[0][0]"
|
||||
SINK_F(rl[0][1])
|
||||
|
||||
@expects(4)
|
||||
@@ -405,13 +405,13 @@ def test_map_tuple():
|
||||
t2 = (NONSOURCE,)
|
||||
|
||||
def f(p1,p2):
|
||||
SINK(p1) #$ flow="SOURCE, l:-4 -> p1"
|
||||
SINK(p1) # $ flow="SOURCE, l:-4 -> p1"
|
||||
SINK_F(p2)
|
||||
|
||||
return p1,p2
|
||||
|
||||
rl = list(map(f, t1, t2))
|
||||
SINK(rl[0][0]) #$ flow="SOURCE, l:-10 -> rl[0][0]"
|
||||
SINK(rl[0][0]) # $ flow="SOURCE, l:-10 -> rl[0][0]"
|
||||
SINK_F(rl[0][1])
|
||||
|
||||
|
||||
@@ -421,13 +421,13 @@ def test_map_dict():
|
||||
d2 = {NONSOURCE: "v2"}
|
||||
|
||||
def f(p1,p2):
|
||||
SINK(p1) #$ MISSING: flow="SOURCE, l:-4 -> p1"
|
||||
SINK(p1) # $ MISSING: flow="SOURCE, l:-4 -> p1"
|
||||
SINK_F(p2)
|
||||
|
||||
return p1,p2
|
||||
|
||||
rl = list(map(f, d1, d2))
|
||||
SINK(rl[0][0]) #$ MISSING: flow="SOURCE, l:-10 -> rl[0][0]"
|
||||
SINK(rl[0][0]) # $ MISSING: flow="SOURCE, l:-10 -> rl[0][0]"
|
||||
SINK_F(rl[0][1])
|
||||
|
||||
@expects(4)
|
||||
@@ -436,13 +436,13 @@ def test_map_multi_list():
|
||||
l2 = [SOURCE]
|
||||
|
||||
def f(p1,p2):
|
||||
SINK(p1) #$ flow="SOURCE, l:-4 -> p1"
|
||||
SINK(p2) #$ flow="SOURCE, l:-4 -> p2"
|
||||
SINK(p1) # $ flow="SOURCE, l:-4 -> p1"
|
||||
SINK(p2) # $ flow="SOURCE, l:-4 -> p2"
|
||||
return p1,p2
|
||||
|
||||
rl = list(map(f, l1, l2))
|
||||
SINK(rl[0][0]) #$ flow="SOURCE, l:-9 -> rl[0][0]"
|
||||
SINK(rl[0][1]) #$ flow="SOURCE, l:-9 -> rl[0][1]"
|
||||
SINK(rl[0][0]) # $ flow="SOURCE, l:-9 -> rl[0][0]"
|
||||
SINK(rl[0][1]) # $ flow="SOURCE, l:-9 -> rl[0][1]"
|
||||
|
||||
@expects(4)
|
||||
def test_map_multi_tuple():
|
||||
@@ -450,59 +450,59 @@ def test_map_multi_tuple():
|
||||
l2 = (SOURCE,)
|
||||
|
||||
def f(p1,p2):
|
||||
SINK(p1) #$ flow="SOURCE, l:-4 -> p1"
|
||||
SINK(p2) #$ MISSING: flow="SOURCE, l:-4 -> p2" # Tuples are not tracked beyond the first list argument for performance.
|
||||
SINK(p1) # $ flow="SOURCE, l:-4 -> p1"
|
||||
SINK(p2) # $ MISSING: flow="SOURCE, l:-4 -> p2" # Tuples are not tracked beyond the first list argument for performance.
|
||||
return p1,p2
|
||||
|
||||
rl = list(map(f, l1, l2))
|
||||
SINK(rl[0][0]) #$ flow="SOURCE, l:-9 -> rl[0][0]"
|
||||
SINK(rl[0][1]) #$ MISSING: flow="SOURCE, l:-9 -> rl[0][1]"
|
||||
SINK(rl[0][0]) # $ flow="SOURCE, l:-9 -> rl[0][0]"
|
||||
SINK(rl[0][1]) # $ MISSING: flow="SOURCE, l:-9 -> rl[0][1]"
|
||||
|
||||
### filter
|
||||
### filter
|
||||
|
||||
@expects(2)
|
||||
def test_filter_list():
|
||||
l = [SOURCE]
|
||||
|
||||
def f(p):
|
||||
SINK(p) #$ flow="SOURCE, l:-3 -> p"
|
||||
return True
|
||||
SINK(p) # $ flow="SOURCE, l:-3 -> p"
|
||||
return True
|
||||
|
||||
rl = list(filter(f,l))
|
||||
SINK(rl[0]) #$ flow="SOURCE, l:-7 -> rl[0]"
|
||||
SINK(rl[0]) # $ flow="SOURCE, l:-7 -> rl[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_filter_set():
|
||||
s = {SOURCE}
|
||||
|
||||
def f(p):
|
||||
SINK(p) #$ flow="SOURCE, l:-3 -> p"
|
||||
return True
|
||||
SINK(p) # $ flow="SOURCE, l:-3 -> p"
|
||||
return True
|
||||
|
||||
rl = list(filter(f,s))
|
||||
SINK(rl[0]) #$ flow="SOURCE, l:-7 -> rl[0]"
|
||||
SINK(rl[0]) # $ flow="SOURCE, l:-7 -> rl[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_filter_tuple():
|
||||
t = (SOURCE,)
|
||||
|
||||
def f(p):
|
||||
SINK(p) #$ flow="SOURCE, l:-3 -> p"
|
||||
return True
|
||||
SINK(p) # $ flow="SOURCE, l:-3 -> p"
|
||||
return True
|
||||
|
||||
rl = list(filter(f,t))
|
||||
SINK(rl[0]) #$ flow="SOURCE, l:-7 -> rl[0]"
|
||||
SINK(rl[0]) # $ flow="SOURCE, l:-7 -> rl[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_filter_dict():
|
||||
d = {SOURCE: "v"}
|
||||
|
||||
def f(p):
|
||||
SINK(p) #$ MISSING: flow="SOURCE, l:-3 -> p"
|
||||
return True
|
||||
SINK(p) # $ MISSING: flow="SOURCE, l:-3 -> p"
|
||||
return True
|
||||
|
||||
rl = list(filter(f,d))
|
||||
SINK(rl[0]) #$ MISSING: flow="SOURCE, l:-7 -> rl[0]"
|
||||
SINK(rl[0]) # $ MISSING: flow="SOURCE, l:-7 -> rl[0]"
|
||||
|
||||
@expects(1)
|
||||
def test_enumerate_list():
|
||||
@@ -510,7 +510,7 @@ def test_enumerate_list():
|
||||
|
||||
e = list(enumerate(l))
|
||||
|
||||
SINK(e[0][1]) #$ flow="SOURCE, l:-4 -> e[0][1]"
|
||||
SINK(e[0][1]) # $ flow="SOURCE, l:-4 -> e[0][1]"
|
||||
|
||||
@expects(1)
|
||||
def test_enumerate_set():
|
||||
@@ -518,7 +518,7 @@ def test_enumerate_set():
|
||||
|
||||
e = list(enumerate(s))
|
||||
|
||||
SINK(e[0][1]) #$ flow="SOURCE, l:-4 -> e[0][1]"
|
||||
SINK(e[0][1]) # $ flow="SOURCE, l:-4 -> e[0][1]"
|
||||
|
||||
@expects(1)
|
||||
def test_enumerate_tuple():
|
||||
@@ -526,17 +526,17 @@ def test_enumerate_tuple():
|
||||
|
||||
e = list(enumerate(t))
|
||||
|
||||
SINK(e[0][1]) #$ flow="SOURCE, l:-4 -> e[0][1]"
|
||||
SINK(e[0][1]) # $ flow="SOURCE, l:-4 -> e[0][1]"
|
||||
|
||||
@expects(2)
|
||||
def test_enumerate_list_for():
|
||||
l = [SOURCE]
|
||||
|
||||
for i, x in enumerate(l):
|
||||
SINK(x) #$ flow="SOURCE, l:-3 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-3 -> x"
|
||||
|
||||
for t in enumerate(l):
|
||||
SINK(t[1]) #$ flow="SOURCE, l:-6 -> t[1]"
|
||||
SINK(t[1]) # $ flow="SOURCE, l:-6 -> t[1]"
|
||||
|
||||
@expects(1)
|
||||
def test_enumerate_dict():
|
||||
@@ -552,16 +552,16 @@ def test_zip_list():
|
||||
l2 = [SOURCE, NONSOURCE]
|
||||
l3 = [NONSOURCE, SOURCE]
|
||||
l4 = [NONSOURCE, NONSOURCE]
|
||||
|
||||
|
||||
z = list(zip(l1,l2,l3,l4))
|
||||
|
||||
SINK(z[0][0]) #$ flow="SOURCE, l:-7 -> z[0][0]"
|
||||
SINK(z[0][1]) #$ flow="SOURCE, l:-7 -> z[0][1]"
|
||||
SINK_F(z[0][2]) #$ SPURIOUS: flow="SOURCE, l:-7 -> z[0][2]"
|
||||
SINK(z[0][0]) # $ flow="SOURCE, l:-7 -> z[0][0]"
|
||||
SINK(z[0][1]) # $ flow="SOURCE, l:-7 -> z[0][1]"
|
||||
SINK_F(z[0][2]) # $ SPURIOUS: flow="SOURCE, l:-7 -> z[0][2]"
|
||||
SINK_F(z[0][3])
|
||||
SINK(z[1][0]) #$ flow="SOURCE, l:-11 -> z[1][0]"
|
||||
SINK_F(z[1][1]) #$ SPURIOUS: flow="SOURCE, l:-11 -> z[1][1]"
|
||||
SINK(z[1][2]) #$ flow="SOURCE, l:-11 -> z[1][2]"
|
||||
SINK(z[1][0]) # $ flow="SOURCE, l:-11 -> z[1][0]"
|
||||
SINK_F(z[1][1]) # $ SPURIOUS: flow="SOURCE, l:-11 -> z[1][1]"
|
||||
SINK(z[1][2]) # $ flow="SOURCE, l:-11 -> z[1][2]"
|
||||
SINK_F(z[1][3])
|
||||
|
||||
@expects(4)
|
||||
@@ -570,12 +570,12 @@ def test_zip_set():
|
||||
s2 = {NONSOURCE}
|
||||
s3 = {SOURCE}
|
||||
s4 = {NONSOURCE}
|
||||
|
||||
|
||||
z = list(zip(s1,s2,s3,s4))
|
||||
|
||||
SINK(z[0][0]) #$ flow="SOURCE, l:-7 -> z[0][0]"
|
||||
SINK(z[0][0]) # $ flow="SOURCE, l:-7 -> z[0][0]"
|
||||
SINK_F(z[0][1])
|
||||
SINK(z[0][2]) #$ flow="SOURCE, l:-7 -> z[0][2]"
|
||||
SINK(z[0][2]) # $ flow="SOURCE, l:-7 -> z[0][2]"
|
||||
SINK_F(z[0][3])
|
||||
|
||||
@expects(8)
|
||||
@@ -584,16 +584,16 @@ def test_zip_tuple():
|
||||
t2 = (SOURCE, NONSOURCE)
|
||||
t3 = (NONSOURCE, SOURCE)
|
||||
t4 = (NONSOURCE, NONSOURCE)
|
||||
|
||||
|
||||
z = list(zip(t1,t2,t3,t4))
|
||||
|
||||
SINK(z[0][0]) #$ flow="SOURCE, l:-7 -> z[0][0]"
|
||||
SINK(z[0][1]) #$ flow="SOURCE, l:-7 -> z[0][1]"
|
||||
SINK_F(z[0][2])
|
||||
SINK(z[0][0]) # $ flow="SOURCE, l:-7 -> z[0][0]"
|
||||
SINK(z[0][1]) # $ flow="SOURCE, l:-7 -> z[0][1]"
|
||||
SINK_F(z[0][2])
|
||||
SINK_F(z[0][3])
|
||||
SINK(z[1][0]) #$ flow="SOURCE, l:-11 -> z[1][0]"
|
||||
SINK_F(z[1][1]) #$ SPURIOUS: flow="SOURCE, l:-11 -> z[1][1]"
|
||||
SINK(z[1][2]) #$ MISSING: flow="SOURCE, l:-11 -> z[1][2]" # Tuple contents are not tracked beyond the first two arguments for performance.
|
||||
SINK(z[1][0]) # $ flow="SOURCE, l:-11 -> z[1][0]"
|
||||
SINK_F(z[1][1]) # $ SPURIOUS: flow="SOURCE, l:-11 -> z[1][1]"
|
||||
SINK(z[1][2]) # $ MISSING: flow="SOURCE, l:-11 -> z[1][2]" # Tuple contents are not tracked beyond the first two arguments for performance.
|
||||
SINK_F(z[1][3])
|
||||
|
||||
@expects(4)
|
||||
@@ -602,10 +602,10 @@ def test_zip_dict():
|
||||
d2 = {NONSOURCE: "v"}
|
||||
d3 = {SOURCE: "v"}
|
||||
d4 = {NONSOURCE: "v"}
|
||||
|
||||
|
||||
z = list(zip(d1,d2,d3,d4))
|
||||
|
||||
SINK(z[0][0]) #$ MISSING: flow="SOURCE, l:-7 -> z[0][0]"
|
||||
SINK_F(z[0][1])
|
||||
SINK(z[0][2]) #$ MISSING: flow="SOURCE, l:-7 -> z[0][2]"
|
||||
SINK_F(z[0][3])
|
||||
SINK(z[0][0]) # $ MISSING: flow="SOURCE, l:-7 -> z[0][0]"
|
||||
SINK_F(z[0][1])
|
||||
SINK(z[0][2]) # $ MISSING: flow="SOURCE, l:-7 -> z[0][2]"
|
||||
SINK_F(z[0][3])
|
||||
|
||||
@@ -1 +1 @@
|
||||
known_attr = [1000] #$ writes=known_attr
|
||||
known_attr = [1000] # $ writes=known_attr
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
# Simple assignment
|
||||
|
||||
g = [5] # $writes=g
|
||||
g = [5] # $ writes=g
|
||||
|
||||
# Multiple assignment
|
||||
|
||||
g1, g2 = [6], [7] # $writes=g1 writes=g2
|
||||
g1, g2 = [6], [7] # $ writes=g1 writes=g2
|
||||
|
||||
# Assignment that's only referenced in this scope.
|
||||
|
||||
unreferenced_g = [8] # $writes=unreferenced_g
|
||||
unreferenced_g = [8] # $ writes=unreferenced_g
|
||||
print(unreferenced_g)
|
||||
|
||||
# Testing modifications of globals
|
||||
@@ -24,49 +24,49 @@ g_mod = []
|
||||
# but currently our analysis thinks `g_mod` might be used in the `print` call
|
||||
g_mod = [10] # $ SPURIOUS: writes=g_mod
|
||||
print("foo")
|
||||
g_mod = [100] # $writes=g_mod
|
||||
g_mod = [100] # $ writes=g_mod
|
||||
|
||||
# Modification by mutation
|
||||
|
||||
g_ins = [50] # $writes=g_ins
|
||||
g_ins = [50] # $ writes=g_ins
|
||||
print(g_ins)
|
||||
g_ins.append(75)
|
||||
|
||||
# A global with multiple potential definitions
|
||||
|
||||
import unknown_module # $writes=unknown_module
|
||||
import unknown_module # $ writes=unknown_module
|
||||
if unknown_module.attr:
|
||||
g_mult = [200] # $writes=g_mult
|
||||
g_mult = [200] # $ writes=g_mult
|
||||
else:
|
||||
g_mult = [300] # $writes=g_mult
|
||||
g_mult = [300] # $ writes=g_mult
|
||||
|
||||
# A global variable that may be redefined depending on some unknown value
|
||||
|
||||
g_redef = [400] # $writes=g_redef
|
||||
g_redef = [400] # $ writes=g_redef
|
||||
if unknown_module.attr:
|
||||
g_redef = [500] # $writes=g_redef
|
||||
g_redef = [500] # $ writes=g_redef
|
||||
|
||||
def global_access(): # $writes=global_access
|
||||
def global_access(): # $ writes=global_access
|
||||
l = 5
|
||||
print(g) # $reads=g
|
||||
print(g1) # $reads=g1
|
||||
print(g2) # $reads=g2
|
||||
print(g_mod) # $reads=g_mod
|
||||
print(g_ins) # $reads=g_ins
|
||||
print(g_mult) # $reads=g_mult
|
||||
print(g_redef) # $reads=g_redef
|
||||
print(g) # $ reads=g
|
||||
print(g1) # $ reads=g1
|
||||
print(g2) # $ reads=g2
|
||||
print(g_mod) # $ reads=g_mod
|
||||
print(g_ins) # $ reads=g_ins
|
||||
print(g_mult) # $ reads=g_mult
|
||||
print(g_redef) # $ reads=g_redef
|
||||
|
||||
def print_g_mod(): # $writes=print_g_mod
|
||||
print(g_mod) # $reads=g_mod
|
||||
def print_g_mod(): # $ writes=print_g_mod
|
||||
print(g_mod) # $ reads=g_mod
|
||||
|
||||
def global_mod(): # $writes=global_mod
|
||||
def global_mod(): # $ writes=global_mod
|
||||
global g_mod
|
||||
g_mod += [150] # $reads,writes=g_mod
|
||||
print_g_mod() # $reads=print_g_mod
|
||||
g_mod += [150] # $ reads,writes=g_mod
|
||||
print_g_mod() # $ reads=print_g_mod
|
||||
|
||||
def global_inside_local_function(): # $writes=global_inside_local_function
|
||||
def global_inside_local_function(): # $ writes=global_inside_local_function
|
||||
def local_function():
|
||||
print(g) # $reads=g
|
||||
print(g) # $ reads=g
|
||||
local_function()
|
||||
|
||||
## Imports
|
||||
@@ -74,24 +74,24 @@ def global_inside_local_function(): # $writes=global_inside_local_function
|
||||
|
||||
# Direct imports
|
||||
|
||||
import foo_module # $writes=foo_module
|
||||
import foo_module # $ writes=foo_module
|
||||
|
||||
def use_foo(): # $writes=use_foo
|
||||
print(foo_module.attr) # $reads=foo_module
|
||||
def use_foo(): # $ writes=use_foo
|
||||
print(foo_module.attr) # $ reads=foo_module
|
||||
|
||||
# Partial imports
|
||||
|
||||
from bar import baz_attr, quux_attr # $writes=baz_attr writes=quux_attr
|
||||
from bar import baz_attr, quux_attr # $ writes=baz_attr writes=quux_attr
|
||||
|
||||
def use_partial_import(): # $writes=use_partial_import
|
||||
print(baz_attr, quux_attr) # $reads=baz_attr reads=quux_attr
|
||||
def use_partial_import(): # $ writes=use_partial_import
|
||||
print(baz_attr, quux_attr) # $ reads=baz_attr reads=quux_attr
|
||||
|
||||
# Aliased imports
|
||||
|
||||
from spam_module import ham_attr as eggs_attr # $writes=eggs_attr
|
||||
from spam_module import ham_attr as eggs_attr # $ writes=eggs_attr
|
||||
|
||||
def use_aliased_import(): # $writes=use_aliased_import
|
||||
print(eggs_attr) # $reads=eggs_attr
|
||||
def use_aliased_import(): # $ writes=use_aliased_import
|
||||
print(eggs_attr) # $ reads=eggs_attr
|
||||
|
||||
# Import star (unlikely to work unless we happen to extract/model the referenced module)
|
||||
|
||||
@@ -99,23 +99,23 @@ def use_aliased_import(): # $writes=use_aliased_import
|
||||
|
||||
from unknown import *
|
||||
|
||||
def secretly_use_unknown(): # $writes=secretly_use_unknown
|
||||
print(unknown_attr) # $reads=unknown_attr
|
||||
def secretly_use_unknown(): # $ writes=secretly_use_unknown
|
||||
print(unknown_attr) # $ reads=unknown_attr
|
||||
|
||||
# Known modules
|
||||
|
||||
from known import *
|
||||
|
||||
def secretly_use_known(): # $writes=secretly_use_known
|
||||
print(known_attr) # $reads=known_attr
|
||||
def secretly_use_known(): # $ writes=secretly_use_known
|
||||
print(known_attr) # $ reads=known_attr
|
||||
|
||||
# Local import in function
|
||||
|
||||
def imports_locally(): # $writes=imports_locally
|
||||
def imports_locally(): # $ writes=imports_locally
|
||||
import mod1
|
||||
|
||||
# Global import hidden in function
|
||||
|
||||
def imports_stuff(): # $writes=imports_stuff
|
||||
def imports_stuff(): # $ writes=imports_stuff
|
||||
global mod2
|
||||
import mod2 # $writes=mod2
|
||||
import mod2 # $ writes=mod2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import threading
|
||||
import threading
|
||||
import time
|
||||
|
||||
# Test 1
|
||||
@@ -7,11 +7,11 @@ foo1 = None
|
||||
|
||||
def bar1():
|
||||
time.sleep(1)
|
||||
ensure_tainted(foo1) # $tainted
|
||||
ensure_tainted(foo1) # $ tainted
|
||||
|
||||
# The intent of these tests is to test how dataflow is handled through shared state accessed by different threads;
|
||||
# The intent of these tests is to test how dataflow is handled through shared state accessed by different threads;
|
||||
# but the presense or absense of the actual call to start a thread does not affect the results (there is no special modelling for Thread)
|
||||
# threading.Thread(target=bar).start()
|
||||
# threading.Thread(target=bar).start()
|
||||
|
||||
foo1 = TAINTED_STRING
|
||||
|
||||
@@ -21,7 +21,7 @@ foo2 = []
|
||||
|
||||
def bar2():
|
||||
time.sleep(1)
|
||||
ensure_tainted(foo2[0]) # $MISSING:tainted
|
||||
ensure_tainted(foo2[0]) # $ MISSING:tainted
|
||||
|
||||
threading.Thread(target=bar2).start()
|
||||
|
||||
@@ -33,7 +33,7 @@ foo3 = []
|
||||
|
||||
def bar3():
|
||||
time.sleep(1)
|
||||
ensure_tainted(foo2[0]) # $MISSING:tainted
|
||||
ensure_tainted(foo2[0]) # $ MISSING:tainted
|
||||
|
||||
foo3.append(TAINTED_STRING)
|
||||
bar3()
|
||||
@@ -42,16 +42,16 @@ bar3()
|
||||
# TP - Sanity check: Flow is found through a ListElement directly without a call
|
||||
foo4 = []
|
||||
foo4.append(TAINTED_STRING)
|
||||
ensure_tainted(foo4[0]) # $tainted
|
||||
ensure_tainted(foo4[0]) # $ tainted
|
||||
|
||||
# Test 5
|
||||
# FN - Flow is *not* tracked through a shared captured but non-global variable
|
||||
def test5():
|
||||
foo5 = None
|
||||
foo5 = None
|
||||
|
||||
def bar5():
|
||||
time.sleep(1)
|
||||
ensure_tainted(foo5) # $MISSING:tainted
|
||||
ensure_tainted(foo5) # $ MISSING:tainted
|
||||
|
||||
threading.Thread(target=bar5).start() # Only the presense of this thread call makes this an FN rather than a TN
|
||||
|
||||
@@ -64,7 +64,7 @@ def test6():
|
||||
|
||||
def bar6():
|
||||
time.sleep(1)
|
||||
ensure_tainted(foo6[0]) # $tainted
|
||||
ensure_tainted(foo6[0]) # $ tainted
|
||||
|
||||
foo6.append(TAINTED_STRING)
|
||||
bar6()
|
||||
@@ -78,7 +78,7 @@ foo7 = []
|
||||
|
||||
def bar7():
|
||||
time.sleep(1)
|
||||
ensure_tainted(foo7[0]) # $MISSING: tainted
|
||||
ensure_tainted(foo7[0]) # $ MISSING: tainted
|
||||
|
||||
def baz7(loc_foo):
|
||||
loc_foo.append(TAINTED_STRING)
|
||||
@@ -88,13 +88,13 @@ threading.Thread(target=bar7).start()
|
||||
baz7(foo7)
|
||||
|
||||
# Test 8
|
||||
# FN - Flow is also *not* found in the above case through a direct call
|
||||
# FN - Flow is also *not* found in the above case through a direct call
|
||||
|
||||
foo8 = []
|
||||
|
||||
def bar8():
|
||||
time.sleep(1)
|
||||
ensure_tainted(foo8[0]) # $MISSING: tainted
|
||||
ensure_tainted(foo8[0]) # $ MISSING: tainted
|
||||
|
||||
def baz8(loc_foo):
|
||||
loc_foo.append(TAINTED_STRING)
|
||||
@@ -109,10 +109,10 @@ def test9():
|
||||
foo9 = []
|
||||
def bar9():
|
||||
time.sleep(1)
|
||||
ensure_tainted(foo9[0]) # $tainted
|
||||
ensure_tainted(foo9[0]) # $ tainted
|
||||
|
||||
def baz9(loc_foo):
|
||||
loc_foo.append(TAINTED_STRING)
|
||||
|
||||
baz9(foo9)
|
||||
bar9()
|
||||
bar9()
|
||||
|
||||
@@ -29,32 +29,32 @@ def SINK_F(x):
|
||||
|
||||
def test_guard():
|
||||
match SOURCE:
|
||||
case x if SINK(x): #$ flow="SOURCE, l:-1 -> x"
|
||||
case x if SINK(x): # $ flow="SOURCE, l:-1 -> x"
|
||||
pass
|
||||
|
||||
@expects(2)
|
||||
def test_as_pattern():
|
||||
match SOURCE:
|
||||
case x as y:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK(y) #$ flow="SOURCE, l:-3 -> y"
|
||||
SINK(x) # $ flow="SOURCE, l:-2 -> x"
|
||||
SINK(y) # $ flow="SOURCE, l:-3 -> y"
|
||||
|
||||
def test_or_pattern():
|
||||
match SOURCE:
|
||||
# We cannot use NONSOURCE in place of "" below, since it would be seen as a variable.
|
||||
case ("" as x) | x:
|
||||
SINK(x) #$ flow="SOURCE, l:-3 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-3 -> x"
|
||||
|
||||
# No flow for literal pattern
|
||||
def test_literal_pattern():
|
||||
match SOURCE:
|
||||
case "source" as x:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x" flow="'source', l:-1 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-2 -> x" flow="'source', l:-1 -> x"
|
||||
|
||||
def test_capture_pattern():
|
||||
match SOURCE:
|
||||
case x:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-2 -> x"
|
||||
|
||||
# No flow for wildcard pattern
|
||||
|
||||
@@ -64,21 +64,21 @@ class Unsafe:
|
||||
def test_value_pattern():
|
||||
match SOURCE:
|
||||
case Unsafe.VALUE as x:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x" flow="SOURCE, l:-5 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-2 -> x" flow="SOURCE, l:-5 -> x"
|
||||
|
||||
@expects(2)
|
||||
def test_sequence_pattern_tuple():
|
||||
match (NONSOURCE, SOURCE):
|
||||
case (x, y):
|
||||
SINK_F(x)
|
||||
SINK(y) #$ flow="SOURCE, l:-3 -> y"
|
||||
SINK(y) # $ flow="SOURCE, l:-3 -> y"
|
||||
|
||||
@expects(2)
|
||||
def test_sequence_pattern_list():
|
||||
match [NONSOURCE, SOURCE]:
|
||||
case [x, y]:
|
||||
SINK_F(x) #$ SPURIOUS: flow="SOURCE, l:-2 -> x"
|
||||
SINK(y) #$ flow="SOURCE, l:-3 -> y"
|
||||
SINK_F(x) # $ SPURIOUS: flow="SOURCE, l:-2 -> x"
|
||||
SINK(y) # $ flow="SOURCE, l:-3 -> y"
|
||||
|
||||
# Sets are excluded from sequence patterns,
|
||||
# see https://www.python.org/dev/peps/pep-0635/#sequence-patterns
|
||||
@@ -88,35 +88,35 @@ def test_star_pattern_tuple():
|
||||
match (NONSOURCE, SOURCE):
|
||||
case (x, *y):
|
||||
SINK_F(x)
|
||||
SINK(y[0]) #$ flow="SOURCE, l:-3 -> y[0]"
|
||||
SINK(y[0]) # $ flow="SOURCE, l:-3 -> y[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_star_pattern_tuple_exclusion():
|
||||
match (SOURCE, NONSOURCE):
|
||||
case (x, *y):
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y[0])
|
||||
|
||||
@expects(2)
|
||||
def test_star_pattern_list():
|
||||
match [NONSOURCE, SOURCE]:
|
||||
case [x, *y]:
|
||||
SINK_F(x) #$ SPURIOUS: flow="SOURCE, l:-2 -> x"
|
||||
SINK(y[0]) #$ flow="SOURCE, l:-3 -> y[0]"
|
||||
SINK_F(x) # $ SPURIOUS: flow="SOURCE, l:-2 -> x"
|
||||
SINK(y[0]) # $ flow="SOURCE, l:-3 -> y[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_star_pattern_list_exclusion():
|
||||
match [SOURCE, NONSOURCE]:
|
||||
case [x, *y]:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y[0]) #$ SPURIOUS: flow="SOURCE, l:-3 -> y[0]"
|
||||
SINK(x) # $ flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y[0]) # $ SPURIOUS: flow="SOURCE, l:-3 -> y[0]"
|
||||
|
||||
@expects(2)
|
||||
def test_mapping_pattern():
|
||||
match {"a": NONSOURCE, "b": SOURCE}:
|
||||
case {"a": x, "b": y}:
|
||||
SINK_F(x)
|
||||
SINK(y) #$ flow="SOURCE, l:-3 -> y"
|
||||
SINK(y) # $ flow="SOURCE, l:-3 -> y"
|
||||
|
||||
# also tests the key value pattern
|
||||
@expects(2)
|
||||
@@ -124,13 +124,13 @@ def test_double_star_pattern():
|
||||
match {"a": NONSOURCE, "b": SOURCE}:
|
||||
case {"a": x, **y}:
|
||||
SINK_F(x)
|
||||
SINK(y["b"]) #$ flow="SOURCE, l:-3 -> y['b']"
|
||||
SINK(y["b"]) # $ flow="SOURCE, l:-3 -> y['b']"
|
||||
|
||||
@expects(2)
|
||||
def test_double_star_pattern_exclusion():
|
||||
match {"a": SOURCE, "b": NONSOURCE}:
|
||||
case {"a": x, **y}:
|
||||
SINK(x) #$ flow="SOURCE, l:-2 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-2 -> x"
|
||||
SINK_F(y["b"])
|
||||
try:
|
||||
SINK_F(y["a"])
|
||||
@@ -149,7 +149,7 @@ def test_class_pattern():
|
||||
|
||||
match bad_cell:
|
||||
case Cell(value = x):
|
||||
SINK(x) #$ flow="SOURCE, l:-5 -> x"
|
||||
SINK(x) # $ flow="SOURCE, l:-5 -> x"
|
||||
|
||||
match good_cell:
|
||||
case Cell(value = x):
|
||||
|
||||
@@ -182,7 +182,7 @@ SINK(instance.instance_method(SOURCE)[1]) # $ flow="SOURCE -> instance.instance
|
||||
returned_class = get_class()
|
||||
SINK(returned_class(SOURCE).config) # $ flow="SOURCE -> returned_class(..).config"
|
||||
|
||||
SINK(returned_class().instance_method(SOURCE)[1]) # $flow="SOURCE -> returned_class().instance_method(..)[1]"
|
||||
SINK(returned_class().instance_method(SOURCE)[1]) # $ flow="SOURCE -> returned_class().instance_method(..)[1]"
|
||||
|
||||
fatory_instance = MS_Factory.get_instance()
|
||||
SINK(fatory_instance.instance_method(SOURCE)[1]) # $ flow="SOURCE -> fatory_instance.instance_method(..)[1]"
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
import sys #$ importTimeFlow="ImportExpr -> sys"
|
||||
import os #$ importTimeFlow="ImportExpr -> os"
|
||||
import sys # $ importTimeFlow="ImportExpr -> sys"
|
||||
import os # $ importTimeFlow="ImportExpr -> os"
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname((__file__))))
|
||||
from testlib import expects #$ importTimeFlow="ImportMember -> expects"
|
||||
from testlib import expects # $ importTimeFlow="ImportMember -> expects"
|
||||
|
||||
# These are defined so that we can evaluate the test code.
|
||||
NONSOURCE = "not a source" #$ importTimeFlow="'not a source' -> NONSOURCE"
|
||||
SOURCE = "source" #$ importTimeFlow="'source' -> SOURCE"
|
||||
NONSOURCE = "not a source" # $ importTimeFlow="'not a source' -> NONSOURCE"
|
||||
SOURCE = "source" # $ importTimeFlow="'source' -> SOURCE"
|
||||
|
||||
|
||||
def is_source(x): #$ importTimeFlow="FunctionExpr -> is_source"
|
||||
def is_source(x): # $ importTimeFlow="FunctionExpr -> is_source"
|
||||
return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j
|
||||
|
||||
|
||||
def SINK(x): #$ importTimeFlow="FunctionExpr -> SINK"
|
||||
if is_source(x): #$ runtimeFlow="ModuleVariableNode in Module multiphase for is_source, l:-17 -> is_source"
|
||||
print("OK") #$ runtimeFlow="ModuleVariableNode in Module multiphase for print, l:-18 -> print"
|
||||
def SINK(x): # $ importTimeFlow="FunctionExpr -> SINK"
|
||||
if is_source(x): # $ runtimeFlow="ModuleVariableNode in Module multiphase for is_source, l:-17 -> is_source"
|
||||
print("OK") # $ runtimeFlow="ModuleVariableNode in Module multiphase for print, l:-18 -> print"
|
||||
else:
|
||||
print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode in Module multiphase for print, l:-20 -> print"
|
||||
print("Unexpected flow", x) # $ runtimeFlow="ModuleVariableNode in Module multiphase for print, l:-20 -> print"
|
||||
|
||||
|
||||
def SINK_F(x): #$ importTimeFlow="FunctionExpr -> SINK_F"
|
||||
if is_source(x): #$ runtimeFlow="ModuleVariableNode in Module multiphase for is_source, l:-24 -> is_source"
|
||||
print("Unexpected flow", x) #$ runtimeFlow="ModuleVariableNode in Module multiphase for print, l:-25 -> print"
|
||||
def SINK_F(x): # $ importTimeFlow="FunctionExpr -> SINK_F"
|
||||
if is_source(x): # $ runtimeFlow="ModuleVariableNode in Module multiphase for is_source, l:-24 -> is_source"
|
||||
print("Unexpected flow", x) # $ runtimeFlow="ModuleVariableNode in Module multiphase for print, l:-25 -> print"
|
||||
else:
|
||||
print("OK") #$ runtimeFlow="ModuleVariableNode in Module multiphase for print, l:-27 -> print"
|
||||
print("OK") # $ runtimeFlow="ModuleVariableNode in Module multiphase for print, l:-27 -> print"
|
||||
|
||||
def set_foo(): #$ importTimeFlow="FunctionExpr -> set_foo"
|
||||
def set_foo(): # $ importTimeFlow="FunctionExpr -> set_foo"
|
||||
global foo
|
||||
foo = SOURCE #$ runtimeFlow="ModuleVariableNode in Module multiphase for SOURCE, l:-31 -> SOURCE" # missing final definition of foo
|
||||
foo = SOURCE # $ runtimeFlow="ModuleVariableNode in Module multiphase for SOURCE, l:-31 -> SOURCE" # missing final definition of foo
|
||||
|
||||
foo = NONSOURCE #$ importTimeFlow="NONSOURCE -> foo"
|
||||
foo = NONSOURCE # $ importTimeFlow="NONSOURCE -> foo"
|
||||
set_foo()
|
||||
|
||||
@expects(2)
|
||||
def test_phases(): #$ importTimeFlow="expects(..)(..), l:-1 -> test_phases"
|
||||
def test_phases(): # $ importTimeFlow="expects(..)(..), l:-1 -> test_phases"
|
||||
global foo
|
||||
SINK(foo) #$ runtimeFlow="ModuleVariableNode in Module multiphase for SINK, l:-39 -> SINK" runtimeFlow="ModuleVariableNode in Module multiphase for foo, l:-39 -> foo"
|
||||
foo = NONSOURCE #$ runtimeFlow="ModuleVariableNode in Module multiphase for NONSOURCE, l:-40 -> NONSOURCE"
|
||||
set_foo() #$ runtimeFlow="ModuleVariableNode in Module multiphase for set_foo, l:-41 -> set_foo"
|
||||
SINK(foo) #$ runtimeFlow="ModuleVariableNode in Module multiphase for SINK, l:-42 -> SINK" runtimeFlow="ModuleVariableNode in Module multiphase for foo, l:-42 -> foo"
|
||||
SINK(foo) # $ runtimeFlow="ModuleVariableNode in Module multiphase for SINK, l:-39 -> SINK" runtimeFlow="ModuleVariableNode in Module multiphase for foo, l:-39 -> foo"
|
||||
foo = NONSOURCE # $ runtimeFlow="ModuleVariableNode in Module multiphase for NONSOURCE, l:-40 -> NONSOURCE"
|
||||
set_foo() # $ runtimeFlow="ModuleVariableNode in Module multiphase for set_foo, l:-41 -> set_foo"
|
||||
SINK(foo) # $ runtimeFlow="ModuleVariableNode in Module multiphase for SINK, l:-42 -> SINK" runtimeFlow="ModuleVariableNode in Module multiphase for foo, l:-42 -> foo"
|
||||
|
||||
@@ -2,32 +2,32 @@ class SomeClass:
|
||||
pass
|
||||
|
||||
def simple_read_write():
|
||||
x = SomeClass() # $tracked=foo
|
||||
x.foo = tracked # $tracked tracked=foo
|
||||
y = x.foo # $tracked=foo tracked
|
||||
do_stuff(y) # $tracked
|
||||
x = SomeClass() # $ tracked=foo
|
||||
x.foo = tracked # $ tracked tracked=foo
|
||||
y = x.foo # $ tracked=foo tracked
|
||||
do_stuff(y) # $ tracked
|
||||
|
||||
def foo():
|
||||
x = SomeClass() # $tracked=attr
|
||||
bar(x) # $tracked=attr
|
||||
x.attr = tracked # $tracked=attr tracked
|
||||
baz(x) # $tracked=attr
|
||||
x = SomeClass() # $ tracked=attr
|
||||
bar(x) # $ tracked=attr
|
||||
x.attr = tracked # $ tracked=attr tracked
|
||||
baz(x) # $ tracked=attr
|
||||
|
||||
def bar(x): # $tracked=attr
|
||||
z = x.attr # $tracked tracked=attr
|
||||
do_stuff(z) # $tracked
|
||||
def bar(x): # $ tracked=attr
|
||||
z = x.attr # $ tracked tracked=attr
|
||||
do_stuff(z) # $ tracked
|
||||
|
||||
def expects_int(x): # $int=field SPURIOUS: str=field
|
||||
do_int_stuff(x.field) # $int int=field SPURIOUS: str str=field
|
||||
def expects_int(x): # $ int=field SPURIOUS: str=field
|
||||
do_int_stuff(x.field) # $ int int=field SPURIOUS: str str=field
|
||||
|
||||
def expects_string(x): # $ str=field SPURIOUS: int=field
|
||||
do_string_stuff(x.field) # $str str=field SPURIOUS: int int=field
|
||||
do_string_stuff(x.field) # $ str str=field SPURIOUS: int int=field
|
||||
|
||||
def test_incompatible_types():
|
||||
x = SomeClass() # $int,str=field
|
||||
x.field = int(5) # $int=field int SPURIOUS: str=field
|
||||
expects_int(x) # $int=field SPURIOUS: str=field
|
||||
x.field = str("Hello") # $str=field str SPURIOUS: int=field
|
||||
x = SomeClass() # $ int,str=field
|
||||
x.field = int(5) # $ int=field int SPURIOUS: str=field
|
||||
expects_int(x) # $ int=field SPURIOUS: str=field
|
||||
x.field = str("Hello") # $ str=field str SPURIOUS: int=field
|
||||
expects_string(x) # $ str=field SPURIOUS: int=field
|
||||
|
||||
# set in different function
|
||||
@@ -58,7 +58,7 @@ def test_global_attribute_read():
|
||||
|
||||
def test_local_attribute_assignment():
|
||||
# Same as `test_global_attribute_assignment`, but the assigned variable is not global
|
||||
# In this case, we don't want flow going to the `ModuleVariableNode` for `local_var`
|
||||
# In this case, we don't want flow going to the `ModuleVariableNode` for `local_var`
|
||||
# (which is referenced in `test_local_attribute_read`).
|
||||
local_var = object() # $ tracked=foo
|
||||
local_var.foo = tracked # $ tracked tracked=foo
|
||||
@@ -71,11 +71,11 @@ def test_local_attribute_read():
|
||||
# Attributes assigned statically to a class
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
class MyClass: # $tracked=field
|
||||
field = tracked # $tracked
|
||||
class MyClass: # $ tracked=field
|
||||
field = tracked # $ tracked
|
||||
|
||||
lookup = MyClass.field # $tracked tracked=field
|
||||
instance = MyClass() # $tracked=field
|
||||
lookup = MyClass.field # $ tracked tracked=field
|
||||
instance = MyClass() # $ tracked=field
|
||||
lookup2 = instance.field # MISSING: tracked
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -85,56 +85,56 @@ lookup2 = instance.field # MISSING: tracked
|
||||
# Via `getattr`/`setattr`
|
||||
|
||||
def setattr_immediate_write():
|
||||
x = SomeClass() # $tracked=foo
|
||||
setattr(x,"foo", tracked) # $tracked tracked=foo
|
||||
y = x.foo # $tracked tracked=foo
|
||||
do_stuff(y) # $tracked
|
||||
x = SomeClass() # $ tracked=foo
|
||||
setattr(x,"foo", tracked) # $ tracked tracked=foo
|
||||
y = x.foo # $ tracked tracked=foo
|
||||
do_stuff(y) # $ tracked
|
||||
|
||||
def getattr_immediate_read():
|
||||
x = SomeClass() # $tracked=foo
|
||||
x.foo = tracked # $tracked tracked=foo
|
||||
y = getattr(x,"foo") # $tracked tracked=foo
|
||||
do_stuff(y) # $tracked
|
||||
x = SomeClass() # $ tracked=foo
|
||||
x.foo = tracked # $ tracked tracked=foo
|
||||
y = getattr(x,"foo") # $ tracked tracked=foo
|
||||
do_stuff(y) # $ tracked
|
||||
|
||||
def setattr_indirect_write():
|
||||
attr = "foo"
|
||||
x = SomeClass() # $tracked=foo
|
||||
setattr(x, attr, tracked) # $tracked tracked=foo
|
||||
y = x.foo # $tracked tracked=foo
|
||||
do_stuff(y) # $tracked
|
||||
x = SomeClass() # $ tracked=foo
|
||||
setattr(x, attr, tracked) # $ tracked tracked=foo
|
||||
y = x.foo # $ tracked tracked=foo
|
||||
do_stuff(y) # $ tracked
|
||||
|
||||
def getattr_indirect_read():
|
||||
attr = "foo"
|
||||
x = SomeClass() # $tracked=foo
|
||||
x.foo = tracked # $tracked tracked=foo
|
||||
y = getattr(x, attr) #$tracked tracked=foo
|
||||
do_stuff(y) # $tracked
|
||||
x = SomeClass() # $ tracked=foo
|
||||
x.foo = tracked # $ tracked tracked=foo
|
||||
y = getattr(x, attr) # $ tracked tracked=foo
|
||||
do_stuff(y) # $ tracked
|
||||
|
||||
# Via `__dict__` -- not currently implemented.
|
||||
|
||||
def dunder_dict_immediate_write():
|
||||
x = SomeClass() # $ MISSING: tracked=foo
|
||||
x.__dict__["foo"] = tracked # $tracked MISSING: tracked=foo
|
||||
x.__dict__["foo"] = tracked # $ tracked MISSING: tracked=foo
|
||||
y = x.foo # $ MISSING: tracked tracked=foo
|
||||
do_stuff(y) # $ MISSING: tracked
|
||||
|
||||
def dunder_dict_immediate_read():
|
||||
x = SomeClass() # $tracked=foo
|
||||
x.foo = tracked # $tracked tracked=foo
|
||||
x = SomeClass() # $ tracked=foo
|
||||
x.foo = tracked # $ tracked tracked=foo
|
||||
y = x.__dict__["foo"] # $ tracked=foo MISSING: tracked
|
||||
do_stuff(y) # $ MISSING: tracked
|
||||
|
||||
def dunder_dict_indirect_write():
|
||||
attr = "foo"
|
||||
x = SomeClass() # $ MISSING: tracked=foo
|
||||
x.__dict__[attr] = tracked # $tracked MISSING: tracked=foo
|
||||
x.__dict__[attr] = tracked # $ tracked MISSING: tracked=foo
|
||||
y = x.foo # $ MISSING: tracked tracked=foo
|
||||
do_stuff(y) # $ MISSING: tracked
|
||||
|
||||
def dunder_dict_indirect_read():
|
||||
attr = "foo"
|
||||
x = SomeClass() # $tracked=foo
|
||||
x.foo = tracked # $tracked tracked=foo
|
||||
x = SomeClass() # $ tracked=foo
|
||||
x.foo = tracked # $ tracked tracked=foo
|
||||
y = x.__dict__[attr] # $ tracked=foo MISSING: tracked
|
||||
do_stuff(y) # $ MISSING: tracked
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# test of other content types than attributes
|
||||
|
||||
def test_tuple(index_arg):
|
||||
tup = (tracked, other) # $tracked
|
||||
tup = (tracked, other) # $ tracked
|
||||
|
||||
tup[0] # $ tracked
|
||||
tup[1]
|
||||
|
||||
a,b = tup # $tracked
|
||||
a,b = tup # $ tracked
|
||||
a # $ tracked
|
||||
b
|
||||
|
||||
@@ -22,7 +22,7 @@ def test_tuple(index_arg):
|
||||
|
||||
|
||||
# nested tuples
|
||||
nested_tuples = ((tracked, other), (other, tracked)) # $tracked
|
||||
nested_tuples = ((tracked, other), (other, tracked)) # $ tracked
|
||||
|
||||
nested_tuples[0][0] # $ MISSING: tracked
|
||||
nested_tuples[0][1]
|
||||
@@ -44,7 +44,7 @@ def test_tuple(index_arg):
|
||||
|
||||
|
||||
def test_dict(key_arg):
|
||||
d1 = {"t": tracked, "o": other} # $tracked
|
||||
d1 = {"t": tracked, "o": other} # $ tracked
|
||||
d1["t"] # $ tracked
|
||||
d1.get("t") # $ MISSING: tracked
|
||||
d1.setdefault("t") # $ MISSING: tracked
|
||||
@@ -84,7 +84,7 @@ def test_dict(key_arg):
|
||||
|
||||
|
||||
def test_list(index_arg):
|
||||
l = [tracked, other] # $tracked
|
||||
l = [tracked, other] # $ tracked
|
||||
|
||||
l[0] # $ MISSING: tracked
|
||||
l[1]
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
def foo(foo_x): # $tracked
|
||||
print("foo", foo_x) # $tracked
|
||||
def foo(foo_x): # $ tracked
|
||||
print("foo", foo_x) # $ tracked
|
||||
|
||||
|
||||
def bar(bar_x): # $tracked
|
||||
print("bar", bar_x) # $tracked
|
||||
def bar(bar_x): # $ tracked
|
||||
print("bar", bar_x) # $ tracked
|
||||
|
||||
|
||||
if len(__file__) % 2 == 0:
|
||||
@@ -11,5 +11,5 @@ if len(__file__) % 2 == 0:
|
||||
else:
|
||||
f = bar
|
||||
|
||||
x = tracked # $tracked
|
||||
f(x) # $tracked
|
||||
x = tracked # $ tracked
|
||||
f(x) # $ tracked
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
x = tracked # $tracked
|
||||
x = tracked # $ tracked
|
||||
|
||||
def func():
|
||||
return tracked # $tracked
|
||||
return tracked # $ tracked
|
||||
|
||||
z = tracked # $tracked
|
||||
some_func(z) # $tracked
|
||||
z = tracked # $ tracked
|
||||
some_func(z) # $ tracked
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
def get_tracked():
|
||||
x = tracked # $tracked
|
||||
return x # $tracked
|
||||
x = tracked # $ tracked
|
||||
return x # $ tracked
|
||||
|
||||
def use_tracked_foo(x): # $tracked
|
||||
do_stuff(x) # $tracked
|
||||
def use_tracked_foo(x): # $ tracked
|
||||
do_stuff(x) # $ tracked
|
||||
|
||||
def foo():
|
||||
use_tracked_foo(
|
||||
get_tracked() # $tracked
|
||||
get_tracked() # $ tracked
|
||||
)
|
||||
|
||||
def use_tracked_bar(x): # $tracked
|
||||
do_stuff(x) # $tracked
|
||||
def use_tracked_bar(x): # $ tracked
|
||||
do_stuff(x) # $ tracked
|
||||
|
||||
def bar():
|
||||
x = get_tracked() # $tracked
|
||||
use_tracked_bar(x) # $tracked
|
||||
x = get_tracked() # $ tracked
|
||||
use_tracked_bar(x) # $ tracked
|
||||
|
||||
def use_tracked_baz(x): # $tracked
|
||||
do_stuff(x) # $tracked
|
||||
def use_tracked_baz(x): # $ tracked
|
||||
do_stuff(x) # $ tracked
|
||||
|
||||
def baz():
|
||||
x = tracked # $tracked
|
||||
use_tracked_baz(x) # $tracked
|
||||
x = tracked # $ tracked
|
||||
use_tracked_baz(x) # $ tracked
|
||||
|
||||
def id(x): # $tracked
|
||||
return x # $tracked
|
||||
def id(x): # $ tracked
|
||||
return x # $ tracked
|
||||
|
||||
def use_tracked_quux(x): # $ MISSING: tracked
|
||||
do_stuff(y) # call after return -- not tracked in here.
|
||||
|
||||
def quux():
|
||||
x = tracked # $tracked
|
||||
y = id(x) # $tracked
|
||||
x = tracked # $ tracked
|
||||
y = id(x) # $ tracked
|
||||
use_tracked_quux(y) # not tracked out of call to id.
|
||||
|
||||
g = None
|
||||
|
||||
def write_g(x): # $tracked
|
||||
def write_g(x): # $ tracked
|
||||
global g
|
||||
g = x # $tracked
|
||||
g = x # $ tracked
|
||||
|
||||
def use_g():
|
||||
do_stuff(g) # $tracked
|
||||
do_stuff(g) # $ tracked
|
||||
|
||||
def global_var_write_test():
|
||||
x = tracked # $tracked
|
||||
write_g(x) # $tracked
|
||||
x = tracked # $ tracked
|
||||
write_g(x) # $ tracked
|
||||
use_g()
|
||||
|
||||
def test_import():
|
||||
import mymodule
|
||||
mymodule.x # $tracked
|
||||
y = mymodule.func() # $tracked
|
||||
y # $tracked
|
||||
mymodule.z # $tracked
|
||||
mymodule.x # $ tracked
|
||||
y = mymodule.func() # $ tracked
|
||||
y # $ tracked
|
||||
mymodule.z # $ tracked
|
||||
|
||||
|
||||
def to_inner_scope():
|
||||
x = tracked # $tracked
|
||||
x = tracked # $ tracked
|
||||
def foo():
|
||||
y = x # $ tracked
|
||||
return y # $ tracked
|
||||
@@ -67,15 +67,15 @@ def to_inner_scope():
|
||||
|
||||
|
||||
def from_parameter_default():
|
||||
x_alias = tracked # $tracked
|
||||
def outer(x=tracked): # $tracked
|
||||
print(x) # $tracked
|
||||
x_alias = tracked # $ tracked
|
||||
def outer(x=tracked): # $ tracked
|
||||
print(x) # $ tracked
|
||||
def inner():
|
||||
print(x) # $ tracked
|
||||
print(x_alias) # $tracked
|
||||
return x # $tracked
|
||||
also_x = outer() # $tracked
|
||||
print(also_x) # $tracked
|
||||
print(x_alias) # $ tracked
|
||||
return x # $ tracked
|
||||
also_x = outer() # $ tracked
|
||||
print(also_x) # $ tracked
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -86,7 +86,7 @@ def my_decorator(func):
|
||||
# This part doesn't make any sense in a normal decorator, but just shows how we
|
||||
# handle type-tracking
|
||||
|
||||
func() # $tracked
|
||||
func() # $ tracked
|
||||
|
||||
def wrapper():
|
||||
print("before function call")
|
||||
@@ -97,7 +97,7 @@ def my_decorator(func):
|
||||
|
||||
@my_decorator
|
||||
def get_tracked2():
|
||||
return tracked # $tracked
|
||||
return tracked # $ tracked
|
||||
|
||||
@my_decorator
|
||||
def unrelated_func():
|
||||
@@ -109,17 +109,17 @@ def use_funcs_with_decorators():
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
def expects_int(x): # $int
|
||||
do_int_stuff(x) # $int
|
||||
def expects_int(x): # $ int
|
||||
do_int_stuff(x) # $ int
|
||||
|
||||
def expects_string(x): # $str
|
||||
do_string_stuff(x) # $str
|
||||
def expects_string(x): # $ str
|
||||
do_string_stuff(x) # $ str
|
||||
|
||||
def redefine_test():
|
||||
x = int(5) # $int
|
||||
expects_int(x) # $int
|
||||
x = str("Hello") # $str
|
||||
expects_string(x) # $str
|
||||
x = int(5) # $ int
|
||||
expects_int(x) # $ int
|
||||
x = str("Hello") # $ str
|
||||
expects_string(x) # $ str
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Tracking of self in methods
|
||||
|
||||
@@ -33,7 +33,7 @@ def SINK_F(x):
|
||||
def by_value1():
|
||||
a = SOURCE
|
||||
def inner(a_val=a):
|
||||
SINK(a_val) #$ captured
|
||||
SINK(a_val) # $ captured
|
||||
SINK_F(a)
|
||||
a = NONSOURCE
|
||||
inner()
|
||||
@@ -41,7 +41,7 @@ def by_value1():
|
||||
def by_value2():
|
||||
a = NONSOURCE
|
||||
def inner(a_val=a):
|
||||
SINK(a) #$ captured
|
||||
SINK(a) # $ captured
|
||||
SINK_F(a_val)
|
||||
a = SOURCE
|
||||
inner()
|
||||
|
||||
@@ -37,7 +37,7 @@ def out():
|
||||
def captureOut1():
|
||||
sinkO1["x"] = SOURCE
|
||||
captureOut1()
|
||||
SINK(sinkO1["x"]) #$ captured
|
||||
SINK(sinkO1["x"]) # $ captured
|
||||
|
||||
sinkO2 = { "x": "" }
|
||||
def captureOut2():
|
||||
@@ -45,7 +45,7 @@ def out():
|
||||
sinkO2["x"] = SOURCE
|
||||
m()
|
||||
captureOut2()
|
||||
SINK(sinkO2["x"]) #$ captured
|
||||
SINK(sinkO2["x"]) # $ captured
|
||||
|
||||
nonSink0 = { "x": "" }
|
||||
def captureOut1NotCalled():
|
||||
@@ -67,7 +67,7 @@ def through(tainted):
|
||||
def captureOut1():
|
||||
sinkO1["x"] = tainted
|
||||
captureOut1()
|
||||
SINK(sinkO1["x"]) #$ captured
|
||||
SINK(sinkO1["x"]) # $ captured
|
||||
|
||||
sinkO2 = { "x": "" }
|
||||
def captureOut2():
|
||||
@@ -75,7 +75,7 @@ def through(tainted):
|
||||
sinkO2["x"] = tainted
|
||||
m()
|
||||
captureOut2()
|
||||
SINK(sinkO2["x"]) #$ captured
|
||||
SINK(sinkO2["x"]) # $ captured
|
||||
|
||||
nonSink1 = { "x": "" }
|
||||
def captureOut1NotCalled():
|
||||
|
||||
@@ -42,7 +42,7 @@ def out():
|
||||
global sinkO1
|
||||
sinkO1 = SOURCE
|
||||
captureOut1()
|
||||
SINK(sinkO1) #$ captured
|
||||
SINK(sinkO1) # $ captured
|
||||
|
||||
def captureOut2():
|
||||
def m():
|
||||
@@ -50,12 +50,12 @@ def out():
|
||||
sinkO2 = SOURCE
|
||||
m()
|
||||
captureOut2()
|
||||
SINK(sinkO2) #$ captured
|
||||
SINK(sinkO2) # $ captured
|
||||
|
||||
def captureOut1NotCalled():
|
||||
global nonSink1
|
||||
nonSink1 = SOURCE
|
||||
SINK_F(nonSink1) #$ SPURIOUS: captured
|
||||
SINK_F(nonSink1) # $ SPURIOUS: captured
|
||||
|
||||
def captureOut2NotCalled():
|
||||
# notice that `m` is not called
|
||||
@@ -63,7 +63,7 @@ def out():
|
||||
global nonSink2
|
||||
nonSink2 = SOURCE
|
||||
captureOut2NotCalled()
|
||||
SINK_F(nonSink2) #$ SPURIOUS: captured
|
||||
SINK_F(nonSink2) # $ SPURIOUS: captured
|
||||
|
||||
@expects(4)
|
||||
def test_out():
|
||||
@@ -78,7 +78,7 @@ def through(tainted):
|
||||
global sinkT1
|
||||
sinkT1 = tainted
|
||||
captureOut1()
|
||||
SINK(sinkT1) #$ captured
|
||||
SINK(sinkT1) # $ captured
|
||||
|
||||
def captureOut2():
|
||||
def m():
|
||||
@@ -86,7 +86,7 @@ def through(tainted):
|
||||
sinkT2 = tainted
|
||||
m()
|
||||
captureOut2()
|
||||
SINK(sinkT2) #$ captured
|
||||
SINK(sinkT2) # $ captured
|
||||
|
||||
def captureOut1NotCalled():
|
||||
global nonSinkT1
|
||||
|
||||
@@ -34,17 +34,17 @@ def SINK_F(x):
|
||||
def inParam(tainted):
|
||||
def captureIn1():
|
||||
sinkI1 = tainted
|
||||
SINK(sinkI1) #$ captured
|
||||
SINK(sinkI1) # $ captured
|
||||
captureIn1()
|
||||
|
||||
def captureIn2():
|
||||
def m():
|
||||
sinkI2 = tainted
|
||||
SINK(sinkI2) #$ captured
|
||||
SINK(sinkI2) # $ captured
|
||||
m()
|
||||
captureIn2()
|
||||
|
||||
captureIn3 = lambda arg: SINK(tainted) #$ captured
|
||||
captureIn3 = lambda arg: SINK(tainted) # $ captured
|
||||
captureIn3("")
|
||||
|
||||
def captureIn1NotCalled():
|
||||
@@ -68,17 +68,17 @@ def inLocal():
|
||||
|
||||
def captureIn1():
|
||||
sinkI1 = tainted
|
||||
SINK(sinkI1) #$ captured
|
||||
SINK(sinkI1) # $ captured
|
||||
captureIn1()
|
||||
|
||||
def captureIn2():
|
||||
def m():
|
||||
sinkI2 = tainted
|
||||
SINK(sinkI2) #$ captured
|
||||
SINK(sinkI2) # $ captured
|
||||
m()
|
||||
captureIn2()
|
||||
|
||||
captureIn3 = lambda arg: SINK(tainted) #$ captured
|
||||
captureIn3 = lambda arg: SINK(tainted) # $ captured
|
||||
captureIn3("")
|
||||
|
||||
def captureIn1NotCalled():
|
||||
|
||||
@@ -38,7 +38,7 @@ def out():
|
||||
nonlocal sinkO1
|
||||
sinkO1 = SOURCE
|
||||
captureOut1()
|
||||
SINK(sinkO1) #$ captured
|
||||
SINK(sinkO1) # $ captured
|
||||
|
||||
sinkO2 = ""
|
||||
def captureOut2():
|
||||
@@ -47,7 +47,7 @@ def out():
|
||||
sinkO2 = SOURCE
|
||||
m()
|
||||
captureOut2()
|
||||
SINK(sinkO2) #$ captured
|
||||
SINK(sinkO2) # $ captured
|
||||
|
||||
nonSink1 = ""
|
||||
def captureOut1NotCalled():
|
||||
@@ -74,7 +74,7 @@ def through(tainted):
|
||||
nonlocal sinkO1
|
||||
sinkO1 = tainted
|
||||
captureOut1()
|
||||
SINK(sinkO1) #$ captured
|
||||
SINK(sinkO1) # $ captured
|
||||
|
||||
sinkO2 = ""
|
||||
def captureOut2():
|
||||
@@ -83,7 +83,7 @@ def through(tainted):
|
||||
sinkO2 = tainted
|
||||
m()
|
||||
captureOut2()
|
||||
SINK(sinkO2) #$ captured
|
||||
SINK(sinkO2) # $ captured
|
||||
|
||||
nonSink1 = ""
|
||||
def captureOut1NotCalled():
|
||||
|
||||
@@ -34,16 +34,16 @@ l = [NONSOURCE]
|
||||
SINK_F(l[0])
|
||||
|
||||
l_mod = [SOURCE for x in l]
|
||||
SINK(l_mod[0]) #$ captured
|
||||
SINK(l_mod[0]) # $ captured
|
||||
|
||||
l_mod_lambda = [(lambda a : SOURCE)(x) for x in l]
|
||||
SINK(l_mod_lambda[0]) #$ captured
|
||||
SINK(l_mod_lambda[0]) # $ captured
|
||||
|
||||
def mod(x):
|
||||
return SOURCE
|
||||
|
||||
l_mod_function = [mod(x) for x in l]
|
||||
SINK(l_mod_function[0]) #$ captured
|
||||
SINK(l_mod_function[0]) # $ captured
|
||||
|
||||
def mod_list(l):
|
||||
def mod_local(x):
|
||||
@@ -52,7 +52,7 @@ def mod_list(l):
|
||||
return [mod_local(x) for x in l]
|
||||
|
||||
l_modded = mod_list(l)
|
||||
SINK(l_modded[0]) #$ captured
|
||||
SINK(l_modded[0]) # $ captured
|
||||
|
||||
def mod_list_first(l):
|
||||
def mod_local(x):
|
||||
@@ -61,4 +61,4 @@ def mod_list_first(l):
|
||||
return [mod_local(l[0])]
|
||||
|
||||
l_modded_first = mod_list_first(l)
|
||||
SINK(l_modded_first[0]) #$ captured
|
||||
SINK(l_modded_first[0]) # $ captured
|
||||
|
||||
@@ -38,7 +38,7 @@ def test_captured_field():
|
||||
foo.setFoo(NONSOURCE)
|
||||
|
||||
def test():
|
||||
SINK(foo.getFoo()) #$ captured
|
||||
SINK(foo.getFoo()) # $ captured
|
||||
|
||||
def read():
|
||||
return foo.getFoo()
|
||||
@@ -48,4 +48,4 @@ def test_captured_field():
|
||||
foo.setFoo(SOURCE)
|
||||
test()
|
||||
|
||||
SINK(read()) #$ captured
|
||||
SINK(read()) # $ captured
|
||||
|
||||
@@ -45,4 +45,4 @@ def test_library_call():
|
||||
for x in map(set, [1]):
|
||||
pass
|
||||
|
||||
SINK(captured["x"]) #$ captured
|
||||
SINK(captured["x"]) # $ captured
|
||||
|
||||
@@ -92,12 +92,12 @@ def only_az(value):
|
||||
class CommentValidatorNotUsed(models.Model):
|
||||
text = models.CharField(max_length=256, validators=[only_az])
|
||||
|
||||
def save_comment_validator_not_used(request): # $requestHandler
|
||||
def save_comment_validator_not_used(request): # $ requestHandler
|
||||
comment = CommentValidatorNotUsed(text=request.POST["text"])
|
||||
comment.save()
|
||||
return HttpResponse("ok")
|
||||
|
||||
def display_comment_validator_not_used(request): # $requestHandler
|
||||
def display_comment_validator_not_used(request): # $ requestHandler
|
||||
comment = CommentValidatorNotUsed.objects.last()
|
||||
return HttpResponse(comment.text) # NOT OK
|
||||
|
||||
@@ -111,12 +111,12 @@ http http://127.0.0.1:8000/display_comment_validator_not_used/
|
||||
class CommentValidatorUsed(models.Model):
|
||||
text = models.CharField(max_length=256, validators=[only_az])
|
||||
|
||||
def save_comment_validator_used(request): # $requestHandler
|
||||
def save_comment_validator_used(request): # $ requestHandler
|
||||
comment = CommentValidatorUsed(text=request.POST["text"])
|
||||
comment.full_clean()
|
||||
comment.save()
|
||||
|
||||
def display_comment_validator_used(request): # $requestHandler
|
||||
def display_comment_validator_used(request): # $ requestHandler
|
||||
comment = CommentValidatorUsed.objects.last()
|
||||
return HttpResponse(comment.text) # sort of OK
|
||||
|
||||
|
||||
@@ -4,21 +4,21 @@ from django.http.response import HttpResponse
|
||||
from django.views.generic import View
|
||||
|
||||
|
||||
def url_match_xss(request, foo, bar, no_taint=None): # $requestHandler routedParameter=foo routedParameter=bar
|
||||
return HttpResponse('url_match_xss: {} {}'.format(foo, bar)) # $HttpResponse
|
||||
def url_match_xss(request, foo, bar, no_taint=None): # $ requestHandler routedParameter=foo routedParameter=bar
|
||||
return HttpResponse('url_match_xss: {} {}'.format(foo, bar)) # $ HttpResponse
|
||||
|
||||
|
||||
def get_params_xss(request): # $requestHandler
|
||||
return HttpResponse(request.GET.get("untrusted")) # $HttpResponse
|
||||
def get_params_xss(request): # $ requestHandler
|
||||
return HttpResponse(request.GET.get("untrusted")) # $ HttpResponse
|
||||
|
||||
|
||||
def post_params_xss(request): # $requestHandler
|
||||
return HttpResponse(request.POST.get("untrusted")) # $HttpResponse
|
||||
def post_params_xss(request): # $ requestHandler
|
||||
return HttpResponse(request.POST.get("untrusted")) # $ HttpResponse
|
||||
|
||||
|
||||
def http_resp_write(request): # $requestHandler
|
||||
rsp = HttpResponse() # $HttpResponse
|
||||
rsp.write(request.GET.get("untrusted")) # $HttpResponse
|
||||
def http_resp_write(request): # $ requestHandler
|
||||
rsp = HttpResponse() # $ HttpResponse
|
||||
rsp.write(request.GET.get("untrusted")) # $ HttpResponse
|
||||
return rsp
|
||||
|
||||
|
||||
@@ -27,53 +27,53 @@ class Foo(object):
|
||||
|
||||
|
||||
def post(self, request, untrusted): # $ MISSING: requestHandler routedParameter=untrusted
|
||||
return HttpResponse('Foo post: {}'.format(untrusted)) # $HttpResponse
|
||||
return HttpResponse('Foo post: {}'.format(untrusted)) # $ HttpResponse
|
||||
|
||||
|
||||
class ClassView(View, Foo):
|
||||
|
||||
def get(self, request, untrusted): # $ requestHandler routedParameter=untrusted
|
||||
return HttpResponse('ClassView get: {}'.format(untrusted)) # $HttpResponse
|
||||
return HttpResponse('ClassView get: {}'.format(untrusted)) # $ HttpResponse
|
||||
|
||||
|
||||
def show_articles(request, page_number=1): # $requestHandler routedParameter=page_number
|
||||
def show_articles(request, page_number=1): # $ requestHandler routedParameter=page_number
|
||||
page_number = int(page_number)
|
||||
return HttpResponse('articles page: {}'.format(page_number)) # $HttpResponse
|
||||
return HttpResponse('articles page: {}'.format(page_number)) # $ HttpResponse
|
||||
|
||||
|
||||
def xxs_positional_arg(request, arg0, arg1, no_taint=None): # $requestHandler routedParameter=arg0 routedParameter=arg1
|
||||
return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1)) # $HttpResponse
|
||||
def xxs_positional_arg(request, arg0, arg1, no_taint=None): # $ requestHandler routedParameter=arg0 routedParameter=arg1
|
||||
return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1)) # $ HttpResponse
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r"^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)", url_match_xss), # $routeSetup="^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)"
|
||||
url(r"^get_params", get_params_xss), # $routeSetup="^get_params"
|
||||
url(r"^post_params", post_params_xss), # $routeSetup="^post_params"
|
||||
url(r"^http_resp_write", http_resp_write), # $routeSetup="^http_resp_write"
|
||||
url(r"^class_view/(?P<untrusted>.+)", ClassView.as_view()), # $routeSetup="^class_view/(?P<untrusted>.+)"
|
||||
url(r"^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)", url_match_xss), # $ routeSetup="^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)"
|
||||
url(r"^get_params", get_params_xss), # $ routeSetup="^get_params"
|
||||
url(r"^post_params", post_params_xss), # $ routeSetup="^post_params"
|
||||
url(r"^http_resp_write", http_resp_write), # $ routeSetup="^http_resp_write"
|
||||
url(r"^class_view/(?P<untrusted>.+)", ClassView.as_view()), # $ routeSetup="^class_view/(?P<untrusted>.+)"
|
||||
|
||||
# one pattern to support `articles/page-<n>` and ensuring that articles/ goes to page-1
|
||||
url(r"articles/^(?:page-(?P<page_number>\d+)/)?", show_articles), # $routeSetup="articles/^(?:page-(?P<page_number>\d+)/)?"
|
||||
url(r"articles/^(?:page-(?P<page_number>\d+)/)?", show_articles), # $ routeSetup="articles/^(?:page-(?P<page_number>\d+)/)?"
|
||||
# passing as positional argument is not the recommended way of doing things, but it is certainly
|
||||
# possible
|
||||
url(r"^([^/]+)/(?:foo|bar)/([^/]+)", xxs_positional_arg, name='xxs_positional_arg'), # $routeSetup="^([^/]+)/(?:foo|bar)/([^/]+)"
|
||||
url(r"^([^/]+)/(?:foo|bar)/([^/]+)", xxs_positional_arg, name='xxs_positional_arg'), # $ routeSetup="^([^/]+)/(?:foo|bar)/([^/]+)"
|
||||
]
|
||||
|
||||
################################################################################
|
||||
# Using patterns() for routing
|
||||
|
||||
def show_user(request, username): # $requestHandler routedParameter=username
|
||||
return HttpResponse('show_user {}'.format(username)) # $HttpResponse
|
||||
def show_user(request, username): # $ requestHandler routedParameter=username
|
||||
return HttpResponse('show_user {}'.format(username)) # $ HttpResponse
|
||||
|
||||
|
||||
urlpatterns = patterns(url(r"^users/(?P<username>[^/]+)", show_user)) # $routeSetup="^users/(?P<username>[^/]+)"
|
||||
urlpatterns = patterns(url(r"^users/(?P<username>[^/]+)", show_user)) # $ routeSetup="^users/(?P<username>[^/]+)"
|
||||
|
||||
################################################################################
|
||||
# Show we understand the keyword arguments to django.conf.urls.url
|
||||
|
||||
def kw_args(request): # $requestHandler
|
||||
return HttpResponse('kw_args') # $HttpResponse
|
||||
def kw_args(request): # $ requestHandler
|
||||
return HttpResponse('kw_args') # $ HttpResponse
|
||||
|
||||
urlpatterns = [
|
||||
url(view=kw_args, regex=r"^kw_args") # $routeSetup="^kw_args"
|
||||
url(view=kw_args, regex=r"^kw_args") # $ routeSetup="^kw_args"
|
||||
]
|
||||
|
||||
@@ -8,12 +8,12 @@ import json
|
||||
# FP reported in https://github.com/github/codeql-python-team/issues/38
|
||||
def safe__json_response(request):
|
||||
# implicitly sets Content-Type to "application/json"
|
||||
return JsonResponse({"foo": request.GET.get("foo")}) # $HttpResponse mimetype=application/json responseBody=Dict
|
||||
return JsonResponse({"foo": request.GET.get("foo")}) # $ HttpResponse mimetype=application/json responseBody=Dict
|
||||
|
||||
# Not an XSS sink, since the Content-Type is not "text/html"
|
||||
def safe__manual_json_response(request):
|
||||
json_data = '{"json": "{}"}'.format(request.GET.get("foo"))
|
||||
return HttpResponse(json_data, content_type="application/json") # $HttpResponse mimetype=application/json responseBody=json_data
|
||||
return HttpResponse(json_data, content_type="application/json") # $ HttpResponse mimetype=application/json responseBody=json_data
|
||||
|
||||
# reproduction of FP seen here:
|
||||
# Usage: https://github.com/edx/edx-platform/blob/d70ebe6343a1573c694d6cf68f92c1ad40b73d7d/lms/djangoapps/commerce/api/v0/views.py#L106
|
||||
@@ -27,25 +27,25 @@ class MyJsonResponse(HttpResponse):
|
||||
# Not an XSS sink, since the Content-Type is not "text/html"
|
||||
def safe__custom_json_response(request):
|
||||
json_data = '{"json": "{}"}'.format(request.GET.get("foo"))
|
||||
return MyJsonResponse(json_data) # $HttpResponse responseBody=json_data SPURIOUS: mimetype=text/html MISSING: mimetype=application/json
|
||||
return MyJsonResponse(json_data) # $ HttpResponse responseBody=json_data SPURIOUS: mimetype=text/html MISSING: mimetype=application/json
|
||||
|
||||
|
||||
# Not an XSS sink, since the Content-Type is not "text/html"
|
||||
def safe__manual_content_type(request):
|
||||
return HttpResponse('<img src="0" onerror="alert(1)">', content_type="text/plain") # $HttpResponse mimetype=text/plain responseBody='<img src="0" onerror="alert(1)">'
|
||||
return HttpResponse('<img src="0" onerror="alert(1)">', content_type="text/plain") # $ HttpResponse mimetype=text/plain responseBody='<img src="0" onerror="alert(1)">'
|
||||
|
||||
# XSS FP reported in https://github.com/github/codeql/issues/3466
|
||||
# Note: This should be an open-redirect sink, but not an XSS sink.
|
||||
def or__redirect(request):
|
||||
next = request.GET.get("next")
|
||||
return HttpResponseRedirect(next) # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation=next
|
||||
return HttpResponseRedirect(next) # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation=next
|
||||
|
||||
def information_exposure_through_redirect(request, as_kw=False):
|
||||
# This is a contrived example, but possible
|
||||
private = "private"
|
||||
next = request.GET.get("next")
|
||||
if as_kw:
|
||||
return HttpResponseRedirect(next, content=private) # $HttpResponse mimetype=text/html responseBody=private HttpRedirectResponse redirectLocation=next
|
||||
return HttpResponseRedirect(next, content=private) # $ HttpResponse mimetype=text/html responseBody=private HttpRedirectResponse redirectLocation=next
|
||||
else:
|
||||
return HttpResponseRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private HttpRedirectResponse redirectLocation=next
|
||||
|
||||
@@ -91,20 +91,20 @@ class CustomRedirectView(RedirectView):
|
||||
|
||||
# Ensure that simple subclasses are still vuln to XSS
|
||||
def xss__not_found(request):
|
||||
return HttpResponseNotFound(request.GET.get("name")) # $HttpResponse mimetype=text/html responseBody=request.GET.get(..)
|
||||
return HttpResponseNotFound(request.GET.get("name")) # $ HttpResponse mimetype=text/html responseBody=request.GET.get(..)
|
||||
|
||||
# Ensure we still have an XSS sink when manually setting the content_type to HTML
|
||||
def xss__manual_response_type(request):
|
||||
return HttpResponse(request.GET.get("name"), content_type="text/html; charset=utf-8") # $HttpResponse mimetype=text/html responseBody=request.GET.get(..)
|
||||
return HttpResponse(request.GET.get("name"), content_type="text/html; charset=utf-8") # $ HttpResponse mimetype=text/html responseBody=request.GET.get(..)
|
||||
|
||||
def xss__write(request):
|
||||
response = HttpResponse() # $HttpResponse mimetype=text/html
|
||||
response.write(request.GET.get("name")) # $HttpResponse mimetype=text/html responseBody=request.GET.get(..)
|
||||
response = HttpResponse() # $ HttpResponse mimetype=text/html
|
||||
response.write(request.GET.get("name")) # $ HttpResponse mimetype=text/html responseBody=request.GET.get(..)
|
||||
|
||||
# This is safe but probably a bug if the argument to `write` is not a result of `json.dumps` or similar.
|
||||
def safe__write_json(request):
|
||||
response = JsonResponse() # $HttpResponse mimetype=application/json
|
||||
response.write(request.GET.get("name")) # $HttpResponse mimetype=application/json responseBody=request.GET.get(..)
|
||||
response = JsonResponse() # $ HttpResponse mimetype=application/json
|
||||
response.write(request.GET.get("name")) # $ HttpResponse mimetype=application/json responseBody=request.GET.get(..)
|
||||
|
||||
# Ensure manual subclasses are vulnerable
|
||||
class CustomResponse(HttpResponse):
|
||||
@@ -112,15 +112,15 @@ class CustomResponse(HttpResponse):
|
||||
super().__init__(content, *args, content_type="text/html", **kwargs)
|
||||
|
||||
def xss__custom_response(request):
|
||||
return CustomResponse("ACME Responses", request.GET("name")) # $HttpResponse MISSING: mimetype=text/html responseBody=request.GET.get(..) SPURIOUS: responseBody="ACME Responses"
|
||||
return CustomResponse("ACME Responses", request.GET("name")) # $ HttpResponse MISSING: mimetype=text/html responseBody=request.GET.get(..) SPURIOUS: responseBody="ACME Responses"
|
||||
|
||||
class CustomJsonResponse(JsonResponse):
|
||||
def __init__(self, banner, content, *args, **kwargs):
|
||||
super().__init__(content, *args, content_type="text/html", **kwargs)
|
||||
|
||||
@csrf_protect # $CsrfLocalProtectionEnabled=safe__custom_json_response
|
||||
@csrf_protect # $ CsrfLocalProtectionEnabled=safe__custom_json_response
|
||||
def safe__custom_json_response(request):
|
||||
return CustomJsonResponse("ACME Responses", {"foo": request.GET.get("foo")}) # $HttpResponse mimetype=application/json MISSING: responseBody=Dict SPURIOUS: responseBody="ACME Responses"
|
||||
return CustomJsonResponse("ACME Responses", {"foo": request.GET.get("foo")}) # $ HttpResponse mimetype=application/json MISSING: responseBody=Dict SPURIOUS: responseBody="ACME Responses"
|
||||
|
||||
################################################################################
|
||||
# Cookies
|
||||
@@ -135,7 +135,7 @@ def setting_cookie(request):
|
||||
resp.delete_cookie("key4") # $ CookieWrite CookieName="key4"
|
||||
resp.delete_cookie(key="key4") # $ CookieWrite CookieName="key4"
|
||||
resp["Set-Cookie"] = "key5=value5" # $ headerWriteName="Set-Cookie" headerWriteValue="key5=value5" CookieWrite CookieRawHeader="key5=value5" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key6", value="value6", secure=True, httponly=False, samesite="None") # $ CookieWrite CookieName="key6" CookieValue="value6" CookieSecure=true CookieHttpOnly=false CookieSameSite=None
|
||||
resp.set_cookie(key="key6", value="value6", secure=True, httponly=False, samesite="None") # $ CookieWrite CookieName="key6" CookieValue="value6" CookieSecure=true CookieHttpOnly=false CookieSameSite=None
|
||||
kwargs = {'secure': True}
|
||||
resp.set_cookie(key="key7", value="value7", **kwargs) # $ CookieWrite CookieName="key7" CookieValue="value7"
|
||||
return resp
|
||||
|
||||
@@ -6,21 +6,21 @@ import django.views.generic.base
|
||||
from django.views.decorators.http import require_GET
|
||||
|
||||
|
||||
def url_match_xss(request, foo, bar, no_taint=None): # $requestHandler routedParameter=foo routedParameter=bar
|
||||
return HttpResponse('url_match_xss: {} {}'.format(foo, bar)) # $HttpResponse
|
||||
def url_match_xss(request, foo, bar, no_taint=None): # $ requestHandler routedParameter=foo routedParameter=bar
|
||||
return HttpResponse('url_match_xss: {} {}'.format(foo, bar)) # $ HttpResponse
|
||||
|
||||
|
||||
def get_params_xss(request): # $requestHandler
|
||||
return HttpResponse(request.GET.get("untrusted")) # $HttpResponse
|
||||
def get_params_xss(request): # $ requestHandler
|
||||
return HttpResponse(request.GET.get("untrusted")) # $ HttpResponse
|
||||
|
||||
|
||||
def post_params_xss(request): # $requestHandler
|
||||
return HttpResponse(request.POST.get("untrusted")) # $HttpResponse
|
||||
def post_params_xss(request): # $ requestHandler
|
||||
return HttpResponse(request.POST.get("untrusted")) # $ HttpResponse
|
||||
|
||||
|
||||
def http_resp_write(request): # $requestHandler
|
||||
rsp = HttpResponse() # $HttpResponse
|
||||
rsp.write(request.GET.get("untrusted")) # $HttpResponse
|
||||
def http_resp_write(request): # $ requestHandler
|
||||
rsp = HttpResponse() # $ HttpResponse
|
||||
rsp.write(request.GET.get("untrusted")) # $ HttpResponse
|
||||
return rsp
|
||||
|
||||
|
||||
@@ -29,13 +29,13 @@ class Foo(object):
|
||||
|
||||
|
||||
def post(self, request, untrusted): # $ MISSING: requestHandler routedParameter=untrusted
|
||||
return HttpResponse('Foo post: {}'.format(untrusted)) # $HttpResponse
|
||||
return HttpResponse('Foo post: {}'.format(untrusted)) # $ HttpResponse
|
||||
|
||||
|
||||
class ClassView(View, Foo):
|
||||
|
||||
def get(self, request, untrusted): # $ requestHandler routedParameter=untrusted
|
||||
return HttpResponse('ClassView get: {}'.format(untrusted)) # $HttpResponse
|
||||
return HttpResponse('ClassView get: {}'.format(untrusted)) # $ HttpResponse
|
||||
|
||||
|
||||
# direct import with full path to `View` class
|
||||
@@ -44,38 +44,38 @@ class ClassView2(django.views.generic.base.View):
|
||||
pass
|
||||
|
||||
|
||||
def show_articles(request, page_number=1): # $requestHandler routedParameter=page_number
|
||||
def show_articles(request, page_number=1): # $ requestHandler routedParameter=page_number
|
||||
page_number = int(page_number)
|
||||
return HttpResponse('articles page: {}'.format(page_number)) # $HttpResponse
|
||||
return HttpResponse('articles page: {}'.format(page_number)) # $ HttpResponse
|
||||
|
||||
|
||||
def xxs_positional_arg(request, arg0, arg1, no_taint=None): # $requestHandler routedParameter=arg0 routedParameter=arg1
|
||||
return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1)) # $HttpResponse
|
||||
def xxs_positional_arg(request, arg0, arg1, no_taint=None): # $ requestHandler routedParameter=arg0 routedParameter=arg1
|
||||
return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1)) # $ HttpResponse
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
re_path(r"^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)", url_match_xss), # $routeSetup="^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)"
|
||||
re_path(r"^get_params", get_params_xss), # $routeSetup="^get_params"
|
||||
re_path(r"^post_params", post_params_xss), # $routeSetup="^post_params"
|
||||
re_path(r"^http_resp_write", http_resp_write), # $routeSetup="^http_resp_write"
|
||||
re_path(r"^class_view/(?P<untrusted>.+)", ClassView.as_view()), # $routeSetup="^class_view/(?P<untrusted>.+)"
|
||||
re_path(r"^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)", url_match_xss), # $ routeSetup="^url_match/(?P<foo>[^/]+)/(?P<bar>[^/]+)"
|
||||
re_path(r"^get_params", get_params_xss), # $ routeSetup="^get_params"
|
||||
re_path(r"^post_params", post_params_xss), # $ routeSetup="^post_params"
|
||||
re_path(r"^http_resp_write", http_resp_write), # $ routeSetup="^http_resp_write"
|
||||
re_path(r"^class_view/(?P<untrusted>.+)", ClassView.as_view()), # $ routeSetup="^class_view/(?P<untrusted>.+)"
|
||||
|
||||
# one pattern to support `articles/page-<n>` and ensuring that articles/ goes to page-1
|
||||
re_path(r"articles/^(?:page-(?P<page_number>\d+)/)?", show_articles), # $routeSetup="articles/^(?:page-(?P<page_number>\d+)/)?"
|
||||
re_path(r"articles/^(?:page-(?P<page_number>\d+)/)?", show_articles), # $ routeSetup="articles/^(?:page-(?P<page_number>\d+)/)?"
|
||||
# passing as positional argument is not the recommended way of doing things, but it is certainly
|
||||
# possible
|
||||
re_path(r"^([^/]+)/(?:foo|bar)/([^/]+)", xxs_positional_arg, name='xxs_positional_arg'), # $routeSetup="^([^/]+)/(?:foo|bar)/([^/]+)"
|
||||
re_path(r"^([^/]+)/(?:foo|bar)/([^/]+)", xxs_positional_arg, name='xxs_positional_arg'), # $ routeSetup="^([^/]+)/(?:foo|bar)/([^/]+)"
|
||||
]
|
||||
|
||||
|
||||
# Show we understand the keyword arguments to django.urls.re_path
|
||||
|
||||
def re_path_kwargs(request): # $requestHandler
|
||||
return HttpResponse('re_path_kwargs') # $HttpResponse
|
||||
def re_path_kwargs(request): # $ requestHandler
|
||||
return HttpResponse('re_path_kwargs') # $ HttpResponse
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
re_path(view=re_path_kwargs, route=r"^specifying-as-kwargs-is-not-a-problem") # $routeSetup="^specifying-as-kwargs-is-not-a-problem"
|
||||
re_path(view=re_path_kwargs, route=r"^specifying-as-kwargs-is-not-a-problem") # $ routeSetup="^specifying-as-kwargs-is-not-a-problem"
|
||||
]
|
||||
|
||||
################################################################################
|
||||
@@ -83,27 +83,27 @@ urlpatterns = [
|
||||
################################################################################
|
||||
|
||||
# saying page_number is an externally controlled *string* is a bit strange, when we have an int converter :O
|
||||
def page_number(request, page_number=1): # $requestHandler routedParameter=page_number
|
||||
return HttpResponse('page_number: {}'.format(page_number)) # $HttpResponse
|
||||
def page_number(request, page_number=1): # $ requestHandler routedParameter=page_number
|
||||
return HttpResponse('page_number: {}'.format(page_number)) # $ HttpResponse
|
||||
|
||||
def foo_bar_baz(request, foo, bar, baz): # $requestHandler routedParameter=foo routedParameter=bar routedParameter=baz
|
||||
return HttpResponse('foo_bar_baz: {} {} {}'.format(foo, bar, baz)) # $HttpResponse
|
||||
def foo_bar_baz(request, foo, bar, baz): # $ requestHandler routedParameter=foo routedParameter=bar routedParameter=baz
|
||||
return HttpResponse('foo_bar_baz: {} {} {}'.format(foo, bar, baz)) # $ HttpResponse
|
||||
|
||||
def path_kwargs(request, foo, bar): # $requestHandler routedParameter=foo routedParameter=bar
|
||||
return HttpResponse('path_kwargs: {} {} {}'.format(foo, bar)) # $HttpResponse
|
||||
def path_kwargs(request, foo, bar): # $ requestHandler routedParameter=foo routedParameter=bar
|
||||
return HttpResponse('path_kwargs: {} {} {}'.format(foo, bar)) # $ HttpResponse
|
||||
|
||||
def not_valid_identifier(request): # $requestHandler
|
||||
return HttpResponse('<foo!>') # $HttpResponse
|
||||
def not_valid_identifier(request): # $ requestHandler
|
||||
return HttpResponse('<foo!>') # $ HttpResponse
|
||||
|
||||
urlpatterns = [
|
||||
path("articles/", page_number), # $routeSetup="articles/"
|
||||
path("articles/page-<int:page_number>", page_number), # $routeSetup="articles/page-<int:page_number>"
|
||||
path("<int:foo>/<str:bar>/<baz>", foo_bar_baz, name='foo-bar-baz'), # $routeSetup="<int:foo>/<str:bar>/<baz>"
|
||||
path("articles/", page_number), # $ routeSetup="articles/"
|
||||
path("articles/page-<int:page_number>", page_number), # $ routeSetup="articles/page-<int:page_number>"
|
||||
path("<int:foo>/<str:bar>/<baz>", foo_bar_baz, name='foo-bar-baz'), # $ routeSetup="<int:foo>/<str:bar>/<baz>"
|
||||
|
||||
path(view=path_kwargs, route="<foo>/<bar>"), # $routeSetup="<foo>/<bar>"
|
||||
path(view=path_kwargs, route="<foo>/<bar>"), # $ routeSetup="<foo>/<bar>"
|
||||
|
||||
# We should not report there is a request parameter called `not_valid!`
|
||||
path("not_valid/<not_valid!>", not_valid_identifier), # $routeSetup="not_valid/<not_valid!>"
|
||||
path("not_valid/<not_valid!>", not_valid_identifier), # $ routeSetup="not_valid/<not_valid!>"
|
||||
]
|
||||
|
||||
################################################################################
|
||||
@@ -113,11 +113,11 @@ urlpatterns = [
|
||||
# This version 1.x way of defining urls is deprecated in Django 3.1, but still works
|
||||
from django.conf.urls import url
|
||||
|
||||
def deprecated(request): # $requestHandler
|
||||
return HttpResponse('deprecated') # $HttpResponse
|
||||
def deprecated(request): # $ requestHandler
|
||||
return HttpResponse('deprecated') # $ HttpResponse
|
||||
|
||||
urlpatterns = [
|
||||
url(r"^deprecated/", deprecated), # $routeSetup="^deprecated/"
|
||||
url(r"^deprecated/", deprecated), # $ routeSetup="^deprecated/"
|
||||
]
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ class PossiblyNotRouted(View):
|
||||
# consider it to be a handle incoming HTTP requests
|
||||
|
||||
def get(self, request, possibly_not_routed=42): # $ requestHandler routedParameter=possibly_not_routed
|
||||
return HttpResponse('PossiblyNotRouted get: {}'.format(possibly_not_routed)) # $HttpResponse
|
||||
return HttpResponse('PossiblyNotRouted get: {}'.format(possibly_not_routed)) # $ HttpResponse
|
||||
|
||||
|
||||
@require_GET
|
||||
|
||||
@@ -4,7 +4,7 @@ from django.http import HttpRequest
|
||||
from django.views import View
|
||||
|
||||
|
||||
def test_taint(request: HttpRequest, foo, bar, baz=None): # $requestHandler routedParameter=foo routedParameter=bar
|
||||
def test_taint(request: HttpRequest, foo, bar, baz=None): # $ requestHandler routedParameter=foo routedParameter=bar
|
||||
ensure_tainted(foo, bar) # $ tainted
|
||||
ensure_not_tainted(baz)
|
||||
|
||||
|
||||
@@ -3,19 +3,19 @@ from django.urls import path, re_path
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path("foo/", views.foo), # $routeSetup="foo/"
|
||||
path("foo/", views.foo), # $ routeSetup="foo/"
|
||||
# TODO: Doesn't include standard `$` to mark end of string, due to problems with
|
||||
# inline expectation tests (which thinks the `$` would mark the beginning of a new
|
||||
# line)
|
||||
re_path(r"^ba[rz]/", views.bar_baz), # $routeSetup="^ba[rz]/"
|
||||
re_path(r"^ba[rz]/", views.bar_baz), # $ routeSetup="^ba[rz]/"
|
||||
|
||||
path("basic-view-handler/", views.MyBasicViewHandler.as_view()), # $routeSetup="basic-view-handler/"
|
||||
path("custom-inheritance-view-handler/", views.MyViewHandlerWithCustomInheritance.as_view()), # $routeSetup="custom-inheritance-view-handler/"
|
||||
path("basic-view-handler/", views.MyBasicViewHandler.as_view()), # $ routeSetup="basic-view-handler/"
|
||||
path("custom-inheritance-view-handler/", views.MyViewHandlerWithCustomInheritance.as_view()), # $ routeSetup="custom-inheritance-view-handler/"
|
||||
|
||||
path("CustomRedirectView/<foo>", views.CustomRedirectView.as_view()), # $routeSetup="CustomRedirectView/<foo>"
|
||||
path("CustomRedirectView2/<foo>", views.CustomRedirectView2.as_view()), # $routeSetup="CustomRedirectView2/<foo>"
|
||||
path("CustomRedirectView/<foo>", views.CustomRedirectView.as_view()), # $ routeSetup="CustomRedirectView/<foo>"
|
||||
path("CustomRedirectView2/<foo>", views.CustomRedirectView2.as_view()), # $ routeSetup="CustomRedirectView2/<foo>"
|
||||
|
||||
path("file-test/", views.file_test), # $routeSetup="file-test/"
|
||||
path("file-test/", views.file_test), # $ routeSetup="file-test/"
|
||||
]
|
||||
|
||||
from django import __version__ as django_version
|
||||
@@ -30,7 +30,7 @@ if django_version[0] == "3":
|
||||
# we need this assignment to get our logic working... maybe it should be more
|
||||
# sophisticated?
|
||||
urlpatterns = [
|
||||
url(r"^deprecated/", views.deprecated), # $routeSetup="^deprecated/"
|
||||
url(r"^deprecated/", views.deprecated), # $ routeSetup="^deprecated/"
|
||||
]
|
||||
|
||||
urlpatterns += old_urlpatterns
|
||||
|
||||
@@ -4,16 +4,16 @@ from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from .models import MyModel
|
||||
|
||||
def foo(request: HttpRequest): # $requestHandler
|
||||
return HttpResponse("foo") # $HttpResponse
|
||||
def foo(request: HttpRequest): # $ requestHandler
|
||||
return HttpResponse("foo") # $ HttpResponse
|
||||
|
||||
|
||||
def bar_baz(request: HttpRequest): # $requestHandler
|
||||
return HttpResponse("bar_baz") # $HttpResponse
|
||||
def bar_baz(request: HttpRequest): # $ requestHandler
|
||||
return HttpResponse("bar_baz") # $ HttpResponse
|
||||
|
||||
|
||||
def deprecated(request: HttpRequest): # $requestHandler
|
||||
return HttpResponse("deprecated") # $HttpResponse
|
||||
def deprecated(request: HttpRequest): # $ requestHandler
|
||||
return HttpResponse("deprecated") # $ HttpResponse
|
||||
|
||||
|
||||
class MyBasicViewHandler(View):
|
||||
|
||||
@@ -13,7 +13,7 @@ https://docs.djangoproject.com/en/3.1/ref/settings/
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent #$ getAPathArgument=Path(..)
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent # $ getAPathArgument=Path(..)
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
@@ -48,7 +48,7 @@ MIDDLEWARE = [
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
] # $CsrfProtectionSetting=false
|
||||
] # $ CsrfProtectionSetting=false
|
||||
|
||||
ROOT_URLCONF = 'testproj.urls'
|
||||
|
||||
|
||||
@@ -17,6 +17,6 @@ from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
|
||||
urlpatterns = [
|
||||
path("admin/", admin.site.urls), # $routeSetup="admin/"
|
||||
path("app/", include("testapp.urls")), # $routeSetup="app/"
|
||||
path("admin/", admin.site.urls), # $ routeSetup="admin/"
|
||||
path("app/", include("testapp.urls")), # $ routeSetup="app/"
|
||||
]
|
||||
|
||||
@@ -4,13 +4,13 @@ from django.db.models.expressions import RawSQL
|
||||
|
||||
def test_plain():
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("some sql") # $getSql="some sql"
|
||||
cursor.execute("some sql") # $ getSql="some sql"
|
||||
|
||||
|
||||
def test_context():
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("some sql") # $getSql="some sql"
|
||||
cursor.execute(sql="some sql") # $getSql="some sql"
|
||||
cursor.execute("some sql") # $ getSql="some sql"
|
||||
cursor.execute(sql="some sql") # $ getSql="some sql"
|
||||
|
||||
|
||||
class User(models.Model):
|
||||
@@ -18,20 +18,20 @@ class User(models.Model):
|
||||
|
||||
|
||||
def test_model():
|
||||
User.objects.raw("some sql") # $getSql="some sql"
|
||||
User.objects.raw("some sql") # $ getSql="some sql"
|
||||
|
||||
User.objects.annotate(RawSQL("some sql")) # $getSql="some sql"
|
||||
User.objects.annotate(RawSQL("foo"), RawSQL("bar")) # $getSql="foo" getSql="bar"
|
||||
User.objects.annotate(val=RawSQL("some sql")) # $getSql="some sql"
|
||||
User.objects.annotate(RawSQL("some sql")) # $ getSql="some sql"
|
||||
User.objects.annotate(RawSQL("foo"), RawSQL("bar")) # $ getSql="foo" getSql="bar"
|
||||
User.objects.annotate(val=RawSQL("some sql")) # $ getSql="some sql"
|
||||
|
||||
User.objects.alias(RawSQL("foo"), RawSQL("bar")) # $getSql="foo" getSql="bar"
|
||||
User.objects.alias(val=RawSQL("some sql")) # $getSql="some sql"
|
||||
User.objects.alias(RawSQL("foo"), RawSQL("bar")) # $ getSql="foo" getSql="bar"
|
||||
User.objects.alias(val=RawSQL("some sql")) # $ getSql="some sql"
|
||||
|
||||
User.objects.extra("some sql") # $getSql="some sql"
|
||||
User.objects.extra(select="select", where="where", tables="tables", order_by="order_by") # $getSql="select" getSql="where" getSql="tables" getSql="order_by"
|
||||
User.objects.extra("some sql") # $ getSql="some sql"
|
||||
User.objects.extra(select="select", where="where", tables="tables", order_by="order_by") # $ getSql="select" getSql="where" getSql="tables" getSql="order_by"
|
||||
|
||||
raw = RawSQL("so raw")
|
||||
User.objects.annotate(val=raw) # $getSql="so raw"
|
||||
User.objects.annotate(val=raw) # $ getSql="so raw"
|
||||
|
||||
# chaining QuerySet calls
|
||||
User.objects.using("db-name").exclude(username="admin").extra("some sql") # $ getSql="some sql"
|
||||
|
||||
@@ -5,15 +5,15 @@ See http://docs.fabfile.org/en/1.14/tutorial.html
|
||||
|
||||
from fabric.api import run, local, sudo
|
||||
|
||||
local("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
sudo("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
local("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
sudo("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
local(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
run(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
sudo(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
local(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
run(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
sudo(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
from fabric import operations
|
||||
|
||||
operations.local("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
operations.local(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
operations.local("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
operations.local(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
@@ -9,41 +9,41 @@ from fabric import connection, Connection, group, SerialGroup, ThreadingGroup, t
|
||||
# Connection
|
||||
################################################################################
|
||||
c = Connection("web1")
|
||||
c.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.local("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.sudo("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
c.local("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
c.sudo("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
c.local(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.run(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.sudo(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.local(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
c.run(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
c.sudo(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
# fully qualified usage
|
||||
c2 = connection.Connection("web2")
|
||||
c2.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c2.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
# ssh proxy_command command injection with gateway parameter,
|
||||
# we need to call some of the following functions to run the proxy command
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c.run(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.run(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.get("afs")
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c.sudo(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.sudo(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.open_gateway()
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.open()
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.create_session()
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.forward_local("80")
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.forward_remote("80")
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.put(local="local")
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.shell()
|
||||
c = Connection("web1", gateway="cmd") # $getCommand="cmd"
|
||||
c = Connection("web1", gateway="cmd") # $ getCommand="cmd"
|
||||
c.sftp()
|
||||
# no call to desired methods so it is safe
|
||||
c = Connection("web1", gateway="cmd")
|
||||
@@ -51,26 +51,26 @@ c = Connection("web1", gateway="cmd")
|
||||
################################################################################
|
||||
# SerialGroup
|
||||
################################################################################
|
||||
results = SerialGroup("web1", "web2", "mac1").run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
results = SerialGroup("web1", "web2", "mac1").run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
pool = SerialGroup("web1", "web2", "web3")
|
||||
pool.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
pool.sudo("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
pool.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
pool.sudo("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
# fully qualified usage
|
||||
group.SerialGroup("web1", "web2", "mac1").run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
group.SerialGroup("web1", "web2", "mac1").run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
################################################################################
|
||||
# ThreadingGroup
|
||||
################################################################################
|
||||
results = ThreadingGroup("web1", "web2", "mac1").run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
results = ThreadingGroup("web1", "web2", "mac1").run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
pool = ThreadingGroup("web1", "web2", "web3")
|
||||
pool.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
pool.sudo("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
pool.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
pool.sudo("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
# fully qualified usage
|
||||
group.ThreadingGroup("web1", "web2", "mac1").run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
group.ThreadingGroup("web1", "web2", "mac1").run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -81,11 +81,11 @@ group.ThreadingGroup("web1", "web2", "mac1").run("cmd1; cmd2") # $getCommand="c
|
||||
@task
|
||||
def foo(c):
|
||||
# 'c' is a fabric.connection.Connection
|
||||
c.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
|
||||
# fully qualified usage
|
||||
@tasks.task
|
||||
def bar(c):
|
||||
# 'c' is a fabric.connection.Connection
|
||||
c.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
@@ -3,9 +3,9 @@ import flask
|
||||
from flask import Flask, request, make_response
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/") # $routeSetup="/"
|
||||
def hello_world(): # $requestHandler
|
||||
return "Hello World!" # $HttpResponse
|
||||
@app.route("/") # $ routeSetup="/"
|
||||
def hello_world(): # $ requestHandler
|
||||
return "Hello World!" # $ HttpResponse
|
||||
|
||||
from flask.views import MethodView
|
||||
|
||||
@@ -22,46 +22,46 @@ class MyView(MethodView):
|
||||
the_view = MyView.as_view('my_view')
|
||||
|
||||
app.add_url_rule('/the/', defaults={'user_id': None},
|
||||
view_func=the_view, methods=['GET',]) # $routeSetup="/the/"
|
||||
view_func=the_view, methods=['GET',]) # $ routeSetup="/the/"
|
||||
|
||||
@app.route("/dangerous") # $routeSetup="/dangerous"
|
||||
def dangerous(): # $requestHandler
|
||||
return request.args.get('payload') # $HttpResponse
|
||||
@app.route("/dangerous") # $ routeSetup="/dangerous"
|
||||
def dangerous(): # $ requestHandler
|
||||
return request.args.get('payload') # $ HttpResponse
|
||||
|
||||
@app.route("/dangerous-with-cfg-split") # $routeSetup="/dangerous-with-cfg-split"
|
||||
def dangerous2(): # $requestHandler
|
||||
@app.route("/dangerous-with-cfg-split") # $ routeSetup="/dangerous-with-cfg-split"
|
||||
def dangerous2(): # $ requestHandler
|
||||
x = request.form['param0']
|
||||
if request.method == "POST":
|
||||
return request.form['param1'] # $HttpResponse
|
||||
return request.form['param1'] # $ HttpResponse
|
||||
return None # $ SPURIOUS: HttpResponse
|
||||
|
||||
@app.route("/unsafe") # $routeSetup="/unsafe"
|
||||
def unsafe(): # $requestHandler
|
||||
@app.route("/unsafe") # $ routeSetup="/unsafe"
|
||||
def unsafe(): # $ requestHandler
|
||||
first_name = request.args.get('name', '')
|
||||
return make_response("Your name is " + first_name) # $HttpResponse
|
||||
return make_response("Your name is " + first_name) # $ HttpResponse
|
||||
|
||||
@app.route("/safe") # $routeSetup="/safe"
|
||||
def safe(): # $requestHandler
|
||||
@app.route("/safe") # $ routeSetup="/safe"
|
||||
def safe(): # $ requestHandler
|
||||
first_name = request.args.get('name', '')
|
||||
return make_response("Your name is " + escape(first_name)) # $HttpResponse
|
||||
return make_response("Your name is " + escape(first_name)) # $ HttpResponse
|
||||
|
||||
@app.route("/hello/<name>") # $routeSetup="/hello/<name>"
|
||||
def hello(name): # $requestHandler routedParameter=name
|
||||
return make_response("Your name is " + name) # $HttpResponse
|
||||
@app.route("/hello/<name>") # $ routeSetup="/hello/<name>"
|
||||
def hello(name): # $ requestHandler routedParameter=name
|
||||
return make_response("Your name is " + name) # $ HttpResponse
|
||||
|
||||
@app.route("/foo/<path:subpath>") # $routeSetup="/foo/<path:subpath>"
|
||||
def foo(subpath): # $requestHandler routedParameter=subpath
|
||||
return make_response("The subpath is " + subpath) # $HttpResponse
|
||||
@app.route("/foo/<path:subpath>") # $ routeSetup="/foo/<path:subpath>"
|
||||
def foo(subpath): # $ requestHandler routedParameter=subpath
|
||||
return make_response("The subpath is " + subpath) # $ HttpResponse
|
||||
|
||||
@app.route("/multiple/") # $routeSetup="/multiple/"
|
||||
@app.route("/multiple/foo/<foo>") # $routeSetup="/multiple/foo/<foo>"
|
||||
@app.route("/multiple/bar/<bar>") # $routeSetup="/multiple/bar/<bar>"
|
||||
def multiple(foo=None, bar=None): # $requestHandler routedParameter=foo routedParameter=bar
|
||||
return make_response("foo={!r} bar={!r}".format(foo, bar)) # $HttpResponse
|
||||
@app.route("/multiple/") # $ routeSetup="/multiple/"
|
||||
@app.route("/multiple/foo/<foo>") # $ routeSetup="/multiple/foo/<foo>"
|
||||
@app.route("/multiple/bar/<bar>") # $ routeSetup="/multiple/bar/<bar>"
|
||||
def multiple(foo=None, bar=None): # $ requestHandler routedParameter=foo routedParameter=bar
|
||||
return make_response("foo={!r} bar={!r}".format(foo, bar)) # $ HttpResponse
|
||||
|
||||
@app.route("/complex/<string(length=2):lang_code>") # $routeSetup="/complex/<string(length=2):lang_code>"
|
||||
def complex(lang_code): # $requestHandler routedParameter=lang_code
|
||||
return make_response("lang_code {}".format(lang_code)) # $HttpResponse
|
||||
@app.route("/complex/<string(length=2):lang_code>") # $ routeSetup="/complex/<string(length=2):lang_code>"
|
||||
def complex(lang_code): # $ requestHandler routedParameter=lang_code
|
||||
return make_response("lang_code {}".format(lang_code)) # $ HttpResponse
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
||||
|
||||
@@ -6,23 +6,23 @@ from werkzeug.datastructures import Headers
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/html1") # $routeSetup="/html1"
|
||||
def html1(): # $requestHandler
|
||||
return "<h1>hello</h1>" # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
@app.route("/html1") # $ routeSetup="/html1"
|
||||
def html1(): # $ requestHandler
|
||||
return "<h1>hello</h1>" # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
|
||||
|
||||
@app.route("/html2") # $routeSetup="/html2"
|
||||
def html2(): # $requestHandler
|
||||
@app.route("/html2") # $ routeSetup="/html2"
|
||||
def html2(): # $ requestHandler
|
||||
# note that response saved in a variable intentionally -- we wan the annotations to
|
||||
# show that we recognize the response creation, and not the return (hopefully). (and
|
||||
# do the same in the following of the file)
|
||||
resp = make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
resp = make_response("<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/html3") # $routeSetup="/html3"
|
||||
def html3(): # $requestHandler
|
||||
resp = app.make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
@app.route("/html3") # $ routeSetup="/html3"
|
||||
def html3(): # $ requestHandler
|
||||
resp = app.make_response("<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@@ -30,50 +30,50 @@ def html3(): # $requestHandler
|
||||
# https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.make_response
|
||||
|
||||
|
||||
@app.route("/html4") # $routeSetup="/html4"
|
||||
def html4(): # $requestHandler
|
||||
resp = Response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
@app.route("/html4") # $ routeSetup="/html4"
|
||||
def html4(): # $ requestHandler
|
||||
resp = Response("<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/html5") # $routeSetup="/html5"
|
||||
def html5(): # $requestHandler
|
||||
resp = Response(response="<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
@app.route("/html5") # $ routeSetup="/html5"
|
||||
def html5(): # $ requestHandler
|
||||
resp = Response(response="<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/html6") # $routeSetup="/html6"
|
||||
def html6(): # $requestHandler
|
||||
@app.route("/html6") # $ routeSetup="/html6"
|
||||
def html6(): # $ requestHandler
|
||||
# note: flask.Flask.response_class is set to `flask.Response` by default.
|
||||
# it can be overridden, but we don't try to handle that right now.
|
||||
resp = Flask.response_class("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
resp = Flask.response_class("<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/html7") # $routeSetup="/html7"
|
||||
def html7(): # $requestHandler
|
||||
@app.route("/html7") # $ routeSetup="/html7"
|
||||
def html7(): # $ requestHandler
|
||||
# note: app.response_class (flask.Flask.response_class) is set to `flask.Response` by default.
|
||||
# it can be overridden, but we don't try to handle that right now.
|
||||
resp = app.response_class("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
resp = app.response_class("<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/html8") # $routeSetup="/html8"
|
||||
def html8(): # $requestHandler
|
||||
resp = make_response() # $HttpResponse mimetype=text/html
|
||||
@app.route("/html8") # $ routeSetup="/html8"
|
||||
def html8(): # $ requestHandler
|
||||
resp = make_response() # $ HttpResponse mimetype=text/html
|
||||
resp.set_data("<h1>hello</h1>") # $ MISSING: responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/jsonify") # $routeSetup="/jsonify"
|
||||
def jsonify_route(): # $requestHandler
|
||||
@app.route("/jsonify") # $ routeSetup="/jsonify"
|
||||
def jsonify_route(): # $ requestHandler
|
||||
x = "x"; y = "y"; z = "z"
|
||||
if True:
|
||||
import flask.json
|
||||
resp = flask.json.jsonify(x, y, z=z) # $HttpResponse mimetype=application/json responseBody=x responseBody=y responseBody=z
|
||||
resp = flask.json.jsonify(x, y, z=z) # $ HttpResponse mimetype=application/json responseBody=x responseBody=y responseBody=z
|
||||
assert resp.mimetype == "application/json"
|
||||
|
||||
resp = app.json.response(x, y, z=z) # $HttpResponse mimetype=application/json responseBody=x responseBody=y responseBody=z
|
||||
resp = app.json.response(x, y, z=z) # $ HttpResponse mimetype=application/json responseBody=x responseBody=y responseBody=z
|
||||
assert resp.mimetype == "application/json"
|
||||
|
||||
resp = jsonify(x, y, z=z) # $ HttpResponse mimetype=application/json responseBody=x responseBody=y responseBody=z
|
||||
@@ -83,24 +83,24 @@ def jsonify_route(): # $requestHandler
|
||||
# Tricky return handling
|
||||
################################################################################
|
||||
|
||||
@app.route("/tricky-return1") # $routeSetup="/tricky-return1"
|
||||
def tricky_return1(): # $requestHandler
|
||||
@app.route("/tricky-return1") # $ routeSetup="/tricky-return1"
|
||||
def tricky_return1(): # $ requestHandler
|
||||
if "raw" in request.args:
|
||||
resp = "<h1>hellu</h1>"
|
||||
else:
|
||||
resp = make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
return resp # $HttpResponse mimetype=text/html responseBody=resp
|
||||
resp = make_response("<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
return resp # $ HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
def helper():
|
||||
if "raw" in request.args:
|
||||
return "<h1>hellu</h1>"
|
||||
else:
|
||||
return make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
return make_response("<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
|
||||
@app.route("/tricky-return2") # $routeSetup="/tricky-return2"
|
||||
def tricky_return2(): # $requestHandler
|
||||
@app.route("/tricky-return2") # $ routeSetup="/tricky-return2"
|
||||
def tricky_return2(): # $ requestHandler
|
||||
resp = helper()
|
||||
return resp # $HttpResponse mimetype=text/html responseBody=resp
|
||||
return resp # $ HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -108,16 +108,16 @@ def tricky_return2(): # $requestHandler
|
||||
################################################################################
|
||||
|
||||
|
||||
@app.route("/content-type/response-modification1") # $routeSetup="/content-type/response-modification1"
|
||||
def response_modification1(): # $requestHandler
|
||||
resp = make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
@app.route("/content-type/response-modification1") # $ routeSetup="/content-type/response-modification1"
|
||||
def response_modification1(): # $ requestHandler
|
||||
resp = make_response("<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
resp.content_type = "text/plain" # $ MISSING: HttpResponse mimetype=text/plain
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/content-type/response-modification2") # $routeSetup="/content-type/response-modification2"
|
||||
def response_modification2(): # $requestHandler
|
||||
resp = make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
@app.route("/content-type/response-modification2") # $ routeSetup="/content-type/response-modification2"
|
||||
def response_modification2(): # $ requestHandler
|
||||
resp = make_response("<h1>hello</h1>") # $ HttpResponse mimetype=text/html responseBody="<h1>hello</h1>"
|
||||
resp.headers["content-type"] = "text/plain" # $ headerWriteNameUnsanitized="content-type" headerWriteValue="text/plain" MISSING: HttpResponse mimetype=text/plain
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
@@ -126,61 +126,61 @@ def response_modification2(): # $requestHandler
|
||||
# see https://werkzeug.palletsprojects.com/en/1.0.x/wrappers/#werkzeug.wrappers.Response
|
||||
|
||||
|
||||
@app.route("/content-type/Response1") # $routeSetup="/content-type/Response1"
|
||||
def Response1(): # $requestHandler
|
||||
resp = Response("<h1>hello</h1>", mimetype="text/plain") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
@app.route("/content-type/Response1") # $ routeSetup="/content-type/Response1"
|
||||
def Response1(): # $ requestHandler
|
||||
resp = Response("<h1>hello</h1>", mimetype="text/plain") # $ HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/content-type/Response2") # $routeSetup="/content-type/Response2"
|
||||
def Response2(): # $requestHandler
|
||||
resp = Response("<h1>hello</h1>", content_type="text/plain; charset=utf-8") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
@app.route("/content-type/Response2") # $ routeSetup="/content-type/Response2"
|
||||
def Response2(): # $ requestHandler
|
||||
resp = Response("<h1>hello</h1>", content_type="text/plain; charset=utf-8") # $ HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/content-type/Response3") # $routeSetup="/content-type/Response3"
|
||||
def Response3(): # $requestHandler
|
||||
@app.route("/content-type/Response3") # $ routeSetup="/content-type/Response3"
|
||||
def Response3(): # $ requestHandler
|
||||
# content_type argument takes priority (and result is text/plain)
|
||||
resp = Response("<h1>hello</h1>", content_type="text/plain; charset=utf-8", mimetype="text/html") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
resp = Response("<h1>hello</h1>", content_type="text/plain; charset=utf-8", mimetype="text/html") # $ HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/content-type/Response4") # $routeSetup="/content-type/Response4"
|
||||
def Response4(): # $requestHandler
|
||||
@app.route("/content-type/Response4") # $ routeSetup="/content-type/Response4"
|
||||
def Response4(): # $ requestHandler
|
||||
# note: capitalization of Content-Type does not matter
|
||||
resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/plain"}) # $ headerWriteBulk=Dict headerWriteBulkUnsanitized=name headerWriteNameUnsanitized="Content-TYPE" headerWriteValue="text/plain" HttpResponse responseBody="<h1>hello</h1>" SPURIOUS: mimetype=text/html MISSING: mimetype=text/plain
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/content-type/Response5") # $routeSetup="/content-type/Response5"
|
||||
def Response5(): # $requestHandler
|
||||
@app.route("/content-type/Response5") # $ routeSetup="/content-type/Response5"
|
||||
def Response5(): # $ requestHandler
|
||||
# content_type argument takes priority (and result is text/plain)
|
||||
# note: capitalization of Content-Type does not matter
|
||||
resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/html"}, content_type="text/plain; charset=utf-8") # $ headerWriteBulk=Dict headerWriteBulkUnsanitized=name headerWriteNameUnsanitized="Content-TYPE" headerWriteValue="text/html" HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/content-type/Response6") # $routeSetup="/content-type/Response6"
|
||||
def Response6(): # $requestHandler
|
||||
@app.route("/content-type/Response6") # $ routeSetup="/content-type/Response6"
|
||||
def Response6(): # $ requestHandler
|
||||
# mimetype argument takes priority over header (and result is text/plain)
|
||||
# note: capitalization of Content-Type does not matter
|
||||
resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/html"}, mimetype="text/plain") # $ headerWriteBulk=Dict headerWriteBulkUnsanitized=name headerWriteNameUnsanitized="Content-TYPE" headerWriteValue="text/html" HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/content-type/Flask-response-class") # $routeSetup="/content-type/Flask-response-class"
|
||||
def Flask_response_class(): # $requestHandler
|
||||
@app.route("/content-type/Flask-response-class") # $ routeSetup="/content-type/Flask-response-class"
|
||||
def Flask_response_class(): # $ requestHandler
|
||||
# note: flask.Flask.response_class is set to `flask.Response` by default.
|
||||
# it can be overridden, but we don't try to handle that right now.
|
||||
resp = Flask.response_class("<h1>hello</h1>", mimetype="text/plain") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
resp = Flask.response_class("<h1>hello</h1>", mimetype="text/plain") # $ HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@app.route("/content-type/app-response-class") # $routeSetup="/content-type/app-response-class"
|
||||
def app_response_class(): # $requestHandler
|
||||
@app.route("/content-type/app-response-class") # $ routeSetup="/content-type/app-response-class"
|
||||
def app_response_class(): # $ requestHandler
|
||||
# note: app.response_class (flask.Flask.response_class) is set to `flask.Response` by default.
|
||||
# it can be overridden, but we don't try to handle that right now.
|
||||
resp = app.response_class("<h1>hello</h1>", mimetype="text/plain") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
resp = app.response_class("<h1>hello</h1>", mimetype="text/plain") # $ HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>"
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
|
||||
|
||||
@@ -192,8 +192,8 @@ def app_response_class(): # $requestHandler
|
||||
################################################################################
|
||||
|
||||
|
||||
@app.route("/redirect-simple") # $routeSetup="/redirect-simple"
|
||||
def redirect_simple(): # $requestHandler
|
||||
@app.route("/redirect-simple") # $ routeSetup="/redirect-simple"
|
||||
def redirect_simple(): # $ requestHandler
|
||||
next = request.args['next']
|
||||
resp = redirect(next) # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation=next
|
||||
return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp
|
||||
@@ -206,13 +206,13 @@ def redirect_simple(): # $requestHandler
|
||||
def unk():
|
||||
return
|
||||
|
||||
@app.route("/setting_cookie") # $routeSetup="/setting_cookie"
|
||||
def setting_cookie(): # $requestHandler
|
||||
@app.route("/setting_cookie") # $ routeSetup="/setting_cookie"
|
||||
def setting_cookie(): # $ requestHandler
|
||||
resp = make_response() # $ HttpResponse mimetype=text/html
|
||||
resp.set_cookie("key", "value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key", value="value") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.set_cookie(key="key", value="value", secure=True, httponly=True, samesite="Strict") # $ CookieWrite CookieName="key" CookieValue="value" CookieSecure=true CookieHttpOnly=true CookieSameSite=Strict
|
||||
resp.set_cookie(key="key", value="value", secure=unk(), httponly=unk(), samesite=unk()) # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.set_cookie(key="key", value="value", secure=unk(), httponly=unk(), samesite=unk()) # $ CookieWrite CookieName="key" CookieValue="value"
|
||||
resp.headers.add("Set-Cookie", "key2=value2") # $ headerWriteNameUnsanitized="Set-Cookie" headerWriteValue="key2=value2" CookieWrite CookieRawHeader="key2=value2" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
resp.delete_cookie("key3") # $ CookieWrite CookieName="key3"
|
||||
resp.delete_cookie(key="key3") # $ CookieWrite CookieName="key3"
|
||||
@@ -222,33 +222,33 @@ def setting_cookie(): # $requestHandler
|
||||
# Headers
|
||||
################################################################################
|
||||
|
||||
@app.route("/headers") # $routeSetup="/headers"
|
||||
def headers(): # $requestHandler
|
||||
@app.route("/headers") # $ routeSetup="/headers"
|
||||
def headers(): # $ requestHandler
|
||||
resp1 = Response() # $ HttpResponse mimetype=text/html
|
||||
resp1.headers["X-MyHeader"] = "a" # $ headerWriteNameUnsanitized="X-MyHeader" headerWriteValue="a"
|
||||
resp2 = make_response() # $ HttpResponse mimetype=text/html
|
||||
resp2.headers["X-MyHeader"] = "aa" # $ headerWriteNameUnsanitized="X-MyHeader" headerWriteValue="aa"
|
||||
resp2.headers.extend({"X-MyHeader2": "b"}) # $ headerWriteBulk=Dict headerWriteBulkUnsanitized=name headerWriteNameUnsanitized="X-MyHeader2" headerWriteValue="b"
|
||||
resp2.headers.extend({"X-MyHeader2": "b"}) # $ headerWriteBulk=Dict headerWriteBulkUnsanitized=name headerWriteNameUnsanitized="X-MyHeader2" headerWriteValue="b"
|
||||
resp3 = make_response("hello", 200, {"X-MyHeader3": "c"}) # $ HttpResponse mimetype=text/html responseBody="hello" headerWriteBulk=Dict headerWriteBulkUnsanitized=name headerWriteNameUnsanitized="X-MyHeader3" headerWriteValue="c"
|
||||
resp4 = make_response("hello", {"X-MyHeader4": "d"}) # $ HttpResponse mimetype=text/html responseBody="hello" headerWriteBulk=Dict headerWriteBulkUnsanitized=name headerWriteNameUnsanitized="X-MyHeader4" headerWriteValue="d"
|
||||
resp5 = Response(headers={"X-MyHeader5":"e"}) # $ HttpResponse mimetype=text/html headerWriteBulk=Dict headerWriteBulkUnsanitized=name headerWriteBulkUnsanitized=name headerWriteNameUnsanitized="X-MyHeader5" headerWriteValue="e"
|
||||
return resp5 # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp5
|
||||
|
||||
@app.route("/werkzeug-headers") # $routeSetup="/werkzeug-headers"
|
||||
def werkzeug_headers(): # $requestHandler
|
||||
@app.route("/werkzeug-headers") # $ routeSetup="/werkzeug-headers"
|
||||
def werkzeug_headers(): # $ requestHandler
|
||||
response = Response() # $ HttpResponse mimetype=text/html
|
||||
headers = Headers()
|
||||
headers.add("X-MyHeader1", "a") # $ headerWriteNameUnsanitized="X-MyHeader1" headerWriteValue="a"
|
||||
headers.add_header("X-MyHeader2", "b") # $ headerWriteNameUnsanitized="X-MyHeader2" headerWriteValue="b"
|
||||
headers.set("X-MyHeader3", "c") # $ headerWriteNameUnsanitized="X-MyHeader3" headerWriteValue="c"
|
||||
headers.setdefault("X-MyHeader4", "d") # $ headerWriteNameUnsanitized="X-MyHeader4" headerWriteValue="d"
|
||||
headers.__setitem__("X-MyHeader5", "e") # $ headerWriteNameUnsanitized="X-MyHeader5" headerWriteValue="e"
|
||||
headers["X-MyHeader6"] = "f" # $ headerWriteNameUnsanitized="X-MyHeader6" headerWriteValue="f"
|
||||
headers.set("X-MyHeader3", "c") # $ headerWriteNameUnsanitized="X-MyHeader3" headerWriteValue="c"
|
||||
headers.setdefault("X-MyHeader4", "d") # $ headerWriteNameUnsanitized="X-MyHeader4" headerWriteValue="d"
|
||||
headers.__setitem__("X-MyHeader5", "e") # $ headerWriteNameUnsanitized="X-MyHeader5" headerWriteValue="e"
|
||||
headers["X-MyHeader6"] = "f" # $ headerWriteNameUnsanitized="X-MyHeader6" headerWriteValue="f"
|
||||
h1 = {"X-MyHeader7": "g"} # $ headerWriteNameUnsanitized="X-MyHeader7" headerWriteValue="g"
|
||||
headers.extend(h1) # $ headerWriteBulk=h1 headerWriteBulkUnsanitized=name
|
||||
headers.extend(h1) # $ headerWriteBulk=h1 headerWriteBulkUnsanitized=name
|
||||
h2 = [("X-MyHeader8", "h")] # $ headerWriteNameUnsanitized="X-MyHeader8" headerWriteValue="h"
|
||||
headers.extend(h2) # $ headerWriteBulk=h2 headerWriteBulkUnsanitized=name
|
||||
response.headers = headers
|
||||
headers.extend(h2) # $ headerWriteBulk=h2 headerWriteBulkUnsanitized=name
|
||||
response.headers = headers
|
||||
return response # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=response
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -5,28 +5,28 @@ app = Flask(__name__)
|
||||
|
||||
|
||||
SOME_ROUTE = "/some/route"
|
||||
@app.route(SOME_ROUTE) # $routeSetup="/some/route"
|
||||
def some_route(): # $requestHandler
|
||||
return make_response("some_route") # $HttpResponse
|
||||
@app.route(SOME_ROUTE) # $ routeSetup="/some/route"
|
||||
def some_route(): # $ requestHandler
|
||||
return make_response("some_route") # $ HttpResponse
|
||||
|
||||
|
||||
def index(): # $requestHandler
|
||||
return make_response("index") # $HttpResponse
|
||||
app.add_url_rule('/index', 'index', index) # $routeSetup="/index"
|
||||
def index(): # $ requestHandler
|
||||
return make_response("index") # $ HttpResponse
|
||||
app.add_url_rule('/index', 'index', index) # $ routeSetup="/index"
|
||||
|
||||
|
||||
# We don't support this yet, and I think that's OK
|
||||
def later_set(): # $ MISSING: requestHandler
|
||||
return make_response("later_set") # $HttpResponse
|
||||
app.add_url_rule('/later-set', 'later_set', view_func=None) # $routeSetup="/later-set"
|
||||
return make_response("later_set") # $ HttpResponse
|
||||
app.add_url_rule('/later-set', 'later_set', view_func=None) # $ routeSetup="/later-set"
|
||||
app.view_functions['later_set'] = later_set
|
||||
|
||||
# We don't want to execute this at runtime (since program will crash). Just using
|
||||
# `False` makes our analysis skip it, so here's a workaround :D
|
||||
if __file__ == "False":
|
||||
@app.route(UNKNOWN_ROUTE) # $routeSetup
|
||||
def unkown_route(foo, bar): # $requestHandler routedParameter=foo routedParameter=bar
|
||||
return make_response("unkown_route") # $HttpResponse
|
||||
@app.route(UNKNOWN_ROUTE) # $ routeSetup
|
||||
def unkown_route(foo, bar): # $ requestHandler routedParameter=foo routedParameter=bar
|
||||
return make_response("unkown_route") # $ HttpResponse
|
||||
|
||||
# View
|
||||
#
|
||||
@@ -40,7 +40,7 @@ class ShowUser(View):
|
||||
def dispatch_request(self, user_id): # $ requestHandler routedParameter=user_id
|
||||
return "user_id: {}".format(user_id) # $ HttpResponse
|
||||
|
||||
app.add_url_rule("/basic/user/<int:user_id>", view_func=ShowUser.as_view('show_user')) # $routeSetup="/basic/user/<int:user_id>"
|
||||
app.add_url_rule("/basic/user/<int:user_id>", view_func=ShowUser.as_view('show_user')) # $ routeSetup="/basic/user/<int:user_id>"
|
||||
|
||||
|
||||
class WithoutKnownRoute1(View):
|
||||
@@ -81,9 +81,9 @@ class UserAPI(MethodView):
|
||||
|
||||
|
||||
user_view = UserAPI.as_view("user_api")
|
||||
app.add_url_rule("/users/", defaults={"user_id": None}, view_func=user_view, methods=["GET",]) # $routeSetup="/users/"
|
||||
app.add_url_rule("/users/", view_func=user_view, methods=["POST",]) # $routeSetup="/users/"
|
||||
app.add_url_rule("/users/<int:user_id>", view_func=user_view, methods=["GET", "PUT", "DELETE"]) # $routeSetup="/users/<int:user_id>"
|
||||
app.add_url_rule("/users/", defaults={"user_id": None}, view_func=user_view, methods=["GET",]) # $ routeSetup="/users/"
|
||||
app.add_url_rule("/users/", view_func=user_view, methods=["POST",]) # $ routeSetup="/users/"
|
||||
app.add_url_rule("/users/<int:user_id>", view_func=user_view, methods=["GET", "PUT", "DELETE"]) # $ routeSetup="/users/<int:user_id>"
|
||||
|
||||
|
||||
class WithoutKnownRoute2(MethodView):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from flask import Flask, request
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/save-uploaded-file") # $routeSetup="/save-uploaded-file"
|
||||
def test_taint(): # $requestHandler
|
||||
@app.route("/save-uploaded-file") # $ routeSetup="/save-uploaded-file"
|
||||
def test_taint(): # $ requestHandler
|
||||
request.files['key'].save("path") # $ getAPathArgument="path"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import flask
|
||||
import flask
|
||||
|
||||
class MySessionInterface(flask.sessions.SessionInterface):
|
||||
def open_session(self, app, request):
|
||||
ensure_tainted(request) # $tainted
|
||||
ensure_tainted(request) # $ tainted
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from flask import Flask, request, render_template_string, stream_template_string
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/test_taint/<name>/<int:number>") # $routeSetup="/test_taint/<name>/<int:number>"
|
||||
def test_taint(name = "World!", number="0", foo="foo"): # $requestHandler routedParameter=name routedParameter=number
|
||||
@app.route("/test_taint/<name>/<int:number>") # $ routeSetup="/test_taint/<name>/<int:number>"
|
||||
def test_taint(name = "World!", number="0", foo="foo"): # $ requestHandler routedParameter=name routedParameter=number
|
||||
ensure_tainted(name, number) # $ tainted
|
||||
ensure_not_tainted(foo)
|
||||
|
||||
@@ -245,8 +245,8 @@ def test_taint(name = "World!", number="0", foo="foo"): # $requestHandler route
|
||||
ensure_not_tainted(x)
|
||||
|
||||
|
||||
@app.route("/debug/<foo>/<bar>", methods=['GET']) # $routeSetup="/debug/<foo>/<bar>"
|
||||
def debug(foo, bar): # $requestHandler routedParameter=foo routedParameter=bar
|
||||
@app.route("/debug/<foo>/<bar>", methods=['GET']) # $ routeSetup="/debug/<foo>/<bar>"
|
||||
def debug(foo, bar): # $ requestHandler routedParameter=foo routedParameter=bar
|
||||
print("request.view_args", request.view_args)
|
||||
|
||||
print("request.headers {!r}".format(request.headers))
|
||||
@@ -254,20 +254,20 @@ def debug(foo, bar): # $requestHandler routedParameter=foo routedParameter=bar
|
||||
|
||||
print("request.pragma {!r}".format(request.pragma))
|
||||
|
||||
return 'ok' # $HttpResponse
|
||||
return 'ok' # $ HttpResponse
|
||||
|
||||
@app.route("/stream", methods=['POST']) # $routeSetup="/stream"
|
||||
def stream(): # $requestHandler
|
||||
@app.route("/stream", methods=['POST']) # $ routeSetup="/stream"
|
||||
def stream(): # $ requestHandler
|
||||
print(request.path)
|
||||
s = request.stream
|
||||
print(s)
|
||||
# just works :)
|
||||
print(s.read())
|
||||
|
||||
return 'ok' # $HttpResponse
|
||||
return 'ok' # $ HttpResponse
|
||||
|
||||
@app.route("/input_stream", methods=['POST']) # $routeSetup="/input_stream"
|
||||
def input_stream(): # $requestHandler
|
||||
@app.route("/input_stream", methods=['POST']) # $ routeSetup="/input_stream"
|
||||
def input_stream(): # $ requestHandler
|
||||
print(request.path)
|
||||
s = request.input_stream
|
||||
print(s)
|
||||
@@ -275,38 +275,38 @@ def input_stream(): # $requestHandler
|
||||
# be handled manually
|
||||
print(s.read())
|
||||
|
||||
return 'ok' # $HttpResponse
|
||||
return 'ok' # $ HttpResponse
|
||||
|
||||
@app.route("/form", methods=['POST']) # $routeSetup="/form"
|
||||
def form(): # $requestHandler
|
||||
@app.route("/form", methods=['POST']) # $ routeSetup="/form"
|
||||
def form(): # $ requestHandler
|
||||
print(request.path)
|
||||
print("request.form", request.form)
|
||||
|
||||
return 'ok' # $HttpResponse
|
||||
return 'ok' # $ HttpResponse
|
||||
|
||||
@app.route("/cache_control", methods=['POST']) # $routeSetup="/cache_control"
|
||||
def cache_control(): # $requestHandler
|
||||
@app.route("/cache_control", methods=['POST']) # $ routeSetup="/cache_control"
|
||||
def cache_control(): # $ requestHandler
|
||||
print(request.path)
|
||||
print("request.cache_control.max_age", request.cache_control.max_age, type(request.cache_control.max_age))
|
||||
print("request.cache_control.max_stale", request.cache_control.max_stale, type(request.cache_control.max_stale))
|
||||
print("request.cache_control.min_fresh", request.cache_control.min_fresh, type(request.cache_control.min_fresh))
|
||||
|
||||
return 'ok' # $HttpResponse
|
||||
return 'ok' # $ HttpResponse
|
||||
|
||||
@app.route("/file_upload", methods=['POST']) # $routeSetup="/file_upload"
|
||||
def file_upload(): # $requestHandler
|
||||
@app.route("/file_upload", methods=['POST']) # $ routeSetup="/file_upload"
|
||||
def file_upload(): # $ requestHandler
|
||||
print(request.path)
|
||||
for k,v in request.files.items():
|
||||
print(k, v, v.name, v.filename, v.stream)
|
||||
|
||||
return 'ok' # $HttpResponse
|
||||
return 'ok' # $ HttpResponse
|
||||
|
||||
@app.route("/args", methods=['GET']) # $routeSetup="/args"
|
||||
def args(): # $requestHandler
|
||||
@app.route("/args", methods=['GET']) # $ routeSetup="/args"
|
||||
def args(): # $ requestHandler
|
||||
print(request.path)
|
||||
print("request.args", request.args)
|
||||
|
||||
return 'ok' # $HttpResponse
|
||||
return 'ok' # $ HttpResponse
|
||||
|
||||
# curl --header "My-Header: some-value" http://localhost:5000/debug/fooval/barval
|
||||
# curl --header "Pragma: foo, bar" --header "Pragma: stuff, foo" http://localhost:5000/debug/fooval/barval
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
from flask import Flask, Response, stream_with_context, render_template_string, stream_template_string
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/a") # $routeSetup="/a"
|
||||
@app.route("/a") # $ routeSetup="/a"
|
||||
def a(): # $ requestHandler
|
||||
r = render_template_string("abc") # $ templateConstruction="abc"
|
||||
return r # $ HttpResponse
|
||||
|
||||
@app.route("/b") # $routeSetup="/b"
|
||||
@app.route("/b") # $ routeSetup="/b"
|
||||
def b(): # $ requestHandler
|
||||
s = stream_template_string("abc") # $ templateConstruction="abc"
|
||||
r = Response(stream_with_context(s)) # $ HttpResponse
|
||||
return r # $ HttpResponse
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
||||
app.run(debug=True)
|
||||
|
||||
@@ -5,35 +5,35 @@ see https://www.pyinvoke.org/
|
||||
|
||||
import invoke
|
||||
|
||||
invoke.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
invoke.run(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
invoke.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
invoke.run(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
|
||||
def with_sudo():
|
||||
invoke.sudo("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
invoke.sudo(command="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
invoke.sudo("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
invoke.sudo(command="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
|
||||
def manual_context():
|
||||
c = invoke.Context()
|
||||
c.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.sudo("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
c.sudo("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
# invoke.Context is just an alias for invoke.context.Context
|
||||
c2 = invoke.context.Context()
|
||||
c2.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c2.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
|
||||
manual_context()
|
||||
|
||||
|
||||
def foo_helper(c):
|
||||
c.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
|
||||
# for use with the 'invoke' command-line tool
|
||||
@invoke.task
|
||||
def foo(c):
|
||||
# 'c' is a invoke.context.Context
|
||||
c.run("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
c.run("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
foo_helper(c)
|
||||
|
||||
@@ -18,7 +18,7 @@ add_salary = ("INSERT INTO salaries "
|
||||
data_employee = ('Geert', 'Vanderkelen', tomorrow, 'M', date(1977, 6, 14))
|
||||
|
||||
# Insert new employee
|
||||
cursor.execute(add_employee, data_employee) # $getSql=add_employee
|
||||
cursor.execute(add_employee, data_employee) # $ getSql=add_employee
|
||||
emp_no = cursor.lastrowid
|
||||
|
||||
# Insert salary information
|
||||
@@ -28,10 +28,10 @@ data_salary = {
|
||||
'from_date': tomorrow,
|
||||
'to_date': date(9999, 1, 1),
|
||||
}
|
||||
cursor.execute(add_salary, data_salary) # $getSql=add_salary
|
||||
cursor.execute(add_salary, data_salary) # $ getSql=add_salary
|
||||
|
||||
# Make sure data is committed to the database
|
||||
cnx.commit()
|
||||
|
||||
cursor.close()
|
||||
cnx.close()
|
||||
cnx.close()
|
||||
|
||||
@@ -4,4 +4,4 @@ db=MySQLdb.connect(passwd="moonpie",db="thangs")
|
||||
|
||||
c=db.cursor()
|
||||
max_price=5
|
||||
c.execute("some sql", (max_price,)) # $getSql="some sql"
|
||||
c.execute("some sql", (max_price,)) # $ getSql="some sql"
|
||||
|
||||
@@ -2,79 +2,79 @@ import pandas as pd
|
||||
import sqlite3
|
||||
|
||||
df = pd.DataFrame({'temp_c': [17.0, 25.0]}, index=['Portland', 'Berkeley'])
|
||||
df.sample().query("query") # $getCode="query"
|
||||
df.mod().query("query") # $getCode="query"
|
||||
pd.eval("pythonExpr", target=df) # $getCode="pythonExpr"
|
||||
df.sample().query("query") # $ getCode="query"
|
||||
df.mod().query("query") # $ getCode="query"
|
||||
pd.eval("pythonExpr", target=df) # $ getCode="pythonExpr"
|
||||
|
||||
df = pd.read_csv("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.copy().query("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
df.copy().query("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_fwf("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
|
||||
df = pd.read_pickle("filepath") # $ decodeInput="filepath" decodeOutput=pd.read_pickle(..) decodeFormat=pickle decodeMayExecuteInput
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_table("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_clipboard("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_excel("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_html("filepath")
|
||||
df[0].query("query") # $getCode="query"
|
||||
df[0].query("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_xml("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_parquet("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_orc("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_spss("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_sql_table("filepath", 'postgres:///db_name')
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
connection = sqlite3.connect("pets.db")
|
||||
df = pd.read_sql_query("sql query", connection) # $getSql="sql query"
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df = pd.read_sql_query("sql query", connection) # $ getSql="sql query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_sql("sql query", connection) # $getSql="sql query"
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df = pd.read_sql("sql query", connection) # $ getSql="sql query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_gbq("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_stata("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
df = pd.read_sas("filepath")
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
df = pd.read_sas("filepath", iterator=True, chunksize=1)
|
||||
df.query("query")
|
||||
df = pd.read_sas("filepath", iterator=False, chunksize=1)
|
||||
@@ -82,5 +82,5 @@ df.query("query")
|
||||
df = pd.read_sas("filepath", iterator=True, chunksize=None)
|
||||
df.query("query")
|
||||
df = pd.read_sas("filepath", iterator=False, chunksize=None)
|
||||
df.query("query") # $getCode="query"
|
||||
df.eval("query") # $getCode="query"
|
||||
df.query("query") # $ getCode="query"
|
||||
df.eval("query") # $ getCode="query"
|
||||
|
||||
@@ -8,4 +8,4 @@ paramiko_ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
paramiko_ssh_client.connect(hostname="127.0.0.1", port="22", username="ssh_user_name", pkey="k", timeout=11, banner_timeout=200)
|
||||
|
||||
cmd = "cmd"
|
||||
paramiko_ssh_client.connect('hostname', username='user', password='yourpassword', sock=paramiko.ProxyCommand(cmd)) # $getCommand=cmd
|
||||
paramiko_ssh_client.connect('hostname', username='user', password='yourpassword', sock=paramiko.ProxyCommand(cmd)) # $ getCommand=cmd
|
||||
|
||||
@@ -8,7 +8,7 @@ def ignore(*args, **kwargs): pass
|
||||
ensure_tainted = ensure_not_tainted = ignore
|
||||
|
||||
@view_config(route_name="test1") # $ routeSetup
|
||||
def test1(request): # $ requestHandler
|
||||
def test1(request): # $ requestHandler
|
||||
ensure_tainted(
|
||||
request, # $ tainted
|
||||
|
||||
@@ -26,7 +26,7 @@ def test1(request): # $ requestHandler
|
||||
request.host_url, # $ tainted
|
||||
request.if_match, # $ tainted
|
||||
request.if_none_match, # $ tainted
|
||||
request.if_range, # $ tainted
|
||||
request.if_range, # $ tainted
|
||||
request.pragma, # $ tainted
|
||||
request.range, # $ tainted
|
||||
request.referer, # $ tainted
|
||||
@@ -71,11 +71,11 @@ def test1(request): # $ requestHandler
|
||||
request.copy_get(), # $ tainted
|
||||
request.copy().GET['a'], # $ tainted
|
||||
request.copy_get().body # $ tainted
|
||||
)
|
||||
)
|
||||
|
||||
return Response("Ok") # $ HttpResponse responseBody="Ok" mimetype=text/html
|
||||
|
||||
def test2(request): # $ requestHandler
|
||||
def test2(request): # $ requestHandler
|
||||
ensure_tainted(request) # $ tainted
|
||||
|
||||
resp = Response("Ok", content_type="text/plain") # $ HttpResponse responseBody="Ok" mimetype=text/plain
|
||||
@@ -83,7 +83,7 @@ def test2(request): # $ requestHandler
|
||||
return resp
|
||||
|
||||
@view_config(route_name="test3", renderer="string") # $ routeSetup
|
||||
def test3(ctx, req): # $ requestHandler
|
||||
def test3(ctx, req): # $ requestHandler
|
||||
ensure_tainted(req) # $ tainted
|
||||
resp = req.response # $ HttpResponse mimetype=text/html
|
||||
resp.set_cookie("hi", "there") # $ CookieWrite CookieName="hi" CookieValue="there" CookieSecure=false CookieHttpOnly=false CookieSameSite=Lax
|
||||
@@ -93,13 +93,13 @@ def test3(ctx, req): # $ requestHandler
|
||||
|
||||
@view_config(route_name="test4", renderer="string") # $ routeSetup
|
||||
def test4(request): # $ requestHandler
|
||||
a = HTTPMultipleChoices("redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
b = HTTPMovedPermanently(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
c = HTTPFound(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
d = HTTPSeeOther(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
e = HTTPUseProxy(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
f = HTTPTemporaryRedirect(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
g = HTTPPermanentRedirect(location="redirect") # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
a = HTTPMultipleChoices("redirect") # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
b = HTTPMovedPermanently(location="redirect") # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
c = HTTPFound(location="redirect") # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
d = HTTPSeeOther(location="redirect") # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
e = HTTPUseProxy(location="redirect") # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
f = HTTPTemporaryRedirect(location="redirect") # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
g = HTTPPermanentRedirect(location="redirect") # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation="redirect"
|
||||
raise a
|
||||
|
||||
# Unsupported cases
|
||||
@@ -121,7 +121,7 @@ class Test6:
|
||||
self.req = request
|
||||
|
||||
def test6method(self): # $ MISSING: requestHandler
|
||||
ensure_not_tainted(self)
|
||||
ensure_not_tainted(self)
|
||||
ensure_tainted(self.req) # $ MISSING: tainted
|
||||
return "Ok" # $ MISSING: HttpResponse mimetype=text/html responseBody="Ok"
|
||||
|
||||
@@ -132,7 +132,7 @@ class Test6:
|
||||
self.req = request
|
||||
|
||||
def __call__(self): # $ MISSING: requestHandler
|
||||
ensure_not_tainted(self)
|
||||
ensure_not_tainted(self)
|
||||
ensure_tainted(self.req) # $ MISSING: tainted
|
||||
return "Ok" # $ MISSING: HttpResponse mimetype=text/html responseBody="Ok"
|
||||
|
||||
|
||||
@@ -18,5 +18,5 @@ from django.urls import path, include
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls), # $ routeSetup="admin/"
|
||||
path("", include("testapp.urls")), # $routeSetup=""
|
||||
path("", include("testapp.urls")), # $ routeSetup=""
|
||||
]
|
||||
|
||||
@@ -6,27 +6,27 @@ ruamel.yaml.load(stream=payload) # $ decodeInput=payload decodeOutput=ruamel.ya
|
||||
ruamel.yaml.load(payload, ruamel.yaml.Loader) # $ decodeInput=payload decodeOutput=ruamel.yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
|
||||
# Safe:
|
||||
ruamel.yaml.load(payload, ruamel.yaml.SafeLoader) # $ decodeInput=payload decodeOutput=ruamel.yaml.load(..) decodeFormat=YAML
|
||||
ruamel.yaml.load(payload, ruamel.yaml.SafeLoader) # $ decodeInput=payload decodeOutput=ruamel.yaml.load(..) decodeFormat=YAML
|
||||
ruamel.yaml.load(payload, Loader=ruamel.yaml.SafeLoader) # $ decodeInput=payload decodeOutput=ruamel.yaml.load(..) decodeFormat=YAML
|
||||
ruamel.yaml.load(payload, ruamel.yaml.BaseLoader) # $ decodeInput=payload decodeOutput=ruamel.yaml.load(..) decodeFormat=YAML
|
||||
ruamel.yaml.safe_load(payload) # $ decodeInput=payload decodeOutput=ruamel.yaml.safe_load(..) decodeFormat=YAML
|
||||
ruamel.yaml.safe_load(payload) # $ decodeInput=payload decodeOutput=ruamel.yaml.safe_load(..) decodeFormat=YAML
|
||||
|
||||
################################################################################
|
||||
# load_all variants
|
||||
################################################################################
|
||||
|
||||
# Unsafe:
|
||||
ruamel.yaml.load_all(payload) # $ decodeInput=payload decodeOutput=ruamel.yaml.load_all(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
ruamel.yaml.load_all(payload) # $ decodeInput=payload decodeOutput=ruamel.yaml.load_all(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
|
||||
# Safe:
|
||||
ruamel.yaml.safe_load_all(payload) # $ decodeInput=payload decodeOutput=ruamel.yaml.safe_load_all(..) decodeFormat=YAML
|
||||
ruamel.yaml.safe_load_all(payload) # $ decodeInput=payload decodeOutput=ruamel.yaml.safe_load_all(..) decodeFormat=YAML
|
||||
|
||||
################################################################################
|
||||
# C-based loaders with `libyaml`
|
||||
################################################################################
|
||||
|
||||
# Unsafe:
|
||||
ruamel.yaml.load(payload, ruamel.yaml.CLoader) # $ decodeInput=payload decodeOutput=ruamel.yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
ruamel.yaml.load(payload, ruamel.yaml.CLoader) # $ decodeInput=payload decodeOutput=ruamel.yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
|
||||
# Safe:
|
||||
ruamel.yaml.load(payload, ruamel.yaml.CSafeLoader) # $ decodeInput=payload decodeOutput=ruamel.yaml.load(..) decodeFormat=YAML
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# exec statement is Python 2 specific
|
||||
exec "print(42)" # $getCode="print(42)"
|
||||
exec "print(42)" # $ getCode="print(42)"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
########################################
|
||||
import os
|
||||
|
||||
os.popen2("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
os.popen3("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
os.popen4("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
os.popen2("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
os.popen3("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
os.popen4("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
|
||||
os.popen2(cmd="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
os.popen3(cmd="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
os.popen4(cmd="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
os.popen2(cmd="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
os.popen3(cmd="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
os.popen4(cmd="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
# os.popen does not support keyword arguments, so this is a TypeError
|
||||
os.popen(cmd="cmd1; cmd2")
|
||||
@@ -16,21 +16,21 @@ os.popen(cmd="cmd1; cmd2")
|
||||
########################################
|
||||
import platform
|
||||
|
||||
platform.popen("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
platform.popen(cmd="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
platform.popen("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
platform.popen(cmd="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
########################################
|
||||
# popen2 was deprecated in Python 2.6, but still available in Python 2.7
|
||||
import popen2
|
||||
|
||||
popen2.popen2("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.popen3("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.popen4("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.Popen3("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.Popen4("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.popen2("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
popen2.popen3("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
popen2.popen4("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
popen2.Popen3("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
popen2.Popen4("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
popen2.popen2(cmd="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.popen3(cmd="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.popen4(cmd="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.Popen3(cmd="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.Popen4(cmd="cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen2.popen2(cmd="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
popen2.popen3(cmd="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
popen2.popen4(cmd="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
popen2.Popen3(cmd="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
popen2.Popen4(cmd="cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import builtins
|
||||
|
||||
# exec being part of builtins is Python 3 only
|
||||
builtins.exec("print(42)") # $getCode="print(42)"
|
||||
builtins.exec("print(42)") # $ getCode="print(42)"
|
||||
|
||||
@@ -9,16 +9,16 @@ if sys.version_info[0] == 3:
|
||||
if sys.version_info[0] == 2:
|
||||
import __builtin__ as builtins
|
||||
|
||||
exec("print(42)") # $getCode="print(42)"
|
||||
eval("print(42)") # $getCode="print(42)"
|
||||
exec("print(42)") # $ getCode="print(42)"
|
||||
eval("print(42)") # $ getCode="print(42)"
|
||||
|
||||
builtins.eval("print(42)") # $getCode="print(42)"
|
||||
builtins.eval("print(42)") # $ getCode="print(42)"
|
||||
|
||||
cmd = compile("print(42)", "<filename>", "exec")
|
||||
exec(cmd) # $getCode=cmd
|
||||
exec(cmd) # $ getCode=cmd
|
||||
|
||||
cmd = builtins.compile("print(42)", "<filename>", "exec")
|
||||
exec(cmd) # $getCode=cmd
|
||||
exec(cmd) # $ getCode=cmd
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# taint related
|
||||
|
||||
@@ -2,17 +2,17 @@ import os.path
|
||||
|
||||
path = "un\\normalized/path"
|
||||
|
||||
p1 = os.path.normpath(path) # $pathNormalization
|
||||
p2 = os.path.normpath(path=path) # $pathNormalization
|
||||
p1 = os.path.normpath(path) # $ pathNormalization
|
||||
p2 = os.path.normpath(path=path) # $ pathNormalization
|
||||
|
||||
np = os.path.normpath
|
||||
|
||||
p3 = np(path) # $pathNormalization
|
||||
p4 = np(path=path) # $pathNormalization
|
||||
p3 = np(path) # $ pathNormalization
|
||||
p4 = np(path=path) # $ pathNormalization
|
||||
|
||||
|
||||
def normalize(path):
|
||||
return os.path.normpath(path) # $pathNormalization
|
||||
return os.path.normpath(path) # $ pathNormalization
|
||||
|
||||
|
||||
p5 = normalize(path)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
s = "taintedString"
|
||||
|
||||
if s.startswith("tainted"):
|
||||
s2 = s # $SafeAccessCheck=s
|
||||
s2 = s # $ SafeAccessCheck=s
|
||||
pass
|
||||
|
||||
sw = s.startswith
|
||||
|
||||
@@ -13,8 +13,8 @@ import os
|
||||
|
||||
# can't use a string literal with spaces in the tags of an InlineExpectationsTest, so using variables :|
|
||||
|
||||
os.popen("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
os.system("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
os.popen("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
os.system("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
|
||||
def os_members():
|
||||
@@ -24,8 +24,8 @@ def os_members():
|
||||
# :|
|
||||
from os import popen, system
|
||||
|
||||
popen("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
system("cmd1; cmd2") # $getCommand="cmd1; cmd2"
|
||||
popen("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
system("cmd1; cmd2") # $ getCommand="cmd1; cmd2"
|
||||
|
||||
|
||||
########################################
|
||||
@@ -85,62 +85,62 @@ os.posix_spawnp(path="path", argv=["<progname>", "arg0"], env=env) # $ getComma
|
||||
|
||||
import subprocess
|
||||
|
||||
subprocess.Popen("cmd1; cmd2", shell=True) # $getCommand="cmd1; cmd2"
|
||||
subprocess.Popen("cmd1; cmd2", shell="truthy string") # $getCommand="cmd1; cmd2"
|
||||
subprocess.Popen(["cmd1; cmd2", "shell-arg"], shell=True) # $getCommand="cmd1; cmd2"
|
||||
subprocess.Popen("cmd1; cmd2", shell=True, executable="/bin/bash") # $getCommand="cmd1; cmd2" getCommand="/bin/bash"
|
||||
subprocess.Popen("cmd1; cmd2", shell=True) # $ getCommand="cmd1; cmd2"
|
||||
subprocess.Popen("cmd1; cmd2", shell="truthy string") # $ getCommand="cmd1; cmd2"
|
||||
subprocess.Popen(["cmd1; cmd2", "shell-arg"], shell=True) # $ getCommand="cmd1; cmd2"
|
||||
subprocess.Popen("cmd1; cmd2", shell=True, executable="/bin/bash") # $ getCommand="cmd1; cmd2" getCommand="/bin/bash"
|
||||
|
||||
subprocess.Popen("executable") # $getCommand="executable"
|
||||
subprocess.Popen(["executable", "arg0"]) # $getCommand="executable"
|
||||
subprocess.Popen("<progname>", executable="executable") # $getCommand="executable"
|
||||
subprocess.Popen(["<progname>", "arg0"], executable="executable") # $getCommand="executable"
|
||||
subprocess.Popen("executable") # $ getCommand="executable"
|
||||
subprocess.Popen(["executable", "arg0"]) # $ getCommand="executable"
|
||||
subprocess.Popen("<progname>", executable="executable") # $ getCommand="executable"
|
||||
subprocess.Popen(["<progname>", "arg0"], executable="executable") # $ getCommand="executable"
|
||||
|
||||
# call/check_call/check_output/run all work like Popen from a command execution point of view
|
||||
subprocess.call(["executable", "arg0"]) # $getCommand="executable"
|
||||
subprocess.check_call(["executable", "arg0"]) # $getCommand="executable"
|
||||
subprocess.check_output(["executable", "arg0"]) # $getCommand="executable"
|
||||
subprocess.run(["executable", "arg0"]) # $getCommand="executable"
|
||||
subprocess.call(["executable", "arg0"]) # $ getCommand="executable"
|
||||
subprocess.check_call(["executable", "arg0"]) # $ getCommand="executable"
|
||||
subprocess.check_output(["executable", "arg0"]) # $ getCommand="executable"
|
||||
subprocess.run(["executable", "arg0"]) # $ getCommand="executable"
|
||||
|
||||
|
||||
########################################
|
||||
# actively using known shell as the executable
|
||||
|
||||
subprocess.Popen(["/bin/sh", "-c", "vuln"]) # $getCommand="/bin/sh" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["/bin/bash", "-c", "vuln"]) # $getCommand="/bin/bash" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["/bin/dash", "-c", "vuln"]) # $getCommand="/bin/dash" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["/bin/zsh", "-c", "vuln"]) # $getCommand="/bin/zsh" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["/bin/sh", "-c", "vuln"]) # $ getCommand="/bin/sh" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["/bin/bash", "-c", "vuln"]) # $ getCommand="/bin/bash" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["/bin/dash", "-c", "vuln"]) # $ getCommand="/bin/dash" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["/bin/zsh", "-c", "vuln"]) # $ getCommand="/bin/zsh" MISSING: getCommand="vuln"
|
||||
|
||||
subprocess.Popen(["sh", "-c", "vuln"]) # $getCommand="sh" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["bash", "-c", "vuln"]) # $getCommand="bash" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["dash", "-c", "vuln"]) # $getCommand="dash" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["zsh", "-c", "vuln"]) # $getCommand="zsh" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["sh", "-c", "vuln"]) # $ getCommand="sh" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["bash", "-c", "vuln"]) # $ getCommand="bash" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["dash", "-c", "vuln"]) # $ getCommand="dash" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["zsh", "-c", "vuln"]) # $ getCommand="zsh" MISSING: getCommand="vuln"
|
||||
|
||||
# Check that we don't consider ANY argument a command injection sink
|
||||
subprocess.Popen(["sh", "/bin/python"]) # $getCommand="sh"
|
||||
subprocess.Popen(["sh", "/bin/python"]) # $ getCommand="sh"
|
||||
|
||||
subprocess.Popen(["cmd.exe", "/c", "vuln"]) # $getCommand="cmd.exe" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["cmd.exe", "/C", "vuln"]) # $getCommand="cmd.exe" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["cmd", "/c", "vuln"]) # $getCommand="cmd" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["cmd", "/C", "vuln"]) # $getCommand="cmd" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["cmd.exe", "/c", "vuln"]) # $ getCommand="cmd.exe" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["cmd.exe", "/C", "vuln"]) # $ getCommand="cmd.exe" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["cmd", "/c", "vuln"]) # $ getCommand="cmd" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["cmd", "/C", "vuln"]) # $ getCommand="cmd" MISSING: getCommand="vuln"
|
||||
|
||||
subprocess.Popen(["<progname>", "-c", "vuln"], executable="/bin/bash") # $getCommand="/bin/bash" MISSING: getCommand="vuln"
|
||||
subprocess.Popen(["<progname>", "-c", "vuln"], executable="/bin/bash") # $ getCommand="/bin/bash" MISSING: getCommand="vuln"
|
||||
|
||||
if UNKNOWN:
|
||||
os.execl("/bin/sh", "<progname>", "-c", "vuln") # $getCommand="/bin/sh" getAPathArgument="/bin/sh" MISSING: getCommand="vuln"
|
||||
os.execl("/bin/sh", "<progname>", "-c", "vuln") # $ getCommand="/bin/sh" getAPathArgument="/bin/sh" MISSING: getCommand="vuln"
|
||||
|
||||
os.spawnl(os.P_WAIT, "/bin/sh", "<progname>", "-c", "vuln") # $getCommand="/bin/sh" getAPathArgument="/bin/sh" MISSING: getCommand="vuln"
|
||||
os.spawnl(os.P_WAIT, "/bin/sh", "<progname>", "-c", "vuln") # $ getCommand="/bin/sh" getAPathArgument="/bin/sh" MISSING: getCommand="vuln"
|
||||
|
||||
|
||||
########################################
|
||||
# Passing arguments by reference
|
||||
|
||||
args = ["/bin/sh", "-c", "vuln"]
|
||||
subprocess.Popen(args) # $getCommand=args
|
||||
subprocess.Popen(args) # $ getCommand=args
|
||||
|
||||
args = "<progname>"
|
||||
use_shell = False
|
||||
exe = "executable"
|
||||
subprocess.Popen(args, shell=use_shell, executable=exe) # $getCommand=exe
|
||||
subprocess.Popen(args, shell=use_shell, executable=exe) # $ getCommand=exe
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -165,14 +165,14 @@ cmd = "sh -c " + wrong_use
|
||||
import asyncio
|
||||
from asyncio import subprocess
|
||||
|
||||
asyncio.run(asyncio.create_subprocess_exec("executable", "arg0")) # $getCommand="executable" getAPathArgument="executable"
|
||||
asyncio.run(subprocess.create_subprocess_exec("executable", "arg0")) # $getCommand="executable" getAPathArgument="executable"
|
||||
asyncio.run(asyncio.create_subprocess_exec("executable", "arg0")) # $ getCommand="executable" getAPathArgument="executable"
|
||||
asyncio.run(subprocess.create_subprocess_exec("executable", "arg0")) # $ getCommand="executable" getAPathArgument="executable"
|
||||
|
||||
loop = asyncio.new_event_loop()
|
||||
loop.run_until_complete(loop.subprocess_exec(asyncio.SubprocessProtocol, "executable", "arg0")) # $getCommand="executable" getAPathArgument="executable"
|
||||
loop.run_until_complete(loop.subprocess_exec(asyncio.SubprocessProtocol, "executable", "arg0")) # $ getCommand="executable" getAPathArgument="executable"
|
||||
|
||||
asyncio.run(asyncio.create_subprocess_shell("shell_command")) # $getCommand="shell_command" getAPathArgument="shell_command"
|
||||
asyncio.run(subprocess.create_subprocess_shell("shell_command")) # $getCommand="shell_command" getAPathArgument="shell_command"
|
||||
asyncio.run(asyncio.create_subprocess_shell("shell_command")) # $ getCommand="shell_command" getAPathArgument="shell_command"
|
||||
asyncio.run(subprocess.create_subprocess_shell("shell_command")) # $ getCommand="shell_command" getAPathArgument="shell_command"
|
||||
|
||||
loop = asyncio.get_running_loop()
|
||||
loop.run_until_complete(loop.subprocess_shell(asyncio.SubprocessProtocol, "shell_command")) # $getCommand="shell_command" getAPathArgument="shell_command"
|
||||
loop.run_until_complete(loop.subprocess_shell(asyncio.SubprocessProtocol, "shell_command")) # $ getCommand="shell_command" getAPathArgument="shell_command"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import yaml
|
||||
|
||||
# Unsafe:
|
||||
yaml.load(payload) # $decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
yaml.load(stream=payload) # $decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
yaml.load(payload, yaml.Loader) # $decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
yaml.load(payload) # $ decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
yaml.load(stream=payload) # $ decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
yaml.load(payload, yaml.Loader) # $ decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
yaml.unsafe_load(payload) # $ decodeInput=payload decodeOutput=yaml.unsafe_load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
yaml.full_load(payload) # $ decodeInput=payload decodeOutput=yaml.full_load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
|
||||
# Safe:
|
||||
yaml.load(payload, yaml.SafeLoader) # $ decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML
|
||||
yaml.load(payload, Loader=yaml.SafeLoader) # $decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML
|
||||
yaml.load(payload, yaml.BaseLoader) # $decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML
|
||||
yaml.load(payload, Loader=yaml.SafeLoader) # $ decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML
|
||||
yaml.load(payload, yaml.BaseLoader) # $ decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML
|
||||
yaml.safe_load(payload) # $ decodeInput=payload decodeOutput=yaml.safe_load(..) decodeFormat=YAML
|
||||
|
||||
################################################################################
|
||||
@@ -34,5 +34,5 @@ yaml.load(payload, yaml.CLoader) # $ decodeInput=payload decodeOutput=yaml.load
|
||||
yaml.load(payload, yaml.CFullLoader) # $ decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML decodeMayExecuteInput
|
||||
|
||||
# Safe:
|
||||
yaml.load(payload, yaml.CSafeLoader) # $decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML
|
||||
yaml.load(payload, yaml.CBaseLoader) # $decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML
|
||||
yaml.load(payload, yaml.CSafeLoader) # $ decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML
|
||||
yaml.load(payload, yaml.CBaseLoader) # $ decodeInput=payload decodeOutput=yaml.load(..) decodeFormat=YAML
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
import re
|
||||
|
||||
|
||||
re.compile(r'[A-Z]') #$ charRange=1:2-3:4
|
||||
re.compile(r'[A-Z]') # $ charRange=1:2-3:4
|
||||
|
||||
try:
|
||||
re.compile(r'[]-[]') #$ SPURIOUS: charRange=1:2-3:4
|
||||
re.compile(r'[]-[]') # $ SPURIOUS: charRange=1:2-3:4
|
||||
raise Exception("this should not be reached")
|
||||
except re.error:
|
||||
pass
|
||||
|
||||
re.compile(r'[---]') #$ charRange=1:2-3:4
|
||||
re.compile(r'[\---]') #$ charRange=1:3-4:5
|
||||
re.compile(r'[--\-]') #$ charRange=1:2-3:5
|
||||
re.compile(r'[\--\-]') #$ charRange=1:3-4:6
|
||||
re.compile(r'[0-9-A-Z]') #$ charRange=1:2-3:4 charRange=5:6-7:8
|
||||
re.compile(r'[0\-9-A-Z]') #$ charRange=4:5-6:7
|
||||
re.compile(r'[---]') # $ charRange=1:2-3:4
|
||||
re.compile(r'[\---]') # $ charRange=1:3-4:5
|
||||
re.compile(r'[--\-]') # $ charRange=1:2-3:5
|
||||
re.compile(r'[\--\-]') # $ charRange=1:3-4:6
|
||||
re.compile(r'[0-9-A-Z]') # $ charRange=1:2-3:4 charRange=5:6-7:8
|
||||
re.compile(r'[0\-9-A-Z]') # $ charRange=4:5-6:7
|
||||
|
||||
try:
|
||||
re.compile(r'[0--9-A-Z]') #$ SPURIOUS: charRange=1:2-3:4 charRange=4:5-6:7
|
||||
re.compile(r'[0--9-A-Z]') # $ SPURIOUS: charRange=1:2-3:4 charRange=4:5-6:7
|
||||
raise Exception("this should not be reached")
|
||||
except re.error:
|
||||
pass
|
||||
|
||||
re.compile(r'[^A-Z]') #$ charRange=2:3-4:5
|
||||
re.compile(r'[^A-Z]') # $ charRange=2:3-4:5
|
||||
|
||||
re.compile(r'[\0-\09]') #$ charRange=1:3-4:6
|
||||
re.compile(r'[\0-\07]') #$ charRange=1:3-4:7
|
||||
re.compile(r'[\0-\09]') # $ charRange=1:3-4:6
|
||||
re.compile(r'[\0-\07]') # $ charRange=1:3-4:7
|
||||
|
||||
re.compile(r'[\0123-5]') #$ charRange=5:6-7:8
|
||||
re.compile(r'[\0123-5]') # $ charRange=5:6-7:8
|
||||
|
||||
|
||||
#Negative lookahead
|
||||
re.compile(r'(?!not-this)^[A-Z_]+$') #$ charRange=14:15-16:17
|
||||
re.compile(r'(?!not-this)^[A-Z_]+$') # $ charRange=14:15-16:17
|
||||
#Negative lookbehind
|
||||
re.compile(r'^[A-Z_]+$(?<!not-this)') #$ charRange=2:3-4:5
|
||||
re.compile(r'^[A-Z_]+$(?<!not-this)') # $ charRange=2:3-4:5
|
||||
|
||||
|
||||
#OK -- ODASA-ODASA-3968
|
||||
re.compile('(?:[^%]|^)?%\((\w*)\)[a-z]') #$ charRange=22:23-24:25
|
||||
re.compile('(?:[^%]|^)?%\((\w*)\)[a-z]') # $ charRange=22:23-24:25
|
||||
|
||||
#ODASA-3985
|
||||
#Half Surrogate pairs
|
||||
re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]') #$ charRange=1:2-3:4 charRange=6:7-8:9
|
||||
re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]') # $ charRange=1:2-3:4 charRange=6:7-8:9
|
||||
#Outside BMP
|
||||
re.compile(u'[\U00010000-\U0010ffff]') #$ charRange=1:2-3:4
|
||||
re.compile(u'[\U00010000-\U0010ffff]') # $ charRange=1:2-3:4
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user