Skip to content

Commit 04f0c22

Browse files
authored
Merge pull request #2203 from erik-krogh/ignorePureFunction
Approved by max-schaefer, mchammer01
2 parents e9336fe + df3c70e commit 04f0c22

File tree

9 files changed

+119
-0
lines changed

9 files changed

+119
-0
lines changed

change-notes/1.23/analysis-javascript.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
| Use of returnless function (`js/use-of-returnless-function`) | maintainability, correctness | Highlights calls where the return value is used, but the callee never returns a value. Results are shown on LGTM by default. |
2828
| Useless regular expression character escape (`js/useless-regexp-character-escape`) | correctness, security, external/cwe/cwe-20 | Highlights regular expression strings with useless character escapes, indicating a possible violation of [CWE-20](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default. |
2929
| Unreachable method overloads (`js/unreachable-method-overloads`) | correctness, typescript | Highlights method overloads that are impossible to use from client code. Results are shown on LGTM by default. |
30+
| Ignoring result from pure array method (`js/ignore-array-result`) | maintainability, correctness | Highlights calls to array methods without side effects where the return value is ignored. Results are shown on LGTM by default. |
3031

3132
## Changes to existing queries
3233

javascript/config/suites/javascript/correctness-core

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,6 @@
3737
+ semmlecode-javascript-queries/RegExp/UnboundBackref.ql: /Correctness/Regular Expressions
3838
+ semmlecode-javascript-queries/RegExp/UnmatchableCaret.ql: /Correctness/Regular Expressions
3939
+ semmlecode-javascript-queries/RegExp/UnmatchableDollar.ql: /Correctness/Regular Expressions
40+
+ semmlecode-javascript-queries/Statements/IgnoreArrayResult.ql: /Correctness/Statements
4041
+ semmlecode-javascript-queries/Statements/InconsistentLoopOrientation.ql: /Correctness/Statements
4142
+ semmlecode-javascript-queries/Statements/UnreachableStatement.ql: /Correctness/Statements
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>
7+
The <code>concat</code>, <code>join</code> and <code>slice</code> methods are
8+
pure and do not modify any of the inputs or the array the method is called
9+
on. It is therefore generally an error to ignore the return value from a call
10+
to one of these methods.
11+
</p>
12+
13+
</overview>
14+
<recommendation>
15+
16+
<p>
17+
Use the returned value from the calls to <code>concat</code>, <code>join</code>
18+
or <code>slice</code>.
19+
</p>
20+
21+
</recommendation>
22+
<example>
23+
24+
<p>
25+
A function <code>extend</code> is defined in the following example. The
26+
function uses the <code>concat</code> method to add elements to the
27+
<code>arr</code> array. However, the <code>extend</code> function has no
28+
effect as the return value from <code>concat</code> is ignored:
29+
</p>
30+
31+
<sample src="examples/IgnoreArrayResult.js" />
32+
33+
<p>
34+
Assigning the returned value from the call to <code>concat</code> to the
35+
<code>arr</code> variable fixes the error:
36+
</p>
37+
38+
<sample src="examples/IgnoreArrayResultFixed.js" />
39+
40+
</example>
41+
<references>
42+
43+
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat">Array concat</a>.</li>
44+
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">Array slice</a>.</li>
45+
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join">Array join</a>.</li>
46+
47+
</references>
48+
</qhelp>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* @name Ignoring result from pure array method
3+
* @description Ignoring the result of an array method that does not modify its receiver is generally an error.
4+
* @kind problem
5+
* @problem.severity warning
6+
* @id js/ignore-array-result
7+
* @tags maintainability
8+
* correctness
9+
* @precision high
10+
*/
11+
12+
import javascript
13+
import Expressions.ExprHasNoEffect
14+
15+
DataFlow::SourceNode callsArray(DataFlow::TypeBackTracker t, DataFlow::MethodCallNode call) {
16+
isIgnoredPureArrayCall(call) and
17+
t.start() and
18+
result = call.getReceiver().getALocalSource()
19+
or
20+
exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t))
21+
}
22+
23+
DataFlow::SourceNode callsArray(DataFlow::MethodCallNode call) {
24+
result = callsArray(DataFlow::TypeBackTracker::end(), call)
25+
}
26+
27+
predicate isIgnoredPureArrayCall(DataFlow::MethodCallNode call) {
28+
inVoidContext(call.asExpr()) and
29+
(
30+
call.getMethodName() = "concat" and
31+
call.getNumArgument() = 1
32+
or
33+
call.getMethodName() = "join" and
34+
call.getNumArgument() < 2
35+
or
36+
call.getMethodName() = "slice" and
37+
call.getNumArgument() < 3
38+
)
39+
}
40+
41+
from DataFlow::MethodCallNode call
42+
where
43+
callsArray(call) instanceof DataFlow::ArrayCreationNode and
44+
not call.getReceiver().asExpr().(ArrayExpr).getSize() = 0
45+
select call, "Result from call to " + call.getMethodName() + " ignored."
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var arr = [1,2,3];
2+
3+
function extend(others) {
4+
arr.concat(others);
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var arr = [1,2,3];
2+
3+
function extend(others) {
4+
arr = arr.concat(others);
5+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| tst.js:3:1:3:19 | arr.concat([1,2,3]) | Result from call to concat ignored. |
2+
| tst.js:5:1:5:15 | arr.concat(arr) | Result from call to concat ignored. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Statements/IgnoreArrayResult.ql
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var arr = [1,2,3];
2+
3+
arr.concat([1,2,3]); // NOT OK!
4+
5+
arr.concat(arr); // NOT OK!
6+
7+
console.log(arr.concat([1,2,3]));
8+
9+
({concat: Array.prototype.concat}.concat(arr));
10+
11+
[].concat([1,2,3]);

0 commit comments

Comments
 (0)