Files
allwpilib/upstream_utils/protobuf_patches/0003-Fix-maybe-uninitialized-warnings.patch
Thad House a9ac5b8e24 Don't read protobuf static data across shared library lines directly (#6979)
Reading exported data from shared objects on windows is broken. It requires __declspec(dllimport). However, this is problematic, as we use the same static libraries both from a shared and static context. So we can't just blindly apply dllimport.

The linker should have caught this, as data members are exported in a different way. However, due to a bug in native-utils, data member symbols were exposed directly. However, interacting with those data member was completely broken.

The only way we can really solve this is to just not use static data members. We're pretty good about this in WPILib itself. However, protobuf is absolutely terrible at this. There are a ton of inline functions that access global data. For the protobuf library itself, we can solve this easily enough.

However, for the generated protobuf code, this is much more problematic. The member needed to bypass the global data is private. This means using just the stock protobuf code, this problem is not solvable. But, protobuf generated code has insertion points. Those insertion points let us add our own code into the generated code via a protoc plugin. And it just so happens that an insertion point exists to add extra public methodsto the generated protobuf header. There is also an insertion point to let us add to the cpp file.

The methods we need are the getters, for unpacking protobufs. For any protobuf that has a message as a member, we generate a new wpi_x() getter (the existing one is just x(), where x is the field name). We then implement this in the cpp file. A trick we can use is in the cpp file, we can safely call the x() function, as the cpp file is in the same library as the global. Thus we can call that inline method, and not actually need to directly access any internal private state of the protobuf object.

TL;DR, all protobuf classes that have messages as fields now have a wpi_x() accessor that must be used instead of x() if you want the code to work on windows. After wpilibsuite/native-utils#212, the bad code will fail to link, rather then just fail at runtime.
2024-08-21 07:53:20 -07:00

169 lines
7.2 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Johnson <johnson.peter@gmail.com>
Date: Sat, 10 Jun 2023 15:00:20 -0700
Subject: [PATCH 03/13] Fix maybe-uninitialized warnings
---
src/google/protobuf/arena.cc | 6 +++---
src/google/protobuf/arena_impl.h | 4 ++--
src/google/protobuf/extension_set_inl.h | 2 +-
.../protobuf/generated_message_tctable_lite.cc | 16 ++++++++--------
src/google/protobuf/io/coded_stream.cc | 2 +-
5 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index 6ba508a5f0f3436d52ccc326cc932ceed3cd79fa..194404213ee5f6ad05b1e01f2bff23859d60dc56 100644
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -411,7 +411,7 @@ uint64_t ThreadSafeArena::Reset() {
std::pair<void*, SerialArena::CleanupNode*>
ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
const std::type_info* type) {
- SerialArena* arena;
+ SerialArena* arena = nullptr;
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
GetSerialArenaFast(&arena))) {
return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
@@ -421,7 +421,7 @@ ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
}
void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) {
- SerialArena* arena;
+ SerialArena* arena = nullptr;
if (PROTOBUF_PREDICT_FALSE(!GetSerialArenaFast(&arena))) {
arena = GetSerialArenaFallback(&thread_cache());
}
@@ -433,7 +433,7 @@ void* ThreadSafeArena::AllocateAlignedFallback(size_t n,
const std::type_info* type) {
if (alloc_policy_.should_record_allocs()) {
alloc_policy_.RecordAlloc(type, n);
- SerialArena* arena;
+ SerialArena* arena = nullptr;
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
return arena->AllocateAligned(n, alloc_policy_.get());
}
diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h
index 76727688b558354be18f0c6576db1d4619348ef4..8af70c48f13feece7cf8580e71845ec267ddaddb 100644
--- a/src/google/protobuf/arena_impl.h
+++ b/src/google/protobuf/arena_impl.h
@@ -482,7 +482,7 @@ class PROTOBUF_EXPORT ThreadSafeArena {
template <AllocationClient alloc_client = AllocationClient::kDefault>
void* AllocateAligned(size_t n, const std::type_info* type) {
- SerialArena* arena;
+ SerialArena* arena = nullptr;
if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
GetSerialArenaFast(&arena))) {
return arena->AllocateAligned<alloc_client>(n, AllocPolicy());
@@ -492,7 +492,7 @@ class PROTOBUF_EXPORT ThreadSafeArena {
}
void ReturnArrayMemory(void* p, size_t size) {
- SerialArena* arena;
+ SerialArena* arena = nullptr;
if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
arena->ReturnArrayMemory(p, size);
}
diff --git a/src/google/protobuf/extension_set_inl.h b/src/google/protobuf/extension_set_inl.h
index e4e711721d4d8690e1e87fc8e31df1b5836d4fd7..50c04cd41feccf6cb5fda2740d6d4adb874645d7 100644
--- a/src/google/protobuf/extension_set_inl.h
+++ b/src/google/protobuf/extension_set_inl.h
@@ -206,7 +206,7 @@ const char* ExtensionSet::ParseMessageSetItemTmpl(
const char* ptr, const Msg* extendee, internal::InternalMetadata* metadata,
internal::ParseContext* ctx) {
std::string payload;
- uint32_t type_id;
+ uint32_t type_id = 0;
enum class State { kNoTag, kHasType, kHasPayload, kDone };
State state = State::kNoTag;
diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc
index 9993811dca3229edc766061c4a8d54933bcb0eba..2268b2be4d4c60c545765469549d73c6a468dac8 100644
--- a/src/google/protobuf/generated_message_tctable_lite.cc
+++ b/src/google/protobuf/generated_message_tctable_lite.cc
@@ -770,7 +770,7 @@ PROTOBUF_NOINLINE const char* TcParser::SingularVarBigint(
};
volatile Spill spill = {data.data, msg, table, hasbits};
- uint64_t tmp;
+ uint64_t tmp = 0;
PROTOBUF_ASSUME(static_cast<int8_t>(*ptr) < 0);
ptr = ParseVarint(ptr, &tmp);
@@ -845,7 +845,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedVarint(
auto expected_tag = UnalignedLoad<TagType>(ptr);
do {
ptr += sizeof(TagType);
- uint64_t tmp;
+ uint64_t tmp = 0;
ptr = ParseVarint(ptr, &tmp);
if (ptr == nullptr) {
return Error(PROTOBUF_TC_PARAM_PASS);
@@ -1001,7 +1001,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularEnum(
}
const char* ptr2 = ptr; // Save for unknown enum case
ptr += sizeof(TagType); // Consume tag
- uint64_t tmp;
+ uint64_t tmp = 0;
ptr = ParseVarint(ptr, &tmp);
if (ptr == nullptr) {
return Error(PROTOBUF_TC_PARAM_PASS);
@@ -1052,7 +1052,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnum(
do {
const char* ptr2 = ptr; // save for unknown enum case
ptr += sizeof(TagType);
- uint64_t tmp;
+ uint64_t tmp = 0;
ptr = ParseVarint(ptr, &tmp);
if (ptr == nullptr) {
return Error(PROTOBUF_TC_PARAM_PASS);
@@ -1477,7 +1477,7 @@ const char* TcParser::MpVarint(PROTOBUF_TC_PARAM_DECL) {
// Parse the value:
const char* ptr2 = ptr; // save for unknown enum case
- uint64_t tmp;
+ uint64_t tmp = 0;
ptr = ParseVarint(ptr, &tmp);
if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
@@ -1542,7 +1542,7 @@ const char* TcParser::MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL) {
const char* ptr2 = ptr;
uint32_t next_tag;
do {
- uint64_t tmp;
+ uint64_t tmp = 0;
ptr = ParseVarint(ptr2, &tmp);
if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
field.Add(is_zigzag ? WireFormatLite::ZigZagDecode64(tmp) : tmp);
@@ -1554,7 +1554,7 @@ const char* TcParser::MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL) {
const char* ptr2 = ptr;
uint32_t next_tag;
do {
- uint64_t tmp;
+ uint64_t tmp = 0;
ptr = ParseVarint(ptr2, &tmp);
if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
if (is_validated_enum) {
@@ -1575,7 +1575,7 @@ const char* TcParser::MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL) {
const char* ptr2 = ptr;
uint32_t next_tag;
do {
- uint64_t tmp;
+ uint64_t tmp = 0;
ptr = ParseVarint(ptr2, &tmp);
if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
field.Add(static_cast<bool>(tmp));
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 487e1b8a379b86bfa3097d68a64ee0a727d36cab..53997901f333292f71ac52e7f9c876bd918f7bf6 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -462,7 +462,7 @@ int64_t CodedInputStream::ReadVarint32Fallback(uint32_t first_byte_or_zero) {
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
GOOGLE_DCHECK_NE(first_byte_or_zero, 0)
<< "Caller should provide us with *buffer_ when buffer is non-empty";
- uint32_t temp;
+ uint32_t temp = 0;
::std::pair<bool, const uint8_t*> p =
ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
if (!p.first) return -1;