@@ -883,6 +883,17 @@ private predicate fieldOrPropertyStore(Expr e, ContentSet c, Expr src, Expr q, b
883
883
)
884
884
)
885
885
)
886
+ or
887
+ // A write to a dynamic property
888
+ exists ( DynamicMemberAccess dma , AssignableDefinition def , DynamicProperty dp |
889
+ def .getTargetAccess ( ) = dma and
890
+ dp .getAnAccess ( ) = dma and
891
+ c .isDynamicProperty ( dp ) and
892
+ src = def .getSource ( ) and
893
+ q = dma .getQualifier ( ) and
894
+ e = def .getExpr ( ) and
895
+ postUpdate = true
896
+ )
886
897
}
887
898
888
899
/**
@@ -894,6 +905,18 @@ private predicate fieldOrPropertyRead(Expr e1, ContentSet c, FieldOrPropertyRead
894
905
c = e2 .getTarget ( ) .( FieldOrProperty ) .getContentSet ( )
895
906
}
896
907
908
+ /**
909
+ * Holds if `e2` is an expression that reads the dynamic property `c` from
910
+ * expression `e1`.
911
+ */
912
+ private predicate dynamicPropertyRead ( Expr e1 , ContentSet c , DynamicMemberRead e2 ) {
913
+ exists ( DynamicPropertyContent dpc |
914
+ e1 = e2 .getQualifier ( ) and
915
+ dpc .getAnAccess ( ) = e2 and
916
+ c .isDynamicProperty ( dpc .getName ( ) )
917
+ )
918
+ }
919
+
897
920
/**
898
921
* Holds if `ce` is a collection expression that adds `src` to the collection `ce`.
899
922
*/
@@ -1099,6 +1122,8 @@ private module Cached {
1099
1122
|
1100
1123
fieldOrPropertyRead ( e , _, read )
1101
1124
or
1125
+ dynamicPropertyRead ( e , _, read )
1126
+ or
1102
1127
arrayRead ( e , read )
1103
1128
)
1104
1129
)
@@ -1140,6 +1165,7 @@ private module Cached {
1140
1165
newtype TContent =
1141
1166
TFieldContent ( Field f ) { f .isUnboundDeclaration ( ) } or
1142
1167
TPropertyContent ( Property p ) { p .isUnboundDeclaration ( ) } or
1168
+ TDynamicPropertyContent ( DynamicProperty dp ) or
1143
1169
TElementContent ( ) or
1144
1170
TSyntheticFieldContent ( SyntheticField f ) or
1145
1171
TPrimaryConstructorParameterContent ( Parameter p ) {
@@ -1154,12 +1180,16 @@ private module Cached {
1154
1180
cached
1155
1181
newtype TContentSet =
1156
1182
TSingletonContent ( Content c ) { not c instanceof PropertyContent } or
1157
- TPropertyContentSet ( Property p ) { p .isUnboundDeclaration ( ) }
1183
+ TPropertyContentSet ( Property p ) { p .isUnboundDeclaration ( ) } or
1184
+ TDynamicPropertyContentSet ( DynamicProperty dp )
1158
1185
1159
1186
cached
1160
1187
newtype TContentApprox =
1161
1188
TFieldApproxContent ( string firstChar ) { firstChar = approximateFieldContent ( _) } or
1162
1189
TPropertyApproxContent ( string firstChar ) { firstChar = approximatePropertyContent ( _) } or
1190
+ TDynamicPropertyApproxContent ( string firstChar ) {
1191
+ firstChar = approximateDynamicPropertyContent ( _)
1192
+ } or
1163
1193
TElementApproxContent ( ) or
1164
1194
TSyntheticFieldApproxContent ( ) or
1165
1195
TPrimaryConstructorParameterApproxContent ( string firstChar ) {
@@ -2084,6 +2114,18 @@ class FieldOrProperty extends Assignable, Modifiable {
2084
2114
}
2085
2115
}
2086
2116
2117
+ /** A string that is a reference to a late-bound target of a dynamic member access. */
2118
+ class DynamicProperty extends string {
2119
+ private DynamicMemberAccess dma ;
2120
+
2121
+ DynamicProperty ( ) { this = dma .getLateBoundTargetName ( ) }
2122
+
2123
+ ContentSet getContentSet ( ) { result .isDynamicProperty ( this ) }
2124
+
2125
+ /** Gets an access of this dynamic property. */
2126
+ DynamicMemberAccess getAnAccess ( ) { result = dma }
2127
+ }
2128
+
2087
2129
private class InstanceFieldOrProperty extends FieldOrProperty {
2088
2130
InstanceFieldOrProperty ( ) { not this .isStatic ( ) }
2089
2131
}
@@ -2342,6 +2384,11 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
2342
2384
or
2343
2385
exactScope = false and
2344
2386
isSuccessor = true and
2387
+ dynamicPropertyRead ( e1 , _, e2 ) and
2388
+ scope = e2
2389
+ or
2390
+ exactScope = false and
2391
+ isSuccessor = true and
2345
2392
arrayRead ( e1 , e2 ) and
2346
2393
scope = e2
2347
2394
or
@@ -2474,6 +2521,8 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
2474
2521
exists ( ReadStepConfiguration x | hasNodePath ( x , node1 , node2 ) |
2475
2522
fieldOrPropertyRead ( node1 .asExpr ( ) , c , node2 .asExpr ( ) )
2476
2523
or
2524
+ dynamicPropertyRead ( node1 .asExpr ( ) , c , node2 .asExpr ( ) )
2525
+ or
2477
2526
node2 .asExpr ( ) .( AwaitExpr ) .getExpr ( ) = node1 .asExpr ( ) and
2478
2527
c = getResultContent ( )
2479
2528
)
@@ -3064,6 +3113,11 @@ class ContentApprox extends TContentApprox {
3064
3113
this = TPropertyApproxContent ( firstChar ) and result = "approximated property " + firstChar
3065
3114
)
3066
3115
or
3116
+ exists ( string firstChar |
3117
+ this = TDynamicPropertyApproxContent ( firstChar ) and
3118
+ result = "approximated dynamic property " + firstChar
3119
+ )
3120
+ or
3067
3121
this = TElementApproxContent ( ) and result = "element"
3068
3122
or
3069
3123
this = TSyntheticFieldApproxContent ( ) and result = "approximated synthetic field"
@@ -3095,6 +3149,11 @@ private string approximatePropertyContent(PropertyContent pc) {
3095
3149
result = pc .getProperty ( ) .getName ( ) .prefix ( 1 )
3096
3150
}
3097
3151
3152
+ /** Gets a string for approximating the name of a dynamic property. */
3153
+ private string approximateDynamicPropertyContent ( DynamicPropertyContent dpc ) {
3154
+ result = dpc .getName ( ) .prefix ( 1 )
3155
+ }
3156
+
3098
3157
/**
3099
3158
* Gets a string for approximating the name of a synthetic field corresponding
3100
3159
* to a primary constructor parameter.
@@ -3110,6 +3169,8 @@ ContentApprox getContentApprox(Content c) {
3110
3169
or
3111
3170
result = TPropertyApproxContent ( approximatePropertyContent ( c ) )
3112
3171
or
3172
+ result = TDynamicPropertyApproxContent ( approximateDynamicPropertyContent ( c ) )
3173
+ or
3113
3174
c instanceof ElementContent and result = TElementApproxContent ( )
3114
3175
or
3115
3176
c instanceof SyntheticFieldContent and result = TSyntheticFieldApproxContent ( )
0 commit comments