mirror of
https://github.com/github/codeql.git
synced 2026-02-08 03:01:10 +01:00
86 lines
2.7 KiB
Plaintext
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)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if `c` is 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()
|