From: Dmitry Volyntsev Date: Wed, 19 Jan 2022 14:03:49 +0000 (+0000) Subject: Fixed Function.prototype.apply() with slow arrays. X-Git-Tag: 0.7.2~3 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/postgres_fdw.c?a=commitdiff_plain;h=39e8fa1b7db1680654527f8fa0e9ee93b334ecba;p=njs.git Fixed Function.prototype.apply() with slow arrays. Previously, the function had two issues: * array->start was referenced without checking for fast array flag * the created arguments list was not sanity-checked for its length, which can be very large. The fix is to remove micro-optimization for arrays and introduce limit size for arguments list. This closes #449 issue in Github. --- diff --git a/src/njs_function.c b/src/njs_function.c index 0c23ca05..ae0fa11f 100644 --- a/src/njs_function.c +++ b/src/njs_function.c @@ -1385,18 +1385,10 @@ njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (njs_is_null_or_undefined(arr_like)) { length = 0; - - goto activate; - - } else if (njs_is_array(arr_like)) { - arr = arr_like->data.u.array; - - args = arr->start; - length = arr->length; - goto activate; + } - } else if (njs_slow_path(!njs_is_object(arr_like))) { + if (njs_slow_path(!njs_is_object(arr_like))) { njs_type_error(vm, "second argument is not an array-like object"); return NJS_ERROR; } @@ -1406,6 +1398,11 @@ njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } + if (njs_slow_path(length > 1024)) { + njs_internal_error(vm, "argument list is too long"); + return NJS_ERROR; + } + arr = njs_array_alloc(vm, 1, length, NJS_ARRAY_SPARE); if (njs_slow_path(arr == NULL)) { return NJS_ERROR; diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index f332999a..35e2f132 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -10063,6 +10063,10 @@ static njs_unit_test_t njs_test[] = "f.apply(123, {})"), njs_str("123") }, + { njs_str("(function(index, ...rest){ return rest[index];})" + ".apply({}, [1022].concat(Array(1023).fill(1).map((v,i)=>i.toString(16))))"), + njs_str("3fe") }, + { njs_str("String.prototype.concat.apply('a', " "{length:2, 0:{toString:function() {return 'b'}}, 1:'c'})"), njs_str("abc") },