Skip to content

Commit 8f8bda2

Browse files
committed
Fix Array.prototype.push() and unshift() in case result length is larger than UINT_MAX
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com
1 parent 63083b3 commit 8f8bda2

File tree

3 files changed

+115
-79
lines changed

3 files changed

+115
-79
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp

Lines changed: 40 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,29 @@
5757
*/
5858
static ecma_completion_value_t
5959
ecma_builtin_array_prototype_helper_set_length (ecma_object_t *object, /**< object*/
60-
uint32_t length) /**< new length */
60+
ecma_number_t length) /**< new length */
6161
{
6262
ecma_completion_value_t ret_value;
63-
ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
6463

65-
ecma_number_t *len_p = ecma_alloc_number ();
66-
*len_p = ecma_uint32_to_number (length);
64+
if (ecma_object_get_class_name (object) == LIT_MAGIC_STRING_ARRAY_UL
65+
&& unlikely (length > (uint32_t)(-1))) /* Check if length greater than UINT_MAX */
66+
{
67+
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE));
68+
}
69+
else
70+
{
71+
ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
6772

68-
ret_value = ecma_op_object_put (object,
69-
magic_string_length_p,
70-
ecma_make_number_value (len_p),
71-
true),
73+
ecma_number_t *len_p = ecma_alloc_number ();
74+
*len_p = length;
7275

73-
ecma_dealloc_number (len_p);
74-
ecma_deref_ecma_string (magic_string_length_p);
76+
ret_value = ecma_op_object_put (object,
77+
magic_string_length_p,
78+
ecma_make_number_value (len_p),
79+
true),
80+
ecma_dealloc_number (len_p);
81+
ecma_deref_ecma_string (magic_string_length_p);
82+
}
7583

7684
return ret_value;
7785
} /* ecma_builtin_array_prototype_helper_set_length */
@@ -571,7 +579,7 @@ ecma_builtin_array_prototype_object_pop (ecma_value_t this_arg) /**< this argume
571579
{
572580
/* 4.a */
573581
ECMA_TRY_CATCH (set_length_value,
574-
ecma_builtin_array_prototype_helper_set_length (obj_p, 0),
582+
ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO),
575583
ret_value);
576584

577585
/* 4.b */
@@ -593,7 +601,7 @@ ecma_builtin_array_prototype_object_pop (ecma_value_t this_arg) /**< this argume
593601

594602
/* 5.d */
595603
ECMA_TRY_CATCH (set_length_value,
596-
ecma_builtin_array_prototype_helper_set_length (obj_p, len),
604+
ecma_builtin_array_prototype_helper_set_length (obj_p, ecma_uint32_to_number (len)),
597605
ret_value);
598606

599607
ret_value = ecma_make_normal_completion_value (ecma_copy_value (get_value, true));
@@ -644,61 +652,38 @@ ecma_builtin_array_prototype_object_push (ecma_value_t this_arg, /**< this argum
644652
/* 3. */
645653
ECMA_OP_TO_NUMBER_TRY_CATCH (length_var, length_value, ret_value);
646654

647-
uint32_t n = ecma_number_to_uint32 (length_var);
655+
ecma_number_t n = ecma_uint32_to_number (ecma_number_to_uint32 (length_var));
648656

649657
/* 5. */
650658
for (uint32_t index = 0;
651-
index < arguments_number;
659+
index < arguments_number && ecma_is_completion_value_empty (ret_value);
652660
index++, n++)
653661
{
654662
/* 5.a */
655663
ecma_value_t e_value = argument_list_p[index];
656664

657665
/* 5.b */
658-
ecma_string_t *n_str_p = ecma_new_ecma_string_from_uint32 (n);
666+
ecma_string_t *n_str_p = ecma_new_ecma_string_from_number (n);
659667

660-
ecma_completion_value_t completion = ecma_op_object_put (obj_p, n_str_p, e_value, true);
668+
ECMA_TRY_CATCH (put_value, ecma_op_object_put (obj_p, n_str_p, e_value, true), ret_value);
669+
ECMA_FINALIZE (put_value);
661670

662671
ecma_deref_ecma_string (n_str_p);
663-
664-
if (unlikely (ecma_is_completion_value_throw (completion)))
665-
{
666-
ret_value = completion;
667-
break;
668-
}
669-
else
670-
{
671-
JERRY_ASSERT (ecma_is_completion_value_normal (completion));
672-
ecma_free_completion_value (completion);
673-
}
674672
}
675673

676674
/* 6. */
677675
if (ecma_is_completion_value_empty (ret_value))
678676
{
679-
ecma_number_t *num_length_p = ecma_alloc_number ();
680-
*num_length_p = ecma_uint32_to_number (n);
681-
682-
ecma_value_t num_length_value = ecma_make_number_value (num_length_p);
677+
ECMA_TRY_CATCH (set_length_value,
678+
ecma_builtin_array_prototype_helper_set_length (obj_p, n),
679+
ret_value);
683680

684-
ecma_completion_value_t completion = ecma_op_object_put (obj_p,
685-
length_str_p,
686-
num_length_value,
687-
true);
681+
ecma_number_t *ret_num_p = ecma_alloc_number ();
682+
*ret_num_p = n;
688683

689-
if (unlikely (ecma_is_completion_value_throw (completion)))
690-
{
691-
ret_value = completion;
684+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
692685

693-
ecma_dealloc_number (num_length_p);
694-
}
695-
else
696-
{
697-
JERRY_ASSERT (ecma_is_completion_value_normal (completion));
698-
ecma_free_completion_value (completion);
699-
700-
ret_value = ecma_make_normal_completion_value (num_length_value);
701-
}
686+
ECMA_FINALIZE (set_length_value)
702687
}
703688

704689
ECMA_OP_TO_NUMBER_FINALIZE (length_var);
@@ -844,7 +829,7 @@ ecma_builtin_array_prototype_object_shift (ecma_value_t this_arg) /**< this argu
844829
if (len == 0)
845830
{
846831
ECMA_TRY_CATCH (set_length_value,
847-
ecma_builtin_array_prototype_helper_set_length (obj_p, 0),
832+
ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO),
848833
ret_value);
849834

850835
ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED);
@@ -899,7 +884,7 @@ ecma_builtin_array_prototype_object_shift (ecma_value_t this_arg) /**< this argu
899884

900885
/* 9. */
901886
ECMA_TRY_CATCH (set_length_value,
902-
ecma_builtin_array_prototype_helper_set_length (obj_p, len),
887+
ecma_builtin_array_prototype_helper_set_length (obj_p, ecma_uint32_to_number (len)),
903888
ret_value);
904889
/* 10. */
905890
ret_value = ecma_make_normal_completion_value (ecma_copy_value (first_value, true));
@@ -1727,7 +1712,7 @@ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this arg
17271712
if (ecma_is_completion_value_empty (ret_value))
17281713
{
17291714
ECMA_TRY_CATCH (set_length_value,
1730-
ecma_builtin_array_prototype_helper_set_length (obj_p, new_len),
1715+
ecma_builtin_array_prototype_helper_set_length (obj_p, ecma_uint32_to_number (new_len)),
17311716
ret_value);
17321717

17331718
ECMA_FINALIZE (set_length_value);
@@ -1790,7 +1775,8 @@ ecma_builtin_array_prototype_object_unshift (ecma_value_t this_arg, /**< this ar
17901775
/* 6.a */
17911776
ecma_string_t *from_str_p = ecma_new_ecma_string_from_uint32 (k - 1);
17921777
/* 6.b */
1793-
ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (k + args_number - 1);
1778+
ecma_number_t new_idx = ecma_uint32_to_number (k) + ecma_uint32_to_number (args_number) - 1;
1779+
ecma_string_t *to_str_p = ecma_new_ecma_string_from_number (new_idx);
17941780

17951781
/* 6.c */
17961782
if (ecma_op_object_get_property (obj_p, from_str_p) != NULL)
@@ -1827,13 +1813,13 @@ ecma_builtin_array_prototype_object_unshift (ecma_value_t this_arg, /**< this ar
18271813

18281814
if (ecma_is_completion_value_empty (ret_value))
18291815
{
1816+
ecma_number_t new_len = ecma_uint32_to_number (len) + ecma_uint32_to_number (args_number);
18301817
/* 10. */
18311818
ECMA_TRY_CATCH (set_length_value,
1832-
ecma_builtin_array_prototype_helper_set_length (obj_p, len + args_number),
1819+
ecma_builtin_array_prototype_helper_set_length (obj_p, new_len),
18331820
ret_value);
1834-
18351821
ecma_number_t *num_p = ecma_alloc_number ();
1836-
*num_p = ecma_uint32_to_number (len + args_number);
1822+
*num_p = new_len;
18371823
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (num_p));
18381824

18391825
ECMA_FINALIZE (set_length_value);
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
// Copyright 2015 University of Szeged.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
var len;
17+
var d = [];
18+
assert (d.length === 0);
19+
len = d.push();
20+
assert (d.length === 0);
21+
assert (d.length === len);
22+
len = d.push(1);
23+
assert (d.length === 1);
24+
assert (d.length === len);
25+
len = d.push(2);
26+
assert (d.length === 2);
27+
assert (d.length === len);
28+
len = d.push('a');
29+
assert (d.length === 3);
30+
assert (d.length === len);
31+
len = d.push('b', 'c', 3);
32+
assert (d.length == 6);
33+
assert (d.length === len);
34+
assert (d[0] === 1);
35+
assert (d[1] === 2);
36+
assert (d[2] === 'a');
37+
assert (d[3] === 'b');
38+
assert (d[4] === 'c');
39+
assert (d[5] === 3);
40+
41+
var a = [];
42+
a.length = 4294967294;
43+
assert(a.push("x") === 4294967295);
44+
assert(a.length === 4294967295);
45+
assert(a[4294967294] === "x");
46+
47+
try {
48+
a.push("y");
49+
assert(false);
50+
} catch (e) {
51+
assert (e instanceof RangeError);
52+
}
53+
assert(a.length === 4294967295)
54+
55+
56+
var o = { length : 4294967294, push : Array.prototype.push };
57+
assert(o.push("x") === 4294967295);
58+
assert(o.length === 4294967295);
59+
assert(o[4294967294] === "x");
60+
61+
try {
62+
assert(o.push("y") === 4294967296);
63+
} catch (e) {
64+
assert(false);
65+
}
66+
assert(o.length === 4294967296);
67+
assert(o[4294967295] === "y");
68+
69+
try {
70+
assert(o.push("z") === 1);
71+
} catch (e) {
72+
assert(false);
73+
}
74+
assert(o.length === 1);
75+
assert(o[0] === "z");

tests/jerry/array.js

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -81,28 +81,3 @@ assert (c[3] === '3');
8181
b[0] = 1;
8282
c[0] += b[0];
8383
assert (c[0] == 1);
84-
85-
var len;
86-
var d = [];
87-
assert (d.length === 0);
88-
len = d.push();
89-
assert (d.length === 0);
90-
assert (d.length === len);
91-
len = d.push(1);
92-
assert (d.length === 1);
93-
assert (d.length === len);
94-
len = d.push(2);
95-
assert (d.length === 2);
96-
assert (d.length === len);
97-
len = d.push('a');
98-
assert (d.length === 3);
99-
assert (d.length === len);
100-
len = d.push('b', 'c', 3);
101-
assert (d.length == 6);
102-
assert (d.length === len);
103-
assert (d[0] === 1);
104-
assert (d[1] === 2);
105-
assert (d[2] === 'a');
106-
assert (d[3] === 'b');
107-
assert (d[4] === 'c');
108-
assert (d[5] === 3);

0 commit comments

Comments
 (0)