Repository: nginx/njs (c)

Issue:
SEGV njs_function.c:780:17 in njs_function_capture_closure
Testcase 

```js
function v1(){

function v0(){
}

v2:;
new v3();
}

new v1();

```

ASAN

```
AddressSanitizer:DEADLYSIGNAL
=================================================================
==2336==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x0000007ef885 bp 0x7ffc1ff0d730 sp 0x7ffc1ff0d640 T0)
==2336==The signal is caused by a READ memory access.
==2336==Hint: address points to the zero page.
    #0 0x7ef884 in njs_function_capture_closure /home/xxx/Desktop/njs/src/njs_function.c:780:17
    #1 0x7ef884 in njs_function_lambda_call /home/xxx/Desktop/njs/src/njs_function.c:604
    #2 0x7ede60 in njs_function_frame_invoke /home/xxx/Desktop/njs/src/njs_function.c:686:16
    #3 0x57f25c in njs_vmcode_interpreter /home/xxx/Desktop/njs/src/njs_vmcode.c:1451:15
    #4 0x5610db in njs_vm_start /home/xxx/Desktop/njs/src/njs_vm.c:664:11
    #5 0x51d7fd in njs_engine_njs_eval /home/xxx/Desktop/njs/external/njs_shell.c:1387:16
    #6 0x519147 in njs_process_script /home/xxx/Desktop/njs/external/njs_shell.c:3528:11
    #7 0x519147 in njs_process_file /home/xxx/Desktop/njs/external/njs_shell.c:3500
    #8 0x519147 in njs_main /home/xxx/Desktop/njs/external/njs_shell.c:458
    #9 0x519147 in main /home/xxx/Desktop/njs/external/njs_shell.c:488
    #10 0x7f7dc35aec86 in __libc_start_main /build/glibc-uZu3wS/glibc-2.27/csu/../csu/libc-start.c:310
    #11 0x41b3e9 in _start (/home/xxx/Desktop/njs/build/njs+0x41b3e9)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/xxx/Desktop/njs/src/njs_function.c:780:17 in njs_function_capture_closure
==2336==ABORTING

```



Discussion:

Patch:
diff --git a/src/njs_parser.c b/src/njs_parser.c
--- a/src/njs_parser.c
+++ b/src/njs_parser.c
@@ -6699,23 +6699,32 @@ njs_parser_labelled_statement_after(njs_parser_t *parser,
 {
     njs_int_t                ret;
     uintptr_t                unique_id;
+    njs_parser_node_t        *node;
     const njs_lexer_entry_t  *entry;
 
-    if (parser->node != NULL) {
-        /* The statement is not empty block or just semicolon. */
-
-        unique_id = (uintptr_t) parser->target;
-        entry = (const njs_lexer_entry_t *) unique_id;
-
-        ret = njs_name_copy(parser->vm, &parser->node->name, &entry->name);
-        if (ret != NJS_OK) {
+    node = parser->node;
+    if (node == NULL) {
+        node = njs_parser_node_new(parser, NJS_TOKEN_BLOCK);
+        if (node == NULL) {
             return NJS_ERROR;
         }
 
-        ret = njs_label_remove(parser->vm, parser->scope, unique_id);
-        if (ret != NJS_OK) {
-            return NJS_ERROR;
-        }
+        node->token_line = token->line;
+
+        parser->node = node;
+    }
+
+    unique_id = (uintptr_t) parser->target;
+    entry = (const njs_lexer_entry_t *) unique_id;
+
+    ret = njs_name_copy(parser->vm, &parser->node->name, &entry->name);
+    if (ret != NJS_OK) {
+        return NJS_ERROR;
+    }
+
+    ret = njs_label_remove(parser->vm, parser->scope, unique_id);
+    if (ret != NJS_OK) {
+        return NJS_ERROR;
     }
 
     return njs_parser_stack_pop(parser);


Test patch:
diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c
+++ b/src/test/njs_unit_test.c
@@ -3494,6 +3494,22 @@ static njs_unit_test_t  njs_test[] =
                  "} catch(e) {c = 10;}; [c, fin]"),
       njs_str("1,1") },
 
+    { njs_str("function v1() {"
+                 "function v2 () {}"
+                 "v3:;"
+                 "1;"
+              "} v1();"),
+      njs_str("undefined") },
+
+    { njs_str("function v1() {"
+                 "function v2 () {}"
+                 "v3:;"
+              "} v1();"),
+      njs_str("undefined") },
+
+    { njs_str("{v1:;}"),
+      njs_str("undefined") },
+
     /* jumping out of a nested try-catch block. */
 
     { njs_str("var r = 0; "