aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-09-15 13:02:59 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-09-15 13:02:59 +0200
commit131c8cb4424c475bbdaf41912ba1ca66869322de (patch)
tree4f8f155a8c876e773c6acdadcee49b52cbf49340
parent3fb35dc4bd8949880e5e6c6cb4825442c7d78b7b (diff)
Handle infinite output when extracting metadata (GitHub issue #102)
-rw-r--r--libbuild2/file.cxx24
1 files changed, 22 insertions, 2 deletions
diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx
index e1dde1f..2660b9e 100644
--- a/libbuild2/file.cxx
+++ b/libbuild2/file.cxx
@@ -3,6 +3,7 @@
#include <libbuild2/file.hxx>
+#include <cerrno>
#include <iomanip> // left, setw()
#include <sstream>
@@ -1713,9 +1714,28 @@ namespace build2
try
{
- ifdstream is (move (pr.in_ofd), fdstream_mode::skip);
+ ifdstream is (move (pr.in_ofd), ifdstream::badbit); // Note: no skip!
+
+ // What are the odds that we will run some unrelated program which
+ // will keep writing to stdout until we run out of memory reading?
+ // Apparently non-negligible (see GitHub issue #102).
+ //
string r;
- getline (is, r, '\0'); // Will fail if there is no data.
+ {
+ char b[1024];
+ while (!eof (is.read (b, sizeof (b))))
+ {
+ r.append (b, sizeof (b));
+ if (r.size () > 65536)
+ {
+ is.close ();
+ pr.kill ();
+ throw_generic_ios_failure (EFBIG, "output too large");
+ }
+ }
+ r.append (b, static_cast<size_t> (is.gcount ()));
+ }
+
is.close (); // Detect errors.
if (pr.wait ())