@@ -31,50 +31,74 @@ class SpringWebClient extends Interface {
3131 }
3232}
3333
34- /** The method `getForObject` on `org.springframework.web.reactive.function.client.RestTemplate`. */
35- class SpringRestTemplateGetForObjectMethod extends Method {
36- SpringRestTemplateGetForObjectMethod ( ) {
34+ /**
35+ * A method on `org.springframework.web.reactive.function.client.RestTemplate`
36+ * which has a parameter `uriVariables` (which can have type `Object..` or
37+ * `Map<String, ?>`) which contains variables to be expanded into the URL
38+ * template in parameter 0.
39+ */
40+ private class SpringRestTemplateMethodWithUriVariablesParameter extends Method {
41+ int pos ;
42+
43+ SpringRestTemplateMethodWithUriVariablesParameter ( ) {
3744 this .getDeclaringType ( ) instanceof SpringRestTemplate and
38- this .hasName ( "getForObject" )
45+ (
46+ this .hasName ( "delete" ) and pos = 1
47+ or
48+ this .hasName ( "exchange" ) and pos = 4
49+ or
50+ this .hasName ( "execute" ) and pos = 4
51+ or
52+ this .hasName ( "getForEntity" ) and pos = 2
53+ or
54+ this .hasName ( "getForObject" ) and pos = 2
55+ or
56+ this .hasName ( "headForHeaders" ) and pos = 1
57+ or
58+ this .hasName ( "optionsForAllow" ) and pos = 1
59+ or
60+ this .hasName ( "patchForObject" ) and pos = 3
61+ or
62+ this .hasName ( "postForEntity" ) and pos = 3
63+ or
64+ this .hasName ( "postForLocation" ) and pos = 2
65+ or
66+ this .hasName ( "postForObject" ) and pos = 3
67+ or
68+ this .hasName ( "put" ) and pos = 2
69+ )
3970 }
40- }
4171
42- /** A call to the method `getForObject` on `org.springframework.web.reactive.function.client.RestTemplate`. */
43- class SpringRestTemplateGetForObjectMethodCall extends MethodCall {
44- SpringRestTemplateGetForObjectMethodCall ( ) {
45- this .getMethod ( ) instanceof SpringRestTemplateGetForObjectMethod
46- }
72+ int getUriVariablesPosition ( ) { result = pos }
73+ }
4774
48- /** Gets the first argument, if it is a compile time constant. */
49- CompileTimeConstantExpr getConstantUrl ( ) { result = this .getArgument ( 0 ) }
75+ /** Gets the first argument, if it is a compile time constant. */
76+ pragma [ inline]
77+ private CompileTimeConstantExpr getConstantUrl ( MethodCall mc ) { result = mc .getArgument ( 0 ) }
5078
51- /**
52- * Holds if the first argument is a compile time constant and it has a
53- * placeholder at offset `offset`, and there are `idx` placeholders that
54- * appear before it.
55- */
56- predicate urlHasPlaceholderAtOffset ( int idx , int offset ) {
57- exists (
58- this .getConstantUrl ( )
59- .getStringValue ( )
60- .replaceAll ( "\\{" , " " )
61- .replaceAll ( "\\}" , " " )
62- .regexpFind ( "\\{[^}]*\\}" , idx , offset )
63- )
64- }
79+ pragma [ inline]
80+ private predicate urlHasPlaceholderAtOffset ( MethodCall mc , int idx , int offset ) {
81+ exists (
82+ getConstantUrl ( mc )
83+ .getStringValue ( )
84+ .replaceAll ( "\\{" , " " )
85+ .replaceAll ( "\\}" , " " )
86+ .regexpFind ( "\\{[^}]*\\}" , idx , offset )
87+ )
6588}
6689
6790private class SpringWebClientRestTemplateGetForObject extends RequestForgerySink {
6891 SpringWebClientRestTemplateGetForObject ( ) {
69- exists ( SpringRestTemplateGetForObjectMethodCall mc , int i |
92+ exists ( SpringRestTemplateMethodWithUriVariablesParameter m , MethodCall mc , int i |
7093 // Note that the first argument is modeled as a request forgery sink
7194 // separately. This model is for arguments beyond the first two. There
7295 // are two relevant overloads, one with third parameter type `Object...`
7396 // and one with third parameter type `Map<String, ?>`. For the latter we
7497 // cannot deal with MapValue content easily but there is a default
7598 // implicit taint read at sinks that will catch it.
99+ mc .getMethod ( ) = m and
76100 i >= 0 and
77- this .asExpr ( ) = mc .getArgument ( i + 2 )
101+ this .asExpr ( ) = mc .getArgument ( m . getUriVariablesPosition ( ) + i )
78102 |
79103 // If we can determine that part of mc.getArgument(0) is a hostname
80104 // sanitizing prefix, then we count how many placeholders occur before it
@@ -83,8 +107,8 @@ private class SpringWebClientRestTemplateGetForObject extends RequestForgerySink
83107 // considering the map values as sinks if there is at least one
84108 // placeholder in the URL before the hostname sanitizing prefix.
85109 exists ( int offset |
86- mc . urlHasPlaceholderAtOffset ( i , offset ) and
87- offset < mc . getConstantUrl ( ) .( HostnameSanitizingPrefix ) .getOffset ( )
110+ urlHasPlaceholderAtOffset ( mc , i , offset ) and
111+ offset < getConstantUrl ( mc ) .( HostnameSanitizingPrefix ) .getOffset ( )
88112 )
89113 or
90114 // If we cannot determine that part of mc.getArgument(0) is a hostname
@@ -94,12 +118,12 @@ private class SpringWebClientRestTemplateGetForObject extends RequestForgerySink
94118 // For the `Map<String, ?>` overload this has the effect of only
95119 // considering the map values as sinks if there is at least one
96120 // placeholder in the URL.
97- not mc . getConstantUrl ( ) instanceof HostnameSanitizingPrefix and
98- mc . urlHasPlaceholderAtOffset ( i , _)
121+ not getConstantUrl ( mc ) instanceof HostnameSanitizingPrefix and
122+ urlHasPlaceholderAtOffset ( mc , i , _)
99123 or
100124 // If we cannot determine the string value of mc.getArgument(0), then we
101125 // conservatively consider all arguments as sinks.
102- not exists ( mc . getConstantUrl ( ) .getStringValue ( ) )
126+ not exists ( getConstantUrl ( mc ) .getStringValue ( ) )
103127 )
104128 }
105129}
0 commit comments