@@ -10,36 +10,86 @@ import PropertyInjectionShared
1010private import semmle.javascript.dataflow.InferredTypes
1111
1212module UnvalidatedDynamicMethodCall {
13- private import DataFlow:: FlowLabel
13+ private newtype TFlowState =
14+ TTaint ( ) or
15+ TMaybeNonFunction ( ) or
16+ TMaybeFromProto ( )
17+
18+ /** A flow state to associate with a tracked value. */
19+ class FlowState extends TFlowState {
20+ /** Gets a string representation fo this flow state */
21+ string toString ( ) {
22+ this = TTaint ( ) and result = "taint"
23+ or
24+ this = TMaybeNonFunction ( ) and result = "maybe-non-function"
25+ or
26+ this = TMaybeFromProto ( ) and result = "maybe-from-proto"
27+ }
28+
29+ deprecated DataFlow:: FlowLabel toFlowLabel ( ) {
30+ this = TTaint ( ) and result .isTaint ( )
31+ or
32+ this = TMaybeNonFunction ( ) and result instanceof MaybeNonFunction
33+ or
34+ this = TMaybeFromProto ( ) and result instanceof MaybeFromProto
35+ }
36+ }
37+
38+ /** Predicates for working with flow states. */
39+ module FlowState {
40+ deprecated FlowState fromFlowLabel ( DataFlow:: FlowLabel label ) { result .toFlowLabel ( ) = label }
41+
42+ /** A tainted value. */
43+ FlowState taint ( ) { result = TTaint ( ) }
44+
45+ /**
46+ * A non-function value, obtained by reading from a tainted property name.
47+ */
48+ FlowState maybeNonFunction ( ) { result = TMaybeNonFunction ( ) }
49+
50+ /**
51+ * A value obtained from a prototype object while reading from a tainted property name.
52+ */
53+ FlowState maybeFromProto ( ) { result = TMaybeFromProto ( ) }
54+ }
1455
1556 /**
1657 * A data flow source for unvalidated dynamic method calls.
1758 */
1859 abstract class Source extends DataFlow:: Node {
1960 /**
20- * Gets the flow label relevant for this source.
61+ * Gets the flow state relevant for this source.
2162 */
22- DataFlow:: FlowLabel getFlowLabel ( ) { result = taint ( ) }
63+ FlowState getAFlowState ( ) { result = FlowState:: taint ( ) }
64+
65+ /** DEPRECATED. Use `getAFlowState()` instead. */
66+ deprecated DataFlow:: FlowLabel getFlowLabel ( ) { result = this .getAFlowState ( ) .toFlowLabel ( ) }
2367 }
2468
2569 /**
2670 * A data flow sink for unvalidated dynamic method calls.
2771 */
2872 abstract class Sink extends DataFlow:: Node {
2973 /**
30- * Gets the flow label relevant for this sink
74+ * Gets the flow state relevant for this sink
3175 */
32- abstract DataFlow:: FlowLabel getFlowLabel ( ) ;
76+ FlowState getAFlowState ( ) { result = FlowState:: taint ( ) }
77+
78+ /** DEPRECATED. Use `getAFlowState()` instead. */
79+ deprecated DataFlow:: FlowLabel getFlowLabel ( ) { result = this .getAFlowState ( ) .toFlowLabel ( ) }
3380 }
3481
3582 /**
3683 * A sanitizer for unvalidated dynamic method calls.
3784 */
3885 abstract class Sanitizer extends DataFlow:: Node {
3986 /**
40- * Gets the flow label blocked by this sanitizer.
87+ * Gets a flow state blocked by this sanitizer.
4188 */
42- DataFlow:: FlowLabel getFlowLabel ( ) { result .isTaint ( ) }
89+ FlowState getAFlowState ( ) { result = FlowState:: taint ( ) }
90+
91+ /** DEPRECATED. Use `getAFlowState()` instead. */
92+ deprecated DataFlow:: FlowLabel getFlowLabel ( ) { result = this .getAFlowState ( ) .toFlowLabel ( ) }
4393
4494 /**
4595 * DEPRECATED. Use sanitizer nodes instead.
@@ -64,16 +114,16 @@ module UnvalidatedDynamicMethodCall {
64114 predicate blocksExpr ( boolean outcome , Expr e ) { none ( ) }
65115
66116 /**
67- * Holds if this node acts as a barrier for `label `, blocking further flow from `e` if `this` evaluates to `outcome`.
117+ * Holds if this node acts as a barrier for `state `, blocking further flow from `e` if `this` evaluates to `outcome`.
68118 */
69- predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) { none ( ) }
119+ predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) { none ( ) }
70120
71121 /** DEPRECATED. Use `blocksExpr` instead. */
72122 deprecated predicate sanitizes ( boolean outcome , Expr e ) { this .blocksExpr ( outcome , e ) }
73123
74124 /** DEPRECATED. Use `blocksExpr` instead. */
75125 deprecated predicate sanitizes ( boolean outcome , Expr e , DataFlow:: FlowLabel label ) {
76- this .blocksExpr ( outcome , e , label )
126+ this .blocksExpr ( outcome , e , FlowState :: fromFlowLabel ( label ) )
77127 }
78128 }
79129
@@ -93,15 +143,15 @@ module UnvalidatedDynamicMethodCall {
93143 * A flow label describing values read from a user-controlled property that
94144 * may not be functions.
95145 */
96- abstract class MaybeNonFunction extends DataFlow:: FlowLabel {
146+ abstract deprecated class MaybeNonFunction extends DataFlow:: FlowLabel {
97147 MaybeNonFunction ( ) { this = "MaybeNonFunction" }
98148 }
99149
100150 /**
101151 * A flow label describing values read from a user-controlled property that
102152 * may originate from a prototype object.
103153 */
104- abstract class MaybeFromProto extends DataFlow:: FlowLabel {
154+ abstract deprecated class MaybeFromProto extends DataFlow:: FlowLabel {
105155 MaybeFromProto ( ) { this = "MaybeFromProto" }
106156 }
107157
@@ -134,14 +184,14 @@ module UnvalidatedDynamicMethodCall {
134184 )
135185 }
136186
137- override DataFlow :: FlowLabel getFlowLabel ( ) {
138- result instanceof MaybeNonFunction and
187+ override FlowState getAFlowState ( ) {
188+ result = FlowState :: maybeNonFunction ( ) and
139189 // don't flag if the type inference can prove that it is a function;
140190 // this complements the `FunctionCheck` sanitizer below: the type inference can
141191 // detect more checks locally, but doesn't provide inter-procedural reasoning
142192 this .analyze ( ) .getAType ( ) != TTFunction ( )
143193 or
144- result instanceof MaybeFromProto
194+ result = FlowState :: maybeFromProto ( )
145195 }
146196 }
147197
@@ -155,10 +205,10 @@ module UnvalidatedDynamicMethodCall {
155205
156206 FunctionCheck ( ) { TaintTracking:: isTypeofGuard ( astNode , operand , "function" ) }
157207
158- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
208+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) {
159209 outcome = astNode .getPolarity ( ) and
160210 e = operand and
161- label instanceof MaybeNonFunction
211+ state = FlowState :: maybeNonFunction ( )
162212 }
163213 }
164214
0 commit comments