Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ private module DispatchImpl {
)
}

private RefType getPreciseType(Expr e) {
result = e.(FunctionalExpr).getConstructedType()
or
not e instanceof FunctionalExpr and result = e.getType()
}

/**
* Holds if the `i`th argument of `ctx` has type `t` and `ctx` is a
* relevant call context.
Expand All @@ -55,7 +61,7 @@ private module DispatchImpl {
ctx.getArgument(i) = arg
|
src = variableTrack(arg) and
srctype = src.getType() and
srctype = getPreciseType(src) and
if src instanceof ClassInstanceExpr then exact = true else exact = false
)
or
Expand All @@ -67,11 +73,9 @@ private module DispatchImpl {
if ctx instanceof ClassInstanceExpr then exact = true else exact = false
)
|
exists(TypeVariable v | v = srctype |
t = v.getUpperBoundType+() and not t instanceof TypeVariable
)
t = srctype.(BoundedType).getAnUltimateUpperBoundType()
or
t = srctype and not srctype instanceof TypeVariable
t = srctype and not srctype instanceof BoundedType
)
}

Expand Down
63 changes: 63 additions & 0 deletions java/ql/test/library-tests/dataflow/lambda/Executor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import java.lang.Runtime;
import java.util.function.Function;

public class Executor {

private static final Processor<String> processor = new Processor<String>();

private static String source() { return "taint"; }

public static void main(String[] args) {
exec1(source());
exec2(source());
exec3(source());
exec4(source());
exec5(source());
}

private static void exec1(String command){
command = process(s->s.toUpperCase(),command);
exec(command);
}

private static void exec2(String command){
command = process(s->"Taint stops here.",command);
exec(command);
}

private static void exec3(String command){
command = processor.process(s->s.toUpperCase(),command);
exec(command);
}

private static void exec4(String command){
command = processor.process(s->"Taint stops here.",command);
exec_b(command);
}

private static void exec5(String command){
command = processor.process(s->s.toUpperCase(),command);
exec_b(command);
}

public static String process(Function<String, String> fun, String command){
return processor.process(fun, command);
}

private static void exec(String command){
command = process(s->s.trim(),command);
try {
Runtime.getRuntime().exec(command);
}
catch(Exception e) {}
}

private static void exec_b(String command){
command = processor.process(s->s.trim(),command);
try {
Runtime.getRuntime().exec(command);
}
catch(Exception e) {}
}
}

9 changes: 9 additions & 0 deletions java/ql/test/library-tests/dataflow/lambda/Processor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import java.util.function.Function;

public class Processor<T> {

public <R> R process(Function<T,R> function, T arg) {
return function.apply(arg);
}
}

30 changes: 30 additions & 0 deletions java/ql/test/library-tests/dataflow/lambda/StringProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import java.util.function.Function;

public class StringProcessor {

private static final Processor<String> processor = new Processor<String>();

public static void main(String[] args) {
String command = args[0];
lambdaExec(command);
}

public static void lambdaExec(String command){
processor.process(s->exec(s), command);
}

public static String lambdaUnrelated(String command){
return processor.process(s->s+"not related to anything", command);
}

public static String exec(String command){
try {
command = processor.process(s->s.trim(), command);
Runtime.getRuntime().exec(command);
return "Executed: "+command;
} catch(Exception e) {
return null;
}
}
}

8 changes: 8 additions & 0 deletions java/ql/test/library-tests/dataflow/lambda/flow.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
| Executor.java:11:15:11:22 | source(...) | Executor.java:50:39:50:45 | command |
| Executor.java:11:15:11:22 | source(...) | StringProcessor.java:23:39:23:45 | command |
| Executor.java:12:15:12:22 | source(...) | Executor.java:50:39:50:45 | command |
| Executor.java:12:15:12:22 | source(...) | StringProcessor.java:23:39:23:45 | command |
| Executor.java:13:15:13:22 | source(...) | Executor.java:50:39:50:45 | command |
| Executor.java:13:15:13:22 | source(...) | StringProcessor.java:23:39:23:45 | command |
| Executor.java:15:15:15:22 | source(...) | Executor.java:58:39:58:45 | command |
| StringProcessor.java:8:26:8:29 | args | StringProcessor.java:23:39:23:45 | command |
24 changes: 24 additions & 0 deletions java/ql/test/library-tests/dataflow/lambda/flow.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import java
import semmle.code.java.dataflow.TaintTracking

class Conf extends TaintTracking::Configuration {
Conf() { this = "qltest lambda" }

override predicate isSource(DataFlow::Node src) {
src.asExpr().(VarAccess).getVariable().hasName("args")
or
src.asExpr().(MethodAccess).getMethod().hasName("source")
}

override predicate isSink(DataFlow::Node sink) {
sink.asExpr().(Argument).getCall() =
any(MethodAccess ma |
ma.getMethod().hasName("exec") and
ma.getQualifier().(MethodAccess).getMethod().hasName("getRuntime")
)
}
}

from DataFlow::Node src, DataFlow::Node sink, Conf c
where c.hasFlow(src, sink)
select src, sink