[njs] Limiting recursion depth while compiling.

Dmitry Volyntsev xeioex at nginx.com
Fri Aug 23 16:10:22 UTC 2019


details:   https://hg.nginx.org/njs/rev/8057f3ad56c1
branches:  
changeset: 1141:8057f3ad56c1
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Fri Aug 23 15:13:45 2019 +0300
description:
Limiting recursion depth while compiling.

This closes #146 issue on Github.

diffstat:

 src/njs_generator.c         |  20 +++++++++++++++++++-
 src/njs_generator.h         |   2 ++
 src/njs_parser.c            |  10 ++++++++++
 src/njs_parser.h            |  13 +++++++++++++
 src/njs_parser_expression.c |  14 ++++++++++++++
 5 files changed, 58 insertions(+), 1 deletions(-)

diffs (148 lines):

diff -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_generator.c
--- a/src/njs_generator.c	Thu Aug 22 18:27:34 2019 +0300
+++ b/src/njs_generator.c	Fri Aug 23 15:13:45 2019 +0300
@@ -257,7 +257,7 @@ static const njs_str_t  undef_label  = {
 
 
 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_generato
 }
 
 
+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 -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_generator.h
--- a/src/njs_generator.h	Thu Aug 22 18:27:34 2019 +0300
+++ b/src/njs_generator.h	Fri Aug 23 15:13:45 2019 +0300
@@ -24,6 +24,8 @@ struct njs_generator_s {
 
     /* Parsing Function() or eval(). */
     uint8_t                         runtime;           /* 1 bit */
+
+    njs_uint_t                      count;
 };
 
 
diff -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_parser.c
--- a/src/njs_parser.c	Thu Aug 22 18:27:34 2019 +0300
+++ b/src/njs_parser.c	Fri Aug 23 15:13:45 2019 +0300
@@ -127,6 +127,11 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p
 
     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,
 
     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 -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_parser.h
--- a/src/njs_parser.h	Thu Aug 22 18:27:34 2019 +0300
+++ b/src/njs_parser.h	Fri Aug 23 15:13:45 2019 +0300
@@ -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_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 -r 6923d5ac84bc -r 8057f3ad56c1 src/njs_parser_expression.c
--- a/src/njs_parser_expression.c	Thu Aug 22 18:27:34 2019 +0300
+++ b/src/njs_parser_expression.c	Fri Aug 23 15:13:45 2019 +0300
@@ -744,7 +744,11 @@ njs_parser_call_expression(njs_vm_t *vm,
         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,
             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, 
         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;
         }


More information about the nginx-devel mailing list