diff --git a/java/ql/src/semmle/code/java/JDK.qll b/java/ql/src/semmle/code/java/JDK.qll index 7bc072e177cb..1e6d730943ac 100644 --- a/java/ql/src/semmle/code/java/JDK.qll +++ b/java/ql/src/semmle/code/java/JDK.qll @@ -3,6 +3,7 @@ */ import Member +import semmle.code.java.security.ExternalProcess // --- Standard types --- /** The class `java.lang.Object`. */ @@ -176,24 +177,37 @@ class TypeFile extends Class { } // --- Standard methods --- +/** + * Any constructor of class `java.lang.ProcessBuilder`. + */ +class ProcessBuilderConstructor extends Constructor, ExecCallable { + ProcessBuilderConstructor() { this.getDeclaringType() instanceof TypeProcessBuilder } + + override int getAnExecutedArgument() { result = 0 } +} + /** * Any of the methods named `command` on class `java.lang.ProcessBuilder`. */ -class MethodProcessBuilderCommand extends Method { +class MethodProcessBuilderCommand extends Method, ExecCallable { MethodProcessBuilderCommand() { hasName("command") and getDeclaringType() instanceof TypeProcessBuilder } + + override int getAnExecutedArgument() { result = 0 } } /** * Any method named `exec` on class `java.lang.Runtime`. */ -class MethodRuntimeExec extends Method { +class MethodRuntimeExec extends Method, ExecCallable { MethodRuntimeExec() { hasName("exec") and getDeclaringType() instanceof TypeRuntime } + + override int getAnExecutedArgument() { result = 0 } } /** diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Exec.qll b/java/ql/src/semmle/code/java/frameworks/apache/Exec.qll index e24428d6fdc2..978154d3274b 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Exec.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Exec.qll @@ -1,20 +1,28 @@ /* Definitions related to the Apache Commons Exec library. */ import semmle.code.java.Type +import semmle.code.java.security.ExternalProcess -library class TypeCommandLine extends Class { +/** The class `org.apache.commons.exec.CommandLine`. */ +private class TypeCommandLine extends Class { TypeCommandLine() { hasQualifiedName("org.apache.commons.exec", "CommandLine") } } -library class MethodCommandLineParse extends Method { +/** The `parse()` method of the class `org.apache.commons.exec.CommandLine`. */ +private class MethodCommandLineParse extends Method, ExecCallable { MethodCommandLineParse() { getDeclaringType() instanceof TypeCommandLine and hasName("parse") } + + override int getAnExecutedArgument() { result = 0 } } -library class MethodCommandLineAddArguments extends Method { +/** The `addArguments()` method of the class `org.apache.commons.exec.CommandLine`. */ +private class MethodCommandLineAddArguments extends Method, ExecCallable { MethodCommandLineAddArguments() { getDeclaringType() instanceof TypeCommandLine and hasName("addArguments") } + + override int getAnExecutedArgument() { result = 0 } } diff --git a/java/ql/src/semmle/code/java/security/ExternalProcess.qll b/java/ql/src/semmle/code/java/security/ExternalProcess.qll index 93d7acd81530..fe5e46d5efbf 100644 --- a/java/ql/src/semmle/code/java/security/ExternalProcess.qll +++ b/java/ql/src/semmle/code/java/security/ExternalProcess.qll @@ -1,7 +1,20 @@ /* Definitions related to external processes. */ import semmle.code.java.Member -import semmle.code.java.JDK -import semmle.code.java.frameworks.apache.Exec + +private module Instances { + private import semmle.code.java.JDK + private import semmle.code.java.frameworks.apache.Exec +} + +/** + * A callable that executes a command. + */ +abstract class ExecCallable extends Callable { + /** + * Gets the index of an argument that will be part of the command that is executed. + */ + abstract int getAnExecutedArgument(); +} /** * An expression used as an argument to a call that executes an external command. For calls to @@ -10,21 +23,10 @@ import semmle.code.java.frameworks.apache.Exec */ class ArgumentToExec extends Expr { ArgumentToExec() { - exists(MethodAccess execCall, Method method | - execCall.getArgument(0) = this and - method = execCall.getMethod() and - ( - method instanceof MethodRuntimeExec or - method instanceof MethodProcessBuilderCommand or - method instanceof MethodCommandLineParse or - method instanceof MethodCommandLineAddArguments - ) - ) - or - exists(ConstructorCall expr, Constructor cons | - expr.getConstructor() = cons and - cons.getDeclaringType().hasQualifiedName("java.lang", "ProcessBuilder") and - expr.getArgument(0) = this + exists(Call execCall, ExecCallable execCallable, int i | + execCall.getArgument(pragma[only_bind_into](i)) = this and + execCallable = execCall.getCallee() and + i = execCallable.getAnExecutedArgument() ) } }