Skip to content

Commit 85a0566

Browse files
authored
Merge pull request #1597 from markshannon/python-tracking-special-variable-attributes-through-phis
Python points-to: Track implicit module attributes through phi-nodes.
2 parents cca1593 + b4d413c commit 85a0566

File tree

9 files changed

+143
-8
lines changed

9 files changed

+143
-8
lines changed

python/ql/src/semmle/python/pointsto/PointsTo.qll

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,8 @@ cached module PointsToInternal {
555555
}
556556

557557
/* Helper for ssa_phi_points_to */
558-
pragma [noinline]
559-
private predicate ssa_phi_reachable_from_input(PhiFunction phi, PointsToContext context, EssaVariable input) {
558+
cached
559+
predicate ssa_phi_reachable_from_input(PhiFunction phi, PointsToContext context, EssaVariable input) {
560560
exists(BasicBlock pred |
561561
input = phi.getInput(pred) and
562562
reachableEdge(pred, phi.getBasicBlock(), context)
@@ -2238,6 +2238,17 @@ cached module ModuleAttributes {
22382238
callsitePointsTo(var.getDefinition(), name, value, origin)
22392239
or
22402240
scopeEntryPointsTo(var.getDefinition(), name, value, origin)
2241+
or
2242+
phiPointsTo(var.getDefinition(), name, value, origin)
2243+
}
2244+
2245+
/** Holds if the phi-function `phi` refers to `(value, origin)` given the context `context`. */
2246+
pragma [nomagic]
2247+
private predicate phiPointsTo(PhiFunction phi, string name, ObjectInternal value, CfgOrigin origin) {
2248+
exists(EssaVariable input |
2249+
PointsToInternal::ssa_phi_reachable_from_input(phi, any(Context c | c.isImport()), input) and
2250+
attributePointsTo(input, name, value, origin)
2251+
)
22412252
}
22422253

22432254
pragma [nomagic]

python/ql/test/library-tests/PointsTo/new/Dataflow.expected

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,11 @@
559559
| i_imports.py:37 | code_2 = ImportExpr |
560560
| j_convoluted_imports.py:0 | __name___0 = ScopeEntryDefinition |
561561
| j_convoluted_imports.py:0 | __package___0 = ScopeEntryDefinition |
562+
| j_convoluted_imports.py:0 | object_0 = ScopeEntryDefinition |
563+
| j_convoluted_imports.py:0 | p_0 = ScopeEntryDefinition |
564+
| j_convoluted_imports.py:0 | q_0 = ScopeEntryDefinition |
565+
| j_convoluted_imports.py:0 | r_0 = ScopeEntryDefinition |
566+
| j_convoluted_imports.py:0 | unknown_0 = ScopeEntryDefinition |
562567
| j_convoluted_imports.py:3 | module_0 = ImportMember |
563568
| j_convoluted_imports.py:6 | x_0 = ImportMember |
564569
| j_convoluted_imports.py:9 | C_0 = ClassExpr |
@@ -567,6 +572,39 @@
567572
| j_convoluted_imports.py:13 | self_0 = ParameterDefinition |
568573
| j_convoluted_imports.py:14 | x_0 = ImportMember |
569574
| j_convoluted_imports.py:16 | moduleX_0 = ImportMember |
575+
| j_convoluted_imports.py:20 | C_1 = ImportStarRefinement(C_0) |
576+
| j_convoluted_imports.py:20 | __name___1 = ImportStarRefinement(__name___0) |
577+
| j_convoluted_imports.py:20 | __package___1 = ImportStarRefinement(__package___0) |
578+
| j_convoluted_imports.py:20 | moduleX_1 = ImportStarRefinement(moduleX_0) |
579+
| j_convoluted_imports.py:20 | module_1 = ImportStarRefinement(module_0) |
580+
| j_convoluted_imports.py:20 | object_1 = ImportStarRefinement(object_0) |
581+
| j_convoluted_imports.py:20 | p_1 = ImportStarRefinement(p_0) |
582+
| j_convoluted_imports.py:20 | q_1 = ImportStarRefinement(q_0) |
583+
| j_convoluted_imports.py:20 | r_1 = ImportStarRefinement(r_0) |
584+
| j_convoluted_imports.py:20 | unknown_1 = ImportStarRefinement(unknown_0) |
585+
| j_convoluted_imports.py:20 | x_1 = ImportStarRefinement(x_0) |
586+
| j_convoluted_imports.py:22 | C_2 = ImportStarRefinement(C_0) |
587+
| j_convoluted_imports.py:22 | __name___2 = ImportStarRefinement(__name___0) |
588+
| j_convoluted_imports.py:22 | __package___2 = ImportStarRefinement(__package___0) |
589+
| j_convoluted_imports.py:22 | moduleX_2 = ImportStarRefinement(moduleX_0) |
590+
| j_convoluted_imports.py:22 | module_2 = ImportStarRefinement(module_0) |
591+
| j_convoluted_imports.py:22 | object_2 = ImportStarRefinement(object_0) |
592+
| j_convoluted_imports.py:22 | p_2 = ImportStarRefinement(p_0) |
593+
| j_convoluted_imports.py:22 | q_2 = ImportStarRefinement(q_0) |
594+
| j_convoluted_imports.py:22 | r_2 = ImportStarRefinement(r_0) |
595+
| j_convoluted_imports.py:22 | unknown_2 = ImportStarRefinement(unknown_0) |
596+
| j_convoluted_imports.py:22 | x_2 = ImportStarRefinement(x_0) |
597+
| j_convoluted_imports.py:23 | C_3 = phi(C_1, C_2) |
598+
| j_convoluted_imports.py:23 | __name___3 = phi(__name___1, __name___2) |
599+
| j_convoluted_imports.py:23 | __package___3 = phi(__package___1, __package___2) |
600+
| j_convoluted_imports.py:23 | moduleX_3 = phi(moduleX_1, moduleX_2) |
601+
| j_convoluted_imports.py:23 | module_3 = phi(module_1, module_2) |
602+
| j_convoluted_imports.py:23 | object_3 = phi(object_1, object_2) |
603+
| j_convoluted_imports.py:23 | p_3 = phi(p_1, p_2) |
604+
| j_convoluted_imports.py:23 | q_3 = phi(q_1, q_2) |
605+
| j_convoluted_imports.py:23 | r_3 = phi(r_1, r_2) |
606+
| j_convoluted_imports.py:23 | unknown_3 = phi(unknown_1, unknown_2) |
607+
| j_convoluted_imports.py:23 | x_3 = phi(x_1, x_2) |
570608
| k_getsetattr.py:0 | __name___0 = ScopeEntryDefinition |
571609
| k_getsetattr.py:0 | __package___0 = ScopeEntryDefinition |
572610
| k_getsetattr.py:4 | C_0 = ClassExpr |

python/ql/test/library-tests/PointsTo/new/NameSpace.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@
107107
| j_convoluted_imports.py:0 | Module code.j_convoluted_imports | C | class C |
108108
| j_convoluted_imports.py:0 | Module code.j_convoluted_imports | module | Function module |
109109
| j_convoluted_imports.py:0 | Module code.j_convoluted_imports | moduleX | Module code.package.moduleX |
110+
| j_convoluted_imports.py:0 | Module code.j_convoluted_imports | p | int 1 |
111+
| j_convoluted_imports.py:0 | Module code.j_convoluted_imports | q | int 2 |
112+
| j_convoluted_imports.py:0 | Module code.j_convoluted_imports | r | Dict |
113+
| j_convoluted_imports.py:0 | Module code.j_convoluted_imports | r | int 3 |
114+
| j_convoluted_imports.py:0 | Module code.j_convoluted_imports | s | NoneType None |
110115
| j_convoluted_imports.py:0 | Module code.j_convoluted_imports | x | Module code.package.x |
111116
| j_convoluted_imports.py:9 | Class C | f | Function f |
112117
| j_convoluted_imports.py:9 | Class C | module2 | int 7 |

python/ql/test/library-tests/PointsTo/new/PointsToWithContext.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,12 @@ WARNING: Predicate points_to has been deprecated and may be removed in future (P
488488
| j_convoluted_imports.py:16 | ControlFlowNode for moduleX | Module code.package.moduleX | builtin-class module | 0 | import |
489489
| j_convoluted_imports.py:17 | ControlFlowNode for Attribute | class Y | builtin-class type | 1 | import |
490490
| j_convoluted_imports.py:17 | ControlFlowNode for moduleX | Module code.package.moduleX | builtin-class module | 0 | import |
491+
| j_convoluted_imports.py:20 | ControlFlowNode for ImportExpr | Module code.test_package.module1 | builtin-class module | 20 | import |
492+
| j_convoluted_imports.py:22 | ControlFlowNode for ImportExpr | Module code.test_package.module2 | builtin-class module | 22 | import |
493+
| j_convoluted_imports.py:23 | ControlFlowNode for p | int 1 | builtin-class int | 3 | import |
494+
| j_convoluted_imports.py:24 | ControlFlowNode for q | int 2 | builtin-class int | 4 | import |
495+
| j_convoluted_imports.py:25 | ControlFlowNode for r | Dict | builtin-class dict | 5 | import |
496+
| j_convoluted_imports.py:25 | ControlFlowNode for r | int 3 | builtin-class int | 5 | import |
491497
| k_getsetattr.py:4 | ControlFlowNode for C | class C | builtin-class type | 4 | import |
492498
| k_getsetattr.py:4 | ControlFlowNode for ClassExpr | class C | builtin-class type | 4 | import |
493499
| k_getsetattr.py:4 | ControlFlowNode for object | builtin-class object | builtin-class type | 4 | import |

python/ql/test/library-tests/PointsTo/new/PointsToWithType.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,12 @@ WARNING: Predicate points_to has been deprecated and may be removed in future (P
585585
| j_convoluted_imports.py:16 | ControlFlowNode for moduleX | Module code.package.moduleX | builtin-class module | 0 |
586586
| j_convoluted_imports.py:17 | ControlFlowNode for Attribute | class Y | builtin-class type | 1 |
587587
| j_convoluted_imports.py:17 | ControlFlowNode for moduleX | Module code.package.moduleX | builtin-class module | 0 |
588+
| j_convoluted_imports.py:20 | ControlFlowNode for ImportExpr | Module code.test_package.module1 | builtin-class module | 20 |
589+
| j_convoluted_imports.py:22 | ControlFlowNode for ImportExpr | Module code.test_package.module2 | builtin-class module | 22 |
590+
| j_convoluted_imports.py:23 | ControlFlowNode for p | int 1 | builtin-class int | 3 |
591+
| j_convoluted_imports.py:24 | ControlFlowNode for q | int 2 | builtin-class int | 4 |
592+
| j_convoluted_imports.py:25 | ControlFlowNode for r | Dict | builtin-class dict | 5 |
593+
| j_convoluted_imports.py:25 | ControlFlowNode for r | int 3 | builtin-class int | 5 |
588594
| k_getsetattr.py:4 | ControlFlowNode for C | class C | builtin-class type | 4 |
589595
| k_getsetattr.py:4 | ControlFlowNode for ClassExpr | class C | builtin-class type | 4 |
590596
| k_getsetattr.py:4 | ControlFlowNode for object | builtin-class object | builtin-class type | 4 |

python/ql/test/library-tests/PointsTo/new/SSA.expected

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,29 @@ WARNING: Predicate ssa_variable_points_to has been deprecated and may be removed
357357
| j_convoluted_imports.py:13 | self_0 = ParameterDefinition | self | class C |
358358
| j_convoluted_imports.py:14 | x_0 = ImportMember | Module code.package.x | builtin-class module |
359359
| j_convoluted_imports.py:16 | moduleX_0 = ImportMember | Module code.package.moduleX | builtin-class module |
360+
| j_convoluted_imports.py:20 | C_1 = ImportStarRefinement(C_0) | class C | builtin-class type |
361+
| j_convoluted_imports.py:20 | __name___1 = ImportStarRefinement(__name___0) | 'code.j_convoluted_imports' | builtin-class str |
362+
| j_convoluted_imports.py:20 | moduleX_1 = ImportStarRefinement(moduleX_0) | Module code.package.moduleX | builtin-class module |
363+
| j_convoluted_imports.py:20 | module_1 = ImportStarRefinement(module_0) | Function module | builtin-class function |
364+
| j_convoluted_imports.py:20 | p_1 = ImportStarRefinement(p_0) | int 1 | builtin-class int |
365+
| j_convoluted_imports.py:20 | q_1 = ImportStarRefinement(q_0) | int 2 | builtin-class int |
366+
| j_convoluted_imports.py:20 | r_1 = ImportStarRefinement(r_0) | int 3 | builtin-class int |
367+
| j_convoluted_imports.py:20 | x_1 = ImportStarRefinement(x_0) | Module code.package.x | builtin-class module |
368+
| j_convoluted_imports.py:22 | C_2 = ImportStarRefinement(C_0) | class C | builtin-class type |
369+
| j_convoluted_imports.py:22 | __name___2 = ImportStarRefinement(__name___0) | 'code.j_convoluted_imports' | builtin-class str |
370+
| j_convoluted_imports.py:22 | moduleX_2 = ImportStarRefinement(moduleX_0) | Module code.package.moduleX | builtin-class module |
371+
| j_convoluted_imports.py:22 | module_2 = ImportStarRefinement(module_0) | Function module | builtin-class function |
372+
| j_convoluted_imports.py:22 | r_2 = ImportStarRefinement(r_0) | Dict | builtin-class dict |
373+
| j_convoluted_imports.py:22 | x_2 = ImportStarRefinement(x_0) | Module code.package.x | builtin-class module |
374+
| j_convoluted_imports.py:23 | C_3 = phi(C_1, C_2) | class C | builtin-class type |
375+
| j_convoluted_imports.py:23 | __name___3 = phi(__name___1, __name___2) | 'code.j_convoluted_imports' | builtin-class str |
376+
| j_convoluted_imports.py:23 | moduleX_3 = phi(moduleX_1, moduleX_2) | Module code.package.moduleX | builtin-class module |
377+
| j_convoluted_imports.py:23 | module_3 = phi(module_1, module_2) | Function module | builtin-class function |
378+
| j_convoluted_imports.py:23 | p_3 = phi(p_1, p_2) | int 1 | builtin-class int |
379+
| j_convoluted_imports.py:23 | q_3 = phi(q_1, q_2) | int 2 | builtin-class int |
380+
| j_convoluted_imports.py:23 | r_3 = phi(r_1, r_2) | Dict | builtin-class dict |
381+
| j_convoluted_imports.py:23 | r_3 = phi(r_1, r_2) | int 3 | builtin-class int |
382+
| j_convoluted_imports.py:23 | x_3 = phi(x_1, x_2) | Module code.package.x | builtin-class module |
360383
| m_attributes.py:0 | __name___0 = ScopeEntryDefinition | 'code.m_attributes' | builtin-class str |
361384
| m_attributes.py:3 | C_0 = ClassExpr | class C | builtin-class type |
362385
| m_attributes.py:5 | __init___0 = FunctionExpr | Function __init__ | builtin-class function |

python/ql/test/library-tests/PointsTo/new/SsaUses.expected

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -618,17 +618,49 @@
618618
| h_classes.py:50 | f_2 | ControlFlowNode for f |
619619
| h_classes.py:52 | arg1_0 | Exit node for Function n |
620620
| h_classes.py:52 | self_0 | Exit node for Function n |
621-
| j_convoluted_imports.py:0 | C_0 | Exit node for Module code.j_convoluted_imports |
622-
| j_convoluted_imports.py:0 | __name___0 | Exit node for Module code.j_convoluted_imports |
623-
| j_convoluted_imports.py:0 | __package___0 | Exit node for Module code.j_convoluted_imports |
624-
| j_convoluted_imports.py:0 | moduleX_0 | Exit node for Module code.j_convoluted_imports |
625-
| j_convoluted_imports.py:0 | module_0 | Exit node for Module code.j_convoluted_imports |
626-
| j_convoluted_imports.py:0 | x_0 | Exit node for Module code.j_convoluted_imports |
621+
| j_convoluted_imports.py:0 | C_3 | Exit node for Module code.j_convoluted_imports |
622+
| j_convoluted_imports.py:0 | __name___3 | Exit node for Module code.j_convoluted_imports |
623+
| j_convoluted_imports.py:0 | __package___3 | Exit node for Module code.j_convoluted_imports |
624+
| j_convoluted_imports.py:0 | moduleX_3 | Exit node for Module code.j_convoluted_imports |
625+
| j_convoluted_imports.py:0 | module_3 | Exit node for Module code.j_convoluted_imports |
626+
| j_convoluted_imports.py:0 | object_3 | Exit node for Module code.j_convoluted_imports |
627+
| j_convoluted_imports.py:0 | p_3 | Exit node for Module code.j_convoluted_imports |
628+
| j_convoluted_imports.py:0 | q_3 | Exit node for Module code.j_convoluted_imports |
629+
| j_convoluted_imports.py:0 | r_3 | Exit node for Module code.j_convoluted_imports |
630+
| j_convoluted_imports.py:0 | unknown_3 | Exit node for Module code.j_convoluted_imports |
631+
| j_convoluted_imports.py:0 | x_3 | Exit node for Module code.j_convoluted_imports |
627632
| j_convoluted_imports.py:9 | f_0 | Exit node for Class C |
628633
| j_convoluted_imports.py:9 | module2_0 | Exit node for Class C |
634+
| j_convoluted_imports.py:9 | object_0 | ControlFlowNode for object |
629635
| j_convoluted_imports.py:13 | self_0 | Exit node for Function f |
630636
| j_convoluted_imports.py:13 | x_0 | Exit node for Function f |
631637
| j_convoluted_imports.py:17 | moduleX_0 | ControlFlowNode for moduleX |
638+
| j_convoluted_imports.py:19 | unknown_0 | ControlFlowNode for unknown |
639+
| j_convoluted_imports.py:20 | C_0 | ControlFlowNode for from code.test_package.module1 import * |
640+
| j_convoluted_imports.py:20 | __name___0 | ControlFlowNode for from code.test_package.module1 import * |
641+
| j_convoluted_imports.py:20 | __package___0 | ControlFlowNode for from code.test_package.module1 import * |
642+
| j_convoluted_imports.py:20 | moduleX_0 | ControlFlowNode for from code.test_package.module1 import * |
643+
| j_convoluted_imports.py:20 | module_0 | ControlFlowNode for from code.test_package.module1 import * |
644+
| j_convoluted_imports.py:20 | object_0 | ControlFlowNode for from code.test_package.module1 import * |
645+
| j_convoluted_imports.py:20 | p_0 | ControlFlowNode for from code.test_package.module1 import * |
646+
| j_convoluted_imports.py:20 | q_0 | ControlFlowNode for from code.test_package.module1 import * |
647+
| j_convoluted_imports.py:20 | r_0 | ControlFlowNode for from code.test_package.module1 import * |
648+
| j_convoluted_imports.py:20 | unknown_0 | ControlFlowNode for from code.test_package.module1 import * |
649+
| j_convoluted_imports.py:20 | x_0 | ControlFlowNode for from code.test_package.module1 import * |
650+
| j_convoluted_imports.py:22 | C_0 | ControlFlowNode for from code.test_package.module2 import * |
651+
| j_convoluted_imports.py:22 | __name___0 | ControlFlowNode for from code.test_package.module2 import * |
652+
| j_convoluted_imports.py:22 | __package___0 | ControlFlowNode for from code.test_package.module2 import * |
653+
| j_convoluted_imports.py:22 | moduleX_0 | ControlFlowNode for from code.test_package.module2 import * |
654+
| j_convoluted_imports.py:22 | module_0 | ControlFlowNode for from code.test_package.module2 import * |
655+
| j_convoluted_imports.py:22 | object_0 | ControlFlowNode for from code.test_package.module2 import * |
656+
| j_convoluted_imports.py:22 | p_0 | ControlFlowNode for from code.test_package.module2 import * |
657+
| j_convoluted_imports.py:22 | q_0 | ControlFlowNode for from code.test_package.module2 import * |
658+
| j_convoluted_imports.py:22 | r_0 | ControlFlowNode for from code.test_package.module2 import * |
659+
| j_convoluted_imports.py:22 | unknown_0 | ControlFlowNode for from code.test_package.module2 import * |
660+
| j_convoluted_imports.py:22 | x_0 | ControlFlowNode for from code.test_package.module2 import * |
661+
| j_convoluted_imports.py:23 | p_3 | ControlFlowNode for p |
662+
| j_convoluted_imports.py:24 | q_3 | ControlFlowNode for q |
663+
| j_convoluted_imports.py:25 | r_3 | ControlFlowNode for r |
632664
| k_getsetattr.py:0 | C_0 | Exit node for Module code.k_getsetattr |
633665
| k_getsetattr.py:0 | __name___0 | Exit node for Module code.k_getsetattr |
634666
| k_getsetattr.py:0 | __package___0 | Exit node for Module code.k_getsetattr |

python/ql/test/library-tests/PointsTo/new/Values.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,12 @@
372372
| j_convoluted_imports.py:16 | ControlFlowNode for ImportMember | import | Module code.package.moduleX | builtin-class module |
373373
| j_convoluted_imports.py:17 | ControlFlowNode for Attribute | import | class Y | builtin-class type |
374374
| j_convoluted_imports.py:17 | ControlFlowNode for moduleX | import | Module code.package.moduleX | builtin-class module |
375+
| j_convoluted_imports.py:20 | ControlFlowNode for ImportExpr | import | Module code.test_package.module1 | builtin-class module |
376+
| j_convoluted_imports.py:22 | ControlFlowNode for ImportExpr | import | Module code.test_package.module2 | builtin-class module |
377+
| j_convoluted_imports.py:23 | ControlFlowNode for p | import | int 1 | builtin-class int |
378+
| j_convoluted_imports.py:24 | ControlFlowNode for q | import | int 2 | builtin-class int |
379+
| j_convoluted_imports.py:25 | ControlFlowNode for r | import | Dict | builtin-class dict |
380+
| j_convoluted_imports.py:25 | ControlFlowNode for r | import | int 3 | builtin-class int |
375381
| k_getsetattr.py:4 | ControlFlowNode for ClassExpr | import | class C | builtin-class type |
376382
| k_getsetattr.py:4 | ControlFlowNode for object | import | builtin-class object | builtin-class type |
377383
| k_getsetattr.py:6 | ControlFlowNode for FunctionExpr | import | Function C.meth1 | builtin-class function |

python/ql/test/library-tests/PointsTo/new/code/j_convoluted_imports.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,11 @@ def f(self):
1515

1616
from code.package import moduleX
1717
moduleX.Y
18+
19+
if unknown:
20+
from code.test_package.module1 import *
21+
else:
22+
from code.test_package.module2 import *
23+
p
24+
q
25+
r

0 commit comments

Comments
 (0)