@@ -753,7 +753,7 @@ predicate jumpStepNotSharedWithTypeTracker(Node nodeFrom, Node nodeTo) {
753753 * As of 2024-04-02 the type-tracking library only supports precise content, so there is
754754 * no reason to include steps for list content right now.
755755 */
756- predicate storeStepCommon ( Node nodeFrom , ContentSet c , Node nodeTo ) {
756+ predicate storeStepCommon ( Node nodeFrom , Content c , Node nodeTo ) {
757757 tupleStoreStep ( nodeFrom , c , nodeTo )
758758 or
759759 dictStoreStep ( nodeFrom , c , nodeTo )
@@ -767,29 +767,31 @@ predicate storeStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
767767 * Holds if data can flow from `nodeFrom` to `nodeTo` via an assignment to
768768 * content `c`.
769769 */
770- predicate storeStep ( Node nodeFrom , ContentSet c , Node nodeTo ) {
771- storeStepCommon ( nodeFrom , c , nodeTo )
772- or
773- listStoreStep ( nodeFrom , c , nodeTo )
774- or
775- setStoreStep ( nodeFrom , c , nodeTo )
776- or
777- attributeStoreStep ( nodeFrom , c , nodeTo )
778- or
779- matchStoreStep ( nodeFrom , c , nodeTo )
780- or
781- any ( Orm:: AdditionalOrmSteps es ) .storeStep ( nodeFrom , c , nodeTo )
770+ predicate storeStep ( Node nodeFrom , ContentSet cs , Node nodeTo ) {
771+ exists ( Content c | cs = singleton ( c ) |
772+ storeStepCommon ( nodeFrom , c , nodeTo )
773+ or
774+ listStoreStep ( nodeFrom , c , nodeTo )
775+ or
776+ setStoreStep ( nodeFrom , c , nodeTo )
777+ or
778+ attributeStoreStep ( nodeFrom , c , nodeTo )
779+ or
780+ matchStoreStep ( nodeFrom , c , nodeTo )
781+ or
782+ any ( Orm:: AdditionalOrmSteps es ) .storeStep ( nodeFrom , c , nodeTo )
783+ or
784+ synthStarArgsElementParameterNodeStoreStep ( nodeFrom , c , nodeTo )
785+ or
786+ synthDictSplatArgumentNodeStoreStep ( nodeFrom , c , nodeTo )
787+ or
788+ yieldStoreStep ( nodeFrom , c , nodeTo )
789+ or
790+ VariableCapture:: storeStep ( nodeFrom , c , nodeTo )
791+ )
782792 or
783- FlowSummaryImpl:: Private:: Steps:: summaryStoreStep ( nodeFrom .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
793+ FlowSummaryImpl:: Private:: Steps:: summaryStoreStep ( nodeFrom .( FlowSummaryNode ) .getSummaryNode ( ) , cs ,
784794 nodeTo .( FlowSummaryNode ) .getSummaryNode ( ) )
785- or
786- synthStarArgsElementParameterNodeStoreStep ( nodeFrom , c , nodeTo )
787- or
788- synthDictSplatArgumentNodeStoreStep ( nodeFrom , c , nodeTo )
789- or
790- yieldStoreStep ( nodeFrom , c , nodeTo )
791- or
792- VariableCapture:: storeStep ( nodeFrom , c , nodeTo )
793795}
794796
795797/**
@@ -985,7 +987,7 @@ predicate attributeStoreStep(Node nodeFrom, AttributeContent c, Node nodeTo) {
985987/**
986988 * Subset of `readStep` that should be shared with type-tracking.
987989 */
988- predicate readStepCommon ( Node nodeFrom , ContentSet c , Node nodeTo ) {
990+ predicate readStepCommon ( Node nodeFrom , Content c , Node nodeTo ) {
989991 subscriptReadStep ( nodeFrom , c , nodeTo )
990992 or
991993 iterableUnpackingReadStep ( nodeFrom , c , nodeTo )
@@ -994,21 +996,25 @@ predicate readStepCommon(Node nodeFrom, ContentSet c, Node nodeTo) {
994996/**
995997 * Holds if data can flow from `nodeFrom` to `nodeTo` via a read of content `c`.
996998 */
997- predicate readStep ( Node nodeFrom , ContentSet c , Node nodeTo ) {
998- readStepCommon ( nodeFrom , c , nodeTo )
999- or
1000- matchReadStep ( nodeFrom , c , nodeTo )
1001- or
1002- forReadStep ( nodeFrom , c , nodeTo )
1003- or
1004- attributeReadStep ( nodeFrom , c , nodeTo )
999+ predicate readStep ( Node nodeFrom , ContentSet cs , Node nodeTo ) {
1000+ exists ( Content c | cs = singleton ( c ) |
1001+ readStepCommon ( nodeFrom , c , nodeTo )
1002+ or
1003+ matchReadStep ( nodeFrom , c , nodeTo )
1004+ or
1005+ forReadStep ( nodeFrom , c , nodeTo )
1006+ or
1007+ attributeReadStep ( nodeFrom , c , nodeTo )
1008+ or
1009+ synthDictSplatParameterNodeReadStep ( nodeFrom , c , nodeTo )
1010+ or
1011+ VariableCapture:: readStep ( nodeFrom , c , nodeTo )
1012+ )
10051013 or
1006- FlowSummaryImpl:: Private:: Steps:: summaryReadStep ( nodeFrom .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
1014+ FlowSummaryImpl:: Private:: Steps:: summaryReadStep ( nodeFrom .( FlowSummaryNode ) .getSummaryNode ( ) , cs ,
10071015 nodeTo .( FlowSummaryNode ) .getSummaryNode ( ) )
10081016 or
1009- synthDictSplatParameterNodeReadStep ( nodeFrom , c , nodeTo )
1010- or
1011- VariableCapture:: readStep ( nodeFrom , c , nodeTo )
1017+ Conversions:: readStep ( nodeFrom , cs , nodeTo )
10121018}
10131019
10141020/** Data flows from a sequence to a subscript of the sequence. */
@@ -1064,23 +1070,68 @@ predicate attributeReadStep(Node nodeFrom, AttributeContent c, AttrRead nodeTo)
10641070 nodeTo .accesses ( nodeFrom , c .getAttribute ( ) )
10651071}
10661072
1073+ module Conversions {
1074+ private import semmle.python.Concepts
1075+
1076+ predicate decoderReadStep ( Node nodeFrom , ContentSet c , Node nodeTo ) {
1077+ exists ( Decoding decoding |
1078+ nodeFrom = decoding .getAnInput ( ) and
1079+ nodeTo = decoding .getOutput ( )
1080+ ) and
1081+ c .isAnyTupleOrDictionaryElement ( )
1082+ }
1083+
1084+ predicate encoderReadStep ( Node nodeFrom , ContentSet c , Node nodeTo ) {
1085+ exists ( Encoding encoding |
1086+ nodeFrom = encoding .getAnInput ( ) and
1087+ nodeTo = encoding .getOutput ( )
1088+ ) and
1089+ c .isAnyTupleOrDictionaryElement ( )
1090+ }
1091+
1092+ predicate formatReadStep ( Node nodeFrom , ContentSet c , Node nodeTo ) {
1093+ // % formatting
1094+ exists ( BinaryExprNode fmt | fmt = nodeTo .asCfgNode ( ) |
1095+ fmt .getOp ( ) instanceof Mod and
1096+ fmt .getRight ( ) = nodeFrom .asCfgNode ( )
1097+ ) and
1098+ c .isAnyTupleElement ( )
1099+ or
1100+ // format_map
1101+ // see https://docs.python.org/3/library/stdtypes.html#str.format_map
1102+ nodeTo .( MethodCallNode ) .calls ( _, "format_map" ) and
1103+ nodeTo .( MethodCallNode ) .getArg ( 0 ) = nodeFrom and
1104+ c .isAnyDictionaryElement ( )
1105+ }
1106+
1107+ predicate readStep ( Node nodeFrom , ContentSet c , Node nodeTo ) {
1108+ decoderReadStep ( nodeFrom , c , nodeTo )
1109+ or
1110+ encoderReadStep ( nodeFrom , c , nodeTo )
1111+ or
1112+ formatReadStep ( nodeFrom , c , nodeTo )
1113+ }
1114+ }
1115+
10671116/**
10681117 * Holds if values stored inside content `c` are cleared at node `n`. For example,
10691118 * any value stored inside `f` is cleared at the pre-update node associated with `x`
10701119 * in `x.f = newValue`.
10711120 */
1072- predicate clearsContent ( Node n , ContentSet c ) {
1073- matchClearStep ( n , c )
1074- or
1075- attributeClearStep ( n , c )
1076- or
1077- dictClearStep ( n , c )
1078- or
1079- FlowSummaryImpl:: Private:: Steps:: summaryClearsContent ( n .( FlowSummaryNode ) .getSummaryNode ( ) , c )
1080- or
1081- dictSplatParameterNodeClearStep ( n , c )
1121+ predicate clearsContent ( Node n , ContentSet cs ) {
1122+ exists ( Content c | cs = singleton ( c ) |
1123+ matchClearStep ( n , c )
1124+ or
1125+ attributeClearStep ( n , c )
1126+ or
1127+ dictClearStep ( n , c )
1128+ or
1129+ dictSplatParameterNodeClearStep ( n , c )
1130+ or
1131+ VariableCapture:: clearsContent ( n , c )
1132+ )
10821133 or
1083- VariableCapture :: clearsContent ( n , c )
1134+ FlowSummaryImpl :: Private :: Steps :: summaryClearsContent ( n . ( FlowSummaryNode ) . getSummaryNode ( ) , cs )
10841135}
10851136
10861137/**
0 commit comments