JS: Avoid BarrierGuardNode's range from depending on Configuration

This commit is contained in:
Asger F
2023-10-04 14:39:52 +02:00
parent e31ae3a1bf
commit 9fef8803ed

View File

@@ -161,7 +161,7 @@ abstract class Configuration extends string {
* Holds if the intermediate flow node `node` is prohibited.
*/
predicate isBarrier(DataFlow::Node node) {
exists(BarrierGuardNode guard |
exists(BarrierGuardNodeInternal guard |
isBarrierGuardInternal(this, guard) and
barrierGuardBlocksNode(guard, node, "")
)
@@ -201,7 +201,7 @@ abstract class Configuration extends string {
* Holds if flow with label `lbl` cannot flow into `node`.
*/
predicate isLabeledBarrier(DataFlow::Node node, FlowLabel lbl) {
exists(BarrierGuardNode guard |
exists(BarrierGuardNodeInternal guard |
isBarrierGuardInternal(this, guard) and
barrierGuardBlocksNode(guard, node, lbl)
)
@@ -282,10 +282,12 @@ abstract class Configuration extends string {
* `isBarrierGuard` or `AdditionalBarrierGuardNode`.
*/
pragma[nomagic]
private predicate isBarrierGuardInternal(Configuration cfg, BarrierGuardNode guard) {
private predicate isBarrierGuardInternal(Configuration cfg, BarrierGuardNodeInternal guard) {
cfg.isBarrierGuard(guard)
or
guard.(AdditionalBarrierGuardNode).appliesTo(cfg)
or
guard.(DerivedBarrierGuardNode).appliesTo(cfg)
}
/**
@@ -348,6 +350,8 @@ module FlowLabel {
FlowLabel taint() { result = "taint" }
}
abstract private class BarrierGuardNodeInternal extends DataFlow::Node { }
/**
* A node that can act as a barrier when appearing in a condition.
*
@@ -359,7 +363,7 @@ module FlowLabel {
* classes as precise as possible: if two subclasses of `BarrierGuardNode` overlap, their
* implementations of `blocks` will _both_ apply to any configuration that includes either of them.
*/
abstract class BarrierGuardNode extends DataFlow::Node {
abstract class BarrierGuardNode extends BarrierGuardNodeInternal {
/**
* Holds if this node blocks expression `e` provided it evaluates to `outcome`.
*
@@ -373,6 +377,20 @@ abstract class BarrierGuardNode extends DataFlow::Node {
predicate blocks(boolean outcome, Expr e, FlowLabel label) { none() }
}
/**
* Barrier guards derived from other barrier guards.
*/
abstract private class DerivedBarrierGuardNode extends BarrierGuardNodeInternal {
abstract predicate appliesTo(Configuration cfg);
/**
* Holds if this node blocks expression `e` from flow of type `label`, provided it evaluates to `outcome`.
*
* `label` is bound to the empty string if it blocks all flow labels.
*/
abstract predicate blocks(boolean outcome, Expr e, string label);
}
/**
* Holds if data flow node `guard` acts as a barrier for data flow.
*
@@ -380,24 +398,20 @@ abstract class BarrierGuardNode extends DataFlow::Node {
*/
pragma[nomagic]
private predicate barrierGuardBlocksExpr(
BarrierGuardNode guard, boolean outcome, Expr test, string label
BarrierGuardNodeInternal guard, boolean outcome, Expr test, string label
) {
guard.blocks(outcome, test) and label = ""
guard.(BarrierGuardNode).blocks(outcome, test) and label = ""
or
guard.blocks(outcome, test, label)
guard.(BarrierGuardNode).blocks(outcome, test, label)
or
// Handle labelled barrier guard functions specially, to avoid negative recursion
// through the non-abstract 3-argument version of blocks().
guard.(AdditionalBarrierGuardCall).internalBlocksLabel(outcome, test, label)
or
guard.(CallAgainstEqualityCheck).internalBlocksLabel(outcome, test, label)
guard.(DerivedBarrierGuardNode).blocks(outcome, test, label)
}
/**
* Holds if `guard` may block the flow of a value reachable through exploratory flow.
*/
pragma[nomagic]
private predicate barrierGuardIsRelevant(BarrierGuardNode guard) {
private predicate barrierGuardIsRelevant(BarrierGuardNodeInternal guard) {
exists(Expr e |
barrierGuardBlocksExpr(guard, _, e, _) and
isRelevantForward(e.flow(), _)
@@ -412,7 +426,7 @@ private predicate barrierGuardIsRelevant(BarrierGuardNode guard) {
*/
pragma[nomagic]
private predicate barrierGuardBlocksAccessPath(
BarrierGuardNode guard, boolean outcome, AccessPath ap, string label
BarrierGuardNodeInternal guard, boolean outcome, AccessPath ap, string label
) {
barrierGuardIsRelevant(guard) and
barrierGuardBlocksExpr(guard, outcome, ap.getAnInstance(), label)
@@ -425,7 +439,7 @@ private predicate barrierGuardBlocksAccessPath(
*/
pragma[nomagic]
private predicate barrierGuardBlocksSsaRefinement(
BarrierGuardNode guard, boolean outcome, SsaRefinementNode ref, string label
BarrierGuardNodeInternal guard, boolean outcome, SsaRefinementNode ref, string label
) {
barrierGuardIsRelevant(guard) and
guard.getEnclosingExpr() = ref.getGuard().getTest() and
@@ -441,7 +455,7 @@ private predicate barrierGuardBlocksSsaRefinement(
*/
pragma[nomagic]
private predicate barrierGuardUsedInCondition(
BarrierGuardNode guard, ConditionGuardNode cond, boolean outcome
BarrierGuardNodeInternal guard, ConditionGuardNode cond, boolean outcome
) {
barrierGuardIsRelevant(guard) and
outcome = cond.getOutcome() and
@@ -459,7 +473,9 @@ private predicate barrierGuardUsedInCondition(
* `label` is bound to the blocked label, or the empty string if all labels should be blocked.
*/
pragma[nomagic]
private predicate barrierGuardBlocksNode(BarrierGuardNode guard, DataFlow::Node nd, string label) {
private predicate barrierGuardBlocksNode(
BarrierGuardNodeInternal guard, DataFlow::Node nd, string label
) {
// 1) `nd` is a use of a refinement node that blocks its input variable
exists(SsaRefinementNode ref, boolean outcome |
nd = DataFlow::ssaDefinitionNode(ref) and
@@ -483,7 +499,7 @@ private predicate barrierGuardBlocksNode(BarrierGuardNode guard, DataFlow::Node
*/
pragma[nomagic]
private predicate barrierGuardBlocksEdge(
BarrierGuardNode guard, DataFlow::Node pred, DataFlow::Node succ, string label
BarrierGuardNodeInternal guard, DataFlow::Node pred, DataFlow::Node succ, string label
) {
exists(
SsaVariable input, SsaPhiNode phi, BasicBlock bb, ConditionGuardNode cond, boolean outcome
@@ -503,7 +519,7 @@ private predicate barrierGuardBlocksEdge(
* This predicate exists to get a better join-order for the `barrierGuardBlocksEdge` predicate above.
*/
pragma[noinline]
private BasicBlock getADominatedBasicBlock(BarrierGuardNode guard, ConditionGuardNode cond) {
private BasicBlock getADominatedBasicBlock(BarrierGuardNodeInternal guard, ConditionGuardNode cond) {
barrierGuardIsRelevant(guard) and
guard.getEnclosingExpr() = cond.getTest() and
cond.dominates(result)
@@ -518,7 +534,7 @@ private BasicBlock getADominatedBasicBlock(BarrierGuardNode guard, ConditionGuar
private predicate isBarrierEdgeRaw(Configuration cfg, DataFlow::Node pred, DataFlow::Node succ) {
cfg.isBarrierEdge(pred, succ)
or
exists(DataFlow::BarrierGuardNode guard |
exists(BarrierGuardNodeInternal guard |
cfg.isBarrierGuard(guard) and
barrierGuardBlocksEdge(guard, pred, succ, "")
)
@@ -548,7 +564,7 @@ private predicate isLabeledBarrierEdgeRaw(
) {
cfg.isBarrierEdge(pred, succ, label)
or
exists(DataFlow::BarrierGuardNode guard |
exists(BarrierGuardNodeInternal guard |
cfg.isBarrierGuard(guard) and
barrierGuardBlocksEdge(guard, pred, succ, label)
)
@@ -1843,7 +1859,7 @@ module PathGraph {
/**
* Gets a logical `and` expression, or parenthesized expression, that contains `guard`.
*/
private Expr getALogicalAndParent(BarrierGuardNode guard) {
private Expr getALogicalAndParent(BarrierGuardNodeInternal guard) {
barrierGuardIsRelevant(guard) and result = guard.asExpr()
or
result.(LogAndExpr).getAnOperand() = getALogicalAndParent(guard)
@@ -1854,7 +1870,7 @@ private Expr getALogicalAndParent(BarrierGuardNode guard) {
/**
* Gets a logical `or` expression, or parenthesized expression, that contains `guard`.
*/
private Expr getALogicalOrParent(BarrierGuardNode guard) {
private Expr getALogicalOrParent(BarrierGuardNodeInternal guard) {
barrierGuardIsRelevant(guard) and result = guard.asExpr()
or
result.(LogOrExpr).getAnOperand() = getALogicalOrParent(guard)
@@ -1879,7 +1895,7 @@ abstract class AdditionalBarrierGuardNode extends BarrierGuardNode {
*/
private class BarrierGuardFunction extends Function {
DataFlow::ParameterNode sanitizedParameter;
BarrierGuardNode guard;
BarrierGuardNodeInternal guard;
boolean guardOutcome;
string label;
int paramIndex;
@@ -1923,23 +1939,18 @@ private class BarrierGuardFunction extends Function {
)
}
/**
* Holds if this function applies to the flow in `cfg`.
*/
predicate appliesTo(Configuration cfg) { isBarrierGuardInternal(cfg, guard) }
}
/**
* A call that sanitizes an argument.
*/
private class AdditionalBarrierGuardCall extends AdditionalBarrierGuardNode, DataFlow::CallNode {
private class AdditionalBarrierGuardCall extends DerivedBarrierGuardNode, DataFlow::CallNode {
BarrierGuardFunction f;
AdditionalBarrierGuardCall() { f.isBarrierCall(this, _, _, _) }
override predicate blocks(boolean outcome, Expr e) { f.isBarrierCall(this, e, outcome, "") }
predicate internalBlocksLabel(boolean outcome, Expr e, DataFlow::FlowLabel label) {
override predicate blocks(boolean outcome, Expr e, string label) {
f.isBarrierCall(this, e, outcome, label)
}
@@ -1955,8 +1966,8 @@ private class AdditionalBarrierGuardCall extends AdditionalBarrierGuardNode, Dat
* }
* ```
*/
private class CallAgainstEqualityCheck extends AdditionalBarrierGuardNode {
DataFlow::BarrierGuardNode prev;
private class CallAgainstEqualityCheck extends DerivedBarrierGuardNode {
BarrierGuardNodeInternal prev;
boolean polarity;
CallAgainstEqualityCheck() {
@@ -1968,11 +1979,7 @@ private class CallAgainstEqualityCheck extends AdditionalBarrierGuardNode {
)
}
override predicate blocks(boolean outcome, Expr e) {
none() // handled by internalBlocksLabel
}
predicate internalBlocksLabel(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
override predicate blocks(boolean outcome, Expr e, string lbl) {
exists(boolean prevOutcome |
barrierGuardBlocksExpr(prev, prevOutcome, e, lbl) and
outcome = prevOutcome.booleanXor(polarity)