` is
+ * a well-known test file identifier, such as `test` or `spec`.
+ */
+// Helper predicate factored out for performance.
+// This predicate is linear in the size of f, and forces
+// callers to join only once against f rather than two separate joins
+// when computing the stem and the extension.
+// This loses some flexibility because callers cannot specify
+// an arbitrary stemExt.
+pragma[nomagic]
+private string getATestFileName(File f) {
+ result = f.getStem() + "." + ["test", "spec"] + "." + f.getExtension()
+}
+
/**
* A Jest test, that is, an invocation of a global function named
* `test` where the first argument is a string and the second
diff --git a/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll b/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll
index 12356d1bf42b..de7ca2a852e5 100644
--- a/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll
+++ b/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll
@@ -16,15 +16,23 @@ import javascript
*/
bindingset[regexp]
predicate isReadFrom(DataFlow::Node read, string regexp) {
+ getAnAccessedName(read).regexpMatch(regexp)
+}
+
+/**
+ * Gets the "name" accessed by `read`. The "name" is one of:
+ * - the name of the read variable, if `read` is a variable read
+ * - the name of the read property, if `read` is a property read
+ * - the suffix of the getter-method name, if `read` is a getter invocation, for example "Number" in "getNumber"
+ */
+string getAnAccessedName(DataFlow::Node read) {
exists(DataFlow::Node actualRead |
actualRead = read.asExpr().getUnderlyingValue().(LogOrExpr).getAnOperand().flow() or // unfold `x || y` once
actualRead = read
|
- exists(string name | name.regexpMatch(regexp) |
- actualRead.asExpr().getUnderlyingValue().(VarAccess).getName() = name or
- actualRead.(DataFlow::PropRead).getPropertyName() = name or
- actualRead.(DataFlow::InvokeNode).getCalleeName() = "get" + name
- )
+ actualRead.asExpr().getUnderlyingValue().(VarAccess).getName() = result or
+ actualRead.(DataFlow::PropRead).getPropertyName() = result or
+ actualRead.(DataFlow::InvokeNode).getCalleeName() = "get" + result
)
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll
index 867494fc0a36..37b1830018e7 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll
@@ -50,8 +50,12 @@ module CorsMisconfigurationForCredentials {
|
routeHandler.getAResponseHeader(_) = origin and
routeHandler.getAResponseHeader(_) = credentials and
- origin.definesExplicitly("access-control-allow-origin", this.asExpr()) and
- credentials.definesExplicitly("access-control-allow-credentials", credentialsValue)
+ // Performance optimisation: start with the set of all route handlers
+ // rather than the set of all exprs.
+ pragma[only_bind_into](origin)
+ .definesExplicitly("access-control-allow-origin", this.asExpr()) and
+ pragma[only_bind_into](credentials)
+ .definesExplicitly("access-control-allow-credentials", credentialsValue)
|
credentialsValue.mayHaveBooleanValue(true) or
credentialsValue.mayHaveStringValue("true")
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll
index 501eed347c55..2f27bb69b9bf 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll
@@ -437,8 +437,27 @@ module DomBasedXss {
b = phi.getAnInput().getDefinition() and
count(phi.getAnInput()) = 2 and
not a = b and
- sanitizer = DataFlow::valueNode(a.getDef().getSource()) and
- sanitizer.getAnArgument().asExpr().(VarAccess).getVariable() = b.getSourceVariable()
+ /*
+ * Performance optimisation:
+ *
+ * When join-ordering and evaluating this conjunction,
+ * it is preferable to start with the relatively small set of
+ * `sanitizer` calls, then compute the set of SSA variables accessed
+ * as the arguments of those sanitizer calls, then reason about how
+ * those variables are used in phi nodes.
+ *
+ * Use directional binding pragmas to encourage this join order,
+ * starting with `sanitizer`.
+ *
+ * Without these pragmas, the join orderer may choose the opposite order:
+ * start with all `phi` nodes, then compute the set of SSA variables involved,
+ * then the (potentially large) set of accesses to those variables,
+ * then the set of accesses used as the argument of a sanitizer call.
+ */
+
+ pragma[only_bind_out](sanitizer) = DataFlow::valueNode(a.getDef().getSource()) and
+ pragma[only_bind_out](sanitizer.getAnArgument().asExpr()) =
+ b.getSourceVariable().getAnAccess()
|
pred = DataFlow::ssaDefinitionNode(b) and
succ = DataFlow::ssaDefinitionNode(phi)
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy