mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge pull request #5411 from aschackmull/java/dataflow-lambda-dispatch
Java: Bugfix dispatch to lambda in call context.
This commit is contained in:
@@ -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.
|
||||
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
63
java/ql/test/library-tests/dataflow/lambda/Executor.java
Normal file
63
java/ql/test/library-tests/dataflow/lambda/Executor.java
Normal file
@@ -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) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
java/ql/test/library-tests/dataflow/lambda/flow.expected
Normal file
8
java/ql/test/library-tests/dataflow/lambda/flow.expected
Normal file
@@ -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
java/ql/test/library-tests/dataflow/lambda/flow.ql
Normal file
24
java/ql/test/library-tests/dataflow/lambda/flow.ql
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user