@@ -15,6 +15,7 @@ import UnsafeUrlForward
15
15
import semmle.code.java.dataflow.FlowSources
16
16
import semmle.code.java.frameworks.Servlets
17
17
import semmle.code.java.controlflow.Guards
18
+ import semmle.code.java.dataflow.NullGuards
18
19
import DataFlow:: PathGraph
19
20
20
21
/**
@@ -92,8 +93,8 @@ class PathNormalizeMethod extends Method {
92
93
* 3. String not startsWith or not match check with decoding processing
93
94
* 4. java.nio.file.Path startsWith check having path normalization
94
95
*/
95
- private class PathMatchSanitizer extends DataFlow:: BarrierGuard {
96
- PathMatchSanitizer ( ) {
96
+ private class PathMatchGuard extends DataFlow:: BarrierGuard {
97
+ PathMatchGuard ( ) {
97
98
isExactStringPathMatch ( this )
98
99
or
99
100
isStringPathMatch ( this ) and
@@ -150,29 +151,25 @@ private class StringOperationSanitizer extends DataFlow::Node {
150
151
StringOperationSanitizer ( ) { exists ( MethodAccess ma | checkStringContent ( ma , this .asExpr ( ) ) ) }
151
152
}
152
153
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 |
164
159
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
+ }
173
166
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
+ }
176
173
}
177
174
178
175
class UnsafeUrlForwardFlowConfig extends TaintTracking:: Configuration {
@@ -194,12 +191,12 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
194
191
195
192
override predicate isSanitizer ( DataFlow:: Node node ) {
196
193
node instanceof UnsafeUrlForwardSanitizer or
197
- node instanceof StringOperationSanitizer or
198
- node instanceof NullOrEmptyCheckSanitizer
194
+ node instanceof StringOperationSanitizer
199
195
}
200
196
201
197
override predicate isSanitizerGuard ( DataFlow:: BarrierGuard guard ) {
202
- guard instanceof PathMatchSanitizer
198
+ guard instanceof PathMatchGuard or
199
+ guard instanceof NullOrEmptyCheckGuard
203
200
}
204
201
205
202
override DataFlow:: FlowFeature getAFeature ( ) {
0 commit comments