Skip to content

Commit 341bacf

Browse files
committed
JS: Fix bug causing re-evaluation of cached barriers
1 parent 1cd00a1 commit 341bacf

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,9 @@ private predicate isBarrierGuardInternal(Configuration cfg, BarrierGuardNodeInte
287287
guard.(AdditionalBarrierGuardNode).appliesTo(cfg)
288288
or
289289
guard.(DerivedBarrierGuardNode).appliesTo(cfg)
290+
or
291+
cfg instanceof TaintTracking::Configuration and
292+
guard.(TaintTracking::AdditionalSanitizerGuardNode).appliesTo(cfg)
290293
}
291294

292295
/**
@@ -390,6 +393,12 @@ abstract private class DerivedBarrierGuardNode extends BarrierGuardNodeInternal
390393
abstract predicate blocks(boolean outcome, Expr e, string label);
391394
}
392395

396+
/**
397+
* Barrier guards derived from `AdditionalSanitizerGuard`
398+
*/
399+
private class BarrierGuardNodeFromAdditionalSanitizerGuard extends BarrierGuardNodeInternal instanceof TaintTracking::AdditionalSanitizerGuardNode
400+
{ }
401+
393402
/**
394403
* Holds if data flow node `guard` acts as a barrier for data flow.
395404
*
@@ -404,6 +413,10 @@ private predicate barrierGuardBlocksExpr(
404413
guard.(BarrierGuardNode).blocks(outcome, test, label)
405414
or
406415
guard.(DerivedBarrierGuardNode).blocks(outcome, test, label)
416+
or
417+
guard.(TaintTracking::AdditionalSanitizerGuardNode).sanitizes(outcome, test) and label = "taint"
418+
or
419+
guard.(TaintTracking::AdditionalSanitizerGuardNode).sanitizes(outcome, test, label)
407420
}
408421

409422
/**
@@ -534,7 +547,7 @@ private predicate isBarrierEdgeRaw(Configuration cfg, DataFlow::Node pred, DataF
534547
cfg.isBarrierEdge(pred, succ)
535548
or
536549
exists(BarrierGuardNodeInternal guard |
537-
cfg.isBarrierGuard(guard) and
550+
isBarrierGuardInternal(cfg, guard) and
538551
barrierGuardBlocksEdge(guard, pred, succ, "")
539552
)
540553
}
@@ -564,7 +577,7 @@ private predicate isLabeledBarrierEdgeRaw(
564577
cfg.isBarrierEdge(pred, succ, label)
565578
or
566579
exists(BarrierGuardNodeInternal guard |
567-
cfg.isBarrierGuard(guard) and
580+
isBarrierGuardInternal(cfg, guard) and
568581
barrierGuardBlocksEdge(guard, pred, succ, label)
569582
)
570583
}

javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,39 @@ module TaintTracking {
182182
* for analysis-specific taint sanitizer guards.
183183
*/
184184
cached
185-
abstract class AdditionalSanitizerGuardNode extends SanitizerGuardNode {
185+
abstract class AdditionalSanitizerGuardNode extends DataFlow::Node {
186+
// For backwards compatibility, this contains a copy of the SanitizerGuard interface,
187+
// but is does not inherit from it as that would cause re-evaluation of cached barriers.
188+
/**
189+
* Holds if this node blocks expression `e`, provided it evaluates to `outcome`.
190+
*/
191+
cached
192+
predicate blocks(boolean outcome, Expr e) { none() }
193+
194+
/**
195+
* Holds if this node sanitizes expression `e`, provided it evaluates
196+
* to `outcome`.
197+
*/
198+
cached
199+
abstract predicate sanitizes(boolean outcome, Expr e);
200+
201+
/**
202+
* Holds if this node blocks expression `e` from flow of type `label`, provided it evaluates to `outcome`.
203+
*/
204+
cached
205+
predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel label) {
206+
this.sanitizes(outcome, e) and label.isTaint()
207+
or
208+
this.sanitizes(outcome, e, label)
209+
}
210+
211+
/**
212+
* Holds if this node sanitizes expression `e`, provided it evaluates
213+
* to `outcome`.
214+
*/
215+
cached
216+
predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { none() }
217+
186218
/**
187219
* Holds if this guard applies to the flow in `cfg`.
188220
*/

0 commit comments

Comments
 (0)