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 stripe stream column-id heap-buffer-overflow

Status: reproduced on current main; prior-art gate open.

Apache ORC's public C++ Reader::getStripeStatistics() path trusts the attacker-controlled column id of every ROW_INDEX stream in a stripe footer. It uses that id with unchecked std::vector::operator[], then calls push_back() through the out-of-bounds vector object.

A 272-byte ORC file with three valid columns and one mutated stream column id reliably produces an AddressSanitizer heap-buffer-overflow. The control differs by one byte and exits normally.

Tested at Apache ORC commit af4cbf36b051c176f0d13ae5a7ac436ada8aeccf (2026-07-29).

Root cause

ReaderImpl::getStripeStatistics() sizes indexStats from the number of column-statistics entries:

size_t num_cols = contents_->metadata->stripe_stats(stripeIndex).col_stats_size();
std::vector<std::vector<proto::ColumnStatistics>> indexStats(num_cols);
getRowIndexStatistics(..., &indexStats);

getRowIndexStatistics() then trusts stream.column() without checking it against indexStats->size():

size_t column = static_cast<size_t>(stream.column());
for (int j = 0; j < num_entries; j++) {
  const proto::RowIndexEntry& entry = rowIndex.entry(j);
  (*indexStats)[column].push_back(entry.statistics());
}

The same attacker-controlled field is also used without bounds checks in extractReadRangesForStripe() and RowReaderImpl::loadStripeIndex():

selectedColumns[stream.column()]
selectedColumns_[colId]

Differential proof

Fixture Third ROW_INDEX stream column Result
control-valid-column.orc 2 Prints all statistics; exit 0
trigger-column-3.orc 3 ASan heap-buffer-overflow; abort

Both fixtures are 272 bytes. They differ at byte 74 only. Column 3 is exactly one past the three valid columns 0, 1, and 2.

AddressSanitizer reports an 8-byte read eight bytes after the 72-byte vector<vector<ColumnStatistics>> allocation. The stack reaches Reader.cc:834 through the official orc-statistics --withIndex tool. Controls exited 0 and triggers aborted in three of three runs.

Reproduce

Build current Apache ORC with explicit sanitizer flags:

cmake -S orc -B orc-sanitized \
  -DCMAKE_BUILD_TYPE=Debug \
  -DBUILD_JAVA=OFF \
  -DBUILD_CPP_TESTS=OFF \
  -DBUILD_TOOLS=ON \
  -DCMAKE_C_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer" \
  -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer" \
  -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined"
cmake --build orc-sanitized --target orc-statistics --parallel 4

Then:

ORC_STATISTICS=/path/to/orc-sanitized/tools/src/orc-statistics ./reproduce.sh

generate_fixture.py materializes both deterministic files and asserts their SHA-256 hashes.

Impact

An application or service that extracts row-index statistics from an untrusted ORC file can be crashed by a one-byte column-id mutation. This is a native out-of-bounds access in a file parser, not allocation pressure.

The adjacent ordinary row-reader paths trust the same field, broadening the set of potentially affected consumers.

Demonstrated impact: deterministic denial of service and native heap out-of-bounds access. No code-execution claim is made.

Suggested remediation

Before every use of a stripe stream's column id:

  • reject stream.column() >= indexStats->size() in getRowIndexStatistics();
  • reject stream.column() >= selectedColumns.size() in extractReadRangesForStripe();
  • reject colId >= selectedColumns_.size() and validate the parallel currentStripeFooter_.columns() lookup in loadStripeIndex().

Return ParseError for malformed stripe metadata and add regression fixtures for column == size, very large column ids, and missing column fields.

Novelty

The exact scan found no Hugging Face or local matches. Apache ORC issue #1475 concerns writer stream ordering, PR #2144 introduced the row-index statistics API, and ORC-2198/ORC-2200 validate byte extents. None reports or fixes attacker-controlled stripe stream column ids indexing these vectors.

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