[
https://issues.apache.org/jira/browse/AVRO-4296?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18102761#comment-18102761
]
ASF subversion and git services commented on AVRO-4296:
-------------------------------------------------------
Commit e39580d436ce4073796f448b389b46536288475b in avro's branch
refs/heads/branch-1.12 from Ismaël Mejía
[ https://gitbox.apache.org/repos/asf?p=avro.git;h=e39580d436 ]
AVRO-4296: [python] Bound zero-byte collection elements per datum, not per
collection (#3926)
The AVRO-4296 zero-byte-element cap (null, zero-length fixed, all-zero-byte
records) was enforced per collection: read_array/read_map each started counting
from zero. Because a container file carries its own schema, an attacker can
declare a record with many array<null> fields, each block individually under the
limit but jointly unbounded, so a tiny payload still drives a huge allocation
(e.g. 16 array<null> fields of ~10M each: an ~80 byte record that exhausts
memory, or 8 fields that burn tens of seconds of CPU).
Track the cumulative zero-byte element count on the DatumReader across a single
decoded datum, reset at the start of each top-level read() (the boundary
DataFileReader uses per record), and check it in _ensure_collection_available.
Positive-size elements are unchanged: they are naturally bounded per collection
because decoding consumes input and the bytes-remaining check shrinks as the
position advances.
Adds regression tests for a multi-field record that exceeds the cap in aggregate
and for a within-limit record that still reads (and confirms the budget resets
between datums).
> [python] Bound allocation when decoding length-prefixed values and collections
> ------------------------------------------------------------------------------
>
> Key: AVRO-4296
> URL: https://issues.apache.org/jira/browse/AVRO-4296
> Project: Apache Avro
> Issue Type: Sub-task
> Components: python
> Affects Versions: 1.11.5, 1.12.1
> Reporter: Ismaël Mejía
> Assignee: Ismaël Mejía
> Priority: Major
> Labels: pull-request-available
> Fix For: 1.12.2
>
> Time Spent: 10.5h
> Remaining Estimate: 0h
>
> A bytes or string value is encoded as a length prefix followed by that many
> bytes of data, and an array or map block is encoded as an element count
> followed by that many items. A malicious or truncated input can declare a
> very large length or count while carrying little or no actual data, causing a
> large allocation before the shortfall is noticed. When the source can report
> how many bytes remain, reject a declared length (or a collection block count)
> that exceeds the bytes actually available before allocating for it. Companion
> to AVRO-4241 (Java).
> BinaryDecoder.bytes_remaining() backs the check; read() consults
> bytes_remaining() directly for a declared length above a threshold, while
> DatumReader.read_array/read_map/skip_array/skip_map consult it via
> min_bytes_per_element(). _ensure_collection_available enforces the per-block
> limits (cumulative across blocks and after normalizing a negative block
> count); maps are additionally bounded by their >=1-byte keys. Rejections
> raise the new AvroCollectionSizeException.
> Zero-byte elements (null, a zero-length fixed, or a record with only
> zero-byte fields) consume no input, so the available-bytes check cannot bound
> their count: a tiny payload such as {"type":"array","items":"null"} declaring
> a block count of 200,000,000 would otherwise drive an unbounded allocation.
> In addition to the available-bytes check this therefore caps the cumulative
> count of zero-byte elements (default 10,000,000), applies a structural cap
> (Integer.MAX_VALUE - 8) to every non-zero-byte-element collection (which also
> covers collections read from a source that cannot report the bytes
> remaining), and bounds the array/map skip paths. When set, the
> AVRO_MAX_COLLECTION_ITEMS environment variable caps both limits. This
> supersedes the separate collection-limit sub-task.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)