Skip to content

Commit e20bcc0

Browse files
committed
ORC-2190: Reject compressed chunk length exceeding block size in ORC C++ reader
1 parent 3b3f227 commit e20bcc0

2 files changed

Lines changed: 23 additions & 0 deletions

File tree

c++/src/Compression.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,9 @@ namespace orc {
419419
MemoryPool& pool;
420420
std::unique_ptr<SeekableInputStream> input;
421421

422+
// the configured compression block size, used to validate chunk lengths
423+
size_t blockSize;
424+
422425
// uncompressed output
423426
DataBuffer<char> outputDataBuffer;
424427

@@ -460,6 +463,7 @@ namespace orc {
460463
ReaderMetrics* metrics)
461464
: pool(pool),
462465
input(std::move(inStream)),
466+
blockSize(bufferSize),
463467
outputDataBuffer(pool, bufferSize),
464468
state(DECOMPRESS_HEADER),
465469
outputBufferStart(nullptr),
@@ -518,6 +522,12 @@ namespace orc {
518522
state = DECOMPRESS_START;
519523
}
520524
remainingLength = header >> 1;
525+
if (state == DECOMPRESS_START && remainingLength > blockSize) {
526+
std::ostringstream ss;
527+
ss << "Buffer size too small. size = " << blockSize << " needed = " << remainingLength
528+
<< " in " << getName();
529+
throw ParseError(ss.str());
530+
}
521531
} else {
522532
remainingLength = 0;
523533
}

c++/test/TestDecompression.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,19 @@ namespace orc {
574574
EXPECT_EQ(16, static_cast<const char*>(ptr)[2]);
575575
}
576576

577+
TEST(Zlib, testChunkLengthExceedsBlockSize) {
578+
// Craft a compressed chunk header whose chunkLength (100) exceeds the
579+
// configured block size (5). header = chunkLength << 1 = 200 = 0xC8.
580+
const unsigned char buffer[] = {0xc8, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5};
581+
std::unique_ptr<SeekableInputStream> result = createDecompressor(
582+
CompressionKind_ZLIB,
583+
std::make_unique<SeekableArrayInputStream>(buffer, ARRAY_SIZE(buffer), 5), 5,
584+
*getDefaultPool(), getDefaultReaderMetrics());
585+
const void* ptr;
586+
int length;
587+
EXPECT_THROW(result->Next(&ptr, &length), ParseError);
588+
}
589+
577590
TEST(Zlib, testInflate) {
578591
const unsigned char buffer[] = {0xe, 0x0, 0x0, 0x63, 0x60, 0x64, 0x62, 0xc0, 0x8d, 0x0};
579592
std::unique_ptr<SeekableInputStream> result =

0 commit comments

Comments
 (0)