Skip to content

Commit a413a32

Browse files
authored
Merge pull request github#3114 from RasmusWL/python-add-fp-for-non-callable
Approved by tausbn
2 parents ac7c74d + 05ecfc8 commit a413a32

File tree

5 files changed

+71
-0
lines changed

5 files changed

+71
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
| test.py:10:15:10:17 | ControlFlowNode for cls | class Foo |
2+
| test.py:17:15:17:17 | ControlFlowNode for cls | class Foo |
3+
| test.py:17:15:17:17 | ControlFlowNode for cls | self instance of Foo |
4+
| test.py:22:15:22:17 | ControlFlowNode for cls | class Foo |
5+
| test.py:22:15:22:17 | ControlFlowNode for cls | self instance of Foo |
6+
| test.py:27:15:27:17 | ControlFlowNode for cls | class Foo |
7+
| test.py:27:15:27:17 | ControlFlowNode for cls | self instance of Foo |
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import python
2+
3+
from NameNode name, CallNode call, string debug
4+
where
5+
call.getAnArg() = name and
6+
call.getFunction().(NameNode).getId() = "check" and
7+
if exists(name.pointsTo())
8+
then debug = name.pointsTo().toString()
9+
else debug = "<MISSING pointsTo()>"
10+
select name, debug
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# See https://github.com/Semmle/ql/issues/3113
2+
def some_decorator(func):
3+
print("this could be tricky for our analysis")
4+
return func
5+
6+
class Foo(object):
7+
8+
@classmethod
9+
def no_problem(cls):
10+
check(cls) # analysis says 'cls' can only point-to Class Foo
11+
12+
@some_decorator
13+
@classmethod
14+
def problem_through_instance(cls):
15+
# Problem is that our analysis says that 'cls' can point to EITHER the
16+
# Class Foo (correct) or an instance of Foo (wrong)
17+
check(cls)
18+
19+
@some_decorator
20+
@classmethod
21+
def problem_through_class(cls):
22+
check(cls) # same as above
23+
24+
@classmethod
25+
@some_decorator
26+
def also_problem(cls):
27+
check(cls) # same as above
28+
29+
# We need to call the methods before our analysis works
30+
f1 = Foo()
31+
f1.no_problem()
32+
f1.problem_through_instance()
33+
f1.also_problem()
34+
35+
Foo.problem_through_class()

python/ql/test/query-tests/Expressions/callable/NonCallableCalled.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
| test.py:18:5:18:8 | List() | Call to a $@ of $@. | test.py:18:5:18:6 | List | non-callable | file://:0:0:0:0 | builtin-class list | builtin-class list |
44
| test.py:26:9:26:16 | non() | Call to a $@ of $@. | test.py:15:11:15:23 | NonCallable() | non-callable | test.py:3:1:3:26 | class NonCallable | class NonCallable |
55
| test.py:47:12:47:27 | NotImplemented() | Call to a $@ of $@. | test.py:47:12:47:25 | NotImplemented | non-callable | file://:0:0:0:0 | builtin-class NotImplementedType | builtin-class NotImplementedType |
6+
| test.py:63:16:63:27 | cls() | Call to a $@ of $@. | test.py:62:22:62:24 | cls | non-callable | test.py:56:1:56:18 | class Foo | class Foo |

python/ql/test/query-tests/Expressions/callable/test.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,21 @@ def foo():
4646
def bar():
4747
return NotImplemented()
4848

49+
50+
# FP due to decorator
51+
# https://github.com/Semmle/ql/issues/3113
52+
def some_decorator(func):
53+
print("this could be tricky for our analysis")
54+
return func
55+
56+
class Foo(object):
57+
def __init__(self, arg):
58+
self.arg = arg
59+
60+
@some_decorator
61+
@classmethod
62+
def new_instance(cls, new_arg):
63+
return cls(new_arg) # TODO: FP
64+
65+
f1 = Foo(1)
66+
f2 = f1.new_instance(2)

0 commit comments

Comments
 (0)