Add missing isArray checks based on the ES11 standard (#3983)

Added checks to the following methods:
- ecma_builtin_json_stringify, ECMA-262 v11, 24.5.2
- ecma_builtin_json_internalize_property, ECMA-262 v11, 24.5.1.1

Fixes #3945
Fixes #3950

JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
This commit is contained in:
Szilagyi Adam 2020-07-10 16:06:27 +02:00 committed by GitHub
parent b90fa63255
commit dfabfe7a56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 217 additions and 91 deletions

View File

@ -602,7 +602,11 @@ ecma_builtin_json_parse_value (ecma_json_token_t *token_p) /**< token argument *
} /* ecma_builtin_json_parse_value */ } /* ecma_builtin_json_parse_value */
/** /**
* Abstract operation InternalizeJSONProperty defined in 24.3.1.1 * Abstract operation InternalizeJSONProperty
*
* See also:
* ECMA-262 v5, 24.3.1.1
* ECMA-262 v11, 24.5.1.1
* *
* @return ecma value * @return ecma value
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
@ -628,10 +632,72 @@ ecma_builtin_json_internalize_property (ecma_object_t *reviver_p, /**< reviver f
/* 3. */ /* 3. */
if (ecma_is_value_object (value)) if (ecma_is_value_object (value))
{ {
/* 3.a */
ecma_value_t is_array = ecma_is_value_array (value);
#if ENABLED (JERRY_ESNEXT)
if (ECMA_IS_VALUE_ERROR (is_array))
{
ecma_free_value (value);
return is_array;
}
#endif /* ENABLED (JERRY_ESNEXT) */
ecma_object_t *object_p = ecma_get_object_from_value (value); ecma_object_t *object_p = ecma_get_object_from_value (value);
/* 3.c */
if (ecma_is_value_true (is_array))
{
/* 3.c.ii */
uint32_t len;
ecma_value_t to_len = ecma_op_object_get_length (object_p, &len);
/* 3.c.iii */
if (ECMA_IS_VALUE_ERROR (to_len))
{
ecma_deref_object (object_p);
return to_len;
}
/* 3.c.iv */
for (uint32_t i = 0; i < len; i++)
{
ecma_string_t *prop_index = ecma_new_ecma_string_from_uint32 (i);
ecma_value_t new_element = ecma_builtin_json_internalize_property (reviver_p, object_p, prop_index);
if (ECMA_IS_VALUE_ERROR (new_element))
{
ecma_deref_ecma_string (prop_index);
ecma_deref_object (object_p);
return new_element;
}
if (ecma_is_value_undefined (new_element))
{
ecma_value_t delete_val = ecma_op_object_delete_by_uint32_index (object_p,
i,
false);
JERRY_ASSERT (ecma_is_value_boolean (delete_val));
}
else
{
ecma_builtin_json_define_value_property (object_p,
prop_index,
new_element);
ecma_free_value (new_element);
}
ecma_deref_ecma_string (prop_index);
}
}
/* 3.d */
else
{
ecma_collection_t *props_p = ecma_op_object_get_property_names (object_p, ECMA_LIST_ENUMERABLE); ecma_collection_t *props_p = ecma_op_object_get_property_names (object_p, ECMA_LIST_ENUMERABLE);
JERRY_ASSERT (props_p != NULL);
ecma_value_t *buffer_p = props_p->buffer_p; ecma_value_t *buffer_p = props_p->buffer_p;
/* 3.d.iii */ /* 3.d.iii */
@ -671,6 +737,7 @@ ecma_builtin_json_internalize_property (ecma_object_t *reviver_p, /**< reviver f
ecma_collection_free (props_p); ecma_collection_free (props_p);
} }
}
ecma_value_t arguments_list[2]; ecma_value_t arguments_list[2];
arguments_list[0] = ecma_make_string_value (name_p); arguments_list[0] = ecma_make_string_value (name_p);
@ -1379,6 +1446,7 @@ ecma_builtin_json_stringify_no_opts (const ecma_value_t value) /**< value to str
* *
* See also: * See also:
* ECMA-262 v5, 15.12.3 * ECMA-262 v5, 15.12.3
* ECMA-262 v11, 24.5.2
* *
* @return ecma value * @return ecma value
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
@ -1406,11 +1474,29 @@ ecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */
context.replacer_function_p = obj_p; context.replacer_function_p = obj_p;
} }
/* 4.b */ /* 4.b */
else if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY) else
{ {
ecma_value_t is_array = ecma_is_value_array (arg2);
#if ENABLED (JERRY_ESNEXT)
if (ECMA_IS_VALUE_ERROR (is_array))
{
return is_array;
}
#endif /* ENABLED (JERRY_ESNEXT) */
if (ecma_is_value_true (is_array))
{
uint32_t array_length;
ecma_value_t to_len = ecma_op_object_get_length (obj_p, &array_length);
if (ECMA_IS_VALUE_ERROR (to_len))
{
return to_len;
}
context.property_list_p = ecma_new_collection (); context.property_list_p = ecma_new_collection ();
ecma_extended_object_t *array_object_p = (ecma_extended_object_t *) obj_p;
uint32_t array_length = array_object_p->u.array.length;
uint32_t index = 0; uint32_t index = 0;
/* 4.b.iii.5 */ /* 4.b.iii.5 */
@ -1483,6 +1569,7 @@ ecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */
} }
} }
} }
}
ecma_value_t space; ecma_value_t space;

View File

@ -0,0 +1,19 @@
// 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.
function a() {
this[2] = { b : new Proxy(Function, {}) }
}
JSON.parse("[1, 2, []]", a);

View File

@ -0,0 +1,20 @@
// 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.
function a() {
this[2] = new Proxy(new function() { return new Array }, {})
return {}
}
JSON.parse("[1, 2, []]", a);