|
| 1 | +/** Provides definitions related to `java.io.InputStream`. */ |
| 2 | + |
| 3 | +import java |
| 4 | +private import semmle.code.java.dataflow.DataFlow |
| 5 | +private import semmle.code.java.dataflow.FlowSteps |
| 6 | +private import semmle.code.java.dataflow.SSA |
| 7 | +private import semmle.code.java.dataflow.TaintTracking |
| 8 | + |
| 9 | +/** |
| 10 | + * A jump taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method |
| 11 | + * to a class instance expression of the type extending `InputStream`. |
| 12 | + * |
| 13 | + * This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will |
| 14 | + * normally only happen in nested classes. |
| 15 | + */ |
| 16 | +private class InputStreamWrapperCapturedJumpStep extends AdditionalTaintStep { |
| 17 | + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { |
| 18 | + exists(InputStreamRead m, NestedClass wrapper | |
| 19 | + m.getDeclaringType() = wrapper and |
| 20 | + wrapper.getASourceSupertype+() instanceof TypeInputStream |
| 21 | + | |
| 22 | + n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and |
| 23 | + n2.asExpr() |
| 24 | + .(ClassInstanceExpr) |
| 25 | + .getConstructedType() |
| 26 | + .getASourceSupertype*() |
| 27 | + .getSourceDeclaration() = wrapper |
| 28 | + ) |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +/** |
| 33 | + * A local taint step from the definition of a captured variable, the capturer of which |
| 34 | + * updates the `bytes[]` parameter in an override of the `InputStream.read` method, |
| 35 | + * to a class instance expression of the type extending `InputStream`. |
| 36 | + * |
| 37 | + * This models how a subtype of `InputStream` could be tainted by capturing tainted variables in |
| 38 | + * the definition of its methods. |
| 39 | + */ |
| 40 | +private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep { |
| 41 | + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { |
| 42 | + exists(InputStreamRead m, NestedClass wrapper, SsaVariable captured, SsaImplicitInit capturer | |
| 43 | + wrapper.getASourceSupertype+() instanceof TypeInputStream and |
| 44 | + m.getDeclaringType() = wrapper and |
| 45 | + capturer.captures(captured) and |
| 46 | + TaintTracking::localTaint(DataFlow::exprNode(capturer.getAFirstUse()), |
| 47 | + any(DataFlow::PostUpdateNode pun | |
| 48 | + pun.getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() |
| 49 | + )) and |
| 50 | + n2.asExpr() |
| 51 | + .(ClassInstanceExpr) |
| 52 | + .getConstructedType() |
| 53 | + .getASourceSupertype*() |
| 54 | + .getSourceDeclaration() = wrapper |
| 55 | + | |
| 56 | + n1.asExpr() = captured.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() |
| 57 | + or |
| 58 | + captured.(SsaImplicitInit).isParameterDefinition(n1.asParameter()) |
| 59 | + ) |
| 60 | + } |
| 61 | +} |
| 62 | + |
| 63 | +/** |
| 64 | + * A taint step from an `InputStream` argument of the constructor of an `InputStream` subtype |
| 65 | + * to the call of the constructor, only if the argument is assigned to a class field. |
| 66 | + * |
| 67 | + * This models how it's assumed that an `InputStream` wrapper is tainted by the wrapped stream, |
| 68 | + * and is a workaround to low `fieldFlowBranchLimit`s in dataflow configurations. |
| 69 | + */ |
| 70 | +private class InputStreamWrapperConstructorStep extends AdditionalTaintStep { |
| 71 | + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { |
| 72 | + exists(ClassInstanceExpr cc, Argument a, AssignExpr ae, int pos | |
| 73 | + cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and |
| 74 | + cc.getArgument(pragma[only_bind_into](pos)) = a and |
| 75 | + cc.getCallee().getParameter(pragma[only_bind_into](pos)).getAnAccess() = ae.getRhs() and |
| 76 | + ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof |
| 77 | + TypeInputStream |
| 78 | + | |
| 79 | + n1.asExpr() = a and |
| 80 | + n2.asExpr() = cc |
| 81 | + ) |
| 82 | + } |
| 83 | +} |
| 84 | + |
| 85 | +private class InputStreamRead extends Method { |
| 86 | + InputStreamRead() { |
| 87 | + this.hasName("read") and |
| 88 | + this.getDeclaringType().getASourceSupertype*() instanceof TypeInputStream |
| 89 | + } |
| 90 | +} |
0 commit comments