Skip to content

fix(http_parser): fix chunked size overflow and MediaType.toString quoting - #2001

Merged
kevmoo merged 4 commits into
masterfrom
fix-http_parser
Oct 13, 2026
Merged

kevmoo merged 4 commits into
masterfrom
fix-http_parser

Conversation

@kevmoo

@kevmoo kevmoo commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Rationale

  1. 64-bit chunk size overflow in ChunkedCodingDecoder (_Sink._decode): Chunk sizes were accumulated via _size = (_size << 4) + digit without checking for integer overflow, and chunk body bounds were computed as math.min(end, start + _size). A 16-digit hexadecimal chunk size >= 0x8000000000000000 (or start + _size when start > 0) overflowed signed 64-bit int to a negative index and threw RangeError in Uint8Buffer.addAll instead of FormatException, while 17+ hex digits truncated the declared chunk size.
  2. Unescaped backslashes and unquoted empty parameter values in MediaType.toString(): In 4.1.2, _quotedString in scan.dart was tightened to disallow unescaped \ in qdtext, but _escapedChar in media_type.dart remained RegExp(r'["\x00-\x1F\x7F]') (missing \\). Any parameter value containing \ (foo="bar\\baz" or trail="end\\") was serialized without escaping \, corrupting bar\baz to barbaz on re-parse and turning trailing backslashes (trail="end\\") into an unterminated quoted string (trail="end\") that threw FormatException in MediaType.parse(). Empty parameter values (foo="") also failed nonToken.hasMatch("") and serialized as foo=, throwing FormatException on re-parse.

Summary of Changes

  • pkgs/http_parser/lib/src/chunked_coding/decoder.dart: Check if (_size > _maxSizeBeforeShift) before accumulating _size = (_size * 16) + digit in _State.size, throwing FormatException('Chunk size is too large.', bytes, start), compute final bytesToRead = math.min(end - start, _size) in _State.body, and remove unused name/toString() members on private enum _State.
  • pkgs/http_parser/lib/src/media_type.dart: Add \\ to _escapedChar (RegExp(r'["\x00-\x1F\x7F\\]')) and quote empty parameter values (if (value.isEmpty || nonToken.hasMatch(value))).
  • pkgs/http_parser/test/chunked_coding_test.dart, pkgs/http_parser/test/media_type_test.dart, & pkgs/http_parser/CHANGELOG.md: Add regression tests for 64-bit chunk size overflows and MediaType.toString() / MediaType.parse() round-tripping (159 tests passing), and document under 4.1.3-wip.

Verification

  • dart analyze --fatal-infos: exit 0
  • dart format --output=none --set-exit-if-changed .: exit 0
  • dart test -p vm -c source & dart test -p node: exit 0 (159 tests passed)

…erflow

Check that shifting `_size` left by 4 bits does not overflow a signed 64-bit
integer in `_Sink._decode`, throwing a `FormatException` when a chunk size
exceeds `0x7fffffffffffffff` instead of overflowing to a negative bound or
wrapping to zero. Also compute `math.min(end - start, _size)` in `_State.body`
so `start + _size` cannot overflow on valid large chunk sizes.
@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

PR Health

Coverage ✔️
File Coverage
pkgs/http_parser/lib/src/chunked_coding/decoder.dart 💚 96 % ⬆️ 3 %
pkgs/http_parser/lib/src/media_type.dart 💚 98 %

This check for test coverage is informational (issues shown here will not fail the PR).

This check can be disabled by tagging the PR with skip-coverage-check.

License Headers ✔️
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
Files
no missing headers

All source files should start with a license header.

Unrelated files missing license headers
Files
pkgs/http_multi_server/test/cert.dart

This check can be disabled by tagging the PR with skip-license-check.

Breaking changes ✔️
Package Change Current Version New Version Needed Version Looking good?
http_parser None 4.1.2 4.1.3-wip 4.1.3-wip ✔️

This check can be disabled by tagging the PR with skip-breaking-check.

Unused Dependencies ✔️
Package Status
http_parser ✔️ All dependencies utilized correctly.

For details on how to fix these, see dependency_validator.

This check can be disabled by tagging the PR with skip-unused-dependencies-check.

API leaks ✔️

The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API.

Package Leaked API symbol Leaking sources

This check can be disabled by tagging the PR with skip-leaking-check.

Changelog Entry ✔️
Package Changed Files

Changes to files need to be accounted for in their respective changelogs.

This check can be disabled by tagging the PR with skip-changelog-check (for example, for non-user-visible changes when the package version is already at -wip).

…ype.toString

Include `\` in `_escapedChar` so quoted parameter values containing backslashes
round-trip through `MediaType.parse(mediaType.toString())` without corrupting
escaped characters or leaving a trailing unescaped quote, and quote empty
parameter values (`value.isEmpty`) as `""` instead of emitting a bare `=`.
Also remove unused `name` and `toString()` members from private `enum _State`
in `chunked_coding/decoder.dart`.
@kevmoo kevmoo changed the title fix(http_parser): reject 64-bit chunk size overflow in chunked coding fix(http_parser): fix chunked size overflow and MediaType.toString quoting Oct 3, 2026
…ctly

Avoid passing `List<int>.addAll` tear-offs into `ByteConversionSink.withCallback`,
which triggers a `dart2wasm` TFA `RuntimeError: unreachable` trap when
`Uint8Buffer.addAll` is present in the same compilation unit.
@kevmoo
kevmoo merged commit ab986ad into master Oct 13, 2026
47 checks passed
@kevmoo
kevmoo deleted the fix-http_parser branch October 13, 2026 01:59
copybara-service Bot pushed a commit to dart-lang/sdk that referenced this pull request Oct 15, 2026
Revisions updated by `dart tools/rev_sdk_deps.dart`.

native is rolled separately in
https://dart-review.googlesource.com/c/sdk/+/563524.

http (https://github.com/dart-lang/http/compare/23f8574..7d7aae2):
  7d7aae2  Mon Oct 12 20:39:25 2026 -0700  Kevin Moore  Clean up dependencies and expand Node and Wasm test coverage (dart-lang/http#1903)
  ab986ad  Mon Oct 12 18:59:24 2026 -0700  Kevin Moore  fix(http_parser): fix chunked size overflow and MediaType.toString quoting (dart-lang/http#2001)
  cb8113b  Mon Oct 12 17:35:26 2026 -0700  Kevin Moore  docs(http2): move post-3.1.0 security entries to 3.2.0-wip (dart-lang/http#2022)

test (https://github.com/dart-lang/test/compare/30acb69..9bf69a8):
  9bf69a88  Tue Oct 13 14:33:18 2026 -0700  Nate Bosch  Reject asynchronous matchers inside isNot and anyOf (dart-lang/test#2792)

tools (https://github.com/dart-lang/tools/compare/2b54c71..350bde5):
  350bde54f  Tue Oct 13 08:22:26 2026 -0700  Kevin Moore  chore(coverage): prepare for v1.16.0 release (dart-lang/tools#2643)
  a55965844  Tue Oct 13 13:29:52 2026 +0200  Sigurd Meldgaard  [markdown] Fix quadratic parsing of consecutive link reference definitions (dart-lang/tools#2662)

[email protected]
TEST=ci

Change-Id: I1065854cfbaf71ebb7a097d89f28902394a80c2e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/563365
Commit-Queue: Nate Bosch <[email protected]>
Reviewed-by: Brian Quinlan <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants