diff --git a/java/ql/lib/semmle/code/java/JDK.qll b/java/ql/lib/semmle/code/java/JDK.qll index c0c388f9308..6372b22c8f4 100644 --- a/java/ql/lib/semmle/code/java/JDK.qll +++ b/java/ql/lib/semmle/code/java/JDK.qll @@ -4,7 +4,6 @@ import Member import semmle.code.java.security.ExternalProcess -private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.FlowSteps // --- Standard types --- @@ -203,48 +202,6 @@ class TypeFile extends Class { TypeFile() { this.hasQualifiedName("java.io", "File") } } -/** - * A taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method - * to a class instance expression of the type extending `InputStream`. - * - * This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will - * normally only happen in anonymous classes. - */ -private class InputStreamWrapperAnonymousStep extends AdditionalTaintStep { - override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(Method m, AnonymousClass wrapper | - m.hasName("read") and - m.getDeclaringType() = wrapper and - wrapper.getASourceSupertype+() instanceof TypeInputStream - | - n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and - n2.asExpr() = wrapper.getClassInstanceExpr() - ) - } -} - -/** - * A taint step from an `InputStream` argument of the constructor of an `InputStream` subtype - * to the call of the constructor, only if the argument is assigned to a class field. - * - * This models how it's assumed that an `InputStream` wrapper is tainted by the wrapped stream, - * and is a workaround to low `fieldFlowBranchLimit`s in dataflow configurations. - */ -private class InputStreamWrapperConstructorStep extends AdditionalTaintStep { - override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(ClassInstanceExpr cc, Argument a, AssignExpr ae, int pos | - cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and - cc.getArgument(pragma[only_bind_into](pos)) = a and - cc.getCallee().getParameter(pragma[only_bind_into](pos)).getAnAccess() = ae.getRhs() and - ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof - TypeInputStream - | - n1.asExpr() = a and - n2.asExpr() = cc - ) - } -} - // --- Standard methods --- /** * DEPRECATED: Any constructor of class `java.lang.ProcessBuilder`. diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll index 1619965f0f0..fef69bec7fd 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll @@ -20,11 +20,11 @@ private module Frameworks { private import semmle.code.java.frameworks.Guice private import semmle.code.java.frameworks.IoJsonWebToken private import semmle.code.java.frameworks.jackson.JacksonSerializability + private import semmle.code.java.frameworks.InputStream private import semmle.code.java.frameworks.Properties private import semmle.code.java.frameworks.Protobuf private import semmle.code.java.frameworks.ratpack.RatpackExec private import semmle.code.java.frameworks.stapler.Stapler - private import semmle.code.java.JDK } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/InputStream.qll b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll new file mode 100644 index 00000000000..e0c524bd1a4 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/InputStream.qll @@ -0,0 +1,47 @@ +/** Provides definitions related to `java.io.InputStream`. */ + +import java +private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.dataflow.FlowSteps + +/** + * A taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method + * to a class instance expression of the type extending `InputStream`. + * + * This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will + * normally only happen in anonymous classes. + */ +private class InputStreamWrapperAnonymousStep extends AdditionalTaintStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(Method m, AnonymousClass wrapper | + m.hasName("read") and + m.getDeclaringType() = wrapper and + wrapper.getASourceSupertype+() instanceof TypeInputStream + | + n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and + n2.asExpr() = wrapper.getClassInstanceExpr() + ) + } +} + +/** + * A taint step from an `InputStream` argument of the constructor of an `InputStream` subtype + * to the call of the constructor, only if the argument is assigned to a class field. + * + * This models how it's assumed that an `InputStream` wrapper is tainted by the wrapped stream, + * and is a workaround to low `fieldFlowBranchLimit`s in dataflow configurations. + */ +private class InputStreamWrapperConstructorStep extends AdditionalTaintStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(ClassInstanceExpr cc, Argument a, AssignExpr ae, int pos | + cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and + cc.getArgument(pragma[only_bind_into](pos)) = a and + cc.getCallee().getParameter(pragma[only_bind_into](pos)).getAnAccess() = ae.getRhs() and + ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof + TypeInputStream + | + n1.asExpr() = a and + n2.asExpr() = cc + ) + } +}