Skip to content

Commit 997a11e

Browse files
committed
JS: Avoid more bad joins due to locality
1 parent 2b24d6d commit 997a11e

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
@@ -474,6 +474,8 @@ module AST {
474474
DataFlow::AnalyzedNode analyze() { result = DataFlow::valueNode(this).analyze() }
475475

476476
/** Gets the data flow node associated with this program element. */
477+
overlay[caller]
478+
pragma[inline]
477479
DataFlow::ValueNode flow() { result = DataFlow::valueNode(this) }
478480

479481
/**

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ private predicate isUsedAsNonMatchObject(DataFlow::MethodCallNode call) {
10091009
pragma[inline]
10101010
private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) {
10111011
any(Comparison compare)
1012-
.hasOperands(value.getALocalUse().asExpr(), any(Expr e | e.analyze().getAType() = TTNumber()))
1012+
.hasOperands(value.getALocalUse().asExpr(), any(Expr e | canBeNumber(e.analyze())))
10131013
or
10141014
value.flowsToExpr(any(ArithmeticExpr e).getAnOperand())
10151015
or
@@ -1024,20 +1024,30 @@ private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) {
10241024
)
10251025
}
10261026

1027+
bindingset[node]
1028+
overlay[global]
1029+
pragma[inline_late]
1030+
private predicate canBeString(DataFlow::AnalyzedNode node) { node.getAType() = TTString() }
1031+
1032+
bindingset[node]
1033+
overlay[global]
1034+
pragma[inline_late]
1035+
private predicate canBeNumber(DataFlow::AnalyzedNode node) { node.getAType() = TTNumber() }
1036+
10271037
/**
10281038
* Holds if `source` may be interpreted as a regular expression.
10291039
*/
10301040
cached
10311041
predicate isInterpretedAsRegExp(DataFlow::Node source) {
10321042
Stages::Taint::ref() and
1033-
source.analyze().getAType() = TTString() and
1043+
canBeString(source) and
10341044
(
10351045
// The first argument to an invocation of `RegExp` (with or without `new`).
10361046
source = DataFlow::globalVarRef("RegExp").getAnInvocation().getArgument(0)
10371047
or
10381048
// The argument of a call that coerces the argument to a regular expression.
10391049
exists(DataFlow::MethodCallNode mce, string methodName |
1040-
mce.getReceiver().analyze().getAType() = TTString() and
1050+
canBeString(mce.getReceiver()) and
10411051
mce.getMethodName() = methodName and
10421052
not exists(Function func | func = mce.getACallee() |
10431053
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
@@ -1419,6 +1419,7 @@ module DataFlow {
14191419
* This predicate is only defined for expressions, properties, and for statements that declare
14201420
* a function, a class, or a TypeScript namespace or enum.
14211421
*/
1422+
pragma[nomagic]
14221423
ValueNode valueNode(AstNode nd) { result.getAstNode() = nd }
14231424

14241425
/**

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ module LazyCache {
4343
pragma[noopt]
4444
override DataFlow::Node getImportedModuleNode() {
4545
this instanceof LazyCacheImport and
46-
result = this.flow()
46+
result = DataFlow::valueNode(this)
4747
or
4848
exists(LazyCacheVariable variable, Expr base, PropAccess access, string localName |
4949
// To avoid recursion, this should not depend on `SourceNode`.
@@ -52,7 +52,7 @@ module LazyCache {
5252
access.getBase() = base and
5353
localName = this.getLocalAlias() and
5454
access.getPropertyName() = localName and
55-
result = access.flow()
55+
result = DataFlow::valueNode(access)
5656
)
5757
}
5858
}

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,18 @@ class ForOfLoopStep extends AdditionalFlowInternal {
4848
) {
4949
exists(ForOfStmt stmt |
5050
pred = getSynthesizedNode(stmt, "for-of-map-key") and
51-
contents.asSingleton().asArrayIndex() = 0
51+
contents = arrayIndex0()
5252
or
5353
pred = getSynthesizedNode(stmt, "for-of-map-value") and
54-
contents.asSingleton().asArrayIndex() = 1
54+
contents = arrayIndex1()
5555
|
5656
succ = DataFlow::lvalueNode(stmt.getLValue())
5757
)
5858
}
5959
}
60+
61+
pragma[nomagic]
62+
private DataFlow::ContentSet arrayIndex0() { result.asSingleton().asArrayIndex() = 0 }
63+
64+
pragma[nomagic]
65+
private DataFlow::ContentSet arrayIndex1() { result.asSingleton().asArrayIndex() = 1 }

0 commit comments

Comments
 (0)