diff --git a/python/ql/test/experimental/dataflow/validTest.py b/python/ql/test/experimental/dataflow/validTest.py index 0c6dc259d51..76bd7bb52a5 100644 --- a/python/ql/test/experimental/dataflow/validTest.py +++ b/python/ql/test/experimental/dataflow/validTest.py @@ -75,6 +75,7 @@ if __name__ == "__main__": check_tests_valid("variable-capture.test_collections") check_tests_valid("variable-capture.by_value") check_tests_valid("variable-capture.test_library_calls") + check_tests_valid("variable-capture.test_fields") check_tests_valid("module-initialization.multiphase") check_tests_valid("fieldflow.test") check_tests_valid("fieldflow.test_dict") diff --git a/python/ql/test/experimental/dataflow/variable-capture/test_fields.py b/python/ql/test/experimental/dataflow/variable-capture/test_fields.py new file mode 100644 index 00000000000..79f2c4d04f4 --- /dev/null +++ b/python/ql/test/experimental/dataflow/variable-capture/test_fields.py @@ -0,0 +1,51 @@ +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname((__file__)))) +from testlib import expects + +# These are defined so that we can evaluate the test code. +NONSOURCE = "not a source" +SOURCE = "source" + +def is_source(x): + return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j + + +def SINK(x): + if is_source(x): + print("OK") + else: + print("Unexpected flow", x) + + +def SINK_F(x): + if is_source(x): + print("Unexpected flow", x) + else: + print("OK") + +class MyObj(object): + def setFoo(self, foo): + self.foo = foo + + def getFoo(self): + return self.foo + +@expects(3) +def test_captured_field(): + foo = MyObj() + foo.setFoo(NONSOURCE) + + def test(): + SINK(foo.getFoo()) #$ captured + + def read(): + return foo.getFoo() + + SINK_F(read()) + + foo.setFoo(SOURCE) + test() + + SINK(read()) #$ captured \ No newline at end of file