From d4dc1d540f32efe0d8181fbc55b759aa5f25bc52 Mon Sep 17 00:00:00 2001 From: Pastoray Date: Mon, 29 Sep 2025 23:04:24 +0100 Subject: [PATCH 01/14] WIP: Fuzz per iteration leak scan implementation --- drmemory/drmemory.c | 3 +++ drmemory/drmemory.h | 1 + drmemory/fuzzer.c | 15 +++++++++++++++ drmemory/optionsx.h | 4 ++++ drmemory/report.c | 6 ++++-- drmemory/report.h | 3 +++ 6 files changed, 30 insertions(+), 2 deletions(-) mode change 100644 => 100755 drmemory/drmemory.c mode change 100644 => 100755 drmemory/drmemory.h mode change 100644 => 100755 drmemory/fuzzer.c mode change 100644 => 100755 drmemory/optionsx.h mode change 100644 => 100755 drmemory/report.c mode change 100644 => 100755 drmemory/report.h diff --git a/drmemory/drmemory.c b/drmemory/drmemory.c old mode 100644 new mode 100755 index 4b278390f..51a10f1c4 --- a/drmemory/drmemory.c +++ b/drmemory/drmemory.c @@ -86,6 +86,7 @@ file_t f_results = INVALID_FILE; file_t f_missing_symbols; file_t f_suppress; file_t f_potential; +file_t f_fuzz; static uint num_threads; #if defined(__DATE__) && defined(__TIME__) @@ -488,6 +489,7 @@ event_exit(void) close_file(f_missing_symbols); close_file(f_suppress); close_file(f_potential); + close_file(f_fuzz); dr_fprintf(f_global, "LOG END\n"); close_file(f_global); @@ -1508,6 +1510,7 @@ create_global_logfile(void) f_suppress = open_logfile("suppress.txt", false, -1); f_potential = open_logfile(RESULTS_POTENTIAL_FNAME, false, -1); print_version(f_potential, true); + f_fuzz = open_logfile("fuzz_results.txt", false, -1); } } diff --git a/drmemory/drmemory.h b/drmemory/drmemory.h old mode 100644 new mode 100755 index 869e401ca..1c5087dd9 --- a/drmemory/drmemory.h +++ b/drmemory/drmemory.h @@ -82,6 +82,7 @@ extern file_t f_results; extern file_t f_suppress; extern file_t f_missing_symbols; extern file_t f_potential; +extern file_t f_fuzz; #ifdef WINDOWS extern app_pc ntdll_base; diff --git a/drmemory/fuzzer.c b/drmemory/fuzzer.c old mode 100644 new mode 100755 index 64f813b04..a7d349899 --- a/drmemory/fuzzer.c +++ b/drmemory/fuzzer.c @@ -30,6 +30,7 @@ #include "drx.h" #include "drfuzz_mutator.h" #include "fuzzer.h" +#include "alloc_drmem.h" #include "drmemory.h" #include "drvector.h" #include "alloc.h" @@ -1603,6 +1604,20 @@ post_fuzz(void *fuzzcxt, generic_func_t target_pc) LOG(2, LOG_PREFIX" executing post-fuzz for "PIFX"\n", target_pc); + if (option_specified.fuzz_per_iter_leak_scan) { + ELOGF(0, f_fuzz, NL"==========================================================================="NL"Thread %d report for inputs (%s, %d):", + fuzz_target.tid, fuzz_state->input_buffer, fuzz_state->input_size); + + report_leak_stats_checkpoint(); + check_reachability(false/*!at exit*/); + + // Mainly to avoid bloating the console & other files through report_summary + report_summary_to_file(f_fuzz, false, false, false); + report_leak_stats_revert(); + + ELOGF(0, f_fuzz, NL"==========================================================================="NL); + } + if (option_specified.fuzz_corpus) return post_fuzz_corpus(fuzzcxt, target_pc); diff --git a/drmemory/optionsx.h b/drmemory/optionsx.h old mode 100644 new mode 100755 index c56f982c6..96c59d1d4 --- a/drmemory/optionsx.h +++ b/drmemory/optionsx.h @@ -746,6 +746,10 @@ OPTION_CLIENT_SCOPE(drmemscope, fuzz_skip_initial, uint, 0, 0, UINT_MAX, OPTION_CLIENT_SCOPE(drmemscope, fuzz_stat_freq, uint, 0, 0, UINT_MAX, "Enable fuzzer status logging with the specified frequency", "Specify the fuzzer status log frequency in number of fuzz iterations (no status is logged when this option is not set).") +OPTION_CLIENT_BOOL(drmemscope, fuzz_per_iter_leak_scan, false, + "Saves the fuzz input that triggered a leak to the current log directory.", + "Saves the fuzz input that triggered a leak to the current log directory. The name of the file is included in the error report summary.") + #ifdef WINDOWS OPTION_CLIENT_BOOL(drmemscope, fuzz_mangled_names, false, "Enable mangled names for fuzz targets on Windows", diff --git a/drmemory/report.c b/drmemory/report.c old mode 100644 new mode 100755 index 18760fd6e..54c8d7954 --- a/drmemory/report.c +++ b/drmemory/report.c @@ -1586,6 +1586,8 @@ report_init(void) #endif ELOGF(0, f_suppress, "# File for suppressing errors found in pid %d: \"%s\""NL NL, dr_get_process_id(), dr_get_application_name()); + ELOGF(0, f_fuzz, "Dr. Memory fuzzing errors for pid %d: \"%s\""NL, + dr_get_process_id(), dr_get_application_name()); ELOGF(0, f_potential, "Dr. Memory errors that are likely to be false positives, " "for pid %d: \"%s\""NL, dr_get_process_id(), dr_get_application_name()); if ((options.lib_allowlist_frames > 0 && options.lib_allowlist[0] != '\0') || @@ -1750,7 +1752,7 @@ report_errors_found(void) /* N.B.: for PR 477013, postprocess.pl duplicates some of this syntax * exactly: try to keep the two in sync */ -static void +void report_summary_to_file(file_t f, bool stderr_too, bool print_full_stats, bool potential) { uint i; @@ -3445,7 +3447,7 @@ report_leak(bool known_malloc, app_pc addr, size_t size, size_t indirect_size, } else { /* num_unique was set to 0 after nudge */ #ifdef STATISTICS /* for num_nudges */ - ASSERT(err->id == 0 || num_nudges > 0 || + ASSERT(err->id == 0 || num_nudges > 0 || option_specified.fuzz_per_iter_leak_scan || (maybe_reachable && !options.possible_leaks) || (reachable && !options.show_reachable), "invalid dup error report!"); diff --git a/drmemory/report.h b/drmemory/report.h old mode 100644 new mode 100755 index 910fc82bc..24f6595e3 --- a/drmemory/report.h +++ b/drmemory/report.h @@ -51,6 +51,9 @@ report_fork_init(void); void report_summary(void); +void +report_summary_to_file(file_t f, bool stderr_too, bool print_full_stats, bool potential); + void report_thread_init(void *drcontext); From 378f319ff218e4c0b3d58e2857a0fb4e3a466375 Mon Sep 17 00:00:00 2001 From: Pastoray Date: Thu, 2 Oct 2025 00:23:31 +0100 Subject: [PATCH 02/14] Add option docs --- drmemory/docs/fuzzer.dox | 15 +++++++++++++++ 1 file changed, 15 insertions(+) mode change 100644 => 100755 drmemory/docs/fuzzer.dox diff --git a/drmemory/docs/fuzzer.dox b/drmemory/docs/fuzzer.dox old mode 100644 new mode 100755 index ec7707e79..13a737ae4 --- a/drmemory/docs/fuzzer.dox +++ b/drmemory/docs/fuzzer.dox @@ -177,6 +177,21 @@ you would specify the following command-line option to \p drmemory: -fuzz_corpus /path/to/inputs -fuzz_corpus_out /path/to/min_corpus/ +Dr. Memory's fuzz mode typically performs a leak scan only at the end of the entire +fuzz run or on request. This option allows you to perform leak detection after every +target function execution. + + - \p -fuzz_per_iter_leak_scan: whether to run a leak scan after **every** + target function execution. + +Enabling this option is useful for precisely isolating the input iteration that +causes a memory leak, which aids in reproduction and minimization. + +For example, to fuzz the function \p DrMemFuzzFunc with per-iteration leak scanning enabled, +you would specify the following command-line option to \p drmemory: + + -fuzz_module a.out -fuzz_function DrMemFuzzFunc -fuzz_per_iter_leak_scan + **************************************************************************** **************************************************************************** */ From 0fc1f138d88e8ab9a29b35607fff7cee8e6cd76b Mon Sep 17 00:00:00 2001 From: Pastoray Date: Thu, 2 Oct 2025 00:24:41 +0100 Subject: [PATCH 03/14] Use macro for fuzz results file name --- drmemory/drmemory.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drmemory/drmemory.h b/drmemory/drmemory.h index 1c5087dd9..cb1812812 100755 --- a/drmemory/drmemory.h +++ b/drmemory/drmemory.h @@ -74,6 +74,7 @@ extern char logsubdir[MAXIMUM_PATH]; #define RESULTS_FNAME "results.txt" #define RESULTS_POTENTIAL_FNAME "potential_errors.txt" +#define FUZZ_FNAME "fuzz_results.txt" #define POTENTIAL_PREFIX "potential" #define POTENTIAL_PREFIX_CAP "Potential" #define POTENTIAL_PREFIX_ALLCAP "POTENTIAL" From 6ef41cc795668c2e28c03ab122f7374e513a627a Mon Sep 17 00:00:00 2001 From: Pastoray Date: Thu, 2 Oct 2025 00:25:41 +0100 Subject: [PATCH 04/14] Create the file only when fuzzing is specified --- drmemory/drmemory.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drmemory/drmemory.c b/drmemory/drmemory.c index 51a10f1c4..d5ee8e47f 100755 --- a/drmemory/drmemory.c +++ b/drmemory/drmemory.c @@ -489,7 +489,8 @@ event_exit(void) close_file(f_missing_symbols); close_file(f_suppress); close_file(f_potential); - close_file(f_fuzz); + if (options.fuzz) // If it was even created + close_file(f_fuzz); dr_fprintf(f_global, "LOG END\n"); close_file(f_global); @@ -1510,7 +1511,8 @@ create_global_logfile(void) f_suppress = open_logfile("suppress.txt", false, -1); f_potential = open_logfile(RESULTS_POTENTIAL_FNAME, false, -1); print_version(f_potential, true); - f_fuzz = open_logfile("fuzz_results.txt", false, -1); + if (options.fuzz) + f_fuzz = open_logfile(FUZZ_FNAME, false, -1); } } From 64d363fdbc4ec4dae119a929cbed61a1f0ae561c Mon Sep 17 00:00:00 2001 From: Pastoray Date: Thu, 2 Oct 2025 00:27:11 +0100 Subject: [PATCH 05/14] Use different function to log only leaks and not other errors --- drmemory/report.c | 21 +++++++++++++++++++-- drmemory/report.h | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drmemory/report.c b/drmemory/report.c index 54c8d7954..e99944435 100755 --- a/drmemory/report.c +++ b/drmemory/report.c @@ -1586,7 +1586,7 @@ report_init(void) #endif ELOGF(0, f_suppress, "# File for suppressing errors found in pid %d: \"%s\""NL NL, dr_get_process_id(), dr_get_application_name()); - ELOGF(0, f_fuzz, "Dr. Memory fuzzing errors for pid %d: \"%s\""NL, + ELOGF(0, f_fuzz, "Dr. Memory fuzzing leaks for pid %d (\"%s\")"NL, dr_get_process_id(), dr_get_application_name()); ELOGF(0, f_potential, "Dr. Memory errors that are likely to be false positives, " "for pid %d: \"%s\""NL, dr_get_process_id(), dr_get_application_name()); @@ -1752,7 +1752,7 @@ report_errors_found(void) /* N.B.: for PR 477013, postprocess.pl duplicates some of this syntax * exactly: try to keep the two in sync */ -void +static void report_summary_to_file(file_t f, bool stderr_too, bool print_full_stats, bool potential) { uint i; @@ -1904,10 +1904,27 @@ report_summary_to_file(file_t f, bool stderr_too, bool print_full_stats, bool po num_throttled_leaks); } } + + NOTIFY_COND(notify && options.fuzz, f, "Fuzz details: %s%c%s"NL, + logsubdir, DIRSEP, FUZZ_FNAME); + NOTIFY_COND(notify, f, "Details: %s%c%s"NL, logsubdir, DIRSEP, potential ? RESULTS_POTENTIAL_FNAME : RESULTS_FNAME); } +void +report_all_leak_stats(file_t f, bool notify, bool potential) { + report_leak_stats(f, notify, potential, ERROR_LEAK); + + if (options.possible_leaks) { + report_leak_stats(f, notify, potential, ERROR_POSSIBLE_LEAK); + } + + if (options.show_reachable) { + report_leak_stats(f, notify, potential, ERROR_REACHABLE_LEAK); + } +} + void report_summary(void) { diff --git a/drmemory/report.h b/drmemory/report.h index 24f6595e3..3a4f721d4 100755 --- a/drmemory/report.h +++ b/drmemory/report.h @@ -52,7 +52,7 @@ void report_summary(void); void -report_summary_to_file(file_t f, bool stderr_too, bool print_full_stats, bool potential); +report_all_leak_stats(file_t f, bool notify, bool potential); void report_thread_init(void *drcontext); From a74880fa6df65b6ede84730acea4e4a6e5586add Mon Sep 17 00:00:00 2001 From: Pastoray Date: Thu, 2 Oct 2025 00:29:25 +0100 Subject: [PATCH 06/14] Better file formatting --- drmemory/fuzzer.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drmemory/fuzzer.c b/drmemory/fuzzer.c index a7d349899..381f2ce0c 100755 --- a/drmemory/fuzzer.c +++ b/drmemory/fuzzer.c @@ -1605,14 +1605,17 @@ post_fuzz(void *fuzzcxt, generic_func_t target_pc) LOG(2, LOG_PREFIX" executing post-fuzz for "PIFX"\n", target_pc); if (option_specified.fuzz_per_iter_leak_scan) { - ELOGF(0, f_fuzz, NL"==========================================================================="NL"Thread %d report for inputs (%s, %d):", + ELOGF(0, f_fuzz, NL"Thread %d report for inputs (%s, %d):"NL"==========================================================================="NL, fuzz_target.tid, fuzz_state->input_buffer, fuzz_state->input_size); report_leak_stats_checkpoint(); check_reachability(false/*!at exit*/); - // Mainly to avoid bloating the console & other files through report_summary - report_summary_to_file(f_fuzz, false, false, false); + ELOGF(0, f_fuzz, NL" LEAKS:"NL); + report_all_leak_stats(f_fuzz, false, false); + ELOGF(0, f_fuzz, NL" POTENTIAL LEAKS:"NL); + report_all_leak_stats(f_fuzz, false, true); + report_leak_stats_revert(); ELOGF(0, f_fuzz, NL"==========================================================================="NL); From 39bfcb2b53a29fd675a01b772362764662ed2ee3 Mon Sep 17 00:00:00 2001 From: Pastoray Date: Thu, 2 Oct 2025 00:30:30 +0100 Subject: [PATCH 07/14] Add fuzz_per_iter_leak_scan to the set of options that enable fuzzing --- drmemory/options.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 100755 drmemory/options.c diff --git a/drmemory/options.c b/drmemory/options.c old mode 100644 new mode 100755 index 52796a7c9..5890c022f --- a/drmemory/options.c +++ b/drmemory/options.c @@ -580,7 +580,8 @@ options_init(const char *opstr) option_specified.fuzz_buffer_offset || option_specified.fuzz_skip_initial || IF_WINDOWS(option_specified.fuzz_mangled_names ||) - option_specified.fuzz_stat_freq) { + option_specified.fuzz_stat_freq || + option_specified.fuzz_per_iter_leak_scan) { options.fuzz = true; /* enable replace_buffer by default if fuzzing with input files */ if ((option_specified.fuzz_corpus || option_specified.fuzz_input_file) && From ce7bd743fe13937066e19189e388ee5773629289 Mon Sep 17 00:00:00 2001 From: Pastoray Date: Thu, 2 Oct 2025 00:39:58 +0100 Subject: [PATCH 08/14] Mention file where fuzzing results are written --- drmemory/docs/fuzzer.dox | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drmemory/docs/fuzzer.dox b/drmemory/docs/fuzzer.dox index 13a737ae4..5430a87bd 100755 --- a/drmemory/docs/fuzzer.dox +++ b/drmemory/docs/fuzzer.dox @@ -185,7 +185,8 @@ target function execution. target function execution. Enabling this option is useful for precisely isolating the input iteration that -causes a memory leak, which aids in reproduction and minimization. +causes a memory leak, which aids in reproduction and minimization. The outputs +of these leak scans are stored in the fuzz_results.txt file. For example, to fuzz the function \p DrMemFuzzFunc with per-iteration leak scanning enabled, you would specify the following command-line option to \p drmemory: From e1ef14fa9e60024ba7734dc6f005c66c6e5086cd Mon Sep 17 00:00:00 2001 From: Pastoray Date: Fri, 3 Oct 2025 00:30:57 +0100 Subject: [PATCH 09/14] Add simple regression test per-iter leak scan --- tests/fuzz/CMakeLists.txt | 4 ++++ tests/fuzz/fuzz_buffer.leak_iter.out | 28 ++++++++++++++++++++++++++++ tests/fuzz/fuzz_buffer.leak_iter.res | 21 +++++++++++++++++++++ 3 files changed, 53 insertions(+) mode change 100644 => 100755 tests/fuzz/CMakeLists.txt create mode 100644 tests/fuzz/fuzz_buffer.leak_iter.out create mode 100644 tests/fuzz/fuzz_buffer.leak_iter.res diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt old mode 100644 new mode 100755 index daa5542c0..329d7c0a0 --- a/tests/fuzz/CMakeLists.txt +++ b/tests/fuzz/CMakeLists.txt @@ -138,6 +138,10 @@ newtest_ex(fuzz_buffer.cpp fuzz_buffer.cpp "initialize" "" OFF "" 0) set(fuzz_buffer_drmem_ops "-no_fuzz_dump_on_error;-fuzz_target;${fuzz_buffer_symbol}|3|1|2|10${cpp_callconv}${enable_mangled_names}") +set(fuzz_iter_leak_base_ops + "-no_fuzz_dump_on_error;-fuzz_target;
!repeatme|2|0|1|10;-fuzz_per_iter_leak_scan") +newtest_nobuild_ex(fuzz_buffer.leak_iter fuzz_buffer + "initialize;leak" "${fuzz_iter_leak_base_ops}" "" OFF "" 0 "") if (NOT X64) # test detection of errors that requires shadow-memory newtest_nobuild_ex(fuzz_buffer.uninitialized.cpp fuzz_buffer.cpp "" "${fuzz_buffer_drmem_ops}" "" OFF "" 0 "") diff --git a/tests/fuzz/fuzz_buffer.leak_iter.out b/tests/fuzz/fuzz_buffer.leak_iter.out new file mode 100644 index 000000000..877041371 --- /dev/null +++ b/tests/fuzz/fuzz_buffer.leak_iter.out @@ -0,0 +1,28 @@ +# ********************************************************** +# Copyright (c) 2015 Google, Inc. All rights reserved. +# ********************************************************** +# +# Dr. Memory: the memory debugger +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; +# version 2.1 of the License, and no later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +done +~~Dr.M~~ ERRORS FOUND: +~~Dr.M~~ 0 unique, 0 total unaddressable access(es) +~~Dr.M~~ 0 unique, 0 total uninitialized access(es) +~~Dr.M~~ 0 unique, 0 total invalid heap argument(s) +~~Dr.M~~ 0 unique, 0 total warning(s) +~~Dr.M~~ 0 unique, 1 total, 16 byte(s) of leak(s) +~~Dr.M~~ 0 unique, 0 total, 0 byte(s) of possible leak(s) \ No newline at end of file diff --git a/tests/fuzz/fuzz_buffer.leak_iter.res b/tests/fuzz/fuzz_buffer.leak_iter.res new file mode 100644 index 000000000..f00d88962 --- /dev/null +++ b/tests/fuzz/fuzz_buffer.leak_iter.res @@ -0,0 +1,21 @@ +# ********************************************************** +# Copyright (c) 2015 Google, Inc. All rights reserved. +# ********************************************************** +# +# Dr. Memory: the memory debugger +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; +# version 2.1 of the License, and no later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +Error #1: LEAK 16 direct bytes \ No newline at end of file From 9a23f64ec5422d0e10cb7cc14ff654f5633020e6 Mon Sep 17 00:00:00 2001 From: Pastoray Date: Fri, 3 Oct 2025 16:15:08 +0100 Subject: [PATCH 10/14] Mention related leak options for -fuzz_per_iter_leak_scan --- drmemory/docs/fuzzer.dox | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drmemory/docs/fuzzer.dox b/drmemory/docs/fuzzer.dox index 5430a87bd..5aae54ea2 100755 --- a/drmemory/docs/fuzzer.dox +++ b/drmemory/docs/fuzzer.dox @@ -186,7 +186,8 @@ target function execution. Enabling this option is useful for precisely isolating the input iteration that causes a memory leak, which aids in reproduction and minimization. The outputs -of these leak scans are stored in the fuzz_results.txt file. +of these leak scans are stored in the fuzz_results.txt file. The types of leaks reported +are additionally controlled by the \p -possible_leaks and \p -show_reachable options. For example, to fuzz the function \p DrMemFuzzFunc with per-iteration leak scanning enabled, you would specify the following command-line option to \p drmemory: From 6b52090a8820c84941508ebe286d394eebc7f3af Mon Sep 17 00:00:00 2001 From: Pastoray Date: Sat, 4 Oct 2025 23:02:52 +0100 Subject: [PATCH 11/14] Add note on cumulative leak results for -fuzz_per_iter_leak_scan --- drmemory/docs/fuzzer.dox | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drmemory/docs/fuzzer.dox b/drmemory/docs/fuzzer.dox index 5aae54ea2..29c62fba5 100755 --- a/drmemory/docs/fuzzer.dox +++ b/drmemory/docs/fuzzer.dox @@ -177,11 +177,13 @@ you would specify the following command-line option to \p drmemory: -fuzz_corpus /path/to/inputs -fuzz_corpus_out /path/to/min_corpus/ +\section sec_per_iter_leak_scan Per-Iteration Leak Scanning + Dr. Memory's fuzz mode typically performs a leak scan only at the end of the entire fuzz run or on request. This option allows you to perform leak detection after every target function execution. - - \p -fuzz_per_iter_leak_scan: whether to run a leak scan after **every** + - \p -fuzz_per_iter_leak_scan: whether to run a leak scan after every target function execution. Enabling this option is useful for precisely isolating the input iteration that @@ -189,6 +191,10 @@ causes a memory leak, which aids in reproduction and minimization. The outputs of these leak scans are stored in the fuzz_results.txt file. The types of leaks reported are additionally controlled by the \p -possible_leaks and \p -show_reachable options. +Note that the leak scan results include all leaks found to date, which will overlap with +leaks found in prior iterations. The user must currently infer manually which leaks +are newly found in the displayed iteration. + For example, to fuzz the function \p DrMemFuzzFunc with per-iteration leak scanning enabled, you would specify the following command-line option to \p drmemory: From 53e0441a18ac9f52d7de3723f7f36fc656a41094 Mon Sep 17 00:00:00 2001 From: Pastoray Date: Sat, 4 Oct 2025 23:03:24 +0100 Subject: [PATCH 12/14] Improve logging details --- drmemory/fuzzer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drmemory/fuzzer.c b/drmemory/fuzzer.c index 381f2ce0c..9b1c4567b 100755 --- a/drmemory/fuzzer.c +++ b/drmemory/fuzzer.c @@ -1605,9 +1605,10 @@ post_fuzz(void *fuzzcxt, generic_func_t target_pc) LOG(2, LOG_PREFIX" executing post-fuzz for "PIFX"\n", target_pc); if (option_specified.fuzz_per_iter_leak_scan) { - ELOGF(0, f_fuzz, NL"Thread %d report for inputs (%s, %d):"NL"==========================================================================="NL, - fuzz_target.tid, fuzz_state->input_buffer, fuzz_state->input_size); + ELOGF(0, f_fuzz, NL"[Thread (#%d) Iteration (#%d)]: Report for inputs (%s, %d):"NL"==========================================================================="NL, + fuzz_target.tid, fuzz_state->repeat_index + 1, fuzz_state->input_buffer, fuzz_state->input_size); + /* XXX i#1797: Remove leaks seen in prior iterations to only display new leaks found in this iteration */ report_leak_stats_checkpoint(); check_reachability(false/*!at exit*/); From 05de02f3cdaf72beda85e39c2a91653c99a43306 Mon Sep 17 00:00:00 2001 From: Pastoray Date: Sat, 4 Oct 2025 23:38:20 +0100 Subject: [PATCH 13/14] Test: Fail if fuzz_results.txt is missing or patterns don't match. --- tests/fuzz/CMakeLists.txt | 1 + tests/fuzz/fuzz_buffer.leak_iter.res | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) mode change 100644 => 100755 tests/fuzz/fuzz_buffer.leak_iter.res diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt index 329d7c0a0..f5a638050 100755 --- a/tests/fuzz/CMakeLists.txt +++ b/tests/fuzz/CMakeLists.txt @@ -140,6 +140,7 @@ set(fuzz_buffer_drmem_ops "-no_fuzz_dump_on_error;-fuzz_target;${fuzz_buffer_symbol}|3|1|2|10${cpp_callconv}${enable_mangled_names}") set(fuzz_iter_leak_base_ops "-no_fuzz_dump_on_error;-fuzz_target;
!repeatme|2|0|1|10;-fuzz_per_iter_leak_scan") +set(fuzz_buffer.leak_iter.resmark "Fuzz details:") newtest_nobuild_ex(fuzz_buffer.leak_iter fuzz_buffer "initialize;leak" "${fuzz_iter_leak_base_ops}" "" OFF "" 0 "") if (NOT X64) # test detection of errors that requires shadow-memory diff --git a/tests/fuzz/fuzz_buffer.leak_iter.res b/tests/fuzz/fuzz_buffer.leak_iter.res old mode 100644 new mode 100755 index f00d88962..870ce3896 --- a/tests/fuzz/fuzz_buffer.leak_iter.res +++ b/tests/fuzz/fuzz_buffer.leak_iter.res @@ -18,4 +18,17 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # -Error #1: LEAK 16 direct bytes \ No newline at end of file +Thread +Iteration +Report for inputs +=========================================================================== + + LEAKS: + 0 unique, 1 total, 16 byte(s) of leak(s) + 0 unique, 0 total, 0 byte(s) of possible leak(s) + + POTENTIAL LEAKS: + 1 unique, 0 total, 0 byte(s) of potential leak(s) + 0 unique, 0 total, 0 byte(s) of potential possible leak(s) + +=========================================================================== \ No newline at end of file From 0fd9809dee487b93de80ac3c53a7d46a9062dc44 Mon Sep 17 00:00:00 2001 From: Pastoray Date: Tue, 7 Oct 2025 17:04:40 +0100 Subject: [PATCH 14/14] Fix: Add required trailing newlines to fuzz result files. --- tests/fuzz/fuzz_buffer.leak_iter.out | 2 +- tests/fuzz/fuzz_buffer.leak_iter.res | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fuzz/fuzz_buffer.leak_iter.out b/tests/fuzz/fuzz_buffer.leak_iter.out index 877041371..1f98cc78d 100644 --- a/tests/fuzz/fuzz_buffer.leak_iter.out +++ b/tests/fuzz/fuzz_buffer.leak_iter.out @@ -25,4 +25,4 @@ done ~~Dr.M~~ 0 unique, 0 total invalid heap argument(s) ~~Dr.M~~ 0 unique, 0 total warning(s) ~~Dr.M~~ 0 unique, 1 total, 16 byte(s) of leak(s) -~~Dr.M~~ 0 unique, 0 total, 0 byte(s) of possible leak(s) \ No newline at end of file +~~Dr.M~~ 0 unique, 0 total, 0 byte(s) of possible leak(s) diff --git a/tests/fuzz/fuzz_buffer.leak_iter.res b/tests/fuzz/fuzz_buffer.leak_iter.res index 870ce3896..7f61651d9 100755 --- a/tests/fuzz/fuzz_buffer.leak_iter.res +++ b/tests/fuzz/fuzz_buffer.leak_iter.res @@ -31,4 +31,4 @@ Report for inputs 1 unique, 0 total, 0 byte(s) of potential leak(s) 0 unique, 0 total, 0 byte(s) of potential possible leak(s) -=========================================================================== \ No newline at end of file +===========================================================================