Skip to content

luzer: fix memory leak in FDP#66

Open
ligurio wants to merge 1 commit intomasterfrom
ligurio/gh-52-fix-fdp-memleak
Open

luzer: fix memory leak in FDP#66
ligurio wants to merge 1 commit intomasterfrom
ligurio/gh-52-fix-fdp-memleak

Conversation

@ligurio
Copy link
Copy Markdown
Owner

@ligurio ligurio commented Oct 14, 2025

Fixes #52
Fixes #65

@ligurio ligurio force-pushed the ligurio/gh-52-fix-fdp-memleak branch from 66c1af6 to ff80f13 Compare October 15, 2025 13:25
@ligurio ligurio force-pushed the ligurio/gh-52-fix-fdp-memleak branch 5 times, most recently from 3b09aa9 to 9a6f771 Compare November 10, 2025 08:31
@ligurio ligurio requested a review from Buristan November 10, 2025 08:33
Copy link
Copy Markdown
Collaborator

@Buristan Buristan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sergey,
Thanks for the patch!
I suppose the next commit may be squashed into this one as well.

Please consider my comment below.

LUA_SETHOOK(L, debug_hook, 0, 0);

/* Prevents memory leaks on module exit. */
lua_gc(L, LUA_GCCOLLECT, 0);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we have several smoking guns here:

  • Since Lua (and therefore LuaJIT) has the GC-based memory management model, it may accumulate memory between iterations of state mutations in the TestOneInput. Libfuzzer checks the possible leaks during fuzzing between state mutations. Hence, we should add -detect_leaks=0 (see options) to the fuzzer options to be sure that we don't fail valid runs due to these false positives. This option disables only intermediate checks. The shutdown check is still enabled (but it may be ignored if you specify the environment variable LSAN_OPTIONS). Adding of lua_gc(), may not be so helpful if the object is allocated once at the first call (loading library via require) and cleared on the exit.
  • Even with the aforementioned option the lua_close() isn't called since the process is finished by the atexit handler, which is set in the FuzzerDriver(). So, we will observe leaks of the FDP object allocated via new.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also https://github.com/google/atheris/blob/master/native_extension_fuzzing.md#leak-detection

Leak detection
Python is known to leak certain data, such as at interpreter initialization time. You should disable leak detection, for example with -detect_leaks=0.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Lua (and therefore LuaJIT) has the GC-based memory management model,

Honestly, I don't like the proposed solution (always disable -detect_leaks=0 for everyone). Sooner or later, this option will lead to an OOM, and we'll have to figure out why the memory leak occurred. I prefer the scenario where the test crashes at the first sign of symptoms.

I propose another solution - leave the patch as is and add a section to a documentation (done).

Even with the aforementioned option

atexit() handler helps for another case - LLVMFuzzerRunDriver() returns due to error

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, I don't like the proposed solution (always disable -detect_leaks=0 for everyone). Sooner or later, this option will lead to an OOM, and we'll have to figure out why the memory leak occurred. I prefer the scenario where the test crashes at the first sign of symptoms.

The generated input (a too large string, for example) may also lead to OOM in tests as well. This is not the part of our concern. OTOH, false-positive leaks, which are possible for user code as well, remain a problem. I'll repeat it again: -detect_leaks=0 doesn't fully disable leak detection but instead postpones it until the end of the fuzzing process, so all true leaks will be reported to the user.

Without this flag, we just see more false-positives, and have no protection against OOM in generated input as well. These reports are meaningless for the GC-based VMs.

@ligurio ligurio force-pushed the ligurio/gh-52-fix-fdp-memleak branch 4 times, most recently from 81952f0 to 494bfe8 Compare March 24, 2026 09:14
The patch fixes memory leaks in luzer that manifest themselves in
different ways:

1. `LLVMFuzzerRunDriver()` returns due to error with dictionary.
2. Lua objects accumulate memory between `TestOneInput()` runs,

but the cause is the same for everyone: Lua is a language with
GC-based memory management, and after finishing the work, we
did not free the memory occupied by Lua objects, so libFuzzer
thinks there was a memory leak.

Fixes #52
Fixes #65
@ligurio
Copy link
Copy Markdown
Owner Author

ligurio commented Mar 24, 2026

The second patch was squashed, the commit message was updated.

@ligurio ligurio force-pushed the ligurio/gh-52-fix-fdp-memleak branch from 494bfe8 to 3cf404e Compare March 24, 2026 10:30
@ligurio ligurio requested a review from Buristan March 24, 2026 10:36
@Buristan Buristan assigned ligurio and unassigned Buristan Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Segfault on parsing wrong dictionary Memory leak in FDP

2 participants