@@ -15,6 +15,7 @@ import UnsafeUrlForward
1515import semmle.code.java.dataflow.FlowSources
1616import semmle.code.java.frameworks.Servlets
1717import semmle.code.java.controlflow.Guards
18+ import semmle.code.java.dataflow.NullGuards
1819import 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
178175class 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