Skip to content

Commit db8be50

Browse files
committed
Support empty target request path in FlashMap
Prior to this commit, if the user configured an empty path for the targetRequestPath property of a FlashMap, the FlashMapManager threw a StringIndexOutOfBoundsException when saving the output FlashMap for the next request. This commit fixes this by skipping the decoding and normalization of an empty target request path. Fixes gh-23240
1 parent efab6eb commit db8be50

File tree

2 files changed

+28
-36
lines changed

2 files changed

+28
-36
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/support/AbstractFlashMapManager.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@
4040
*
4141
* @author Rossen Stoyanchev
4242
* @author Juergen Hoeller
43+
* @author Sam Brannen
4344
* @since 3.1.1
4445
*/
4546
public abstract class AbstractFlashMapManager implements FlashMapManager {
@@ -218,7 +219,7 @@ public final void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest reque
218219

219220
@Nullable
220221
private String decodeAndNormalizePath(@Nullable String path, HttpServletRequest request) {
221-
if (path != null) {
222+
if (path != null && !path.isEmpty()) {
222223
path = getUrlPathHelper().decodeRequestString(request, path);
223224
if (path.charAt(0) != '/') {
224225
String requestUri = getUrlPathHelper().getRequestUri(request);

spring-webmvc/src/test/java/org/springframework/web/servlet/support/FlashMapManagerTests.java

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,47 +16,37 @@
1616

1717
package org.springframework.web.servlet.support;
1818

19-
import static org.junit.Assert.*;
20-
2119
import java.net.URLEncoder;
2220
import java.util.ArrayList;
2321
import java.util.Arrays;
2422
import java.util.Collections;
2523
import java.util.List;
2624
import java.util.concurrent.CopyOnWriteArrayList;
27-
2825
import javax.servlet.http.HttpServletRequest;
2926
import javax.servlet.http.HttpServletResponse;
3027

31-
import org.junit.Before;
3228
import org.junit.Test;
3329

3430
import org.springframework.mock.web.test.MockHttpServletRequest;
3531
import org.springframework.mock.web.test.MockHttpServletResponse;
3632
import org.springframework.web.servlet.FlashMap;
3733
import org.springframework.web.util.WebUtils;
3834

35+
import static org.junit.Assert.*;
3936

4037
/**
4138
* Test fixture for testing {@link AbstractFlashMapManager} methods.
4239
*
4340
* @author Rossen Stoyanchev
41+
* @author Sam Brannen
4442
*/
4543
public class FlashMapManagerTests {
4644

47-
private TestFlashMapManager flashMapManager;
48-
49-
private MockHttpServletRequest request;
45+
private final TestFlashMapManager flashMapManager = new TestFlashMapManager();
5046

51-
private MockHttpServletResponse response;
47+
private final MockHttpServletRequest request = new MockHttpServletRequest();
5248

53-
54-
@Before
55-
public void setup() {
56-
this.flashMapManager = new TestFlashMapManager();
57-
this.request = new MockHttpServletRequest();
58-
this.response = new MockHttpServletResponse();
59-
}
49+
private final MockHttpServletResponse response = new MockHttpServletResponse();
6050

6151

6252
@Test
@@ -73,9 +63,7 @@ public void retrieveAndUpdateMatchByPath() {
7363
assertEquals(flashMap, inputFlashMap);
7464
}
7565

76-
// SPR-8779
77-
78-
@Test
66+
@Test // SPR-8779
7967
public void retrieveAndUpdateMatchByOriginatingPath() {
8068
FlashMap flashMap = new FlashMap();
8169
flashMap.put("key", "value");
@@ -133,9 +121,7 @@ public void retrieveAndUpdateMatchByParams() {
133121
assertEquals("Input FlashMap should have been removed", 0, this.flashMapManager.getFlashMaps().size());
134122
}
135123

136-
// SPR-8798
137-
138-
@Test
124+
@Test // SPR-8798
139125
public void retrieveAndUpdateMatchWithMultiValueParam() {
140126
FlashMap flashMap = new FlashMap();
141127
flashMap.put("name", "value");
@@ -180,7 +166,7 @@ public void retrieveAndUpdateSortMultipleMatches() {
180166
}
181167

182168
@Test
183-
public void retrieveAndUpdateRemoveExpired() throws InterruptedException {
169+
public void retrieveAndUpdateRemoveExpired() {
184170
List<FlashMap> flashMaps = new ArrayList<>();
185171
for (int i = 0; i < 5; i++) {
186172
FlashMap expiredFlashMap = new FlashMap();
@@ -195,7 +181,7 @@ public void retrieveAndUpdateRemoveExpired() throws InterruptedException {
195181
}
196182

197183
@Test
198-
public void saveOutputFlashMapEmpty() throws InterruptedException {
184+
public void saveOutputFlashMapEmpty() {
199185
FlashMap flashMap = new FlashMap();
200186

201187
this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response);
@@ -205,7 +191,7 @@ public void saveOutputFlashMapEmpty() throws InterruptedException {
205191
}
206192

207193
@Test
208-
public void saveOutputFlashMap() throws InterruptedException {
194+
public void saveOutputFlashMap() {
209195
FlashMap flashMap = new FlashMap();
210196
flashMap.put("name", "value");
211197

@@ -219,7 +205,7 @@ public void saveOutputFlashMap() throws InterruptedException {
219205
}
220206

221207
@Test
222-
public void saveOutputFlashMapDecodeTargetPath() throws InterruptedException {
208+
public void saveOutputFlashMapDecodeTargetPath() {
223209
FlashMap flashMap = new FlashMap();
224210
flashMap.put("key", "value");
225211

@@ -230,7 +216,7 @@ public void saveOutputFlashMapDecodeTargetPath() throws InterruptedException {
230216
}
231217

232218
@Test
233-
public void saveOutputFlashMapNormalizeTargetPath() throws InterruptedException {
219+
public void saveOutputFlashMapNormalizeTargetPath() {
234220
FlashMap flashMap = new FlashMap();
235221
flashMap.put("key", "value");
236222

@@ -265,11 +251,19 @@ public void saveOutputFlashMapNormalizeTargetPath() throws InterruptedException
265251
assertEquals("/once/only", flashMap.getTargetRequestPath());
266252
}
267253

268-
// SPR-9657, SPR-11504
254+
@Test // gh-23240
255+
public void saveOutputFlashMapAndNormalizeEmptyTargetPath() {
256+
FlashMap flashMap = new FlashMap();
257+
flashMap.put("key", "value");
269258

270-
@Test
271-
public void saveOutputFlashMapDecodeParameters() throws Exception {
259+
flashMap.setTargetRequestPath("");
260+
this.flashMapManager.saveOutputFlashMap(flashMap, this.request, this.response);
272261

262+
assertEquals("", flashMap.getTargetRequestPath());
263+
}
264+
265+
@Test // SPR-9657, SPR-11504
266+
public void saveOutputFlashMapDecodeParameters() throws Exception {
273267
FlashMap flashMap = new FlashMap();
274268
flashMap.put("key", "value");
275269
flashMap.setTargetRequestPath("/path");
@@ -295,11 +289,8 @@ public void saveOutputFlashMapDecodeParameters() throws Exception {
295289
assertEquals("value", flashMap.get("key"));
296290
}
297291

298-
// SPR-12569
299-
300-
@Test
292+
@Test // SPR-12569
301293
public void flashAttributesWithQueryParamsWithSpace() throws Exception {
302-
303294
String encodedValue = URLEncoder.encode("1 2", "UTF-8");
304295

305296
FlashMap flashMap = new FlashMap();

0 commit comments

Comments
 (0)