Skip to content

Commit 95eb4cf

Browse files
authored
Merge pull request #1089 from markshannon/python-fix-redundant-comparison-complex-test
Fix false positive for redundant comparison query
2 parents d549a0d + 3fbe3c3 commit 95eb4cf

File tree

3 files changed

+15
-1
lines changed

3 files changed

+15
-1
lines changed

change-notes/1.20/analysis-python.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ The API has been improved to declutter the global namespace and improve discover
3030
| Comparison using is when operands support \_\_eq\_\_ (`py/comparison-using-is`) | Fewer false positive results | Results where one of the objects being compared is an enum member are no longer reported. |
3131
| Modification of parameter with default (`py/modification-of-default-value`) | More true positive results | Instances where the mutable default value is mutated inside other functions are now also reported. |
3232
| Mutation of descriptor in \_\_get\_\_ or \_\_set\_\_ method (`py/mutable-descriptor`) | Fewer false positive results | Results where the mutation does not occur when calling one of the `__get__`, `__set__` or `__delete__` methods are no longer reported. |
33+
| Redundant comparison (`py/redundant-comparison`) | Fewer false positive results | Results in chained comparisons are no longer reported. |
3334
| Unused import (`py/unused-import`) | Fewer false positive results | Results where the imported module is used in a `doctest` string are no longer reported. |
3435
| Unused import (`py/unused-import`) | Fewer false positive results | Results where the imported module is used in a type-hint comment are no longer reported. |
3536

python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,22 @@
1515
import python
1616
import semmle.python.Comparisons
1717

18+
/* Holds if the comparison `comp` is of the complex form `a op b op c` and not of
19+
* the simple form `a op b`.
20+
*/
21+
private predicate is_complex(Expr comp) {
22+
exists(comp.(Compare).getOp(1))
23+
or
24+
is_complex(comp.(UnaryExpr).getOperand())
25+
}
1826

1927
/** A test is useless if for every block that it controls there is another test that is at least as
2028
* strict and also controls that block.
2129
*/
2230
private predicate useless_test(Comparison comp, ComparisonControlBlock controls, boolean isTrue) {
2331
controls.impliesThat(comp.getBasicBlock(), comp, isTrue) and
2432
/* Exclude complex comparisons of form `a < x < y`, as we do not (yet) have perfect flow control for those */
25-
not exists(controls.getTest().getNode().(Compare).getOp(1))
33+
not is_complex(controls.getTest().getNode())
2634
}
2735

2836
private predicate useless_test_ast(AstNode comp, AstNode previous, boolean isTrue) {

python/ql/test/query-tests/Expressions/comparisons/test.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,8 @@ def odasa6782_v3(protocol):
8686
pass
8787
else:
8888
raise ValueError()
89+
90+
#Inverted complex test
91+
if not (0 > stop >= step) and stop < 0:
92+
pass
93+

0 commit comments

Comments
 (0)