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
pull/13171/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent 4d3998b54b
commit d3ec4b63c9
  1. 3
      .github/workflows/python_tests.yml
  2. 2
      bazel/workspace_deps.bzl
  3. 37
      protos/protos.h
  4. 14
      protos_generator/tests/test_generated.cc
  5. 3
      python/pb_unit_tests/reflection_test_wrapper.py
  6. 2
      upb/msg.c

@ -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

@ -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"],
)

@ -358,6 +358,24 @@ bool Parse(T& message, absl::string_view bytes) {
arena) == kUpb_DecodeStatus_Ok;
}
template <typename T>
bool Parse(std::unique_ptr<T>& message, absl::string_view bytes) {
_upb_Message_Clear(message->msg(), T::minitable());
auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(),
/* extreg= */ nullptr, /* options= */ 0,
arena) == kUpb_DecodeStatus_Ok;
}
template <typename T>
bool Parse(std::shared_ptr<T>& message, absl::string_view bytes) {
_upb_Message_Clear(message->msg(), T::minitable());
auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(),
/* extreg= */ nullptr, /* options= */ 0,
arena) == kUpb_DecodeStatus_Ok;
}
template <typename T>
absl::StatusOr<T> Parse(absl::string_view bytes, int options = 0) {
T message;
@ -390,7 +408,24 @@ absl::StatusOr<T> Parse(absl::string_view bytes,
template <typename T>
absl::StatusOr<absl::string_view> 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 <typename T>
absl::StatusOr<absl::string_view> Serialize(std::unique_ptr<T>& message,
upb::Arena& arena,
int options = 0) {
return ::protos::internal::Serialize(message->msg(), T::minitable(),
arena.ptr(), options);
}
template <typename T>
absl::StatusOr<absl::string_view> Serialize(std::shared_ptr<T>& message,
upb::Arena& arena,
int options = 0) {
return ::protos::internal::Serialize(message->msg(), T::minitable(),
arena.ptr(), options);
}

@ -580,3 +580,17 @@ TEST(CppGeneratedCode, NameCollisions) {
model.set_arena__("test");
EXPECT_EQ("test", model.arena__());
}
TEST(CppGeneratedCode, SharedPointer) {
std::shared_ptr<TestModel> model = std::make_shared<TestModel>();
::upb::Arena arena;
auto bytes = protos::Serialize(model, arena);
EXPECT_TRUE(protos::Parse(model, bytes.value()));
}
TEST(CppGeneratedCode, UniquePointer) {
std::unique_ptr<TestModel> model = std::make_unique<TestModel>();
::upb::Arena arena;
auto bytes = protos::Serialize(model, arena);
EXPECT_TRUE(protos::Parse(model, bytes.value()));
}

@ -41,5 +41,8 @@ SerializationTest.testFieldDataDescriptor.__unittest_expecting_failure__ = True
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)

@ -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));
}

Loading…
Cancel
Save