MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add parse depth protection

+53 -30
+2
examples/spec/localstorage.js
··· 1 + import { unlinkSync } from 'ant:fs'; 1 2 import { test, testThrows, summary } from './helpers.js'; 2 3 3 4 console.log('localStorage Tests\n'); ··· 90 91 test('JSON storage age', retrieved.age, 30); 91 92 92 93 localStorage.clear(); 94 + unlinkSync('storage.json'); 93 95 94 96 summary();
-3
include/config.h
··· 13 13 #define ANT_BUILD_DATE "unknown" 14 14 #endif 15 15 16 - #define JS_EXPR_MAX 20 17 - #define JS_GC_THRESHOLD 0.75 18 - 19 16 #define SLOTMASK ~(((jsoff_t) ~0) >> 1) 20 17 #define CONSTMASK (~(((jsoff_t) ~0) >> 1) >> 1) 21 18 #define ARRMASK (~(((jsoff_t) ~0) >> 1) >> 2)
-3
include/config.h.in
··· 5 5 #define ANT_GIT_HASH "@ANT_GIT_HASH@" 6 6 #define ANT_BUILD_DATE "@ANT_BUILD_DATE@" 7 7 8 - #define JS_EXPR_MAX 20 9 - #define JS_GC_THRESHOLD 0.75 10 - 11 8 #define SLOTMASK ~(((jsoff_t) ~0) >> 1) 12 9 #define CONSTMASK (~(((jsoff_t) ~0) >> 1) >> 1) 13 10 #define ARRMASK (~(((jsoff_t) ~0) >> 1) >> 2)
+5 -1
include/internal.h
··· 45 45 uint64_t sym_counter; // counter for generating unique symbol IDs 46 46 bool needs_gc; // deferred GC flag, checked at statement boundaries 47 47 int eval_depth; // recursion depth of js_eval calls 48 + int parse_depth; // recursion depth of parser (for stack overflow protection) 48 49 }; 49 50 50 51 #define JS_T_OBJ 0 ··· 59 60 #define JS_V_PROMISE 12 60 61 #define JS_V_BIGINT 14 61 62 #define JS_V_GENERATOR 17 62 - #define JS_HASH_SIZE 512 63 + 64 + #define JS_HASH_SIZE 512 65 + #define JS_MAX_PARSE_DEPTH (1024 * 2) 66 + #define JS_ERR_NO_STACK (1 << 8) 63 67 64 68 #define NANBOX_PREFIX 0x7FC0000000000000ULL 65 69 #define NANBOX_PREFIX_CHK 0x3FEULL
+1 -1
meson.build
··· 96 96 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 97 97 98 98 version_conf = configuration_data() 99 - version_conf.set('ANT_VERSION', '0.3.2.15') 99 + version_conf.set('ANT_VERSION', '0.3.2.16') 100 100 version_conf.set('ANT_GIT_HASH', git_hash) 101 101 version_conf.set('ANT_BUILD_DATE', build_date) 102 102
+45 -22
src/ant.c
··· 692 692 return (tok >= TOK_ASYNC && tok <= TOK_GLOBAL_THIS) || tok == TOK_TYPEOF; 693 693 } 694 694 695 + static bool is_valid_arrow_param_tok(uint8_t tok) { 696 + static const uint64_t bits[4] = { 697 + 0x0004000000000F0Cull, 698 + 0x001CC01003C00000ull, 699 + 0x0000000000800100ull, 700 + 0x0000000000000000ull 701 + }; 702 + return (bits[tok >> 6] >> (tok & 63)) & 1; 703 + } 704 + 695 705 static uint32_t js_to_uint32(double d) { 696 706 if (!isfinite(d) || d == 0) return 0; 697 707 double sign = (d < 0) ? -1.0 : 1.0; ··· 2098 2108 int error_col = 0; 2099 2109 char error_msg[256] = {0}; 2100 2110 2111 + bool no_stack = (err_type & JS_ERR_NO_STACK) != 0; 2112 + err_type = (js_err_type_t)(err_type & ~JS_ERR_NO_STACK); 2113 + 2101 2114 if (!js->errmsg) { 2102 2115 js->errmsg_size = 4096; 2103 2116 js->errmsg = (char *)malloc(js->errmsg_size); ··· 2137 2150 n += (size_t) snprintf(js->errmsg + n, remaining, "\x1b[31m%s\x1b[0m: \x1b[1m%s\x1b[0m", err_name, error_msg); 2138 2151 } 2139 2152 2140 - format_error_stack(js, &n, line, col, true, error_line, error_col); 2153 + if (!no_stack) { 2154 + format_error_stack(js, &n, line, col, true, error_line, error_col); 2155 + } 2141 2156 2142 2157 js->pos = js->clen, js->tok = TOK_EOF, js->consumed = 0; 2143 2158 return mkval(T_ERR, 0); ··· 7447 7462 7448 7463 static jsval_t js_group(struct js *js) { 7449 7464 if (next(js) == TOK_LPAREN) { 7465 + if (++js->parse_depth > JS_MAX_PARSE_DEPTH) { 7466 + js->parse_depth--; 7467 + return js_mkerr_typed(js, JS_ERR_RANGE | JS_ERR_NO_STACK, "Maximum call stack size exceeded"); 7468 + } 7450 7469 jsoff_t paren_start = js->pos - 1; 7451 7470 js->consumed = 1; 7452 7471 ··· 7462 7481 while (paren_depth > 0 && next(js) != TOK_EOF) { 7463 7482 if (js->tok == TOK_LPAREN) paren_depth++; 7464 7483 else if (js->tok == TOK_RPAREN) paren_depth--; 7465 - 7466 - if (paren_depth > 0) { 7467 - if (js->tok != TOK_IDENTIFIER && js->tok != TOK_COMMA && js->tok != TOK_REST && 7468 - js->tok != TOK_ASSIGN && js->tok != TOK_NUMBER && js->tok != TOK_STRING && 7469 - js->tok != TOK_TRUE && js->tok != TOK_FALSE && js->tok != TOK_NULL && 7470 - js->tok != TOK_UNDEF && js->tok != TOK_LBRACKET && js->tok != TOK_RBRACKET && 7471 - js->tok != TOK_LBRACE && js->tok != TOK_RBRACE && js->tok != TOK_DOT && 7472 - js->tok != TOK_PLUS && js->tok != TOK_MINUS && js->tok != TOK_MUL && js->tok != TOK_DIV) { 7473 - could_be_arrow = false; 7474 - } 7475 - } 7484 + if (paren_depth > 0 && !is_valid_arrow_param_tok(js->tok)) could_be_arrow = false; 7476 7485 js->consumed = 1; 7477 7486 } 7478 7487 ··· 7486 7495 7487 7496 if (is_arrow) { 7488 7497 js->flags |= F_NOEXEC; 7489 - while (next(js) != TOK_RPAREN && next(js) != TOK_EOF) { 7490 - js->consumed = 1; 7498 + while (next(js) != TOK_RPAREN && next(js) != TOK_EOF) js->consumed = 1; 7499 + 7500 + if (next(js) != TOK_RPAREN) { 7501 + js->parse_depth--; 7502 + return js_mkerr_typed(js, JS_ERR_SYNTAX, ") expected"); 7491 7503 } 7492 - if (next(js) != TOK_RPAREN) return js_mkerr_typed(js, JS_ERR_SYNTAX, ") expected"); 7504 + 7493 7505 js->consumed = 1; 7494 7506 js->flags = saved_flags; 7495 7507 7496 - if (next(js) != TOK_ARROW) return js_mkerr_typed(js, JS_ERR_SYNTAX, "=> expected"); 7508 + if (next(js) != TOK_ARROW) { 7509 + js->parse_depth--; 7510 + return js_mkerr_typed(js, JS_ERR_SYNTAX, "=> expected"); 7511 + } 7512 + 7497 7513 js->consumed = 1; 7514 + js->parse_depth--; 7498 7515 7499 7516 return js_arrow_func(js, paren_start, paren_end, false); 7500 7517 } else { 7501 7518 jsval_t v = js_expr(js); 7502 - if (is_err(v)) return v; 7519 + if (is_err(v)) { js->parse_depth--; return v; } 7520 + 7503 7521 while (next(js) == TOK_COMMA) { 7504 7522 js->consumed = 1; 7505 7523 v = js_expr(js); 7506 - if (is_err(v)) return v; 7524 + if (is_err(v)) { js->parse_depth--; return v; } 7525 + } 7526 + 7527 + if (next(js) != TOK_RPAREN) { 7528 + js->parse_depth--; 7529 + return js_mkerr_typed(js, JS_ERR_SYNTAX, ") expected"); 7507 7530 } 7508 - if (next(js) != TOK_RPAREN) return js_mkerr_typed(js, JS_ERR_SYNTAX, ") expected"); 7531 + 7509 7532 js->consumed = 1; 7533 + js->parse_depth--; 7534 + 7510 7535 return v; 7511 7536 } 7512 - } else { 7513 - return js_literal(js); 7514 - } 7537 + } else return js_literal(js); 7515 7538 } 7516 7539 7517 7540 static jsval_t js_call_dot(struct js *js) {