compiler: avoid undefined behavior in Import::read

For some implementations of Stream, advancing the stream will invalidate
the previously-returned peek buffer. Copy the peek buffer before
advancing in Import::read to avoid this undefined behavior.

Change-Id: Icfd56cf5e6f0d94a582d44e63bc51e75c24b8804
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/259438
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Than McIntosh <thanm@google.com>
diff --git a/go/gogo.cc b/go/gogo.cc
index aef1c47..f40f131 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -6212,7 +6212,7 @@
 	  return false;
 	}
 
-      *body = imp->read(static_cast<size_t>(llen));
+      imp->read(static_cast<size_t>(llen), body);
     }
 
   return true;
diff --git a/go/import.cc b/go/import.cc
index 081afef..c6c1178 100644
--- a/go/import.cc
+++ b/go/import.cc
@@ -1375,8 +1375,8 @@
 
 // Read LENGTH bytes from the stream.
 
-std::string
-Import::read(size_t length)
+void
+Import::read(size_t length, std::string* out)
 {
   const char* data;
   if (!this->stream_->peek(length, &data))
@@ -1385,10 +1385,11 @@
 	go_error_at(this->location_, "import error at %d: expected %d bytes",
 		    this->stream_->pos(), static_cast<int>(length));
       this->stream_->set_saw_error();
-      return "";
+      *out = std::string("");
+      return;
     }
+  *out = std::string(data, length);
   this->advance(length);
-  return std::string(data, length);
 }
 
 // Turn a string into a integer with appropriate error handling.
diff --git a/go/import.h b/go/import.h
index b12b3b8..1d8aae4 100644
--- a/go/import.h
+++ b/go/import.h
@@ -240,10 +240,10 @@
   get_char()
   { return this->stream_->get_char(); }
 
-  // Read LENGTH characters into a string and advance past them.  On
-  // EOF reports an error and returns an empty string.
-  std::string
-  read(size_t length);
+  // Read LENGTH characters into *OUT and advance past them.  On
+  // EOF reports an error and sets *OUT to an empty string.
+  void
+  read(size_t length, std::string* out);
 
   // Return true at the end of the stream.
   bool