Skip to content

explicit java Function<X,Y> implementation is not tainted? #15494

Open
@odipar

Description

@odipar

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"

Metadata

Metadata

Assignees

No one assigned

    Labels

    JavaquestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions