Skip to content

AVRO-4343: [perl] Fix broken decoder skip path used in schema resolution - #3947

Open
iemejia wants to merge 1 commit into
apache:mainfrom
iemejia:AVRO-4343-perl-skip-fix
Open

AVRO-4343: [perl] Fix broken decoder skip path used in schema resolution#3947
iemejia wants to merge 1 commit into
apache:mainfrom
iemejia:AVRO-4343-perl-skip-fix

Conversation

@iemejia

@iemejia iemejia commented Aug 22, 2026

Copy link
Copy Markdown
Member

What

Fixes the Perl BinaryDecoder skip path, which is exercised during schema resolution whenever the writer's record contains a field that is absent from the reader's schema (decode_recordskip). Three related defects, present since the initial Perl implementation (AVRO-974):

  1. Absolute seek → silent data corruption. skip_bytes/skip_string/skip_fixed did $reader->seek($size, 0) — whence 0 is SEEK_SET (absolute) rather than SEEK_CUR. Skipping a bytes/string/fixed field repositioned the reader to absolute offset $size, corrupting every subsequent field. (Masked in the existing test only because its skipped field was the last one.)
  2. Crash when skipping an array/map field. skip_array/skip_map invoked skip_block(...) as a plain sub, so shifting $class misaligned $reader and the content callback, dying with "Can't call method "read" on unblessed reference".
  3. Broken negative-block-count handling. skip_block seeked to a negative absolute offset and re-looped via next without re-reading the block count.

Fix

  • Use relative (SEEK_CUR) skips in skip_bytes/skip_string/skip_fixed.
  • Reject negative bytes lengths and negative block sizes with Avro::Schema::Error::Parse.
  • Invoke skip_block as a method ($class->skip_block), fixing the argument alignment.
  • Handle negative block counts the same way as decode_array/decode_map: take the absolute value and consume the following block-size long.

Tests

Adds regression tests to t/03_bin_decode.t covering resolution that skips: a non-trailing bytes field, an array field, a map field, an array encoded with a negative block count, and rejection of a negative bytes length. Full existing Perl suite still passes (the pre-existing 04_datafile.t failure is unrelated — a missing IO::Compress dependency).

JIRA: https://issues.apache.org/jira/browse/AVRO-4343

The BinaryDecoder skip path (reached when the writer's record has a field
absent from the reader's schema) was broken:

- skip_bytes/skip_string/skip_fixed used seek($n, 0) (SEEK_SET, absolute)
  instead of SEEK_CUR, repositioning the reader to an absolute offset and
  silently corrupting every subsequent field.
- skip_array/skip_map called skip_block(...) as a plain sub, misaligning
  $class/$reader/the callback, so skipping an array or map field crashed
  ("Can't call method read on unblessed reference"). The negative-block-count
  branch also seeked to a negative absolute offset and re-looped without
  re-reading the count.

Fix: use relative (SEEK_CUR) skips, reject negative bytes/block sizes, invoke
skip_block as a method, and handle negative block counts like decode_array/
decode_map (abs count + consume block size). Adds regression tests for skipping
non-trailing bytes, arrays, maps, negative-block-count arrays, and rejecting a
negative length.
@github-actions github-actions Bot added the Perl label Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant