Java: Replace global flow by local flow

This commit is contained in:
intrigus
2021-01-11 19:02:07 +01:00
parent 722bd4dafa
commit 85286f362c

View File

@@ -106,45 +106,42 @@ private predicate isEqualsIgnoreCaseMethodAccess(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypeString ma.getMethod().getDeclaringType() instanceof TypeString
} }
/** A configuration to model the flow of feature flags into `Guard`s. This is used to determine whether something is guarded by such a flag. */ /** Holds if `source` should is considered a flag. */
private class FlagToGuardFlow extends DataFlow::Configuration { private predicate isFlag(DataFlow::Node source) {
FlagToGuardFlow() { this = "FlagToGuardFlow" } exists(VarAccess v | v.getVariable().getName() = getAFlagName() |
source.asExpr() = v and v.getType() instanceof FlagType
)
or
exists(StringLiteral s | s.getRepresentedString() = getAFlagName() | source.asExpr() = s)
or
exists(MethodAccess ma | ma.getMethod().getName() = getAFlagName() |
source.asExpr() = ma and
ma.getType() instanceof FlagType and
not isEqualsIgnoreCaseMethodAccess(ma)
)
}
override predicate isSource(DataFlow::Node source) { /** Holds if there is flow from `node1` to `node2` either due to local flow or due to custom flow steps. */
exists(VarAccess v | v.getVariable().getName() = getAFlagName() | private predicate flagFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
source.asExpr() = v and v.getType() instanceof FlagType DataFlow::localFlowStep(node1, node2)
) or
or exists(MethodAccess ma | ma.getMethod() = any(EnvReadMethod m) |
exists(StringLiteral s | s.getRepresentedString() = getAFlagName() | source.asExpr() = s) ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr()
or )
exists(MethodAccess ma | ma.getMethod().getName() = getAFlagName() | or
source.asExpr() = ma and exists(MethodAccess ma |
ma.getType() instanceof FlagType and ma.getMethod().hasName("parseBoolean") and
not isEqualsIgnoreCaseMethodAccess(ma) ma.getMethod().getDeclaringType().hasQualifiedName("java.lang", "Boolean")
) |
} ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr()
)
override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof Guard }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma | ma.getMethod() = any(EnvReadMethod m) |
ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr()
)
or
exists(MethodAccess ma |
ma.getMethod().hasName("parseBoolean") and
ma.getMethod().getDeclaringType().hasQualifiedName("java.lang", "Boolean")
|
ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr()
)
}
} }
/** Gets a guard that depends on a flag. */ /** Gets a guard that depends on a flag. */
private Guard getAGuard() { private Guard getAGuard() {
exists(FlagToGuardFlow cfg, DataFlow::Node source, DataFlow::Node sink | exists(DataFlow::Node source, DataFlow::Node sink |
cfg.hasFlow(source, sink) isFlag(source) and
| flagFlowStep*(source, sink) and
sink.asExpr() = result sink.asExpr() = result
) )
} }