@@ -817,24 +817,7 @@ module InterProceduralPointsTo {
817817 PointsToInternal:: pointsTo ( f .getArg ( 0 ) , context , value , origin )
818818 )
819819 or
820- value = call_to_type ( f , context ) and
821- (
822- value .isBuiltin ( ) and origin = f
823- or
824- origin = value .getOrigin ( )
825- or
826- value = ObjectInternal:: unknownClass ( ) and origin = f
827- )
828- }
829-
830- pragma [ noinline]
831- private ObjectInternal call_to_type ( CallNode f , PointsToContext context ) {
832- count ( f .getArg ( _) ) = 1 and
833- call ( f , context , ObjectInternal:: builtin ( "type" ) ) and
834- exists ( ObjectInternal arg |
835- PointsToInternal:: pointsTo ( f .getArg ( 0 ) , context , arg , _) and
836- result = arg .getClass ( )
837- )
820+ Expressions:: typeCallPointsTo ( f , context , value , origin , _, _)
838821 }
839822
840823 /** Points-to for parameter. `def foo(param): ...`. */
@@ -1174,6 +1157,16 @@ module Expressions {
11741157 origin = call
11751158 }
11761159
1160+ pragma [ noinline]
1161+ predicate typeCallPointsTo ( CallNode call , PointsToContext context , ObjectInternal value , ControlFlowNode origin , ControlFlowNode arg , ObjectInternal argvalue ) {
1162+ not exists ( call .getArg ( 1 ) ) and
1163+ arg = call .getArg ( 0 ) and
1164+ InterProceduralPointsTo:: call ( call , context , ObjectInternal:: builtin ( "type" ) ) and
1165+ PointsToInternal:: pointsTo ( arg , context , argvalue , _) and
1166+ value = argvalue .getClass ( ) and
1167+ origin = CfgOrigin:: fromObject ( value ) .asCfgNodeOrHere ( call )
1168+ }
1169+
11771170 pragma [ noinline]
11781171 private predicate lenCallPointsTo ( CallNode call , PointsToContext context , ObjectInternal value , ControlFlowNode origin , ControlFlowNode arg , ObjectInternal argvalue ) {
11791172 len_call ( call , arg , context , argvalue ) and
@@ -1317,6 +1310,8 @@ module Expressions {
13171310 or
13181311 lenCallPointsTo ( expr , context , value , origin , subexpr , subvalue )
13191312 or
1313+ typeCallPointsTo ( expr , context , value , origin , subexpr , subvalue )
1314+ or
13201315 getattrPointsTo ( expr , context , value , origin , subexpr , subvalue )
13211316 or
13221317 value = ObjectInternal:: bool ( evaluatesTo ( expr , context , subexpr , subvalue ) ) and origin = expr
@@ -1754,7 +1749,9 @@ cached module Types {
17541749 cached boolean improperSubclass ( ObjectInternal sub , ObjectInternal sup ) {
17551750 sub = sup and result = true
17561751 or
1757- result = mroContains ( Types:: getMro ( sub ) , sup , 0 )
1752+ result = true and mroContains ( Types:: getMro ( sub ) , sup )
1753+ or
1754+ result = false and mroDoesnotContain ( Types:: getMro ( sub ) , sup , 0 )
17581755 or
17591756 result = tupleSubclass ( sub , sup , 0 )
17601757 }
@@ -1768,32 +1765,47 @@ cached module Types {
17681765 )
17691766 }
17701767
1771- private boolean mroContains ( ClassList mro , ClassObjectInternal sup , int n ) {
1768+ private predicate mroContains ( ClassList mro , ClassObjectInternal sup ) {
1769+ mro .contains ( sup )
1770+ or
1771+ exists ( ClassDecl item , ClassDecl sdecl |
1772+ item = mro .getAnItem ( ) .getClassDeclaration ( ) and
1773+ sdecl = sup .getClassDeclaration ( ) and
1774+ is_abstract_subclass ( item , sdecl )
1775+ )
1776+ }
1777+
1778+ private predicate mroDoesnotContain ( ClassList mro , ClassObjectInternal sup , int n ) {
17721779 exists ( ClassObjectInternal cls |
17731780 Expressions:: requireSubClass ( cls , sup ) and
17741781 mro = getMro ( cls )
17751782 )
17761783 and
17771784 (
1778- n = mro .length ( ) and result = false
1779- or
1780- mro .getItem ( n ) = sup and result = true
1781- or
1782- mro .getItem ( n ) = abc_to_concrete ( sup ) and result = true
1783- or
1784- mro .getItem ( n ) != sup and sup != AbstractBaseClass:: named ( "Iterable" ) and
1785- mro .getItem ( n ) != abc_to_concrete ( sup ) and result = mroContains ( mro , sup , n + 1 )
1786- or
1787- sup = AbstractBaseClass:: named ( "Iterable" ) and result = mro .getItem ( n ) .isIterableSubclass ( )
1785+ n = mro .length ( )
1786+ or
1787+ mroDoesnotContain ( mro , sup , n + 1 ) and
1788+ mro .getItem ( n ) != sup and
1789+ exists ( ClassDecl item , ClassDecl sdecl |
1790+ item = mro .getItem ( n ) .getClassDeclaration ( ) and
1791+ sdecl = sup .getClassDeclaration ( ) and
1792+ not is_abstract_subclass ( item , sdecl )
1793+ )
17881794 )
17891795 }
17901796
1791- private ClassObjectInternal abc_to_concrete ( ClassObjectInternal c ) {
1792- c = AbstractBaseClass:: named ( "Sequence" ) and result = ObjectInternal:: builtin ( "list" )
1797+ private predicate is_abstract_subclass ( ClassDecl cls , ClassDecl sup ) {
1798+ cls = Builtin:: builtin ( "list" ) and sup .isAbstractBaseClass ( "Sequence" )
1799+ or
1800+ cls = Builtin:: builtin ( "set" ) and sup .isAbstractBaseClass ( "Set" )
17931801 or
1794- c = AbstractBaseClass :: named ( "Set ") and result = ObjectInternal :: builtin ( "set ")
1802+ cls = Builtin :: builtin ( "dict ") and sup . isAbstractBaseClass ( "Mapping ")
17951803 or
1796- c = AbstractBaseClass:: named ( "Mapping" ) and result = ObjectInternal:: builtin ( "dict" )
1804+ cls = Builtin:: builtin ( "list" ) and sup .isAbstractBaseClass ( "Iterable" )
1805+ or
1806+ cls = Builtin:: builtin ( "set" ) and sup .isAbstractBaseClass ( "Iterable" )
1807+ or
1808+ cls = Builtin:: builtin ( "dict" ) and sup .isAbstractBaseClass ( "Iterable" )
17971809 }
17981810
17991811 cached boolean hasAttr ( ObjectInternal cls , string name ) {
@@ -1822,19 +1834,6 @@ cached module Types {
18221834}
18231835
18241836
1825- module AbstractBaseClass {
1826-
1827- ClassObjectInternal named ( string name ) {
1828- exists ( ModuleObjectInternal m |
1829- m .getName ( ) = "_abcoll"
1830- or
1831- m .getName ( ) = "_collections_abc"
1832- |
1833- m .attribute ( name , result , _)
1834- )
1835- }
1836- }
1837-
18381837module AttributePointsTo {
18391838
18401839 predicate pointsTo ( AttrNode f , Context context , ObjectInternal value , ControlFlowNode origin ) {
0 commit comments