Skip to content

Commit a2e3c50

Browse files
committed
JS: Avoid more bad joins due to locality
1 parent 66565b3 commit a2e3c50

File tree

5 files changed

+26
-7
lines changed

5 files changed

+26
-7
lines changed

javascript/ql/lib/semmle/javascript/AST.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,8 @@ module AST {
477477
DataFlow::AnalyzedNode analyze() { result = DataFlow::valueNode(this).analyze() }
478478

479479
/** Gets the data flow node associated with this program element. */
480+
overlay[caller]
481+
pragma[inline]
480482
DataFlow::ValueNode flow() { result = DataFlow::valueNode(this) }
481483

482484
/**

javascript/ql/lib/semmle/javascript/Regexp.qll

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ overlay[global]
10161016
pragma[inline]
10171017
private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) {
10181018
any(Comparison compare)
1019-
.hasOperands(value.getALocalUse().asExpr(), any(Expr e | e.analyze().getAType() = TTNumber()))
1019+
.hasOperands(value.getALocalUse().asExpr(), any(Expr e | canBeNumber(e.analyze())))
10201020
or
10211021
value.flowsToExpr(any(ArithmeticExpr e).getAnOperand())
10221022
or
@@ -1031,21 +1031,31 @@ private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) {
10311031
)
10321032
}
10331033

1034+
bindingset[node]
1035+
overlay[global]
1036+
pragma[inline_late]
1037+
private predicate canBeString(DataFlow::AnalyzedNode node) { node.getAType() = TTString() }
1038+
1039+
bindingset[node]
1040+
overlay[global]
1041+
pragma[inline_late]
1042+
private predicate canBeNumber(DataFlow::AnalyzedNode node) { node.getAType() = TTNumber() }
1043+
10341044
/**
10351045
* Holds if `source` may be interpreted as a regular expression.
10361046
*/
10371047
overlay[global]
10381048
cached
10391049
predicate isInterpretedAsRegExp(DataFlow::Node source) {
10401050
Stages::Taint::ref() and
1041-
source.analyze().getAType() = TTString() and
1051+
canBeString(source) and
10421052
(
10431053
// The first argument to an invocation of `RegExp` (with or without `new`).
10441054
source = DataFlow::globalVarRef("RegExp").getAnInvocation().getArgument(0)
10451055
or
10461056
// The argument of a call that coerces the argument to a regular expression.
10471057
exists(DataFlow::MethodCallNode mce, string methodName |
1048-
mce.getReceiver().analyze().getAType() = TTString() and
1058+
canBeString(mce.getReceiver()) and
10491059
mce.getMethodName() = methodName and
10501060
not exists(Function func | func = mce.getACallee() |
10511061
not isNativeStringMethod(func, methodName)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,7 @@ module DataFlow {
14301430
* This predicate is only defined for expressions, properties, and for statements that declare
14311431
* a function, a class, or a TypeScript namespace or enum.
14321432
*/
1433+
pragma[nomagic]
14331434
ValueNode valueNode(AstNode nd) { result.getAstNode() = nd }
14341435

14351436
/**

javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ module LazyCache {
4545
pragma[noopt]
4646
override DataFlow::Node getImportedModuleNode() {
4747
this instanceof LazyCacheImport and
48-
result = this.flow()
48+
result = DataFlow::valueNode(this)
4949
or
5050
exists(LazyCacheVariable variable, Expr base, PropAccess access, string localName |
5151
// To avoid recursion, this should not depend on `SourceNode`.
@@ -54,7 +54,7 @@ module LazyCache {
5454
access.getBase() = base and
5555
localName = this.getLocalAlias() and
5656
access.getPropertyName() = localName and
57-
result = access.flow()
57+
result = DataFlow::valueNode(access)
5858
)
5959
}
6060
}

javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,18 @@ class ForOfLoopStep extends AdditionalFlowInternal {
5050
) {
5151
exists(ForOfStmt stmt |
5252
pred = getSynthesizedNode(stmt, "for-of-map-key") and
53-
contents.asSingleton().asArrayIndex() = 0
53+
contents = arrayIndex0()
5454
or
5555
pred = getSynthesizedNode(stmt, "for-of-map-value") and
56-
contents.asSingleton().asArrayIndex() = 1
56+
contents = arrayIndex1()
5757
|
5858
succ = DataFlow::lvalueNode(stmt.getLValue())
5959
)
6060
}
6161
}
62+
63+
pragma[nomagic]
64+
private DataFlow::ContentSet arrayIndex0() { result.asSingleton().asArrayIndex() = 0 }
65+
66+
pragma[nomagic]
67+
private DataFlow::ContentSet arrayIndex1() { result.asSingleton().asArrayIndex() = 1 }

0 commit comments

Comments
 (0)