Summary
The Pelorus side-data pack/parse code (interop.c, vendored into vmafx as
core/src/interop/pelorus_interop.c per ADR-1113) computes section-payload
pointers as blob_base + padded_offset and then casts the resulting
const uint8_t * to the concrete section struct type before reading fields.
The framing comment documents that payload starts are padded up to 8 bytes
"so a consumer can cast the returned pointer to the section struct without an
unaligned access" — but that guarantee only holds relative to the blob base.
If a caller hands the parser a blob whose base address is not 8-byte aligned,
every base + offset section pointer inherits the base's misalignment, and the
subsequent struct-field reads are undefined behavior (unaligned access). On
strict-alignment targets (some aarch64 configs, UBSan -fsanitize=alignment)
this is a real fault, not just a theoretical one.
Impact
Low in practice for the current vmafx consumer: perceptual_weight.c already
memcpys section bytes into a local aligned struct rather than casting, so
vmafx is only exposed if a caller passes a misaligned blob straight to the
parser. But the parser is the canonical reference and should not depend on an
undocumented "callers must pass an 8-byte-aligned blob" precondition.
Suggested fix (either)
- Make the parser alignment-agnostic — read each header/section-dir/section
field via memcpy into a properly-aligned local struct instead of casting the
blob pointer. This removes the precondition entirely and matches what
perceptual_weight.c already does. (Preferred — robust, and the cost is
negligible for these small fixed structs.)
- Or formalize + enforce the precondition — document that the blob base must
be alignof(max_align_t)-aligned and assert it at parse entry, so misuse
fails loudly instead of silently invoking UB.
Why filed upstream
The vmafx copy is a read-only vendored mirror (ADR-1113 + scripts/sync-pelorus-interop.sh
drift guard); the fix must land here in VMAFx/pelorus and then be re-vendored.
Found during the vmafx 2026-06-27 bug-hunt sweep (item R3-11).
Summary
The Pelorus side-data pack/parse code (
interop.c, vendored into vmafx ascore/src/interop/pelorus_interop.cper ADR-1113) computes section-payloadpointers as
blob_base + padded_offsetand then casts the resultingconst uint8_t *to the concrete section struct type before reading fields.The framing comment documents that payload starts are padded up to 8 bytes
"so a consumer can cast the returned pointer to the section struct without an
unaligned access" — but that guarantee only holds relative to the blob base.
If a caller hands the parser a blob whose base address is not 8-byte aligned,
every
base + offsetsection pointer inherits the base's misalignment, and thesubsequent struct-field reads are undefined behavior (unaligned access). On
strict-alignment targets (some aarch64 configs, UBSan
-fsanitize=alignment)this is a real fault, not just a theoretical one.
Impact
Low in practice for the current vmafx consumer:
perceptual_weight.calreadymemcpys section bytes into a local aligned struct rather than casting, sovmafx is only exposed if a caller passes a misaligned blob straight to the
parser. But the parser is the canonical reference and should not depend on an
undocumented "callers must pass an 8-byte-aligned blob" precondition.
Suggested fix (either)
field via
memcpyinto a properly-aligned local struct instead of casting theblob pointer. This removes the precondition entirely and matches what
perceptual_weight.calready does. (Preferred — robust, and the cost isnegligible for these small fixed structs.)
be
alignof(max_align_t)-aligned and assert it at parse entry, so misusefails loudly instead of silently invoking UB.
Why filed upstream
The vmafx copy is a read-only vendored mirror (ADR-1113 +
scripts/sync-pelorus-interop.shdrift guard); the fix must land here in
VMAFx/pelorusand then be re-vendored.Found during the vmafx 2026-06-27 bug-hunt sweep (item R3-11).