[njs] Fixed redefinition of special props in Object.defineProperty().
Dmitry Volyntsev
xeioex at nginx.com
Thu May 19 23:50:26 UTC 2022
details: https://hg.nginx.org/njs/rev/beb180165976
branches:
changeset: 1860:beb180165976
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu May 19 16:41:08 2022 -0700
description:
Fixed redefinition of special props in Object.defineProperty().
Previously, when NJS_PROPERTY_HANDLER property was updated it might be
left in inconsistent state. Namely, prop->type was left unchanged, but
prop->value did not have an expected property handler. As a result
consecutive reference to the property may result in a segment violation.
The fix is to update the prop->type during redefinition.
This closes #504 issue on Github.
diffstat:
src/njs_object.h | 4 +++-
src/njs_object_prop.c | 11 ++++++++++-
src/njs_value.c | 1 +
src/njs_value.h | 2 ++
src/test/njs_unit_test.c | 6 ++++++
5 files changed, 22 insertions(+), 2 deletions(-)
diffs (88 lines):
diff -r aa27056f4bc9 -r beb180165976 src/njs_object.h
--- a/src/njs_object.h Wed May 18 00:01:05 2022 -0700
+++ b/src/njs_object.h Thu May 19 16:41:08 2022 -0700
@@ -88,7 +88,9 @@ njs_int_t njs_object_prop_init(njs_vm_t
njs_inline njs_bool_t
njs_is_data_descriptor(njs_object_prop_t *prop)
{
- return prop->writable != NJS_ATTRIBUTE_UNSET || njs_is_valid(&prop->value);
+ return njs_is_valid(&prop->value) ||
+ prop->writable != NJS_ATTRIBUTE_UNSET ||
+ prop->type == NJS_PROPERTY_HANDLER;
}
diff -r aa27056f4bc9 -r beb180165976 src/njs_object_prop.c
--- a/src/njs_object_prop.c Wed May 18 00:01:05 2022 -0700
+++ b/src/njs_object_prop.c Thu May 19 16:41:08 2022 -0700
@@ -364,6 +364,15 @@ set_prop:
* the property's attributes to their default values.
*/
+ if (pq.temp) {
+ pq.lhq.value = NULL;
+ prop->configurable = prev->configurable;
+ prop->enumerable = prev->enumerable;
+ goto set_prop;
+ }
+
+ prev->type = prop->type;
+
if (njs_is_data_descriptor(prev)) {
njs_set_undefined(&prev->getter);
njs_set_undefined(&prev->setter);
@@ -414,7 +423,7 @@ set_prop:
done:
- if (njs_is_valid(&prop->value) || njs_is_accessor_descriptor(prop)) {
+ if (njs_is_valid(&prop->value)) {
if (prev->type == NJS_PROPERTY_HANDLER) {
if (prev->writable) {
ret = prev->value.data.u.prop_handler(vm, prev, object,
diff -r aa27056f4bc9 -r beb180165976 src/njs_value.c
--- a/src/njs_value.c Wed May 18 00:01:05 2022 -0700
+++ b/src/njs_value.c Thu May 19 16:41:08 2022 -0700
@@ -942,6 +942,7 @@ njs_external_property_query(njs_vm_t *vm
return NJS_DECLINED;
}
+ pq->temp = 1;
prop = &pq->scratch;
njs_memzero(prop, sizeof(njs_object_prop_t));
diff -r aa27056f4bc9 -r beb180165976 src/njs_value.h
--- a/src/njs_value.h Wed May 18 00:01:05 2022 -0700
+++ b/src/njs_value.h Thu May 19 16:41:08 2022 -0700
@@ -374,6 +374,7 @@ typedef struct {
njs_object_prop_t *own_whiteout;
uint8_t query;
uint8_t shared;
+ uint8_t temp;
uint8_t own;
} njs_property_query_t;
@@ -1030,6 +1031,7 @@ njs_set_object_value(njs_value_t *value,
(pq)->query = _query; \
(pq)->shared = 0; \
(pq)->own = _own; \
+ (pq)->temp = 0; \
} while (0)
diff -r aa27056f4bc9 -r beb180165976 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Wed May 18 00:01:05 2022 -0700
+++ b/src/test/njs_unit_test.c Thu May 19 16:41:08 2022 -0700
@@ -9681,6 +9681,12 @@ static njs_unit_test_t njs_test[] =
"fn(1); arr"),
njs_str("1,2,3,4,5,6") },
+ { njs_str("function f(){};"
+ "Object.defineProperty(f, 'length', {set: () => {}});"
+ "Object.defineProperty(f, 'length', {value: 42});"
+ "f.length"),
+ njs_str("42") },
+
/* Function nesting depth. */
{ njs_str("() => () => () => () => () => () => () => () => () => () => () =>"
More information about the nginx-devel
mailing list