Skip to content

Commit

Permalink
Restrict memory allocation in ContentCachingRequestWrapper
Browse files Browse the repository at this point in the history
Prior to this commit, the `ContentCachingRequestWrapper` could allocate
a `FastByteArrayOutputStream` block that was larger than the content
cache limit given as a consturctor argument. This was due to an
optimization applied in gh-31834 for allocating the right content cache
size when the request size is known.

Fixes gh-32987
  • Loading branch information
bclozel committed Jun 10, 2024
1 parent 6681394 commit 0ca393c
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ public ContentCachingRequestWrapper(HttpServletRequest request) {
public ContentCachingRequestWrapper(HttpServletRequest request, int contentCacheLimit) {
super(request);
int contentLength = request.getContentLength();
this.cachedContent = (contentLength > 0) ? new FastByteArrayOutputStream(contentLength) : new FastByteArrayOutputStream();
if (contentLength > 0) {
this.cachedContent = new FastByteArrayOutputStream(Math.min(contentLength, contentCacheLimit));
}
else {
this.cachedContent = new FastByteArrayOutputStream();
}
this.contentCacheLimit = contentCacheLimit;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
package org.springframework.web.util;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;

import org.junit.jupiter.api.Test;

import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -89,6 +92,19 @@ void cachedContentToStringWithLimit() throws Exception {
assertThat(wrapper.getContentAsString()).isEqualTo(new String("Hel".getBytes(CHARSET), CHARSET));
}

@Test
void shouldNotAllocateMoreThanCacheLimit() throws Exception {
ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(createGetRequest("Hello World"), CONTENT_CACHE_LIMIT);
Field field = ReflectionUtils.findField(ContentCachingRequestWrapper.class, "cachedContent");
ReflectionUtils.makeAccessible(field);
FastByteArrayOutputStream cachedContent = (FastByteArrayOutputStream) ReflectionUtils.getField(field, wrapper);
field = ReflectionUtils.findField(FastByteArrayOutputStream.class, "initialBlockSize");
ReflectionUtils.makeAccessible(field);
int blockSize = (int) ReflectionUtils.getField(field, cachedContent);
assertThat(blockSize).isEqualTo(CONTENT_CACHE_LIMIT);
}


@Test
void cachedContentWithOverflow() throws Exception {
ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(
Expand Down

0 comments on commit 0ca393c

Please sign in to comment.