diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2016-06-22 14:56:18 +0200 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2016-06-29 12:21:11 +0200 |
commit | c50e19220453039b08065f50eb2cd1713c402c4e (patch) | |
tree | 1f32a2a025cbdbe0188f8c68310e0c917c609e20 | |
parent | da4c1c314d0b933810c03b368a9a3379b82481d3 (diff) | |
download | android-node-v8-c50e19220453039b08065f50eb2cd1713c402c4e.tar.gz android-node-v8-c50e19220453039b08065f50eb2cd1713c402c4e.tar.bz2 android-node-v8-c50e19220453039b08065f50eb2cd1713c402c4e.zip |
src: fix memory leak in WriteBuffers() error path
Pointed out by Coverity. Introduced in commit 05d30d53 from July 2015
("fs: implemented WriteStream#writev").
WriteBuffers() leaked memory in the synchronous uv_fs_write() error path
when trying to write > 1024 buffers.
PR-URL: https://github.com/nodejs/node/pull/7374
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
-rw-r--r-- | src/node_file.cc | 25 | ||||
-rw-r--r-- | src/util.h | 14 |
2 files changed, 19 insertions, 20 deletions
diff --git a/src/node_file.cc b/src/node_file.cc index 089ead82ea..968284788a 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1079,38 +1079,23 @@ static void WriteBuffers(const FunctionCallbackInfo<Value>& args) { int64_t pos = GET_OFFSET(args[2]); Local<Value> req = args[3]; - uint32_t chunkCount = chunks->Length(); + MaybeStackBuffer<uv_buf_t> iovs(chunks->Length()); - uv_buf_t s_iovs[1024]; // use stack allocation when possible - uv_buf_t* iovs; - - if (chunkCount > arraysize(s_iovs)) - iovs = new uv_buf_t[chunkCount]; - else - iovs = s_iovs; - - for (uint32_t i = 0; i < chunkCount; i++) { + for (uint32_t i = 0; i < iovs.length(); i++) { Local<Value> chunk = chunks->Get(i); - if (!Buffer::HasInstance(chunk)) { - if (iovs != s_iovs) - delete[] iovs; + if (!Buffer::HasInstance(chunk)) return env->ThrowTypeError("Array elements all need to be buffers"); - } iovs[i] = uv_buf_init(Buffer::Data(chunk), Buffer::Length(chunk)); } if (req->IsObject()) { - ASYNC_CALL(write, req, UTF8, fd, iovs, chunkCount, pos) - if (iovs != s_iovs) - delete[] iovs; + ASYNC_CALL(write, req, UTF8, fd, *iovs, iovs.length(), pos) return; } - SYNC_CALL(write, nullptr, fd, iovs, chunkCount, pos) - if (iovs != s_iovs) - delete[] iovs; + SYNC_CALL(write, nullptr, fd, *iovs, iovs.length(), pos) args.GetReturnValue().Set(SYNC_RESULT); } diff --git a/src/util.h b/src/util.h index 0a6b5e0dbe..1570c57f19 100644 --- a/src/util.h +++ b/src/util.h @@ -231,6 +231,16 @@ class MaybeStackBuffer { return buf_; } + T& operator[](size_t index) { + CHECK_LT(index, length()); + return buf_[index]; + } + + const T& operator[](size_t index) const { + CHECK_LT(index, length()); + return buf_[index]; + } + size_t length() const { return length_; } @@ -282,6 +292,10 @@ class MaybeStackBuffer { buf_[0] = T(); } + explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() { + AllocateSufficientStorage(storage); + } + ~MaybeStackBuffer() { if (buf_ != buf_st_) free(buf_); |