diff options
author | Timothy Gu <timothygu99@gmail.com> | 2017-03-19 13:35:47 -0700 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2017-03-21 21:53:57 -0700 |
commit | 4fb9b1226f3b80bf1e4661fd3be6e91283b8531b (patch) | |
tree | 11fc501575edb472438f3bb320f61200a918c42e /src | |
parent | 1d82adc8c7ff4a04a9b8ef3fdbbf28515967cdcb (diff) | |
download | android-node-v8-4fb9b1226f3b80bf1e4661fd3be6e91283b8531b.tar.gz android-node-v8-4fb9b1226f3b80bf1e4661fd3be6e91283b8531b.tar.bz2 android-node-v8-4fb9b1226f3b80bf1e4661fd3be6e91283b8531b.zip |
src, buffer: do not segfault on out-of-range index
Also add test cases for partial writes and invalid indices.
PR-URL: https://github.com/nodejs/node/pull/11927
Fixes: https://github.com/nodejs/node/issues/8724
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/node_buffer.cc | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/src/node_buffer.cc b/src/node_buffer.cc index dc8afd5783..04c0161edd 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -169,7 +169,8 @@ void CallbackInfo::WeakCallback(Isolate* isolate) { // Parse index for external array data. inline MUST_USE_RESULT bool ParseArrayIndex(Local<Value> arg, size_t def, - size_t* ret) { + size_t* ret, + size_t needed = 0) { if (arg->IsUndefined()) { *ret = def; return true; @@ -183,7 +184,7 @@ inline MUST_USE_RESULT bool ParseArrayIndex(Local<Value> arg, // Check that the result fits in a size_t. const uint64_t kSizeMax = static_cast<uint64_t>(static_cast<size_t>(-1)); // coverity[pointless_expression] - if (static_cast<uint64_t>(tmp_i) > kSizeMax) + if (static_cast<uint64_t>(tmp_i) > kSizeMax - needed) return false; *ret = static_cast<size_t>(tmp_i); @@ -815,17 +816,28 @@ void WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) { CHECK_NE(ts_obj_data, nullptr); T val = args[1]->NumberValue(env->context()).FromMaybe(0); - size_t offset = args[2]->IntegerValue(env->context()).FromMaybe(0); size_t memcpy_num = sizeof(T); + size_t offset; - if (should_assert) { - THROW_AND_RETURN_IF_OOB(offset + memcpy_num >= memcpy_num); - THROW_AND_RETURN_IF_OOB(offset + memcpy_num <= ts_obj_length); + // If the offset is negative or larger than the size of the ArrayBuffer, + // throw an error (if needed) and return directly. + if (!ParseArrayIndex(args[2], 0, &offset, memcpy_num) || + offset >= ts_obj_length) { + if (should_assert) + THROW_AND_RETURN_IF_OOB(false); + return; } - if (offset + memcpy_num > ts_obj_length) - memcpy_num = ts_obj_length - offset; + // If the offset is too large for the entire value, but small enough to fit + // part of the value, throw an error and return only if should_assert is + // true. Otherwise, write the part of the value that fits. + if (offset + memcpy_num > ts_obj_length) { + if (should_assert) + THROW_AND_RETURN_IF_OOB(false); + else + memcpy_num = ts_obj_length - offset; + } union NoAlias { T val; |