Skip to content

http: parse the full positive chunk-size range without signed overflow - #832

Open
tcoatswo wants to merge 1 commit into
apache:trunkfrom
tcoatswo:fix-chunk-size-bounds-trunk
Open

tcoatswo wants to merge 1 commit into
apache:trunkfrom
tcoatswo:fix-chunk-size-bounds-trunk

Conversation

@tcoatswo

Copy link
Copy Markdown

Trunk already prevents the signed left shift in parse_chunk_size() by limiting significant hex digits to sizeof(apr_off_t) * 8 - 4 bits. That also rejects positive chunk sizes whose highest hex digit would fit in a signed apr_off_t (for example, a 16-digit size below 0x8000000000000000 on a 64-bit build).

Use the full-width digit budget and check the accumulated prefix before each four-bit shift. The guard rejects a prefix that would shift into the sign bit; the existing APR_ENOSPC path still returns HTTP 413 for oversized values. Add three pyhttpd raw-socket cases for the first high-bit value, all-one hex digits, and leading zeroes.

Validation

  • git diff --check and Python syntax compilation passed.
  • The same pre-shift guard and three pyhttpd cases passed on a patched 2.4.69 sanitizer build: test/modules/http1 120 passed, 2 skipped; the high-bit reproducer produced no ASan/UBSan diagnostic.
  • The full current-trunk build and pyhttpd suite have not run in this environment. These HTTP-status tests also pass on the old safe trunk guard; they preserve the error response, while UBSan checks the undefined-shift boundary.

README.CHANGES exempts fixes for regressions that existed only on trunk, so this draft has no changes entry.


  • This PR does not report or address a security vulnerability.
  • Code follows the httpd style guide.
  • No new log messages were added.
  • A changes entry is not needed for a trunk-only regression.
  • pyhttpd test cases are included in test/modules/http1.

@tcoatswo
tcoatswo marked this pull request as ready for review October 12, 2026 03:09
@arturobernalg

Copy link
Copy Markdown
Member

The overflow guard itself looks correct.

I reproduced the range difference on current trunk: with a 64-bit apr_off_t, trunk accepts through 0x0fffffffffffffff, while this change accepts through 0x7fffffffffffffff. In particular, 0x1000000000000000 is rejected with 413/AH01590 on trunk and passes chunk-size parsing with this patch.

The current three tests also pass on unmodified trunk, so they do not exercise the behavior changed here. Could you add a positive regression case that fails with the old -4 guard and passes with this change, while accounting for the build's apr_off_t width? Using a body-consuming handler such as /h1test/echo would make it possible to distinguish successful chunk-size parsing from the later incomplete-body condition.

The comment above parse_chunk_size() should also be updated: it still describes the old sign-bit overflow path and says the too-many-bits case returns APR_EGENERAL, while that path actually returns APR_ENOSPC.

The remaining ctx->remaining < 0 check is unreachable after the pre-shift guard and can be removed as well.

RFC 9112 requires recipients to handle potentially large hexadecimal chunk sizes without integer-conversion overflow or precision loss; the new pre-shift check preserves that property while extending the accepted range.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants