@@ -106,45 +106,42 @@ private predicate isEqualsIgnoreCaseMethodAccess(MethodAccess ma) {
106
106
ma .getMethod ( ) .getDeclaringType ( ) instanceof TypeString
107
107
}
108
108
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
+ }
128
123
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
+ )
141
138
}
142
139
143
140
/** Gets a guard that depends on a flag. */
144
141
private 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
148
145
sink .asExpr ( ) = result
149
146
)
150
147
}
0 commit comments