99import javascript
1010private import internal.FlowSteps
1111
12+ private class PropertyName extends string {
13+ PropertyName ( ) { this = any ( DataFlow:: PropRef pr ) .getPropertyName ( ) }
14+ }
15+
1216/**
1317 * A description of a step on an inter-procedural data flow path.
1418 */
1519private newtype TStepSummary =
1620 LevelStep ( ) or
1721 CallStep ( ) or
18- ReturnStep ( )
22+ ReturnStep ( ) or
23+ StoreStep ( PropertyName prop ) or
24+ LoadStep ( PropertyName prop )
1925
2026/**
2127 * INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead.
@@ -64,6 +70,14 @@ module StepSummary {
6470 // Flow through an instance field between members of the same class
6571 DataFlow:: localFieldStep ( predNode , succ ) and
6672 summary = LevelStep ( )
73+ or
74+ exists ( string prop |
75+ basicStoreStep ( predNode , succ , prop ) and
76+ summary = StoreStep ( prop )
77+ or
78+ loadStep ( predNode , succ , prop ) and
79+ summary = LoadStep ( prop )
80+ )
6781 )
6882 }
6983
@@ -73,8 +87,22 @@ module StepSummary {
7387 * Appends a step summary onto a type-tracking summary.
7488 */
7589 TypeTracker append ( TypeTracker type , StepSummary summary ) {
76- not ( type .hasCall ( ) = true and summary .hasReturn ( ) = true ) and
77- result .hasCall ( ) = type .hasCall ( ) .booleanOr ( summary .hasCall ( ) )
90+ exists ( boolean hadCall , boolean hasCall , string oldProp , string newProp |
91+ hadCall = type .hasCall ( ) and
92+ oldProp = type .getProp ( )
93+ |
94+ not ( hadCall = true and summary .hasReturn ( ) = true ) and
95+ hasCall = hadCall .booleanOr ( summary .hasCall ( ) ) and
96+ (
97+ if summary instanceof StoreStep
98+ then oldProp = "" and summary = StoreStep ( newProp )
99+ else
100+ if summary instanceof LoadStep
101+ then summary = LoadStep ( oldProp ) and newProp = ""
102+ else newProp = oldProp
103+ ) and
104+ result = MkTypeTracker ( hasCall , newProp )
105+ )
78106 }
79107
80108 /**
@@ -83,12 +111,27 @@ module StepSummary {
83111 * Prepends a step summary before a backwards type-tracking summary.
84112 */
85113 TypeBackTracker prepend ( StepSummary summary , TypeBackTracker type ) {
86- not ( type .hasReturn ( ) = true and summary .hasCall ( ) = true ) and
87- result .hasReturn ( ) = type .hasReturn ( ) .booleanOr ( summary .hasReturn ( ) )
114+ exists ( boolean hadReturn , boolean hasReturn , string oldProp , string newProp |
115+ hadReturn = type .hasReturn ( ) and
116+ oldProp = type .getProp ( )
117+ |
118+ not ( hadReturn = true and summary .hasCall ( ) = true ) and
119+ hasReturn = hadReturn .booleanOr ( summary .hasReturn ( ) ) and
120+ (
121+ if summary instanceof StoreStep
122+ then summary = StoreStep ( oldProp ) and newProp = ""
123+ else
124+ if summary instanceof LoadStep
125+ then oldProp = "" and summary = LoadStep ( newProp )
126+ else newProp = oldProp
127+ ) and
128+ result = MkTypeBackTracker ( hasReturn , newProp )
129+ )
88130 }
89131}
90132
91- private newtype TTypeTracker = MkTypeTracker ( Boolean hasCall )
133+ private newtype TTypeTracker =
134+ MkTypeTracker ( Boolean hasCall , string prop ) { prop = "" or prop instanceof PropertyName }
92135
93136/**
94137 * EXPERIMENTAL.
@@ -112,7 +155,7 @@ private newtype TTypeTracker = MkTypeTracker(Boolean hasCall)
112155 * )
113156 * }
114157 *
115- * DataFlow::SourceNode myType() { result = myType(_ ) }
158+ * DataFlow::SourceNode myType() { result = myType(DataFlow::TypeTracker::end() ) }
116159 * ```
117160 *
118161 * To track values backwards, which can be useful for tracking
@@ -121,28 +164,41 @@ private newtype TTypeTracker = MkTypeTracker(Boolean hasCall)
121164class TypeTracker extends TTypeTracker {
122165 Boolean hasCall ;
123166
124- TypeTracker ( ) { this = MkTypeTracker ( hasCall ) }
167+ string prop ;
168+
169+ TypeTracker ( ) { this = MkTypeTracker ( hasCall , prop ) }
125170
126171 string toString ( ) {
127- hasCall = true and result = "type tracker with call steps"
128- or
129- hasCall = false and result = "type tracker without call steps"
172+ exists ( string withCall , string withProp |
173+ ( if hasCall = true then withCall = "with" else withCall = "without" ) and
174+ ( if prop != "" then withProp = " with property " + prop else withProp = "" ) and
175+ result = "type tracker " + withCall + " call steps" + withProp
176+ )
130177 }
131178
132179 /**
133180 * Holds if this is the starting point of type tracking.
134181 */
135- predicate start ( ) { hasCall = false }
182+ predicate start ( ) { hasCall = false and prop = "" }
183+
184+ predicate end ( ) { prop = "" }
136185
137186 /**
138187 * INTERNAL. DO NOT USE.
139188 *
140189 * Holds if this type has been tracked into a call.
141190 */
142191 boolean hasCall ( ) { result = hasCall }
192+
193+ string getProp ( ) { result = prop }
143194}
144195
145- private newtype TTypeBackTracker = MkTypeBackTracker ( Boolean hasReturn )
196+ module TypeTracker {
197+ TypeTracker end ( ) { result .end ( ) }
198+ }
199+
200+ private newtype TTypeBackTracker =
201+ MkTypeBackTracker ( Boolean hasReturn , string prop ) { prop = "" or prop instanceof PropertyName }
146202
147203/**
148204 * EXPERIMENTAL.
@@ -168,29 +224,41 @@ private newtype TTypeBackTracker = MkTypeBackTracker(Boolean hasReturn)
168224 * )
169225 * }
170226 *
171- * DataFlow::SourceNode myCallback() { result = myCallback(_ ) }
227+ * DataFlow::SourceNode myCallback() { result = myCallback(DataFlow::TypeBackTracker::end() ) }
172228 * ```
173229 */
174230class TypeBackTracker extends TTypeBackTracker {
175231 Boolean hasReturn ;
176232
177- TypeBackTracker ( ) { this = MkTypeBackTracker ( hasReturn ) }
233+ string prop ;
234+
235+ TypeBackTracker ( ) { this = MkTypeBackTracker ( hasReturn , prop ) }
178236
179237 string toString ( ) {
180- hasReturn = true and result = "type back-tracker with return steps"
181- or
182- hasReturn = false and result = "type back-tracker without return steps"
238+ exists ( string withReturn , string withProp |
239+ ( if hasReturn = true then withReturn = "with" else withReturn = "without" ) and
240+ ( if prop != "" then withProp = " with property " + prop else withProp = "" ) and
241+ result = "type back-tracker " + withReturn + " return steps" + withProp
242+ )
183243 }
184244
185245 /**
186246 * Holds if this is the starting point of type tracking.
187247 */
188- predicate start ( ) { hasReturn = false }
248+ predicate start ( ) { hasReturn = false and prop = "" }
249+
250+ predicate end ( ) { prop = "" }
189251
190252 /**
191253 * INTERNAL. DO NOT USE.
192254 *
193255 * Holds if this type has been back-tracked into a call through return edge.
194256 */
195257 boolean hasReturn ( ) { result = hasReturn }
258+
259+ string getProp ( ) { result = prop }
260+ }
261+
262+ module TypeBackTracker {
263+ TypeBackTracker end ( ) { result .end ( ) }
196264}
0 commit comments