From 1d25184b3214078361865d579d3c0a6fd63f61e5 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 9 Feb 2021 13:35:44 +0100 Subject: [PATCH] Python: Add test for type-tracking through decorators In general, if there is _some_ decorator on a function, it might not be safe to track content out of it (since the decorator could do anything), but in this case, we can see what the decorator does, so we should be able to handle it (but we don't right now). By my understanding of how type-tracking works, if we track content through `my_decorator`, then we would also track content to the result of `unrelated_func()`, which I wanted to make sure our tests would catch. I found out the core of the problem seems to come from our lack of being able to track to the inner scope, and added an explicit test for that. --- .../dataflow/typetracking/test.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/python/ql/test/experimental/dataflow/typetracking/test.py b/python/ql/test/experimental/dataflow/typetracking/test.py index a4dd1baeac15..4392e3bbf469 100644 --- a/python/ql/test/experimental/dataflow/typetracking/test.py +++ b/python/ql/test/experimental/dataflow/typetracking/test.py @@ -56,6 +56,41 @@ def test_import(): y # $tracked mymodule.z # $tracked + +def to_inner_scope(): + x = tracked # $tracked + def foo(): + y = x # $ MISSING: tracked + return y # $ MISSING: tracked + also_x = foo() # $ MISSING: tracked + print(also_x) # $ MISSING: tracked + + +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 + + def wrapper(): + print("before function call") + val = func() # $ MISSING: tracked + print("after function call") + return val # $ MISSING: tracked + return wrapper + +@my_decorator +def get_tracked2(): + return tracked # $tracked + +@my_decorator +def unrelated_func(): + return "foo" + +def use_funcs_with_decorators(): + x = get_tracked2() # $ MISSING: tracked + y = unrelated_func() + # ------------------------------------------------------------------------------ def expects_int(x): # $int