You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@orc.apache.org by do...@apache.org on 2026/07/08 23:14:13 UTC
(orc) branch main updated: ORC-2196: [C++] Validate type tree when creating reader from serialized file tail
This is an automated email from the ASF dual-hosted git repository.
dongjoon-hyun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/orc.git
The following commit(s) were added to refs/heads/main by this push:
new 11f07f665 ORC-2196: [C++] Validate type tree when creating reader from serialized file tail
11f07f665 is described below
commit 11f07f665eaf64e9c85c60870813096e4fb7effc
Author: Dongjoon Hyun <do...@apache.org>
AuthorDate: Wed Jul 8 16:14:06 2026 -0700
ORC-2196: [C++] Validate type tree when creating reader from serialized file tail
### What changes were proposed in this pull request?
This PR aims to validate the ORC type tree in `createReader` when the footer comes from a serialized file tail (`ReaderOptions.setSerializedFileTail`), by calling the existing `checkProtoTypes` in the same way as the file-read path.
### Why are the changes needed?
The serialized-file-tail branch of `createReader` builds `contents->footer` directly from the parsed `proto::FileTail` without validation. A malformed footer with an out-of-range or back-referencing subtype flows into `convertType`, causing an out-of-bounds read or unbounded recursion (stack overflow) in release builds.
The file-read path already validates via `checkProtoTypes`, and the Java reader validates both tail paths (`OrcTail` and `ReaderImpl`). This closes the remaining C++ parity gap.
### How was this patch tested?
Pass the CIs with a newly added test case.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Fable 5
Closes #2679 from dongjoon-hyun/ORC-2196.
Authored-by: Dongjoon Hyun <do...@apache.org>
Signed-off-by: Dongjoon Hyun <do...@apache.org>
---
c++/src/Reader.cc | 1 +
c++/test/TestReader.cc | 29 +++++++++++++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/c++/src/Reader.cc b/c++/src/Reader.cc
index 68a277fc0..c409576cc 100644
--- a/c++/src/Reader.cc
+++ b/c++/src/Reader.cc
@@ -1646,6 +1646,7 @@ namespace orc {
}
contents->postscript = std::make_unique<proto::PostScript>(tail.postscript());
contents->footer = std::make_unique<proto::Footer>(tail.footer());
+ checkProtoTypes(*contents->footer);
fileLength = tail.file_length();
postscriptLength = tail.postscript_length();
} else {
diff --git a/c++/test/TestReader.cc b/c++/test/TestReader.cc
index fab981339..ee4762a87 100644
--- a/c++/test/TestReader.cc
+++ b/c++/test/TestReader.cc
@@ -1424,4 +1424,33 @@ namespace orc {
"Invalid compression block size: 8388608");
}
+ /**
+ * Test that createReader validates the type tree when the footer comes
+ * from a serialized file tail, matching the file-read path (ORC-317).
+ */
+ TEST(TestReader, testSerializedFileTailInvalidTypes) {
+ proto::FileTail tail;
+ proto::PostScript* ps = tail.mutable_postscript();
+ ps->set_footer_length(0);
+ ps->set_compression(proto::NONE);
+ ps->set_magic("ORC");
+ proto::Footer* footer = tail.mutable_footer();
+ // Root STRUCT with a subtype that points back to itself (type 0),
+ // which would cause unbounded recursion in convertType if unchecked.
+ proto::Type* rootType = footer->add_types();
+ rootType->set_kind(proto::Type_Kind_STRUCT);
+ rootType->add_subtypes(0);
+ rootType->add_field_names("f1");
+ tail.set_file_length(0);
+ tail.set_postscript_length(0);
+
+ std::string serializedTail;
+ ASSERT_TRUE(tail.SerializeToString(&serializedTail));
+
+ ReaderOptions options;
+ options.setSerializedFileTail(serializedTail);
+ auto stream = std::make_unique<MemoryInputStream>(nullptr, 0);
+ EXPECT_THROW(createReader(std::move(stream), options), ParseError);
+ }
+
} // namespace orc