From 836cccbe8d44c00fc3bc9411f128e0ba8dd62861 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 7 Jan 2020 18:20:41 +0100 Subject: [PATCH 01/38] Add configuration support for Intel SGX enclaves --- .../DUK_USE_DATE_GET_LOCAL_TZOFFSET.yaml | 3 + .../config-options/DUK_USE_DATE_GET_NOW.yaml | 3 + config/helper-snippets/DUK_F_INTELSGX.h.in | 11 +++ config/platforms.yaml | 4 + config/platforms/platform_intelsgx.h.in | 73 +++++++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 config/helper-snippets/DUK_F_INTELSGX.h.in create mode 100644 config/platforms/platform_intelsgx.h.in diff --git a/config/config-options/DUK_USE_DATE_GET_LOCAL_TZOFFSET.yaml b/config/config-options/DUK_USE_DATE_GET_LOCAL_TZOFFSET.yaml index 572f3c4eca..b638b0a392 100644 --- a/config/config-options/DUK_USE_DATE_GET_LOCAL_TZOFFSET.yaml +++ b/config/config-options/DUK_USE_DATE_GET_LOCAL_TZOFFSET.yaml @@ -7,3 +7,6 @@ tags: description: > Mandatory macro for getting the local time offset for a given datetime, see datetime.rst. + + When used in Intel SGX enclaves it must be implemented by the enclave + developer, otherwise it will fail with a compilation error. diff --git a/config/config-options/DUK_USE_DATE_GET_NOW.yaml b/config/config-options/DUK_USE_DATE_GET_NOW.yaml index b89d9b089b..ea1caa04b2 100644 --- a/config/config-options/DUK_USE_DATE_GET_NOW.yaml +++ b/config/config-options/DUK_USE_DATE_GET_NOW.yaml @@ -13,3 +13,6 @@ description: > If the time provided experiences time jumps or doesn't advance in realtime (which is useful in some time virtualization scenarios), consider defining DUK_USE_GET_MONOTONIC_TIME. + + When used in Intel SGX enclaves it must be implemented by the enclave + developer, otherwise it will fail with a compilation error. diff --git a/config/helper-snippets/DUK_F_INTELSGX.h.in b/config/helper-snippets/DUK_F_INTELSGX.h.in new file mode 100644 index 0000000000..d292b9585c --- /dev/null +++ b/config/helper-snippets/DUK_F_INTELSGX.h.in @@ -0,0 +1,11 @@ +/** + * Automatic Intel SGX detection is not possible at compile time. + * Therefore Intel SGX enclave developers wanting to use Duktape + * should either manually specify --platform=intelsgx to configure.py + * or manually define the DUK_F_INTELSGX macro. + */ +#if defined(DUK_F_INTELSGX) +/* Trick genconfig.py that we've autodetected it. */ +#undef DUK_F_INTELSGX +#define DUK_F_INTELSGX +#endif diff --git a/config/platforms.yaml b/config/platforms.yaml index 1028374897..7faf65371f 100644 --- a/config/platforms.yaml +++ b/config/platforms.yaml @@ -31,6 +31,10 @@ autodetect: name: Durango (XboxOne) check: DUK_F_DURANGO include: platform_durango.h.in + - + name: Intel SGX # Keep this above Linux or Windows. + check: DUK_F_INTELSGX + include: platform_intelsgx.h.in - name: Windows check: DUK_F_WINDOWS diff --git a/config/platforms/platform_intelsgx.h.in b/config/platforms/platform_intelsgx.h.in new file mode 100644 index 0000000000..c0b92487de --- /dev/null +++ b/config/platforms/platform_intelsgx.h.in @@ -0,0 +1,73 @@ +#include +#include +#include +#include + +/** + * Intel SGX enclaves are completely isolated from the underlying + * kernel and therefore syscalls are not allowed by default. This + * means that getting the current time and locale information is + * impossible unless there is intervention by the enclave developers. + * + * Thus enclave developers must define DUK_USE_DATE_GET_NOW and + * DUK_USE_DATE_GET_LOCAL_TZOFFSET for their enclave either manually + * in duk_config.h or via other means (other config header, compiler + * flags). If these are not defined compilation will fail with a + * preprocessor error. + * + * DUK_USE_DATE_GET_NOW should return a duk_double_t value containing + * the current ECMASCript time. + * DUK_USE_DATE_GET_LOCAL_TZOFFSET should return a duk_int_t value + * containing the offset from UTC in seconds of the current time. + * See the datetime.rst file for more information, as well as the + * duk_bi_date.c, duk_bi_date_unix.c files for inspiration. + * + * DUK_USE_DATE_FORMAT_STRING and DUK_USE_DATE_PARSE_STRING macros are + * not mandatory and are therefore not defined here, but enclave + * developers are free to define them via duk_config.h or other means + * if they are implementing platform or locale scpecific date parsing + * and formatting. + * + * All related Duktape provided implementations regarding date and + * time are intentionally disabled. + * + * Similarly, any file I/O APIs are disabled since file I/O is not + * available in the enclave. + * + * DUK_USE_JX needs to be undefined since JX uses sscanf to parse out + * pointers from strings, and sscanf is not available in Intel SGX + * enclaves. + */ + +#undef DUK_USE_DATE_FMT_STRFTIME +#undef DUK_USE_DATE_NOW_GETTIMEOFDAY +#undef DUK_USE_DATE_NOW_TIME +#undef DUK_USE_DATE_NOW_WINDOWS +#undef DUK_USE_DATE_NOW_WINDOWS_SUBMS +#undef DUK_USE_DATE_PRS_GETDATE +#undef DUK_USE_DATE_PRS_STRPTIME +#undef DUK_USE_DATE_TZO_GMTIME +#undef DUK_USE_DATE_TZO_GMTIME_R +#undef DUK_USE_DATE_TZO_GMTIME_S +#undef DUK_USE_DATE_TZO_WINDOWS +#undef DUK_USE_DATE_TZO_WINDOWS_NO_DST + +#define DUK_SNPRINTF(a,b,c,...) _snprintf_s(a,b,b,c,__VA_ARGS__) +#define DUK_VSNPRINTF(a,b,c,...) _vsnprintf_s(a,b,b,c,__VA_ARGS__) + +#if defined(DUK_F_WINDOWS) +/* On Windows, assume we're little endian. Even Itanium which has a + * configurable endianness runs little endian in Windows. + */ +#if !defined(DUK_USE_BYTEORDER) +#define DUK_USE_BYTEORDER 1 +#endif +#endif + +#if defined(DUK_F_WINDOWS) +#define DUK_USE_OS_STRING "intelsgx-windows" +#elif defined(DUK_F_LINUX) +#define DUK_USE_OS_STRING "intelsgx-linux" +#else +#error Intel SGX is supported only on Linux or Windows. +#endif From 2521275f58c1354c271612ccffece4553fce0dad Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 7 Jan 2020 21:45:32 +0100 Subject: [PATCH 02/38] Use DUK_SNPRINTF when formatting dates --- src-input/duk_bi_date.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src-input/duk_bi_date.c b/src-input/duk_bi_date.c index 4eaaf93557..3e655e3a57 100644 --- a/src-input/duk_bi_date.c +++ b/src-input/duk_bi_date.c @@ -957,8 +957,7 @@ DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_doub return 1; } -/* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */ -DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) { +DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf, duk_size_t bufsize) { char yearstr[8]; /* "-123456\0" */ char tzstr[8]; /* "+11:22\0" */ char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE; @@ -1008,16 +1007,16 @@ DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, d * is portable. */ if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) { - DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s", + DUK_SNPRINTF((char *) out_buf, bufsize, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s", (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep, (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE], (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr); } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) { - DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d", + DUK_SNPRINTF((char *) out_buf, bufsize, "%s-%02d-%02d", (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]); } else { DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME); - DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s", + DUK_SNPRINTF((char *) out_buf, bufsize, "%02d:%02d:%02d.%03d%s", (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE], (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr); @@ -1074,7 +1073,7 @@ DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t fla /* Different calling convention than above used because the helper * is shared. */ - duk__format_parts_iso8601(parts, tzoffset, flags, buf); + duk__format_parts_iso8601(parts, tzoffset, flags, buf, sizeof(buf)); duk_push_string(thr, (const char *) buf); return 1; } From 497dd46bcfc6c7083babf7281831185d2494aa98 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 7 Jan 2020 21:47:51 +0100 Subject: [PATCH 03/38] Use DUK_SNPRINTF in JSON enc/dec --- src-input/duk_bi_json.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index efe0ad01b7..3da4a99a83 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -1419,7 +1419,7 @@ DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) { * "long long" type exists. Could also rely on C99 directly but that * won't work for older MSVC. */ - DUK_SPRINTF((char *) buf, "%lld", (long long) v); + DUK_SNPRINTF((char *) buf, sizeof(buf), "%lld", (long long) v); DUK__EMIT_CSTR(js_ctx, (const char *) buf); } #endif @@ -1591,14 +1591,14 @@ DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuff for (i = 0; i < n; i++) { duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1); q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32); - q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]); + q += DUK_SNPRINTF((char *) q, 32, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]); DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q); } } else { q = DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw); for (i = 0; i < n; i++) { q = DUK_BW_ENSURE_RAW(js_ctx->thr, &js_ctx->bw, 32, q); - q += DUK_SPRINTF((char *) q, "\"%lu\":%u,", (unsigned long) i, (unsigned int) buf[i]); + q += DUK_SNPRINTF((char *) q, 32, "\"%lu\":%u,", (unsigned long) i, (unsigned int) buf[i]); } DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q); } @@ -2749,7 +2749,7 @@ DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, du DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv)); d = DUK_TVAL_GET_DOUBLE(tv); - DUK_SPRINTF(buf, "%lg", d); + DUK_SNPRINTF(buf, sizeof(buf), "%lg", d); DUK__EMIT_CSTR(js_ctx, buf); #endif } From e12db1ee292b19f7651d4d3b5f5e15fdf93b15d1 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 7 Jan 2020 22:08:06 +0100 Subject: [PATCH 04/38] Use DUK_SNPRINTF for symbols --- src-input/duk_bi_symbol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-input/duk_bi_symbol.c b/src-input/duk_bi_symbol.c index a6c49ac2a5..e299beb505 100644 --- a/src-input/duk_bi_symbol.c +++ b/src-input/duk_bi_symbol.c @@ -50,7 +50,7 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) { if (++thr->heap->sym_counter[0] == 0) { thr->heap->sym_counter[1]++; } - p += DUK_SPRINTF((char *) p, "\xFF" "%lx-%lx", + p += DUK_SNPRINTF((char *) p, 1 + 17 + 1 /* 1 + len lost above */, "\xFF" "%lx-%lx", (unsigned long) thr->heap->sym_counter[1], (unsigned long) thr->heap->sym_counter[0]); if (desc == NULL) { From bb8427a4a31171c7700b49296c13bd548c726c3d Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 7 Jan 2020 22:17:01 +0100 Subject: [PATCH 05/38] Use DUK_SNPRINTF in numconv --- src-input/duk_numconv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-input/duk_numconv.c b/src-input/duk_numconv.c index cabc39192b..f2a312e1c4 100644 --- a/src-input/duk_numconv.c +++ b/src-input/duk_numconv.c @@ -93,12 +93,12 @@ DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) { duk_small_int_t i; /* No NUL term checks in this debug code. */ - p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n); + p += DUK_SNPRINTF(p, sizeof(buf), "%p n=%ld", (void *) x, (long) x->n); if (x->n == 0) { - p += DUK_SPRINTF(p, " 0"); + p += DUK_SNPRINTF(p, 3, " 0"); } for (i = x->n - 1; i >= 0; i--) { - p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]); + p += DUK_SNPRINTF(p, 10, " %08lx", (unsigned long) x->v[i]); } DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf)); From f69ad97a0811e27d7542fe1469f392f310a49cd7 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 7 Jan 2020 22:20:04 +0100 Subject: [PATCH 06/38] Add .ccls-cache to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index df2ce2a020..61869f8795 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,4 @@ /references/ECMA-262 5.1 edition June 2011.pdf /references/ECMA-262.pdf /tests/octane/octane +/.ccls-cache From 1d6d59f5acfe4a493a095d5f8c04a4c7465aa057 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 7 Jan 2020 22:39:50 +0100 Subject: [PATCH 07/38] Add myself to AUTHORS.rst --- AUTHORS.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index 031c6a162c..1fcfa73c41 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -108,6 +108,7 @@ bugs, provided ideas, etc; roughly in order of appearance): * Andrew Janke (https://github.com/apjanke) * Unamer (https://github.com/unamer) * Karl Dahlke (eklhad@gmail.com) +* Stojan Dimitrovski (https://github.com/hf) If you are accidentally missing from this list, send me an e-mail (``sami.vaarala@iki.fi``) and I'll fix the omission. From 0ec10b74d51a1b18aa393d76b86882f1ef1787a5 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 11 Jan 2020 20:52:49 +0100 Subject: [PATCH 08/38] Add duk_encode_pointer_cstr, duk_decode_pointer_cstr --- src-input/duk_bi_json.c | 24 +++---- src-input/duk_util_misc.c | 132 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 12 deletions(-) diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index 3da4a99a83..ad255bd0b0 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -538,6 +538,7 @@ DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) { DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; const duk_uint8_t *p; + char pcpy[DUK_MAX_POINTER_ENCODING_SIZE]; duk_small_int_t x; void *voidptr; @@ -552,6 +553,7 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { * parenthesis. */ + encsz++; if (x == DUK_ASC_RPAREN) { break; } else if (x <= 0) { @@ -561,19 +563,16 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { p++; } - /* There is no need to NUL delimit the sscanf() call: trailing garbage is - * ignored and there is always a NUL terminator which will force an error - * if no error is encountered before it. It's possible that the scan - * would scan further than between [js_ctx->p,p[ though and we'd advance - * by less than the scanned value. - * - * Because pointers are platform specific, a failure to scan a pointer - * results in a null pointer which is a better placeholder than a missing - * value or an error. - */ - voidptr = NULL; - (void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr); + + if (encsz > 0 && encsz <= sizeof(pcpy)) { + duk_memzero(pcpy, sizeof(pcpy)); + duk_memcpy(pcpy, p, encsz); + pcpy[encsz] = 0; /* copied ')' change to NUL */ + + duk_decode_pointer_cstr(pcpy, encsz, &voidptr); + } + duk_push_pointer(thr, voidptr); js_ctx->p = p + 1; /* skip ')' */ @@ -1641,6 +1640,7 @@ DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}"; } #endif + duk_encode_pointer_cstr(ptrbuf, sizeof(ptrbuf), ptr); /* When ptr == NULL, the format argument is unused. */ DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */ diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index 8922d5e1bc..5084425225 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -181,3 +181,135 @@ DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) { } } #endif + +#if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) +union duk_ptr_access { + void* ptr; + unsigned char bytes[sizeof(void*)]; +}; +#endif + +/* + * Encodes a pointer value to a NUL terminated C string representing the ptr value, into buf. + * + * Returns: the number of the written characters without the null character at the end. + */ +DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* ptr) { +#if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) + duk_size_t i; + union duk_ptr_access ptraccess; + const char hex[] = "0123456789abcdef"; + + duk_memzero(buf, sz); + + if (sz < 2 * sizeof(ptraccess.bytes) + 1) { + return 0; + } + + for (i = 0; i < sz; i++) { + buf[i] = 0; + } + + ptraccess.ptr = ptr; + + for (i = 0; i < sizeof(ptraccess.bytes); i++) { + buf[2 * i + 0] = hex[(ptraccess.bytes[i] >> 4) & 0xF]; + buf[2 * i + 1] = hex[(ptraccess.bytes[i] >> 0) & 0xF]; + } + + return 2 * sizeof(ptraccess.bytes); +#else + int compsize = DUK_SNPRINTF(buf, sz, "%p", ptr); + + if (compsize > 0 && ((duk_size_t) compsize) < sz) { + return (duk_size_t) compsize; + } + + duk_memzero(buf, sz); + + return 0; +#endif +} + +/* + * Decodes a pointer value represented in a NUL terminated string containing *only ASCII*. + * + * Params: + * - buf the NUL termnated string + * - sz the size of the buffer, this is to ensure proper parsing + * - outputs the parsed pointer value or NULL + * + * Retunrns: 0 if parsing failed, 1 if parsing is successful. + */ +DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** ptr) { +#if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) + duk_size_t i; + unsigned char a, b; + union duk_ptr_access ptraccess; + + *ptr = NULL; + + if (sz <= 2 * sizeof(ptraccess.bytes) || 0 != buf[sz]) { + return 0; /* syntax error */ + } + + for (i = 0; i < 2 * sizeof(ptraccess.bytes); i++) { + if (buf[i] >= '0' && buf[i] <= '9') { + continue; + } + + if (buf[i] >= 'a' && buf[i] <= 'f') { + continue; + } + + return 0; /* syntax error */ + } + + for (i = 0; i < sizeof(ptraccess.bytes); i++) { + a = buf[2 * i + 0]; + b = buf[2 * i + 1]; + + if (a >= 'a') { + a -= 'a'; + } else { + a -= '0'; + } + + if (b >= 'a') { + b -= 'a'; + } else { + b -= '0'; + } + + ptraccess.bytes[i] = ((a << 4) & 0xF0) | ((b << 0) & 0x0F); + } + + *ptr = ptraccess.ptr; + + return 1; /* OK */ +#else + int res; + duk_size_t i; + + for (i = 0; i < sz; i++) { + if (0 == buf[i]) { + goto safe_sscanf; + } + } + + /* no NUL was found, therefore not safe to call sscanf */ + goto syntax_error; + +safe_sscanf: + res = DUK_SSCANF(buf, "%p", ptr); + + if (1 != res) { + goto syntax_error; + } + + return 1; /* OK */ + +syntax_error: + return 0; +#endif +} From 167efd7d94b262aecac2d9a434f9a9a3df0344a8 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 11 Jan 2020 20:53:25 +0100 Subject: [PATCH 09/38] Use pointer encode functions in JX/JC --- src-input/duk_bi_json.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index ad255bd0b0..bdc93389e1 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -540,11 +540,13 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { const duk_uint8_t *p; char pcpy[DUK_MAX_POINTER_ENCODING_SIZE]; duk_small_int_t x; + duk_size_t encsz; void *voidptr; /* Caller has already eaten the first character ('(') which we don't need. */ p = js_ctx->p; + encsz = 0; for (;;) { x = *p; @@ -561,6 +563,7 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { goto syntax_error; } p++; + encsz++; } voidptr = NULL; @@ -1613,6 +1616,7 @@ DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuff #if defined(DUK_USE_JX) || defined(DUK_USE_JC) DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { char buf[64]; /* XXX: how to figure correct size? */ + char ptrbuf[21]; /* (2^64 - 1) as base 10 is 20 chars long + 1 */ const char *fmt; DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */ @@ -1628,7 +1632,7 @@ DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { #endif #if defined(DUK_USE_JX) { - fmt = ptr ? "(%p)" : "(null)"; + fmt = ptr ? "(%s)" : "(null)"; } #endif #if defined(DUK_USE_JX) && defined(DUK_USE_JC) @@ -1637,13 +1641,13 @@ DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { #if defined(DUK_USE_JC) { DUK_ASSERT(js_ctx->flag_ext_compatible); - fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}"; + fmt = ptr ? "{\"_ptr\":\"%s\"}" : "{\"_ptr\":\"null\"}"; } #endif duk_encode_pointer_cstr(ptrbuf, sizeof(ptrbuf), ptr); /* When ptr == NULL, the format argument is unused. */ - DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */ + DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptrbuf); /* must not truncate */ DUK__EMIT_CSTR(js_ctx, buf); } #endif /* DUK_USE_JX || DUK_USE_JC */ From 6bacf104d7608d894e85b95f721d05ee01c4953f Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 11 Jan 2020 20:58:39 +0100 Subject: [PATCH 10/38] Register DUK_USE_STANDARDIZED_POINTER_ENCODING option --- .../DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml diff --git a/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml b/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml new file mode 100644 index 0000000000..08593c9542 --- /dev/null +++ b/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml @@ -0,0 +1,12 @@ +define: DUK_USE_STANDARDIZED_POINTER_ENCODING +introduced: 2.6.0 +default: false +tags: + - debug +description: > + All pointers that need to be encoded as string will be encoded in + lowercase hexadecimal encoding in the byte order they are laid out in + memory. Decoding will also work the same way. + + When turned off, pointer encoding to string is done via the %p format + specifier in the printf and scanf family of functions. From ab5f62d0b87e9af91fa02e0b6d09c4d2ee144b68 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 11 Jan 2020 21:20:51 +0100 Subject: [PATCH 11/38] Add DUK_MAX_POINTER_ENCODING_SIZE and use it --- src-input/duk_bi_json.c | 5 +++-- src-input/duk_util.h | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index bdc93389e1..584affd931 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -1615,14 +1615,15 @@ DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuff #if defined(DUK_USE_JX) || defined(DUK_USE_JC) DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { - char buf[64]; /* XXX: how to figure correct size? */ - char ptrbuf[21]; /* (2^64 - 1) as base 10 is 20 chars long + 1 */ + char buf[DUK_MAX_POINTER_ENCODING_SIZE + 15]; /* length of {"_ptr":"null"} is 15 */ + char ptrbuf[DUK_MAX_POINTER_ENCODING_SIZE]; const char *fmt; DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */ DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible); duk_memzero(buf, sizeof(buf)); + duk_memzero(ptrbuf, sizeof(ptrbuf)); /* The #if defined() clutter here needs to handle the three * cases: (1) JX+JC, (2) JX only, (3) JC only. diff --git a/src-input/duk_util.h b/src-input/duk_util.h index a63eba8292..bb9ea8d8ae 100644 --- a/src-input/duk_util.h +++ b/src-input/duk_util.h @@ -728,4 +728,21 @@ DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y); #define DUK_IS_POWER_OF_TWO(x) \ ((x) != 0U && ((x) & ((x) - 1U)) == 0U) +#if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) +/* + * Standardized encoding is simple: 2 chars per byte. + */ +#define DUK_MAX_POINTER_ENCODING_SIZE (2 * sizeof(void*) + 1) +#else +/* + * It's impossible to know the actual size of the pointer encoded + * as string with %p (or decoded) at compile time. However, assuming + * that the worst thing printf/scanf can do is encode it as possibly + * signed base 8 integer, the encoding for (2^64-1) in base 8 is + * 22 characters long. We round at 32 (inc \0) to account for other + * bases or other weird encodings. + */ +#define DUK_MAX_POINTER_ENCODING_SIZE 32 +#endif + #endif /* DUK_UTIL_H_INCLUDED */ From ec5b6388b7f6de357afb28d4e2080cd39ffd70f3 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 11 Jan 2020 23:03:21 +0100 Subject: [PATCH 12/38] Add guard for decoding ptr with JX only --- src-input/duk_util.h | 21 +++++++++++++++++++++ src-input/duk_util_misc.c | 17 ++--------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src-input/duk_util.h b/src-input/duk_util.h index bb9ea8d8ae..5ae5ece7a6 100644 --- a/src-input/duk_util.h +++ b/src-input/duk_util.h @@ -745,4 +745,25 @@ DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y); #define DUK_MAX_POINTER_ENCODING_SIZE 32 #endif +/* + * Encodes a pointer value to a NUL terminated C string representing the ptr value, into buf. + * + * Returns: the number of the written characters without the null character at the end. + */ +DUK_INTERNAL_DECL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* ptr); + +#if defined(DUK_USE_JX) +/* + * Decodes a pointer value represented in a NUL terminated string containing *only ASCII*. + * + * Params: + * - buf the NUL termnated string + * - sz the size of the buffer, this is to ensure proper parsing + * - outputs the parsed pointer value or NULL + * + * Retunrns: 0 if parsing failed, 1 if parsing is successful. + */ +DUK_INTERNAL_DECL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** ptr); +#endif + #endif /* DUK_UTIL_H_INCLUDED */ diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index 5084425225..c4ef3405b2 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -189,11 +189,6 @@ union duk_ptr_access { }; #endif -/* - * Encodes a pointer value to a NUL terminated C string representing the ptr value, into buf. - * - * Returns: the number of the written characters without the null character at the end. - */ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* ptr) { #if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) duk_size_t i; @@ -231,16 +226,7 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* #endif } -/* - * Decodes a pointer value represented in a NUL terminated string containing *only ASCII*. - * - * Params: - * - buf the NUL termnated string - * - sz the size of the buffer, this is to ensure proper parsing - * - outputs the parsed pointer value or NULL - * - * Retunrns: 0 if parsing failed, 1 if parsing is successful. - */ +#if defined(DUK_USE_JX) DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** ptr) { #if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) duk_size_t i; @@ -312,4 +298,5 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** syntax_error: return 0; #endif +#endif /* DUK_USE_JX */ } From 994eb1206a661e347178a57c15042453f2934a3d Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 11 Jan 2020 23:12:50 +0100 Subject: [PATCH 13/38] Add explicit cast to unsigned char --- src-input/duk_util_misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index c4ef3405b2..3b1f59581c 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -252,8 +252,8 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** } for (i = 0; i < sizeof(ptraccess.bytes); i++) { - a = buf[2 * i + 0]; - b = buf[2 * i + 1]; + a = (unsigned char) buf[2 * i + 0]; + b = (unsigned char) buf[2 * i + 1]; if (a >= 'a') { a -= 'a'; From 31af16f0a1e855f021ddd72a2997417ee132f853 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 11 Jan 2020 23:13:17 +0100 Subject: [PATCH 14/38] Add better docs for DUK_USE_STANDARDIZED_POINTER_ENCODING --- .../DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml b/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml index 08593c9542..298a2328b8 100644 --- a/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml +++ b/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml @@ -1,12 +1,13 @@ define: DUK_USE_STANDARDIZED_POINTER_ENCODING -introduced: 2.6.0 +introduced: 2.7.0 default: false tags: - - debug + - ecmascript description: > All pointers that need to be encoded as string will be encoded in lowercase hexadecimal encoding in the byte order they are laid out in - memory. Decoding will also work the same way. + memory. Decoding will also work the same way. Using this will also + skip reliance on sscanf for platforms that don't support it. When turned off, pointer encoding to string is done via the %p format specifier in the printf and scanf family of functions. From c7ce26c685a2c4875fb4adce250fe8eda9bfb736 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sun, 12 Jan 2020 00:26:23 +0100 Subject: [PATCH 15/38] Use pointer enc/dec functions everywhere --- src-input/duk_api_stack.c | 8 +++++++- src-input/duk_bi_json.c | 8 ++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src-input/duk_api_stack.c b/src-input/duk_api_stack.c index 1b895b053e..854cc7b566 100644 --- a/src-input/duk_api_stack.c +++ b/src-input/duk_api_stack.c @@ -3345,6 +3345,12 @@ DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, d return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL); /* out_clamped==NULL -> RangeError if outside range */ } +DUK_INTERNAL void duk_pointer_to_string(duk_hthread *thr, void* ptr) { + char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; + duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) ptr); + duk_push_string(thr, ptrstr); +} + DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) { duk_tval *tv; @@ -3408,7 +3414,7 @@ DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) { case DUK_TAG_POINTER: { void *ptr = DUK_TVAL_GET_POINTER(tv); if (ptr != NULL) { - duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) ptr); + duk_pointer_to_string(thr, ptr); } else { /* Represent a null pointer as 'null' to be consistent with * the JX format variant. Native '%p' format for a NULL diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index 584affd931..e0410bf3f3 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -1741,6 +1741,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ duk_hthread *thr = js_ctx->thr; duk_hobject *h_target; duk_uint_fast32_t i, n; + char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; *entry_top = duk_get_top(thr); @@ -1766,7 +1767,8 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) { js_ctx->visiting[js_ctx->recursion_depth] = h_target; } else { - duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target); + duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); + duk_push_string(thr, ptrstr); duk_dup_top(thr); /* -> [ ... voidp voidp ] */ if (duk_has_prop(thr, js_ctx->idx_loop)) { DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT); @@ -1794,6 +1796,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) { duk_hthread *thr = js_ctx->thr; duk_hobject *h_target; + char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; /* C recursion check. */ @@ -1808,7 +1811,8 @@ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_t if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) { /* Previous entry was inside visited[], nothing to do. */ } else { - duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target); + duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); + duk_push_string(thr, ptrstr); duk_del_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */ } From 43fba82480a82d5502dac8baf402bdf131c15d8f Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sun, 12 Jan 2020 00:26:36 +0100 Subject: [PATCH 16/38] Fix pointer decoding issue --- src-input/duk_bi_json.c | 4 ++-- src-input/duk_util_misc.c | 22 ++++++++++------------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index e0410bf3f3..364a1c3446 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -568,10 +568,10 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { voidptr = NULL; - if (encsz > 0 && encsz <= sizeof(pcpy)) { + if (encsz > 1 && encsz <= sizeof(pcpy)) { duk_memzero(pcpy, sizeof(pcpy)); duk_memcpy(pcpy, p, encsz); - pcpy[encsz] = 0; /* copied ')' change to NUL */ + pcpy[encsz - 1] = 0; /* copied ')' change to NUL */ duk_decode_pointer_cstr(pcpy, encsz, &voidptr); } diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index 3b1f59581c..0907bf5b0c 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -197,24 +197,20 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* duk_memzero(buf, sz); - if (sz < 2 * sizeof(ptraccess.bytes) + 1) { + if (sz < 2 * sizeof(void*) + 1) { return 0; } - for (i = 0; i < sz; i++) { - buf[i] = 0; - } - ptraccess.ptr = ptr; - for (i = 0; i < sizeof(ptraccess.bytes); i++) { + for (i = 0; i < sizeof(void*); i++) { buf[2 * i + 0] = hex[(ptraccess.bytes[i] >> 4) & 0xF]; buf[2 * i + 1] = hex[(ptraccess.bytes[i] >> 0) & 0xF]; } - return 2 * sizeof(ptraccess.bytes); + return 2 * sizeof(void*); #else - int compsize = DUK_SNPRINTF(buf, sz, "%p", ptr); + int compsize = DUK_SNPRINTF(buf, sz, DUK_STR_FMT_PTR, ptr); if (compsize > 0 && ((duk_size_t) compsize) < sz) { return (duk_size_t) compsize; @@ -235,11 +231,11 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** *ptr = NULL; - if (sz <= 2 * sizeof(ptraccess.bytes) || 0 != buf[sz]) { + if (sz < 2 * sizeof(void*) + 1 || 0 != buf[sz]) { return 0; /* syntax error */ } - for (i = 0; i < 2 * sizeof(ptraccess.bytes); i++) { + for (i = 0; i < 2 * sizeof(void*); i++) { if (buf[i] >= '0' && buf[i] <= '9') { continue; } @@ -251,18 +247,20 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** return 0; /* syntax error */ } - for (i = 0; i < sizeof(ptraccess.bytes); i++) { + for (i = 0; i < sizeof(void*); i++) { a = (unsigned char) buf[2 * i + 0]; b = (unsigned char) buf[2 * i + 1]; if (a >= 'a') { a -= 'a'; + a += 10; } else { a -= '0'; } if (b >= 'a') { b -= 'a'; + b += 10; } else { b -= '0'; } @@ -287,7 +285,7 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** goto syntax_error; safe_sscanf: - res = DUK_SSCANF(buf, "%p", ptr); + res = DUK_SSCANF(buf, DUK_STR_FMT_PTR, ptr); if (1 != res) { goto syntax_error; From 307dba73cd0ee616e2bcd20a2374b66c17f4e032 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sun, 12 Jan 2020 11:38:11 +0100 Subject: [PATCH 17/38] Change space-indent to tab --- src-input/duk_bi_json.c | 31 ++++---- src-input/duk_util_misc.c | 148 +++++++++++++++++++------------------- 2 files changed, 89 insertions(+), 90 deletions(-) diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index 364a1c3446..3a6293b09d 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -538,15 +538,15 @@ DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) { DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { duk_hthread *thr = js_ctx->thr; const duk_uint8_t *p; - char pcpy[DUK_MAX_POINTER_ENCODING_SIZE]; + char pcpy[DUK_MAX_POINTER_ENCODING_SIZE]; duk_small_int_t x; - duk_size_t encsz; + duk_size_t encsz; void *voidptr; /* Caller has already eaten the first character ('(') which we don't need. */ p = js_ctx->p; - encsz = 0; + encsz = 0; for (;;) { x = *p; @@ -555,7 +555,7 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { * parenthesis. */ - encsz++; + encsz++; if (x == DUK_ASC_RPAREN) { break; } else if (x <= 0) { @@ -563,18 +563,17 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { goto syntax_error; } p++; - encsz++; } voidptr = NULL; - if (encsz > 1 && encsz <= sizeof(pcpy)) { - duk_memzero(pcpy, sizeof(pcpy)); - duk_memcpy(pcpy, p, encsz); - pcpy[encsz - 1] = 0; /* copied ')' change to NUL */ + if (encsz > 1 && encsz <= sizeof(pcpy)) { + duk_memzero(pcpy, sizeof(pcpy)); + duk_memcpy(pcpy, p, encsz); + pcpy[encsz - 1] = 0; /* copied ')' change to NUL */ - duk_decode_pointer_cstr(pcpy, encsz, &voidptr); - } + duk_decode_pointer_cstr(pcpy, encsz, &voidptr); + } duk_push_pointer(thr, voidptr); js_ctx->p = p + 1; /* skip ')' */ @@ -1645,7 +1644,7 @@ DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { fmt = ptr ? "{\"_ptr\":\"%s\"}" : "{\"_ptr\":\"null\"}"; } #endif - duk_encode_pointer_cstr(ptrbuf, sizeof(ptrbuf), ptr); + duk_encode_pointer_cstr(ptrbuf, sizeof(ptrbuf), ptr); /* When ptr == NULL, the format argument is unused. */ DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptrbuf); /* must not truncate */ @@ -1767,8 +1766,8 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) { js_ctx->visiting[js_ctx->recursion_depth] = h_target; } else { - duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); - duk_push_string(thr, ptrstr); + duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); + duk_push_string(thr, ptrstr); duk_dup_top(thr); /* -> [ ... voidp voidp ] */ if (duk_has_prop(thr, js_ctx->idx_loop)) { DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT); @@ -1811,8 +1810,8 @@ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_t if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) { /* Previous entry was inside visited[], nothing to do. */ } else { - duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); - duk_push_string(thr, ptrstr); + duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); + duk_push_string(thr, ptrstr); duk_del_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */ } diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index 0907bf5b0c..aefd5d3a93 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -184,117 +184,117 @@ DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) { #if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) union duk_ptr_access { - void* ptr; - unsigned char bytes[sizeof(void*)]; + void* ptr; + unsigned char bytes[sizeof(void*)]; }; #endif DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* ptr) { #if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) - duk_size_t i; - union duk_ptr_access ptraccess; - const char hex[] = "0123456789abcdef"; + duk_size_t i; + union duk_ptr_access ptraccess; + const char hex[] = "0123456789abcdef"; - duk_memzero(buf, sz); + duk_memzero(buf, sz); - if (sz < 2 * sizeof(void*) + 1) { - return 0; - } + if (sz < 2 * sizeof(void*) + 1) { + return 0; + } - ptraccess.ptr = ptr; + ptraccess.ptr = ptr; - for (i = 0; i < sizeof(void*); i++) { - buf[2 * i + 0] = hex[(ptraccess.bytes[i] >> 4) & 0xF]; - buf[2 * i + 1] = hex[(ptraccess.bytes[i] >> 0) & 0xF]; - } + for (i = 0; i < sizeof(void*); i++) { + buf[2 * i + 0] = hex[(ptraccess.bytes[i] >> 4) & 0xF]; + buf[2 * i + 1] = hex[(ptraccess.bytes[i] >> 0) & 0xF]; + } - return 2 * sizeof(void*); + return 2 * sizeof(void*); #else - int compsize = DUK_SNPRINTF(buf, sz, DUK_STR_FMT_PTR, ptr); + int compsize = DUK_SNPRINTF(buf, sz, DUK_STR_FMT_PTR, ptr); - if (compsize > 0 && ((duk_size_t) compsize) < sz) { - return (duk_size_t) compsize; - } + if (compsize > 0 && ((duk_size_t) compsize) < sz) { + return (duk_size_t) compsize; + } - duk_memzero(buf, sz); + duk_memzero(buf, sz); - return 0; + return 0; #endif } #if defined(DUK_USE_JX) DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** ptr) { #if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) - duk_size_t i; - unsigned char a, b; - union duk_ptr_access ptraccess; - - *ptr = NULL; - - if (sz < 2 * sizeof(void*) + 1 || 0 != buf[sz]) { - return 0; /* syntax error */ - } - - for (i = 0; i < 2 * sizeof(void*); i++) { - if (buf[i] >= '0' && buf[i] <= '9') { - continue; - } + duk_size_t i; + unsigned char a, b; + union duk_ptr_access ptraccess; - if (buf[i] >= 'a' && buf[i] <= 'f') { - continue; - } + *ptr = NULL; - return 0; /* syntax error */ - } + if (sz < 2 * sizeof(void*) + 1 || 0 != buf[sz]) { + return 0; /* syntax error */ + } - for (i = 0; i < sizeof(void*); i++) { - a = (unsigned char) buf[2 * i + 0]; - b = (unsigned char) buf[2 * i + 1]; + for (i = 0; i < 2 * sizeof(void*); i++) { + if (buf[i] >= '0' && buf[i] <= '9') { + continue; + } - if (a >= 'a') { - a -= 'a'; - a += 10; - } else { - a -= '0'; - } + if (buf[i] >= 'a' && buf[i] <= 'f') { + continue; + } - if (b >= 'a') { - b -= 'a'; - b += 10; - } else { - b -= '0'; - } + return 0; /* syntax error */ + } - ptraccess.bytes[i] = ((a << 4) & 0xF0) | ((b << 0) & 0x0F); - } + for (i = 0; i < sizeof(void*); i++) { + a = (unsigned char) buf[2 * i + 0]; + b = (unsigned char) buf[2 * i + 1]; + + if (a >= 'a') { + a -= 'a'; + a += 10; + } else { + a -= '0'; + } + + if (b >= 'a') { + b -= 'a'; + b += 10; + } else { + b -= '0'; + } + + ptraccess.bytes[i] = ((a << 4) & 0xF0) | ((b << 0) & 0x0F); + } - *ptr = ptraccess.ptr; + *ptr = ptraccess.ptr; - return 1; /* OK */ + return 1; /* OK */ #else - int res; - duk_size_t i; + int res; + duk_size_t i; - for (i = 0; i < sz; i++) { - if (0 == buf[i]) { - goto safe_sscanf; - } - } + for (i = 0; i < sz; i++) { + if (0 == buf[i]) { + goto safe_sscanf; + } + } - /* no NUL was found, therefore not safe to call sscanf */ - goto syntax_error; + /* no NUL was found, therefore not safe to call sscanf */ + goto syntax_error; safe_sscanf: - res = DUK_SSCANF(buf, DUK_STR_FMT_PTR, ptr); + res = DUK_SSCANF(buf, DUK_STR_FMT_PTR, ptr); - if (1 != res) { - goto syntax_error; - } + if (1 != res) { + goto syntax_error; + } - return 1; /* OK */ + return 1; /* OK */ syntax_error: - return 0; + return 0; #endif #endif /* DUK_USE_JX */ } From e09a9474a9d249fb0935d82768f7076574af82db Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sun, 12 Jan 2020 11:58:18 +0100 Subject: [PATCH 18/38] Add setting ptr to NULL on failures --- src-input/duk_util_misc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index aefd5d3a93..e0609ae6d7 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -275,6 +275,8 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** int res; duk_size_t i; + *ptr = NULL; + for (i = 0; i < sz; i++) { if (0 == buf[i]) { goto safe_sscanf; @@ -294,6 +296,8 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** return 1; /* OK */ syntax_error: + *ptr = NULL; + return 0; #endif #endif /* DUK_USE_JX */ From 60c27b9351fe4acfcca36a0a3422776de4a22345 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sun, 12 Jan 2020 14:51:35 +0100 Subject: [PATCH 19/38] Fix ECMA tests failing on decode (improper impl) --- src-input/duk_api_stack.c | 8 ++++---- src-input/duk_bi_json.c | 14 +++++++------- src-input/duk_util_misc.c | 6 ++---- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src-input/duk_api_stack.c b/src-input/duk_api_stack.c index 854cc7b566..78ae247338 100644 --- a/src-input/duk_api_stack.c +++ b/src-input/duk_api_stack.c @@ -3346,9 +3346,9 @@ DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, d } DUK_INTERNAL void duk_pointer_to_string(duk_hthread *thr, void* ptr) { - char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; - duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) ptr); - duk_push_string(thr, ptrstr); + char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; + duk_size_t size = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) ptr); + duk_push_lstring(thr, ptrstr, size); } DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) { @@ -3414,7 +3414,7 @@ DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) { case DUK_TAG_POINTER: { void *ptr = DUK_TVAL_GET_POINTER(tv); if (ptr != NULL) { - duk_pointer_to_string(thr, ptr); + duk_pointer_to_string(thr, ptr); } else { /* Represent a null pointer as 'null' to be consistent with * the JX format variant. Native '%p' format for a NULL diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index 3a6293b09d..8b445e7f63 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -569,7 +569,7 @@ DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) { if (encsz > 1 && encsz <= sizeof(pcpy)) { duk_memzero(pcpy, sizeof(pcpy)); - duk_memcpy(pcpy, p, encsz); + duk_memcpy(pcpy, js_ctx->p, encsz); pcpy[encsz - 1] = 0; /* copied ')' change to NUL */ duk_decode_pointer_cstr(pcpy, encsz, &voidptr); @@ -1615,14 +1615,14 @@ DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuff #if defined(DUK_USE_JX) || defined(DUK_USE_JC) DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) { char buf[DUK_MAX_POINTER_ENCODING_SIZE + 15]; /* length of {"_ptr":"null"} is 15 */ - char ptrbuf[DUK_MAX_POINTER_ENCODING_SIZE]; + char ptrbuf[DUK_MAX_POINTER_ENCODING_SIZE]; const char *fmt; DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */ DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible); duk_memzero(buf, sizeof(buf)); - duk_memzero(ptrbuf, sizeof(ptrbuf)); + duk_memzero(ptrbuf, sizeof(ptrbuf)); /* The #if defined() clutter here needs to handle the three * cases: (1) JX+JC, (2) JX only, (3) JC only. @@ -1766,8 +1766,8 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) { js_ctx->visiting[js_ctx->recursion_depth] = h_target; } else { - duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); - duk_push_string(thr, ptrstr); + duk_size_t len = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); + duk_push_lstring(thr, ptrstr, len); duk_dup_top(thr); /* -> [ ... voidp voidp ] */ if (duk_has_prop(thr, js_ctx->idx_loop)) { DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT); @@ -1810,8 +1810,8 @@ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_t if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) { /* Previous entry was inside visited[], nothing to do. */ } else { - duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); - duk_push_string(thr, ptrstr); + duk_size_t len = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); + duk_push_lstring(thr, ptrstr, len); duk_del_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */ } diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index e0609ae6d7..1652f8a0ce 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -195,8 +195,6 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* union duk_ptr_access ptraccess; const char hex[] = "0123456789abcdef"; - duk_memzero(buf, sz); - if (sz < 2 * sizeof(void*) + 1) { return 0; } @@ -287,9 +285,9 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** goto syntax_error; safe_sscanf: - res = DUK_SSCANF(buf, DUK_STR_FMT_PTR, ptr); + return DUK_SSCANF(buf, DUK_STR_FMT_PTR, ptr); - if (1 != res) { + if (res < 1) { goto syntax_error; } From 9ca0bd76b20f654b1cc63d0a8bb353fe04a756a6 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sun, 12 Jan 2020 14:54:45 +0100 Subject: [PATCH 20/38] Add runtests/package-lock.json to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 61869f8795..7ab31963b0 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ /es5-tests.zip /JS-Interpreter/ /runtests/node_modules/ +/runtests/package-lock.json /d067d2f0ca30.tar.bz2 /595a36b252ee97110724e6fa89fc92c9aa9a206a.zip /regfuzz-0.1.tar.gz From fa687f6ce308a88b5f0d17b34792ecd0b6f1e554 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sun, 12 Jan 2020 16:33:15 +0100 Subject: [PATCH 21/38] Add info in doc/json.rst for DUK_USE_STANDARDIZED_POINTER_ENCODING --- doc/json.rst | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/json.rst b/doc/json.rst index 42c695212b..eefceaaacf 100644 --- a/doc/json.rst +++ b/doc/json.rst @@ -151,7 +151,9 @@ detection: need to maintain yet another growing data structure for the stack, and don't need to do linear stack scans to detect loops. The downside is relatively large memory footprint and lots of additional string table operations. - However, these effects only come into play for very deep objects. + However, these effects only come into play for very deep objects. The option + ``DUK_USE_STANDARDIZED_POINTER_ENCODING`` can be used to remove the reliance + on ``%p``, however pointer values will still be platform-dependent. There's much room for improvement in the loop detection: @@ -546,6 +548,8 @@ specific form, using the format ``(%p)``, e.g.:: (0x1ff0e10) // 32-bit Linux (000FEFF8) // 32-bit Windows (000000000026A8A0) // 64-bit Windows + (0D0C0B0A00000000) // 0x0A0B0C0D in 64-bit little-endian x64 + // with DUK_USE_STANDARDIZED_POINTER_ENCODING A pointer value parses back correctly when serialized and parsed by the same program. Other than that there is no guarantee that a pointer value can be @@ -561,6 +565,14 @@ an error. (null) +By enabling the ``DUK_USE_STANDARDIZED_POINTER_ENCODING`` option you can make +the pointer encoding and decoding be "standard" across Duktape builds, but it +is still platform dependant. It would depend on the memory layout and size in +bytes of a pointer value, rather than ``%p``. Pointers can, therefore, be +parsed across different Duktape builds for the same platform. The pointers are +encoded in lowercase hex and there are 2 hex characters for each byte of the +pointer value, as it appears in memory, including heading / trailing 0s. + ASCII only output ----------------- @@ -674,6 +686,9 @@ specific form, using the format ``%p``, but wrapped in a marker table:: Note that compared to JX, the difference is that there are no surrounding parentheses outside the pointer value. +The option ``DUK_USE_STANDARDIZED_POINTER_ENCODING`` will also be used here as +well. + ASCII only output ----------------- From c984c1fe15264a2613fc9500eadb602c1b458975 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sun, 12 Jan 2020 16:33:45 +0100 Subject: [PATCH 22/38] Fix ...decode_pointer_cstr with DUK_USE_STANDARDIZED_POINTER_ENCODING --- src-input/duk_util_misc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index 1652f8a0ce..e2d9b287b3 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -195,7 +195,7 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* union duk_ptr_access ptraccess; const char hex[] = "0123456789abcdef"; - if (sz < 2 * sizeof(void*) + 1) { + if (DUK_UNLIKELY(sz < 2 * sizeof(void*) + 1)) { return 0; } @@ -210,7 +210,7 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* #else int compsize = DUK_SNPRINTF(buf, sz, DUK_STR_FMT_PTR, ptr); - if (compsize > 0 && ((duk_size_t) compsize) < sz) { + if (DUK_LIKELY(compsize > 0 && ((duk_size_t) compsize) < sz)) { return (duk_size_t) compsize; } @@ -229,16 +229,16 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** *ptr = NULL; - if (sz < 2 * sizeof(void*) + 1 || 0 != buf[sz]) { + if (DUK_UNLIKELY(sz < 1 || sz < 2 * sizeof(void*) + 1 || 0 != buf[sz - 1])) { return 0; /* syntax error */ } for (i = 0; i < 2 * sizeof(void*); i++) { - if (buf[i] >= '0' && buf[i] <= '9') { + if (DUK_LIKELY(buf[i] >= '0' && buf[i] <= '9')) { continue; } - if (buf[i] >= 'a' && buf[i] <= 'f') { + if (DUK_LIKELY(buf[i] >= 'a' && buf[i] <= 'f')) { continue; } From abe247f3684ed5276cec393bf909b5fcc1146e08 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sun, 12 Jan 2020 17:05:40 +0100 Subject: [PATCH 23/38] Enable DUK_USE_STANDARDIZED_POINTER_ENCODING when in Intel SGX --- config/platforms/platform_intelsgx.h.in | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/config/platforms/platform_intelsgx.h.in b/config/platforms/platform_intelsgx.h.in index c0b92487de..ac67d3d1bf 100644 --- a/config/platforms/platform_intelsgx.h.in +++ b/config/platforms/platform_intelsgx.h.in @@ -3,7 +3,7 @@ #include #include -/** +/* * Intel SGX enclaves are completely isolated from the underlying * kernel and therefore syscalls are not allowed by default. This * means that getting the current time and locale information is @@ -52,11 +52,18 @@ #undef DUK_USE_DATE_TZO_WINDOWS #undef DUK_USE_DATE_TZO_WINDOWS_NO_DST +/* + * Intel SGX enclaves don't have access to sscanf, so pointer parsing must + * be standardized. + */ +#define DUK_USE_STANDARDIZED_POINTER_ENCODING + #define DUK_SNPRINTF(a,b,c,...) _snprintf_s(a,b,b,c,__VA_ARGS__) #define DUK_VSNPRINTF(a,b,c,...) _vsnprintf_s(a,b,b,c,__VA_ARGS__) #if defined(DUK_F_WINDOWS) -/* On Windows, assume we're little endian. Even Itanium which has a +/* + * On Windows, assume we're little endian. Even Itanium which has a * configurable endianness runs little endian in Windows. */ #if !defined(DUK_USE_BYTEORDER) From 9ca1f0bb95557a773d60caa4857ba7f17c677885 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 25 Jan 2020 17:58:22 +0100 Subject: [PATCH 24/38] Define INTELSGX to trigger DUK_F_INTELSGX --- config/helper-snippets/DUK_F_INTELSGX.h.in | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/config/helper-snippets/DUK_F_INTELSGX.h.in b/config/helper-snippets/DUK_F_INTELSGX.h.in index d292b9585c..0e095f946a 100644 --- a/config/helper-snippets/DUK_F_INTELSGX.h.in +++ b/config/helper-snippets/DUK_F_INTELSGX.h.in @@ -2,10 +2,8 @@ * Automatic Intel SGX detection is not possible at compile time. * Therefore Intel SGX enclave developers wanting to use Duktape * should either manually specify --platform=intelsgx to configure.py - * or manually define the DUK_F_INTELSGX macro. + * or manually define INTELSGX when compiling. */ -#if defined(DUK_F_INTELSGX) -/* Trick genconfig.py that we've autodetected it. */ -#undef DUK_F_INTELSGX +#if defined(INTELSGX) #define DUK_F_INTELSGX #endif From 55bc9b61206564c2d7b6c848aa9c322c6d40a9c7 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 25 Jan 2020 18:03:34 +0100 Subject: [PATCH 25/38] Eliminate dead code --- src-input/duk_util_misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index e2d9b287b3..e02baffa40 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -285,7 +285,7 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** goto syntax_error; safe_sscanf: - return DUK_SSCANF(buf, DUK_STR_FMT_PTR, ptr); + res = DUK_SSCANF(buf, DUK_STR_FMT_PTR, ptr); if (res < 1) { goto syntax_error; From 42fdfef1de86798ca8e1c12e181cbbc1174d4b0d Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 4 Feb 2020 22:34:11 +0100 Subject: [PATCH 26/38] Rename to DUK_USE_MEMBASED_POINTER_ENCODING --- .../DUK_USE_MEMBASED_POINTER_ENCODING.yaml | 13 +++++++++++++ .../DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml | 2 +- config/platforms/platform_intelsgx.h.in | 14 ++++---------- doc/json.rst | 10 +++++----- src-input/duk_util.h | 4 ++-- src-input/duk_util_misc.c | 6 +++--- 6 files changed, 28 insertions(+), 21 deletions(-) create mode 100644 config/config-options/DUK_USE_MEMBASED_POINTER_ENCODING.yaml diff --git a/config/config-options/DUK_USE_MEMBASED_POINTER_ENCODING.yaml b/config/config-options/DUK_USE_MEMBASED_POINTER_ENCODING.yaml new file mode 100644 index 0000000000..ae4a246940 --- /dev/null +++ b/config/config-options/DUK_USE_MEMBASED_POINTER_ENCODING.yaml @@ -0,0 +1,13 @@ +define: DUK_USE_MEMBASED_POINTER_ENCODING +introduced: 2.7.0 +default: false +tags: + - ecmascript +description: > + All pointers that need to be encoded as string will be encoded in + lowercase hexadecimal encoding in the byte order they are laid out in + memory. Decoding will also work the same way. Using this will also + skip reliance on sscanf for platforms that don't support it. + + When turned off, pointer encoding to string is done via the %p format + specifier in the printf and scanf family of functions. diff --git a/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml b/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml index 298a2328b8..ae4a246940 100644 --- a/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml +++ b/config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml @@ -1,4 +1,4 @@ -define: DUK_USE_STANDARDIZED_POINTER_ENCODING +define: DUK_USE_MEMBASED_POINTER_ENCODING introduced: 2.7.0 default: false tags: diff --git a/config/platforms/platform_intelsgx.h.in b/config/platforms/platform_intelsgx.h.in index ac67d3d1bf..9b7e2c00de 100644 --- a/config/platforms/platform_intelsgx.h.in +++ b/config/platforms/platform_intelsgx.h.in @@ -29,14 +29,8 @@ * and formatting. * * All related Duktape provided implementations regarding date and - * time are intentionally disabled. - * - * Similarly, any file I/O APIs are disabled since file I/O is not - * available in the enclave. - * - * DUK_USE_JX needs to be undefined since JX uses sscanf to parse out - * pointers from strings, and sscanf is not available in Intel SGX - * enclaves. + * time are intentionally disabled, since date and time functions are + * not generally available in Intel SGX enclaves. */ #undef DUK_USE_DATE_FMT_STRFTIME @@ -54,9 +48,9 @@ /* * Intel SGX enclaves don't have access to sscanf, so pointer parsing must - * be standardized. + * be without using sscanf. */ -#define DUK_USE_STANDARDIZED_POINTER_ENCODING +#define DUK_USE_MEMBASED_POINTER_ENCODING #define DUK_SNPRINTF(a,b,c,...) _snprintf_s(a,b,b,c,__VA_ARGS__) #define DUK_VSNPRINTF(a,b,c,...) _vsnprintf_s(a,b,b,c,__VA_ARGS__) diff --git a/doc/json.rst b/doc/json.rst index eefceaaacf..c8ad5284ba 100644 --- a/doc/json.rst +++ b/doc/json.rst @@ -152,7 +152,7 @@ detection: need to do linear stack scans to detect loops. The downside is relatively large memory footprint and lots of additional string table operations. However, these effects only come into play for very deep objects. The option - ``DUK_USE_STANDARDIZED_POINTER_ENCODING`` can be used to remove the reliance + ``DUK_USE_MEMBASED_POINTER_ENCODING`` can be used to remove the reliance on ``%p``, however pointer values will still be platform-dependent. There's much room for improvement in the loop detection: @@ -548,8 +548,8 @@ specific form, using the format ``(%p)``, e.g.:: (0x1ff0e10) // 32-bit Linux (000FEFF8) // 32-bit Windows (000000000026A8A0) // 64-bit Windows - (0D0C0B0A00000000) // 0x0A0B0C0D in 64-bit little-endian x64 - // with DUK_USE_STANDARDIZED_POINTER_ENCODING + (0d0c0b0a00000000) // 0x0A0B0C0D in 64-bit little-endian x64 + // with DUK_USE_MEMBASED_POINTER_ENCODING A pointer value parses back correctly when serialized and parsed by the same program. Other than that there is no guarantee that a pointer value can be @@ -565,7 +565,7 @@ an error. (null) -By enabling the ``DUK_USE_STANDARDIZED_POINTER_ENCODING`` option you can make +By enabling the ``DUK_USE_MEMBASED_POINTER_ENCODING`` option you can make the pointer encoding and decoding be "standard" across Duktape builds, but it is still platform dependant. It would depend on the memory layout and size in bytes of a pointer value, rather than ``%p``. Pointers can, therefore, be @@ -686,7 +686,7 @@ specific form, using the format ``%p``, but wrapped in a marker table:: Note that compared to JX, the difference is that there are no surrounding parentheses outside the pointer value. -The option ``DUK_USE_STANDARDIZED_POINTER_ENCODING`` will also be used here as +The option ``DUK_USE_MEMBASED_POINTER_ENCODING`` will also be used here as well. ASCII only output diff --git a/src-input/duk_util.h b/src-input/duk_util.h index 5ae5ece7a6..7a4cc20289 100644 --- a/src-input/duk_util.h +++ b/src-input/duk_util.h @@ -728,9 +728,9 @@ DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y); #define DUK_IS_POWER_OF_TWO(x) \ ((x) != 0U && ((x) & ((x) - 1U)) == 0U) -#if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) +#if defined(DUK_USE_MEMBASED_POINTER_ENCODING) /* - * Standardized encoding is simple: 2 chars per byte. + * Memory based encoding is simple: 2 chars per byte. */ #define DUK_MAX_POINTER_ENCODING_SIZE (2 * sizeof(void*) + 1) #else diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index e02baffa40..77fc0deac6 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -182,7 +182,7 @@ DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) { } #endif -#if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) +#if defined(DUK_USE_MEMBASED_POINTER_ENCODING) union duk_ptr_access { void* ptr; unsigned char bytes[sizeof(void*)]; @@ -190,7 +190,7 @@ union duk_ptr_access { #endif DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* ptr) { -#if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) +#if defined(DUK_USE_MEMBASED_POINTER_ENCODING) duk_size_t i; union duk_ptr_access ptraccess; const char hex[] = "0123456789abcdef"; @@ -222,7 +222,7 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* #if defined(DUK_USE_JX) DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** ptr) { -#if defined(DUK_USE_STANDARDIZED_POINTER_ENCODING) +#if defined(DUK_USE_MEMBASED_POINTER_ENCODING) duk_size_t i; unsigned char a, b; union duk_ptr_access ptraccess; From 1f43ea5d017da9fff29a6ace70df1367001248ec Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 4 Feb 2020 22:55:48 +0100 Subject: [PATCH 27/38] Add myself to code authors --- AUTHORS.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 1fcfa73c41..7f4c08d200 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -66,6 +66,7 @@ and agreed to irrevocably license their contributions under the Duktape * Rick Sayre (https://github.com/whorfin) * Craig Leres (https://github.com/leres) * Maurici Abad (https://github.com/mauriciabad) +* Stojan Dimitrovski (https://github.com/hf) Other contributions =================== @@ -108,7 +109,6 @@ bugs, provided ideas, etc; roughly in order of appearance): * Andrew Janke (https://github.com/apjanke) * Unamer (https://github.com/unamer) * Karl Dahlke (eklhad@gmail.com) -* Stojan Dimitrovski (https://github.com/hf) If you are accidentally missing from this list, send me an e-mail (``sami.vaarala@iki.fi``) and I'll fix the omission. From 3fc9a1a57bf7abb8e7136b3b2c2214523f138586 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 4 Feb 2020 22:59:50 +0100 Subject: [PATCH 28/38] Fix void* style and typos --- src-input/duk_api_stack.c | 2 +- src-input/duk_util.h | 4 ++-- src-input/duk_util_misc.c | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src-input/duk_api_stack.c b/src-input/duk_api_stack.c index 78ae247338..9b4e63fa66 100644 --- a/src-input/duk_api_stack.c +++ b/src-input/duk_api_stack.c @@ -3345,7 +3345,7 @@ DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, d return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL); /* out_clamped==NULL -> RangeError if outside range */ } -DUK_INTERNAL void duk_pointer_to_string(duk_hthread *thr, void* ptr) { +DUK_INTERNAL void duk_pointer_to_string(duk_hthread *thr, void *ptr) { char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; duk_size_t size = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) ptr); duk_push_lstring(thr, ptrstr, size); diff --git a/src-input/duk_util.h b/src-input/duk_util.h index 7a4cc20289..0949e097b1 100644 --- a/src-input/duk_util.h +++ b/src-input/duk_util.h @@ -750,7 +750,7 @@ DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y); * * Returns: the number of the written characters without the null character at the end. */ -DUK_INTERNAL_DECL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* ptr); +DUK_INTERNAL_DECL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void *ptr); #if defined(DUK_USE_JX) /* @@ -761,7 +761,7 @@ DUK_INTERNAL_DECL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, v * - sz the size of the buffer, this is to ensure proper parsing * - outputs the parsed pointer value or NULL * - * Retunrns: 0 if parsing failed, 1 if parsing is successful. + * Returns: 0 if parsing failed, 1 if parsing is successful. */ DUK_INTERNAL_DECL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** ptr); #endif diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index 77fc0deac6..598b56cd58 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -183,16 +183,16 @@ DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) { #endif #if defined(DUK_USE_MEMBASED_POINTER_ENCODING) -union duk_ptr_access { - void* ptr; +union duk__ptr_access { + void *ptr; unsigned char bytes[sizeof(void*)]; }; #endif -DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void* ptr) { +DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void *ptr) { #if defined(DUK_USE_MEMBASED_POINTER_ENCODING) duk_size_t i; - union duk_ptr_access ptraccess; + union duk__ptr_access ptraccess; const char hex[] = "0123456789abcdef"; if (DUK_UNLIKELY(sz < 2 * sizeof(void*) + 1)) { From a6226b43e1cba87c5ec20bb689a31d365af8eece Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 4 Feb 2020 23:05:01 +0100 Subject: [PATCH 29/38] Fix indentation issues --- src-input/duk_bi_json.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index 8b445e7f63..aee2a1ff6c 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -1592,7 +1592,7 @@ DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuff for (i = 0; i < n; i++) { duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1); q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32); - q += DUK_SNPRINTF((char *) q, 32, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]); + q += DUK_SNPRINTF((char *) q, 32, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]); DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q); } } else { @@ -1740,7 +1740,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ duk_hthread *thr = js_ctx->thr; duk_hobject *h_target; duk_uint_fast32_t i, n; - char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; + char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; *entry_top = duk_get_top(thr); @@ -1795,7 +1795,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) { duk_hthread *thr = js_ctx->thr; duk_hobject *h_target; - char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; + char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; /* C recursion check. */ From 69d9561b7c9be2fc64543effe4af3490d163db8b Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 4 Feb 2020 23:09:44 +0100 Subject: [PATCH 30/38] Use duk_lc_digits instead of another static hex definition --- src-input/duk_util_misc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index 598b56cd58..ffb1c62ea3 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -193,7 +193,6 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void * #if defined(DUK_USE_MEMBASED_POINTER_ENCODING) duk_size_t i; union duk__ptr_access ptraccess; - const char hex[] = "0123456789abcdef"; if (DUK_UNLIKELY(sz < 2 * sizeof(void*) + 1)) { return 0; @@ -202,8 +201,8 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void * ptraccess.ptr = ptr; for (i = 0; i < sizeof(void*); i++) { - buf[2 * i + 0] = hex[(ptraccess.bytes[i] >> 4) & 0xF]; - buf[2 * i + 1] = hex[(ptraccess.bytes[i] >> 0) & 0xF]; + buf[2 * i + 0] = duk_lc_digits[(ptraccess.bytes[i] >> 4) & 0xF]; + buf[2 * i + 1] = duk_lc_digits[(ptraccess.bytes[i] >> 0) & 0xF]; } return 2 * sizeof(void*); From 0d7e9bef7aecc95f160c6e4177b6bcca37ea5bdd Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 4 Feb 2020 23:17:12 +0100 Subject: [PATCH 31/38] Fix all remaining void* style issues --- src-input/duk_api_stack.c | 2 +- src-input/duk_bi_json.c | 4 ++-- src-input/duk_util.h | 2 +- src-input/duk_util_misc.c | 14 +++++++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src-input/duk_api_stack.c b/src-input/duk_api_stack.c index 9b4e63fa66..1ba9b50312 100644 --- a/src-input/duk_api_stack.c +++ b/src-input/duk_api_stack.c @@ -3347,7 +3347,7 @@ DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, d DUK_INTERNAL void duk_pointer_to_string(duk_hthread *thr, void *ptr) { char ptrstr[DUK_MAX_POINTER_ENCODING_SIZE]; - duk_size_t size = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) ptr); + duk_size_t size = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void *) ptr); duk_push_lstring(thr, ptrstr, size); } diff --git a/src-input/duk_bi_json.c b/src-input/duk_bi_json.c index aee2a1ff6c..de3abcf62d 100644 --- a/src-input/duk_bi_json.c +++ b/src-input/duk_bi_json.c @@ -1766,7 +1766,7 @@ DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_ if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) { js_ctx->visiting[js_ctx->recursion_depth] = h_target; } else { - duk_size_t len = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); + duk_size_t len = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void *) h_target); duk_push_lstring(thr, ptrstr, len); duk_dup_top(thr); /* -> [ ... voidp voidp ] */ if (duk_has_prop(thr, js_ctx->idx_loop)) { @@ -1810,7 +1810,7 @@ DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_t if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) { /* Previous entry was inside visited[], nothing to do. */ } else { - duk_size_t len = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void*) h_target); + duk_size_t len = duk_encode_pointer_cstr(ptrstr, sizeof(ptrstr), (void *) h_target); duk_push_lstring(thr, ptrstr, len); duk_del_prop(thr, js_ctx->idx_loop); /* -> [ ... ] */ } diff --git a/src-input/duk_util.h b/src-input/duk_util.h index 0949e097b1..588a4d7602 100644 --- a/src-input/duk_util.h +++ b/src-input/duk_util.h @@ -732,7 +732,7 @@ DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y); /* * Memory based encoding is simple: 2 chars per byte. */ -#define DUK_MAX_POINTER_ENCODING_SIZE (2 * sizeof(void*) + 1) +#define DUK_MAX_POINTER_ENCODING_SIZE (2 * sizeof(void *) + 1) #else /* * It's impossible to know the actual size of the pointer encoded diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index ffb1c62ea3..ff5415612c 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -185,7 +185,7 @@ DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) { #if defined(DUK_USE_MEMBASED_POINTER_ENCODING) union duk__ptr_access { void *ptr; - unsigned char bytes[sizeof(void*)]; + unsigned char bytes[sizeof(void *)]; }; #endif @@ -194,18 +194,18 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void * duk_size_t i; union duk__ptr_access ptraccess; - if (DUK_UNLIKELY(sz < 2 * sizeof(void*) + 1)) { + if (DUK_UNLIKELY(sz < 2 * sizeof(void *) + 1)) { return 0; } ptraccess.ptr = ptr; - for (i = 0; i < sizeof(void*); i++) { + for (i = 0; i < sizeof(void *); i++) { buf[2 * i + 0] = duk_lc_digits[(ptraccess.bytes[i] >> 4) & 0xF]; buf[2 * i + 1] = duk_lc_digits[(ptraccess.bytes[i] >> 0) & 0xF]; } - return 2 * sizeof(void*); + return 2 * sizeof(void *); #else int compsize = DUK_SNPRINTF(buf, sz, DUK_STR_FMT_PTR, ptr); @@ -228,11 +228,11 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** *ptr = NULL; - if (DUK_UNLIKELY(sz < 1 || sz < 2 * sizeof(void*) + 1 || 0 != buf[sz - 1])) { + if (DUK_UNLIKELY(sz < 1 || sz < 2 * sizeof(void *) + 1 || 0 != buf[sz - 1])) { return 0; /* syntax error */ } - for (i = 0; i < 2 * sizeof(void*); i++) { + for (i = 0; i < 2 * sizeof(void *); i++) { if (DUK_LIKELY(buf[i] >= '0' && buf[i] <= '9')) { continue; } @@ -244,7 +244,7 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** return 0; /* syntax error */ } - for (i = 0; i < sizeof(void*); i++) { + for (i = 0; i < sizeof(void *); i++) { a = (unsigned char) buf[2 * i + 0]; b = (unsigned char) buf[2 * i + 1]; From d5b4c8c4cfe7f15c0f527a16bf9c56cf1e293782 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Wed, 5 Feb 2020 23:41:46 +0100 Subject: [PATCH 32/38] Clarify symbol representation, assert --- src-input/duk_bi_symbol.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src-input/duk_bi_symbol.c b/src-input/duk_bi_symbol.c index e299beb505..f3696e9336 100644 --- a/src-input/duk_bi_symbol.c +++ b/src-input/duk_bi_symbol.c @@ -35,6 +35,17 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) { * +1 0xff after description, before unique suffix * +17 autogenerated unique suffix: 'ffffffff-ffffffff' is longest * +1 0xff after unique suffix for symbols with undefined description + * + * The layout therefore looks like so: + * + * A len B f f f f f f f f - f f f f f f f f C + * -- --- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + * 00 len 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 + * + * snprintf does not always terminate with NUL, however if it does it will + * write the NUL in the C position, which can be overwritten with 0xff + * if desc is NULL. Nonetheless, snprintf when positive, returns the number + * of bytes that the format would have taken without counting NUL. */ buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1); DUK_ASSERT(buf != NULL); @@ -50,9 +61,18 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) { if (++thr->heap->sym_counter[0] == 0) { thr->heap->sym_counter[1]++; } - p += DUK_SNPRINTF((char *) p, 1 + 17 + 1 /* 1 + len lost above */, "\xFF" "%lx-%lx", - (unsigned long) thr->heap->sym_counter[1], - (unsigned long) thr->heap->sym_counter[0]); + + duk_int_t flen = DUK_SNPRINTF((char *) p, + 1 + 17 + 1, /* B || format || C for NUL */ + "\xFF" "%lx-%lx", + (unsigned long) thr->heap->sym_counter[1], + (unsigned long) thr->heap->sym_counter[0]); + + /* make sure that we had enough room to format the symbol */ + DUK_ASSERT(flen > 0 && flen <= 1 + 17 /* without + 1 for NUL */); + + p += flen; + if (desc == NULL) { /* Special case for 'undefined' description, trailing * 0xff distinguishes from empty string description, From 1e9402dbe69ff7201a3b8df4153e0520a4ac67a3 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Thu, 6 Feb 2020 00:06:16 +0100 Subject: [PATCH 33/38] duk__bi_print with better snprintf --- src-input/duk_numconv.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src-input/duk_numconv.c b/src-input/duk_numconv.c index f2a312e1c4..5b157a9065 100644 --- a/src-input/duk_numconv.c +++ b/src-input/duk_numconv.c @@ -91,16 +91,40 @@ DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) { char buf[DUK__BI_MAX_PARTS * 9 + 64]; char *p = buf; duk_small_int_t i; + duk_int_t flen; /* No NUL term checks in this debug code. */ - p += DUK_SNPRINTF(p, sizeof(buf), "%p n=%ld", (void *) x, (long) x->n); + flen = DUK_SNPRINTF(p, 64, "%p n=%ld", (void *) x, (long) x->n); + if (flen > 63) { + p += 63; + } else if (flen > 0) { + p += flen; + } + if (x->n == 0) { - p += DUK_SNPRINTF(p, 3, " 0"); + DUK_ASSERT(p - buf < sizeof(buf)); + + flen = DUK_SNPRINTF(p, 3, " 0"); + if (flen > 2) { + p += 2; + } else if (flen > 0) { + p += flen; + } } for (i = x->n - 1; i >= 0; i--) { - p += DUK_SNPRINTF(p, 10, " %08lx", (unsigned long) x->v[i]); + DUK_ASSERT(p - buf < sizeof(buf)); + + flen = DUK_SNPRINTF(p, 10, " %08lx", (unsigned long) x->v[i]); + if (flen > 9) { + p += 9; + } else if (flen > 0) { + p += flen; + } } + *p = 0; /* finally, NUL terminate buf regardless of snprintf */ + DUK_ASSERT(p - buf < sizeof(buf)); + DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf)); } #endif From 2688816813cc8bb8072874e440fb6615a8f5e9b0 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Thu, 6 Feb 2020 00:25:14 +0100 Subject: [PATCH 34/38] Use hex dectables to parse membased ptrs --- src-input/duk_util_misc.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index ff5415612c..1ce5c0d09e 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -223,7 +223,6 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void * DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** ptr) { #if defined(DUK_USE_MEMBASED_POINTER_ENCODING) duk_size_t i; - unsigned char a, b; union duk_ptr_access ptraccess; *ptr = NULL; @@ -245,24 +244,7 @@ DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** } for (i = 0; i < sizeof(void *); i++) { - a = (unsigned char) buf[2 * i + 0]; - b = (unsigned char) buf[2 * i + 1]; - - if (a >= 'a') { - a -= 'a'; - a += 10; - } else { - a -= '0'; - } - - if (b >= 'a') { - b -= 'a'; - b += 10; - } else { - b -= '0'; - } - - ptraccess.bytes[i] = ((a << 4) & 0xF0) | ((b << 0) & 0x0F); + ptraccess.bytes[i] = duk_hex_dectab_shift4[buf[2 * i + 0]] | duk_hex_dectab[buf[2 * i + 1]]; } *ptr = ptraccess.ptr; From 06181e7b01a2d9d49403c159c8f0e8ab0c87c50c Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Thu, 6 Feb 2020 00:30:16 +0100 Subject: [PATCH 35/38] C99 compatibility --- src-input/duk_bi_symbol.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src-input/duk_bi_symbol.c b/src-input/duk_bi_symbol.c index f3696e9336..789a7dadad 100644 --- a/src-input/duk_bi_symbol.c +++ b/src-input/duk_bi_symbol.c @@ -16,6 +16,7 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) { duk_uint8_t *buf; duk_uint8_t *p; duk_int_t magic; + duk_int_t flen; magic = duk_get_current_magic(thr); if (duk_is_undefined(thr, 0) && (magic == 0)) { @@ -62,11 +63,11 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) { thr->heap->sym_counter[1]++; } - duk_int_t flen = DUK_SNPRINTF((char *) p, - 1 + 17 + 1, /* B || format || C for NUL */ - "\xFF" "%lx-%lx", - (unsigned long) thr->heap->sym_counter[1], - (unsigned long) thr->heap->sym_counter[0]); + flen = DUK_SNPRINTF((char *) p, + 1 + 17 + 1, /* B || format || C for NUL */ + "\xFF" "%lx-%lx", + (unsigned long) thr->heap->sym_counter[1], + (unsigned long) thr->heap->sym_counter[0]); /* make sure that we had enough room to format the symbol */ DUK_ASSERT(flen > 0 && flen <= 1 + 17 /* without + 1 for NUL */); From 430a2fb7c990b294687becafb013d2d86bd8e469 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Wed, 12 Feb 2020 20:01:57 +0100 Subject: [PATCH 36/38] Fix indentation issues --- src-input/duk_bi_symbol.c | 18 ++++++++--------- src-input/duk_numconv.c | 42 +++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src-input/duk_bi_symbol.c b/src-input/duk_bi_symbol.c index 789a7dadad..c5c52ef3cb 100644 --- a/src-input/duk_bi_symbol.c +++ b/src-input/duk_bi_symbol.c @@ -16,7 +16,7 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) { duk_uint8_t *buf; duk_uint8_t *p; duk_int_t magic; - duk_int_t flen; + duk_int_t flen; magic = duk_get_current_magic(thr); if (duk_is_undefined(thr, 0) && (magic == 0)) { @@ -63,16 +63,16 @@ DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) { thr->heap->sym_counter[1]++; } - flen = DUK_SNPRINTF((char *) p, - 1 + 17 + 1, /* B || format || C for NUL */ - "\xFF" "%lx-%lx", - (unsigned long) thr->heap->sym_counter[1], - (unsigned long) thr->heap->sym_counter[0]); + flen = DUK_SNPRINTF((char *) p, + 1 + 17 + 1, /* B || format || C for NUL */ + "\xFF" "%lx-%lx", + (unsigned long) thr->heap->sym_counter[1], + (unsigned long) thr->heap->sym_counter[0]); - /* make sure that we had enough room to format the symbol */ - DUK_ASSERT(flen > 0 && flen <= 1 + 17 /* without + 1 for NUL */); + /* make sure that we had enough room to format the symbol */ + DUK_ASSERT(flen > 0 && flen <= 1 + 17 /* without + 1 for NUL */); - p += flen; + p += flen; if (desc == NULL) { /* Special case for 'undefined' description, trailing diff --git a/src-input/duk_numconv.c b/src-input/duk_numconv.c index 5b157a9065..47a44f7882 100644 --- a/src-input/duk_numconv.c +++ b/src-input/duk_numconv.c @@ -95,35 +95,35 @@ DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) { /* No NUL term checks in this debug code. */ flen = DUK_SNPRINTF(p, 64, "%p n=%ld", (void *) x, (long) x->n); - if (flen > 63) { - p += 63; - } else if (flen > 0) { - p += flen; - } + if (flen > 63) { + p += 63; + } else if (flen > 0) { + p += flen; + } if (x->n == 0) { - DUK_ASSERT(p - buf < sizeof(buf)); + DUK_ASSERT(p - buf < sizeof(buf)); flen = DUK_SNPRINTF(p, 3, " 0"); - if (flen > 2) { - p += 2; - } else if (flen > 0) { - p += flen; - } + if (flen > 2) { + p += 2; + } else if (flen > 0) { + p += flen; + } } for (i = x->n - 1; i >= 0; i--) { - DUK_ASSERT(p - buf < sizeof(buf)); - - flen = DUK_SNPRINTF(p, 10, " %08lx", (unsigned long) x->v[i]); - if (flen > 9) { - p += 9; - } else if (flen > 0) { - p += flen; - } + DUK_ASSERT(p - buf < sizeof(buf)); + + flen = DUK_SNPRINTF(p, 10, " %08lx", (unsigned long) x->v[i]); + if (flen > 9) { + p += 9; + } else if (flen > 0) { + p += flen; + } } - *p = 0; /* finally, NUL terminate buf regardless of snprintf */ - DUK_ASSERT(p - buf < sizeof(buf)); + *p = 0; /* finally, NUL terminate buf regardless of snprintf */ + DUK_ASSERT(p - buf < sizeof(buf)); DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf)); } From 345ab2d161c7a8f0cf170de9317677860f37c59b Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 29 Feb 2020 13:19:21 +0100 Subject: [PATCH 37/38] Format void** to void ** --- src-input/duk_util.h | 2 +- src-input/duk_util_misc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-input/duk_util.h b/src-input/duk_util.h index 588a4d7602..9194a3d37d 100644 --- a/src-input/duk_util.h +++ b/src-input/duk_util.h @@ -763,7 +763,7 @@ DUK_INTERNAL_DECL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, v * * Returns: 0 if parsing failed, 1 if parsing is successful. */ -DUK_INTERNAL_DECL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** ptr); +DUK_INTERNAL_DECL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void **ptr); #endif #endif /* DUK_UTIL_H_INCLUDED */ diff --git a/src-input/duk_util_misc.c b/src-input/duk_util_misc.c index 1ce5c0d09e..c3b8898c51 100644 --- a/src-input/duk_util_misc.c +++ b/src-input/duk_util_misc.c @@ -220,7 +220,7 @@ DUK_INTERNAL duk_size_t duk_encode_pointer_cstr(char* buf, duk_size_t sz, void * } #if defined(DUK_USE_JX) -DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void** ptr) { +DUK_INTERNAL int duk_decode_pointer_cstr(const char* buf, duk_size_t sz, void **ptr) { #if defined(DUK_USE_MEMBASED_POINTER_ENCODING) duk_size_t i; union duk_ptr_access ptraccess; From ead84741b8a60c13a09c2a95fc93f9ec504bc4a8 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Sat, 29 Feb 2020 13:27:01 +0100 Subject: [PATCH 38/38] DUK_USE_MEMBASED_POINTER_ENCODING introduced in 3.0.0 --- config/config-options/DUK_USE_MEMBASED_POINTER_ENCODING.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config-options/DUK_USE_MEMBASED_POINTER_ENCODING.yaml b/config/config-options/DUK_USE_MEMBASED_POINTER_ENCODING.yaml index ae4a246940..34d34d1dcb 100644 --- a/config/config-options/DUK_USE_MEMBASED_POINTER_ENCODING.yaml +++ b/config/config-options/DUK_USE_MEMBASED_POINTER_ENCODING.yaml @@ -1,5 +1,5 @@ define: DUK_USE_MEMBASED_POINTER_ENCODING -introduced: 2.7.0 +introduced: 3.0.0 default: false tags: - ecmascript