Skip to content

Commit 252cfb0

Browse files
authored
Fix length check for Array.prototype indexOf, lastIndexOf and fill (#3798)
JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi [email protected]
1 parent c09c2c5 commit 252cfb0

File tree

6 files changed

+197
-7
lines changed

6 files changed

+197
-7
lines changed

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

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,9 +1676,15 @@ ecma_builtin_array_prototype_object_index_of (const ecma_value_t args[], /**< ar
16761676
{
16771677
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
16781678

1679-
if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE
1680-
&& len != 0)
1679+
if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE)
16811680
{
1681+
if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL))
1682+
{
1683+
return ecma_make_integer_value (-1);
1684+
}
1685+
1686+
len = JERRY_MIN (ext_obj_p->u.array.length, len);
1687+
16821688
ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp);
16831689

16841690
while (from_idx < len)
@@ -1775,12 +1781,16 @@ ecma_builtin_array_prototype_object_last_index_of (const ecma_value_t args[], /*
17751781
if (ecma_op_object_is_fast_array (obj_p))
17761782
{
17771783
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
1778-
// It is possible that the length changed due to the callback performed above.
1779-
uint32_t array_length = ext_obj_p->u.array.length;
17801784

1781-
if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE
1782-
&& array_length > 0)
1785+
if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE)
17831786
{
1787+
if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL))
1788+
{
1789+
return ecma_make_integer_value (-1);
1790+
}
1791+
1792+
len = JERRY_MIN (ext_obj_p->u.array.length, len);
1793+
17841794
ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp);
17851795

17861796
while (from_idx < len)
@@ -2294,9 +2304,14 @@ ecma_builtin_array_prototype_fill (ecma_value_t value, /**< value */
22942304
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
22952305

22962306
if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE
2297-
&& len != 0
22982307
&& ecma_op_ordinary_object_is_extensible (obj_p))
22992308
{
2309+
if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL))
2310+
{
2311+
ecma_ref_object (obj_p);
2312+
return ecma_make_object_value (obj_p);
2313+
}
2314+
23002315
ecma_value_t *buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp);
23012316

23022317
while (k < final)

tests/jerry/array-prototype-indexof.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,33 @@ try {
8686
assert(e.message === "foo");
8787
assert(e instanceof ReferenceError);
8888
}
89+
90+
// Remove the buffer
91+
var array = [1, 2, 3, 4, 5];
92+
var value = array.indexOf(4, {
93+
valueOf: function() {
94+
array.length = 0;
95+
}
96+
})
97+
98+
assert(value === -1);
99+
100+
// Extend the buffer
101+
var array = [1, 2, 3];
102+
var value = array.indexOf(2, {
103+
valueOf: function() {
104+
array.length = 5;
105+
}
106+
})
107+
108+
assert(value === 1);
109+
110+
// Reduce the buffer
111+
var array = [1, 2, 3, 4, 5, 6, 7];
112+
var value = array.indexOf(6, {
113+
valueOf: function() {
114+
array.length = 5;
115+
}
116+
})
117+
118+
assert(value === -1);

tests/jerry/array-prototype-lastindexof.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,33 @@ try {
6969
assert(e.message === "foo");
7070
assert(e instanceof ReferenceError);
7171
}
72+
73+
// Remove the buffer
74+
var array = [1, 2, 3, 4, 5];
75+
var value = array.lastIndexOf(4, {
76+
valueOf: function() {
77+
array.length = 0;
78+
}
79+
})
80+
81+
assert(value === -1);
82+
83+
// Extend the buffer
84+
var array = [1, 2, 3];
85+
var value = array.lastIndexOf(1, {
86+
valueOf: function() {
87+
array.length = 5;
88+
}
89+
})
90+
91+
assert(value === 0);
92+
93+
// Reduce the buffer
94+
var array = [1, 2, 3, 4, 5, 6, 7];
95+
var value = array.indexOf(5, {
96+
valueOf: function() {
97+
array.length = 2;
98+
}
99+
})
100+
101+
assert(value === -1);

tests/jerry/array-prototype-slice.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,41 @@ try {
151151
assert (e.message === "foo");
152152
assert (e instanceof ReferenceError);
153153
}
154+
155+
function array_check(result_array, expected_array) {
156+
assert(result_array instanceof Array);
157+
assert(result_array.length === expected_array.length);
158+
for (var idx = 0; idx < expected_array.length; idx++) {
159+
assert(result_array[idx] === expected_array[idx]);
160+
}
161+
}
162+
163+
// Remove the buffer
164+
var array = [1, 2, 3, 4, 5];
165+
var value = array.slice(4, {
166+
valueOf: function() {
167+
array.length = 0;
168+
}
169+
})
170+
171+
array_check(value, []);
172+
173+
// Extend the buffer
174+
var array = [1, 2, 3, 4, 5];
175+
var value = array.slice(6, {
176+
valueOf: function() {
177+
array.length = 10;
178+
}
179+
})
180+
181+
array_check(value, []);
182+
183+
// Reduce the buffer
184+
var array = [1, 2, 3, 4, 5];
185+
var value = array.slice(1, {
186+
valueOf: function() {
187+
array.length = 3;
188+
}
189+
})
190+
191+
array_check(value, []);

tests/jerry/es2015/array-prototype-copywithin.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,41 @@ var obj = { '0' : 2, '2' : "foo", length : 3, copyWithin : Array.prototype.copyW
7979
obj.copyWithin(1);
8080
assert(obj[0] === 2);
8181
assert(obj[1] === 2);
82+
83+
function array_check(result_array, expected_array) {
84+
assert(result_array instanceof Array);
85+
assert(result_array.length === expected_array.length);
86+
for (var idx = 0; idx < expected_array.length; idx++) {
87+
assert(result_array[idx] === expected_array[idx]);
88+
}
89+
}
90+
91+
// Remove the buffer
92+
var array = [1, 2, 3];
93+
var value = array.copyWithin(0, {
94+
valueOf: function() {
95+
array.length = 0;
96+
}
97+
})
98+
99+
array_check(value, []);
100+
101+
// Extend the buffer
102+
var array = [1, 2, 3];
103+
var value = array.copyWithin(1, {
104+
valueOf: function() {
105+
array.length = 6;
106+
}
107+
})
108+
109+
array_check(value, [1, 1, 2, undefined, undefined, undefined]);
110+
111+
// Reduce the buffer
112+
var array = [1, 2, 3, 4, 5, 6, 7];
113+
var value = array.copyWithin(4, 2, {
114+
valueOf: function() {
115+
array.length = 3;
116+
}
117+
})
118+
119+
array_check(value, [1, 2, 3]);

tests/jerry/es2015/array-prototype-fill.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,42 @@ function TestFillFrozenObject () {
177177
}
178178
}
179179
TestFillFrozenObject ();
180+
181+
function array_check(result_array, expected_array) {
182+
assert(result_array instanceof Array);
183+
assert(result_array.length === expected_array.length);
184+
for (var idx = 0; idx < expected_array.length; idx++) {
185+
assert(result_array[idx] === expected_array[idx]);
186+
}
187+
}
188+
189+
190+
// Remove the buffer
191+
var array = [1, 2, 3, 4, 5];
192+
var value = array.fill(2, 0, {
193+
valueOf: function() {
194+
array.length = 0;
195+
}
196+
})
197+
198+
array_check(value, []);
199+
200+
// Extend the buffer
201+
var array = [1, 2, 3];
202+
var value = array.fill(1, {
203+
valueOf: function() {
204+
array.length = 6;
205+
}
206+
})
207+
208+
array_check(value, [1, 1, 1, undefined, undefined, undefined]);
209+
210+
// Reduce the buffer
211+
var array = [1, 2, 3, 4, 5, 6, 7];
212+
var value = array.fill(4, {
213+
valueOf: function() {
214+
array.length = 3;
215+
}
216+
})
217+
218+
array_check(value, [4, 4, 4]);

0 commit comments

Comments
 (0)