@@ -8,7 +8,45 @@ private import semmle.python.pointsto.MRO
88private import semmle.python.pointsto.PointsToContext
99private import semmle.python.types.Builtins
1010
11- class SpecificInstanceInternal extends TSpecificInstance , ObjectInternal {
11+ abstract class InstanceObject extends ObjectInternal {
12+
13+ pragma [ nomagic]
14+ override predicate attribute ( string name , ObjectInternal value , CfgOrigin origin ) {
15+ PointsToInternal:: attributeRequired ( this , name ) and
16+ (
17+ exists ( ObjectInternal cls_attr |
18+ this .getClass ( ) .( ClassObjectInternal ) .lookup ( name , cls_attr , _)
19+ |
20+ /* If class attribute is not a descriptor, that usually means it is some sort of
21+ * default value and likely overridden by an instance attribute. In that case
22+ * use `unknown` to signal that an attribute exists but to avoid false positives
23+ * f using the default value.
24+ */
25+ cls_attr .isDescriptor ( ) = false and value = ObjectInternal:: unknown ( ) and origin = CfgOrigin:: unknown ( )
26+ or
27+ cls_attr .isDescriptor ( ) = true and cls_attr .descriptorGetInstance ( this , value , origin )
28+ )
29+ or
30+ exists ( EssaVariable self , PythonFunctionObjectInternal init , Context callee |
31+ this .initializer ( init , callee ) and
32+ self_variable_reaching_init_exit ( self ) and
33+ self .getScope ( ) = init .getScope ( ) and
34+ AttributePointsTo:: variableAttributePointsTo ( self , callee , name , value , origin )
35+ )
36+ )
37+ }
38+
39+ abstract predicate initializer ( PythonFunctionObjectInternal init , Context callee ) ;
40+
41+ }
42+
43+ private predicate self_variable_reaching_init_exit ( EssaVariable self ) {
44+ BaseFlow:: reaches_exit ( self ) and
45+ self .getSourceVariable ( ) .( Variable ) .isSelf ( ) and
46+ self .getScope ( ) .getName ( ) = "__init__"
47+ }
48+
49+ class SpecificInstanceInternal extends TSpecificInstance , InstanceObject {
1250
1351 override string toString ( ) {
1452 result = this .getOrigin ( ) .getNode ( ) .toString ( )
@@ -76,35 +114,6 @@ class SpecificInstanceInternal extends TSpecificInstance, ObjectInternal {
76114 none ( )
77115 }
78116
79- pragma [ nomagic]
80- override predicate attribute ( string name , ObjectInternal value , CfgOrigin origin ) {
81- PointsToInternal:: attributeRequired ( this , name ) and
82- exists ( ObjectInternal cls_attr , CfgOrigin attr_orig |
83- this .getClass ( ) .( ClassObjectInternal ) .lookup ( name , cls_attr , attr_orig )
84- |
85- /* If class attribute is not a descriptor, that usually means it is some sort of
86- * default value and likely overridden by an instance attribute. In that case
87- * use `unknown` to signal that an attribute exists but to avoid false positives
88- * for due to using the default value.
89- */
90- cls_attr .isDescriptor ( ) = false and value = ObjectInternal:: unknown ( ) and origin = CfgOrigin:: unknown ( )
91- or
92- cls_attr .isDescriptor ( ) = true and cls_attr .descriptorGetInstance ( this , value , origin )
93- )
94- or
95- exists ( EssaVariable self , PythonFunctionObjectInternal init , Context callee |
96- BaseFlow:: reaches_exit ( self ) and
97- self .getSourceVariable ( ) .( Variable ) .isSelf ( ) and
98- self .getScope ( ) = init .getScope ( ) and
99- exists ( CallNode call , Context caller , ClassObjectInternal cls |
100- this = TSpecificInstance ( call , cls , caller ) and
101- callee .fromCall ( this .getOrigin ( ) , caller ) and
102- cls .lookup ( "__init__" , init , _)
103- ) and
104- AttributePointsTo:: variableAttributePointsTo ( self , callee , name , value , origin )
105- )
106- }
107-
108117 pragma [ noinline] override predicate attributesUnknown ( ) { any ( ) }
109118
110119 override predicate subscriptUnknown ( ) { any ( ) }
@@ -128,10 +137,18 @@ class SpecificInstanceInternal extends TSpecificInstance, ObjectInternal {
128137 result = lengthFromClass ( this .getClass ( ) )
129138 }
130139
140+ override predicate initializer ( PythonFunctionObjectInternal init , Context callee ) {
141+ exists ( CallNode call , Context caller , ClassObjectInternal cls |
142+ this = TSpecificInstance ( call , cls , caller ) and
143+ callee .fromCall ( this .getOrigin ( ) , caller ) and
144+ cls .lookup ( "__init__" , init , _)
145+ )
146+ }
147+
131148}
132149
133150
134- class SelfInstanceInternal extends TSelfInstance , ObjectInternal {
151+ class SelfInstanceInternal extends TSelfInstance , InstanceObject {
135152
136153 override string toString ( ) {
137154 result = "self instance of " + this .getClass ( ) .( ClassObjectInternal ) .getName ( )
@@ -201,17 +218,6 @@ class SelfInstanceInternal extends TSelfInstance, ObjectInternal {
201218 none ( )
202219 }
203220
204- pragma [ nomagic] override predicate attribute ( string name , ObjectInternal value , CfgOrigin origin ) {
205- PointsToInternal:: attributeRequired ( this , name ) and
206- exists ( ObjectInternal cls_attr , CfgOrigin attr_orig |
207- this .getClass ( ) .( ClassObjectInternal ) .lookup ( name , cls_attr , attr_orig )
208- |
209- cls_attr .isDescriptor ( ) = false and value = cls_attr and origin = attr_orig
210- or
211- cls_attr .isDescriptor ( ) = true and cls_attr .descriptorGetInstance ( this , value , origin )
212- )
213- }
214-
215221 pragma [ noinline] override predicate attributesUnknown ( ) { any ( ) }
216222
217223 override predicate subscriptUnknown ( ) { any ( ) }
@@ -234,6 +240,12 @@ class SelfInstanceInternal extends TSelfInstance, ObjectInternal {
234240 result = lengthFromClass ( this .getClass ( ) )
235241 }
236242
243+ override predicate initializer ( PythonFunctionObjectInternal init , Context callee ) {
244+ callee .isRuntime ( ) and
245+ init .getScope ( ) != this .getParameter ( ) .getScope ( ) and
246+ this .getClass ( ) .attribute ( "__init__" , init , _)
247+ }
248+
237249}
238250
239251/** Represents a value that has a known class, but no other information */
@@ -245,7 +257,6 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal {
245257
246258 /** The boolean value of this object, if it has one */
247259 override boolean booleanValue ( ) {
248- //result = this.getClass().instancesBooleanValue()
249260 result = maybe ( )
250261 }
251262
0 commit comments