Skip to content

Commit f9106b3

Browse files
author
Max Schaefer
authored
Merge pull request #685 from asger-semmle/useless-conditional-as-value
JS: fix FPs in UselessConditional
2 parents 7f21f14 + f737830 commit f9106b3

File tree

3 files changed

+22
-5
lines changed

3 files changed

+22
-5
lines changed

javascript/ql/src/Statements/UselessConditional.ql

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,26 @@ predicate whitelist(Expr e) {
109109

110110
/**
111111
* Holds if `e` is part of a conditional node `cond` that evaluates
112-
* `e` and checks its value for truthiness.
112+
* `e` and checks its value for truthiness, and the return value of `e`
113+
* is not used for anything other than this truthiness check.
113114
*/
114-
predicate isConditional(ASTNode cond, Expr e) {
115+
predicate isExplicitConditional(ASTNode cond, Expr e) {
115116
e = cond.(IfStmt).getCondition() or
116117
e = cond.(LoopStmt).getTest() or
117118
e = cond.(ConditionalExpr).getCondition() or
118-
e = cond.(LogicalBinaryExpr).getLeftOperand() or
119-
// Include `z` in `if (x && z)`.
120-
isConditional(_, cond) and e = cond.(Expr).getUnderlyingValue().(LogicalBinaryExpr).getRightOperand()
119+
isExplicitConditional(_, cond) and e = cond.(Expr).getUnderlyingValue().(LogicalBinaryExpr).getAnOperand()
120+
}
121+
122+
/**
123+
* Holds if `e` is part of a conditional node `cond` that evaluates
124+
* `e` and checks its value for truthiness.
125+
*
126+
* The return value of `e` may have other uses besides the truthiness check,
127+
* but if the truthiness check always goes one way, it still indicates an error.
128+
*/
129+
predicate isConditional(ASTNode cond, Expr e) {
130+
isExplicitConditional(cond, e) or
131+
e = cond.(LogicalBinaryExpr).getLeftOperand()
121132
}
122133

123134
from ASTNode cond, DataFlow::AnalyzedNode op, boolean cv, ASTNode sel, string msg

javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
| UselessConditional.js:101:18:101:18 | x | This use of variable 'x' always evaluates to false. |
2222
| UselessConditional.js:102:19:102:19 | x | This use of variable 'x' always evaluates to false. |
2323
| UselessConditional.js:103:23:103:23 | x | This use of variable 'x' always evaluates to false. |
24+
| UselessConditional.js:109:15:109:16 | {} | This expression always evaluates to true. |
2425
| UselessConditionalGood.js:58:12:58:13 | x2 | This use of variable 'x2' always evaluates to false. |
2526
| UselessConditionalGood.js:69:12:69:13 | xy | This use of variable 'xy' always evaluates to false. |
2627
| UselessConditionalGood.js:85:12:85:13 | xy | This use of variable 'xy' always evaluates to false. |

javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,9 @@ async function awaitFlow(){
104104
}
105105
});
106106

107+
(function(x,y) {
108+
let obj = (x && {}) || y; // OK
109+
if ((x && {}) || y) {} // NOT OK
110+
});
111+
107112
// semmle-extractor-options: --experimental

0 commit comments

Comments
 (0)