Skip to content

Commit

Permalink
🐛 Fix bug in calculation of maximum form part size
Browse files Browse the repository at this point in the history
  • Loading branch information
TAKETODAY committed Nov 10, 2023
1 parent ed3aa4e commit 7843056
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,14 @@ private boolean tooManyParts(AtomicInteger partCount) {
private Publisher<? extends PartEvent> createEvents(HttpHeaders headers, Flux<MultipartParser.BodyToken> bodyTokens) {
if (MultipartUtils.isFormField(headers)) {
Flux<DataBuffer> contents = bodyTokens.map(MultipartParser.BodyToken::getBuffer);
int maxSize = (int) Math.min(this.maxInMemorySize, this.maxPartSize);
int maxSize;
if (this.maxPartSize == -1) {
maxSize = this.maxInMemorySize;
}
else {
// maxInMemorySize is an int, so we can safely cast the long result of Math.min
maxSize = (int) Math.min(this.maxInMemorySize, this.maxPartSize);
}
return DataBufferUtils.join(contents, maxSize)
.map(content -> {
String value = content.toString(MultipartUtils.charset(headers));
Expand Down Expand Up @@ -222,8 +229,12 @@ private Publisher<? extends PartEvent> createEvents(HttpHeaders headers, Flux<Mu
}

private boolean tooLarge(AtomicLong partSize, DataBuffer buffer) {
long size = partSize.addAndGet(buffer.readableByteCount());
return this.maxPartSize > 0 && size > this.maxPartSize;
if (this.maxPartSize != -1) {
long size = partSize.addAndGet(buffer.readableByteCount());
return size > this.maxPartSize;
}
else {
return false;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

package cn.taketoday.http.codec.multipart;

import org.assertj.core.api.AssertionsForClassTypes;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -46,6 +45,7 @@
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.entry;

/**
* @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
Expand Down Expand Up @@ -146,8 +146,8 @@ public void noBody() {
Flux<PartEvent> result = this.reader.read(forClass(PartEvent.class), request, emptyMap());

StepVerifier.create(result)
.assertNext(form(headers -> assertThat(headers).contains(AssertionsForClassTypes.entry("Part", List.of("1"))), ""))
.assertNext(data(headers -> assertThat(headers).contains(AssertionsForClassTypes.entry("Part", List.of("2"))), bodyText("a"), true))
.assertNext(form(headers -> assertThat(headers).contains(entry("Part", List.of("1"))), ""))
.assertNext(data(headers -> assertThat(headers).contains(entry("Part", List.of("2"))), bodyText("a"), true))
.verifyComplete();
}

Expand Down Expand Up @@ -258,7 +258,21 @@ void partSizeTooLarge() {
.assertNext(data(headersFormField("text2"), bodyText("b"), true))
.expectError(DataBufferLimitException.class)
.verify();
}

@Test
void formPartTooLarge() {
MockServerHttpRequest request = createRequest(
new ClassPathResource("simple.multipart", getClass()), "simple-boundary");

PartEventHttpMessageReader reader = new PartEventHttpMessageReader();
reader.setMaxInMemorySize(40);

Flux<PartEvent> result = reader.read(forClass(PartEvent.class), request, emptyMap());

StepVerifier.create(result)
.expectError(DataBufferLimitException.class)
.verify();
}

@Test
Expand Down

0 comments on commit 7843056

Please sign in to comment.