mirror of
https://github.com/github/codeql.git
synced 2025-12-24 12:46:34 +01:00
introduce backtracking, and also marking join/slice calls
This commit is contained in:
@@ -4,16 +4,18 @@
|
|||||||
<qhelp>
|
<qhelp>
|
||||||
<overview>
|
<overview>
|
||||||
<p>
|
<p>
|
||||||
The <code>concat</code> method on is pure and does not modify any of the input
|
The <code>concat</code>, <code>join</code> and <code>slice</code> methods are
|
||||||
arrays. It is therefore generally an error to ignore the return value from a
|
pure and does not modify any of the inputs or the array the method was called
|
||||||
call to <code>concat</code>.
|
on. It is therefore generally an error to ignore the return value from a call
|
||||||
|
to one of these methods.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</overview>
|
</overview>
|
||||||
<recommendation>
|
<recommendation>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Use the returned value from the call to <code>concat</code>.
|
Use the returned value from the calls to <code>concat</code>, <code>join</code>
|
||||||
|
or <code>slice</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</recommendation>
|
</recommendation>
|
||||||
@@ -26,19 +28,21 @@ function uses the <code>concat</code> method to add elements to the
|
|||||||
effect as the return value from <code>concat</code> is ignored.
|
effect as the return value from <code>concat</code> is ignored.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<sample src="examples/IgnoreConcat.js" />
|
<sample src="examples/IgnoreArrayResult.js" />
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Assigning the returned value from the call to <code>concat</code> to the
|
Assigning the returned value from the call to <code>concat</code> to the
|
||||||
<code>arr</code> variable fixes the error.
|
<code>arr</code> variable fixes the error.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<sample src="examples/IgnoreConcatFixed.js" />
|
<sample src="examples/IgnoreArrayResultFixed.js" />
|
||||||
|
|
||||||
</example>
|
</example>
|
||||||
<references>
|
<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/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>
|
</references>
|
||||||
</qhelp>
|
</qhelp>
|
||||||
45
javascript/ql/src/Statements/IgnoreArrayResult.ql
Normal file
45
javascript/ql/src/Statements/IgnoreArrayResult.ql
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* @name Ignoring result from pure array method
|
||||||
|
* @description The array methods do not modify the array, ignoring the result of such a call is therefore 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()
|
||||||
|
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
|
||||||
|
select call, "Result from call to " + call.getMethodName() + " ignored."
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/**
|
|
||||||
* @name Ignoring return from concat
|
|
||||||
* @description The concat method does not modify an array, ignoring the result of a call to concat is therefore generally an error.
|
|
||||||
* @kind problem
|
|
||||||
* @problem.severity warning
|
|
||||||
* @id js/ignore-result-from-concat
|
|
||||||
* @tags maintainability,
|
|
||||||
* correctness
|
|
||||||
* @precision high
|
|
||||||
*/
|
|
||||||
|
|
||||||
import javascript
|
|
||||||
import Expressions.ExprHasNoEffect
|
|
||||||
|
|
||||||
DataFlow::SourceNode array(DataFlow::TypeTracker t) {
|
|
||||||
t.start() and
|
|
||||||
result instanceof DataFlow::ArrayCreationNode
|
|
||||||
or
|
|
||||||
exists (DataFlow::TypeTracker t2 |
|
|
||||||
result = array(t2).track(t2, t)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) }
|
|
||||||
|
|
||||||
predicate isArrayMethod(DataFlow::MethodCallNode call) {
|
|
||||||
call.getReceiver().getALocalSource() = array()
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate isIncomplete(DataFlow::Node node) {
|
|
||||||
any(DataFlow::Incompleteness cause | node.analyze().getAValue().isIndefinite(cause)) != "global"
|
|
||||||
}
|
|
||||||
|
|
||||||
from DataFlow::CallNode call
|
|
||||||
where
|
|
||||||
isArrayMethod(call) and
|
|
||||||
call.getCalleeName() = "concat" and
|
|
||||||
call.getNumArgument() = 1 and
|
|
||||||
(call.getArgument(0).getALocalSource() = array() or isIncomplete(call.getArgument(0))) and
|
|
||||||
not call.getArgument(0).asExpr().(ArrayExpr).getSize() = 0 and
|
|
||||||
inVoidContext(call.asExpr())
|
|
||||||
select call, "Return value from call to concat ignored."
|
|
||||||
Reference in New Issue
Block a user