Ismaël Mejía created AVRO-4303:
----------------------------------

             Summary: Bound bytes/string allocation from length prefix on 
non-seekable streams
                 Key: AVRO-4303
                 URL: https://issues.apache.org/jira/browse/AVRO-4303
             Project: Apache Avro
          Issue Type: Improvement
          Components: csharp, javascript, perl, c, php, ruby, c++, java, python
            Reporter: Ismaël Mejía
            Assignee: Ismaël Mejía


h2. Summary

The "available bytes" guard added under AVRO-4292 rejects a declared {{bytes}}/
{{string}} length that exceeds the data actually remaining -- but *only when the
decoder can report the number of bytes remaining* (memory-backed or seekable
sources). On a *non-seekable stream* (socket, pipe, a decompression stream,
etc.) the check is a no-op, so a huge declared length still drives a single
large up-front allocation ({{new byte[len]}}) before any payload is read. A tiny
truncated input can therefore force a multi-hundred-MB (up to the max-length
limit) allocation.

h2. Details

For example, in the Java SDK {{BinaryDecoder.remainingBytes()}} returns {{-1}}
for any source other than {{ByteArrayInputStream}}/{{ByteBufferInputStream}}, so
{{ensureAvailableBytes()}} does nothing for the common streaming case; the C#
{{BinaryDecoder.RemainingBytes()}} likewise returns {{-1}} when
{{!stream.CanSeek}}. The C, C++ and Python stream decoders have the same
blind spot.

h2. Proposed approach

* When the remaining byte count is *unknown* (non-seekable stream), read the
  {{bytes}}/{{string}} value into a *growing buffer in bounded chunks* rather
  than allocating the full attacker-declared length up front. A truncated or
  hostile stream then fails after a bounded allocation (at EOF) instead of
  attempting one huge allocation. This mirrors the collection preallocation
  clamp already applied for arrays/maps.
* Keep the existing single-allocation fast path when the remaining byte count
  *is* known (the available-bytes check already bounds it there).
* Apply consistently across the SDKs that allocate a buffer sized from a length
  prefix.

h2. Relationship

* AVRO-4292 -- collection/allocation limits ("available bytes"). This issue is
  the residual protection for the streaming case that the available-bytes check
  cannot cover, and re-touches the same decoder read paths, so it is best landed
  after the current AVRO-4292 SDK PRs merge.

Recommend an umbrella with one subtask per affected SDK.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to