Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -60,6 +60,7 @@ public class FormEncodingProvider<T> extends AbstractConfigurableProvider
private String attachmentDir;
private String attachmentThreshold;
private String attachmentMaxSize;
private int formParamsMaxSize = FormUtils.DEFAULT_FORM_PARAMS_MAX_SIZE;

private boolean expectEncoded;

Expand All @@ -86,6 +87,10 @@ public void setAttachmentThreshold(String threshold) {
public void setAttachmentMaxSize(String maxSize) {
attachmentMaxSize = maxSize;
}

public void setFormParamsMaxSize(int maxSize) {
this.formParamsMaxSize = maxSize;
}

public void setValidator(FormValidator formValidator) {
validator = formValidator;
Expand Down Expand Up @@ -171,13 +176,13 @@ protected void populateMap(MultivaluedMap<String, String> params,
if (servletRequest == null) {
FormUtils.populateMapFromString(params,
PhaseInterceptorChain.getCurrentMessage(),
FormUtils.readBody(is, enc),
FormUtils.readBody(is, enc, formParamsMaxSize),
enc,
decode);
} else {
FormUtils.populateMapFromString(params,
PhaseInterceptorChain.getCurrentMessage(),
FormUtils.readBody(is, enc),
FormUtils.readBody(is, enc, formParamsMaxSize),
enc,
decode,
(jakarta.servlet.http.HttpServletRequest)servletRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import jakarta.ws.rs.core.MultivaluedMap;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.common.util.SystemPropertyAction;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
Expand All @@ -54,6 +55,9 @@
import org.apache.cxf.transport.http.AbstractHTTPDestination;

public final class FormUtils {
public static final int DEFAULT_FORM_PARAMS_MAX_SIZE =
SystemPropertyAction.getInteger("org.apache.cxf.form-params-max-size", 104857600 /* 100Mb */);

public static final int DEFAULT_MAX_FORM_PARAM_COUNT = 500;

public static final String FORM_PARAMS_FROM_HTTP_PARAMS = "set.form.parameters.from.http.parameters";
Expand Down Expand Up @@ -116,10 +120,18 @@ public static void addPropertyToForm(MultivaluedMap<String, String> map, String
}
}

/**
* @deprecated please use {@code readBody(InputStream is, String encoding, int maxSize)}
*/
@Deprecated
public static String readBody(InputStream is, String encoding) {
return readBody(is, encoding, -1);
}

public static String readBody(InputStream is, String encoding, int maxSize) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
IOUtils.copy(is, bos, 1024);
IOUtils.copy(is, bos, 1024, maxSize);
return new String(bos.toByteArray(), encoding);
} catch (Exception ex) {
throw ExceptionUtils.toInternalServerErrorException(ex, null);
Expand All @@ -134,6 +146,8 @@ public static void populateMapFromString(MultivaluedMap<String, String> params,
if (StringUtils.isEmpty(postBody)) {
return;
}
final int numberOfParts = estimateNumberOfParts(postBody);
checkNumberOfParts(m, numberOfParts);
String[] parts = postBody.split("&");
checkNumberOfParts(m, parts.length);
for (String part : parts) {
Expand Down Expand Up @@ -288,6 +302,18 @@ public static void populateMapFromMultipart(MultivaluedMap<String, String> param
}
}

/**
* Estimates how many parts we should expect by checking on & separator
*/
private static int estimateNumberOfParts(String postBody) {
int count = 0;
int index = -1;
while ((index = postBody.indexOf('&', index + 1)) >= 0) {
++count;
}
return count;
}
Comment thread
reta marked this conversation as resolved.

private static void checkNumberOfParts(Message m, int numberOfParts) {
if (m == null || m.getExchange() == null || m.getExchange().getInMessage() == null) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.zip.GZIPInputStream;

import javax.xml.namespace.QName;
Expand Down Expand Up @@ -342,6 +344,30 @@ public void testPostEmptyFormAsInStream() throws Exception {
assertEquals("empty form", r.readEntity(String.class));
}

@Test
public void testTooManyFormParams() throws Exception {
// Exceeding 500 limit
String params = IntStream.range(0, 501).mapToObj(i -> "param" + i + "=" + i).collect(Collectors.joining("&"));
String address = "http://localhost:" + PORT + "/bookstore/form";
WebClient wc = WebClient.create(address);
wc.type(MediaType.APPLICATION_FORM_URLENCODED);
Response r = wc.post(new ByteArrayInputStream(params.getBytes(StandardCharsets.UTF_8)));
assertThat("max form params limit reached", r.getStatus(), equalTo(413));
}

@Test
public void testTooLargeFormParams() throws Exception {
// Exceeding 100Mb limit
String params = IntStream.range(0, 110)
.mapToObj(i -> "param" + i + "="
+ new String(Integer.toString(i)).repeat(524800)).collect(Collectors.joining("&"));
String address = "http://localhost:" + PORT + "/bookstore/form";
WebClient wc = WebClient.create(address);
wc.type(MediaType.APPLICATION_FORM_URLENCODED);
Response r = wc.post(new ByteArrayInputStream(params.getBytes(StandardCharsets.UTF_8)));
assertThat("max form params limit reached", r.getStatus(), equalTo(500));
Comment thread
reta marked this conversation as resolved.
}

@Test
public void testGetBookDescriptionHttpResponse() throws Exception {
String address = "http://localhost:" + PORT + "/bookstore/httpresponse";
Expand Down
Loading