mirror of
https://github.com/github/codeql.git
synced 2025-12-25 05:06:34 +01:00
Will need subsequent PRs fixing up test failures (due to deprecated methods moving around), but other than that everything should be straight-forward.
93 lines
2.8 KiB
Plaintext
93 lines
2.8 KiB
Plaintext
/**
|
|
* @name Imprecise assert
|
|
* @description Using 'assertTrue' or 'assertFalse' rather than a more specific assertion can give uninformative failure messages.
|
|
* @kind problem
|
|
* @tags maintainability
|
|
* testability
|
|
* @problem.severity recommendation
|
|
* @sub-severity high
|
|
* @precision very-high
|
|
* @id py/imprecise-assert
|
|
*/
|
|
|
|
import python
|
|
|
|
/* Helper predicate for CallToAssertOnComparison class */
|
|
predicate callToAssertOnComparison(Call call, string assertName, Cmpop op) {
|
|
call.getFunc().(Attribute).getName() = assertName and
|
|
(assertName = "assertTrue" or assertName = "assertFalse") and
|
|
exists(Compare cmp |
|
|
cmp = call.getArg(0) and
|
|
/* Exclude complex comparisons like: a < b < c */
|
|
not exists(cmp.getOp(1)) and
|
|
op = cmp.getOp(0)
|
|
)
|
|
}
|
|
|
|
class CallToAssertOnComparison extends Call {
|
|
CallToAssertOnComparison() { callToAssertOnComparison(this, _, _) }
|
|
|
|
Cmpop getOperator() { callToAssertOnComparison(this, _, result) }
|
|
|
|
string getMethodName() { callToAssertOnComparison(this, result, _) }
|
|
|
|
string getBetterName() {
|
|
exists(Cmpop op |
|
|
callToAssertOnComparison(this, "assertTrue", op) and
|
|
(
|
|
op instanceof Eq and result = "assertEqual"
|
|
or
|
|
op instanceof NotEq and result = "assertNotEqual"
|
|
or
|
|
op instanceof Lt and result = "assertLess"
|
|
or
|
|
op instanceof LtE and result = "assertLessEqual"
|
|
or
|
|
op instanceof Gt and result = "assertGreater"
|
|
or
|
|
op instanceof GtE and result = "assertGreaterEqual"
|
|
or
|
|
op instanceof In and result = "assertIn"
|
|
or
|
|
op instanceof NotIn and result = "assertNotIn"
|
|
or
|
|
op instanceof Is and result = "assertIs"
|
|
or
|
|
op instanceof IsNot and result = "assertIsNot"
|
|
)
|
|
or
|
|
callToAssertOnComparison(this, "assertFalse", op) and
|
|
(
|
|
op instanceof NotEq and result = "assertEqual"
|
|
or
|
|
op instanceof Eq and result = "assertNotEqual"
|
|
or
|
|
op instanceof GtE and result = "assertLess"
|
|
or
|
|
op instanceof Gt and result = "assertLessEqual"
|
|
or
|
|
op instanceof LtE and result = "assertGreater"
|
|
or
|
|
op instanceof Lt and result = "assertGreaterEqual"
|
|
or
|
|
op instanceof NotIn and result = "assertIn"
|
|
or
|
|
op instanceof In and result = "assertNotIn"
|
|
or
|
|
op instanceof IsNot and result = "assertIs"
|
|
or
|
|
op instanceof Is and result = "assertIsNot"
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
from CallToAssertOnComparison call
|
|
where
|
|
/* Exclude cases where an explicit message is provided*/
|
|
not exists(call.getArg(1))
|
|
select call,
|
|
call.getMethodName() + "(a " + call.getOperator().getSymbol() + " b) " +
|
|
"cannot provide an informative message. Using " + call.getBetterName() +
|
|
"(a, b) instead will give more informative messages."
|