fix: keep same ABI in asan and non-asan builds (#12831)

fixes: #12830

Closes #12831

PiperOrigin-RevId: 534121876
pull/12857/head
Matt Kulukundis 2 years ago committed by Copybara-Service
parent bec4585d3d
commit ded8f486c7
  1. 50
      src/google/protobuf/parse_context.h

@ -35,6 +35,7 @@
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <utility>
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/log/absl_check.h" #include "absl/log/absl_check.h"
@ -133,50 +134,41 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
if (count > 0) StreamBackUp(count); if (count > 0) StreamBackUp(count);
} }
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || defined(ABSL_HAVE_MEMORY_SANITIZER) // In sanitizer mode we use memory poisoning to guarantee that:
// In sanitizer mode we use an optional<int> to guarantee that:
// - We do not read an uninitialized token. // - We do not read an uninitialized token.
// - Every non-empty token is moved from and consumed. // - We would like to verify that this token was consumed, but unforuntately
// __asan_address_is_poisoned is allowed to have false negatives.
class LimitToken { class LimitToken {
public: public:
LimitToken() = default; LimitToken() { PROTOBUF_POISON_MEMORY_REGION(&token_, sizeof(token_)); }
explicit LimitToken(int token) : token_(token) {}
LimitToken(LimitToken&& other) { *this = std::move(other); }
LimitToken& operator=(LimitToken&& other) {
token_ = std::exchange(other.token_, absl::nullopt);
return *this;
}
~LimitToken() { ABSL_CHECK(!token_.has_value()); } explicit LimitToken(int token) : token_(token) {
PROTOBUF_UNPOISON_MEMORY_REGION(&token_, sizeof(token_));
}
LimitToken(const LimitToken&) = delete; LimitToken(const LimitToken&) = delete;
LimitToken& operator=(const LimitToken&) = delete; LimitToken& operator=(const LimitToken&) = delete;
int token() && { LimitToken(LimitToken&& other) { *this = std::move(other); }
ABSL_CHECK(token_.has_value());
return *std::exchange(token_, absl::nullopt);
}
private: LimitToken& operator=(LimitToken&& other) {
absl::optional<int> token_; PROTOBUF_UNPOISON_MEMORY_REGION(&token_, sizeof(token_));
}; token_ = other.token_;
#else PROTOBUF_POISON_MEMORY_REGION(&other.token_, sizeof(token_));
class LimitToken { return *this;
public: }
LimitToken() = default;
explicit LimitToken(int token) : token_(token) {}
LimitToken(LimitToken&&) = default;
LimitToken& operator=(LimitToken&&) = default;
LimitToken(const LimitToken&) = delete; ~LimitToken() = default;
LimitToken& operator=(const LimitToken&) = delete;
int token() const { return token_; } int token() && {
int t = token_;
PROTOBUF_POISON_MEMORY_REGION(&token_, sizeof(token_));
return t;
}
private: private:
int token_; int token_;
}; };
#endif
// If return value is negative it's an error // If return value is negative it's an error
PROTOBUF_NODISCARD LimitToken PushLimit(const char* ptr, int limit) { PROTOBUF_NODISCARD LimitToken PushLimit(const char* ptr, int limit) {

Loading…
Cancel
Save