If these walls could talk... PiperOrigin-RevId: 458711847
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 7503d7d..f8e0c4e 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc
@@ -427,11 +427,12 @@ uint8_t* ExtensionSet::SerializeMessageSetWithCachedSizesToArray( const MessageLite* extendee, uint8_t* target) const { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; io::EpsCopyOutputStream stream( target, MessageSetByteSize(), io::CodedOutputStream::IsDefaultSerializationDeterministic()); - return InternalSerializeMessageSetWithCachedSizesToArray(extendee, target, - &stream); + return stream.Finalize(InternalSerializeMessageSetWithCachedSizesToArray( + extendee, target, &stream)); } } // namespace internal
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index ef623ea..1f7b951 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc
@@ -62,6 +62,37 @@ // Must be included last. #include "google/protobuf/port_def.inc" +int max_count = 0; + +void set_max_count(int count) { max_count = count; } + +bool jdcoff = false; +bool jdcon(int count) { return !jdcoff && (count < max_count); } + +void TurningOff1() { + // std::cerr << "TURNINGOFF" << std::endl; + // std::cerr << "TURNINGOFF" << std::endl; + // std::cerr << "TURNINGOFF" << std::endl; + // std::cerr << "TURNINGOFF" << std::endl; + // std::cerr << "TURNINGOFF" << std::endl; + // std::cerr << "TURNINGOFF" << std::endl; + // std::cerr << "TURNINGOFF" << std::endl; + // std::cerr << "TURNINGOFF" << std::endl; + // std::cerr << "TURNINGOFF" << std::endl; + jdcoff = !jdcoff; +} + +google::protobuf::io::EpsCopyOutputStream::EpsCopyOutputStream(void* data, int size, + bool deterministic) + : array_end_(static_cast<uint8_t*>(data) + size), + buffer_end_(nullptr), + stream_(nullptr), + is_serialization_deterministic_(deterministic) { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; + // Added by jdcollin@ + end_ = static_cast<uint8_t*>(data) + size - kSlopBytes; +} + namespace google { namespace protobuf { namespace io { @@ -757,6 +788,45 @@ return s; } +uint8_t* EpsCopyOutputStream::FlushArray(uint8_t* ptr) { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; + DCHECK(stream_ == nullptr); + if (PROTOBUF_PREDICT_FALSE(had_error_)) return ptr; + if (buffer_end_ != nullptr) { + const ptrdiff_t bytes = ptr - buffer_; + DCHECK_GE(bytes, 0); + DCHECK_LE(bytes, array_end_ - buffer_end_); + memcpy(buffer_end_, buffer_, static_cast<size_t>(bytes)); + ptr = buffer_end_ + bytes; + buffer_end_ = nullptr; + } + return ptr; +} + +std::pair<uint8_t*, uint8_t*> EpsCopyOutputStream::ConsumeArray(uint8_t* ptr, + int size) { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; + DCHECK(array_end_ != nullptr); + + if (buffer_end_ == nullptr) { + int avail = array_end_ - ptr; + if (size > avail) return {nullptr, nullptr}; + return {ptr, ptr + size}; + } + DCHECK(ptr >= buffer_ && ptr <= buffer_ + kSlopBytes); + + int bytes = ptr - buffer_; + int avail = array_end_ - buffer_end_ - bytes; + if (size > avail) return {nullptr, nullptr}; + + memcpy(buffer_end_, buffer_, bytes); + ptr = buffer_end_ + bytes; + buffer_end_ += bytes + size; + end_ = buffer_ + kSlopBytes; + + return {ptr, buffer_}; +} + uint8_t* EpsCopyOutputStream::Trim(uint8_t* ptr) { if (had_error_) return ptr; int s = Flush(ptr); @@ -879,6 +949,21 @@ } uint8_t* EpsCopyOutputStream::EnsureSpaceFallback(uint8_t* ptr) { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; + // if (!jdcoff && array_end_) { + if (array_end_) { + if (PROTOBUF_PREDICT_FALSE(had_error_)) return buffer_; + if (buffer_end_ == nullptr) { + buffer_end_ = ptr; + } else { + DCHECK(ptr >= buffer_ && ptr <= buffer_ + kSlopBytes); + int bytes = ptr - buffer_; + memcpy(buffer_end_, buffer_, bytes); + buffer_end_ += bytes; + } + end_ = buffer_ + kSlopBytes; + return buffer_; + } do { if (PROTOBUF_PREDICT_FALSE(had_error_)) return buffer_; int overrun = ptr - end_; @@ -892,6 +977,15 @@ uint8_t* EpsCopyOutputStream::WriteRawFallback(const void* data, int size, uint8_t* ptr) { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; + if (array_end_) { + // if (!jdcoff && array_end_) { + auto ptrs = ConsumeArray(ptr, size); + if (PROTOBUF_PREDICT_FALSE(ptrs.first == nullptr)) return Error(); + memcpy(ptrs.first, data, size); + return ptrs.second; + } + int s = GetSize(ptr); while (s < size) { std::memcpy(ptr, data, s); @@ -965,18 +1059,19 @@ #endif uint8_t* EpsCopyOutputStream::WriteCord(const absl::Cord& cord, uint8_t* ptr) { - int s = GetSize(ptr); + // std::cerr << __FUNCTION__ << std::endl; if (stream_ == nullptr) { - if (static_cast<int64_t>(cord.size()) <= s) { - // Just copy it to the current buffer. - return CopyCordToArray(cord, ptr); - } else { - return Error(); - } - } else if (static_cast<int64_t>(cord.size()) <= s && - static_cast<int64_t>(cord.size()) < kMaxCordBytesToCopy) { + auto ptrs = ConsumeArray(ptr, static_cast<int>(cord.size())); + if (PROTOBUF_PREDICT_FALSE(ptrs.first == nullptr)) return Error(); + cord.CopyToArray(reinterpret_cast<char*>(ptrs.first)); + return ptrs.second; + } + int s = GetSize(ptr); + if (static_cast<int64_t>(cord.size()) <= s && + static_cast<int64_t>(cord.size()) < kMaxCordBytesToCopy) { // Just copy it to the current buffer. - return CopyCordToArray(cord, ptr); + cord.CopyToArray(reinterpret_cast<char*>(ptr)); + return ptr + cord.size(); } else { // Back up to the position where the Cord should start. ptr = Trim(ptr); @@ -1034,6 +1129,22 @@ return WriteStringToArray(str, target); } +uint8_t* JDCUnsafeVarint(uint64_t value, uint8_t* ptr) { + static int counter = 0; + bool jdconval = jdcon(counter); + if (jdconval) { + // std::cerr << jdconval << " JDC" << " " << counter++ << std::endl; + *(uint64_t*)ptr = 0; + } + while (PROTOBUF_PREDICT_FALSE(value >= 0x80)) { + *ptr = static_cast<uint8_t>(value | 0x80); + value >>= 7; + ++ptr; + } + *ptr++ = static_cast<uint8_t>(value); + return ptr; +} + } // namespace io } // namespace protobuf } // namespace google
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 98ff721..32d2f09 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h
@@ -1,3 +1,4 @@ +bool jdcon(int); // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ @@ -111,6 +112,7 @@ #include <assert.h> +#include <algorithm> #include <atomic> #include <climits> #include <cstddef> @@ -160,6 +162,7 @@ // Defined in other files. class ZeroCopyInputStream; // zero_copy_stream.h class ZeroCopyOutputStream; // zero_copy_stream.h +uint8_t* JDCUnsafeVarint(uint64_t value, uint8_t* ptr); // Class which reads and decodes binary data which is composed of varint- // encoded integers and fixed-width pieces. Wraps a ZeroCopyInputStream. @@ -654,12 +657,7 @@ // Only for array serialization. No overflow protection, end_ will be the // pointed to the end of the array. When using this the total size is already // known, so no need to maintain the slop region. - EpsCopyOutputStream(void* data, int size, bool deterministic) - : end_(static_cast<uint8_t*>(data) + size), - buffer_end_(nullptr), - stream_(nullptr), - is_serialization_deterministic_(deterministic) {} - + EpsCopyOutputStream(void* data, int size, bool deterministic); // Initialize from stream but with the first buffer already given (eager). EpsCopyOutputStream(void* data, int size, ZeroCopyOutputStream* stream, bool deterministic, uint8_t** pp) @@ -667,10 +665,21 @@ *pp = SetInitialBuffer(data, size); } + // Finlizes this instance. Invokes `Trim()` for stream bound instances and + // `FlushArray()` for array bound instances. + uint8_t* Finalize(uint8_t* ptr) { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; + return stream_ ? Trim(ptr) : FlushArray(ptr); + } + // Flush everything that's written into the underlying ZeroCopyOutputStream // and trims the underlying stream to the location of ptr. uint8_t* Trim(uint8_t* ptr); + // Flushes any yet unwritten data into the array provided at construction. + // Returns a pointer directly beyond the last byte written into the array. + uint8_t* FlushArray(uint8_t* ptr); + // After this it's guaranteed you can safely write kSlopBytes to ptr. This // will never fail! The underlying stream can produce an error. Use HadError // to check for errors. @@ -831,6 +840,7 @@ private: + uint8_t* array_end_ = nullptr; uint8_t* end_; uint8_t* buffer_end_ = buffer_; uint8_t buffer_[2 * kSlopBytes]; @@ -840,6 +850,8 @@ bool is_serialization_deterministic_; bool skip_check_consistency = false; + std::pair<uint8_t*, uint8_t*> ConsumeArray(uint8_t* ptr, int size); + uint8_t* EnsureSpaceFallback(uint8_t* ptr); inline uint8_t* Next(); int Flush(uint8_t* ptr); @@ -911,8 +923,19 @@ template <typename T> PROTOBUF_ALWAYS_INLINE static uint8_t* UnsafeVarint(T value, uint8_t* ptr) { + if (std::is_same<T, uint64_t>::value) { + return JDCUnsafeVarint(value, ptr); + } + static_assert(std::is_unsigned<T>::value, "Varint serialization must be unsigned"); + static int counter = 0; + bool jdconval = jdcon(counter); + if (jdconval) { + // std::cerr << jdconval << " JDC" << sizeof(T) << " " << counter++ << + // std::endl; + *(T*)ptr = 0; + } while (PROTOBUF_PREDICT_FALSE(value >= 0x80)) { *ptr = static_cast<uint8_t>(value | 0x80); value >>= 7; @@ -1789,6 +1812,8 @@ } // namespace protobuf } // namespace google +extern void TurningOff1(); + #if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) #pragma runtime_checks("c", restore) #endif // _MSC_VER && !defined(__INTEL_COMPILER)
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index fc0f56a..cc7bf29 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc
@@ -382,7 +382,10 @@ io::EpsCopyOutputStream out( target, size, io::CodedOutputStream::IsDefaultSerializationDeterministic()); - uint8_t* res = msg._InternalSerialize(target, &out); + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; + // std::cerr << msg.DebugString() << std::endl; + auto serialized = msg._InternalSerialize(target, &out); + auto res = out.Finalize(serialized); GOOGLE_ABSL_DCHECK(target + size == res); return res; } @@ -548,6 +551,7 @@ } bool MessageLite::AppendPartialToCord(absl::Cord* output) const { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; // For efficiency, we'd like to pass a size hint to CordOutputStream with // the exact total size expected. const size_t size = ByteSizeLong(); @@ -568,7 +572,7 @@ io::EpsCopyOutputStream out( target, static_cast<int>(available.size()), io::CodedOutputStream::IsDefaultSerializationDeterministic()); - auto res = _InternalSerialize(target, &out); + uint8_t* res = out.Finalize(_InternalSerialize(target, &out)); GOOGLE_ABSL_DCHECK_EQ(res, target + size); buffer.IncreaseLengthBy(size); output->Append(std::move(buffer));
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h index 5abd813..f45fffc 100644 --- a/src/google/protobuf/wire_format.h +++ b/src/google/protobuf/wire_format.h
@@ -181,11 +181,13 @@ // Returns a pointer past the last written byte. static uint8_t* SerializeUnknownFieldsToArray( const UnknownFieldSet& unknown_fields, uint8_t* target) { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; io::EpsCopyOutputStream stream( target, static_cast<int>(ComputeUnknownFieldsSize(unknown_fields)), io::CodedOutputStream::IsDefaultSerializationDeterministic()); - return InternalSerializeUnknownFieldsToArray(unknown_fields, target, - &stream); + target = + InternalSerializeUnknownFieldsToArray(unknown_fields, target, &stream); + return stream.Finalize(target); } static uint8_t* InternalSerializeUnknownFieldsToArray( const UnknownFieldSet& unknown_fields, uint8_t* target,
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h index b95098e..ca1e890 100644 --- a/src/google/protobuf/wire_format_lite.h +++ b/src/google/protobuf/wire_format_lite.h
@@ -652,16 +652,19 @@ // that are non-deterministic always. PROTOBUF_NDEBUG_INLINE static uint8_t* WriteGroupToArray( int field_number, const MessageLite& value, uint8_t* target) { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; io::EpsCopyOutputStream stream( target, value.GetCachedSize() + static_cast<int>(2 * io::CodedOutputStream::VarintSize32( static_cast<uint32_t>(field_number) << 3)), io::CodedOutputStream::IsDefaultSerializationDeterministic()); - return InternalWriteGroup(field_number, value, target, &stream); + target = InternalWriteGroup(field_number, value, target, &stream); + return stream.Finalize(target); } PROTOBUF_NDEBUG_INLINE static uint8_t* WriteMessageToArray( int field_number, const MessageLite& value, uint8_t* target) { + // std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl; int size = value.GetCachedSize(); io::EpsCopyOutputStream stream( target, @@ -669,8 +672,9 @@ static_cast<uint32_t>(field_number) << 3) + io::CodedOutputStream::VarintSize32(size)), io::CodedOutputStream::IsDefaultSerializationDeterministic()); - return InternalWriteMessage(field_number, value, value.GetCachedSize(), - target, &stream); + target = InternalWriteMessage(field_number, value, value.GetCachedSize(), + target, &stream); + return stream.Finalize(target); } // Compute the byte size of a field. The XxSize() functions do NOT include