Open
Description
Version
CodeQL extension version: 1.12.0
CodeQL CLI version: 2.15.5
Platform: win32 x64
Dependencies:
codeql/java-all: 0.8.5
Description
It looks like taint tracking erroneously reports that taint flows "backwards" from an array element assignment.
For example:
void arrayAssign() {
String[] s = {"a"};
s[0] = source(sink(s[0]));
}
Here it erroneously reports that there is taint flow from source
to sink
, even though sink
is actually executed before source
, so there should not be any flow between them.
Here is also real world code where this occurs: apache/logging-log4j2
(my query considered the output of String.format
as source, and an argument to String.format
as sink)
Steps to reproduce
Java code:
class FlowTest {
<T> T source(T o) {
return o;
}
<T> T sink(T o) {
return o;
}
void varAssign() {
String s = "a";
s = source(sink(s));
}
void arrayAssign() {
String[] s = {"a"};
// Erroneously reports flow from `source` to `sink`
s[0] = source(sink(s[0]));
}
}
CodeQL query:
/**
* @kind problem
*/
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
class Source extends DataFlow::Node {
Source() {
exists(Method m |
m = this.asExpr().(MethodCall).getMethod().getSourceDeclaration() and
m.hasName("source") and
m.fromSource()
)
}
}
class Sink extends DataFlow::Node {
Sink() {
exists(MethodCall call, Method m |
call.getAnArgument() = this.asExpr() and
m = call.getMethod().getSourceDeclaration() and
m.hasName("sink") and
m.fromSource()
)
}
}
from Source source, Sink sink, string type
where
type = "dataflow" and DataFlow::localFlow(source, sink)
or
type = "taint" and TaintTracking::localTaint(source, sink)
select sink, type + " from $@", source, "source"