Skip to content

Commit 9f6e048

Browse files
committed
JS: Fix FP from word boundaries
1 parent b604be5 commit 9f6e048

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

javascript/ql/src/RegExp/RegExpAlwaysMatches.ql

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,19 @@ class RegExpSearchCall extends DataFlow::MethodCallNode, RegExpQuery {
9898
}
9999
}
100100

101+
/**
102+
* Holds if `t` is a zero-width assertion other than an anchor.
103+
*/
104+
predicate isAssertion(RegExpTerm t) {
105+
t instanceof RegExpSubPattern or
106+
t instanceof RegExpWordBoundary or
107+
t instanceof RegExpNonWordBoundary
108+
}
109+
101110
from RegExpTerm term, RegExpQuery call, string message
102111
where
103112
term.isNullable() and
104-
not term.getAChild() instanceof RegExpSubPattern and
113+
not isAssertion(term.getAChild*()) and
105114
not isUniversalRegExp(term) and
106115
term = getEffectiveRoot(call.getRegExp()) and
107116
(
@@ -111,7 +120,6 @@ where
111120
or
112121
call instanceof RegExpSearchCall and
113122
not term.getAChild*() instanceof RegExpDollar and
114-
not term.getAChild*() instanceof RegExpSubPattern and
115123
message = "This regular expression always the matches at index 0 when used $@, as it matches the empty substring."
116124
)
117125
select term, message, call, "here"

javascript/ql/test/query-tests/RegExp/RegExpAlwaysMatches/tst.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,11 @@ function searchPrefix(x) {
7373
function searchSuffix(x) {
7474
return /foo?$/.search(x); // OK - `foo?` affects the returned index
7575
}
76+
77+
function wordBoundary(x) {
78+
return /\b/.test(x); // OK - some strings don't have word boundaries
79+
}
80+
81+
function nonWordBoundary(x) {
82+
return /\B/.test(x); // OK - some strings don't have non-word boundaries
83+
}

0 commit comments

Comments
 (0)