From 454d4848e158f6ff0affd8dfdefd0b4396a02cc3 Mon Sep 17 00:00:00 2001 From: Dmitry Spikhalsky Date: Wed, 21 Oct 2026 12:16:09 -0400 Subject: [PATCH] GH-54916: [C++][IPC] Align metadata in Message::Open Message::Open() verified and read the Flatbuffers metadata in place, so metadata starting at an address that is not 8-byte aligned (for example a Flight data_header sliced zero-copy out of a gRPC message) caused misaligned loads in Flatbuffers. Copy such metadata with the existing MaybeAlignMetadata(), as MessageDecoder already does. --- cpp/src/arrow/ipc/message.cc | 1 + cpp/src/arrow/ipc/read_write_test.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/cpp/src/arrow/ipc/message.cc b/cpp/src/arrow/ipc/message.cc index 4123a6b17355..38780d7572c7 100644 --- a/cpp/src/arrow/ipc/message.cc +++ b/cpp/src/arrow/ipc/message.cc @@ -87,6 +87,7 @@ class Message::MessageImpl { : metadata_(std::move(metadata)), message_(nullptr), body_(std::move(body)) {} Status Open() { + RETURN_NOT_OK(MaybeAlignMetadata(&metadata_)); RETURN_NOT_OK( internal::VerifyMessage(metadata_->data(), metadata_->size(), &message_)); diff --git a/cpp/src/arrow/ipc/read_write_test.cc b/cpp/src/arrow/ipc/read_write_test.cc index cfa6a541d5cc..51530c2bc8e3 100644 --- a/cpp/src/arrow/ipc/read_write_test.cc +++ b/cpp/src/arrow/ipc/read_write_test.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -224,6 +225,31 @@ TEST(TestMessage, Verify) { ASSERT_FALSE(message.Verify()); } +TEST(TestMessage, OpenUnalignedMetadata) { + auto custom_metadata = key_value_metadata({"foo"}, {"bar"}); + ASSERT_OK_AND_ASSIGN( + auto serialized, + internal::WriteRecordBatchMessage( + /*length=*/0, /*body_length=*/0, custom_metadata, + /*nodes=*/{}, + /*buffers=*/{}, /*variadic_counts=*/{}, IpcWriteOptions::Defaults())); + + // Place the metadata at an odd address, as when it is sliced out of a larger + // buffer (e.g. a Flight data_header) + ASSERT_OK_AND_ASSIGN(std::shared_ptr storage, + AllocateBuffer(serialized->size() + 1)); + std::memcpy(storage->mutable_data() + 1, serialized->data(), serialized->size()); + auto unaligned = SliceBuffer(storage, 1, serialized->size()); + ASSERT_NE(0, reinterpret_cast(unaligned->data()) % 8); + + ASSERT_OK_AND_ASSIGN(auto message, Message::Open(unaligned, /*body=*/nullptr)); + ASSERT_EQ(0, reinterpret_cast(message->metadata()->data()) % 8); + ASSERT_TRUE(message->metadata()->Equals(*serialized)); + ASSERT_EQ(MessageType::RECORD_BATCH, message->type()); + ASSERT_EQ(0, message->body_length()); + ASSERT_TRUE(message->custom_metadata()->Equals(*custom_metadata)); +} + INSTANTIATE_TEST_SUITE_P(TestMessage, TestMessage, ::testing::ValuesIn(kMetadataVersions));