@@ -106,45 +106,42 @@ private predicate isEqualsIgnoreCaseMethodAccess(MethodAccess ma) {
106106 ma .getMethod ( ) .getDeclaringType ( ) instanceof TypeString
107107}
108108
109- /** 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. */
110- private class FlagToGuardFlow extends DataFlow:: Configuration {
111- FlagToGuardFlow ( ) { this = "FlagToGuardFlow" }
112-
113- override predicate isSource ( DataFlow:: Node source ) {
114- exists ( VarAccess v | v .getVariable ( ) .getName ( ) = getAFlagName ( ) |
115- source .asExpr ( ) = v and v .getType ( ) instanceof FlagType
116- )
117- or
118- exists ( StringLiteral s | s .getRepresentedString ( ) = getAFlagName ( ) | source .asExpr ( ) = s )
119- or
120- exists ( MethodAccess ma | ma .getMethod ( ) .getName ( ) = getAFlagName ( ) |
121- source .asExpr ( ) = ma and
122- ma .getType ( ) instanceof FlagType and
123- not isEqualsIgnoreCaseMethodAccess ( ma )
124- )
125- }
126-
127- override predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof Guard }
109+ /** Holds if `source` should is considered a flag. */
110+ private predicate isFlag ( DataFlow:: Node source ) {
111+ exists ( VarAccess v | v .getVariable ( ) .getName ( ) = getAFlagName ( ) |
112+ source .asExpr ( ) = v and v .getType ( ) instanceof FlagType
113+ )
114+ or
115+ exists ( StringLiteral s | s .getRepresentedString ( ) = getAFlagName ( ) | source .asExpr ( ) = s )
116+ or
117+ exists ( MethodAccess ma | ma .getMethod ( ) .getName ( ) = getAFlagName ( ) |
118+ source .asExpr ( ) = ma and
119+ ma .getType ( ) instanceof FlagType and
120+ not isEqualsIgnoreCaseMethodAccess ( ma )
121+ )
122+ }
128123
129- override predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
130- exists ( MethodAccess ma | ma .getMethod ( ) = any ( EnvReadMethod m ) |
131- ma = node2 .asExpr ( ) and ma .getAnArgument ( ) = node1 .asExpr ( )
132- )
133- or
134- exists ( MethodAccess ma |
135- ma .getMethod ( ) .hasName ( "parseBoolean" ) and
136- ma .getMethod ( ) .getDeclaringType ( ) .hasQualifiedName ( "java.lang" , "Boolean" )
137- |
138- ma = node2 .asExpr ( ) and ma .getAnArgument ( ) = node1 .asExpr ( )
139- )
140- }
124+ /** Holds if there is flow from `node1` to `node2` either due to local flow or due to custom flow steps. */
125+ private predicate flagFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
126+ DataFlow:: localFlowStep ( node1 , node2 )
127+ or
128+ exists ( MethodAccess ma | ma .getMethod ( ) = any ( EnvReadMethod m ) |
129+ ma = node2 .asExpr ( ) and ma .getAnArgument ( ) = node1 .asExpr ( )
130+ )
131+ or
132+ exists ( MethodAccess ma |
133+ ma .getMethod ( ) .hasName ( "parseBoolean" ) and
134+ ma .getMethod ( ) .getDeclaringType ( ) .hasQualifiedName ( "java.lang" , "Boolean" )
135+ |
136+ ma = node2 .asExpr ( ) and ma .getAnArgument ( ) = node1 .asExpr ( )
137+ )
141138}
142139
143140/** Gets a guard that depends on a flag. */
144141private Guard getAGuard ( ) {
145- exists ( FlagToGuardFlow cfg , DataFlow:: Node source , DataFlow:: Node sink |
146- cfg . hasFlow ( source , sink )
147- |
142+ exists ( DataFlow:: Node source , DataFlow:: Node sink |
143+ isFlag ( source ) and
144+ flagFlowStep * ( source , sink ) and
148145 sink .asExpr ( ) = result
149146 )
150147}
0 commit comments