@@ -85,137 +85,6 @@ class SelfAttributeStore extends SelfAttribute {
8585
8686}
8787
88- private Object object_getattribute ( ) {
89- py_cmembers_versioned ( theObjectType ( ) , "__getattribute__" , result , major_version ( ) .toString ( ) )
90- }
91-
92- /** Helper class for UndefinedClassAttribute.ql and MaybeUndefinedClassAttribute.ql */
93- class CheckClass extends ClassObject {
94-
95- private predicate ofInterest ( ) {
96- not this .unknowableAttributes ( ) and
97- not this .getPyClass ( ) .isProbableMixin ( ) and
98- this .getPyClass ( ) .isPublic ( ) and
99- not this .getPyClass ( ) .getScope ( ) instanceof Function and
100- not this .probablyAbstract ( ) and
101- not this .declaresAttribute ( "__new__" ) and
102- not this .selfDictAssigns ( ) and
103- not this .lookupAttribute ( "__getattribute__" ) != object_getattribute ( ) and
104- not this .hasAttribute ( "__getattr__" ) and
105- not this .selfSetattr ( ) and
106- /* If class overrides object.__init__, but we can't resolve it to a Python function then give up */
107- forall ( ClassObject sup |
108- sup = this .getAnImproperSuperType ( ) and
109- sup .declaresAttribute ( "__init__" ) and
110- not sup = theObjectType ( ) |
111- sup .declaredAttribute ( "__init__" ) instanceof PyFunctionObject
112- )
113- }
114-
115- predicate alwaysDefines ( string name ) {
116- auto_name ( name ) or
117- this .hasAttribute ( name ) or
118- this .getAnImproperSuperType ( ) .assignedInInit ( name ) or
119- this .getMetaClass ( ) .assignedInInit ( name )
120- }
121-
122- predicate sometimesDefines ( string name ) {
123- this .alwaysDefines ( name ) or
124- exists ( SelfAttributeStore sa |
125- sa .getScope ( ) .getScope + ( ) = this .getAnImproperSuperType ( ) .getPyClass ( ) |
126- name = sa .getName ( )
127- )
128- }
129-
130- private predicate selfDictAssigns ( ) {
131- exists ( Assign a , SelfAttributeRead self_dict , Subscript sub |
132- self_dict .getName ( ) = "__dict__" and
133- (
134- self_dict = sub .getObject ( )
135- or
136- /* Indirect assignment via temporary variable */
137- exists ( SsaVariable v |
138- v .getAUse ( ) = sub .getObject ( ) .getAFlowNode ( ) and
139- v .getDefinition ( ) .( DefinitionNode ) .getValue ( ) = self_dict .getAFlowNode ( )
140- )
141- ) and
142- a .getATarget ( ) = sub and
143- exists ( FunctionObject meth | meth = this .lookupAttribute ( _) and a .getScope ( ) = meth .getFunction ( ) )
144- )
145- }
146-
147- pragma [ nomagic]
148- private predicate monkeyPatched ( string name ) {
149- exists ( Attribute a |
150- a .getCtx ( ) instanceof Store and
151- PointsTo:: points_to ( a .getObject ( ) .getAFlowNode ( ) , _, this , _, _) and a .getName ( ) = name
152- )
153- }
154-
155- private predicate selfSetattr ( ) {
156- exists ( Call c , Name setattr , Name self , Function method |
157- ( method .getScope ( ) = this .getPyClass ( ) or
158- method .getScope ( ) = this .getASuperType ( ) .getPyClass ( )
159- ) and
160- c .getScope ( ) = method and
161- c .getFunc ( ) = setattr and
162- setattr .getId ( ) = "setattr" and
163- c .getArg ( 0 ) = self and
164- self .getId ( ) = "self"
165- )
166- }
167-
168- predicate interestingUndefined ( SelfAttributeRead a ) {
169- exists ( string name | name = a .getName ( ) |
170- interestingContext ( a , name ) and
171- not this .definedInBlock ( a .getAFlowNode ( ) .getBasicBlock ( ) , name )
172- )
173- }
174-
175- private predicate interestingContext ( SelfAttributeRead a , string name ) {
176- name = a .getName ( ) and
177- this .ofInterest ( ) and
178- this .getPyClass ( ) = a .getScope ( ) .getScope ( ) and
179- not a .locallyDefined ( ) and
180- not a .guardedByHasattr ( ) and
181- a .getScope ( ) .isPublic ( ) and
182- not this .monkeyPatched ( name ) and
183- not attribute_assigned_in_method ( lookupAttribute ( "setUp" ) , name )
184- }
185-
186- private predicate probablyAbstract ( ) {
187- this .getName ( ) .matches ( "Abstract%" )
188- or
189- this .isAbstract ( )
190- }
191-
192- private pragma [ nomagic] predicate definitionInBlock ( BasicBlock b , string name ) {
193- exists ( SelfAttributeStore sa |
194- sa .getAFlowNode ( ) .getBasicBlock ( ) = b and sa .getName ( ) = name and sa .getClass ( ) = this .getPyClass ( )
195- )
196- or
197- exists ( FunctionObject method | this .lookupAttribute ( _) = method |
198- attribute_assigned_in_method ( method , name ) and
199- b = method .getACall ( ) .getBasicBlock ( )
200- )
201- }
202-
203- private pragma [ nomagic] predicate definedInBlock ( BasicBlock b , string name ) {
204- // manual specialisation: this is only called from interestingUndefined,
205- // so we can push the context in from there, which must apply to a
206- // SelfAttributeRead in the same scope
207- exists ( SelfAttributeRead a |
208- a .getScope ( ) = b .getScope ( ) and name = a .getName ( ) |
209- interestingContext ( a , name )
210- )
211- and
212- this .definitionInBlock ( b , name )
213- or
214- exists ( BasicBlock prev | this .definedInBlock ( prev , name ) and prev .getASuccessor ( ) = b )
215- }
216-
217- }
218-
21988private predicate attr_assigned_in_method_arg_n ( FunctionObject method , string name , int n ) {
22089 exists ( SsaVariable param |
22190 method .getFunction ( ) .getArg ( n ) .asName ( ) = param .getDefinition ( ) .getNode ( )
@@ -235,7 +104,3 @@ private predicate attr_assigned_in_method_arg_n(FunctionObject method, string na
235104predicate attribute_assigned_in_method ( FunctionObject method , string name ) {
236105 attr_assigned_in_method_arg_n ( method , name , 0 )
237106}
238-
239- private predicate auto_name ( string name ) {
240- name = "__class__" or name = "__dict__"
241- }
0 commit comments