]> git.kaiwu.me - njs.git/commitdiff
Fixed redefinition of special props in Object.defineProperty().
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 19 May 2022 23:41:08 +0000 (16:41 -0700)
committerDmitry Volyntsev <xeioex@nginx.com>
Thu, 19 May 2022 23:41:08 +0000 (16:41 -0700)
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.

src/njs_object.h
src/njs_object_prop.c
src/njs_value.c
src/njs_value.h
src/test/njs_unit_test.c

index 85d6fde7e2a72107af373b5e068fd6d1e2cccef5..219f2f89e57c8a616f43c0d151f31bdc16133f58 100644 (file)
@@ -88,7 +88,9 @@ njs_int_t njs_object_prop_init(njs_vm_t *vm, const njs_object_init_t* init,
 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;
 }
 
 
index dc1aa2158e669af4074f78959528d2219caf3ff2..74e63fc111d41ea61a6cef1ac06703831c728eae 100644 (file)
@@ -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,
index 9347d505f7f9f7d1deace69aa2ddc45949ce6f58..f0f3651e3963ef9d4f8126149daa408c0b0a30fe 100644 (file)
@@ -942,6 +942,7 @@ njs_external_property_query(njs_vm_t *vm, njs_property_query_t *pq,
         return NJS_DECLINED;
     }
 
+    pq->temp = 1;
     prop = &pq->scratch;
 
     njs_memzero(prop, sizeof(njs_object_prop_t));
index d654e1572506726961f4b6a8e300ae4dbc42623f..2ebbd0cb36d5be87a7358d391733379be79ce5c7 100644 (file)
@@ -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, njs_object_value_t *object_value)
         (pq)->query = _query;                                                 \
         (pq)->shared = 0;                                                     \
         (pq)->own = _own;                                                     \
+        (pq)->temp = 0;                                                       \
     } while (0)
 
 
index cb1c6020cb6dce7ea11e14a3f8d711af226c0240..502e3fb8de00727887505e7603a4f154a5c144a1 100644 (file)
@@ -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("() => () => () => () => () => () => () => () => () => () => () =>"