Browse Source

Merge pull request #1516 from svaarala/fix-dump-function-template-length

Fix duk_dump_function() .length handling when _Formals omitted
pull/1494/merge
Sami Vaarala 8 years ago
committed by GitHub
parent
commit
0035404cb8
  1. 4
      RELEASES.rst
  2. 80
      src-input/duk_api_bytecode.c
  3. 2
      tests/api/test-dump-load-basic.c

4
RELEASES.rst

@ -2856,6 +2856,10 @@ Planned
"collapse" bound function chains so that the target of a duk_hboundfunc is
always a non-bound function (GH-1503)
* Fix incorrect .length behavior for function templates loaded by
duk_load_function(), caused by not distinguishing between a missing and a
zero length _Formals array (GH-1513, GH-1516)
* Fix missing duk_require_stack() in bound function call handling which caused
calls to bound functions with a lot of bound arguments to fail with a value
stack limit error (GH-1504)

80
src-input/duk_api_bytecode.c

@ -19,6 +19,7 @@
#define DUK__SER_STRING 0x00
#define DUK__SER_NUMBER 0x01
#define DUK__BYTECODE_INITIAL_ALLOC 256
#define DUK__NO_FORMALS 0xffffffffUL
/*
* Dump/load helpers, xxx_raw() helpers do no buffer checks
@ -183,40 +184,44 @@ DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_b
tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));
if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
duk_hobject *h;
duk_uint_fast32_t i;
duk_harray *h;
duk_uint32_t i;
h = DUK_TVAL_GET_OBJECT(tv);
/* Here we rely on _Formals being a dense array containing
* strings. This should be the case unless _Formals has been
* tweaked by the application (which we don't support right
* now).
*/
h = (duk_harray *) DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(h != NULL);
DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
/* We know _Formals is dense and all entries will be in the
* array part. GC and finalizers shouldn't affect _Formals
* so side effects should be fine.
*/
for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
DUK_ASSERT(h->length != DUK__NO_FORMALS); /* limits */
DUK_RAW_WRITE_U32_BE(p, h->length);
for (i = 0; i < h->length; i++) {
duk_tval *tv_val;
duk_hstring *varname;
tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i);
tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, (duk_hobject *) h, i);
DUK_ASSERT(tv_val != NULL);
if (DUK_TVAL_IS_STRING(tv_val)) {
/* Array is dense and contains only strings, but ASIZE may
* be larger than used part and there are UNUSED entries.
*/
varname = DUK_TVAL_GET_STRING(tv_val);
DUK_ASSERT(varname != NULL);
DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1); /* won't be confused with terminator */
DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(varname), p);
p = duk__dump_hstring_raw(p, varname);
}
DUK_ASSERT(DUK_TVAL_IS_STRING(tv_val));
varname = DUK_TVAL_GET_STRING(tv_val);
DUK_ASSERT(varname != NULL);
DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);
DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(varname), p);
p = duk__dump_hstring_raw(p, varname);
}
} else {
DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit empty list"));
DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
DUK_RAW_WRITE_U32_BE(p, DUK__NO_FORMALS); /* marker: no formals */
}
p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Formals */
return p;
}
@ -394,6 +399,7 @@ static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t
duk_idx_t idx_base;
duk_tval *tv1;
duk_uarridx_t arr_idx;
duk_uarridx_t arr_limit;
duk_hobject *func_env;
duk_bool_t need_pop;
@ -659,26 +665,20 @@ static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t
duk_compact_m1(ctx);
duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
/* If _Formals wasn't present in the original function, the list
* here will be empty. Same happens if _Formals was present but
* had zero length. We can omit _Formals from the result if its
* length is zero and matches nargs.
/* _Formals may have been missing in the original function, which is
* handled using a marker length.
*/
duk_push_array(ctx); /* _Formals */
for (arr_idx = 0; ; arr_idx++) {
/* XXX: awkward */
p = duk__load_string_raw(ctx, p);
if (duk_get_length(ctx, -1) == 0) {
duk_pop(ctx);
break;
arr_limit = DUK_RAW_READ_U32_BE(p);
if (arr_limit != DUK__NO_FORMALS) {
duk_push_array(ctx); /* _Formals */
for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
p = duk__load_string_raw(ctx, p);
duk_put_prop_index(ctx, -2, arr_idx);
}
duk_put_prop_index(ctx, -2, arr_idx);
}
if (arr_idx == 0 && h_fun->nargs == 0) {
duk_pop(ctx);
} else {
duk_compact_m1(ctx);
duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
} else {
DUK_DD(DUK_DDPRINT("no _Formals in dumped function"));
}
/* Return with final function pushed on stack top. */

2
tests/api/test-dump-load-basic.c

@ -40,7 +40,7 @@
/*===
*** test_basic (duk_safe_call)
dump result type: 7
ff000000000e0000000300000001000900000000000100000001180008800000000600000199000103020000049c00040500000505ae8001070380020803000502b00005040000020502000103b000010000000000a100000000057072696e74000000000568656c6c6f0140091eb851eb851f000000030000000000000000000300020000000100000001180c098001000234000200a1000000a2000000020000000561646465720000000f66616b6546696c656e616d652e6a730000000d03000000010000000c000000000000000178000000000000000179000000010000000000000001780000000179000000000000000000000006676c6f62616c0000000f66616b6546696c656e616d652e6a730000000e0e000000010000000c00000000000000000000000000
ff000000000e0000000300000001000900000000000100000001180008800000000600000199000103020000049c00040500000505ae8001070380020803000502b00005040000020502000103b000010000000000a100000000057072696e74000000000568656c6c6f0140091eb851eb851f000000030000000000000000000300020000000100000001180c098001000234000200a1000000a2000000020000000561646465720000000f66616b6546696c656e616d652e6a730000000d03000000010000000c000000000000000178000000000000000179000000010000000000000002000000017800000001790000000000000006676c6f62616c0000000f66616b6546696c656e616d652e6a730000000e0e000000010000000c00000000000000000000000000
load result type: 6
hello 3 3.14
call result type: 1

Loading…
Cancel
Save