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. 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..c93993336d95 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringController.qll @@ -153,8 +153,16 @@ 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 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. */ string getMethodValue() { 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" + } + } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy