diff --git a/pclsync/ppath.c b/pclsync/ppath.c index e4a053b..672928f 100644 --- a/pclsync/ppath.c +++ b/pclsync/ppath.c @@ -58,12 +58,14 @@ int64_t ppath_free_space(const char *path) { char *ppath_home() { struct stat st; const char *dir; + /* buff must be function-scoped: dir may point into it (via pw_dir) and + * must remain valid through the putil_strdup(dir) call below. */ + char buff[4096]; dir = getenv("HOME"); if (pdbg_unlikely(!dir) || pdbg_unlikely(stat(dir, &st)) || pdbg_unlikely(!pfile_stat_mode_ok(&st, 7))) { struct passwd pwd; struct passwd *result; - char buff[4096]; if (pdbg_unlikely(getpwuid_r(getuid(), &pwd, buff, sizeof(buff), &result)) || pdbg_unlikely(stat(result->pw_dir, &st)) || pdbg_unlikely(!pfile_stat_mode_ok(&st, 7))) diff --git a/tests/unit-tests/test_ptools_errptr.c b/tests/unit-tests/test_ptools_errptr.c index 42edb7e..4a0a2a3 100644 --- a/tests/unit-tests/test_ptools_errptr.c +++ b/tests/unit-tests/test_ptools_errptr.c @@ -18,6 +18,28 @@ #include #include +/* Suppress LSAN reports for intentional leaks used to verify bug behaviour. + * GCC sets __SANITIZE_ADDRESS__; Clang exposes __has_feature as a built-in. + * Use nested #if so the __has_feature() call is only evaluated when the + * compiler actually understands it (avoids "missing binary operator" on GCC). */ +#ifdef __SANITIZE_ADDRESS__ +# include +# define LSAN_DISABLE() __lsan_disable() +# define LSAN_ENABLE() __lsan_enable() +#elif defined(__has_feature) +# if __has_feature(address_sanitizer) +# include +# define LSAN_DISABLE() __lsan_disable() +# define LSAN_ENABLE() __lsan_enable() +# else +# define LSAN_DISABLE() do {} while (0) +# define LSAN_ENABLE() do {} while (0) +# endif +#else +# define LSAN_DISABLE() do {} while (0) +# define LSAN_ENABLE() do {} while (0) +#endif + /* ------------------------------------------------------------------ */ /* Allocation tracking via --wrap */ /* ------------------------------------------------------------------ */ @@ -119,6 +141,9 @@ static int run_unfixed(void) { char *errPtr = NULL; int callRes; + /* Intentional leak: suppress LSAN so the process exits cleanly and + * stdio flushes before the sanitizer reports it. */ + LSAN_DISABLE(); callRes = mock_backend_call_1(&errPtr); (void)callRes; @@ -129,6 +154,7 @@ static int run_unfixed(void) { if (errPtr) free(errPtr); + LSAN_ENABLE(); return 0; }