From f575d2f94165b0864025d5aeefe5be21060a6702 Mon Sep 17 00:00:00 2001 From: sentient0being <2663472225@qq.com> Date: Sat, 17 May 2025 19:40:41 +0800 Subject: [PATCH 1/6] get array string url --- .../semmle/code/java/frameworks/spring/SpringController.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll index a222be20c20a..cb7bd0e3dac4 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -156,6 +156,10 @@ class SpringRequestMappingMethod extends SpringControllerMethod { /** Gets the "value" @RequestMapping annotation value, if present. */ string getValue() { result = requestMappingAnnotation.getStringValue("value") } + + + /** Gets the "value" @RequestMapping annotation array string value, if present. */ + string getArrayValue() { result = requestMappingAnnotation.getAStringArrayValue("value") } /** Gets the "method" @RequestMapping annotation value, if present. */ string getMethodValue() { result = requestMappingAnnotation.getAnEnumConstantArrayValue("method").getName() From 775338ebdd74df612b04d50a4f344495cd790d08 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 22 May 2025 12:21:20 +0100 Subject: [PATCH 2/6] Rename `getArrayValue` to `getAValue` --- .../semmle/code/java/frameworks/spring/SpringController.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll index cb7bd0e3dac4..847ca788bb9f 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -159,7 +159,8 @@ class SpringRequestMappingMethod extends SpringControllerMethod { /** Gets the "value" @RequestMapping annotation array string value, if present. */ - string getArrayValue() { result = requestMappingAnnotation.getAStringArrayValue("value") } + string getAValue() { result = requestMappingAnnotation.getAStringArrayValue("value") } + /** Gets the "method" @RequestMapping annotation value, if present. */ string getMethodValue() { result = requestMappingAnnotation.getAnEnumConstantArrayValue("method").getName() From 708bbe391e3b113f760e778411e09c47b4e49f73 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 22 May 2025 12:22:34 +0100 Subject: [PATCH 3/6] Add test for `SpringRequestMappingMethod.getAValue` --- .../controller/RequestController.expected | 0 .../spring/controller/RequestController.ql | 18 +++++ .../frameworks/spring/controller/Test.java | 72 ++++++++++--------- 3 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 java/ql/test/library-tests/frameworks/spring/controller/RequestController.expected create mode 100644 java/ql/test/library-tests/frameworks/spring/controller/RequestController.ql diff --git a/java/ql/test/library-tests/frameworks/spring/controller/RequestController.expected b/java/ql/test/library-tests/frameworks/spring/controller/RequestController.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/ql/test/library-tests/frameworks/spring/controller/RequestController.ql b/java/ql/test/library-tests/frameworks/spring/controller/RequestController.ql new file mode 100644 index 000000000000..b1c1c1c86000 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/controller/RequestController.ql @@ -0,0 +1,18 @@ +import java +import utils.test.InlineExpectationsTest +private import semmle.code.java.frameworks.spring.SpringController + +module TestRequestController implements TestSig { + string getARelevantTag() { result = "RequestMappingURL" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "RequestMappingURL" and + exists(SpringRequestMappingMethod m | + m.getLocation() = location and + element = m.toString() and + value = "\"" + m.getAValue() + "\"" + ) + } +} + +import MakeTest diff --git a/java/ql/test/library-tests/frameworks/spring/controller/Test.java b/java/ql/test/library-tests/frameworks/spring/controller/Test.java index 6267073ce876..ad4fbc89f44f 100644 --- a/java/ql/test/library-tests/frameworks/spring/controller/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/controller/Test.java @@ -32,92 +32,93 @@ public class Test { - static void sink(Object o) {} + static void sink(Object o) { + } @Controller static class NotTaintedTest { @RequestMapping("/") - public void get(WebRequest src) { + public void get(WebRequest src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(NativeWebRequest src) { + public void get(NativeWebRequest src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(ServletRequest src) { + public void get(ServletRequest src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(HttpSession src) { + public void get(HttpSession src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(PushBuilder src) { + public void get(PushBuilder src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(Principal src) { + public void get(Principal src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(HttpMethod src) { + public void get(HttpMethod src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(Locale src) { + public void get(Locale src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(TimeZone src) { + public void get(TimeZone src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(ZoneId src) { + public void get(ZoneId src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(OutputStream src) { + public void get(OutputStream src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(Writer src) { + public void get(Writer src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(RedirectAttributes src) { + public void get(RedirectAttributes src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(Errors src) { + public void get(Errors src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(SessionStatus src) { + public void get(SessionStatus src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(UriComponentsBuilder src) { + public void get(UriComponentsBuilder src) { // $ RequestMappingURL="/" sink(src); } @RequestMapping("/") - public void get(Pageable src) { + public void get(Pageable src) { // $ RequestMappingURL="/" sink(src); } } @@ -125,62 +126,62 @@ public void get(Pageable src) { @Controller static class ExplicitlyTaintedTest { @RequestMapping("/") - public void get(InputStream src) { + public void get(InputStream src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void get(Reader src) { + public void get(Reader src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void matrixVariable(@MatrixVariable Object src) { + public void matrixVariable(@MatrixVariable Object src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void requestParam(@RequestParam Object src) { + public void requestParam(@RequestParam Object src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void requestHeader(@RequestHeader Object src) { + public void requestHeader(@RequestHeader Object src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void cookieValue(@CookieValue Object src) { + public void cookieValue(@CookieValue Object src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void requestPart(@RequestPart Object src) { + public void requestPart(@RequestPart Object src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void pathVariable(@PathVariable Object src) { + public void pathVariable(@PathVariable Object src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void requestBody(@RequestBody Object src) { + public void requestBody(@RequestBody Object src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void get(HttpEntity src) { + public void get(HttpEntity src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void requestAttribute(@RequestAttribute Object src) { + public void requestAttribute(@RequestAttribute Object src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void sessionAttribute(@SessionAttribute Object src) { + public void sessionAttribute(@SessionAttribute Object src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } } @@ -191,13 +192,20 @@ static class Pojo { } @RequestMapping("/") - public void get(String src) { + public void get(String src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } @RequestMapping("/") - public void get1(Pojo src) { + public void get1(Pojo src) { // $ RequestMappingURL="/" sink(src); // $hasValueFlow } } + + @Controller + static class MultipleValuesTest { + @RequestMapping({"/a", "/b"}) + public void get(WebRequest src) { // $ RequestMappingURL="/a" RequestMappingURL="/b" + } + } } From 59d4f039d8e8bf5b8b90390de7a24bada2c7b17d Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 22 May 2025 12:23:04 +0100 Subject: [PATCH 4/6] Deprecate `SpringRequestMappingMethod.getValue` (which didn't work) --- .../semmle/code/java/frameworks/spring/SpringController.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll index 847ca788bb9f..4717cf031a23 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -153,10 +153,8 @@ class SpringRequestMappingMethod extends SpringControllerMethod { result = this.getProducesExpr().(CompileTimeConstantExpr).getStringValue() } - /** Gets the "value" @RequestMapping annotation value, if present. */ - string getValue() { result = requestMappingAnnotation.getStringValue("value") } - - + /** DEPRECATED: Use `getAValue()` instead. */ + deprecated string getValue() { result = requestMappingAnnotation.getStringValue("value") } /** Gets the "value" @RequestMapping annotation array string value, if present. */ string getAValue() { result = requestMappingAnnotation.getAStringArrayValue("value") } From 45475c5c1debec552a30f0b1a05bfbe017b17146 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 22 May 2025 12:23:15 +0100 Subject: [PATCH 5/6] Add change note --- .../change-notes/2025-05-22-spring-request-mapping-value.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/lib/change-notes/2025-05-22-spring-request-mapping-value.md diff --git a/java/ql/lib/change-notes/2025-05-22-spring-request-mapping-value.md b/java/ql/lib/change-notes/2025-05-22-spring-request-mapping-value.md new file mode 100644 index 000000000000..8b7effc535de --- /dev/null +++ b/java/ql/lib/change-notes/2025-05-22-spring-request-mapping-value.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The predicate `getValue()` on `SpringRequestMappingMethod` is now deprecated. Use `getAValue()` instead. From 476ada13dbf4753257d3bdd01b66dddd31a2b114 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 22 May 2025 14:22:28 +0100 Subject: [PATCH 6/6] Improve QLDoc for `SpringRequestMappingMethod.getAValue` --- .../code/java/frameworks/spring/SpringController.qll | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll index 4717cf031a23..c93993336d95 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -156,7 +156,12 @@ class SpringRequestMappingMethod extends SpringControllerMethod { /** DEPRECATED: Use `getAValue()` instead. */ deprecated string getValue() { result = requestMappingAnnotation.getStringValue("value") } - /** Gets the "value" @RequestMapping annotation array string value, if present. */ + /** + * Gets a "value" @RequestMapping annotation string value, if present. + * + * If the annotation element is defined with an array initializer, then the result will be one of the + * elements of that array. Otherwise, the result will be the single expression used as value. + */ string getAValue() { result = requestMappingAnnotation.getAStringArrayValue("value") } /** Gets the "method" @RequestMapping annotation value, if present. */