constchar* EpsCopyInputStream::ReadStringFallback(constchar* ptr, int size, std::string* str){ str->clear(); if (PROTOBUF_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { // Reserve the string up to a static safe size. If strings are bigger than // this we proceed by growing the string as needed. This protects against // malicious payloads making protobuf hold on to a lot of memory. str->reserve(str->size() + std::min<int>(size, kSafeStringSize)); } returnAppendSize(ptr, size, [str](constchar* p, int s) { str->append(p, s); }); }
constchar* EpsCopyInputStream::AppendStringFallback(constchar* ptr, int size, std::string* str){ if (PROTOBUF_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { // Reserve the string up to a static safe size. If strings are bigger than // this we proceed by growing the string as needed. This protects against // malicious payloads making protobuf hold on to a lot of memory. str->reserve(str->size() + std::min<int>(size, kSafeStringSize)); } returnAppendSize(ptr, size, [str](constchar* p, int s) { str->append(p, s); }); }
template <typename A> constchar* AppendSize(constchar* ptr, int size, const A& append){ int chunk_size = buffer_end_ + kSlopBytes - ptr; do { GOOGLE_DCHECK(size > chunk_size); if (next_chunk_ == nullptr) returnnullptr; append(ptr, chunk_size); ptr += chunk_size; size -= chunk_size; // TODO(gerbens) Next calls NextBuffer which generates buffers with // overlap and thus incurs cost of copying the slop regions. This is not // necessary for reading strings. We should just call Next buffers. if (limit_ <= kSlopBytes) returnnullptr; ptr = Next(); if (ptr == nullptr) returnnullptr; // passed the limit ptr += kSlopBytes; chunk_size = buffer_end_ + kSlopBytes - ptr; } while (size > chunk_size); append(ptr, size); return ptr + size; }
可以看到 pb.cc 中的操作也是类似的, 只不过 pb.cc 中可以通过 proto 文件提前得知都有哪些 field 和他们的类型