summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTimothy Gu <timothygu99@gmail.com>2017-03-19 13:35:47 -0700
committerJames M Snell <jasnell@gmail.com>2017-03-21 21:53:57 -0700
commit4fb9b1226f3b80bf1e4661fd3be6e91283b8531b (patch)
tree11fc501575edb472438f3bb320f61200a918c42e /src
parent1d82adc8c7ff4a04a9b8ef3fdbbf28515967cdcb (diff)
downloadandroid-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.cc28
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;