mirror of
https://github.com/github/codeql.git
synced 2026-05-24 08:07:07 +02:00
JS: Improve performance of StandardEndpointFilters::isNumeric
Factor the regex-independent logic of `isReadFrom` into its own predicate. Call this predicate directly from `isNumeric`, which doesn't have much restrictive context on the set of starting nodes. Use a binding hint to discourage starting with all expr nodes in this case. Other callers may have more restrictive context on the set of nodes, so they are not changed.
This commit is contained in:
committed by
Henry Mercer
parent
1b7088abde
commit
1d507f1993
@@ -53,7 +53,11 @@ predicate isSomeModeledArgument(DataFlow::Node n) {
|
||||
/**
|
||||
* Holds if `n` appears to be a numeric value.
|
||||
*/
|
||||
predicate isNumeric(DataFlow::Node n) { isReadFrom(n, ".*index.*") }
|
||||
// Performance optimisation: This predicate operates on a large set of
|
||||
// starting nodes, so use binding hints to suggest computing that set last.
|
||||
predicate isNumeric(DataFlow::Node n) {
|
||||
getAnAccessedName(pragma[only_bind_into](n)).regexpMatch(".*index.*")
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is an argument to a library without sinks.
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user