commit - fc4a32fe98f1da8b07f74a35f40b678692e7152b
commit + 253efe7357b42df840d4dc45a55f0cf4a765df34
blob - ef7cf4a9aa6384454941dd31063c85a568046ce3
blob + 0dc4fe20be52bd11a239b08f679bae64e99f86a2
--- CHANGELOG.md
+++ CHANGELOG.md
- Arguments checking in `Fuzz()` (#41).
- A memory leak in a Lua-based implementation of `TestOneInput()`.
- An initial buffer size in FuzzedDataProvider.
+- Memory leak in FuzzedDataProvider (#52).
blob - 35f0c1738ff5cc86ffeb13dee4f8730d693633f5
blob + 431246052f162aa44e83323c8d2ae2a22dabaf28
--- luzer/luzer.c
+++ luzer/luzer.c
/* Disable debug hook. */
LUA_SETHOOK(L, debug_hook, 0, 0);
+ lua_gc(L, LUA_GCCOLLECT, 0);
+
return rc;
}
}
NO_SANITIZE static int
+os_exit(int exit_code) {
+ lua_State *L = luaL_newstate();
+ luaL_openlibs(L);
+ lua_getglobal(L, "os");
+ if (!lua_istable(L, -1)) {
+ fprintf(stderr, "Error: 'os' table not found.\n");
+ lua_close(L);
+ return 1;
+ }
+
+ lua_getfield(L, -1, "exit");
+ if (!lua_isfunction(L, -1)) {
+ fprintf(stderr, "Error: 'os.exit' function not found.\n");
+ lua_close(L);
+ return 1;
+ }
+
+ // Remove the 'os' table from the stack, leaving only 'os.exit'
+ lua_remove(L, -2);
+ // Optional: Push an exit code argument (e.g., 1 for error)
+ lua_pushinteger(L, exit_code);
+ lua_pushboolean(L, 1);
+ lua_call(L, 1, 0);
+
+ // This part will only be reached if os.exit somehow fails
+ // or doesn't exit the process.
+ lua_close(L);
+ return 0;
+}
+
+NO_SANITIZE static void
+shutdown_lua(void)
+{
+ lua_State *L = get_global_lua_state();
+ lua_gc(L, LUA_GCCOLLECT, 0);
+ luaL_cleanup(L);
+ lua_close(L);
+ set_global_lua_state(NULL);
+}
+
+int atexit_retcode;
+
+NO_SANITIZE void
+xxx(void) {
+ _exit(atexit_retcode);
+}
+
+NO_SANITIZE static void
+graceful_exit(int retcode, bool prevent_crash_report) {
+ prevent_crash_report = true;
+ if (prevent_crash_report) {
+ // Disable libfuzzer's atexit.
+ atexit_retcode = retcode;
+ atexit(&xxx);
+ }
+ shutdown_lua();
+ os_exit(retcode);
+}
+
+NO_SANITIZE static int
luaL_fuzz(lua_State *L)
{
const char *str = luaL_checkstring(L, -1);
jit_status = luajit_has_enabled_jit(L);
set_global_lua_state(L);
- int rc = LLVMFuzzerRunDriver(&argc, &argv, &TestOneInput);
+ graceful_exit(LLVMFuzzerRunDriver(&argc, &argv, &TestOneInput), true);
- free_argv(argc, argv);
- luaL_cleanup(L);
-
- lua_pushnumber(L, rc);
-
- return 1;
+ return 0;
}
static const struct luaL_Reg Module[] = {
blob - fe734815c350ac052811554b84c94905ec236be5
blob + 3a1ae9f89c17714f98a88349ebe0ee19c079960d
--- luzer/tests/CMakeLists.txt
+++ luzer/tests/CMakeLists.txt
"${TEST_ENV};FFI_LIB_NAME=testlib.so"
"Done 10 runs in 0 second"
)
- # XXX: Memory leak in FDP is expected, should be fixed in [1].
- # 1. https://github.com/ligurio/luzer/issues/52
generate_ffi_test(luzer_ffi_asan
"${TEST_ENV};LD_PRELOAD=${ASAN_DSO_PATH};FFI_LIB_NAME=testlib_asan.so"
- "LeakSanitizer: detected memory leaks"
+ "Done 10 runs in 0 second"
)
generate_ffi_test(luzer_ffi_ubsan
"${TEST_ENV};LD_PRELOAD=${UBSAN_DSO_PATH};FFI_LIB_NAME=testlib_ubsan.so"