Files
codeql/javascript/ql/src/Expressions/CompareIdenticalValues.ql
Max Schaefer a803120414 Lower precision for a number of queries.
These queries are currently run by default, but don't have their results displayed.

Looking through results on LGTM.com, they are either false positives (e.g., `BitwiseSignCheck` which flags many perfectly harmless operations and `CompareIdenticalValues` which mostly flags NaN checks) or harmless results that developers are unlikely to care about (e.g., `EmptyArrayInit` or `MisspelledIdentifier`).

With this PR, the only queries that are still run but not displayed are security queries, where different considerations may apply.
2020-05-19 13:43:17 +01:00

86 lines
2.7 KiB
Plaintext

/**
* @name Comparison of identical values
* @description If the same expression occurs on both sides of a comparison
* operator, the operator is redundant, and probably indicates a mistake.
* @kind problem
* @problem.severity warning
* @id js/comparison-of-identical-expressions
* @tags reliability
* correctness
* readability
* convention
* external/cwe/cwe-570
* external/cwe/cwe-571
* @precision low
*/
import Clones
/**
* Holds if `e` is a reference to variable `v`, possibly with parentheses or
* numeric conversions (that is, the unary operators `+` or `-` or a call to `Number`)
* applied.
*/
predicate accessWithConversions(Expr e, Variable v) {
e = v.getAnAccess()
or
accessWithConversions(e.(ParExpr).getExpression(), v)
or
exists(UnaryExpr ue | ue instanceof NegExpr or ue instanceof PlusExpr |
ue = e and accessWithConversions(ue.getOperand(), v)
)
or
exists(CallExpr ce | ce = e |
ce = DataFlow::globalVarRef("Number").getACall().asExpr() and
ce.getNumArgument() = 1 and
accessWithConversions(ce.getArgument(0), v)
)
}
/**
* A comment containing the word "NaN".
*/
predicate isNaNComment(Comment c, string filePath, int startLine) {
c.getText().matches("%NaN%") and
c.getLocation().hasLocationInfo(filePath, startLine, _, _, _)
}
/**
* Holds if the equality test `eq` looks like a NaN check.
*
* In order to qualify as a NaN check, both sides of the equality have
* to be references to the same variable `x`, possibly with added parentheses
* or numeric conversions, and one of the following holds:
*
* - `x` is a parameter of the enclosing function, which is called
* `isNaN` (modulo capitalization);
* - there is a comment next to the comparison (that is, no further than
* one line away in either direction) that contains the word `NaN`.
*/
predicate isNaNCheck(EqualityTest eq) {
exists(Variable v |
accessWithConversions(eq.getLeftOperand(), v) and
accessWithConversions(eq.getRightOperand(), v)
|
// `v` is a parameter of the enclosing function, which is called `isNaN`
exists(Function isNaN |
isNaN = eq.getEnclosingFunction() and
isNaN.getName().toLowerCase() = "isnan" and
v = isNaN.getAParameter().getAVariable()
)
or
// there is a comment containing the word "NaN" next to the comparison
exists(string f, int l |
eq.getLocation().hasLocationInfo(f, l, _, _, _) and
isNaNComment(_, f, [l - 1 .. l + 1])
)
)
}
from Comparison selfComparison, OperandComparedToSelf e
where
e = selfComparison.getAnOperand() and
e.same(_) and
not isNaNCheck(selfComparison)
select selfComparison, "This expression compares $@ to itself.", e, e.toString()