Merge pull request #7002 from aschackmull/java/field-node

Java: Add FieldValueNode to break up cartesian step relation.
This commit is contained in:
Anders Schack-Mulligen
2021-11-08 09:31:42 +01:00
committed by GitHub
10 changed files with 99 additions and 47 deletions

View File

@@ -8,9 +8,9 @@ private import semmle.code.java.dispatch.VirtualDispatch as VirtualDispatch
private module DispatchImpl { private module DispatchImpl {
/** Gets a viable implementation of the target of the given `Call`. */ /** Gets a viable implementation of the target of the given `Call`. */
DataFlowCallable viableCallable(DataFlowCall c) { DataFlowCallable viableCallable(DataFlowCall c) {
result = VirtualDispatch::viableCallable(c.asCall()) result.asCallable() = VirtualDispatch::viableCallable(c.asCall())
or or
result.(SummarizedCallable) = c.asCall().getCallee().getSourceDeclaration() result.(SummarizedCallable).asCallable() = c.asCall().getCallee().getSourceDeclaration()
} }
/** /**
@@ -93,31 +93,32 @@ private module DispatchImpl {
* qualifier is a parameter of the enclosing callable `c`. * qualifier is a parameter of the enclosing callable `c`.
*/ */
predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable c) { predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable c) {
mayBenefitFromCallContext(call.asCall(), c, _) mayBenefitFromCallContext(call.asCall(), c.asCallable(), _)
} }
/** /**
* Gets a viable dispatch target of `call` in the context `ctx`. This is * Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference. * restricted to those `call`s for which a context might make a difference.
*/ */
Method viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
result = viableCallable(call) and result = viableCallable(call) and
exists(int i, Callable c, Method def, RefType t, boolean exact, MethodAccess ma | exists(int i, Callable c, Method def, RefType t, boolean exact, MethodAccess ma |
ma = call.asCall() and ma = call.asCall() and
mayBenefitFromCallContext(ma, c, i) and mayBenefitFromCallContext(ma, c, i) and
c = viableCallable(ctx) and c = viableCallable(ctx).asCallable() and
contextArgHasType(ctx.asCall(), i, t, exact) and contextArgHasType(ctx.asCall(), i, t, exact) and
ma.getMethod().getSourceDeclaration() = def ma.getMethod().getSourceDeclaration() = def
| |
exact = true and result = VirtualDispatch::exactMethodImpl(def, t.getSourceDeclaration()) exact = true and
result.asCallable() = VirtualDispatch::exactMethodImpl(def, t.getSourceDeclaration())
or or
exact = false and exact = false and
exists(RefType t2 | exists(RefType t2 |
result = VirtualDispatch::viableMethodImpl(def, t.getSourceDeclaration(), t2) and result.asCallable() = VirtualDispatch::viableMethodImpl(def, t.getSourceDeclaration(), t2) and
not failsUnification(t, t2) not failsUnification(t, t2)
) )
or or
result = def and def instanceof SummarizedCallable result.asCallable() = def and result instanceof SummarizedCallable
) )
} }

View File

@@ -14,14 +14,14 @@ newtype TNode =
not e.getParent*() instanceof Annotation not e.getParent*() instanceof Annotation
} or } or
TExplicitParameterNode(Parameter p) { TExplicitParameterNode(Parameter p) {
exists(p.getCallable().getBody()) or p.getCallable() instanceof SummarizedCallable exists(p.getCallable().getBody()) or p.getCallable() = any(SummarizedCallable sc).asCallable()
} or } or
TImplicitVarargsArray(Call c) { TImplicitVarargsArray(Call c) {
c.getCallee().isVarargs() and c.getCallee().isVarargs() and
not exists(Argument arg | arg.getCall() = c and arg.isExplicitVarargsArray()) not exists(Argument arg | arg.getCall() = c and arg.isExplicitVarargsArray())
} or } or
TInstanceParameterNode(Callable c) { TInstanceParameterNode(Callable c) {
(exists(c.getBody()) or c instanceof SummarizedCallable) and (exists(c.getBody()) or c = any(SummarizedCallable sc).asCallable()) and
not c.isStatic() not c.isStatic()
} or } or
TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
@@ -44,7 +44,8 @@ newtype TNode =
} or } or
TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) { TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state) FlowSummaryImpl::Private::summaryNodeRange(c, state)
} } or
TFieldValueNode(Field f)
private predicate explicitInstanceArgument(Call call, Expr instarg) { private predicate explicitInstanceArgument(Call call, Expr instarg) {
call instanceof MethodAccess and call instanceof MethodAccess and
@@ -94,19 +95,12 @@ module Public {
result = this.(MallocNode).getClassInstanceExpr().getType() result = this.(MallocNode).getClassInstanceExpr().getType()
or or
result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getType() result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getType()
or
result = this.(FieldValueNode).getField().getType()
} }
/** Gets the callable in which this node occurs. */ /** Gets the callable in which this node occurs. */
Callable getEnclosingCallable() { Callable getEnclosingCallable() { result = nodeGetEnclosingCallable(this).asCallable() }
result = this.asExpr().getEnclosingCallable() or
result = this.asParameter().getCallable() or
result = this.(ImplicitVarargsArray).getCall().getEnclosingCallable() or
result = this.(InstanceParameterNode).getCallable() or
result = this.(ImplicitInstanceAccess).getInstanceAccess().getEnclosingCallable() or
result = this.(MallocNode).getClassInstanceExpr().getEnclosingCallable() or
result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getEnclosingCallable() or
this = TSummaryInternalNode(result, _)
}
private Type getImprovedTypeBound() { private Type getImprovedTypeBound() {
exprTypeFlow(this.asExpr(), result, _) or exprTypeFlow(this.asExpr(), result, _) or
@@ -257,6 +251,18 @@ module Public {
abstract Node getPreUpdateNode(); abstract Node getPreUpdateNode();
} }
/**
* A node representing the value of a field.
*/
class FieldValueNode extends Node, TFieldValueNode {
/** Gets the field corresponding to this node. */
Field getField() { this = TFieldValueNode(result) }
override string toString() { result = getField().toString() }
override Location getLocation() { result = getField().getLocation() }
}
/** /**
* Gets the node that occurs as the qualifier of `fa`. * Gets the node that occurs as the qualifier of `fa`.
*/ */
@@ -305,11 +311,21 @@ private class ImplicitExprPostUpdate extends ImplicitPostUpdateNode, TImplicitEx
module Private { module Private {
/** Gets the callable in which this node occurs. */ /** Gets the callable in which this node occurs. */
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() } DataFlowCallable nodeGetEnclosingCallable(Node n) {
result.asCallable() = n.asExpr().getEnclosingCallable() or
result.asCallable() = n.asParameter().getCallable() or
result.asCallable() = n.(ImplicitVarargsArray).getCall().getEnclosingCallable() or
result.asCallable() = n.(InstanceParameterNode).getCallable() or
result.asCallable() = n.(ImplicitInstanceAccess).getInstanceAccess().getEnclosingCallable() or
result.asCallable() = n.(MallocNode).getClassInstanceExpr().getEnclosingCallable() or
result = nodeGetEnclosingCallable(n.(ImplicitPostUpdateNode).getPreUpdateNode()) or
n = TSummaryInternalNode(result, _) or
result.asFieldScope() = n.(FieldValueNode).getField()
}
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */ /** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
predicate isParameterNode(ParameterNode p, DataFlowCallable c, int pos) { predicate isParameterNode(ParameterNode p, DataFlowCallable c, int pos) {
p.isParameterOf(c, pos) p.isParameterOf(c.asCallable(), pos)
} }
/** /**

View File

@@ -32,12 +32,18 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
/** /**
* Holds if data can flow from `node1` to `node2` through a static field. * Holds if data can flow from `node1` to `node2` through a static field.
*/ */
private predicate staticFieldStep(ExprNode node1, ExprNode node2) { private predicate staticFieldStep(Node node1, Node node2) {
exists(Field f |
f.isStatic() and
f.getAnAssignedValue() = node1.asExpr() and
node2.(FieldValueNode).getField() = f
)
or
exists(Field f, FieldRead fr | exists(Field f, FieldRead fr |
f.isStatic() and f.isStatic() and
f.getAnAssignedValue() = node1.getExpr() and node1.(FieldValueNode).getField() = f and
fr.getField() = f and fr.getField() = f and
fr = node2.getExpr() and fr = node2.asExpr() and
hasNonlocalValue(fr) hasNonlocalValue(fr)
) )
} }
@@ -205,7 +211,30 @@ class CastNode extends ExprNode {
CastNode() { this.getExpr() instanceof CastExpr } CastNode() { this.getExpr() instanceof CastExpr }
} }
class DataFlowCallable = Callable; private newtype TDataFlowCallable =
TCallable(Callable c) or
TFieldScope(Field f)
class DataFlowCallable extends TDataFlowCallable {
Callable asCallable() { this = TCallable(result) }
Field asFieldScope() { this = TFieldScope(result) }
RefType getDeclaringType() {
result = asCallable().getDeclaringType() or
result = asFieldScope().getDeclaringType()
}
string toString() {
result = asCallable().toString() or
result = "Field scope: " + asFieldScope().toString()
}
Location getLocation() {
result = asCallable().getLocation() or
result = asFieldScope().getLocation()
}
}
class DataFlowExpr = Expr; class DataFlowExpr = Expr;
@@ -251,7 +280,9 @@ class SrcCall extends DataFlowCall, TCall {
SrcCall() { this = TCall(call) } SrcCall() { this = TCall(call) }
override DataFlowCallable getEnclosingCallable() { result = call.getEnclosingCallable() } override DataFlowCallable getEnclosingCallable() {
result.asCallable() = call.getEnclosingCallable()
}
override string toString() { result = call.toString() } override string toString() { result = call.toString() }
@@ -345,10 +376,10 @@ class LambdaCallKind = Method; // the "apply" method in the functional interface
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
exists(ClassInstanceExpr func, Interface t, FunctionalInterface interface | exists(ClassInstanceExpr func, Interface t, FunctionalInterface interface |
creation.asExpr() = func and creation.asExpr() = func and
func.getAnonymousClass().getAMethod() = c and func.getAnonymousClass().getAMethod() = c.asCallable() and
func.getConstructedType().extendsOrImplements+(t) and func.getConstructedType().extendsOrImplements+(t) and
t.getSourceDeclaration() = interface and t.getSourceDeclaration() = interface and
c.(Method).overridesOrInstantiates+(pragma[only_bind_into](kind)) and c.asCallable().(Method).overridesOrInstantiates+(pragma[only_bind_into](kind)) and
pragma[only_bind_into](kind) = interface.getRunMethod().getSourceDeclaration() pragma[only_bind_into](kind) = interface.getRunMethod().getSourceDeclaration()
) )
} }

View File

@@ -30,7 +30,7 @@ DataFlowType getContentType(Content c) { result = c.getType() }
/** Gets the return type of kind `rk` for callable `c`. */ /** Gets the return type of kind `rk` for callable `c`. */
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) {
result = getErasedRepr(c.getReturnType()) and result = getErasedRepr(c.asCallable().getReturnType()) and
exists(rk) exists(rk)
} }
@@ -62,7 +62,7 @@ predicate summaryElement(DataFlowCallable c, string input, string output, string
string namespace, string type, boolean subtypes, string name, string signature, string ext string namespace, string type, boolean subtypes, string name, string signature, string ext
| |
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind) and summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind) and
c = interpretElement(namespace, type, subtypes, name, signature, ext) c.asCallable() = interpretElement(namespace, type, subtypes, name, signature, ext)
) )
} }
@@ -119,7 +119,7 @@ class InterpretNode extends TInterpretNode {
DataFlowCall asCall() { result.asCall() = this.asElement() } DataFlowCall asCall() { result.asCall() = this.asElement() }
/** Gets the callable that this node corresponds to, if any. */ /** Gets the callable that this node corresponds to, if any. */
DataFlowCallable asCallable() { result = this.asElement() } DataFlowCallable asCallable() { result.asCallable() = this.asElement() }
/** Gets the target of this call, if any. */ /** Gets the target of this call, if any. */
Callable getCallTarget() { result = this.asCall().asCall().getCallee().getSourceDeclaration() } Callable getCallTarget() { result = this.asCall().asCall().getCallee().getSourceDeclaration() }

View File

@@ -189,10 +189,9 @@ private predicate flowStep(RelevantNode n1, RelevantNode n2) {
n2.(ImplicitInstanceAccess).getInstanceAccess().(OwnInstanceAccess).getEnclosingCallable() = c n2.(ImplicitInstanceAccess).getInstanceAccess().(OwnInstanceAccess).getEnclosingCallable() = c
) )
or or
exists(Field f | n2.(FieldValueNode).getField().getAnAssignedValue() = n1.asExpr()
f.getAnAssignedValue() = n1.asExpr() and or
n2.asExpr().(FieldRead).getField() = f n2.asExpr().(FieldRead).getField() = n1.(FieldValueNode).getField()
)
or or
exists(EnumType enum, Method getValue | exists(EnumType enum, Method getValue |
enum.getAnEnumConstant().getAnAssignedValue() = n1.asExpr() and enum.getAnEnumConstant().getAnAssignedValue() = n1.asExpr() and

View File

@@ -94,10 +94,9 @@ private predicate step(Node n1, Node n2) {
n2.(ImplicitInstanceAccess).getInstanceAccess().(OwnInstanceAccess).getEnclosingCallable() = c n2.(ImplicitInstanceAccess).getInstanceAccess().(OwnInstanceAccess).getEnclosingCallable() = c
) )
or or
exists(Field f | n2.(FieldValueNode).getField().getAnAssignedValue() = n1.asExpr()
f.getAnAssignedValue() = n1.asExpr() and or
n2.asExpr().(FieldRead).getField() = f n2.asExpr().(FieldRead).getField() = n1.(FieldValueNode).getField()
)
or or
n2.asExpr().(CastExpr).getExpr() = n1.asExpr() n2.asExpr().(CastExpr).getExpr() = n1.asExpr()
or or
@@ -132,7 +131,7 @@ private predicate step(Node n1, Node n2) {
or or
exists(Field v | exists(Field v |
containerStep(n1.asExpr(), v.getAnAccess()) and containerStep(n1.asExpr(), v.getAnAccess()) and
n2.asExpr() = v.getAnAccess() n2.(FieldValueNode).getField() = v
) )
} }

View File

@@ -62,7 +62,7 @@ class ExternalAPI extends Callable {
/** Holds if this API has a supported summary. */ /** Holds if this API has a supported summary. */
predicate hasSummary() { predicate hasSummary() {
this instanceof SummarizedCallable or this = any(SummarizedCallable sc).asCallable() or
TaintTracking::localAdditionalTaintStep(this.getAnInput(), _) TaintTracking::localAdditionalTaintStep(this.getAnInput(), _)
} }

View File

@@ -1,7 +1,8 @@
edges edges
| UnsafeHostnameVerification.java:66:37:80:9 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:81:55:81:62 | verifier | | UnsafeHostnameVerification.java:66:37:80:9 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:81:55:81:62 | verifier |
| UnsafeHostnameVerification.java:88:37:93:9 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:94:55:94:62 | verifier | | UnsafeHostnameVerification.java:88:37:93:9 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:94:55:94:62 | verifier |
| UnsafeHostnameVerification.java:97:72:102:5 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:34:59:34:85 | ALLOW_ALL_HOSTNAME_VERIFIER | | UnsafeHostnameVerification.java:97:42:97:68 | ALLOW_ALL_HOSTNAME_VERIFIER : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:34:59:34:85 | ALLOW_ALL_HOSTNAME_VERIFIER |
| UnsafeHostnameVerification.java:97:72:102:5 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:97:42:97:68 | ALLOW_ALL_HOSTNAME_VERIFIER : new HostnameVerifier(...) { ... } |
nodes nodes
| UnsafeHostnameVerification.java:14:55:19:9 | new (...) | semmle.label | new (...) | | UnsafeHostnameVerification.java:14:55:19:9 | new (...) | semmle.label | new (...) |
| UnsafeHostnameVerification.java:26:55:26:71 | ...->... | semmle.label | ...->... | | UnsafeHostnameVerification.java:26:55:26:71 | ...->... | semmle.label | ...->... |
@@ -12,6 +13,7 @@ nodes
| UnsafeHostnameVerification.java:81:55:81:62 | verifier | semmle.label | verifier | | UnsafeHostnameVerification.java:81:55:81:62 | verifier | semmle.label | verifier |
| UnsafeHostnameVerification.java:88:37:93:9 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | | UnsafeHostnameVerification.java:88:37:93:9 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } |
| UnsafeHostnameVerification.java:94:55:94:62 | verifier | semmle.label | verifier | | UnsafeHostnameVerification.java:94:55:94:62 | verifier | semmle.label | verifier |
| UnsafeHostnameVerification.java:97:42:97:68 | ALLOW_ALL_HOSTNAME_VERIFIER : new HostnameVerifier(...) { ... } | semmle.label | ALLOW_ALL_HOSTNAME_VERIFIER : new HostnameVerifier(...) { ... } |
| UnsafeHostnameVerification.java:97:72:102:5 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | | UnsafeHostnameVerification.java:97:72:102:5 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } |
subpaths subpaths
#select #select

View File

@@ -1,6 +1,7 @@
edges edges
| CredentialsTest.java:7:34:7:41 | "123456" : String | CredentialsTest.java:13:39:13:39 | p | | CredentialsTest.java:7:30:7:30 | p : String | CredentialsTest.java:13:39:13:39 | p |
| CredentialsTest.java:7:34:7:41 | "123456" : String | CredentialsTest.java:14:16:14:16 | p : String | | CredentialsTest.java:7:30:7:30 | p : String | CredentialsTest.java:14:16:14:16 | p : String |
| CredentialsTest.java:7:34:7:41 | "123456" : String | CredentialsTest.java:7:30:7:30 | p : String |
| CredentialsTest.java:11:14:11:20 | "admin" : String | CredentialsTest.java:13:36:13:36 | u | | CredentialsTest.java:11:14:11:20 | "admin" : String | CredentialsTest.java:13:36:13:36 | u |
| CredentialsTest.java:11:14:11:20 | "admin" : String | CredentialsTest.java:14:13:14:13 | u : String | | CredentialsTest.java:11:14:11:20 | "admin" : String | CredentialsTest.java:14:13:14:13 | u : String |
| CredentialsTest.java:14:13:14:13 | u : String | CredentialsTest.java:17:38:17:45 | v : String | | CredentialsTest.java:14:13:14:13 | u : String | CredentialsTest.java:17:38:17:45 | v : String |
@@ -44,6 +45,7 @@ edges
| Test.java:29:38:29:48 | user : String | Test.java:30:36:30:39 | user | | Test.java:29:38:29:48 | user : String | Test.java:30:36:30:39 | user |
| Test.java:29:51:29:65 | password : String | Test.java:30:42:30:49 | password | | Test.java:29:51:29:65 | password : String | Test.java:30:42:30:49 | password |
nodes nodes
| CredentialsTest.java:7:30:7:30 | p : String | semmle.label | p : String |
| CredentialsTest.java:7:34:7:41 | "123456" : String | semmle.label | "123456" : String | | CredentialsTest.java:7:34:7:41 | "123456" : String | semmle.label | "123456" : String |
| CredentialsTest.java:11:14:11:20 | "admin" : String | semmle.label | "admin" : String | | CredentialsTest.java:11:14:11:20 | "admin" : String | semmle.label | "admin" : String |
| CredentialsTest.java:13:36:13:36 | u | semmle.label | u | | CredentialsTest.java:13:36:13:36 | u | semmle.label | u |

View File

@@ -12,7 +12,8 @@ edges
| HardcodedAzureCredentials.java:61:3:61:33 | new HardcodedAzureCredentials(...) [clientSecret] : String | HardcodedAzureCredentials.java:15:14:15:42 | parameter this [clientSecret] : String | | HardcodedAzureCredentials.java:61:3:61:33 | new HardcodedAzureCredentials(...) [clientSecret] : String | HardcodedAzureCredentials.java:15:14:15:42 | parameter this [clientSecret] : String |
| HardcodedAzureCredentials.java:61:3:61:33 | new HardcodedAzureCredentials(...) [username] : String | HardcodedAzureCredentials.java:15:14:15:42 | parameter this [username] : String | | HardcodedAzureCredentials.java:61:3:61:33 | new HardcodedAzureCredentials(...) [username] : String | HardcodedAzureCredentials.java:15:14:15:42 | parameter this [username] : String |
| Test.java:10:17:10:24 | "123456" : String | Test.java:26:17:26:20 | pass | | Test.java:10:17:10:24 | "123456" : String | Test.java:26:17:26:20 | pass |
| User.java:2:43:2:50 | "123456" : String | User.java:5:15:5:24 | DEFAULT_PW | | User.java:2:30:2:39 | DEFAULT_PW : String | User.java:5:15:5:24 | DEFAULT_PW |
| User.java:2:43:2:50 | "123456" : String | User.java:2:30:2:39 | DEFAULT_PW : String |
nodes nodes
| HardcodedAzureCredentials.java:8:14:8:38 | this <.method> [post update] [clientSecret] : String | semmle.label | this <.method> [post update] [clientSecret] : String | | HardcodedAzureCredentials.java:8:14:8:38 | this <.method> [post update] [clientSecret] : String | semmle.label | this <.method> [post update] [clientSecret] : String |
| HardcodedAzureCredentials.java:8:14:8:38 | this <.method> [post update] [username] : String | semmle.label | this <.method> [post update] [username] : String | | HardcodedAzureCredentials.java:8:14:8:38 | this <.method> [post update] [username] : String | semmle.label | this <.method> [post update] [username] : String |
@@ -30,6 +31,7 @@ nodes
| HardcodedAzureCredentials.java:61:3:61:33 | new HardcodedAzureCredentials(...) [username] : String | semmle.label | new HardcodedAzureCredentials(...) [username] : String | | HardcodedAzureCredentials.java:61:3:61:33 | new HardcodedAzureCredentials(...) [username] : String | semmle.label | new HardcodedAzureCredentials(...) [username] : String |
| Test.java:10:17:10:24 | "123456" : String | semmle.label | "123456" : String | | Test.java:10:17:10:24 | "123456" : String | semmle.label | "123456" : String |
| Test.java:26:17:26:20 | pass | semmle.label | pass | | Test.java:26:17:26:20 | pass | semmle.label | pass |
| User.java:2:30:2:39 | DEFAULT_PW : String | semmle.label | DEFAULT_PW : String |
| User.java:2:43:2:50 | "123456" : String | semmle.label | "123456" : String | | User.java:2:43:2:50 | "123456" : String | semmle.label | "123456" : String |
| User.java:5:15:5:24 | DEFAULT_PW | semmle.label | DEFAULT_PW | | User.java:5:15:5:24 | DEFAULT_PW | semmle.label | DEFAULT_PW |
subpaths subpaths