Merge pull request #2203 from erik-krogh/ignorePureFunction

Approved by max-schaefer, mchammer01
This commit is contained in:
semmle-qlci
2019-11-06 09:09:11 +00:00
committed by GitHub
9 changed files with 119 additions and 0 deletions

View File

@@ -37,5 +37,6 @@
+ semmlecode-javascript-queries/RegExp/UnboundBackref.ql: /Correctness/Regular Expressions
+ semmlecode-javascript-queries/RegExp/UnmatchableCaret.ql: /Correctness/Regular Expressions
+ semmlecode-javascript-queries/RegExp/UnmatchableDollar.ql: /Correctness/Regular Expressions
+ semmlecode-javascript-queries/Statements/IgnoreArrayResult.ql: /Correctness/Statements
+ semmlecode-javascript-queries/Statements/InconsistentLoopOrientation.ql: /Correctness/Statements
+ semmlecode-javascript-queries/Statements/UnreachableStatement.ql: /Correctness/Statements

View File

@@ -0,0 +1,48 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
The <code>concat</code>, <code>join</code> and <code>slice</code> methods are
pure and do not modify any of the inputs or the array the method is called
on. It is therefore generally an error to ignore the return value from a call
to one of these methods.
</p>
</overview>
<recommendation>
<p>
Use the returned value from the calls to <code>concat</code>, <code>join</code>
or <code>slice</code>.
</p>
</recommendation>
<example>
<p>
A function <code>extend</code> is defined in the following example. The
function uses the <code>concat</code> method to add elements to the
<code>arr</code> array. However, the <code>extend</code> function has no
effect as the return value from <code>concat</code> is ignored:
</p>
<sample src="examples/IgnoreArrayResult.js" />
<p>
Assigning the returned value from the call to <code>concat</code> to the
<code>arr</code> variable fixes the error:
</p>
<sample src="examples/IgnoreArrayResultFixed.js" />
</example>
<references>
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat">Array concat</a>.</li>
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">Array slice</a>.</li>
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join">Array join</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,45 @@
/**
* @name Ignoring result from pure array method
* @description Ignoring the result of an array method that does not modify its receiver is generally an error.
* @kind problem
* @problem.severity warning
* @id js/ignore-array-result
* @tags maintainability
* correctness
* @precision high
*/
import javascript
import Expressions.ExprHasNoEffect
DataFlow::SourceNode callsArray(DataFlow::TypeBackTracker t, DataFlow::MethodCallNode call) {
isIgnoredPureArrayCall(call) and
t.start() and
result = call.getReceiver().getALocalSource()
or
exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t))
}
DataFlow::SourceNode callsArray(DataFlow::MethodCallNode call) {
result = callsArray(DataFlow::TypeBackTracker::end(), call)
}
predicate isIgnoredPureArrayCall(DataFlow::MethodCallNode call) {
inVoidContext(call.asExpr()) and
(
call.getMethodName() = "concat" and
call.getNumArgument() = 1
or
call.getMethodName() = "join" and
call.getNumArgument() < 2
or
call.getMethodName() = "slice" and
call.getNumArgument() < 3
)
}
from DataFlow::MethodCallNode call
where
callsArray(call) instanceof DataFlow::ArrayCreationNode and
not call.getReceiver().asExpr().(ArrayExpr).getSize() = 0
select call, "Result from call to " + call.getMethodName() + " ignored."

View File

@@ -0,0 +1,5 @@
var arr = [1,2,3];
function extend(others) {
arr.concat(others);
}

View File

@@ -0,0 +1,5 @@
var arr = [1,2,3];
function extend(others) {
arr = arr.concat(others);
}

View File

@@ -0,0 +1,2 @@
| tst.js:3:1:3:19 | arr.concat([1,2,3]) | Result from call to concat ignored. |
| tst.js:5:1:5:15 | arr.concat(arr) | Result from call to concat ignored. |

View File

@@ -0,0 +1 @@
Statements/IgnoreArrayResult.ql

View File

@@ -0,0 +1,11 @@
var arr = [1,2,3];
arr.concat([1,2,3]); // NOT OK!
arr.concat(arr); // NOT OK!
console.log(arr.concat([1,2,3]));
({concat: Array.prototype.concat}.concat(arr));
[].concat([1,2,3]);