don't allocate large buffers on the stack

This commit is contained in:
Will Dietz 2018-03-01 15:00:58 -06:00
parent 3748a0ca1e
commit c89a3d5368
5 changed files with 30 additions and 29 deletions

View file

@ -4156,8 +4156,8 @@ void Worker::waitForInput()
set<int> fds2(j->fds); set<int> fds2(j->fds);
for (auto & k : fds2) { for (auto & k : fds2) {
if (FD_ISSET(k, &fds)) { if (FD_ISSET(k, &fds)) {
unsigned char buffer[4096]; std::vector<unsigned char> buffer(4096);
ssize_t rd = read(k, buffer, sizeof(buffer)); ssize_t rd = read(k, buffer.data(), buffer.size());
if (rd == -1) { if (rd == -1) {
if (errno != EINTR) if (errno != EINTR)
throw SysError(format("reading from %1%") throw SysError(format("reading from %1%")
@ -4169,7 +4169,7 @@ void Worker::waitForInput()
} else { } else {
printMsg(lvlVomit, format("%1%: read %2% bytes") printMsg(lvlVomit, format("%1%: read %2% bytes")
% goal->getName() % rd); % goal->getName() % rd);
string data((char *) buffer, rd); string data((char *) buffer.data(), rd);
j->lastOutput = after; j->lastOutput = after;
goal->handleChildOutput(k, data); goal->handleChildOutput(k, data);
} }

View file

@ -40,14 +40,14 @@ static void dumpContents(const Path & path, size_t size,
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
if (!fd) throw SysError(format("opening file '%1%'") % path); if (!fd) throw SysError(format("opening file '%1%'") % path);
unsigned char buf[65536]; std::vector<unsigned char> buf(65536);
size_t left = size; size_t left = size;
while (left > 0) { while (left > 0) {
size_t n = left > sizeof(buf) ? sizeof(buf) : left; size_t n = left > buf.size() ? buf.size() : left;
readFull(fd.get(), buf, n); readFull(fd.get(), buf.data(), n);
left -= n; left -= n;
sink(buf, n); sink(buf.data(), n);
} }
writePadding(size, sink); writePadding(size, sink);
@ -146,14 +146,14 @@ static void parseContents(ParseSink & sink, Source & source, const Path & path)
sink.preallocateContents(size); sink.preallocateContents(size);
unsigned long long left = size; unsigned long long left = size;
unsigned char buf[65536]; std::vector<unsigned char> buf(65536);
while (left) { while (left) {
checkInterrupt(); checkInterrupt();
unsigned int n = sizeof(buf); auto n = buf.size();
if ((unsigned long long)n > left) n = left; if ((unsigned long long)n > left) n = left;
source(buf, n); source(buf.data(), n);
sink.receiveContents(buf, n); sink.receiveContents(buf.data(), n);
left -= n; left -= n;
} }

View file

@ -256,12 +256,12 @@ Hash hashFile(HashType ht, const Path & path)
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
if (!fd) throw SysError(format("opening file '%1%'") % path); if (!fd) throw SysError(format("opening file '%1%'") % path);
unsigned char buf[8192]; std::vector<unsigned char> buf(8192);
ssize_t n; ssize_t n;
while ((n = read(fd.get(), buf, sizeof(buf)))) { while ((n = read(fd.get(), buf.data(), buf.size()))) {
checkInterrupt(); checkInterrupt();
if (n == -1) throw SysError(format("reading file '%1%'") % path); if (n == -1) throw SysError(format("reading file '%1%'") % path);
update(ht, ctx, buf, n); update(ht, ctx, buf.data(), n);
} }
finish(ht, ctx, hash.hash); finish(ht, ctx, hash.hash);

View file

@ -229,16 +229,17 @@ bool pathExists(const Path & path)
Path readLink(const Path & path) Path readLink(const Path & path)
{ {
checkInterrupt(); checkInterrupt();
std::vector<char> buf;
for (ssize_t bufSize = PATH_MAX/4; true; bufSize += bufSize/2) { for (ssize_t bufSize = PATH_MAX/4; true; bufSize += bufSize/2) {
char buf[bufSize]; buf.resize(bufSize);
ssize_t rlSize = readlink(path.c_str(), buf, bufSize); ssize_t rlSize = readlink(path.c_str(), buf.data(), bufSize);
if (rlSize == -1) if (rlSize == -1)
if (errno == EINVAL) if (errno == EINVAL)
throw Error("'%1%' is not a symlink", path); throw Error("'%1%' is not a symlink", path);
else else
throw SysError("reading symbolic link '%1%'", path); throw SysError("reading symbolic link '%1%'", path);
else if (rlSize < bufSize) else if (rlSize < bufSize)
return string(buf, rlSize); return string(buf.data(), rlSize);
} }
} }
@ -293,10 +294,10 @@ string readFile(int fd)
if (fstat(fd, &st) == -1) if (fstat(fd, &st) == -1)
throw SysError("statting file"); throw SysError("statting file");
auto buf = std::make_unique<unsigned char[]>(st.st_size); std::vector<unsigned char> buf(st.st_size);
readFull(fd, buf.get(), st.st_size); readFull(fd, buf.data(), st.st_size);
return string((char *) buf.get(), st.st_size); return string((char *) buf.data(), st.st_size);
} }
@ -438,10 +439,10 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
static Lazy<Path> getHome2([]() { static Lazy<Path> getHome2([]() {
Path homeDir = getEnv("HOME"); Path homeDir = getEnv("HOME");
if (homeDir.empty()) { if (homeDir.empty()) {
char buf[16384]; std::vector<char> buf(16384);
struct passwd pwbuf; struct passwd pwbuf;
struct passwd * pw; struct passwd * pw;
if (getpwuid_r(getuid(), &pwbuf, buf, sizeof(buf), &pw) != 0 if (getpwuid_r(getuid(), &pwbuf, buf.data(), buf.size(), &pw) != 0
|| !pw || !pw->pw_dir || !pw->pw_dir[0]) || !pw || !pw->pw_dir || !pw->pw_dir[0])
throw Error("cannot determine user's home directory"); throw Error("cannot determine user's home directory");
homeDir = pw->pw_dir; homeDir = pw->pw_dir;
@ -569,16 +570,16 @@ void writeFull(int fd, const string & s, bool allowInterrupts)
string drainFD(int fd) string drainFD(int fd)
{ {
string result; string result;
unsigned char buffer[4096]; std::vector<unsigned char> buffer(4096);
while (1) { while (1) {
checkInterrupt(); checkInterrupt();
ssize_t rd = read(fd, buffer, sizeof buffer); ssize_t rd = read(fd, buffer.data(), buffer.size());
if (rd == -1) { if (rd == -1) {
if (errno != EINTR) if (errno != EINTR)
throw SysError("reading from file"); throw SysError("reading from file");
} }
else if (rd == 0) break; else if (rd == 0) break;
else result.append((char *) buffer, rd); else result.append((char *) buffer.data(), rd);
} }
return result; return result;
} }

View file

@ -37,13 +37,13 @@ using namespace nix;
static ssize_t splice(int fd_in, void *off_in, int fd_out, void *off_out, size_t len, unsigned int flags) static ssize_t splice(int fd_in, void *off_in, int fd_out, void *off_out, size_t len, unsigned int flags)
{ {
/* We ignore most parameters, we just have them for conformance with the linux syscall */ /* We ignore most parameters, we just have them for conformance with the linux syscall */
char buf[8192]; std::vector<char> buf(8192);
auto read_count = read(fd_in, buf, sizeof(buf)); auto read_count = read(fd_in, buf.data(), buf.size());
if (read_count == -1) if (read_count == -1)
return read_count; return read_count;
auto write_count = decltype(read_count)(0); auto write_count = decltype(read_count)(0);
while (write_count < read_count) { while (write_count < read_count) {
auto res = write(fd_out, buf + write_count, read_count - write_count); auto res = write(fd_out, buf.data() + write_count, read_count - write_count);
if (res == -1) if (res == -1)
return res; return res;
write_count += res; write_count += res;