Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2e0244c

Browse files
committed
address review feedback
1 parent 2805679 commit 2e0244c

5 files changed

Lines changed: 28 additions & 10 deletions

File tree

javascript/ql/src/Expressions/ExprHasNoEffect.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import javascript
1616
import ExprHasNoEffect
17+
import semmle.javascript.RestrictedLocations
1718

1819

1920
from Expr e

javascript/ql/src/Expressions/ExprHasNoEffect.qll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import javascript
66
import DOMProperties
77
import semmle.javascript.frameworks.xUnit
8-
import semmle.javascript.RestrictedLocations
98

109
/**
1110
* Holds if `e` appears in a syntactic context where its value is discarded.

javascript/ql/src/Statements/UseOfReturnlessFunction.ql

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,19 @@ predicate alwaysThrows(Function f) {
8282
)
8383
}
8484

85+
/**
86+
* Holds if the last statement in the function is flagged by the js/useless-expression query.
87+
*/
88+
predicate alwaysHasNoEffect(Function f) {
89+
exists(ReachableBasicBlock entry, DataFlow::Node noEffect |
90+
entry = f.getEntryBB() and
91+
hasNoEffect(noEffect.asExpr()) and
92+
entry.dominates(noEffect.getBasicBlock())
93+
)
94+
}
95+
8596
predicate callToVoidFunction(DataFlow::CallNode call, Function func) {
86-
not call.isIndefinite(_) and
97+
not call.isIncomplete() and
8798
func = call.getACallee() and
8899
forall(Function f | f = call.getACallee() |
89100
returnsVoid(f) and not isStub(f) and not alwaysThrows(f)
@@ -113,6 +124,11 @@ DataFlow::SourceNode array(DataFlow::TypeTracker t) {
113124

114125
DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) }
115126

127+
/**
128+
* Holds if `call` is an Array or Lodash method accepting a callback `func`,
129+
* where the `call` expects a callback that returns an expression,
130+
* but `func` does return a value.
131+
*/
116132
predicate voidArrayCallback(DataFlow::CallNode call, Function func) {
117133
hasNonVoidCallbackMethod(call.getCalleeName()) and
118134
func = call.getAnArgument().getALocalSource().asExpr() and
@@ -132,15 +148,14 @@ where
132148
(
133149
callToVoidFunction(call, func) and
134150
msg = "the $@ does not return anything, yet the return value is used." and
135-
name = "function " + call.getCalleeName()
151+
name = func.describe()
136152
or
137153
voidArrayCallback(call, func) and
138-
msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + "() is used." and
154+
msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + " is used." and
139155
name = "callback function"
140156
) and
141157
not benignContext(call.asExpr()) and
142-
// Avoid double reporting from js/useless-expression
143-
not hasNoEffect(func.getBodyStmt(func.getNumBodyStmt() - 1).(ExprStmt).getExpr()) and
158+
not alwaysHasNoEffect(func) and
144159
// anonymous one-shot closure. Those are used in weird ways and we ignore them.
145160
not oneshotClosure(call.asExpr())
146161
select
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
| tst.js:20:17:20:33 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects |
22
| tst.js:24:13:24:29 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects |
33
| tst.js:30:20:30:36 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects |
4-
| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function bothOnlyHaveSideEffects |
5-
| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function bothOnlyHaveSideEffects |
6-
| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function |
7-
| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function |
4+
| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects |
5+
| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function onlySideEffects2 |
6+
| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function |
7+
| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function |

javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,7 @@
7979
import { filter } from 'lodash'
8080
var bar = filter([1,2,4], x => { equals(x, 3) } ) // NOT OK!
8181
console.log(bar);
82+
83+
var baz = [1,2,3].filter(n => {n === 3}) // OK
84+
console.log(baz);
8285
})();

0 commit comments

Comments
 (0)