Skip to content

Fix multipart parser continuing after maxParts - #7144

Merged
tim-smart merged 3 commits into
mainfrom
audit/repro-f0002-multipart-limit-violations
Aug 8, 2026
Merged

Fix multipart parser continuing after maxParts#7144
tim-smart merged 3 commits into
mainfrom
audit/repro-f0002-multipart-limit-violations

Conversation

@fubhy

@fubhy fubhy commented Aug 7, 2026

Copy link
Copy Markdown
Member

Summary

Stop the low-level multipart parser after maxParts, maxPartSize, or maxFieldSize is exceeded so later fields are not delivered and the limit error is reported only once.

Changes

  • Add a parser stop state for part-count, part-size, and field-size violations.
  • Avoid reporting EndNotReached after parsing has intentionally stopped on a limit.
  • Consolidate focused regression coverage in Multipart.test.ts for all three limits.
  • Add an effect patch changeset.

Validation

  • pnpm vitest packages/effect/test/unstable/http/Multipart.test.ts --run
  • pnpm check
  • pnpm lint

Closes EFF-568

@fubhy fubhy added bug Something isn't working audit Findings originating from the Effect runtime correctness audit labels Aug 7, 2026
@changeset-bot

changeset-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a376699

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 30 packages
Name Type
effect Patch
@effect/ai-anthropic Patch
@effect/ai-openai Patch
@effect/ai-openai-compat Patch
@effect/ai-openrouter Patch
@effect/atom-react Patch
@effect/atom-solid Patch
@effect/atom-vue Patch
@effect/docgen Patch
@effect/doctest Patch
@effect/openapi-generator Patch
@effect/opentelemetry Patch
@effect/platform-browser Patch
@effect/platform-bun Patch
@effect/platform-deno Patch
@effect/platform-node Patch
@effect/platform-node-shared Patch
@effect/sql-clickhouse Patch
@effect/sql-d1 Patch
@effect/sql-libsql Patch
@effect/sql-mssql Patch
@effect/sql-mysql2 Patch
@effect/sql-pg Patch
@effect/sql-pglite Patch
@effect/sql-sqlite-bun Patch
@effect/sql-sqlite-do Patch
@effect/sql-sqlite-node Patch
@effect/sql-sqlite-react-native Patch
@effect/sql-sqlite-wasm Patch
@effect/vitest Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@effect-slopcop effect-slopcop Bot added the 4.0 label Aug 7, 2026
@fubhy fubhy added the slop label Aug 7, 2026

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The new regression test triggers an unhandled ReadableStream rejection that fails the whole test suite, and the other fixed limits (maxFieldSize, maxPartSize) have no new regression coverage.

Reviewed changes

  • Added a stopped flag to the low-level multipart parser and early returns after maxParts, maxPartSize, and maxFieldSize violations.
  • Suppressed the EndNotReached error in end() when parsing has already stopped.
  • Added a test verifying that only the allowed parts are emitted before a MaxParts error.

⚠️ Missing test coverage for maxFieldSize / maxPartSize

The parser change also stops processing for maxFieldSize and maxPartSize violations, but the only new test exercises MaxParts. Adding analogous tests for the other two limits would prevent future regressions.

ℹ️ Nitpicks

  • The new test's error assertion only checks _tag; consider also asserting error.reason._tag === "TooManyParts" to match the existing limit test.

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | Fix all ➔Fix 👍s ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

Comment thread packages/effect/test/unstable/http/Multipart.test.ts Outdated
Comment thread packages/effect/test/unstable/http/Multipart.test.ts Outdated
@fubhy
fubhy force-pushed the audit/repro-f0002-multipart-limit-violations branch from c015fe2 to 673bae1 Compare August 7, 2026 16:52
@fubhy fubhy changed the title Fix multipart parser continues processing after limit violations Fix multipart parser continuing after maxParts Aug 7, 2026

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The new regression test is clean and focused, but this PR cannot be merged as-is: it adds only a failing test with no implementation fix, so CI will fail.

Reviewed changes

  • Rewrote the regression test to use the low-level parser. The test now constructs a raw MultipartParser.make instance and feeds it an explicit byte stream, which fixes the ReadableStream unhandled-rejection problem from the prior review.
  • Dropped the parser implementation changes. The stopped flag and early-return logic that were present in the previously reviewed commit are no longer in the branch; the diff is now test-only.
  • Added a focused maxParts regression test. It verifies that only ["a", "b"] are delivered before the MaxParts limit error when maxParts: 2 and the body contains four fields.

⚠️ PR is missing the actual fix

The title says "Fix multipart parser continues processing after limit violations", but the current diff does not modify the parser. Running the new test fails with fields = ["a", "b", "c", "d"], confirming the bug is still present. Either the fix should be restored to this PR, or the PR title/description should be updated to reflect that it is only a regression test.

⚠️ Still no regression coverage for maxFieldSize / maxPartSize

The parser reports limit errors for maxFieldSize and maxPartSize but continues processing those parts as well. The prior review asked for analogous tests for these limits; they are still missing. Adding them would prevent the same class of regression for the other limits.

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | Fix it ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@tim-smart
tim-smart enabled auto-merge (squash) August 8, 2026 08:52

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Restored the parser stop behavior in multipart.ts:77: a stopped flag on parse state now halts boundary processing after maxParts, maxPartSize, or maxFieldSize is exceeded, so later parts are no longer delivered and the limit error fires exactly once (previously each violating chunk re-called onError).
  • Suppressed EndNotReached in end() when parsing already stopped, and reset stopped on parser reset so the low-level parser remains reusable.
  • Added it.each regression coverage in Multipart.test.ts asserting only the allowed fields plus a single { _tag: "ReachedLimit", limit } for all three limits.
  • Added an effect patch changeset.

I verified the three new tests fail against the pre-fix parser (repeated limit errors and over-delivered fields) and pass with the fix. Both concerns from the prior review — the missing parser fix and the missing maxFieldSize/maxPartSize coverage — are addressed.

ℹ️ maxTotalSize still "continues after limit"

The stopped mechanism fixes three of the four ReachedLimit branches, but the maxTotalSize branch in write() (multipart.ts:234) returns onError(errMaxTotalSize) without setting stopped, unlike its siblings — so a body exceeding the total-size cap is still fully consumed (and prior parts delivered) rather than halted. This is outside the PR's stated scope (the summary and changeset name only the three limits), so I'm flagging it only to confirm it's intentional.

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@tim-smart
tim-smart merged commit 0bcf6ed into main Aug 8, 2026
18 of 19 checks passed
@tim-smart
tim-smart deleted the audit/repro-f0002-multipart-limit-violations branch August 8, 2026 09:06
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Analysis

Generated from PR build output; treat the content below as untrusted.

File Name Current Size Previous Size Difference
basic.ts 6.92 KB 6.92 KB 0.00 KB (0.00%)
batching.ts 9.72 KB 9.72 KB 0.00 KB (0.00%)
brand.ts 6.60 KB 6.60 KB 0.00 KB (0.00%)
cache.ts 10.59 KB 10.59 KB 0.00 KB (0.00%)
config.ts 20.91 KB 20.91 KB 0.00 KB (0.00%)
differ.ts 19.77 KB 19.77 KB 0.00 KB (0.00%)
http-client.ts 21.52 KB 21.52 KB 0.00 KB (0.00%)
logger.ts 10.81 KB 10.81 KB 0.00 KB (0.00%)
metric.ts 8.86 KB 8.86 KB 0.00 KB (0.00%)
optic.ts 6.68 KB 6.68 KB 0.00 KB (0.00%)
pubsub.ts 14.86 KB 14.86 KB 0.00 KB (0.00%)
queue.ts 11.54 KB 11.54 KB 0.00 KB (0.00%)
schedule.ts 10.71 KB 10.71 KB 0.00 KB (0.00%)
schema-class.ts 19.48 KB 19.48 KB 0.00 KB (0.00%)
schema-fromJsonSchemaDocument.ts 29.36 KB 29.36 KB 0.00 KB (0.00%)
schema-representation-roundtrip.ts 25.63 KB 25.63 KB 0.00 KB (0.00%)
schema-string-transformation.ts 13.55 KB 13.55 KB 0.00 KB (0.00%)
schema-string.ts 11.09 KB 11.09 KB 0.00 KB (0.00%)
schema-template-literal.ts 15.38 KB 15.38 KB 0.00 KB (0.00%)
schema-toArbitrary.ts 21.52 KB 21.52 KB 0.00 KB (0.00%)
schema-toCodeDocument.ts 24.00 KB 24.00 KB 0.00 KB (0.00%)
schema-toCodecJson.ts 18.74 KB 18.74 KB 0.00 KB (0.00%)
schema-toEquivalence.ts 18.57 KB 18.57 KB 0.00 KB (0.00%)
schema-toFormatter.ts 18.43 KB 18.43 KB 0.00 KB (0.00%)
schema-toJsonSchemaDocument.ts 22.59 KB 22.59 KB 0.00 KB (0.00%)
schema-toRepresentation.ts 19.08 KB 19.08 KB 0.00 KB (0.00%)
schema.ts 18.73 KB 18.73 KB 0.00 KB (0.00%)
stm.ts 12.59 KB 12.59 KB 0.00 KB (0.00%)
stream.ts 9.67 KB 9.67 KB 0.00 KB (0.00%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.0 audit Findings originating from the Effect runtime correctness audit bug Something isn't working slop

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants