Skip to content

Commit 8a38633

Browse files
committed
JS: Handle exec() == undefined
1 parent 7d5384b commit 8a38633

File tree

4 files changed

+18
-2
lines changed

4 files changed

+18
-2
lines changed

javascript/ql/src/semmle/javascript/Expr.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,11 @@ class EqualityTest extends @equalitytest, Comparison {
13551355
(this instanceof NEqExpr or this instanceof StrictNEqExpr) and
13561356
result = false
13571357
}
1358+
1359+
/**
1360+
* Holds if the equality operator is strict (`===` or `!==`).
1361+
*/
1362+
predicate isStrict() { this instanceof StrictEqExpr or this instanceof StrictNEqExpr }
13581363
}
13591364

13601365
/**

javascript/ql/src/semmle/javascript/StringOps.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -744,10 +744,16 @@ module StringOps {
744744
* Holds if `e` evaluating to `polarity` implies that `operand` is not null.
745745
*/
746746
private predicate impliesNotNull(Expr e, Expr operand, boolean polarity) {
747-
exists(EqualityTest test |
747+
exists(EqualityTest test, Expr other |
748748
e = test and
749749
polarity = test.getPolarity().booleanNot() and
750-
test.hasOperands(any(NullLiteral n), operand)
750+
test.hasOperands(other, operand) and
751+
SyntacticConstants::isNullOrUndefined(other) and
752+
not (
753+
// 'exec() === undefined' doesn't work
754+
other instanceof SyntacticConstants::UndefinedConstant and
755+
test.isStrict()
756+
)
751757
)
752758
or
753759
isCoercedToBoolean(e) and

javascript/ql/test/library-tests/StringOps/RegExpTest/RegExpTest.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ regexpTest
1616
| tst.js:25:23:25:27 | match |
1717
| tst.js:29:21:29:36 | regexp.test(str) |
1818
| tst.js:33:21:33:39 | str.matches(regexp) |
19+
| tst.js:40:9:40:37 | regexp. ... defined |
1920
#select
2021
| tst.js:6:9:6:28 | /^[a-z]+$/.test(str) | tst.js:6:10:6:17 | ^[a-z]+$ | tst.js:6:9:6:18 | /^[a-z]+$/ | tst.js:6:25:6:27 | str | true |
2122
| tst.js:7:9:7:36 | /^[a-z] ... != null | tst.js:7:10:7:17 | ^[a-z]+$ | tst.js:7:9:7:18 | /^[a-z]+$/ | tst.js:7:25:7:27 | str | true |
@@ -34,3 +35,4 @@ regexpTest
3435
| tst.js:25:23:25:27 | match | tst.js:3:17:3:24 | ^[a-z]+$ | tst.js:17:17:17:22 | regexp | tst.js:17:29:17:31 | str | true |
3536
| tst.js:29:21:29:36 | regexp.test(str) | tst.js:3:17:3:24 | ^[a-z]+$ | tst.js:29:21:29:26 | regexp | tst.js:29:33:29:35 | str | true |
3637
| tst.js:33:21:33:39 | str.matches(regexp) | tst.js:3:17:3:24 | ^[a-z]+$ | tst.js:33:33:33:38 | regexp | tst.js:33:21:33:23 | str | true |
38+
| tst.js:40:9:40:37 | regexp. ... defined | tst.js:3:17:3:24 | ^[a-z]+$ | tst.js:40:9:40:14 | regexp | tst.js:40:21:40:23 | str | false |

javascript/ql/test/library-tests/StringOps/RegExpTest/tst.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,7 @@ function f(str) {
3636
something({
3737
someOption: regexp.exec(str) // not recognized as RegExpTest
3838
})
39+
40+
if (regexp.exec(str) == undefined) {}
41+
if (regexp.exec(str) === undefined) {} // not recognized as RegExpTest
3942
}

0 commit comments

Comments
 (0)