Description
The new servlet MultipartHttpMessageConverter (spring-web, 7.1) silently drops every part whose body is empty, so a blank form field is indistinguishable from an absent field.
Analysis
Parts are emitted exclusively from PartListener.onBody(buffer, last=true) (PartGenerator: FormFieldState, InMemoryState, FileState). For an empty part, MultipartParser.BodyState computes len == 0 and transitions to the next headers state without ever invoking onBody, so the part is never added to the resulting MultiValueMap.
This is the servlet-side equivalent of the issue fixed for the reactive stack in #30953 (regression test: DefaultPartHttpMessageReaderTests.emptyLastPart asserts empty parts are emitted). The new servlet port did not carry the fix over; MultipartParserTests.noBody() currently pins the broken event sequence.
Impact
An HTML form with a blank text input yields "field absent" instead of "field = empty string", which can flip application logic that distinguishes the two (including auth/business-rule branches).
Reproduction
GET-style body:
--boundary
Content-Disposition: form-data; name="text1"
<empty>
--boundary
Content-Disposition: form-data; name="text2"
a
--boundary--
Reading via MultipartHttpMessageConverter returns only text2; text1 is missing.
Description
The new servlet
MultipartHttpMessageConverter(spring-web, 7.1) silently drops every part whose body is empty, so a blank form field is indistinguishable from an absent field.Analysis
Parts are emitted exclusively from
PartListener.onBody(buffer, last=true)(PartGenerator: FormFieldState, InMemoryState, FileState). For an empty part,MultipartParser.BodyStatecomputeslen == 0and transitions to the next headers state without ever invokingonBody, so the part is never added to the resultingMultiValueMap.This is the servlet-side equivalent of the issue fixed for the reactive stack in #30953 (regression test:
DefaultPartHttpMessageReaderTests.emptyLastPartasserts empty parts are emitted). The new servlet port did not carry the fix over;MultipartParserTests.noBody()currently pins the broken event sequence.Impact
An HTML form with a blank text input yields "field absent" instead of "field = empty string", which can flip application logic that distinguishes the two (including auth/business-rule branches).
Reproduction
GET-style body:Reading via
MultipartHttpMessageConverterreturns onlytext2;text1is missing.