@@ -661,7 +661,7 @@ module InterModulePointsTo {
661661 imp = def .getDefiningNode ( ) and
662662 PointsToInternal:: pointsTo ( imp .getModule ( ) , context , mod , _) and
663663 name = def .getSourceVariable ( ) .getName ( ) and
664- module_exports_boolean ( mod , name ) = true and
664+ moduleExportsBoolean ( mod , name ) = true and
665665 mod .attribute ( name , value , orig ) and
666666 origin = orig .fix ( imp )
667667 )
@@ -679,7 +679,7 @@ module InterModulePointsTo {
679679 var = def .getInput ( ) and
680680 exists ( ModuleObjectInternal mod |
681681 PointsToInternal:: pointsTo ( def .getDefiningNode ( ) .( ImportStarNode ) .getModule ( ) , context , mod , _) |
682- module_exports_boolean ( mod , var .getSourceVariable ( ) .getName ( ) ) = false
682+ moduleExportsBoolean ( mod , var .getSourceVariable ( ) .getName ( ) ) = false
683683 or
684684 exists ( Module m , string name |
685685 m = mod .getSourceModule ( ) and name = var .getSourceVariable ( ) .getName ( ) |
@@ -698,52 +698,77 @@ module InterModulePointsTo {
698698 )
699699 }
700700
701- private predicate ofInterestInModule ( ModuleObjectInternal mod , string name ) {
702- exists ( ImportStarNode isn , Module m |
703- m = mod .getSourceModule ( ) and
704- isn .getScope ( ) = m and
705- exists ( EssaVariable var | var .getAUse ( ) = isn and var .getName ( ) = name )
701+ predicate ofInterestInExports ( ModuleObjectInternal mod , string name ) {
702+ exists ( ImportStarNode imp , ImportStarRefinement def |
703+ imp = def .getDefiningNode ( ) and
704+ PointsToInternal:: pointsTo ( imp .getModule ( ) , any ( Context ctx | ctx .isImport ( ) ) , mod , _) |
705+ def .getVariable ( ) .getName ( ) = "$" and
706+ ModuleAttributes:: attributePointsTo ( def .getInput ( ) .getDefinition ( ) , name , _, _)
707+ or
708+ def .getVariable ( ) .getName ( ) = name and not name = "$" and not name = "*"
706709 )
707- }
708-
709- private predicate ofInterestInExports ( ModuleObjectInternal mod , string name ) {
710- exists ( ModuleObjectInternal importer |
711- importsByImportStar ( importer , mod ) and
712- ofInterestInModule ( importer , name )
710+ or
711+ exists ( PackageObjectInternal package |
712+ ofInterestInExports ( package , name ) and
713+ package .getInitModule ( ) = mod
713714 )
714715 }
715716
716- boolean module_exports_boolean ( ModuleObjectInternal mod , string name ) {
717- ofInterestInExports ( mod , name ) and
717+ private boolean pythonModuleExportsBoolean ( PythonModuleObjectInternal mod , string name ) {
718718 exists ( Module src |
719719 src = mod .getSourceModule ( )
720720 |
721- if exists ( SsaVariable var | name = var .getId ( ) and var .getAUse ( ) = src .getANormalExit ( ) ) then
722- result = true
723- else (
724- exists ( ImportStarNode isn , ModuleObjectInternal imported |
725- isn .getScope ( ) = src and
726- PointsToInternal:: pointsTo ( isn .getModule ( ) , _, imported , _) and
727- result = module_exports_boolean ( imported , name )
728- )
721+ src .declaredInAll ( name ) and result = true
722+ or
723+ src .declaredInAll ( _) and not src .declaredInAll ( name ) and
724+ ofInterestInExports ( mod , name ) and result = false
725+ or
726+ not src .declaredInAll ( _) and
727+ exists ( ObjectInternal val |
728+ ModuleAttributes:: pointsToAtExit ( src , name , val , _) |
729+ val = ObjectInternal:: undefined ( ) and result = false
729730 or
730- not exists ( ImportStarNode isn | isn . getScope ( ) = src ) and result = false
731+ val != ObjectInternal :: undefined ( ) and result = true
731732 )
732733 )
733- or
734- ofInterestInExports ( mod , name ) and
734+ }
735+
736+ private boolean packageExportsBoolean ( PackageObjectInternal mod , string name ) {
735737 exists ( Folder folder |
736- mod .( PackageObjectInternal ) .hasNoInitModule ( ) and
737- folder = mod .( PackageObjectInternal ) .getFolder ( ) |
738- if ( exists ( folder .getChildContainer ( name ) ) or exists ( folder .getFile ( name + ".py" ) ) ) then
739- result = true
740- else
741- result = false
738+ folder = mod .getFolder ( ) |
739+ exportsSubmodule ( folder , name ) and result = true
740+ or
741+ not exportsSubmodule ( folder , name ) and result = moduleExportsBoolean ( mod .getInitModule ( ) , name )
742+ or
743+ mod .hasNoInitModule ( ) and not exportsSubmodule ( folder , name ) and
744+ ofInterestInExports ( mod , name ) and result = false
745+ )
746+ }
747+
748+ private predicate exportsSubmodule ( Folder folder , string name ) {
749+ name .regexpMatch ( "\\p{L}(\\p{L}|\\d|_)*" ) and
750+ (
751+ exists ( Folder child | child = folder .getChildContainer ( name ) )
752+ or
753+ exists ( folder .getFile ( name + ".py" ) )
742754 )
755+ }
756+
757+ boolean builtinModuleExportsBoolean ( BuiltinModuleObjectInternal mod , string name ) {
758+ exists ( Builtin bltn |
759+ bltn = mod .getBuiltin ( ) |
760+ exists ( bltn .getMember ( name ) ) and result = true
761+ or
762+ ofInterestInExports ( mod , name ) and not exists ( bltn .getMember ( name ) ) and result = false
763+ )
764+ }
765+
766+ boolean moduleExportsBoolean ( ModuleObjectInternal mod , string name ) {
767+ result = pythonModuleExportsBoolean ( mod , name )
743768 or
744- name = "__name__" and result = true
769+ result = packageExportsBoolean ( mod , name )
745770 or
746- exists ( mod . ( BuiltinModuleObjectInternal ) . getBuiltin ( ) . getMember ( name ) ) and result = true
771+ result = builtinModuleExportsBoolean ( mod , name )
747772 }
748773
749774}
@@ -1678,11 +1703,11 @@ module ModuleAttributes {
16781703 if exists ( varAtExit ( mod , name ) ) then (
16791704 PointsToInternal:: variablePointsTo ( varAtExit ( mod , name ) , any ( Context c | c .isImport ( ) ) , value , origin )
16801705 ) else (
1681- moduleAttributePointsTo ( moduleStateVarAtExit ( mod ) , name , value , origin )
1706+ attributePointsTo ( moduleStateVarAtExit ( mod ) , name , value , origin )
16821707 )
16831708 }
16841709
1685- private predicate moduleAttributePointsTo ( EssaVariable var , string name , ObjectInternal value , CfgOrigin origin ) {
1710+ predicate attributePointsTo ( EssaVariable var , string name , ObjectInternal value , CfgOrigin origin ) {
16861711 importStarPointsTo ( var .getDefinition ( ) , name , value , origin )
16871712 or
16881713 callsitePointsTo ( var .getDefinition ( ) , name , value , origin )
@@ -1693,18 +1718,20 @@ module ModuleAttributes {
16931718 pragma [ noinline]
16941719 private predicate importStarPointsTo ( ImportStarRefinement def , string name , ObjectInternal value , CfgOrigin origin ) {
16951720 def .getVariable ( ) .getName ( ) = "$" and
1696- exists ( ImportStarNode imp , ModuleObjectInternal mod , CfgOrigin orig |
1721+ exists ( ImportStarNode imp , ModuleObjectInternal mod |
16971722 imp = def .getDefiningNode ( ) and
1698- origin = orig . fix ( imp ) and
1699- PointsToInternal :: pointsTo ( imp . getModule ( ) , any ( Context ctx | ctx . isImport ( ) ) , mod , _ ) |
1723+ PointsToInternal :: pointsTo ( imp . getModule ( ) , any ( Context ctx | ctx . isImport ( ) ) , mod , _ )
1724+ |
17001725 /* Attribute from imported module */
1701- InterModulePointsTo:: module_exports_boolean ( mod , name ) = true and
1702- mod .attribute ( name , value , orig ) and
1703- not exists ( Variable v | v .getId ( ) = name and v .getScope ( ) = imp .getScope ( ) )
1726+ exists ( CfgOrigin orig |
1727+ InterModulePointsTo:: moduleExportsBoolean ( mod , name ) = true and
1728+ mod .attribute ( name , value , orig ) and origin = orig .fix ( imp ) and
1729+ not exists ( Variable v | v .getId ( ) = name and v .getScope ( ) = imp .getScope ( ) )
1730+ )
17041731 or
17051732 /* Retain value held before import */
1706- InterModulePointsTo:: module_exports_boolean ( mod , name ) = false and
1707- moduleAttributePointsTo ( def .getInput ( ) . getDefinition ( ) , name , value , origin )
1733+ InterModulePointsTo:: moduleExportsBoolean ( mod , name ) = false and
1734+ attributePointsTo ( def .getInput ( ) , name , value , origin )
17081735 )
17091736 }
17101737
@@ -1718,25 +1745,30 @@ module ModuleAttributes {
17181745 exists ( EssaVariable var , Function func , PointsToContext callee |
17191746 InterProceduralPointsTo:: callsite_calls_function ( def .getCall ( ) , _, func , callee , _) and
17201747 var = moduleStateVariable ( func .getANormalExit ( ) ) and
1721- moduleAttributePointsTo ( var , name , value , origin )
1748+ attributePointsTo ( var , name , value , origin )
17221749 )
17231750 }
17241751
1752+ /** Holds if the attribute name of the implicit '$' variable refers to `value` at the start of the scope.
1753+ * Since it cannot refer to any actual value, it is set to "undefined" for sub module names.
1754+ */
17251755 pragma [ noinline]
17261756 predicate scopeEntryPointsTo ( ScopeEntryDefinition def , string name , ObjectInternal value , CfgOrigin origin ) {
17271757 def .getVariable ( ) .getName ( ) = "$" and
1728- /* Transfer from another scope */
1729- exists ( EssaVariable var , PointsToContext outer |
1730- InterProceduralPointsTo:: scope_entry_value_transfer ( var , outer , def , _) and
1731- moduleAttributePointsTo ( var , name , value , origin )
1732- )
1733- or
1734- def .getVariable ( ) .getName ( ) = "$" and
1735- exists ( PackageObjectInternal package |
1736- package .getSourceModule ( ) = def .getScope ( ) and
1737- exists ( package .submodule ( name ) ) and
1758+ exists ( Module m |
1759+ def .getScope ( ) = m and
1760+ not exists ( EssaVariable named | named .getName ( ) = name and named .getScope ( ) = m ) and
1761+ not name = "$" and not name = "*" and
17381762 value = ObjectInternal:: undefined ( ) and
17391763 origin = CfgOrigin:: unknown ( )
1764+ |
1765+ m .isPackageInit ( ) and exists ( m .getPackage ( ) .getSubModule ( name ) )
1766+ or
1767+ not m .declaredInAll ( _) and
1768+ exists ( PythonModuleObjectInternal mod |
1769+ mod .getSourceModule ( ) = m and
1770+ InterModulePointsTo:: ofInterestInExports ( mod , name )
1771+ )
17401772 )
17411773 }
17421774
0 commit comments