@@ -6,7 +6,7 @@ import semmle.code.java.dataflow.TaintTracking
66import semmle.code.java.security.SensitiveActions
77import semmle.code.java.frameworks.android.Compose
88private import semmle.code.java.security.Sanitizers
9- import semmle.code.java.Constants
9+ private import semmle.code.java.dataflow.RangeAnalysis
1010
1111/** A data flow source node for sensitive logging sources. */
1212abstract class SensitiveLoggerSource extends DataFlow:: Node { }
@@ -49,110 +49,65 @@ private class TypeType extends RefType {
4949 *
5050 * It allows for substring operations taking the first N (or last N, for Kotlin) characters, limited to 7 or fewer.
5151 */
52- private class SensitiveLoggerSanitizerCalled extends SensitiveLoggerBarrier {
53- SensitiveLoggerSanitizerCalled ( ) {
52+ private class PrefixSuffixBarrier extends SensitiveLoggerBarrier {
53+ PrefixSuffixBarrier ( ) {
5454 exists ( MethodCall mc , Method m , int limit |
5555 limit = 7 and
56- mc .getMethod ( ) = m and
56+ mc .getMethod ( ) = m
57+ |
58+ // substring in Java
5759 (
58- // substring in Java
59- (
60- m .hasQualifiedName ( "java.lang" , "String " , "substring" ) or
61- m . hasQualifiedName ( "java.lang" , "StringBuffer" , "substring" ) or
62- m . hasQualifiedName ( "java.lang" , "StringBuilder" , "substring" )
63- ) and
64- (
65- twoArgLimit ( mc , limit , false ) or
66- singleArgLimit ( mc , limit , false )
67- ) and
68- this . asExpr ( ) = mc . getQualifier ( )
69- or
70- // Kotlin string operations, which use extension methods (so the string is the first argument)
60+ m . hasQualifiedName ( "java.lang" , "String" , " substring" ) or
61+ m . hasQualifiedName ( "java.lang" , "StringBuffer" , "substring" ) or
62+ m .hasQualifiedName ( "java.lang" , "StringBuilder " , "substring" )
63+ ) and
64+ (
65+ twoArgLimit ( mc , limit , false ) or
66+ singleArgLimit ( mc , limit , false )
67+ ) and
68+ this . asExpr ( ) = mc . getQualifier ( )
69+ or
70+ // Kotlin string operations, which use extension methods (so the string is the first argument )
71+ (
72+ m . hasQualifiedName ( "kotlin.text" , "StringsKt" , "substring" ) and
7173 (
72- m .hasQualifiedName ( "kotlin.text" , "StringsKt" , "substring" ) and
73- (
74- twoArgLimit ( mc , limit , true ) or
75- singleArgLimit ( mc , limit , true )
76- )
77- or
78- m .hasQualifiedName ( "kotlin.text" , "StringsKt" , [ "take" , "takeLast" ] ) and
74+ twoArgLimit ( mc , limit , true ) or
7975 singleArgLimit ( mc , limit , true )
80- ) and
81- this .asExpr ( ) = mc .getArgument ( 0 )
82- )
76+ )
77+ or
78+ m .hasQualifiedName ( "kotlin.text" , "StringsKt" , [ "take" , "takeLast" ] ) and
79+ singleArgLimit ( mc , limit , true )
80+ ) and
81+ this .asExpr ( ) = mc .getArgument ( 0 )
8382 )
8483 }
8584}
8685
8786/** A predicate to check single-argument method calls for a constant integer below a set limit. */
8887bindingset [ limit, isKotlin]
8988private predicate singleArgLimit ( MethodCall mc , int limit , boolean isKotlin ) {
90- exists ( int argIndex , int staticInt |
89+ exists ( int argIndex |
9190 ( if isKotlin = true then argIndex = 1 else argIndex = 0 ) and
92- (
93- staticInt <= limit and
94- staticInt > 0 and
95- mc .getArgument ( argIndex ) .getUnderlyingExpr ( ) .( CompileTimeConstantExpr ) .getIntValue ( ) =
96- staticInt
97- or
98- exists ( CompileTimeConstantExpr cte , DataFlow:: Node source , DataFlow:: Node sink |
99- source .asExpr ( ) = cte and
100- cte .getIntValue ( ) = staticInt and
101- sink .asExpr ( ) = mc .getArgument ( argIndex ) and
102- IntegerToArgFlow:: flow ( source , sink )
103- )
104- )
91+ bounded ( mc .getArgument ( argIndex ) , any ( ZeroBound z ) , limit , true , _)
10592 )
10693}
10794
10895/** A predicate to check two-argument method calls for zero and a constant integer below a set limit. */
10996bindingset [ limit, isKotlin]
11097private predicate twoArgLimit ( MethodCall mc , int limit , boolean isKotlin ) {
111- exists ( int firstArgIndex , int secondArgIndex , int staticInt |
112- staticInt <= limit and
113- staticInt > 0 and
98+ exists ( int firstArgIndex , int secondArgIndex |
11499 (
115100 isKotlin = true and firstArgIndex = 1 and secondArgIndex = 2
116101 or
117102 isKotlin = false and firstArgIndex = 0 and secondArgIndex = 1
118103 ) and
119104 mc .getArgument ( firstArgIndex ) .getUnderlyingExpr ( ) .( CompileTimeConstantExpr ) .getIntValue ( ) = 0 and
120- (
121- mc .getArgument ( secondArgIndex ) .getUnderlyingExpr ( ) .( CompileTimeConstantExpr ) .getIntValue ( ) =
122- staticInt
123- or
124- exists ( CompileTimeConstantExpr cte , DataFlow:: Node source , DataFlow:: Node sink |
125- source .asExpr ( ) = cte and
126- cte .getIntValue ( ) = staticInt and
127- sink .asExpr ( ) = mc .getArgument ( secondArgIndex ) and
128- IntegerToArgFlow:: flow ( source , sink )
129- )
130- )
105+ bounded ( mc .getArgument ( secondArgIndex ) , any ( ZeroBound z ) , limit , true , _)
131106 )
132107}
133108
134- /** A data-flow configuration for identifying flow from a constant integer to a use in a method argument. */
135- private module IntegerToArgConfig implements DataFlow:: ConfigSig {
136- predicate isSource ( DataFlow:: Node source ) {
137- source .asExpr ( ) .getUnderlyingExpr ( ) instanceof CompileTimeConstantExpr and
138- source .asExpr ( ) .getType ( ) instanceof IntegralType and
139- source .asExpr ( ) .( CompileTimeConstantExpr ) .getIntValue ( ) > 0
140- }
141-
142- predicate isSink ( DataFlow:: Node sink ) {
143- exists ( MethodCall mc |
144- sink .asExpr ( ) = mc .getAnArgument ( ) and
145- sink .asExpr ( ) .getType ( ) instanceof IntegralType
146- )
147- }
148-
149- predicate isBarrier ( DataFlow:: Node sanitizer ) { none ( ) }
150-
151- predicate isBarrierIn ( DataFlow:: Node node ) { none ( ) }
152- }
153-
154- private class GenericSanitizer extends SensitiveLoggerBarrier {
155- GenericSanitizer ( ) {
109+ private class DefaultSensitiveLoggerBarrier extends SensitiveLoggerBarrier {
110+ DefaultSensitiveLoggerBarrier ( ) {
156111 this .asExpr ( ) instanceof LiveLiteral or
157112 this instanceof SimpleTypeSanitizer or
158113 this .getType ( ) instanceof TypeType
@@ -173,5 +128,3 @@ module SensitiveLoggerConfig implements DataFlow::ConfigSig {
173128}
174129
175130module SensitiveLoggerFlow = TaintTracking:: Global< SensitiveLoggerConfig > ;
176-
177- module IntegerToArgFlow = TaintTracking:: Global< IntegerToArgConfig > ;
0 commit comments