Skip to content

Commit 2629ec1

Browse files
committed
JS: Be more conservative about flagging "search" call arguments as regex
1 parent ca83b7c commit 2629ec1

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

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

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,27 @@ private predicate isUsedAsNonMatchObject(DataFlow::MethodCallNode call) {
958958
)
959959
}
960960

961+
/**
962+
* Holds if `call` is a call to `search` whose result is used in a way that suggests it returns a number.
963+
*/
964+
pragma[inline]
965+
private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) {
966+
any(Comparison compare)
967+
.hasOperands(value.getALocalUse().asExpr(), any(Expr e | e.analyze().getAType() = TTNumber()))
968+
or
969+
value.flowsToExpr(any(ArithmeticExpr e).getAnOperand())
970+
or
971+
value.flowsToExpr(any(UnaryExpr e | e.getOperator() = "-").getOperand())
972+
or
973+
value.flowsToExpr(any(IndexExpr expr).getPropertyNameExpr())
974+
or
975+
exists(DataFlow::CallNode call |
976+
call.getCalleeName() =
977+
["substring", "substr", "slice", "splice", "charAt", "charCodeAt", "codePointAt"] and
978+
value.flowsTo(call.getAnArgument())
979+
)
980+
}
981+
961982
/**
962983
* Holds if `source` may be interpreted as a regular expression.
963984
*/
@@ -985,9 +1006,9 @@ predicate isInterpretedAsRegExp(DataFlow::Node source) {
9851006
methodName = "search" and
9861007
source = mce.getArgument(0) and
9871008
mce.getNumArgument() = 1 and
988-
// "search" is a common method name, and so we exclude chained accesses
989-
// because `String.prototype.search` returns a number
990-
not exists(PropAccess p | p.getBase() = mce.getEnclosingExpr())
1009+
// "search" is a common method name, and the built-in "search" method is rarely used,
1010+
// so to reduce FPs we also require that the return value appears to be used as a number.
1011+
isUsedAsNumber(mce)
9911012
)
9921013
or
9931014
exists(DataFlow::SourceNode schema | schema = JsonSchema::getAPartOfJsonSchema() |

0 commit comments

Comments
 (0)