Skip to content

Commit

Permalink
Add Parse/Serialize templates to support shared_ptr/unique_ptr.
Browse files Browse the repository at this point in the history
Fix UBSAN in _upb_Message_Clear due to unsigned UPB_PTR_AT

PiperOrigin-RevId: 489007182
  • Loading branch information
protobuf-github-bot authored and copybara-github committed Nov 16, 2022
1 parent 4d3998b commit d3ec4b6
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 5 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/python_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion bazel/workspace_deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
)

Expand Down
37 changes: 36 additions & 1 deletion protos/protos.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down
14 changes: 14 additions & 0 deletions protos_generator/tests/test_generated.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
}
3 changes: 3 additions & 0 deletions python/pb_unit_tests/reflection_test_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion upb/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down

0 comments on commit d3ec4b6

Please sign in to comment.