@@ -3,7 +3,6 @@ private import semmle.python.pointsto.PointsTo
3
3
4
4
/** Helper class for UndefinedClassAttribute.ql and MaybeUndefinedClassAttribute.ql */
5
5
class CheckClass extends ClassObject {
6
-
7
6
private predicate ofInterest ( ) {
8
7
not this .unknowableAttributes ( ) and
9
8
not this .getPyClass ( ) .isProbableMixin ( ) and
@@ -19,7 +18,8 @@ class CheckClass extends ClassObject {
19
18
forall ( ClassObject sup |
20
19
sup = this .getAnImproperSuperType ( ) and
21
20
sup .declaresAttribute ( "__init__" ) and
22
- not sup = theObjectType ( ) |
21
+ not sup = theObjectType ( )
22
+ |
23
23
sup .declaredAttribute ( "__init__" ) instanceof PyFunctionObject
24
24
)
25
25
}
@@ -32,108 +32,111 @@ class CheckClass extends ClassObject {
32
32
}
33
33
34
34
predicate sometimesDefines ( string name ) {
35
- this .alwaysDefines ( name ) or
36
- exists ( SelfAttributeStore sa |
37
- sa .getScope ( ) .getScope + ( ) = this .getAnImproperSuperType ( ) .getPyClass ( ) |
35
+ this .alwaysDefines ( name )
36
+ or
37
+ exists ( SelfAttributeStore sa |
38
+ sa .getScope ( ) .getScope + ( ) = this .getAnImproperSuperType ( ) .getPyClass ( )
39
+ |
38
40
name = sa .getName ( )
39
41
)
40
42
}
41
43
42
44
private predicate selfDictAssigns ( ) {
43
- exists ( Assign a , SelfAttributeRead self_dict , Subscript sub |
45
+ exists ( Assign a , SelfAttributeRead self_dict , Subscript sub |
44
46
self_dict .getName ( ) = "__dict__" and
45
- (
46
- self_dict = sub .getObject ( )
47
- or
48
- /* Indirect assignment via temporary variable */
49
- exists ( SsaVariable v |
50
- v .getAUse ( ) = sub .getObject ( ) .getAFlowNode ( ) and
51
- v .getDefinition ( ) .( DefinitionNode ) .getValue ( ) = self_dict .getAFlowNode ( )
52
- )
47
+ (
48
+ self_dict = sub .getObject ( )
49
+ or
50
+ /* Indirect assignment via temporary variable */
51
+ exists ( SsaVariable v |
52
+ v .getAUse ( ) = sub .getObject ( ) .getAFlowNode ( ) and
53
+ v .getDefinition ( ) .( DefinitionNode ) .getValue ( ) = self_dict .getAFlowNode ( )
54
+ )
53
55
) and
54
56
a .getATarget ( ) = sub and
55
- exists ( FunctionObject meth | meth = this .lookupAttribute ( _) and a .getScope ( ) = meth .getFunction ( ) )
57
+ exists ( FunctionObject meth |
58
+ meth = this .lookupAttribute ( _) and a .getScope ( ) = meth .getFunction ( )
59
+ )
56
60
)
57
61
}
58
62
59
- pragma [ nomagic]
63
+ pragma [ nomagic]
60
64
private predicate monkeyPatched ( string name ) {
61
65
exists ( Attribute a |
62
- a .getCtx ( ) instanceof Store and
63
- PointsTo:: points_to ( a .getObject ( ) .getAFlowNode ( ) , _, this , _, _) and a .getName ( ) = name
66
+ a .getCtx ( ) instanceof Store and
67
+ PointsTo:: points_to ( a .getObject ( ) .getAFlowNode ( ) , _, this , _, _) and
68
+ a .getName ( ) = name
64
69
)
65
70
}
66
71
67
72
private predicate selfSetattr ( ) {
68
- exists ( Call c , Name setattr , Name self , Function method |
69
- ( method .getScope ( ) = this .getPyClass ( ) or
70
- method .getScope ( ) = this .getASuperType ( ) .getPyClass ( )
71
- ) and
72
- c .getScope ( ) = method and
73
- c .getFunc ( ) = setattr and
74
- setattr .getId ( ) = "setattr" and
75
- c .getArg ( 0 ) = self and
76
- self .getId ( ) = "self"
77
- )
73
+ exists ( Call c , Name setattr , Name self , Function method |
74
+ (
75
+ method .getScope ( ) = this .getPyClass ( ) or
76
+ method .getScope ( ) = this .getASuperType ( ) .getPyClass ( )
77
+ ) and
78
+ c .getScope ( ) = method and
79
+ c .getFunc ( ) = setattr and
80
+ setattr .getId ( ) = "setattr" and
81
+ c .getArg ( 0 ) = self and
82
+ self .getId ( ) = "self"
83
+ )
78
84
}
79
85
80
- predicate interestingUndefined ( SelfAttributeRead a ) {
81
- exists ( string name | name = a .getName ( ) |
82
- interestingContext ( a , name ) and
83
- not this .definedInBlock ( a .getAFlowNode ( ) .getBasicBlock ( ) , name )
84
- )
85
- }
86
-
87
- private predicate interestingContext ( SelfAttributeRead a , string name ) {
88
- name = a .getName ( ) and
89
- this .ofInterest ( ) and
90
- this .getPyClass ( ) = a .getScope ( ) .getScope ( ) and
91
- not a .locallyDefined ( ) and
92
- not a .guardedByHasattr ( ) and
93
- a .getScope ( ) .isPublic ( ) and
94
- not this .monkeyPatched ( name ) and
95
- not attribute_assigned_in_method ( lookupAttribute ( "setUp" ) , name )
96
- }
86
+ predicate interestingUndefined ( SelfAttributeRead a ) {
87
+ exists ( string name | name = a .getName ( ) |
88
+ interestingContext ( a , name ) and
89
+ not this .definedInBlock ( a .getAFlowNode ( ) .getBasicBlock ( ) , name )
90
+ )
91
+ }
97
92
98
- private predicate probablyAbstract ( ) {
99
- this .getName ( ) .matches ( "Abstract%" )
100
- or
101
- this .isAbstract ( )
102
- }
93
+ private predicate interestingContext ( SelfAttributeRead a , string name ) {
94
+ name = a .getName ( ) and
95
+ this .ofInterest ( ) and
96
+ this .getPyClass ( ) = a .getScope ( ) .getScope ( ) and
97
+ not a .locallyDefined ( ) and
98
+ not a .guardedByHasattr ( ) and
99
+ a .getScope ( ) .isPublic ( ) and
100
+ not this .monkeyPatched ( name ) and
101
+ not attribute_assigned_in_method ( lookupAttribute ( "setUp" ) , name )
102
+ }
103
103
104
- private pragma [ nomagic] predicate definitionInBlock ( BasicBlock b , string name ) {
105
- exists ( SelfAttributeStore sa |
106
- sa .getAFlowNode ( ) .getBasicBlock ( ) = b and sa .getName ( ) = name and sa .getClass ( ) = this .getPyClass ( )
107
- )
108
- or
109
- exists ( FunctionObject method | this .lookupAttribute ( _) = method |
110
- attribute_assigned_in_method ( method , name ) and
111
- b = method .getACall ( ) .getBasicBlock ( )
112
- )
113
- }
104
+ private predicate probablyAbstract ( ) {
105
+ this .getName ( ) .matches ( "Abstract%" )
106
+ or
107
+ this .isAbstract ( )
108
+ }
114
109
115
- private pragma [ nomagic] predicate definedInBlock ( BasicBlock b , string name ) {
116
- // manual specialisation: this is only called from interestingUndefined,
117
- // so we can push the context in from there, which must apply to a
118
- // SelfAttributeRead in the same scope
119
- exists ( SelfAttributeRead a |
120
- a . getScope ( ) = b . getScope ( ) and name = a . getName ( ) |
121
- interestingContext ( a , name )
122
- )
123
- and
124
- this . definitionInBlock ( b , name )
125
- or
126
- exists ( BasicBlock prev | this . definedInBlock ( prev , name ) and prev . getASuccessor ( ) = b )
127
- }
110
+ pragma [ nomagic]
111
+ private predicate definitionInBlock ( BasicBlock b , string name ) {
112
+ exists ( SelfAttributeStore sa |
113
+ sa . getAFlowNode ( ) . getBasicBlock ( ) = b and
114
+ sa . getName ( ) = name and
115
+ sa . getClass ( ) = this . getPyClass ( )
116
+ )
117
+ or
118
+ exists ( FunctionObject method | this . lookupAttribute ( _ ) = method |
119
+ attribute_assigned_in_method ( method , name ) and
120
+ b = method . getACall ( ) . getBasicBlock ( )
121
+ )
122
+ }
128
123
124
+ pragma [ nomagic]
125
+ private predicate definedInBlock ( BasicBlock b , string name ) {
126
+ // manual specialisation: this is only called from interestingUndefined,
127
+ // so we can push the context in from there, which must apply to a
128
+ // SelfAttributeRead in the same scope
129
+ exists ( SelfAttributeRead a | a .getScope ( ) = b .getScope ( ) and name = a .getName ( ) |
130
+ interestingContext ( a , name )
131
+ ) and
132
+ this .definitionInBlock ( b , name )
133
+ or
134
+ exists ( BasicBlock prev | this .definedInBlock ( prev , name ) and prev .getASuccessor ( ) = b )
135
+ }
129
136
}
130
137
131
-
132
138
private Object object_getattribute ( ) {
133
139
result .asBuiltin ( ) = theObjectType ( ) .asBuiltin ( ) .getMember ( "__getattribute__" )
134
140
}
135
141
136
- private predicate auto_name ( string name ) {
137
- name = "__class__" or name = "__dict__"
138
- }
139
-
142
+ private predicate auto_name ( string name ) { name = "__class__" or name = "__dict__" }
0 commit comments