@@ -910,6 +910,26 @@ private module Stdlib {
910910 */
911911 private string pathlibPathMethodExport ( ) { result in [ "as_posix" , "as_uri" ] }
912912
913+ /**
914+ * Flow for type presering mehtods.
915+ */
916+ private predicate typePreservingCall ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
917+ exists ( DataFlow:: AttrRead returnsPath | returnsPath .getAttributeName ( ) = pathlibPathMethod ( ) |
918+ nodeTo .( DataFlow:: CallCfgNode ) .getFunction ( ) = returnsPath and
919+ nodeFrom = returnsPath .getObject ( )
920+ )
921+ }
922+
923+ /**
924+ * Flow for type presering attributes.
925+ */
926+ private predicate typePreservingAttribute ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
927+ exists ( DataFlow:: AttrRead isPath | isPath .getAttributeName ( ) = pathlibPathAttribute ( ) |
928+ nodeTo = isPath and
929+ nodeFrom = isPath .getObject ( )
930+ )
931+ }
932+
913933 /**
914934 * Gets a reference to a `pathlib.Path` object.
915935 * This type tracker makes the monomorphic API use assumption.
@@ -920,26 +940,25 @@ private module Stdlib {
920940 result = pathlib ( ) .getMember ( pathlibPathConstructor ( ) ) .getACall ( )
921941 or
922942 // Type-preserving call
923- exists ( DataFlow:: AttrRead returnsPath , DataFlow:: TypeTracker t2 |
924- returnsPath .getAttributeName ( ) = pathlibPathMethod ( ) and
925- returnsPath .getObject ( ) .getALocalSource ( ) = pathlibPath ( t2 ) and
943+ exists ( DataFlow:: Node nodeFrom , DataFlow:: TypeTracker t2 |
944+ nodeFrom .getALocalSource ( ) = pathlibPath ( t2 ) and
926945 t2 .end ( )
927946 |
928947 t .start ( ) and
929- result . ( DataFlow :: CallCfgNode ) . getFunction ( ) = returnsPath
948+ typePreservingCall ( nodeFrom , result )
930949 )
931950 or
932951 // Type-preserving attribute
933- exists ( DataFlow:: AttrRead isPath , DataFlow:: TypeTracker t2 |
934- isPath .getAttributeName ( ) = pathlibPathAttribute ( ) and
935- isPath .getObject ( ) .getALocalSource ( ) = pathlibPath ( t2 ) and
952+ exists ( DataFlow:: Node nodeFrom , DataFlow:: TypeTracker t2 |
953+ nodeFrom .getALocalSource ( ) = pathlibPath ( t2 ) and
936954 t2 .end ( )
937955 |
938956 t .start ( ) and
939- result = isPath
957+ typePreservingAttribute ( nodeFrom , result )
940958 )
941959 or
942960 // Data injection
961+ // Special handling of the `/` operator
943962 exists ( BinaryExprNode slash , DataFlow:: Node pathOperand , DataFlow:: TypeTracker t2 |
944963 slash .getOp ( ) instanceof Div and
945964 pathOperand .asCfgNode ( ) = slash .getAnOperand ( ) and
@@ -950,6 +969,7 @@ private module Stdlib {
950969 result .asCfgNode ( ) = slash
951970 )
952971 or
972+ // standard case
953973 exists ( DataFlow:: AttrRead returnsPath , DataFlow:: TypeTracker t2 |
954974 returnsPath .getAttributeName ( ) = pathlibPathInjection ( ) and
955975 returnsPath .getObject ( ) .getALocalSource ( ) = pathlibPath ( t2 ) and
@@ -996,18 +1016,10 @@ private module Stdlib {
9961016 nodeTo .getALocalSource ( ) = pathlibPath ( ) and
9971017 (
9981018 // Type-preserving call
999- exists ( DataFlow:: AttrRead returnsPath |
1000- returnsPath .getAttributeName ( ) = pathlibPathMethod ( )
1001- |
1002- nodeTo .( DataFlow:: CallCfgNode ) .getFunction ( ) = returnsPath and
1003- nodeFrom = returnsPath .getObject ( )
1004- )
1019+ typePreservingCall ( nodeFrom , nodeTo )
10051020 or
10061021 // Type-preserving attribute
1007- exists ( DataFlow:: AttrRead isPath | isPath .getAttributeName ( ) = pathlibPathAttribute ( ) |
1008- nodeTo = isPath and
1009- nodeFrom = isPath .getObject ( )
1010- )
1022+ typePreservingAttribute ( nodeFrom , nodeTo )
10111023 )
10121024 or
10131025 // Data injection
0 commit comments