Skip to content

Commit cd9a485

Browse files
committed
Refactor NullOrEmptyCheckGuard
1 parent 263dbd3 commit cd9a485

File tree

1 file changed

+23
-26
lines changed

1 file changed

+23
-26
lines changed

java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import UnsafeUrlForward
1515
import semmle.code.java.dataflow.FlowSources
1616
import semmle.code.java.frameworks.Servlets
1717
import semmle.code.java.controlflow.Guards
18+
import semmle.code.java.dataflow.NullGuards
1819
import DataFlow::PathGraph
1920

2021
/**
@@ -92,8 +93,8 @@ class PathNormalizeMethod extends Method {
9293
* 3. String not startsWith or not match check with decoding processing
9394
* 4. java.nio.file.Path startsWith check having path normalization
9495
*/
95-
private class PathMatchSanitizer extends DataFlow::BarrierGuard {
96-
PathMatchSanitizer() {
96+
private class PathMatchGuard extends DataFlow::BarrierGuard {
97+
PathMatchGuard() {
9798
isExactStringPathMatch(this)
9899
or
99100
isStringPathMatch(this) and
@@ -150,29 +151,25 @@ private class StringOperationSanitizer extends DataFlow::Node {
150151
StringOperationSanitizer() { exists(MethodAccess ma | checkStringContent(ma, this.asExpr())) }
151152
}
152153

153-
/**
154-
* Holds if `expr` is an expression returned from null or empty string check.
155-
*/
156-
predicate isNullOrEmptyCheck(Expr expr) {
157-
exists(ConditionBlock cb, ReturnStmt rt |
158-
cb.controls(rt.getBasicBlock(), true) and
159-
(
160-
cb.getCondition().(EQExpr).getAnOperand() instanceof NullLiteral // if (path == null)
161-
or
162-
// if (path.equals(""))
163-
exists(MethodAccess ma |
154+
private class NullOrEmptyCheckGuard extends DataFlow::BarrierGuard {
155+
NullOrEmptyCheckGuard() {
156+
this = nullGuard(_, _, _)
157+
or
158+
exists(MethodAccess ma |
164159
cb.getCondition() = ma and
165-
ma.getMethod().getDeclaringType() instanceof TypeString and
166-
ma.getMethod().hasName("equals") and
167-
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = ""
168-
)
169-
) and
170-
expr.getParent+() = rt
171-
)
172-
}
160+
ma.getMethod().getDeclaringType() instanceof TypeString and
161+
ma.getMethod().hasName("equals") and
162+
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "" and
163+
this = ma
164+
)
165+
}
173166

174-
private class NullOrEmptyCheckSanitizer extends DataFlow::Node {
175-
NullOrEmptyCheckSanitizer() { isNullOrEmptyCheck(this.asExpr()) }
167+
override predicate checks(Expr e, boolean branch) {
168+
exists(SsaVariable ssa | this = nullGuard(ssa, branch, true) and e = ssa.getAFirstUse())
169+
or
170+
e = this.(MethodAccess).getQualifier() and
171+
branch = true
172+
}
176173
}
177174

178175
class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
@@ -194,12 +191,12 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
194191

195192
override predicate isSanitizer(DataFlow::Node node) {
196193
node instanceof UnsafeUrlForwardSanitizer or
197-
node instanceof StringOperationSanitizer or
198-
node instanceof NullOrEmptyCheckSanitizer
194+
node instanceof StringOperationSanitizer
199195
}
200196

201197
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
202-
guard instanceof PathMatchSanitizer
198+
guard instanceof PathMatchGuard or
199+
guard instanceof NullOrEmptyCheckGuard
203200
}
204201

205202
override DataFlow::FlowFeature getAFeature() {

0 commit comments

Comments
 (0)