diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index d934bda38225536ce1fc965a353c769cd6a2326f..5562d46892a89f62a69ffeab13edc236f48fc9b0 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -155,7 +155,7 @@ static StringSet parseStrings(std::istream & str, bool arePaths)
 static Derivation parseDerivation(const string & s)
 {
     Derivation drv;
-    std::istringstream str(s);
+    istringstream_nocopy str(s);
     expect(str, "Derive([");
 
     /* Parse the list of outputs. */
diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc
index c11f2b06b990e5835f5dec6524760cde42ae6cac..1bc8576a8aef8bccec6213d2793520f7e5f8969b 100644
--- a/src/libstore/s3-binary-cache-store.cc
+++ b/src/libstore/s3-binary-cache-store.cc
@@ -145,7 +145,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
             .WithBucket(bucketName)
             .WithKey(path);
 
-        auto stream = std::make_shared<std::stringstream>(data);
+        auto stream = std::make_shared<istringstream_nocopy>(data);
 
         request.SetBody(stream);
 
diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc
index 81aced0fde164243d23237bc507479c39d3d5704..49e781980f3ad2f3bfe12319f9df75ae7ccc36a4 100644
--- a/src/libutil/hash.cc
+++ b/src/libutil/hash.cc
@@ -106,7 +106,7 @@ Hash parseHash(HashType ht, const string & s)
         string s2(s, i * 2, 2);
         if (!isxdigit(s2[0]) || !isxdigit(s2[1]))
             throw BadHash(format("invalid hash ‘%1%’") % s);
-        std::istringstream str(s2);
+        istringstream_nocopy str(s2);
         int n;
         str >> std::hex >> n;
         hash.hash[i] = n;
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 50b96f7ed92c51a293799ae6efb5be644311879e..a8f6f99b957fae45bca6f03e107d3fe11cfafc15 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -431,4 +431,18 @@ void callSuccess(
 }
 
 
+/* A variant of std::istringstream that doesn't its string
+   argument. This is useful for large strings. The caller must ensure
+   that the string object is not destroyed while it's referenced by
+   this object. */
+struct istringstream_nocopy : public std::stringstream
+{
+    istringstream_nocopy(const std::string & s)
+    {
+        rdbuf()->pubsetbuf(
+            (char *) s.data(), s.size());
+    }
+};
+
+
 }