Skip to content

Commit 66c17dd

Browse files
committed
Fix memory leak when using continue or break statement with syntaxError
This patch fixes #5062. JerryScript-DCO-1.0-Signed-off-by: Gergo Csizi [email protected]
1 parent b3fa5e0 commit 66c17dd

File tree

7 files changed

+142
-13
lines changed

7 files changed

+142
-13
lines changed

jerry-core/parser/js/js-parser-internal.h

+16
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,16 @@ typedef struct parser_branch_node_t
366366
parser_branch_t branch; /**< branch */
367367
} parser_branch_node_t;
368368

369+
/**
370+
* All data allocated by the parser is
371+
* stored in parser_data_pages in the memory.
372+
*/
373+
typedef struct parser_branch_list_t
374+
{
375+
struct parser_branch_list_t *next_p; /**< next page */
376+
parser_branch_node_t *branch_node_p;
377+
} parser_branch_list_t;
378+
369379
/**
370380
* Items of scope stack.
371381
*/
@@ -591,6 +601,7 @@ typedef struct
591601
ecma_value_t tagged_template_literal_cp; /**< compessed pointer to the tagged template literal collection */
592602
parser_private_context_t *private_context_p; /**< private context */
593603
uint8_t stack_top_uint8; /**< top byte stored on the stack */
604+
parser_branch_list_t *branch_list; /**< list of branches */
594605

595606
#ifndef JERRY_NDEBUG
596607
/* Variables for debugging / logging. */
@@ -654,6 +665,11 @@ void *parser_list_get (parser_list_t *list_p, size_t index);
654665
void parser_list_iterator_init (parser_list_t *list_p, parser_list_iterator_t *iterator_p);
655666
void *parser_list_iterator_next (parser_list_iterator_t *iterator_p);
656667

668+
void parser_branch_list_init (parser_context_t *context_p);
669+
void *parser_branch_list_append (parser_context_t *context_p);
670+
void parser_branch_list_remove (const parser_context_t *context_p, const parser_branch_node_t *node_p);
671+
void parser_branch_list_free (const parser_context_t *context_p);
672+
657673
/* Parser stack. Optimized for pushing bytes.
658674
* Pop functions never throws error. */
659675

jerry-core/parser/js/js-parser-mem.c

+99
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,105 @@ parser_list_iterator_next (parser_list_iterator_t *iterator_p) /**< iterator */
327327
return result;
328328
} /* parser_list_iterator_next */
329329

330+
/*
331+
* Init branch linked list.
332+
*/
333+
void
334+
parser_branch_list_init (parser_context_t *context_p)
335+
{
336+
context_p->branch_list = (parser_branch_list_t *) parser_malloc (context_p, sizeof (parser_branch_list_t));
337+
context_p->branch_list->branch_node_p = NULL;
338+
context_p->branch_list->next_p = NULL;
339+
} /* parser_branch_list_init */
340+
341+
/**
342+
* Append a branch node to the branch list.
343+
*
344+
* @return the newly created branch node.
345+
*/
346+
void *
347+
parser_branch_list_append (parser_context_t *context_p)
348+
{
349+
parser_branch_node_t *result = parser_malloc (context_p, sizeof (parser_branch_node_t));
350+
351+
if (result == NULL)
352+
{
353+
return NULL;
354+
}
355+
356+
parser_branch_list_t *last_pos = context_p->branch_list;
357+
while (last_pos->next_p != NULL)
358+
{
359+
last_pos = last_pos->next_p;
360+
}
361+
362+
last_pos->next_p = (parser_branch_list_t *) parser_malloc (context_p, sizeof (parser_branch_list_t));
363+
last_pos->next_p->branch_node_p = result;
364+
last_pos->next_p->next_p = NULL;
365+
366+
return result;
367+
} /* parser_branch_list_append */
368+
369+
/**
370+
* Remove a branch node from the branch list.
371+
*/
372+
void
373+
parser_branch_list_remove (const parser_context_t *context_p, const parser_branch_node_t *node_p)
374+
{
375+
parser_branch_list_t *pos = context_p->branch_list;
376+
parser_branch_list_t *prev_pos = NULL;
377+
378+
while (pos->next_p != NULL && pos->branch_node_p != node_p)
379+
{
380+
prev_pos = pos;
381+
pos = pos->next_p;
382+
}
383+
384+
if (pos->branch_node_p != node_p)
385+
{
386+
return;
387+
}
388+
389+
parser_branch_list_t *next_pos = pos->next_p;
390+
391+
parser_free (pos->branch_node_p, sizeof (parser_branch_node_t));
392+
393+
if (prev_pos == NULL && next_pos == NULL)
394+
{
395+
context_p->branch_list->branch_node_p = NULL;
396+
return;
397+
}
398+
399+
parser_free (pos, sizeof (parser_branch_list_t));
400+
401+
if (prev_pos != NULL)
402+
{
403+
prev_pos->next_p = next_pos;
404+
}
405+
} /* parser_branch_list_remove */
406+
407+
/**
408+
* Free the branch list.
409+
*/
410+
void
411+
parser_branch_list_free (const parser_context_t *context_p)
412+
{
413+
parser_branch_list_t *pos = context_p->branch_list;
414+
parser_branch_list_t *prev_pos = NULL;
415+
416+
while (pos != NULL)
417+
{
418+
prev_pos = pos;
419+
pos = pos->next_p;
420+
if (prev_pos->branch_node_p != NULL)
421+
{
422+
parser_free (prev_pos->branch_node_p, sizeof (parser_branch_node_t));
423+
}
424+
425+
parser_free (prev_pos, sizeof (parser_branch_list_t));
426+
}
427+
} /* parser_branch_list_free */
428+
330429
/**********************************************************************/
331430
/* Parser stack management functions */
332431
/**********************************************************************/

jerry-core/parser/js/js-parser-statm.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2053,7 +2053,7 @@ parser_parse_case_statement (parser_context_t *context_p) /**< context */
20532053
parser_stack_iterator_write (&iterator, &switch_statement, sizeof (parser_switch_statement_t));
20542054

20552055
parser_set_branch_to_current_position (context_p, &branch_p->branch);
2056-
parser_free (branch_p, sizeof (parser_branch_node_t));
2056+
parser_branch_list_remove (context_p, branch_p);
20572057
} /* parser_parse_case_statement */
20582058

20592059
/**

jerry-core/parser/js/js-parser-util.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ parser_emit_cbc_forward_branch_item (parser_context_t *context_p, /**< context *
540540
* the branch is constructed locally, and copied later. */
541541
parser_emit_cbc_forward_branch (context_p, opcode, &branch);
542542

543-
new_item = (parser_branch_node_t *) parser_malloc (context_p, sizeof (parser_branch_node_t));
543+
new_item = (parser_branch_node_t *) parser_branch_list_append (context_p);
544544
new_item->branch = branch;
545545
new_item->next_p = next_p;
546546
return new_item;
@@ -730,7 +730,7 @@ parser_set_breaks_to_current_position (parser_context_t *context_p, /**< context
730730
{
731731
parser_set_branch_to_current_position (context_p, &current_p->branch);
732732
}
733-
parser_free (current_p, sizeof (parser_branch_node_t));
733+
parser_branch_list_remove (context_p, current_p);
734734
current_p = next_p;
735735
}
736736
} /* parser_set_breaks_to_current_position */

jerry-core/parser/js/js-parser.c

+3-5
Original file line numberDiff line numberDiff line change
@@ -2140,6 +2140,7 @@ parser_parse_source (void *source_p, /**< source code */
21402140
context.scope_stack_global_end = 0;
21412141
context.tagged_template_literal_cp = JMEM_CP_NULL;
21422142
context.private_context_p = NULL;
2143+
parser_branch_list_init (&context);
21432144

21442145
#ifndef JERRY_NDEBUG
21452146
context.context_stack_depth = 0;
@@ -2293,6 +2294,7 @@ parser_parse_source (void *source_p, /**< source code */
22932294
JERRY_ASSERT (!(context.status_flags & PARSER_HAS_LATE_LIT_INIT));
22942295

22952296
compiled_code_p = parser_post_processing (&context);
2297+
parser_branch_list_free (&context);
22962298
parser_list_free (&context.literal_pool);
22972299

22982300
/* When parsing is successful, only the dummy value can be remained on the stack. */
@@ -2366,11 +2368,6 @@ parser_parse_source (void *source_p, /**< source code */
23662368
}
23672369
PARSER_CATCH
23682370
{
2369-
if (context.last_statement.current_p != NULL)
2370-
{
2371-
parser_free_jumps (context.last_statement);
2372-
}
2373-
23742371
parser_free_allocated_buffer (&context);
23752372

23762373
scanner_cleanup (&context);
@@ -2383,6 +2380,7 @@ parser_parse_source (void *source_p, /**< source code */
23832380
#endif /* JERRY_MODULE_SYSTEM */
23842381

23852382
compiled_code_p = NULL;
2383+
parser_branch_list_free (&context);
23862384
parser_free_literals (&context.literal_pool);
23872385
parser_cbc_stream_free (&context.byte_code);
23882386

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright JS Foundation and other contributors, http://js.foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
( async ( ) => { for await ( const b of n ) { continue ;

tools/run-tests.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def skip_if(condition, desc):
5050
OPTIONS_DOCTESTS = ['--doctests=on', '--jerry-cmdline=off', '--error-messages=on',
5151
'--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on']
5252
OPTIONS_PROMISE_CALLBACK = ['--promise-callback=on']
53+
OPTIONS_HEAP_SIZE = ['--mem-heap=1024']
5354

5455
# Test options for unittests
5556
JERRY_UNITTESTS_OPTIONS = [
@@ -67,15 +68,15 @@ def skip_if(condition, desc):
6768
# Test options for jerry-tests
6869
JERRY_TESTS_OPTIONS = [
6970
Options('jerry_tests',
70-
OPTIONS_COMMON + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT + OPTIONS_MEM_STRESS),
71+
OPTIONS_COMMON + OPTIONS_STACK_LIMIT + OPTIONS_HEAP_SIZE + OPTIONS_GC_MARK_LIMIT + OPTIONS_MEM_STRESS),
7172
Options('jerry_tests-snapshot',
72-
OPTIONS_COMMON + OPTIONS_SNAPSHOT + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT,
73+
OPTIONS_COMMON + OPTIONS_SNAPSHOT + OPTIONS_HEAP_SIZE + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT,
7374
['--snapshot']),
7475
Options('jerry_tests-cpointer_32bit',
75-
OPTIONS_COMMON + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT
76-
+ ['--cpointer-32bit=on', '--mem-heap=1024']),
76+
OPTIONS_COMMON + OPTIONS_STACK_LIMIT + OPTIONS_HEAP_SIZE + OPTIONS_GC_MARK_LIMIT
77+
+ ['--cpointer-32bit=on']),
7778
Options('jerry_tests-external_context',
78-
OPTIONS_COMMON + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT
79+
OPTIONS_COMMON + OPTIONS_STACK_LIMIT + OPTIONS_HEAP_SIZE + OPTIONS_GC_MARK_LIMIT
7980
+ ['--external-context=on']),
8081
]
8182

0 commit comments

Comments
 (0)