codeql
codeql copied to clipboard
explicit java Function<X,Y> implementation is not tainted?
I hit on an issue while implementing a taint tracking use case. So I've prepared a minimal example that showcases the issue: Here is the java code:
import java.util.Optional;
import java.util.function.Function;
public class SourceToSinkBug {
public class DoubleToString implements Function<Double, String> {
public String apply(Double x) { return x.toString(); }
}
public String flow0() { // toString() is tainted
Double source0 = 1.0;
String sink0 = source0.toString();
return sink0;
}
public String flow1() { // Lambda is tainted
Double source1 = 1.0;
Optional<Double> opt1 = Optional.of(source1);
Optional<String> map1 = opt1.map(x -> x.toString());
String sink1 = map1.get();
return sink1;
}
public String flow2() { // BUG?: DoubleToString *isn't* tainted?
Double source2 = 2.0;
Optional<Double> opt2 = Optional.of(source2);
Optional<String> map2 = opt2.map(new DoubleToString());
String sink2 = map2.get();
return sink2;
}
public String flow3() { // Inline function is tainted
Double source3 = 3.0;
Optional<Double> opt3 = Optional.of(source3);
Optional<String> map3 = opt3.map(
new Function<Double,String>(){ public String apply(Double x) { return x.toString(); }});
String sink3 = map3.get();
return sink3;
}
}
I expect all flows to be in the query result when we taint source(x) with sink(x). However flow2 is not reported?
Here is the codeql query:
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
class Source1 extends VarAccess {
Source1() { this.getVariable().getName().matches("source%")}
}
class Sink1 extends VarAccess {
Sink1() { this.getVariable().getName().matches("sink%") }
}
// source% to sink%
module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof Source1 }
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof Sink1 }
}
module MyFlow = TaintTracking::Global<Config>;
from DataFlow::Node source, DataFlow::Node sink
where MyFlow::flow(source, sink)
select source, sink, "source to sink"