aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2016-06-22 14:56:18 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2016-06-29 12:21:11 +0200
commitc50e19220453039b08065f50eb2cd1713c402c4e (patch)
tree1f32a2a025cbdbe0188f8c68310e0c917c609e20
parentda4c1c314d0b933810c03b368a9a3379b82481d3 (diff)
downloadandroid-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.cc25
-rw-r--r--src/util.h14
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_);