Skip to content

framing: preserve aliased stream input across body growth - #115

Open
mcc0nnell wants to merge 2 commits into
xiph:mainfrom
mcc0nnell:patch-rewards/iovecin-self-alias
Open

mcc0nnell wants to merge 2 commits into
xiph:mainfrom
mcc0nnell:patch-rewards/iovecin-self-alias

Conversation

@mcc0nnell

@mcc0nnell mcc0nnell commented Sep 15, 2026

Copy link
Copy Markdown

Summary

Preserve caller input that aliases ogg_stream_state.body_data when framing APIs compact or grow the internal body buffer. The affected public entry points are ogg_stream_iovecin() / ogg_stream_packetin() on the encoding side and ogg_stream_pagein() on the page-decomposition side.

Problem

All three paths can retain a caller pointer into os->body_data, mutate or grow that allocation, and only then consume the saved pointer. If _os_body_expand() moves the allocation, the later memcpy() reads freed storage.

Two standalone sanitizer repros reliably fail on current main (06a5e026):

  • ogg_stream_packetin() with a 16 KiB packet aliasing the stream's initial body buffer: ASan heap-use-after-free, 16 KiB read in ogg_stream_iovecin(), after _os_body_expand() reallocates the source allocation.
  • ogg_stream_pagein() with a valid-sized lacing table and og.body aliasing the same 16 KiB allocation: ASan heap-use-after-free, 16 KiB read after _os_body_expand() moves the body buffer.

ogg_stream_iovecin() directly reproduces the first failure as well.

Fix

When submitted packet/page data points into the stream's current body allocation, snapshot that input before compaction or growth. External caller buffers remain on the existing path and incur no extra allocation.

Validation

  • test_framing under Clang ASan + UBSan: pass
  • direct ogg_stream_iovecin() self-alias reproducer: ASan UAF before, byte-identical success after
  • ogg_stream_packetin() wrapper reproducer: ASan UAF before, byte-identical success after
  • ogg_stream_pagein() body-alias reproducer: ASan UAF before, byte-identical success after
  • strict C89 -pedantic-errors -Wall -Wextra -Werror: pass
  • git diff --check: pass

This is the framing-buffer analogue of the self-referential growth problem addressed separately in bit-packing PR #106; the affected storage and APIs are independent.

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

Signed-off-by: Robert McConnell <robert@mcc0nnell.org>
Signed-off-by: Robert McConnell <robert@mcc0nnell.org>
@mcc0nnell mcc0nnell changed the title framing: preserve aliased packet input across growth framing: preserve aliased stream input across body growth Sep 15, 2026
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