You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

Apache ORC C++ RLEv2 patch-list heap-buffer-overflow PoC

Tested against Apache ORC commit:

af4cbf36b051c176f0d13ae5a7ac436ada8aeccf

Summary

Apache ORC's C++ RLEv2 decoder accepts a PATCHED_BASE patch-list entry that means “continue the gap in the next entry” even when that entry is the last element of the attacker-controlled patch list.

RleDecoderV2::adjustGapAndPatch() increments the patch index and immediately dereferences it without checking the vector length. A one-entry patch list whose entry encodes gap == 255 && patch == 0 therefore causes an eight-byte heap-buffer-overflow read.

The complete 277-byte .orc trigger reaches the flaw through the public createReader() / RowReader::next() path. The corresponding control differs in one patch-gap byte and parses one row normally.

Reproduce

Build prerequisites are the same as Apache ORC C++. Then run:

ORC_SRC=/path/to/orc bash reproduce.sh

The script builds current ORC with AddressSanitizer and UndefinedBehaviorSanitizer, tests the raw decoder control/trigger, and then tests the complete ORC control/trigger.

Expected complete-file control:

rows=1

Expected complete-file trigger:

ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 8
RleDecoderV2.cc:265 in orc::RleDecoderV2::adjustGapAndPatch(...)
RleDecoderV2.cc:346 in orc::RleDecoderV2::nextPatched<long long>(...)
ColumnReader.cc:966 in orc::ListColumnReader::nextInternal<false>(...)
Reader.cc in orc::RowReaderImpl::next(...)

Fixture integrity

098d1f9d7b64afa2cc15c257b4e8d5b57707f19402dd241ef7b8b26ffb94224d  control-valid-patch-list.orc
9fbbd8fdc5c991f55fede3823193f439e1843146d6f5d44e0e4f7ca80859fba2  trigger-unterminated-gap-continuation.orc

The two generated ORC files are identical except for byte offset 53:

  • control: patch-list bits decode to gap == 1
  • trigger: patch-list bits decode to gap == 255 && patch == 0

Both files have internally consistent stream and stripe lengths.

Root cause

At c++/src/RleDecoderV2.cc:253-266:

uint64_t idx = *patchIdx;
uint64_t gap =
    static_cast<uint64_t>(unpackedPatch_[idx]) >> patchBitSize;
int64_t patch = unpackedPatch_[idx] & patchMask;

while (gap == 255 && patch == 0) {
  actualGap += 255;
  ++idx;
  gap = static_cast<uint64_t>(unpackedPatch_[idx]) >> patchBitSize;
  patch = unpackedPatch_[idx] & patchMask;
}

The loop does not check idx < unpackedPatch_.size() after incrementing it.

Prior-art distinction

Fresh searches of Apache ORC issues and pull requests for adjustGapAndPatch, PATCHED_BASE patch-list corruption, gap == 255, and RLEv2 heap-buffer-overflow returned no matching disclosure.

ORC-2214 hardens the compressed input cursor in readByte(). It does not validate the decoded patch-list index and does not prevent this heap read.

Suggested fix

Pass the patch-list length into adjustGapAndPatch() and reject an unterminated gap-continuation entry before the next dereference:

++idx;
if (idx >= unpackedPatch_.size()) {
  throw ParseError("Corrupt PATCHED_BASE patch list");
}

Add a regression test for a one-entry list ending in gap == 255 && patch == 0.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support