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

Ismaël Mejía updated AVRO-4276:
-------------------------------
    Description: 
BinaryDecoder::doDecodeItemCount() in lang/c++/impl/BinaryDecoder.cc does not 
reject INT64_MIN as a block count. While the -(result + 1) + 1 idiom (added in 
AVRO-4228) correctly avoids undefined behavior during negation, it converts 
INT64_MIN to 2^63 as the item count. Callers such as Generic.cc then attempt 
vector::resize(2^63), which will throw std::bad_alloc since no system can 
allocate that much memory.

The zigzag encoding of INT64_MIN is a valid 10-byte varint (FF FF FF FF FF FF 
FF FF FF 01), so the decoder can encounter this value when reading malformed or 
corrupted data. Rather than propagating an impossibly large count that 
inevitably fails downstream, the decoder should reject it early with a clear 
error.

The C binding already rejects INT64_MIN explicitly (AVRO-4275). The C++ binding 
should do the same for consistency and robustness.

Fix: Guard against INT64_MIN before negation in doDecodeItemCount(), and 
simplify the negation to -result (safe once INT64_MIN is excluded).

  was:
BinaryDecoder::doDecodeItemCount() in lang/c++/impl/BinaryDecoder.cc does not 
reject INT64_MIN as a block count. While the -(result + 1) + 1 idiom (added in 
AVRO-4228) avoids undefined behavior, it silently converts INT64_MIN to 2^63 as 
the item count. Callers such as Generic.cc then attempt vector::resize(2^63), 
triggering std::bad_alloc and crashing the process.

An attacker can craft a 10-byte varint (FF FF FF FF FF FF FF FF FF 01, zigzag 
encoding of INT64_MIN) as an array or map block count to trigger this denial of 
service.

The C binding already rejects INT64_MIN explicitly (AVRO-4275). The C++ binding 
should do the same.

Fix: Guard against INT64_MIN before negation in doDecodeItemCount(), and 
simplify the negation to -result (safe once INT64_MIN is excluded).

        Summary: [C++] BinaryDecoder::doDecodeItemCount() should reject 
INT64_MIN block count  (was: [C++] BinaryDecoder::doDecodeItemCount() missing 
INT64_MIN rejection allows DoS via crafted block count)

> [C++] BinaryDecoder::doDecodeItemCount() should reject INT64_MIN block count
> ----------------------------------------------------------------------------
>
>                 Key: AVRO-4276
>                 URL: https://issues.apache.org/jira/browse/AVRO-4276
>             Project: Apache Avro
>          Issue Type: Bug
>          Components: c++
>            Reporter: Ismaël Mejía
>            Priority: Major
>
> BinaryDecoder::doDecodeItemCount() in lang/c++/impl/BinaryDecoder.cc does not 
> reject INT64_MIN as a block count. While the -(result + 1) + 1 idiom (added 
> in AVRO-4228) correctly avoids undefined behavior during negation, it 
> converts INT64_MIN to 2^63 as the item count. Callers such as Generic.cc then 
> attempt vector::resize(2^63), which will throw std::bad_alloc since no system 
> can allocate that much memory.
> The zigzag encoding of INT64_MIN is a valid 10-byte varint (FF FF FF FF FF FF 
> FF FF FF 01), so the decoder can encounter this value when reading malformed 
> or corrupted data. Rather than propagating an impossibly large count that 
> inevitably fails downstream, the decoder should reject it early with a clear 
> error.
> The C binding already rejects INT64_MIN explicitly (AVRO-4275). The C++ 
> binding should do the same for consistency and robustness.
> Fix: Guard against INT64_MIN before negation in doDecodeItemCount(), and 
> simplify the negation to -result (safe once INT64_MIN is excluded).



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

Reply via email to