From d3ec4b63c9f5fd6858580f8d19e41eaaaccf9fd7 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Wed, 16 Nov 2022 12:21:33 -0800 Subject: [PATCH] Add Parse/Serialize templates to support shared_ptr/unique_ptr. Fix UBSAN in _upb_Message_Clear due to unsigned UPB_PTR_AT PiperOrigin-RevId: 489007182 --- .github/workflows/python_tests.yml | 3 +- bazel/workspace_deps.bzl | 2 +- protos/protos.h | 37 ++++++++++++++++++- protos_generator/tests/test_generated.cc | 14 +++++++ .../pb_unit_tests/reflection_test_wrapper.py | 3 ++ upb/msg.c | 2 +- 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml index 2f38aea054..49a310ed9f 100644 --- a/.github/workflows/python_tests.yml +++ b/.github/workflows/python_tests.yml @@ -15,8 +15,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.pull_request.head.repo.full_name == 'protocolbuffers/upb' }} env: - DOCKER_IMAGE: gcr.io/protobuf-build/bazel/linux@sha256:2bfd061284eff8234f2fcca16d71d43c69ccf3a22206628b54c204a6a9aac277 - BAZEL_CACHE: --remote_cache=https://storage.googleapis.com/protobuf-bazel-cache/upb --google_default_credentials + DOCKER_IMAGE: gcr.io/protobuf-build/bazel/linux@sha256:9dba7773926bb6dce839de098948055c9e80260d7470a7fefb94b6a4fed363ba steps: - uses: actions/checkout@v2 diff --git a/bazel/workspace_deps.bzl b/bazel/workspace_deps.bzl index bfe1ea5cbc..2e78baf782 100644 --- a/bazel/workspace_deps.bzl +++ b/bazel/workspace_deps.bzl @@ -24,7 +24,7 @@ def upb_deps(): _github_archive, name = "com_google_protobuf", repo = "https://github.com/protocolbuffers/protobuf", - commit = "d938afd6e35676f6b8c8012d9eacd1dc0bb693b4", + commit = "c79832bddc3931d798d31d417238e4377f869c79", patches = ["@upb//bazel:protobuf.patch"], ) diff --git a/protos/protos.h b/protos/protos.h index 6f1ade4d92..63c72ffd46 100644 --- a/protos/protos.h +++ b/protos/protos.h @@ -358,6 +358,24 @@ bool Parse(T& message, absl::string_view bytes) { arena) == kUpb_DecodeStatus_Ok; } +template +bool Parse(std::unique_ptr& message, absl::string_view bytes) { + _upb_Message_Clear(message->msg(), T::minitable()); + auto* arena = static_cast(message->GetInternalArena()); + return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(), + /* extreg= */ nullptr, /* options= */ 0, + arena) == kUpb_DecodeStatus_Ok; +} + +template +bool Parse(std::shared_ptr& message, absl::string_view bytes) { + _upb_Message_Clear(message->msg(), T::minitable()); + auto* arena = static_cast(message->GetInternalArena()); + return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(), + /* extreg= */ nullptr, /* options= */ 0, + arena) == kUpb_DecodeStatus_Ok; +} + template absl::StatusOr Parse(absl::string_view bytes, int options = 0) { T message; @@ -390,7 +408,24 @@ absl::StatusOr Parse(absl::string_view bytes, template absl::StatusOr Serialize(const T& message, upb::Arena& arena, int options = 0) { - return ::protos::internal::Serialize(message.msg(), T::minitable(), + return ::protos::internal::Serialize( + ::protos::internal::GetInternalMsg(message), T::minitable(), arena.ptr(), + options); +} + +template +absl::StatusOr Serialize(std::unique_ptr& message, + upb::Arena& arena, + int options = 0) { + return ::protos::internal::Serialize(message->msg(), T::minitable(), + arena.ptr(), options); +} + +template +absl::StatusOr Serialize(std::shared_ptr& message, + upb::Arena& arena, + int options = 0) { + return ::protos::internal::Serialize(message->msg(), T::minitable(), arena.ptr(), options); } diff --git a/protos_generator/tests/test_generated.cc b/protos_generator/tests/test_generated.cc index f9fcea53fe..558476c60a 100644 --- a/protos_generator/tests/test_generated.cc +++ b/protos_generator/tests/test_generated.cc @@ -580,3 +580,17 @@ TEST(CppGeneratedCode, NameCollisions) { model.set_arena__("test"); EXPECT_EQ("test", model.arena__()); } + +TEST(CppGeneratedCode, SharedPointer) { + std::shared_ptr model = std::make_shared(); + ::upb::Arena arena; + auto bytes = protos::Serialize(model, arena); + EXPECT_TRUE(protos::Parse(model, bytes.value())); +} + +TEST(CppGeneratedCode, UniquePointer) { + std::unique_ptr model = std::make_unique(); + ::upb::Arena arena; + auto bytes = protos::Serialize(model, arena); + EXPECT_TRUE(protos::Parse(model, bytes.value())); +} diff --git a/python/pb_unit_tests/reflection_test_wrapper.py b/python/pb_unit_tests/reflection_test_wrapper.py index f9fdf6f756..a1f458f437 100644 --- a/python/pb_unit_tests/reflection_test_wrapper.py +++ b/python/pb_unit_tests/reflection_test_wrapper.py @@ -41,5 +41,8 @@ SerializationTest.testFieldProperties.__unittest_expecting_failure__ = True +# TODO(259423340) Python Docker image on MacOS failing. +ClassAPITest.testParsingNestedClass.__unittest_skip__ = True + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/upb/msg.c b/upb/msg.c index b8e1631e87..b53f03a792 100644 --- a/upb/msg.c +++ b/upb/msg.c @@ -52,7 +52,7 @@ upb_Message* upb_Message_New(const upb_MiniTable* mini_table, } void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l) { - void* mem = UPB_PTR_AT(msg, -sizeof(upb_Message_Internal), char); + void* mem = (char*)msg - sizeof(upb_Message_Internal); memset(mem, 0, upb_msg_sizeof(l)); }