@@ -900,38 +900,46 @@ module InterProceduralPointsTo {
900900 /** Helper for parameter_points_to */
901901 pragma [ noinline]
902902 private predicate special_parameter_points_to ( ParameterDefinition def , PointsToContext context , ObjectInternal value , ControlFlowNode origin ) {
903+ /* Runtime: Just an unknown tuple (or dict for `**` args) */
903904 special_parameter_value ( def , value ) and
904905 context .isRuntime ( ) and
905906 origin = def .getDefiningNode ( )
906907 or
908+ /* A tuple constructed from positional arguments for a `*` parameter. */
907909 exists ( CallNode call , Function scope , PointsToContext caller , int offset , int length |
908- varargs_tuple ( call , scope , caller , context , offset , length ) and
910+ varargs_tuple ( call , caller , scope , context , offset , length ) and
909911 value = TVarargsTuple ( call , caller , offset , length ) and
910912 def .getScope ( ) = scope
911913 ) and
912914 origin = def .getDefiningNode ( )
913915 or
916+ /* A `*` parameter with no surplus positional arguments; an empty tuple */
914917 exists ( Function scope |
915918 varargs_empty_tuple ( scope , context ) and
916- value . ( BuiltinTupleObjectInternal ) . length ( ) = 0 and
919+ value = ObjectInternal :: emptyTuple ( ) and
917920 def .getScope ( ) = scope
918921 ) and
919922 origin = def .getDefiningNode ( )
920923 }
921924
922- predicate varargs_tuple ( CallNode call , Function scope , PointsToContext caller , PointsToContext callee , int startOffset , int length ) {
925+ /** Holds if `call` in context `caller` calls into the function scope `func` in context `callee` and
926+ * that the number of position arguments (including expansion of `*` argument) exceeds the number of positional arguments by
927+ * `length` and that the excess arguments start at `start`.
928+ */
929+ predicate varargs_tuple ( CallNode call , PointsToContext caller , Function scope , PointsToContext callee , int start , int length ) {
923930 exists ( int parameter_offset |
924931 callsite_calls_function ( call , caller , scope , callee , parameter_offset ) and
925- startOffset = scope .getPositionalParameterCount ( ) - parameter_offset and
926- length = positional_argument_count ( call , caller ) - startOffset and
932+ start = scope .getPositionalParameterCount ( ) - parameter_offset and
933+ length = positional_argument_count ( call , caller ) - start and
927934 length > 0
928935 )
929936 }
930937
931- predicate varargs_empty_tuple ( Function scope , PointsToContext callee ) {
938+ /** Holds if for function scope `func` in context `callee` the `*` parameter will hold the empty tuple. */
939+ predicate varargs_empty_tuple ( Function func , PointsToContext callee ) {
932940 exists ( CallNode call , PointsToContext caller , int parameter_offset |
933- callsite_calls_function ( call , caller , scope , callee , parameter_offset ) and
934- scope .getPositionalParameterCount ( ) - parameter_offset >= positional_argument_count ( call , caller )
941+ callsite_calls_function ( call , caller , func , callee , parameter_offset ) and
942+ func .getPositionalParameterCount ( ) - parameter_offset >= positional_argument_count ( call , caller )
935943 )
936944 }
937945
@@ -942,17 +950,21 @@ module InterProceduralPointsTo {
942950 p .isKwargs ( ) and value = TUnknownInstance ( ObjectInternal:: builtin ( "dict" ) )
943951 }
944952
945- predicate positional_argument_points_to ( CallNode call , int argument , PointsToContext caller , ObjectInternal value , ControlFlowNode origin ) {
946- PointsToInternal:: pointsTo ( call .getArg ( argument ) , caller , value , origin )
953+ /** Holds if the `n`th argument in call `call` with context `caller` points-to `value` from `origin`, including values in tuples
954+ * expanded by a `*` argument. For example, for the call `f('a', *(`x`,`y`))` the arguments are `('a', 'x', y')`
955+ */
956+ predicate positional_argument_points_to ( CallNode call , int n , PointsToContext caller , ObjectInternal value , ControlFlowNode origin ) {
957+ PointsToInternal:: pointsTo ( call .getArg ( n ) , caller , value , origin )
947958 or
948959 exists ( SequenceObjectInternal arg , int pos |
949960 pos = call .getNode ( ) .getPositionalArgumentCount ( ) and
950961 PointsToInternal:: pointsTo ( origin , caller , arg , _) and
951- value = arg .getItem ( argument - pos ) and
962+ value = arg .getItem ( n - pos ) and
952963 origin = call .getStarArg ( )
953964 )
954965 }
955966
967+ /** Gets the number of positional arguments including values in tuples expanded by a `*` argument.*/
956968 private int positional_argument_count ( CallNode call , PointsToContext caller ) {
957969 result = call .getNode ( ) .getPositionalArgumentCount ( ) and not exists ( call .getStarArg ( ) ) and caller .appliesTo ( call )
958970 or
@@ -963,6 +975,7 @@ module InterProceduralPointsTo {
963975 )
964976 }
965977
978+ /** Holds if the parameter definition `def` points-to `value` from `origin` given the context `context` */
966979 predicate positional_parameter_points_to ( ParameterDefinition def , PointsToContext context , ObjectInternal value , ControlFlowNode origin ) {
967980 exists ( CallNode call , int argument , PointsToContext caller , Function func , int offset |
968981 positional_argument_points_to ( call , argument , caller , value , origin ) and
@@ -971,6 +984,7 @@ module InterProceduralPointsTo {
971984 )
972985 }
973986
987+ /** Holds if the named `argument` given the context `caller` is transferred to the parameter `param` with conntext `callee` by a call. */
974988 cached predicate named_argument_transfer ( ControlFlowNode argument , PointsToContext caller , ParameterDefinition param , PointsToContext callee ) {
975989 exists ( CallNode call , Function func , int offset |
976990 callsite_calls_function ( call , caller , func , callee , offset )
@@ -982,6 +996,9 @@ module InterProceduralPointsTo {
982996 )
983997 }
984998
999+ /** Holds if the `call` with context `caller` calls the function `scope` in context `callee`
1000+ * and the offset from argument to parameter is `parameter_offset`
1001+ */
9851002 cached predicate callsite_calls_function ( CallNode call , PointsToContext caller , Function scope , PointsToContext callee , int parameter_offset ) {
9861003 exists ( ObjectInternal func |
9871004 callWithContext ( call , caller , func , callee ) and
0 commit comments