Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: deprecated
---
* The predicate `getValue()` on `SpringRequestMappingMethod` is now deprecated. Use `getAValue()` instead.
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,11 @@ 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. */
Copy link

Copilot AI May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The doc comment for getAValue() could clarify the format of the returned string when multiple values are present (e.g., comma-separated).

Suggested change
/** Gets the "value" @RequestMapping annotation array string value, if present. */
/**
* Gets a single "value" from the @RequestMapping annotation array string, if present.
* If the annotation specifies multiple values, this method retrieves one of them.
*/

Copilot uses AI. Check for mistakes.
string getAValue() { result = requestMappingAnnotation.getAStringArrayValue("value") }

/** Gets the "method" @RequestMapping annotation value, if present. */
string getMethodValue() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<TestRequestController>
72 changes: 40 additions & 32 deletions java/ql/test/library-tests/frameworks/spring/controller/Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,155 +32,156 @@

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);
}
}

@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
}
}
Expand All @@ -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"
}
}
}