@@ -88,15 +88,35 @@ abstract class Configuration extends string {
8888 /**
8989 * Holds if `source` is a relevant data flow source for this configuration.
9090 */
91- abstract predicate isSource ( DataFlow:: Node source ) ;
91+ predicate isSource ( DataFlow:: Node source ) {
92+ none ( )
93+ }
94+
95+ /**
96+ * Holds if `source` is a source of flow labelled with `lbl` that is relevant
97+ * for this configuration.
98+ */
99+ predicate isSource ( DataFlow:: Node source , FlowLabel lbl ) {
100+ none ( )
101+ }
92102
93103 /**
94104 * Holds if `sink` is a relevant data flow sink for this configuration.
95105 */
96- abstract predicate isSink ( DataFlow:: Node sink ) ;
106+ predicate isSink ( DataFlow:: Node sink ) {
107+ none ( )
108+ }
109+
110+ /**
111+ * Holds if `sink` is a sink of flow labelled with `lbl` that is relevant
112+ * for this configuration.
113+ */
114+ predicate isSink ( DataFlow:: Node sink , FlowLabel lbl ) {
115+ none ( )
116+ }
97117
98118 /**
99- * Holds if `source -> sink ` should be considered as a flow edge
119+ * Holds if `src -> trg ` should be considered as a flow edge
100120 * in addition to standard data flow edges.
101121 */
102122 predicate isAdditionalFlowStep ( DataFlow:: Node src , DataFlow:: Node trg ) { none ( ) }
@@ -105,14 +125,22 @@ abstract class Configuration extends string {
105125 * INTERNAL: This predicate should not normally be used outside the data flow
106126 * library.
107127 *
108- * Holds if `source -> sink ` should be considered as a flow edge
128+ * Holds if `src -> trg ` should be considered as a flow edge
109129 * in addition to standard data flow edges, with `valuePreserving`
110130 * indicating whether the step preserves values or just taintedness.
111131 */
112132 predicate isAdditionalFlowStep ( DataFlow:: Node src , DataFlow:: Node trg , boolean valuePreserving ) {
113133 isAdditionalFlowStep ( src , trg ) and valuePreserving = true
114134 }
115135
136+ /**
137+ * Holds if `src -> trg` is a flow edge converting flow with label `inlbl` to
138+ * flow with label `outlbl`.
139+ */
140+ predicate isAdditionalFlowStep ( DataFlow:: Node src , DataFlow:: Node trg , FlowLabel inlbl , FlowLabel outlbl ) {
141+ none ( )
142+ }
143+
116144 /**
117145 * Holds if the intermediate flow node `node` is prohibited.
118146 */
@@ -128,6 +156,11 @@ abstract class Configuration extends string {
128156 */
129157 predicate isBarrier ( DataFlow:: Node src , DataFlow:: Node trg ) { none ( ) }
130158
159+ /**
160+ * Holds if flow with label `lbl` cannot flow from `src` to `trg`.
161+ */
162+ predicate isBarrier ( DataFlow:: Node src , DataFlow:: Node trg , FlowLabel lbl ) { none ( ) }
163+
131164 /**
132165 * Holds if data flow node `guard` can act as a barrier when appearing
133166 * in a condition.
@@ -142,7 +175,7 @@ abstract class Configuration extends string {
142175 * Holds if data may flow from `source` to `sink` for this configuration.
143176 */
144177 predicate hasFlow ( DataFlow:: Node source , DataFlow:: Node sink ) {
145- isSource ( _, this ) and isSink ( _, this ) and
178+ isSource ( _, this , _ ) and isSink ( _, this , _ ) and
146179 exists ( SourcePathNode flowsource , SinkPathNode flowsink |
147180 hasPathFlow ( flowsource , flowsink ) and
148181 source = flowsource .getNode ( ) and
@@ -176,6 +209,34 @@ abstract class Configuration extends string {
176209 }
177210}
178211
212+ /**
213+ * A label describing the kind of information tracked by a flow configuration.
214+ *
215+ * There are two standard labels "data" and "taint", the former describing values
216+ * that directly originate from a flow source, the latter values that are derived
217+ * from a flow source via one or more transformations (such as string operations).
218+ */
219+ abstract class FlowLabel extends string {
220+ bindingset [ this ] FlowLabel ( ) { any ( ) }
221+ }
222+
223+ module FlowLabel {
224+ private class StandardFlowLabel extends FlowLabel {
225+ StandardFlowLabel ( ) { this = "data" or this = "taint" }
226+ }
227+
228+ /**
229+ * Gets the standard flow label for describing values that directly originate from a flow source.
230+ */
231+ FlowLabel data ( ) { result = "data" }
232+
233+ /**
234+ * Gets the standard flow label for describing values that are influenced ("tainted") by a flow
235+ * source, but not necessarily directly derived from it.
236+ */
237+ FlowLabel taint ( ) { result = "taint" }
238+ }
239+
179240/**
180241 * A node that can act as a barrier when appearing in a condition.
181242 *
@@ -353,9 +414,10 @@ private predicate basicFlowStep(DataFlow::Node pred, DataFlow::Node succ, PathSu
353414 isRelevantForward ( pred , cfg ) and
354415 (
355416 // Local flow
356- exists ( boolean valuePreserving |
357- localFlowStep ( pred , succ , cfg , valuePreserving ) and
358- summary = PathSummary:: level ( valuePreserving )
417+ exists ( FlowLabel predlbl , FlowLabel succlbl |
418+ localFlowStep ( pred , succ , cfg , predlbl , succlbl ) and
419+ not cfg .isBarrier ( pred , succ , predlbl ) and
420+ summary = MkPathSummary ( false , false , predlbl , succlbl )
359421 )
360422 or
361423 // Flow through properties of objects
@@ -393,15 +455,21 @@ private predicate exploratoryFlowStep(DataFlow::Node pred, DataFlow::Node succ,
393455/**
394456 * Holds if `nd` is a source node for configuration `cfg`.
395457 */
396- private predicate isSource ( DataFlow:: Node nd , DataFlow:: Configuration cfg ) {
397- cfg .isSource ( nd ) or nd .( AdditionalSource ) .isSourceFor ( cfg )
458+ private predicate isSource ( DataFlow:: Node nd , DataFlow:: Configuration cfg , FlowLabel lbl ) {
459+ ( cfg .isSource ( nd ) or nd .( AdditionalSource ) .isSourceFor ( cfg ) ) and
460+ lbl = FlowLabel:: data ( )
461+ or
462+ cfg .isSource ( nd , lbl )
398463}
399464
400465/**
401466 * Holds if `nd` is a sink node for configuration `cfg`.
402467 */
403- private predicate isSink ( DataFlow:: Node nd , DataFlow:: Configuration cfg ) {
404- cfg .isSink ( nd ) or nd .( AdditionalSink ) .isSinkFor ( cfg )
468+ private predicate isSink ( DataFlow:: Node nd , DataFlow:: Configuration cfg , FlowLabel lbl ) {
469+ ( cfg .isSink ( nd ) or nd .( AdditionalSink ) .isSinkFor ( cfg ) ) and
470+ lbl = any ( FlowLabel f )
471+ or
472+ cfg .isSink ( nd , lbl )
405473}
406474
407475/**
@@ -410,7 +478,7 @@ private predicate isSink(DataFlow::Node nd, DataFlow::Configuration cfg) {
410478 * No call/return matching is done, so this is a relatively coarse over-approximation.
411479 */
412480private predicate isRelevantForward ( DataFlow:: Node nd , DataFlow:: Configuration cfg ) {
413- isSource ( nd , cfg )
481+ isSource ( nd , cfg , _ )
414482 or
415483 exists ( DataFlow:: Node mid |
416484 isRelevantForward ( mid , cfg ) and exploratoryFlowStep ( mid , nd , cfg )
@@ -424,7 +492,7 @@ private predicate isRelevantForward(DataFlow::Node nd, DataFlow::Configuration c
424492 */
425493private predicate isRelevant ( DataFlow:: Node nd , DataFlow:: Configuration cfg ) {
426494 isRelevantForward ( nd , cfg ) and
427- isSink ( nd , cfg )
495+ isSink ( nd , cfg , _ )
428496 or
429497 exists ( DataFlow:: Node mid |
430498 isRelevant ( mid , cfg ) and
@@ -527,7 +595,7 @@ private predicate reachableFromStoreBase(string prop, DataFlow::Node rhs, DataFl
527595 exists ( DataFlow:: Node mid , PathSummary oldSummary , PathSummary newSummary |
528596 reachableFromStoreBase ( prop , rhs , mid , cfg , oldSummary ) and
529597 flowStep ( mid , cfg , nd , newSummary ) and
530- newSummary .valuePreserving ( ) = true and
598+ newSummary .getEndLabel ( ) = FlowLabel :: data ( ) and
531599 summary = oldSummary .append ( newSummary )
532600 )
533601}
@@ -586,9 +654,11 @@ private predicate flowsTo(PathNode flowsource, DataFlow::Node source,
586654 */
587655private predicate reachableFromSource ( DataFlow:: Node nd , DataFlow:: Configuration cfg ,
588656 PathSummary summary ) {
589- isSource ( nd , cfg ) and
590- not cfg .isBarrier ( nd ) and
591- summary = PathSummary:: empty ( )
657+ exists ( FlowLabel lbl |
658+ isSource ( nd , cfg , lbl ) and
659+ not cfg .isBarrier ( nd ) and
660+ summary = MkPathSummary ( false , false , lbl , lbl )
661+ )
592662 or
593663 exists ( DataFlow:: Node pred , PathSummary oldSummary , PathSummary newSummary |
594664 reachableFromSource ( pred , cfg , oldSummary ) and
@@ -605,7 +675,7 @@ private predicate reachableFromSource(DataFlow::Node nd, DataFlow::Configuration
605675private predicate onPath ( DataFlow:: Node nd , DataFlow:: Configuration cfg ,
606676 PathSummary summary1 , PathSummary summary2 ) {
607677 reachableFromSource ( nd , cfg , summary1 ) and
608- isSink ( nd , cfg ) and
678+ isSink ( nd , cfg , summary1 . getEndLabel ( ) ) and
609679 not cfg .isBarrier ( nd ) and
610680 summary2 = PathSummary:: empty ( )
611681 or
@@ -691,7 +761,7 @@ class PathNode extends TPathNode {
691761 */
692762class SourcePathNode extends PathNode {
693763 SourcePathNode ( ) {
694- isSource ( nd , cfg )
764+ isSource ( nd , cfg , _ )
695765 }
696766}
697767
@@ -700,7 +770,7 @@ class SourcePathNode extends PathNode {
700770 */
701771class SinkPathNode extends PathNode {
702772 SinkPathNode ( ) {
703- isSink ( nd , cfg )
773+ isSink ( nd , cfg , _ )
704774 }
705775}
706776
0 commit comments