Skip to content

framing: wrap page sequence numbers in 32 bits - #113

Open
mcc0nnell wants to merge 2 commits into
xiph:mainfrom
mcc0nnell:patch-rewards/page-number-rollover
Open

mcc0nnell wants to merge 2 commits into
xiph:mainfrom
mcc0nnell:patch-rewards/page-number-rollover

Conversation

@mcc0nnell

@mcc0nnell mcc0nnell commented Sep 15, 2026

Copy link
Copy Markdown

Summary

Keep Ogg page sequence-number arithmetic in the 32-bit unsigned domain used by the wire format, including rollover on 32-bit long platforms.

Details

Current main stores the page sequence number in long and increments it with signed arithmetic.

That causes several observable problems:

  • on 64-bit builds, decoding page 0xffffffff stores the next expected page as 0x100000000; a valid following page 0 is then treated as a discontinuity and ogg_stream_packetout() reports a false hole;
  • on 32-bit builds, page-number increment can trigger signed overflow;
  • on 32-bit builds, the valid wire value 0xffffffff maps to signed -1, which collides with libogg's existing pageno == -1 reset sentinel. Without distinguishing those states, the encoder can skip page 0xffffffff, and the decoder can suppress a hole when that page is actually missing.

The change keeps page-number comparison and increment in ogg_uint32_t, uses a defined mapping when storing the value back in the existing long field, and keeps reset state distinct from an initialized decoder sequence without changing the public struct layout.

Regression coverage exercises both a contiguous 0xfffffffd -> 0xfffffffe -> 0xffffffff -> 0 transition and a dropped 0xffffffff page across rollover.

Validation

  • x86-64 framing self-test under Clang ASan + UBSan with -Wall -Wextra -Werror: pass
  • i386 framing self-test under Clang UBSan with -Wall -Wextra -Werror: pass
  • x86-64 GCC framing + bitwise self-tests with -Wall -Wextra -Werror: pass
  • focused i386 probe on the first commit: encoder emits 0xfffffffe, 0; missing 0xffffffff is not reported as a hole
  • focused i386 probe on the current head: encoder emits 0xfffffffe, 0xffffffff; missing 0xffffffff reports exactly one hole

Signed-off-by: Robert McConnell robert@mcc0nnell.org

Signed-off-by: Robert McConnell <robert@mcc0nnell.org>
The initial modulo-32-bit fix still lets the valid 0xffffffff page number collide with the pageno==-1 reset sentinel on ILP32. That can make the encoder skip page 0xffffffff and can suppress a decoder hole when that page is missing.\n\nStore 32-bit page numbers with a defined long mapping, distinguish decoder sequence initialization from reset state, and extend the rollover regression to cover both contiguous wrap and a dropped 0xffffffff page.

Signed-off-by: Robert McConnell <robert@mcc0nnell.org>
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.

1 participant