Browse Source

Draft: hiding internal props from Ecmascript code

Draft of an approach where internal properties are hidden from user
Ecmascript code even when the correct (internal) key is used.
Internal properties can only be accessed using the C API, which
should fulfill sandboxing requirements for protecting the internal
properties securely.
pull/979/head
Sami Vaarala 10 years ago
parent
commit
855c36f8a9
  1. 20
      src-input/duk_api_object.c
  2. 2
      src-input/duk_bi_json.c
  3. 4
      src-input/duk_bi_reflect.c
  4. 13
      src-input/duk_hobject.h
  5. 107
      src-input/duk_hobject_props.c
  6. 4
      src-input/duk_hthread_builtins.c
  7. 16
      src-input/duk_js_executor.c
  8. 3
      src-input/duk_js_ops.c
  9. 10
      src-input/duk_js_var.c

20
src-input/duk_api_object.c

@ -27,7 +27,7 @@ DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_idx) {
tv_obj = duk_require_tval(ctx, obj_idx);
tv_key = duk_require_tval(ctx, -1);
rc = duk_hobject_getprop(thr, tv_obj, tv_key);
rc = duk_hobject_getprop(thr, tv_obj, tv_key, DUK_PROP_FLAG_INTERNAL /*flags*/);
DUK_ASSERT(rc == 0 || rc == 1);
/* a value is left on stack regardless of rc */
@ -96,7 +96,7 @@ DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_context *ctx, duk_idx_t obj_idx, d
duk_tval *tv_obj;
duk_tval *tv_key;
duk_tval *tv_val;
duk_small_int_t throw_flag;
duk_small_uint_t flags;
duk_bool_t rc;
/* Note: copying tv_obj and tv_key to locals to shield against a valstack
@ -112,9 +112,11 @@ DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_context *ctx, duk_idx_t obj_idx, d
tv_obj = duk_require_tval(ctx, obj_idx);
tv_key = duk_require_tval(ctx, idx_key);
tv_val = duk_require_tval(ctx, idx_key ^ 1);
throw_flag = duk_is_strict_call(ctx);
DUK_ASSERT(DUK_PROP_FLAG_THROW == 1); /* duk_is_strict_call() -> throw flag */
DUK_ASSERT(duk_is_strict_call(ctx) == 0 || duk_is_strict_call(ctx) == 1);
flags = duk_is_strict_call(ctx) | DUK_PROP_FLAG_INTERNAL;
rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, flags);
DUK_ASSERT(rc == 0 || rc == 1);
duk_pop_2(ctx); /* remove key and value */
@ -173,7 +175,7 @@ DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_idx) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_tval *tv_obj;
duk_tval *tv_key;
duk_small_int_t throw_flag;
duk_small_uint_t flags;
duk_bool_t rc;
DUK_ASSERT_CTX_VALID(ctx);
@ -184,9 +186,11 @@ DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_idx) {
tv_obj = duk_require_tval(ctx, obj_idx);
tv_key = duk_require_tval(ctx, -1);
throw_flag = duk_is_strict_call(ctx);
DUK_ASSERT(DUK_PROP_FLAG_THROW == 1); /* duk_is_strict_call() -> throw flag */
DUK_ASSERT(duk_is_strict_call(ctx) == 0 || duk_is_strict_call(ctx) == 1);
flags = duk_is_strict_call(ctx) | DUK_PROP_FLAG_INTERNAL;
rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
rc = duk_hobject_delprop(thr, tv_obj, tv_key, flags);
DUK_ASSERT(rc == 0 || rc == 1);
duk_pop(ctx); /* remove key */
@ -247,7 +251,7 @@ DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_idx) {
tv_obj = duk_require_tval(ctx, obj_idx);
tv_key = duk_require_tval(ctx, -1);
rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
rc = duk_hobject_hasprop(thr, tv_obj, tv_key, DUK_PROP_FLAG_INTERNAL /*flags*/);
DUK_ASSERT(rc == 0 || rc == 1);
duk_pop(ctx); /* remove key */

2
src-input/duk_bi_json.c

@ -1949,7 +1949,7 @@ DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_hold
DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
tv_key = DUK_GET_TVAL_NEGIDX(ctx, -1);
DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
(void) duk_hobject_getprop(thr, tv_holder, tv_key);
(void) duk_hobject_getprop(thr, tv_holder, tv_key, 0 /*flags*/); /* FIXME: allow internal? */
/* -> [ ... key val ] */

4
src-input/duk_bi_reflect.c

@ -53,7 +53,7 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx) {
DUK_ASSERT(thr != NULL);
tv_obj = DUK_GET_TVAL_POSIDX(ctx, 0);
tv_key = DUK_GET_TVAL_POSIDX(ctx, 1);
(void) duk_hobject_getprop(thr, tv_obj, tv_key); /* This could also be a duk_get_prop(). */
(void) duk_hobject_getprop(thr, tv_obj, tv_key, 0 /*flags*/); /* This could also be a duk_get_prop(). */
return 1;
}
@ -73,7 +73,7 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx) {
DUK_ASSERT(thr != NULL);
tv_obj = DUK_GET_TVAL_POSIDX(ctx, 0);
tv_key = DUK_GET_TVAL_POSIDX(ctx, 1);
ret = duk_hobject_hasprop(thr, tv_obj, tv_key);
ret = duk_hobject_hasprop(thr, tv_obj, tv_key, 0 /*flags*/);
duk_push_boolean(ctx, ret);
return 1;
}

13
src-input/duk_hobject.h

@ -873,14 +873,15 @@ DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_
duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
/* core property functions */
DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
#define DUK_PROP_FLAG_THROW (1 << 0)
#define DUK_PROP_FLAG_FORCE (1 << 1)
#define DUK_PROP_FLAG_INTERNAL (1 << 2) /* allow access to internal keys */
DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_small_uint_t flags);
/* internal property functions */
#define DUK_DELPROP_FLAG_THROW (1 << 0)
#define DUK_DELPROP_FLAG_FORCE (1 << 1)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);

107
src-input/duk_hobject_props.c

@ -107,7 +107,7 @@ DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
dbl = DUK_TVAL_GET_NUMBER(tv);
idx = (duk_uint32_t) dbl;
if ((duk_double_t) idx == dbl) {
/* Is whole and within 32 bit range. If the value happens to be 0xFFFFFFFF,
/* Is whole and within 32 bit range. If the value happens to be 0xFFFFFFFF,
* it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
*/
return idx;
@ -1669,6 +1669,23 @@ DUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *ob
if (out_desc->e_idx >= 0) {
duk_int_t e_idx = out_desc->e_idx;
out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
#if 0
/* FIXME: this would impact all prototype lookup steps but
* fixes Object.defineProperty() etc automatically.
*/
if (DUK_HSTRING_HAS_INTERNAL(key)) {
DUK_DDD(DUK_DDDPRINT("-> internal property, pretend 'undefined' and protected"));
if (flags & DUK__DESC_FLAG_PUSH_VALUE) {
duk_push_undefined(ctx);
}
out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE | /* E5 Section 15.5.5.2 */
DUK_PROPDESC_FLAG_VIRTUAL;
return 1;
}
#endif
if (out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR) {
DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
@ -2276,7 +2293,7 @@ DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hob
* GETPROP: Ecmascript property read.
*/
DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_small_uint_t flags) {
duk_context *ctx = (duk_context *) thr;
duk_tval tv_obj_copy;
duk_tval tv_key_copy;
@ -2285,6 +2302,9 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
duk_propdesc desc;
duk_uint_t sanity;
duk_bool_t internal_flag;
internal_flag = (flags & DUK_PROP_FLAG_INTERNAL);
DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
(void *) thr, (void *) tv_obj, (void *) tv_key,
@ -2447,6 +2467,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
DUK_ASSERT(key != NULL);
/* FIXME: internal property check */
if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
duk_tval *tv_hook = duk_require_tval(ctx, -3); /* value from hook */
duk_tval *tv_targ = duk_require_tval(ctx, -1); /* value from target */
@ -2647,6 +2668,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(curr != NULL);
DUK_ASSERT(key != NULL);
/* FIXME: this applies to the "front end" of a property lookup */
if (DUK_HSTRING_HAS_INTERNAL(key) && !internal_flag) {
DUK_DDD(DUK_DDDPRINT("-> internal property, pretend 'undefined' and protected"));
goto not_found;
}
sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
do {
if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
@ -2700,6 +2727,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
* Not found
*/
not_found:
duk_to_undefined(ctx, -1); /* [key] -> [undefined] (default value) */
DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(ctx, -1)));
@ -2780,7 +2808,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj,
* the target object.
*/
DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_small_uint_t flags) {
duk_context *ctx = (duk_context *) thr;
duk_tval tv_key_copy;
duk_hobject *obj;
@ -2788,6 +2816,9 @@ DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj,
duk_uint32_t arr_idx;
duk_bool_t rc;
duk_propdesc desc;
duk_bool_t internal_flag;
internal_flag = (flags & DUK_PROP_FLAG_INTERNAL);
DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
(void *) thr, (void *) tv_obj, (void *) tv_key,
@ -2853,6 +2884,13 @@ DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj,
DUK_ASSERT(obj != NULL);
DUK_UNREF(arr_idx);
/* FIXME: this applies to the "front end" of a property lookup */
if (DUK_HSTRING_HAS_INTERNAL(key) && !internal_flag) {
DUK_DDD(DUK_DDDPRINT("-> internal property, pretend 'undefined' and protected"));
rc = 0;
goto pop_and_return;
}
#if defined(DUK_USE_ES6_PROXY)
if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
duk_hobject *h_target;
@ -3166,7 +3204,7 @@ duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
* The delete always succeeds: key has no exotic behavior, property
* is configurable, and no resize occurs.
*/
rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_PROP_FLAG_FORCE : 0);
DUK_UNREF(rc);
DUK_ASSERT(rc != 0);
}
@ -3292,7 +3330,7 @@ DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject
* (We currently make a copy of all of the input values to avoid issues.)
*/
DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag) {
DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_small_uint_t flags) {
duk_context *ctx = (duk_context *) thr;
duk_tval tv_obj_copy;
duk_tval tv_key_copy;
@ -3307,11 +3345,16 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
duk_int_t e_idx;
duk_uint_t sanity;
duk_uint32_t new_array_length = 0; /* 0 = no update */
duk_bool_t throw_flag;
duk_bool_t internal_flag;
DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
throw_flag = (flags & DUK_PROP_FLAG_THROW);
internal_flag = (flags & DUK_PROP_FLAG_INTERNAL);
DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, flags=%lx "
"(obj -> %!T, key -> %!T, val -> %!T)",
(void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
(long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
(unsigned long) flags, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->heap != NULL);
@ -3460,6 +3503,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
DUK_ASSERT(key != NULL);
/* FIXME: internal key check */
if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
duk_tval *tv_targ = duk_require_tval(ctx, -1);
duk_bool_t datadesc_reject;
@ -3619,6 +3663,12 @@ DUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj,
lookup:
/* FIXME: this applies to the "front end" of a property lookup */
if (DUK_HSTRING_HAS_INTERNAL(key) && !internal_flag) {
DUK_DDD(DUK_DDDPRINT("-> internal property, pretend 'undefined' and protected"));
goto fail_not_writable;
}
/*
* Check whether the property already exists in the prototype chain.
* Note that the actual write goes into the original base object
@ -4217,8 +4267,10 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o
duk_bool_t throw_flag;
duk_bool_t force_flag;
throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
/* FIXME: this always allows internal property deletion */
throw_flag = (flags & DUK_PROP_FLAG_THROW);
force_flag = (flags & DUK_PROP_FLAG_FORCE);
DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
(void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
@ -4360,7 +4412,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *o
* DELPROP: Ecmascript property deletion.
*/
DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_small_uint_t flags) {
duk_context *ctx = (duk_context *) thr;
duk_hstring *key = NULL;
#if defined(DUK_USE_ES6_PROXY)
@ -4369,6 +4421,11 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
duk_int_t entry_top;
duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
duk_bool_t rc;
duk_bool_t throw_flag;
duk_bool_t internal_flag;
throw_flag = (flags & DUK_PROP_FLAG_THROW);
internal_flag = (flags & DUK_PROP_FLAG_INTERNAL);
DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
(void *) thr, (void *) tv_obj, (void *) tv_key,
@ -4401,6 +4458,15 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
DUK_ASSERT(obj != NULL);
arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
DUK_ASSERT(key != NULL);
/* FIXME: this applies to the "front end" of a property lookup */
if (DUK_HSTRING_HAS_INTERNAL(key) && !internal_flag) {
DUK_DDD(DUK_DDDPRINT("-> internal property, pretend 'undefined' and protected"));
goto fail_not_configurable;
}
#if defined(DUK_USE_ES6_PROXY)
if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
duk_hobject *h_target;
@ -4423,7 +4489,6 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
/* Target object must be checked for a conflicting
* non-configurable property.
*/
arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
DUK_ASSERT(key != NULL);
if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
@ -4451,8 +4516,7 @@ DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj,
key = duk_to_hstring(ctx, -1);
DUK_ASSERT(key != NULL);
rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_PROP_FLAG_THROW : 0);
goto done_rc;
} else if (DUK_TVAL_IS_STRING(tv_obj)) {
/* XXX: unnecessary string coercion for array indices,
@ -4751,7 +4815,7 @@ DUK_INTERNAL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk
DUK_GET_TVAL_NEGIDX(ctx, -3),
DUK_GET_TVAL_NEGIDX(ctx, -2),
DUK_GET_TVAL_NEGIDX(ctx, -1),
0);
0 /*flags*/);
duk_pop_n(ctx, 3);
}
@ -4776,7 +4840,8 @@ DUK_INTERNAL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *
duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH);
(void) duk_hobject_getprop(thr,
DUK_GET_TVAL_NEGIDX(ctx, -2),
DUK_GET_TVAL_NEGIDX(ctx, -1));
DUK_GET_TVAL_NEGIDX(ctx, -1),
0 /*flags*/);
val = duk_to_number(ctx, -1);
duk_pop_n(ctx, 3);
@ -4807,6 +4872,8 @@ DUK_INTERNAL duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_contex
obj = duk_require_hobject_promote_mask(ctx, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
key = duk_to_hstring(ctx, 1);
/* FIXME: internal key check */
DUK_ASSERT(obj != NULL);
DUK_ASSERT(key != NULL);
@ -5037,6 +5104,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_context *ctx,
duk_bool_t is_configurable;
duk_bool_t is_writable;
duk_bool_t force_flag;
duk_bool_t internal_flag;
duk_small_uint_t new_flags;
duk_propdesc curr;
duk_uint32_t arridx_new_array_length; /* != 0 => post-update for array 'length' (used when key is an array index) */
@ -5065,6 +5133,7 @@ duk_bool_t duk_hobject_define_property_helper(duk_context *ctx,
is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
internal_flag = force_flag; /* FIXME: separate flag? */
arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
@ -5088,6 +5157,12 @@ duk_bool_t duk_hobject_define_property_helper(duk_context *ctx,
(long) has_set, (void *) set, (duk_heaphdr *) set,
(long) arr_idx, (long) throw_flag));
/* FIXME: this applies to the "front end" of a property lookup */
if (DUK_HSTRING_HAS_INTERNAL(key) && !internal_flag) {
DUK_DDD(DUK_DDDPRINT("-> internal property, pretend 'undefined' and protected"));
goto fail_not_configurable;
}
/*
* Array exotic behaviors can be implemented at this point. The local variables
* are essentially a 'value copy' of the input descriptor (Desc), which is modified
@ -5906,6 +5981,8 @@ DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_
h_v = duk_to_hstring(ctx, 0);
DUK_ASSERT(h_v != NULL);
/* FIXME: internal key check */
h_obj = duk_push_this_coercible_to_object(ctx);
DUK_ASSERT(h_obj != NULL);

4
src-input/duk_hthread_builtins.c

@ -666,12 +666,12 @@ DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
#if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_PROP_FLAG_THROW);
#endif
#if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_PROP_FLAG_THROW);
#endif
/* XXX: relocate */

16
src-input/duk_js_executor.c

@ -3518,7 +3518,7 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
tv_obj = DUK__REGCONSTP_B(ins);
tv_key = DUK__REGCONSTP_C(ins);
rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
rc = duk_hobject_getprop(thr, tv_obj, tv_key, 0 /*flags*/); /* -> [val] */
DUK_UNREF(rc); /* ignore */
tv_obj = NULL; /* invalidated */
tv_key = NULL; /* invalidated */
@ -3541,7 +3541,9 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
DUK_ASSERT(tv_val != NULL);
tv_obj = DUK__REGCONSTP_B(ins);
tv_key = DUK__REGCONSTP_C(ins);
rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
DUK_ASSERT(DUK_PROP_FLAG_THROW == 1); /* DUK__STRICT() -> throw flag */
DUK_ASSERT(DUK__STRICT() == 0 || DUK__STRICT() == 1);
rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT() /*flags*/);
DUK_UNREF(rc); /* ignore */
tv_obj = NULL; /* invalidated */
tv_key = NULL; /* invalidated */
@ -3567,7 +3569,7 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
* B -> object reg/const (may be const e.g. in "'foo'[1]") \
* C -> key reg/const \
*/ \
(void) duk_hobject_getprop(thr, (barg), (carg)); \
(void) duk_hobject_getprop(thr, (barg), (carg), 0 /*flags*/); \
DUK__REPLACE_TOP_A_BREAK(); \
}
#define DUK__PUTPROP_BODY(aarg,barg,carg) { \
@ -3578,7 +3580,9 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
* Note: intentional difference to register arrangement \
* of e.g. GETPROP; 'A' must contain a register-only value. \
*/ \
(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
DUK_ASSERT(DUK_PROP_FLAG_THROW == 1); /* DUK__STRICT() -> throw flag */ \
DUK_ASSERT(DUK__STRICT() == 0 || DUK__STRICT() == 1); \
(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT() /*flags*/); \
break; \
}
#define DUK__DELPROP_BODY(barg,carg) { \
@ -3587,7 +3591,9 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
* C -> key reg/const \
*/ \
duk_bool_t rc; \
rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \
DUK_ASSERT(DUK_PROP_FLAG_THROW == 1); /* DUK__STRICT() -> throw flag */\
DUK_ASSERT(DUK__STRICT() == 0 || DUK__STRICT() == 1); \
rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT() /*flags*/); \
DUK_ASSERT(rc == 0 || rc == 1); \
DUK__REPLACE_BOOL_A_BREAK(rc); \
}

3
src-input/duk_js_ops.c

@ -1192,7 +1192,8 @@ DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv
retval = duk_hobject_hasprop(thr,
DUK_GET_TVAL_NEGIDX(ctx, -1),
DUK_GET_TVAL_NEGIDX(ctx, -2));
DUK_GET_TVAL_NEGIDX(ctx, -2),
0 /*flags*/);
duk_pop_2(ctx);
return retval;

10
src-input/duk_js_var.c

@ -1082,14 +1082,14 @@ duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
DUK_ASSERT(name != NULL);
DUK_TVAL_SET_STRING(&tv_name, name);
found = duk_hobject_hasprop(thr, tv_target, &tv_name);
found = duk_hobject_hasprop(thr, tv_target, &tv_name, 0 /*flags*/); /* FIXME: internal? */
} else {
/* XXX: duk_hobject_hasprop() would be correct for
* non-Proxy objects too, but it is about ~20-25%
* slower at present so separate code paths for
* Proxy and non-Proxy now.
*/
found = duk_hobject_hasprop_raw(thr, target, name);
found = duk_hobject_hasprop_raw(thr, target, name); /* FIXME: internal? */
}
if (found) {
@ -1245,7 +1245,7 @@ duk_bool_t duk__getvar_helper(duk_hthread *thr,
DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
DUK_TVAL_SET_STRING(&tv_tmp_key, name);
(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key); /* [this value] */
(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key, 0 /*flags*/); /* [this value] */
/* ref.value, ref.this.binding invalidated here by getprop call */
@ -1364,6 +1364,8 @@ void duk__putvar_helper(duk_hthread *thr,
DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
DUK_TVAL_SET_STRING(&tv_tmp_key, name);
DUK_ASSERT(DUK_PROP_FLAG_THROW == 1); /* strict -> throw flag */
DUK_ASSERT(strict == 0 || strict == 1);
(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);
/* ref.value and ref.this_binding invalidated here */
@ -1388,7 +1390,7 @@ void duk__putvar_helper(duk_hthread *thr,
DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
DUK_TVAL_SET_STRING(&tv_tmp_key, name);
(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0); /* 0 = no throw */
(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0 /*flags*/); /* 0 = no throw */
/* NB: 'val' may be invalidated here because put_value may realloc valstack,
* caller beware.

Loading…
Cancel
Save