From: Dmitry Volyntsev Date: Fri, 23 Aug 2019 12:13:45 +0000 (+0300) Subject: Limiting recursion depth while compiling. X-Git-Tag: 0.3.6~51 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=d2d47eb0e1891b295eb9e2ec7919f9070041c6d2;p=njs.git Limiting recursion depth while compiling. This closes #146 issue on Github. --- diff --git a/src/njs_generator.c b/src/njs_generator.c index 11bbcf0f..dbefd02c 100644 --- a/src/njs_generator.c +++ b/src/njs_generator.c @@ -257,7 +257,7 @@ static const njs_str_t undef_label = { 0xffffffff, (u_char *) "" }; static njs_int_t -njs_generator(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) +njs_generate(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { if (node == NULL) { return NJS_OK; @@ -508,6 +508,24 @@ njs_generator(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) } +njs_inline njs_int_t +njs_generator(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) +{ + njs_int_t ret; + + if (njs_slow_path(generator->count++ > 1024)) { + njs_range_error(vm, "Maximum call stack size exceeded"); + return NJS_ERROR; + } + + ret = njs_generate(vm, generator, node); + + generator->count--; + + return ret; +} + + static u_char * njs_generate_reserve(njs_vm_t *vm, njs_generator_t *generator, size_t size) { diff --git a/src/njs_generator.h b/src/njs_generator.h index 51128d7a..043a9e8f 100644 --- a/src/njs_generator.h +++ b/src/njs_generator.h @@ -24,6 +24,8 @@ struct njs_generator_s { /* Parsing Function() or eval(). */ uint8_t runtime; /* 1 bit */ + + njs_uint_t count; }; diff --git a/src/njs_parser.c b/src/njs_parser.c index ff8e20d0..02444e0e 100644 --- a/src/njs_parser.c +++ b/src/njs_parser.c @@ -127,6 +127,11 @@ njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev) node->token = NJS_TOKEN_END; + if (njs_slow_path(parser->count != 0)) { + njs_internal_error(vm, "parser->count != 0"); + return NJS_ERROR; + } + return NJS_OK; } @@ -249,7 +254,12 @@ njs_parser_statement_chain(njs_vm_t *vm, njs_parser_t *parser, last = *child; + njs_parser_enter(vm, parser); + token = njs_parser_statement(vm, parser, token); + + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return njs_parser_unexpected_token(vm, parser, token); } diff --git a/src/njs_parser.h b/src/njs_parser.h index a0bcd027..cf4062d7 100644 --- a/src/njs_parser.h +++ b/src/njs_parser.h @@ -73,6 +73,7 @@ struct njs_parser_s { njs_lexer_t *lexer; njs_parser_node_t *node; njs_parser_scope_t *scope; + njs_uint_t count; }; @@ -113,6 +114,18 @@ void njs_parser_node_error(njs_vm_t *vm, njs_parser_node_t *node, njs_value_type_t type, const char *fmt, ...); +#define njs_parser_enter(vm, parser) \ + do { \ + if (njs_slow_path((parser)->count++ > 1024)) { \ + njs_range_error(vm, "Maximum call stack size exceeded"); \ + return NJS_TOKEN_ERROR; \ + } \ + } while (0) + + +#define njs_parser_leave(parser) ((parser)->count--) + + #define njs_parser_is_lvalue(node) \ ((node)->token == NJS_TOKEN_NAME || (node)->token == NJS_TOKEN_PROPERTY) diff --git a/src/njs_parser_expression.c b/src/njs_parser_expression.c index 52851758..e46a81f9 100644 --- a/src/njs_parser_expression.c +++ b/src/njs_parser_expression.c @@ -744,7 +744,11 @@ njs_parser_call_expression(njs_vm_t *vm, njs_parser_t *parser, token = njs_parser_new_expression(vm, parser, token); } else { + njs_parser_enter(vm, parser); + token = njs_parser_terminal(vm, parser, token); + + njs_parser_leave(parser); } if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { @@ -761,7 +765,12 @@ njs_parser_call_expression(njs_vm_t *vm, njs_parser_t *parser, return token; } + njs_parser_enter(vm, parser); + token = njs_parser_call(vm, parser, token, 0); + + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } @@ -863,7 +872,12 @@ njs_parser_new_expression(njs_vm_t *vm, njs_parser_t *parser, token = njs_parser_new_expression(vm, parser, token); } else { + njs_parser_enter(vm, parser); + token = njs_parser_terminal(vm, parser, token); + + njs_parser_leave(parser); + if (njs_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; }