[
https://issues.apache.org/jira/browse/AVRO-4295?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18102841#comment-18102841
]
ASF subversion and git services commented on AVRO-4295:
-------------------------------------------------------
Commit d200b5f073738188d66738b5a42cc31389682321 in avro's branch
refs/heads/AVRO-4295-csharp-available-bytes from Ismaël Mejía
[ https://gitbox.apache.org/repos/asf?p=avro.git;h=d200b5f073 ]
AVRO-4295: [csharp] Cap zero-byte collection element allocation
Completes the available-bytes protection for collections. Elements whose schema
encodes to zero bytes (null, a zero-length fixed, or a record with only
zero-byte fields) consume no input, so the bytes-remaining check cannot bound
their count. A tiny payload declaring a huge array block count of such elements
(e.g. {"type":"array","items":"null"} with a count of 200,000,000) therefore
drove an unbounded ResizeArray and exhausted memory.
EnsureCollectionAvailable now tracks the cumulative count across blocks and
enforces, per block: a structural cap on all collections
(MaxCollectionStructural = Integer.MAX_VALUE - 8, also covering non-seekable
decoders and keeping the total within the int range the callers cast to); a
zero-byte item cap (MaxCollectionItems = 10,000,000) when the per-element
minimum is zero; and the existing bytes-remaining check otherwise.
AVRO_MAX_COLLECTION_ITEMS, when set, caps both. The reader array/map loops and
the schema-resolution Skip path for arrays and maps are all bounded the same
way, so skipping a huge zero-byte block cannot loop unboundedly.
Assisted-by: GitHub Copilot:claude-opus-4.8
> [csharp] Bound allocation when decoding length-prefixed values and collections
> ------------------------------------------------------------------------------
>
> Key: AVRO-4295
> URL: https://issues.apache.org/jira/browse/AVRO-4295
> Project: Apache Avro
> Issue Type: Sub-task
> Components: csharp
> Affects Versions: 1.11.5, 1.12.1
> Reporter: Ismaël Mejía
> Assignee: Ismaël Mejía
> Priority: Major
> Labels: pull-request-available
> Time Spent: 6h
> 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.RemainingBytes() reports the bytes still readable for a
> seekable stream; ReadBytes/ReadString consult it directly
> (EnsureAvailableBytes), while DefaultReader.ReadArray/ReadMap consult it via
> MinBytesPerElement(). EnsureCollectionAvailable tracks the cumulative count
> and enforces the limits, and the schema-resolution Skip path for arrays and
> maps is bounded the same way. Negative and out-of-range counts are rejected
> before the int cast.
> Zero-byte elements (null, 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 (int.MaxValue - 8,
> further clamped to the runtime's maximum array length) 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 message was sent by Atlassian Jira
(v8.20.10#820010)