Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions drmemory/docs/fuzzer.dox
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,29 @@ you would specify the following command-line option to \p drmemory:

Comment thread
Pastoray marked this conversation as resolved.
-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
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. The types of leaks reported
Comment thread
Pastoray marked this conversation as resolved.
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:

-fuzz_module a.out -fuzz_function DrMemFuzzFunc -fuzz_per_iter_leak_scan

****************************************************************************
****************************************************************************
*/
5 changes: 5 additions & 0 deletions drmemory/drmemory.c
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down Expand Up @@ -488,6 +489,8 @@ event_exit(void)
close_file(f_missing_symbols);
close_file(f_suppress);
close_file(f_potential);
if (options.fuzz) // If it was even created
close_file(f_fuzz);
dr_fprintf(f_global, "LOG END\n");
close_file(f_global);

Expand Down Expand Up @@ -1508,6 +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);
if (options.fuzz)
f_fuzz = open_logfile(FUZZ_FNAME, false, -1);
}
}

Expand Down
2 changes: 2 additions & 0 deletions drmemory/drmemory.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -82,6 +83,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;
Expand Down
19 changes: 19 additions & 0 deletions drmemory/fuzzer.c
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1603,6 +1604,24 @@ 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) 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();
Comment thread
Pastoray marked this conversation as resolved.
check_reachability(false/*!at exit*/);

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);
}

if (option_specified.fuzz_corpus)
return post_fuzz_corpus(fuzzcxt, target_pc);

Expand Down
3 changes: 2 additions & 1 deletion drmemory/options.c
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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) &&
Expand Down
4 changes: 4 additions & 0 deletions drmemory/optionsx.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Comment thread
Pastoray marked this conversation as resolved.
Comment thread
Pastoray marked this conversation as resolved.

#ifdef WINDOWS
OPTION_CLIENT_BOOL(drmemscope, fuzz_mangled_names, false,
"Enable mangled names for fuzz targets on Windows",
Expand Down
21 changes: 20 additions & 1 deletion drmemory/report.c
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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 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());
if ((options.lib_allowlist_frames > 0 && options.lib_allowlist[0] != '\0') ||
Expand Down Expand Up @@ -1902,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)
{
Expand Down Expand Up @@ -3445,7 +3464,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!");
Expand Down
3 changes: 3 additions & 0 deletions drmemory/report.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ report_fork_init(void);
void
report_summary(void);

void
report_all_leak_stats(file_t f, bool notify, bool potential);

void
report_thread_init(void *drcontext);

Expand Down
5 changes: 5 additions & 0 deletions tests/fuzz/CMakeLists.txt
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ 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;<main>!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 "")
Comment thread
Pastoray marked this conversation as resolved.
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 "")
Expand Down
28 changes: 28 additions & 0 deletions tests/fuzz/fuzz_buffer.leak_iter.out
Original file line number Diff line number Diff line change
@@ -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)
34 changes: 34 additions & 0 deletions tests/fuzz/fuzz_buffer.leak_iter.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# **********************************************************
# 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.
#
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)

===========================================================================