Skip to content

Commit 0b1e859

Browse files
committed
JS: Remove uses of AdditionalSanitizerGuardNode
1 parent c2abb0f commit 0b1e859

2 files changed

Lines changed: 57 additions & 49 deletions

File tree

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

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,44 @@ module TaintTracking {
173173
override DataFlow::FlowLabel getDefaultSourceLabel() { result.isTaint() }
174174
}
175175

176+
/**
177+
* A barrier guard that applies to all taint-tracking configurations.
178+
*
179+
* Note: For performance reasons, all subclasses of this class should be part
180+
* of the standard library. To define a query-specific barrier guard, instead override
181+
* `isBarrier` and use the `DataFlow::MakeBarrierGuard` module. For example:
182+
* ```codeql
183+
* module MyConfig implements DataFlow::ConfigSig {
184+
* predicate isBarrier(DataFlow::Node node) {
185+
* node = DataFlow::MakeBarrierGuard<MyGuard>
186+
* }
187+
* }
188+
* class MyGuard extends DataFlow::Node {
189+
* MyGuard() { ... }
190+
* predicate blocksExpr(boolean outcome, Expr e) { ... }
191+
* }
192+
*/
193+
abstract class AdditionalBarrierGuard extends DataFlow::Node {
194+
/**
195+
* Holds if this node blocks expression `e`, provided it evaluates to `outcome`.
196+
*/
197+
abstract predicate blocksExpr(boolean outcome, Expr e);
198+
}
199+
200+
/**
201+
* Internal barrier guard class that populates both the new `AdditionalBarrierGuard` class
202+
* and the legacy `AdditionalSanitizerGuardNode` class.
203+
*
204+
* It exposes the member predicates of `AdditionalSanitizerGuardNode` for backwards compatibility.
205+
*/
206+
abstract private class LegacyAdditionalBarrierGuard extends AdditionalBarrierGuard,
207+
AdditionalSanitizerGuardNode
208+
{
209+
override predicate sanitizes(boolean outcome, Expr e) { this.blocksExpr(outcome, e) }
210+
211+
deprecated override predicate appliesTo(Configuration cfg) { any() }
212+
}
213+
176214
/**
177215
* A `SanitizerGuardNode` that controls which taint tracking
178216
* configurations it is used in.
@@ -779,7 +817,7 @@ module TaintTracking {
779817
* A conditional checking a tainted string against a regular expression, which is
780818
* considered to be a sanitizer for all configurations.
781819
*/
782-
class SanitizingRegExpTest extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
820+
class SanitizingRegExpTest extends LegacyAdditionalBarrierGuard, DataFlow::ValueNode {
783821
Expr expr;
784822
boolean sanitizedOutcome;
785823

@@ -812,12 +850,10 @@ module TaintTracking {
812850

813851
private boolean getSanitizedOutcome() { result = sanitizedOutcome }
814852

815-
override predicate sanitizes(boolean outcome, Expr e) {
853+
override predicate blocksExpr(boolean outcome, Expr e) {
816854
outcome = sanitizedOutcome and
817855
e = expr
818856
}
819-
820-
deprecated override predicate appliesTo(Configuration cfg) { any() }
821857
}
822858

823859
/**
@@ -827,23 +863,21 @@ module TaintTracking {
827863
*
828864
* Note that the `includes` method is covered by `MembershipTestSanitizer`.
829865
*/
830-
class WhitelistContainmentCallSanitizer extends AdditionalSanitizerGuardNode,
866+
class WhitelistContainmentCallSanitizer extends LegacyAdditionalBarrierGuard,
831867
DataFlow::MethodCallNode
832868
{
833869
WhitelistContainmentCallSanitizer() {
834870
this.getMethodName() = ["contains", "has", "hasOwnProperty", "hasOwn"]
835871
}
836872

837-
override predicate sanitizes(boolean outcome, Expr e) {
873+
override predicate blocksExpr(boolean outcome, Expr e) {
838874
exists(int propertyIndex |
839875
if this.getMethodName() = "hasOwn" then propertyIndex = 1 else propertyIndex = 0
840876
|
841877
outcome = true and
842878
e = this.getArgument(propertyIndex).asExpr()
843879
)
844880
}
845-
846-
deprecated override predicate appliesTo(Configuration cfg) { any() }
847881
}
848882

849883
/**
@@ -876,19 +910,17 @@ module TaintTracking {
876910
module AdHocWhitelistCheckSanitizer = DataFlow::MakeBarrierGuard<AdHocWhitelistCheckSanitizer>;
877911

878912
/** A check of the form `if(x in o)`, which sanitizes `x` in its "then" branch. */
879-
class InSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
913+
class InSanitizer extends LegacyAdditionalBarrierGuard, DataFlow::ValueNode {
880914
override InExpr astNode;
881915

882-
override predicate sanitizes(boolean outcome, Expr e) {
916+
override predicate blocksExpr(boolean outcome, Expr e) {
883917
outcome = true and
884918
e = astNode.getLeftOperand()
885919
}
886-
887-
deprecated override predicate appliesTo(Configuration cfg) { any() }
888920
}
889921

890922
/** A check of the form `if(o[x] != undefined)`, which sanitizes `x` in its "then" branch. */
891-
class UndefinedCheckSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
923+
class UndefinedCheckSanitizer extends LegacyAdditionalBarrierGuard, DataFlow::ValueNode {
892924
Expr x;
893925
override EqualityTest astNode;
894926

@@ -904,27 +936,23 @@ module TaintTracking {
904936
)
905937
}
906938

907-
override predicate sanitizes(boolean outcome, Expr e) {
939+
override predicate blocksExpr(boolean outcome, Expr e) {
908940
outcome = astNode.getPolarity().booleanNot() and
909941
e = x
910942
}
911-
912-
deprecated override predicate appliesTo(Configuration cfg) { any() }
913943
}
914944

915945
/** A check of the form `type x === "undefined"`, which sanitized `x` in its "then" branch. */
916-
class TypeOfUndefinedSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
946+
class TypeOfUndefinedSanitizer extends LegacyAdditionalBarrierGuard, DataFlow::ValueNode {
917947
Expr x;
918948
override EqualityTest astNode;
919949

920950
TypeOfUndefinedSanitizer() { isTypeofGuard(astNode, x, "undefined") }
921951

922-
override predicate sanitizes(boolean outcome, Expr e) {
952+
override predicate blocksExpr(boolean outcome, Expr e) {
923953
outcome = astNode.getPolarity() and
924954
e = x
925955
}
926-
927-
deprecated override predicate appliesTo(Configuration cfg) { any() }
928956
}
929957

930958
/**
@@ -985,7 +1013,7 @@ module TaintTracking {
9851013
/**
9861014
* A test of form `x.length === "0"`, preventing `x` from being tainted.
9871015
*/
988-
class IsEmptyGuard extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
1016+
class IsEmptyGuard extends LegacyAdditionalBarrierGuard, DataFlow::ValueNode {
9891017
override EqualityTest astNode;
9901018
boolean polarity;
9911019
Expr operand;
@@ -999,32 +1027,28 @@ module TaintTracking {
9991027
)
10001028
}
10011029

1002-
override predicate sanitizes(boolean outcome, Expr e) { polarity = outcome and e = operand }
1003-
1004-
deprecated override predicate appliesTo(Configuration cfg) { any() }
1030+
override predicate blocksExpr(boolean outcome, Expr e) { polarity = outcome and e = operand }
10051031
}
10061032

10071033
/**
10081034
* A check of the form `whitelist.includes(x)` or equivalent, which sanitizes `x` in its "then" branch.
10091035
*/
1010-
class MembershipTestSanitizer extends AdditionalSanitizerGuardNode {
1036+
class MembershipTestSanitizer extends LegacyAdditionalBarrierGuard {
10111037
MembershipCandidate candidate;
10121038

10131039
MembershipTestSanitizer() { this = candidate.getTest() }
10141040

1015-
override predicate sanitizes(boolean outcome, Expr e) {
1041+
override predicate blocksExpr(boolean outcome, Expr e) {
10161042
candidate = e.flow() and candidate.getTestPolarity() = outcome
10171043
}
1018-
1019-
deprecated override predicate appliesTo(Configuration cfg) { any() }
10201044
}
10211045

10221046
/**
10231047
* A check of form `x.indexOf(y) > 0` or similar, which sanitizes `y` in the "then" branch.
10241048
*
10251049
* The more typical case of `x.indexOf(y) >= 0` is covered by `MembershipTestSanitizer`.
10261050
*/
1027-
class PositiveIndexOfSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
1051+
class PositiveIndexOfSanitizer extends LegacyAdditionalBarrierGuard, DataFlow::ValueNode {
10281052
MethodCallExpr indexOf;
10291053
override RelationalComparison astNode;
10301054

@@ -1037,19 +1061,17 @@ module TaintTracking {
10371061
)
10381062
}
10391063

1040-
override predicate sanitizes(boolean outcome, Expr e) {
1064+
override predicate blocksExpr(boolean outcome, Expr e) {
10411065
outcome = true and
10421066
e = indexOf.getArgument(0)
10431067
}
1044-
1045-
deprecated override predicate appliesTo(Configuration cfg) { any() }
10461068
}
10471069

10481070
/**
10491071
* An equality test on `e.origin` or `e.source` where `e` is a `postMessage` event object,
10501072
* considered as a sanitizer for `e`.
10511073
*/
1052-
private class PostMessageEventSanitizer extends AdditionalSanitizerGuardNode {
1074+
private class PostMessageEventSanitizer extends LegacyAdditionalBarrierGuard {
10531075
VarAccess event;
10541076
boolean polarity;
10551077

@@ -1066,12 +1088,10 @@ module TaintTracking {
10661088
)
10671089
}
10681090

1069-
override predicate sanitizes(boolean outcome, Expr e) {
1091+
override predicate blocksExpr(boolean outcome, Expr e) {
10701092
outcome = polarity and
10711093
e = event
10721094
}
1073-
1074-
deprecated override predicate appliesTo(Configuration cfg) { any() }
10751095
}
10761096

10771097
import internal.sharedlib.TaintTracking

javascript/ql/lib/semmle/javascript/dataflow/internal/TaintTrackingPrivate.qll

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,6 @@ predicate defaultAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2,
3939
defaultAdditionalTaintStep(node1, node2) and model = "" // TODO: set model
4040
}
4141

42-
abstract private class SanitizerGuardAdapter extends DataFlow::Node {
43-
// Note: avoid depending on DataFlow::FlowLabel here as it will cause these barriers to be re-evaluated
44-
abstract predicate blocksExpr(boolean outcome, Expr e);
45-
}
46-
47-
deprecated private class SanitizerGuardAdapterImpl extends SanitizerGuardAdapter instanceof TaintTracking::AdditionalSanitizerGuardNode
48-
{
49-
// TODO: reverse this relationship, so the sanitizer guards are implemented with the new interface, and the AdditionalSanitizerGuardNode
50-
// takes its values from the new implementations
51-
override predicate blocksExpr(boolean outcome, Expr e) { super.sanitizes(outcome, e) }
52-
}
53-
5442
bindingset[node]
5543
pragma[inline_late]
5644
private BasicBlock getBasicBlockFromSsa2(Ssa2::Node node) {
@@ -96,7 +84,7 @@ cached
9684
predicate defaultTaintSanitizer(DataFlow::Node node) {
9785
node instanceof DataFlow::VarAccessBarrier or
9886
varAccessBarrier(node) or
99-
node = MakeBarrierGuard<SanitizerGuardAdapter>::getABarrierNode()
87+
node = MakeBarrierGuard<TaintTracking::AdditionalBarrierGuard>::getABarrierNode()
10088
}
10189

10290
/**

0 commit comments

Comments
 (0)