@@ -69,7 +69,7 @@ import javascript
6969 *
7070 * CAVEATS:
7171 *
72- * - We assume !(x <= y) means x > y, ignoring NaN.
72+ * - We assume !(x <= y) means x > y, ignoring NaN, unless a nearby comment or identifier mentions NaN .
7373 *
7474 * - We assume integer arithmetic is exact, ignoring values above 2^53.
7575 *
@@ -257,6 +257,24 @@ module RangeAnalysis {
257257 )
258258 }
259259
260+ /**
261+ * Holds if the given container has a comment or identifier mentioning `NaN`.
262+ */
263+ predicate hasNaNIndicator ( StmtContainer container ) {
264+ exists ( Comment comment |
265+ comment .getText ( ) .regexpMatch ( "(?s).*N[aA]N.*" ) and
266+ comment .getFile ( ) = container .getFile ( ) and
267+ (
268+ comment .getLocation ( ) .getStartLine ( ) >= container .getLocation ( ) .getStartLine ( ) and
269+ comment .getLocation ( ) .getEndLine ( ) <= container .getLocation ( ) .getEndLine ( )
270+ or
271+ comment .getNextToken ( ) = container .getFirstToken ( )
272+ ) )
273+ or
274+ exists ( Identifier id | id .getName ( ) = "NaN" or id .getName ( ) = "isNaN" |
275+ id .getContainer ( ) = container )
276+ }
277+
260278 /**
261279 * Holds if `guard` asserts that the outcome of `A <op> B + bias` is true, where `<op>` is a comparison operator.
262280 */
@@ -266,6 +284,7 @@ module RangeAnalysis {
266284 (
267285 guard .getOutcome ( ) = true and operator = compare .getOperator ( )
268286 or
287+ not hasNaNIndicator ( guard .getContainer ( ) ) and
269288 guard .getOutcome ( ) = false and operator = negateOperator ( compare .getOperator ( ) )
270289 )
271290 )
0 commit comments