Whole file
defnull/multipart
The author described this change as “fix: Allow empty segment names”. It counts as a record because the check below fails on the code as it stood at e80c30a13 and passes on 6756044c9, with nothing else changed between the two runs.
Projectdefnull/multipart
Fix saved2024-09-28
Sharing licenceMIT · LICENSE
Change size+11 −8
What the code was meant to do, written into the code itself as a save note
fix: Allow empty segment names
The change
| 407 | 407 | ||
| 408 | 408 | #: List of headers as name/value pairs with normalized (Title-Case) names. | |
| 409 | 409 | headerlist: List[Tuple[str, str]] | |
| 410 | - | #: The required 'name' option of the Content-Disposition header. | |
| 410 | + | #: The 'name' option of the Content-Disposition header. Always a string, | |
| 411 | + | #: but may be empty. | |
| 411 | 412 | name: str | |
| 412 | 413 | #: The optional 'filename' option of the Content-Disposition header. | |
| 413 | 414 | filename: Optional[str] | |
| ⋯ | |||
| 449 | 450 | self._size_limit = parser.max_segment_size | |
| 450 | 451 | ||
| 451 | 452 | def _add_headerline(self, line: bytearray): | |
| 452 | - | assert line and not self.name | |
| 453 | + | assert line and self.name is None | |
| 453 | 454 | parser = self._parser | |
| 454 | 455 | ||
| 455 | 456 | if line[0] in b" \t": # Multi-line header value | |
| ⋯ | |||
| 477 | 478 | self.headerlist.append((name.title(), value)) | |
| 478 | 479 | ||
| 479 | 480 | def _close_headers(self): | |
| 480 | - | assert not self.name and not self.complete | |
| 481 | + | assert self.name is None | |
| 481 | 482 | ||
| 482 | 483 | cdisp = self.header("Content-Disposition") | |
| 483 | 484 | if not cdisp: | |
| 484 | 485 | raise self._fail("Missing Content-Disposition segment header") | |
| 485 | 486 | cdisp, args = parse_options_header(cdisp) | |
| 486 | - | if cdisp != "form-data" or "name" not in args: | |
| 487 | - | raise self._fail("Invalid Content-Disposition segment header") | |
| 488 | - | self.name = args.get("name") | |
| 487 | + | if cdisp != "form-data": | |
| 488 | + | raise self._fail("Invalid Content-Disposition segment header: Wrong type") | |
| 489 | + | if "name" not in args and self._parser.strict: | |
| 490 | + | raise self._fail("Invalid Content-Disposition segment header: Missing name option") | |
| 491 | + | self.name = args.get("name", "") | |
| 489 | 492 | self.filename = args.get("filename") | |
| 490 | 493 | ||
| 491 | 494 | content_type = self.header("Content-Type", "application/octet-stream") | |
| ⋯ | |||
| 495 | 498 | self._clen = int(self.header("Content-Length", -1)) | |
| 496 | 499 | ||
| 497 | 500 | def _update_size(self, bytecount: int): | |
| 498 | - | assert self.name and not self.complete | |
| 501 | + | assert self.name is not None and not self.complete | |
| 499 | 502 | self.size += bytecount | |
| 500 | 503 | if self._clen >= 0 and self.size > self._clen: | |
| 501 | 504 | raise self._fail("Segment Content-Length exceeded") | |
| ⋯ | |||
| 503 | 506 | raise self._fail("Maximum segment size exceeded") | |
| 504 | 507 | ||
| 505 | 508 | def _mark_complete(self): | |
| 506 | - | assert self.name and not self.complete | |
| 509 | + | assert self.name is not None and not self.complete | |
| 507 | 510 | if self._clen >= 0 and self.size != self._clen: | |
| 508 | 511 | raise self._fail("Segment size does not match Content-Length header") | |
| 509 | 512 | self.complete = True | |
The check that tells the two apart
fail→pass·test/test_push_parser.py::TestPushParser::test_header_wrong_segment_subtype
Check file test/test_push_parser.py, taken without changes from the fix and copied onto the older code, so the exact same check runs against both versions.
Origin and history
The code before ite80c30a13ffb4183b1d90d42eec84d0ce53d0fcf
Broken version dated2024-09-28
Modulemultipart
Units changedMultipartSegment
Fingerprintae6f9c83668deb64
Checked2026-08-18 by goldset/0.1
Every field above is generated by our program. None of it is written by hand.
Other bugs found in defnull/multipart
- 2026-03-09change: Raise ParserStateError on invalid boundaries.
- 2025-07-26fix: Hardened header parsing.
- 2025-01-21MultipartPart
- 2024-08-26parse_form_data
- 2024-08-26fix: Properly handle completely empty input stream.