Make sure the size arg of alloc will not overflow (#1618)

Also make sure the bytelength = arraylength << shift will not overflow

Fix issue #1616

JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang zidong.jiang@intel.com
This commit is contained in:
Zidong Jiang
2017-03-07 07:37:19 +08:00
committed by yichoi
parent 71e1383d13
commit c6f22a9683
4 changed files with 150 additions and 66 deletions
@@ -321,6 +321,12 @@ ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this argument
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ecma_value_t new_typedarray = ecma_op_create_typedarray_with_type_and_length (obj_p, len); ecma_value_t new_typedarray = ecma_op_create_typedarray_with_type_and_length (obj_p, len);
if (ECMA_IS_VALUE_ERROR (new_typedarray))
{
return new_typedarray;
}
ecma_object_t *new_obj_p = ecma_get_object_from_value (new_typedarray); ecma_object_t *new_obj_p = ecma_get_object_from_value (new_typedarray);
for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++) for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++)
@@ -331,7 +337,7 @@ ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this argument
ECMA_TRY_CATCH (mapped_value, ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3), ret_value); ECMA_TRY_CATCH (mapped_value, ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3), ret_value);
ecma_value_t set_status = ecma_op_typedarray_set_index_prop (new_obj_p, index, mapped_value); bool set_status = ecma_op_typedarray_set_index_prop (new_obj_p, index, mapped_value);
if (!set_status) if (!set_status)
{ {
@@ -574,25 +580,33 @@ ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this argum
if (ecma_is_value_empty (ret_value)) if (ecma_is_value_empty (ret_value))
{ {
ecma_value_t new_typedarray = ecma_op_create_typedarray_with_type_and_length (obj_p, pass_num); ecma_value_t new_typedarray = ecma_op_create_typedarray_with_type_and_length (obj_p, pass_num);
ecma_object_t *new_obj_p = ecma_get_object_from_value (new_typedarray);
for (uint32_t index = 0; index < pass_num && ecma_is_value_empty (ret_value); index++) if (ECMA_IS_VALUE_ERROR (new_typedarray))
{
ecma_value_t set_status = ecma_op_typedarray_set_index_prop (new_obj_p, index, *(pass_value_list + index));
if (!set_status)
{
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("error in typedarray set"));
}
}
if (ecma_is_value_empty (ret_value))
{ {
ret_value = new_typedarray; ret_value = new_typedarray;
} }
else else
{ {
ecma_free_value (new_typedarray); ecma_object_t *new_obj_p = ecma_get_object_from_value (new_typedarray);
for (uint32_t index = 0; index < pass_num && ecma_is_value_empty (ret_value); index++)
{
bool set_status = ecma_op_typedarray_set_index_prop (new_obj_p, index, *(pass_value_list + index));
if (!set_status)
{
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("error in typedarray set"));
}
}
if (ecma_is_value_empty (ret_value))
{
ret_value = new_typedarray;
}
else
{
ecma_free_value (new_typedarray);
}
} }
} }
@@ -21,6 +21,7 @@
#include "ecma-gc.h" #include "ecma-gc.h"
#include "ecma-globals.h" #include "ecma-globals.h"
#include "ecma-helpers.h" #include "ecma-helpers.h"
#include "jmem.h"
#ifndef CONFIG_DISABLE_ARRAYBUFFER_BUILTIN #ifndef CONFIG_DISABLE_ARRAYBUFFER_BUILTIN
@@ -68,6 +69,11 @@ ecma_op_create_arraybuffer_object (const ecma_value_t *arguments_list_p, /**< li
} }
} }
if (length > UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1)
{
return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid ArrayBuffer length."));
}
ecma_object_t *object_p = ecma_arraybuffer_new_object (length); ecma_object_t *object_p = ecma_arraybuffer_new_object (length);
return ecma_make_object_value (object_p); return ecma_make_object_value (object_p);
@@ -205,18 +205,28 @@ set_typedarray_element (lit_utf8_byte_t *dst, /**< the location in the internal
* *
* See also: ES2015 22.2.1.2.1 * See also: ES2015 22.2.1.2.1
* *
* @return pointer to the new typedarray object * @return ecma value of the new typedarray object
* Returned value must be freed with ecma_free_value
*/ */
static ecma_object_t * static ecma_value_t
ecma_typedarray_create_object_with_length (ecma_length_t array_length, /**< length of the typedarray */ ecma_typedarray_create_object_with_length (ecma_length_t array_length, /**< length of the typedarray */
ecma_object_t *proto_p, /**< prototype object */ ecma_object_t *proto_p, /**< prototype object */
uint8_t element_size_shift, /**< the size shift of the element length */ uint8_t element_size_shift, /**< the size shift of the element length */
lit_magic_string_id_t class_id) /**< class name of the typedarray */ lit_magic_string_id_t class_id) /**< class name of the typedarray */
{ {
if (array_length > (UINT32_MAX >> element_size_shift))
{
return ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached."));
}
ecma_length_t byte_length = array_length << element_size_shift; ecma_length_t byte_length = array_length << element_size_shift;
ecma_value_t new_arraybuffer_p = ecma_make_object_value (ecma_arraybuffer_new_object (byte_length)); if (byte_length > UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1)
{
return ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached."));
}
ecma_value_t new_arraybuffer_p = ecma_make_object_value (ecma_arraybuffer_new_object (byte_length));
ecma_object_t *object_p = ecma_create_object (proto_p, ecma_object_t *object_p = ecma_create_object (proto_p,
sizeof (ecma_extended_object_t), sizeof (ecma_extended_object_t),
ECMA_OBJECT_TYPE_PSEUDO_ARRAY); ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
@@ -229,7 +239,7 @@ ecma_typedarray_create_object_with_length (ecma_length_t array_length, /**< leng
ecma_free_value (new_arraybuffer_p); ecma_free_value (new_arraybuffer_p);
return object_p; return ecma_make_object_value (object_p);
} /* !ecma_typedarray_create_object_with_length */ } /* !ecma_typedarray_create_object_with_length */
/** /**
@@ -237,9 +247,10 @@ ecma_typedarray_create_object_with_length (ecma_length_t array_length, /**< leng
* *
* See also: ES2015 22.2.1.5 * See also: ES2015 22.2.1.5
* *
* @return pointer to the new typedarray object * @return ecma value of the new typedarray object
* Returned value must be freed with ecma_free_value
*/ */
static ecma_object_t * static ecma_value_t
ecma_typedarray_create_object_with_buffer (ecma_object_t *arraybuffer_p, /**< the arraybuffer inside */ ecma_typedarray_create_object_with_buffer (ecma_object_t *arraybuffer_p, /**< the arraybuffer inside */
ecma_length_t byte_offset, /**< the byte offset of the arraybuffer */ ecma_length_t byte_offset, /**< the byte offset of the arraybuffer */
ecma_length_t array_length, /**< length of the typedarray */ ecma_length_t array_length, /**< length of the typedarray */
@@ -248,6 +259,7 @@ ecma_typedarray_create_object_with_buffer (ecma_object_t *arraybuffer_p, /**< th
lit_magic_string_id_t class_id) /**< class name of the typedarray */ lit_magic_string_id_t class_id) /**< class name of the typedarray */
{ {
ecma_object_t *object_p; ecma_object_t *object_p;
if (byte_offset == 0 && array_length == ecma_arraybuffer_get_length (arraybuffer_p) >> element_size_shift) if (byte_offset == 0 && array_length == ecma_arraybuffer_get_length (arraybuffer_p) >> element_size_shift)
{ {
object_p = ecma_create_object (proto_p, object_p = ecma_create_object (proto_p,
@@ -260,7 +272,7 @@ ecma_typedarray_create_object_with_buffer (ecma_object_t *arraybuffer_p, /**< th
ext_object_p->u.pseudo_array.extra_info = element_size_shift; ext_object_p->u.pseudo_array.extra_info = element_size_shift;
ext_object_p->u.pseudo_array.u2.arraybuffer = ecma_make_object_value (arraybuffer_p); ext_object_p->u.pseudo_array.u2.arraybuffer = ecma_make_object_value (arraybuffer_p);
return object_p; return ecma_make_object_value (object_p);
} }
object_p = ecma_create_object (proto_p, object_p = ecma_create_object (proto_p,
@@ -277,7 +289,7 @@ ecma_typedarray_create_object_with_buffer (ecma_object_t *arraybuffer_p, /**< th
typedarray_info_p->array_length = array_length; typedarray_info_p->array_length = array_length;
typedarray_info_p->byte_offset = byte_offset; typedarray_info_p->byte_offset = byte_offset;
return object_p; return ecma_make_object_value (object_p);
} /* ecma_typedarray_create_object_with_buffer */ } /* ecma_typedarray_create_object_with_buffer */
/** /**
@@ -285,9 +297,10 @@ ecma_typedarray_create_object_with_buffer (ecma_object_t *arraybuffer_p, /**< th
* *
* See also: ES2015 22.2.1.3 * See also: ES2015 22.2.1.3
* *
* @return pointer to the new typedarray object * @return ecma value of the new typedarray object
* Returned value must be freed with ecma_free_value
*/ */
static ecma_object_t * static ecma_value_t
ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**< a typedarray object */ ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**< a typedarray object */
ecma_object_t *proto_p, /**< prototype object */ ecma_object_t *proto_p, /**< prototype object */
uint8_t element_size_shift, /**< the size shift of the element length */ uint8_t element_size_shift, /**< the size shift of the element length */
@@ -306,7 +319,18 @@ ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**<
} }
else else
{ {
if (array_length > (UINT32_MAX >> element_size_shift))
{
return ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached."));
}
ecma_length_t byte_length = array_length << element_size_shift; ecma_length_t byte_length = array_length << element_size_shift;
if (byte_length > UINT32_MAX - sizeof (ecma_extended_object_t) - JMEM_ALIGNMENT + 1)
{
return ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached."));
}
arraybuffer_p = ecma_arraybuffer_new_object (byte_length); arraybuffer_p = ecma_arraybuffer_new_object (byte_length);
lit_utf8_byte_t *src_buf = ecma_arraybuffer_get_buffer (src_arraybuffer_p); lit_utf8_byte_t *src_buf = ecma_arraybuffer_get_buffer (src_arraybuffer_p);
lit_utf8_byte_t *dst_buf = ecma_arraybuffer_get_buffer (arraybuffer_p); lit_utf8_byte_t *dst_buf = ecma_arraybuffer_get_buffer (arraybuffer_p);
@@ -324,16 +348,16 @@ ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**<
} }
} }
ecma_object_t *object_p = ecma_typedarray_create_object_with_buffer (arraybuffer_p, ecma_value_t obj = ecma_typedarray_create_object_with_buffer (arraybuffer_p,
0, 0,
array_length, array_length,
proto_p, proto_p,
element_size_shift, element_size_shift,
class_id); class_id);
ecma_deref_object (arraybuffer_p); ecma_deref_object (arraybuffer_p);
return object_p; return obj;
} /* ecma_typedarray_create_object_with_typedarray */ } /* ecma_typedarray_create_object_with_typedarray */
/** /**
@@ -341,7 +365,7 @@ ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**<
* *
* See also: ES2015 22.2.2.1 * See also: ES2015 22.2.2.1
* *
* @return ecma value * @return ecma value of the new typedarray object
* Returned value must be freed with ecma_free_value * Returned value must be freed with ecma_free_value
*/ */
ecma_value_t ecma_value_t
@@ -364,11 +388,11 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje
} }
/* 10 */ /* 10 */
ECMA_TRY_CATCH (arraylike_val, ECMA_TRY_CATCH (arraylike,
ecma_op_to_object (items_val), ecma_op_to_object (items_val),
ret_value); ret_value);
ecma_object_t *arraylike_p = ecma_get_object_from_value (arraylike_val); ecma_object_t *arraylike_p = ecma_get_object_from_value (arraylike);
/* 12 */ /* 12 */
ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string ();
@@ -382,10 +406,17 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje
uint32_t len = ecma_number_to_uint32 (len_number); uint32_t len = ecma_number_to_uint32 (len_number);
/* 14 */ /* 14 */
ecma_object_t *new_typedarray_p = ecma_typedarray_create_object_with_length (len, ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (len,
proto_p, proto_p,
element_size_shift, element_size_shift,
class_id); class_id);
if (ECMA_IS_VALUE_ERROR (new_typedarray))
{
ret_value = ecma_copy_value (new_typedarray);
}
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
/* 17 */ /* 17 */
ecma_value_t current_index; ecma_value_t current_index;
@@ -446,7 +477,7 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje
ECMA_OP_TO_NUMBER_FINALIZE (len_number); ECMA_OP_TO_NUMBER_FINALIZE (len_number);
ECMA_FINALIZE (len_value); ECMA_FINALIZE (len_value);
ecma_deref_ecma_string (magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p);
ECMA_FINALIZE (arraylike_val); ECMA_FINALIZE (arraylike);
return ret_value; return ret_value;
} /* ecma_op_typedarray_from */ } /* ecma_op_typedarray_from */
@@ -539,7 +570,7 @@ ecma_typedarray_get_offset (ecma_object_t *typedarray_p) /**< the pointer to the
* extend_part * extend_part
* typedarray_info * typedarray_info
* *
* @return ecma value * @return ecma value of the new typedarray object
* Returned value must be freed with ecma_free_value * Returned value must be freed with ecma_free_value
*/ */
ecma_value_t ecma_value_t
@@ -556,7 +587,7 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
if (arguments_list_len == 0) if (arguments_list_len == 0)
{ {
/* 22.2.1.1 */ /* 22.2.1.1 */
ret = ecma_make_object_value (ecma_typedarray_create_object_with_length (0, proto_p, element_size_shift, class_id)); ret = ecma_typedarray_create_object_with_length (0, proto_p, element_size_shift, class_id);
} }
else if (!ecma_is_value_object (arguments_list_p[0])) else if (!ecma_is_value_object (arguments_list_p[0]))
{ {
@@ -576,10 +607,10 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
} }
else else
{ {
ret = ecma_make_object_value (ecma_typedarray_create_object_with_length (length, ret = ecma_typedarray_create_object_with_length (length,
proto_p, proto_p,
element_size_shift, element_size_shift,
class_id)); class_id);
} }
ECMA_OP_TO_NUMBER_FINALIZE (num); ECMA_OP_TO_NUMBER_FINALIZE (num);
@@ -590,10 +621,10 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
{ {
/* 22.2.1.3 */ /* 22.2.1.3 */
ecma_object_t *typedarray_p = ecma_get_object_from_value (arguments_list_p[0]); ecma_object_t *typedarray_p = ecma_get_object_from_value (arguments_list_p[0]);
ret = ecma_make_object_value (ecma_typedarray_create_object_with_typedarray (typedarray_p, ret = ecma_typedarray_create_object_with_typedarray (typedarray_p,
proto_p, proto_p,
element_size_shift, element_size_shift,
class_id)); class_id);
} }
else if (ecma_is_arraybuffer (arguments_list_p[0])) else if (ecma_is_arraybuffer (arguments_list_p[0]))
{ {
@@ -638,6 +669,12 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
ECMA_OP_TO_NUMBER_TRY_CATCH (num3, arg3, ret); ECMA_OP_TO_NUMBER_TRY_CATCH (num3, arg3, ret);
int32_t new_length = ecma_number_to_int32 (num3); int32_t new_length = ecma_number_to_int32 (num3);
new_length = (new_length > 0) ? new_length : 0; new_length = (new_length > 0) ? new_length : 0;
if ((uint32_t) new_length > (UINT32_MAX >> element_size_shift))
{
ret = ecma_raise_range_error (ECMA_ERR_MSG ("Maximum typedarray size is reached."));
}
new_byte_length = (ecma_length_t) new_length << element_size_shift; new_byte_length = (ecma_length_t) new_length << element_size_shift;
if (new_byte_length + offset > buf_byte_length) if (new_byte_length + offset > buf_byte_length)
@@ -651,12 +688,12 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
if (ecma_is_value_empty (ret)) if (ecma_is_value_empty (ret))
{ {
ecma_length_t array_length = new_byte_length >> element_size_shift; ecma_length_t array_length = new_byte_length >> element_size_shift;
ret = ecma_make_object_value (ecma_typedarray_create_object_with_buffer (arraybuffer_p, ret = ecma_typedarray_create_object_with_buffer (arraybuffer_p,
offset, offset,
array_length, array_length,
proto_p, proto_p,
element_size_shift, element_size_shift,
class_id)); class_id);
} }
} }
@@ -665,10 +702,10 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
else else
{ {
/* 22.2.1.4 */ /* 22.2.1.4 */
ecma_value_t undef_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ecma_value_t undef = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
ret = ecma_op_typedarray_from (arguments_list_p[0], ret = ecma_op_typedarray_from (arguments_list_p[0],
undef_val, undef,
undef_val, undef,
proto_p, proto_p,
element_size_shift, element_size_shift,
class_id); class_id);
@@ -825,9 +862,9 @@ ecma_op_typedarray_set_index_prop (ecma_object_t *obj_p, /**< a TypedArray objec
return false; return false;
} }
ecma_value_t error_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_value_t error = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ECMA_OP_TO_NUMBER_TRY_CATCH (value_num, value, error_val); ECMA_OP_TO_NUMBER_TRY_CATCH (value_num, value, error);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (obj_p); ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (obj_p);
ecma_length_t offset = ecma_typedarray_get_offset (obj_p); ecma_length_t offset = ecma_typedarray_get_offset (obj_p);
@@ -839,7 +876,7 @@ ecma_op_typedarray_set_index_prop (ecma_object_t *obj_p, /**< a TypedArray objec
ECMA_OP_TO_NUMBER_FINALIZE (value_num); ECMA_OP_TO_NUMBER_FINALIZE (value_num);
if (ecma_is_value_empty (error_val)) if (ecma_is_value_empty (error))
{ {
return true; return true;
} }
@@ -929,14 +966,14 @@ ecma_op_create_typedarray_with_type_and_length (ecma_object_t *obj_p, /**< Typed
} }
} }
ecma_object_t *new_obj_p = ecma_typedarray_create_object_with_length (array_length, ecma_value_t new_obj = ecma_typedarray_create_object_with_length (array_length,
proto_p, proto_p,
element_size_shift, element_size_shift,
class_id); class_id);
ecma_deref_object (proto_p); ecma_deref_object (proto_p);
return ecma_make_object_value (new_obj_p); return new_obj;
} /* ecma_op_create_typedarray_with_type_and_length */ } /* ecma_op_create_typedarray_with_type_and_length */
/** /**
@@ -0,0 +1,27 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var name = "";
try
{
var a = new ArrayBuffer (0xfffffffe)
}
catch (e)
{
name = e.name;
}
assert(name === "RangeError");