[ 
https://issues.apache.org/jira/browse/AVRO-4283?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Ismaël Mejía reassigned AVRO-4283:
----------------------------------

    Assignee: Ismaël Mejía

> Enforce a maximum decompressed block size across language SDKs
> --------------------------------------------------------------
>
>                 Key: AVRO-4283
>                 URL: https://issues.apache.org/jira/browse/AVRO-4283
>             Project: Apache Avro
>          Issue Type: Improvement
>          Components: c, c++, csharp, javascript, perl, php, python, ruby
>    Affects Versions: 1.11.5, 1.12.1
>            Reporter: Ismaël Mejía
>            Assignee: Ismaël Mejía
>            Priority: Major
>             Fix For: 1.12.2
>
>
> When reading an Avro container (data) file, each block is decompressed 
> according to the file's codec (deflate, bzip2, snappy, xz, zstandard). 
> Several SDKs read the compressed block into memory and decompress into an 
> output buffer that grows (or is sized from an attacker-declared length) 
> without any upper bound. A block with a very high compression ratio can 
> therefore expand to an amount of memory far larger than the input, leading to 
> excessive allocation on malformed or hostile input.
> The Java SDK addressed this in AVRO-4247 by enforcing a maximum decompressed 
> size in every codec, defaulting to 200MB and configurable via 
> {{org.apache.avro.limits.decompress.maxLength}}. This umbrella tracks 
> bringing the C, C++, C#, JavaScript, Perl, PHP, Python, and Ruby SDKs in line 
> with that behavior so all SDKs bound decompression output consistently.
> h3. Proposed approach
> * Enforce a configurable maximum decompressed size while 
> inflating/decompressing each data-file block, across all codecs.
> * Reject a block whose decompressed output would exceed the limit with a 
> clear error instead of continuing to allocate.
> * Default the limit to a runtime-safe value; allow it to be tuned per SDK 
> (mirroring the Java property).
> * Add regression tests: a block that decompresses to more than the limit must 
> fail with a bounded, well-defined error rather than exhausting memory.
> An audit of the current decompression paths (for reference in the subtasks):
> * C: {{lang/c/src/codec.c}} (deflate doubles the output buffer; snappy 
> allocates the attacker-declared uncompressed length; lzma doubles), driven 
> from {{lang/c/src/datafile.c}}.
> * C++: {{lang/c++/impl/DataFile.cc}} (deflate/snappy) and 
> {{lang/c++/impl/ZstdDecompressWrapper.cc}} (zstd trusts the frame content 
> size). The existing {{BoundedInputStream}} bounds only the compressed input.
> * C#: {{lang/csharp/src/apache/main/File/DataFileReader.cs}} and the codec 
> classes (deflate/snappy/zstandard/bzip2/xz), all via {{Stream.CopyTo}} into 
> an unbounded {{MemoryStream}}.
> * JavaScript: {{lang/js/lib/files.js}} (deflate via {{zlib.inflateRaw}} with 
> no {{maxOutputLength}}).
> * Perl: {{lang/perl/lib/Avro/DataFileReader.pm}} (a {{block_max_size}} 
> attribute exists but is never enforced).
> * PHP: {{lang/php/lib/DataFile/AvroDataIOReader.php}} 
> (deflate/zstandard/snappy/bzip2).
> * Python: {{lang/py/avro/codecs.py}} (deflate/bzip2/snappy/zstandard).
> * Ruby: {{lang/ruby/lib/avro/data_file.rb}} (deflate/snappy/zstandard).
> Subtasks: one per SDK (below).



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

Reply via email to