@@ -423,10 +423,11 @@ cached module PointsToInternal {
423423
424424 /** Holds if ESSA edge refinement, `def`, refers to `(value, cls, origin)`. */
425425 private predicate ssa_filter_definition_points_to ( PyEdgeRefinement def , PointsToContext context , ObjectInternal value , CfgOrigin origin ) {
426- def .getSense ( ) = Conditionals:: testEvaluates ( def .getTest ( ) , def .getInput ( ) .getASourceUse ( ) , context , value , origin )
427- //exists(ControlFlowNode test, ControlFlowNode use |
428- // refinement_test(test, use, Conditionals::branchEvaluatesTo(test, use, context, value, origin.toCfgNode()), def)
429- //)
426+ def .getSense ( ) = ssa_filter_definition_bool ( def , context , value , origin )
427+ }
428+
429+ private boolean ssa_filter_definition_bool ( PyEdgeRefinement def , PointsToContext context , ObjectInternal value , CfgOrigin origin ) {
430+ result = Conditionals:: testEvaluates ( def .getTest ( ) , def .getInput ( ) .getASourceUse ( ) , context , value , origin )
430431 }
431432
432433 /** Holds if ESSA definition, `uniphi`, refers to `(value, origin)`. */
@@ -982,6 +983,7 @@ module Conditionals {
982983 result = evaluates ( expr , use , context , value , origin ) .booleanValue ( )
983984 }
984985
986+ pragma [ noinline]
985987 ObjectInternal evaluates ( ControlFlowNode expr , ControlFlowNode use , PointsToContext context , ObjectInternal val , ControlFlowNode origin ) {
986988 PointsToInternal:: pointsTo ( use , context , val , origin ) and
987989 pinode_test ( _, use ) and expr = use and result = val
@@ -1111,19 +1113,21 @@ module Conditionals {
11111113 }
11121114
11131115 //private
1114- predicate isinstance_call ( CallNode call , ControlFlowNode use , PointsToContext context , ObjectInternal val , ObjectInternal cls , ControlFlowNode origin ) {
1116+ predicate isinstance_call ( CallNode call , ControlFlowNode use , PointsToContext context , ObjectInternal val , ObjectInternal cls ) {
11151117 pinode_test_part ( call , use ) and
1116- PointsToInternal:: pointsTo ( call .getFunction ( ) , context , ObjectInternal:: builtin ( "isinstance" ) , _) and
1117- use = call .getArg ( 0 ) and
1118- PointsToInternal:: pointsTo ( use , context , val , origin ) and
1119- PointsToInternal:: pointsTo ( call .getArg ( 1 ) , context , cls , _)
1118+ exists ( ControlFlowNode func , ControlFlowNode arg1 |
1119+ call2 ( call , func , use , arg1 ) and
1120+ PointsToInternal:: pointsTo ( func , context , ObjectInternal:: builtin ( "isinstance" ) , _) and
1121+ PointsToInternal:: pointsTo ( use , context , val , _) and
1122+ PointsToInternal:: pointsTo ( arg1 , context , cls , _)
1123+ )
11201124 }
11211125
11221126 pragma [ nomagic]
11231127 //private
11241128 boolean isinstance_test_evaluates_boolean ( CallNode call , ControlFlowNode use , PointsToContext context , ObjectInternal val ) {
11251129 exists ( ObjectInternal cls |
1126- isinstance_call ( call , use , context , val , cls , _ ) |
1130+ isinstance_call ( call , use , context , val , cls ) |
11271131 result = Types:: improperSubclass ( val .getClass ( ) , cls )
11281132 or
11291133 val = ObjectInternal:: unknown ( ) and result = maybe ( )
@@ -1134,18 +1138,20 @@ module Conditionals {
11341138 )
11351139 }
11361140
1137- private predicate issubclass_call ( CallNode call , ControlFlowNode use , PointsToContext context , ObjectInternal val , ObjectInternal cls , ControlFlowNode origin ) {
1138- PointsToInternal:: pointsTo ( call .getFunction ( ) , context , ObjectInternal:: builtin ( "issubclass" ) , _) and
1139- use = call .getArg ( 0 ) and
1140- PointsToInternal:: pointsTo ( use , context , val , origin ) and
1141- PointsToInternal:: pointsTo ( call .getArg ( 1 ) , context , cls , _)
1141+ private predicate issubclass_call ( CallNode call , ControlFlowNode use , PointsToContext context , ObjectInternal val , ObjectInternal cls ) {
1142+ pinode_test_part ( call , use ) and
1143+ exists ( ControlFlowNode func , ControlFlowNode arg1 |
1144+ call2 ( call , func , use , arg1 ) and
1145+ PointsToInternal:: pointsTo ( func , context , ObjectInternal:: builtin ( "issubclass" ) , _) and
1146+ PointsToInternal:: pointsTo ( use , context , val , _) and
1147+ PointsToInternal:: pointsTo ( arg1 , context , cls , _)
1148+ )
11421149 }
11431150
11441151 pragma [ nomagic]
11451152 private boolean issubclass_test_evaluates_boolean ( CallNode call , ControlFlowNode use , PointsToContext context , ObjectInternal val ) {
1146- pinode_test_part ( call , use ) and
11471153 exists ( ObjectInternal cls |
1148- issubclass_call ( call , use , context , val , cls , _ ) |
1154+ issubclass_call ( call , use , context , val , cls ) |
11491155 result = Types:: improperSubclass ( val , cls )
11501156 or
11511157 val = ObjectInternal:: unknownClass ( ) and result = maybe ( )
@@ -1161,14 +1167,17 @@ module Conditionals {
11611167 predicate requireSubClass ( ObjectInternal sub , ObjectInternal sup ) {
11621168 sup != ObjectInternal:: unknownClass ( ) and
11631169 sub != ObjectInternal:: unknownClass ( ) and
1164- ( sup .isClass ( ) = true or sup instanceof TupleObjectInternal ) and
1165- (
1166- issubclass_call ( _, _, _, sub , sup , _) and sub .isClass ( ) = true
1170+ exists ( ObjectInternal sup_or_tuple |
1171+ issubclass_call ( _, _, _, sub , sup_or_tuple ) and sub .isClass ( ) = true
11671172 or
11681173 exists ( ObjectInternal val |
1169- isinstance_call ( _, _, _, val , sup , _ ) and
1174+ isinstance_call ( _, _, _, val , sup_or_tuple ) and
11701175 sub = val .getClass ( )
11711176 )
1177+ |
1178+ sup = sup_or_tuple
1179+ or
1180+ sup = sup_or_tuple .( TupleObjectInternal ) .getItem ( _)
11721181 )
11731182 }
11741183
@@ -1181,7 +1190,7 @@ module Conditionals {
11811190 hasattr_call ( _, _, _, val , name )
11821191 )
11831192 }
1184-
1193+
11851194 pragma [ noinline]
11861195 private boolean inequalityEvaluatesBoolean ( ControlFlowNode expr , ControlFlowNode use , PointsToContext context , ObjectInternal val ) {
11871196 pinode_test_part ( expr , use ) and
@@ -1462,16 +1471,21 @@ cached module Types {
14621471 cached boolean improperSubclass ( ObjectInternal sub , ObjectInternal sup ) {
14631472 sub = sup and result = true
14641473 or
1465- result = mroContains ( Types:: getMro ( sub ) , sup )
1466- // TO DO...
1467- // Handle tuples of classes
1474+ result = mroContains ( Types:: getMro ( sub ) , sup , 0 )
1475+ or
1476+ result = tupleSubclass ( sub , sup , 0 )
14681477 }
14691478
1470- private boolean mroContains ( ClassList mro , ObjectInternal sup ) {
1471- result = mroContains ( mro , sup , 0 )
1479+ private boolean tupleSubclass ( ObjectInternal cls , TupleObjectInternal tpl , int n ) {
1480+ Conditionals:: requireSubClass ( cls , tpl ) and
1481+ (
1482+ n = tpl .length ( ) and result = false
1483+ or
1484+ result = improperSubclass ( cls , tpl .getItem ( n ) ) .booleanOr ( tupleSubclass ( cls , tpl , n + 1 ) )
1485+ )
14721486 }
14731487
1474- private boolean mroContains ( ClassList mro , ObjectInternal sup , int n ) {
1488+ private boolean mroContains ( ClassList mro , ClassObjectInternal sup , int n ) {
14751489 exists ( ClassObjectInternal cls |
14761490 Conditionals:: requireSubClass ( cls , sup ) and
14771491 mro = getMro ( cls )
0 commit comments