[ubsan] Fix some UBSAN warnings
Passing nullptr to memset/memcpy is UB, even if the size passed in is 0.
Avoid making such calls when we don't yet have a buffer to write into.
Avoid possible signed integer overflow.
This is basically a cherry-pick of
https://github.com/protocolbuffers/protobuf/commit/d14cacd791ac553b5dfba5f303fc631b42f6e662
and
https://github.com/protocolbuffers/protobuf/commit/0f8e6d1402fc021e02b9def83df9a9683ba6ea76
Change-Id: I286e90dd247c25cf4757cbf4bc92ab578b5d7bdb
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/protobuf/+/426575
Reviewed-by: Roland McGrath <mcgrathr@google.com>
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index 8493268..992ef84 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -350,10 +350,12 @@
while (size > buffer_size_) {
// Data exceeds space in the buffer. Copy what we can and request a
// new buffer.
- memcpy(buffer_, data, buffer_size_);
- offset_ += buffer_size_;
- data += buffer_size_;
- size -= buffer_size_;
+ if (buffer_) {
+ memcpy(buffer_, data, buffer_size_);
+ offset_ += buffer_size_;
+ data += buffer_size_;
+ size -= buffer_size_;
+ }
void* void_buffer;
failed_ = !output_->Next(&void_buffer, &buffer_size_);
if (failed_) return;
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 1a4d71c..9858375 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -1114,10 +1114,12 @@
}
char* FastInt64ToBufferLeft(int64 i, char* buffer) {
- uint64 u = i;
+ uint64 u = 0;
if (i < 0) {
*buffer++ = '-';
- u = -i;
+ u -= i;
+ } else {
+ u = i;
}
return FastUInt64ToBufferLeft(u, buffer);
}
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index eed2a76..a0df094 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -1269,8 +1269,10 @@
while (size > buffer_size_) {
// Data exceeds space in the buffer. Write what we can and request a new
// buffer.
- memset(buffer_, ' ', buffer_size_);
- size -= buffer_size_;
+ if (buffer_size_ > 0) {
+ memset(buffer_, ' ', buffer_size_);
+ size -= buffer_size_;
+ }
void* void_buffer;
failed_ = !output_->Next(&void_buffer, &buffer_size_);
if (failed_) return;