diff options
author | Angus Gratton <angus@redyak.com.au> | 2024-03-20 16:19:33 +1100 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2024-03-22 10:49:20 +1100 |
commit | 71044a4186bda22477e7daf98e718c144d22d519 (patch) | |
tree | b5a713a174d38cede7dc58df7f64c13d410d4c1d /py/parse.c | |
parent | 9d27183bde0a70521a0d189636e53975df2260eb (diff) |
py/parse: Zero out dangling parse tree pointer to fix potential GC leak.
This fixes a bug where a random Python object may become
un-garbage-collectable until an enclosing Python file (compiled on device)
finishes executing.
Details:
The mp_parse_tree_t structure is stored on the stack in top-level functions
such as parse_compile_execute() in pyexec.c (and others).
Although it quickly falls out of scope in these functions, it is usually
still in the current stack frame when the compiled code executes. (Compiler
dependent, but usually it's one stack push per function.)
This means if any Python object happens to allocate at the same address as
the (freed) root parse tree chunk, it's un-garbage-collectable as there's a
(dangling) pointer up the stack referencing this same address.
As reported by @GitHubsSilverBullet here:
https://github.com/orgs/micropython/discussions/14116#discussioncomment-8837214
This work was funded through GitHub Sponsors.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
Diffstat (limited to 'py/parse.c')
-rw-r--r-- | py/parse.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/py/parse.c b/py/parse.c index 54be8b97d..1392303e6 100644 --- a/py/parse.c +++ b/py/parse.c @@ -1386,6 +1386,7 @@ void mp_parse_tree_clear(mp_parse_tree_t *tree) { m_del(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc); chunk = next; } + tree->chunk = NULL; // Avoid dangling pointer that may live on stack } #endif // MICROPY_ENABLE_COMPILER |