@@ -31,50 +31,55 @@ 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.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+ this .getParameter ( pos ) . getName ( ) = "uriVariables"
3946 }
40- }
4147
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- }
48+ int getUriVariablesPosition ( ) { result = pos }
49+ }
4750
48- /** Gets the first argument, if it is a compile time constant. */
49- CompileTimeConstantExpr getConstantUrl ( ) { result = this .getArgument ( 0 ) }
51+ /** Gets the first argument of `mc`, if it is a compile-time constant. */
52+ pragma [ inline]
53+ private CompileTimeConstantExpr getConstantUrl ( MethodCall mc ) { result = mc .getArgument ( 0 ) }
5054
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- }
55+ /**
56+ * Holds if the first argument of `mc` is a compile-time constant URL template
57+ * which has its `idx`-th placeholder at the offset `offset`.
58+ */
59+ pragma [ inline]
60+ private predicate urlHasPlaceholderAtOffset ( MethodCall mc , int idx , int offset ) {
61+ exists (
62+ getConstantUrl ( mc )
63+ .getStringValue ( )
64+ .replaceAll ( "\\{" , " " )
65+ .replaceAll ( "\\}" , " " )
66+ .regexpFind ( "\\{[^}]*\\}" , idx , offset )
67+ )
6568}
6669
67- private class SpringWebClientRestTemplateGetForObject extends RequestForgerySink {
68- SpringWebClientRestTemplateGetForObject ( ) {
69- exists ( SpringRestTemplateGetForObjectMethodCall mc , int i |
70- // Note that the first argument is modeled as a request forgery sink
71- // separately. This model is for arguments beyond the first two. There
72- // are two relevant overloads, one with third parameter type `Object...`
73- // and one with third parameter type `Map<String, ?>`. For the latter we
74- // cannot deal with MapValue content easily but there is a default
75- // implicit taint read at sinks that will catch it.
70+ private class SpringWebClientRestTemplateUriVariable extends RequestForgerySink {
71+ SpringWebClientRestTemplateUriVariable ( ) {
72+ exists ( SpringRestTemplateMethodWithUriVariablesParameter m , MethodCall mc , int i |
73+ // Note that the first argument of `m` is modeled as a request forgery
74+ // sink separately. This model is for arguments corresponding to the
75+ // `uriVariables` parameter. There are always two relevant overloads, one
76+ // with parameter type `Object...` and one with parameter type
77+ // `Map<String, ?>`. For the latter we cannot deal with MapValue content
78+ // easily but there is a default implicit taint read at sinks that will
79+ // catch it.
80+ mc .getMethod ( ) = m and
7681 i >= 0 and
77- this .asExpr ( ) = mc .getArgument ( i + 2 )
82+ this .asExpr ( ) = mc .getArgument ( m . getUriVariablesPosition ( ) + i )
7883 |
7984 // If we can determine that part of mc.getArgument(0) is a hostname
8085 // sanitizing prefix, then we count how many placeholders occur before it
@@ -83,8 +88,8 @@ private class SpringWebClientRestTemplateGetForObject extends RequestForgerySink
8388 // considering the map values as sinks if there is at least one
8489 // placeholder in the URL before the hostname sanitizing prefix.
8590 exists ( int offset |
86- mc . urlHasPlaceholderAtOffset ( i , offset ) and
87- offset < mc . getConstantUrl ( ) .( HostnameSanitizingPrefix ) .getOffset ( )
91+ urlHasPlaceholderAtOffset ( mc , i , offset ) and
92+ offset < getConstantUrl ( mc ) .( HostnameSanitizingPrefix ) .getOffset ( )
8893 )
8994 or
9095 // If we cannot determine that part of mc.getArgument(0) is a hostname
@@ -94,12 +99,12 @@ private class SpringWebClientRestTemplateGetForObject extends RequestForgerySink
9499 // For the `Map<String, ?>` overload this has the effect of only
95100 // considering the map values as sinks if there is at least one
96101 // placeholder in the URL.
97- not mc . getConstantUrl ( ) instanceof HostnameSanitizingPrefix and
98- mc . urlHasPlaceholderAtOffset ( i , _)
102+ not getConstantUrl ( mc ) instanceof HostnameSanitizingPrefix and
103+ urlHasPlaceholderAtOffset ( mc , i , _)
99104 or
100105 // If we cannot determine the string value of mc.getArgument(0), then we
101106 // conservatively consider all arguments as sinks.
102- not exists ( mc . getConstantUrl ( ) .getStringValue ( ) )
107+ not exists ( getConstantUrl ( mc ) .getStringValue ( ) )
103108 )
104109 }
105110}
0 commit comments