mirror of
https://github.com/github/codeql.git
synced 2026-04-24 16:25:15 +02:00
JS: Avoid BarrierGuardNode's range from depending on Configuration
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user