aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2022-08-06 18:35:30 -0400
committerTheodore Ts'o <tytso@mit.edu>2022-08-09 19:45:07 -0400
commit2869485be9b1b94b93a50589de52ca553e5a116d (patch)
treef5562f9f850f5a1788638fcc27c2627c9a758178
parent27504bcf89193d47d7632cde922a65e0c051be01 (diff)
downloade2fsprogs-2869485be9b1b94b93a50589de52ca553e5a116d.tar.gz
Build the fuzzers from oss-fuzz
The fuzzers from oss-fuzz in projects/e2fsprogs/fuzz (as of commit 78ecd3f07fca with some slight modifications for better error reporting) have been placed in the tests/fuzz directory and the configure script now supports a new option --enable-fuzzing which will build these fuzzers using clang's -fsanitize=fuzzer command line option. In general, some sanitizer such as --enable-addrsan or --enable-ubsan (to enable ASAN or UBSAN, respectively) should be enabled alongside --enable-fuzzing. A typical configure command to build the fuzzers might be: configure CC=clang CXX=clang++ CFLAGS=-g --enable-fuzzing --enable-addrsan Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--MCONFIG.in3
-rw-r--r--Makefile.in4
-rwxr-xr-xconfigure715
-rw-r--r--configure.ac42
-rw-r--r--depfix.sed2
-rw-r--r--lib/support/Makefile.in2
-rw-r--r--lib/support/print_fs_flags.c75
-rw-r--r--lib/support/print_fs_flags.h5
-rw-r--r--tests/fuzz/.gitignore3
-rw-r--r--tests/fuzz/Makefile.in83
-rw-r--r--tests/fuzz/ext2fs_check_directory_fuzzer.cc43
-rw-r--r--tests/fuzz/ext2fs_image_read_write_fuzzer.cc135
-rw-r--r--tests/fuzz/ext2fs_read_bitmap_fuzzer.cc108
13 files changed, 1214 insertions, 6 deletions
diff --git a/MCONFIG.in b/MCONFIG.in
index 3fede36df..82c75a28e 100644
--- a/MCONFIG.in
+++ b/MCONFIG.in
@@ -87,6 +87,7 @@ SANITIZER_CFLAGS = @lto_cflags@ @ubsan_cflags@ @addrsan_cflags@ @threadsan_cflag
SANITIZER_LDFLAGS = @lto_ldflags@ @ubsan_ldflags@ @addrsan_ldflags@ @threadsan_ldflags@
CC = @PTHREAD_CC@
+CXX = @CXX@
BUILD_CC = @BUILD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -99,7 +100,7 @@ ALL_CFLAGS_SHLIB = $(CPPFLAGS) $(SANITIZER_CFLAGS) $(CFLAGS_SHLIB) $(PTHREAD_CFL
ALL_CFLAGS_STLIB = $(CPPFLAGS) $(SANITIZER_CFLAGS) $(CFLAGS_STLIB) $(PTHREAD_CFLAGS) $(CFLAGS_WARN) @DEFS@ $(LOCAL_CFLAGS)
LDFLAGS = $(SANITIZER_LDFLAGS) $(PTHREAD_CFLAGS) @LDFLAGS@
LDFLAGS_SHLIB = $(SANITIZER_LDFLAGS) $(PTHREAD_CFLAGS) @LDFLAGS_SHLIB@
-ALL_LDFLAGS = $(LDFLAGS) @LDFLAG_DYNAMIC@
+ALL_LDFLAGS = $(LDFLAGS) @LDFLAG_DYNAMIC@ $(LOCAL_LDFLAGS)
LDFLAGS_STATIC = $(SANITIZER_LDFLAGS) $(PTHREAD_CFLAGS) @LDFLAGS_STATIC@
BUILD_CFLAGS = $(SANITIZER_CFLAGS) @BUILD_CFLAGS@
BUILD_LDFLAGS = $(SANITIZER_LDFLAGS) @BUILD_LDFLAGS@
diff --git a/Makefile.in b/Makefile.in
index d412dfbce..79b711650 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -22,8 +22,8 @@ MKDIR_P = @MKDIR_P@
LIB_SUBDIRS=lib/et lib/ss $(E2P_LIB_SUBDIR) $(UUID_LIB_SUBDIR) \
$(BLKID_LIB_SUBDIR) $(SUPPORT_LIB_SUBDIR) $(EXT2FS_LIB_SUBDIR)
-PROG_SUBDIRS=e2fsck $(DEBUGFS_DIR) misc $(RESIZE_DIR) tests/progs po \
- $(E2SCRUB_DIR)
+PROG_SUBDIRS=e2fsck $(DEBUGFS_DIR) misc $(RESIZE_DIR) tests/progs \
+ tests/fuzz po $(E2SCRUB_DIR)
SUBDIRS=util $(LIB_SUBDIRS) $(PROG_SUBDIRS) tests
diff --git a/configure b/configure
index bfcb1ad14..493542367 100755
--- a/configure
+++ b/configure
@@ -678,6 +678,13 @@ E2SCRUB_CMT
UNIX_CMT
CYGWIN_CMT
LINUX_CMT
+FUZZING_CMT
+fuzzer_ldflags
+fuzzer_cflags
+have_fuzzer
+ac_ct_CXX
+CXXFLAGS
+CXX
threadsan_ldflags
threadsan_cflags
have_threadsan
@@ -923,6 +930,7 @@ enable_lto
enable_ubsan
enable_addrsan
enable_threadsan
+enable_fuzzing
with_multiarch
with_udev_rules_dir
with_crond_dir
@@ -940,6 +948,9 @@ CPP
PKG_CONFIG
PKG_CONFIG_PATH
PKG_CONFIG_LIBDIR
+CXX
+CXXFLAGS
+CCC
udev_CFLAGS
udev_LIBS
systemd_CFLAGS
@@ -1609,6 +1620,7 @@ Optional Features:
--enable-ubsan enable undefined behavior sanitizer
--enable-addrsan enable address sanitizer
--enable-threadsan enable thread sanitizer
+ --enable-fuzzing enable fuzzing sanitizer
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1647,6 +1659,8 @@ Some influential environment variables:
directories to add to pkg-config's search path
PKG_CONFIG_LIBDIR
path overriding pkg-config's built-in search path
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
udev_CFLAGS C compiler flags for udev, overriding pkg-config
udev_LIBS linker flags for udev, overriding pkg-config
systemd_CFLAGS
@@ -2354,6 +2368,45 @@ rm -f conftest.val
as_fn_set_status $ac_retval
} # ac_fn_c_compute_int
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
ac_configure_args_raw=
for ac_arg
do
@@ -2970,6 +3023,222 @@ as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H"
as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H"
gt_needs="$gt_needs "
as_fn_append ac_func_c_list " vprintf HAVE_VPRINTF"
+# Test code for whether the C++ compiler supports C++98 (global declarations)
+ac_cxx_conftest_cxx98_globals='
+// Does the compiler advertise C++98 conformance?
+#if !defined __cplusplus || __cplusplus < 199711L
+# error "Compiler does not advertise C++98 conformance"
+#endif
+
+// These inclusions are to reject old compilers that
+// lack the unsuffixed header files.
+#include <cstdlib>
+#include <exception>
+
+// <cassert> and <cstring> are *not* freestanding headers in C++98.
+extern void assert (int);
+namespace std {
+ extern int strcmp (const char *, const char *);
+}
+
+// Namespaces, exceptions, and templates were all added after "C++ 2.0".
+using std::exception;
+using std::strcmp;
+
+namespace {
+
+void test_exception_syntax()
+{
+ try {
+ throw "test";
+ } catch (const char *s) {
+ // Extra parentheses suppress a warning when building autoconf itself,
+ // due to lint rules shared with more typical C programs.
+ assert (!(strcmp) (s, "test"));
+ }
+}
+
+template <typename T> struct test_template
+{
+ T const val;
+ explicit test_template(T t) : val(t) {}
+ template <typename U> T add(U u) { return static_cast<T>(u) + val; }
+};
+
+} // anonymous namespace
+'
+
+# Test code for whether the C++ compiler supports C++98 (body of main)
+ac_cxx_conftest_cxx98_main='
+ assert (argc);
+ assert (! argv[0]);
+{
+ test_exception_syntax ();
+ test_template<double> tt (2.0);
+ assert (tt.add (4) == 6.0);
+ assert (true && !false);
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (global declarations)
+ac_cxx_conftest_cxx11_globals='
+// Does the compiler advertise C++ 2011 conformance?
+#if !defined __cplusplus || __cplusplus < 201103L
+# error "Compiler does not advertise C++11 conformance"
+#endif
+
+namespace cxx11test
+{
+ constexpr int get_val() { return 20; }
+
+ struct testinit
+ {
+ int i;
+ double d;
+ };
+
+ class delegate
+ {
+ public:
+ delegate(int n) : n(n) {}
+ delegate(): delegate(2354) {}
+
+ virtual int getval() { return this->n; };
+ protected:
+ int n;
+ };
+
+ class overridden : public delegate
+ {
+ public:
+ overridden(int n): delegate(n) {}
+ virtual int getval() override final { return this->n * 2; }
+ };
+
+ class nocopy
+ {
+ public:
+ nocopy(int i): i(i) {}
+ nocopy() = default;
+ nocopy(const nocopy&) = delete;
+ nocopy & operator=(const nocopy&) = delete;
+ private:
+ int i;
+ };
+
+ // for testing lambda expressions
+ template <typename Ret, typename Fn> Ret eval(Fn f, Ret v)
+ {
+ return f(v);
+ }
+
+ // for testing variadic templates and trailing return types
+ template <typename V> auto sum(V first) -> V
+ {
+ return first;
+ }
+ template <typename V, typename... Args> auto sum(V first, Args... rest) -> V
+ {
+ return first + sum(rest...);
+ }
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (body of main)
+ac_cxx_conftest_cxx11_main='
+{
+ // Test auto and decltype
+ auto a1 = 6538;
+ auto a2 = 48573953.4;
+ auto a3 = "String literal";
+
+ int total = 0;
+ for (auto i = a3; *i; ++i) { total += *i; }
+
+ decltype(a2) a4 = 34895.034;
+}
+{
+ // Test constexpr
+ short sa[cxx11test::get_val()] = { 0 };
+}
+{
+ // Test initializer lists
+ cxx11test::testinit il = { 4323, 435234.23544 };
+}
+{
+ // Test range-based for
+ int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3,
+ 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
+ for (auto &x : array) { x += 23; }
+}
+{
+ // Test lambda expressions
+ using cxx11test::eval;
+ assert (eval ([](int x) { return x*2; }, 21) == 42);
+ double d = 2.0;
+ assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0);
+ assert (d == 5.0);
+ assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0);
+ assert (d == 5.0);
+}
+{
+ // Test use of variadic templates
+ using cxx11test::sum;
+ auto a = sum(1);
+ auto b = sum(1, 2);
+ auto c = sum(1.0, 2.0, 3.0);
+}
+{
+ // Test constructor delegation
+ cxx11test::delegate d1;
+ cxx11test::delegate d2();
+ cxx11test::delegate d3(45);
+}
+{
+ // Test override and final
+ cxx11test::overridden o1(55464);
+}
+{
+ // Test nullptr
+ char *c = nullptr;
+}
+{
+ // Test template brackets
+ test_template<::test_template<int>> v(test_template<int>(12));
+}
+{
+ // Unicode literals
+ char const *utf8 = u8"UTF-8 string \u2500";
+ char16_t const *utf16 = u"UTF-8 string \u2500";
+ char32_t const *utf32 = U"UTF-32 string \u2500";
+}
+'
+
+# Test code for whether the C compiler supports C++11 (complete).
+ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals}
+${ac_cxx_conftest_cxx11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ ${ac_cxx_conftest_cxx11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C++98 (complete).
+ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals}
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ return ok;
+}
+"
+
# Auxiliary files required by this configure script.
ac_aux_files="config.rpath install-sh config.guess config.sub"
@@ -14091,6 +14360,449 @@ if test "$have_threadsan" = "yes" && test "$have_addrsan" = "yes"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ADDRSAN and THREADSAN are not known to work together." >&5
printf "%s\n" "$as_me: WARNING: ADDRSAN and THREADSAN are not known to work together." >&2;}
fi
+FUZZING_CMT="#"
+# Check whether --enable-fuzzing was given.
+if test ${enable_fuzzing+y}
+then :
+ enableval=$enable_fuzzing;
+else $as_nop
+ enable_fuzzing=no
+fi
+
+if test "$enable_fuzzing" = "yes" || test "$enable_fuzzing" = "probe"; then
+
+
+
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+printf "%s\n" "$CXX" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+printf "%s\n" "$ac_ct_CXX" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5
+printf %s "checking whether the compiler supports GNU C++... " >&6; }
+if test ${ac_cv_cxx_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_compiler_gnu=yes
+else $as_nop
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+y}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+printf %s "checking whether $CXX accepts -g... " >&6; }
+if test ${ac_cv_prog_cxx_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_g=yes
+else $as_nop
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+
+else $as_nop
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+printf "%s\n" "$ac_cv_prog_cxx_g" >&6; }
+if test $ac_test_CXXFLAGS; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_prog_cxx_stdcxx=no
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
+printf %s "checking for $CXX option to enable C++11 features... " >&6; }
+if test ${ac_cv_prog_cxx_11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_11=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx11_program
+_ACEOF
+for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA
+do
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CXX=$ac_save_CXX
+fi
+
+if test "x$ac_cv_prog_cxx_cxx11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx11"
+fi
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11
+ ac_prog_cxx_stdcxx=cxx11
+fi
+fi
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
+printf %s "checking for $CXX option to enable C++98 features... " >&6; }
+if test ${ac_cv_prog_cxx_98+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_98=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx98_program
+_ACEOF
+for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA
+do
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx98=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx98" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CXX=$ac_save_CXX
+fi
+
+if test "x$ac_cv_prog_cxx_cxx98" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx98" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx98"
+fi
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98
+ ac_prog_cxx_stdcxx=cxx98
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if C compiler supports fuzzing sanitizer" >&5
+printf %s "checking if C compiler supports fuzzing sanitizer... " >&6; }
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+ OLD_CXXFLAGS="$CXXFLAGS"
+ OLD_LDFLAGS="$LDFLAGS"
+ FUZZER_FLAGS="-fsanitize=fuzzer"
+ CXXFLAGS="$CXXFLAGS $FUZZER_FLAGS"
+ LDFLAGS="$LDFLAGS $FUZZER_FLAGS"
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <stddef.h>
+ #include <stdint.h>
+
+int
+main (void)
+{
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ fuzzer_cflags=$FUZZER_FLAGS
+ fuzzer_ldflags=$FUZZER_FLAGS
+ FUZZING_CMT=
+ have_fuzzer=yes
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ as_fn_error $? "fuzzing requested but not available" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CXXFLAGS="${OLD_CXXFLAGS}"
+ LDFLAGS="${OLD_LDFLAGS}"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+fi
+if test "$enable_fuzzer" = "yes" && test "$have_fuzzer" != "yes"; then
+ as_fn_error $? "Fuzzing not supported by compiler." "$LINENO" 5
+fi
+
LINUX_CMT="#"
CYGWIN_CMT="#"
UNIX_CMT=
@@ -14584,7 +15296,8 @@ for i in MCONFIG Makefile \
lib/ss/ss.pc lib/et/com_err.pc lib/e2p/e2p.pc lib/ext2fs/ext2fs.pc \
misc/Makefile ext2ed/Makefile e2fsck/Makefile \
debugfs/Makefile tests/Makefile tests/progs/Makefile \
- resize/Makefile doc/Makefile po/Makefile.in scrub/Makefile; do
+ tests/fuzz/Makefile resize/Makefile doc/Makefile \
+ po/Makefile.in scrub/Makefile; do
if test -d `dirname ${srcdir}/$i` ; then
outlist="$outlist $i"
fi
diff --git a/configure.ac b/configure.ac
index cb528da68..78f71fd8e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1495,6 +1495,45 @@ if test "$have_threadsan" = "yes" && test "$have_addrsan" = "yes"; then
AC_MSG_WARN([ADDRSAN and THREADSAN are not known to work together.])
fi
dnl
+dnl Enable the fuzzer sanitizer for all packages
+dnl
+FUZZING_CMT="#"
+AC_ARG_ENABLE([fuzzing],
+AS_HELP_STRING([--enable-fuzzing],[enable fuzzing sanitizer]),,
+enable_fuzzing=no)
+if test "$enable_fuzzing" = "yes" || test "$enable_fuzzing" = "probe"; then
+ AC_PROG_CXX
+ AC_MSG_CHECKING([if C compiler supports fuzzing sanitizer])
+ AC_LANG_PUSH([C++])
+ OLD_CXXFLAGS="$CXXFLAGS"
+ OLD_LDFLAGS="$LDFLAGS"
+ FUZZER_FLAGS="-fsanitize=fuzzer"
+ CXXFLAGS="$CXXFLAGS $FUZZER_FLAGS"
+ LDFLAGS="$LDFLAGS $FUZZER_FLAGS"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <stddef.h>
+ #include <stdint.h>
+ ]],
+ [ return 0; ])],
+ [AC_MSG_RESULT([yes])]
+ [fuzzer_cflags=$FUZZER_FLAGS]
+ [fuzzer_ldflags=$FUZZER_FLAGS]
+ [FUZZING_CMT=]
+ [have_fuzzer=yes],
+ [AC_MSG_RESULT([no])]
+ [AC_MSG_ERROR([fuzzing requested but not available])])
+ CXXFLAGS="${OLD_CXXFLAGS}"
+ LDFLAGS="${OLD_LDFLAGS}"
+ AC_LANG_POP([C++])
+ AC_SUBST(have_fuzzer)
+ AC_SUBST(fuzzer_cflags)
+ AC_SUBST(fuzzer_ldflags)
+fi
+if test "$enable_fuzzer" = "yes" && test "$have_fuzzer" != "yes"; then
+ AC_MSG_ERROR([Fuzzing not supported by compiler.])
+fi
+AC_SUBST(FUZZING_CMT)
+dnl
dnl OS-specific uncomment control
dnl
LINUX_CMT="#"
@@ -1819,7 +1858,8 @@ for i in MCONFIG Makefile \
lib/ss/ss.pc lib/et/com_err.pc lib/e2p/e2p.pc lib/ext2fs/ext2fs.pc \
misc/Makefile ext2ed/Makefile e2fsck/Makefile \
debugfs/Makefile tests/Makefile tests/progs/Makefile \
- resize/Makefile doc/Makefile po/Makefile.in scrub/Makefile; do
+ tests/fuzz/Makefile resize/Makefile doc/Makefile \
+ po/Makefile.in scrub/Makefile; do
if test -d `dirname ${srcdir}/$i` ; then
outlist="$outlist $i"
fi
diff --git a/depfix.sed b/depfix.sed
index 582d79fd9..680fb2200 100644
--- a/depfix.sed
+++ b/depfix.sed
@@ -24,7 +24,7 @@ s/ */ /g
s;/usr/include/[^ ]* *;;g
s;/usr/lib/[^ ]* *;;g
-s;/mit/cygnus[^ ]* *;;g
+s;/bin/[^ ]* *;;g
s;\.\./[^ ]*lib/blkid/blkid[^ ]* *;;g
s;\.\./[^ ]*lib/uuid/uuid.h[^ ]* *;;g
diff --git a/lib/support/Makefile.in b/lib/support/Makefile.in
index f3c7981e4..e5600a82a 100644
--- a/lib/support/Makefile.in
+++ b/lib/support/Makefile.in
@@ -18,6 +18,7 @@ OBJS= cstring.o \
plausible.o \
profile.o \
parse_qtype.o \
+ print_fs_flags.o \
profile_helpers.o \
prof_err.o \
quotaio.o \
@@ -30,6 +31,7 @@ SRCS= $(srcdir)/argv_parse.c \
$(srcdir)/mkquota.c \
$(srcdir)/parse_qtype.c \
$(srcdir)/plausible.c \
+ $(srcdir)/print_fs_flags.c \
$(srcdir)/profile.c \
$(srcdir)/profile_helpers.c \
prof_err.c \
diff --git a/lib/support/print_fs_flags.c b/lib/support/print_fs_flags.c
new file mode 100644
index 000000000..e54acc04b
--- /dev/null
+++ b/lib/support/print_fs_flags.c
@@ -0,0 +1,75 @@
+/*
+ * print_flags.c - Print ext2_filsys flags
+ *
+ * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
+ * Laboratoire MASI, Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Library
+ * General Public License, version 2.
+ * %End-Header%
+ */
+
+#include "config.h"
+#include <stdio.h>
+
+#include "ext2fs/ext2fs.h"
+
+struct flags_name {
+ unsigned long flag;
+ const char *name;
+};
+
+static struct flags_name flags_array[] = {
+ EXT2_FLAG_RW, "EXT2_FLAG_RW",
+ EXT2_FLAG_CHANGED, "EXT2_FLAG_CHANGED",
+ EXT2_FLAG_DIRTY, "EXT2_FLAG_DIRTY",
+ EXT2_FLAG_VALID, "EXT2_FLAG_VALID",
+ EXT2_FLAG_IB_DIRTY, "EXT2_FLAG_IB_DIRTY",
+ EXT2_FLAG_BB_DIRTY, "EXT2_FLAG_BB_DIRTY",
+ EXT2_FLAG_SWAP_BYTES, "EXT2_FLAG_SWAP_BYTES",
+ EXT2_FLAG_SWAP_BYTES_READ, "EXT2_FLAG_SWAP_BYTES_READ",
+ EXT2_FLAG_SWAP_BYTES_WRITE, "EXT2_FLAG_SWAP_BYTES_WRITE",
+ EXT2_FLAG_MASTER_SB_ONLY, "EXT2_FLAG_MASTER_SB_ONLY",
+ EXT2_FLAG_FORCE, "EXT2_FLAG_FORCE",
+ EXT2_FLAG_SUPER_ONLY, "EXT2_FLAG_SUPER_ONLY",
+ EXT2_FLAG_JOURNAL_DEV_OK, "EXT2_FLAG_JOURNAL_DEV_OK",
+ EXT2_FLAG_IMAGE_FILE, "EXT2_FLAG_IMAGE_FILE",
+ EXT2_FLAG_EXCLUSIVE, "EXT2_FLAG_EXCLUSIVE",
+ EXT2_FLAG_SOFTSUPP_FEATURES, "EXT2_FLAG_SOFTSUPP_FEATURES",
+ EXT2_FLAG_NOFREE_ON_ERROR, "EXT2_FLAG_NOFREE_ON_ERROR",
+ EXT2_FLAG_64BITS, "EXT2_FLAG_64BITS",
+ EXT2_FLAG_PRINT_PROGRESS, "EXT2_FLAG_PRINT_PROGRESS",
+ EXT2_FLAG_DIRECT_IO, "EXT2_FLAG_DIRECT_IO",
+ EXT2_FLAG_SKIP_MMP, "EXT2_FLAG_SKIP_MMP",
+ EXT2_FLAG_IGNORE_CSUM_ERRORS, "EXT2_FLAG_IGNORE_CSUM_ERRORS",
+ EXT2_FLAG_SHARE_DUP, "EXT2_FLAG_SHARE_DUP",
+ EXT2_FLAG_IGNORE_SB_ERRORS, "EXT2_FLAG_IGNORE_SB_ERRORS",
+ EXT2_FLAG_BBITMAP_TAIL_PROBLEM, "EXT2_FLAG_BBITMAP_TAIL_PROBLEM",
+ EXT2_FLAG_IBITMAP_TAIL_PROBLEM, "EXT2_FLAG_IBITMAP_TAIL_PROBLEM",
+ EXT2_FLAG_THREADS, "EXT2_FLAG_THREADS",
+ 0
+};
+
+void print_fs_flags(FILE * f, unsigned long flags)
+{
+ struct flags_name *fp;
+ int first = 1, pos = 16;
+
+ for (fp = flags_array; fp->flag != 0; fp++) {
+ if ((flags & fp->flag) == 0)
+ continue;
+ pos += strlen(fp->name) + 1;
+ if (pos > 72) {
+ fputs("\n\t", f);
+ pos = 9 + strlen(fp->name);
+ }
+ if (first)
+ first = 0;
+ else
+ fputc(' ', f);
+ fputs(fp->name, f);
+ }
+ fputc('\n', f);
+}
diff --git a/lib/support/print_fs_flags.h b/lib/support/print_fs_flags.h
new file mode 100644
index 000000000..bdd58a00a
--- /dev/null
+++ b/lib/support/print_fs_flags.h
@@ -0,0 +1,5 @@
+/*
+ * print_flags.h -- header file for printing the fs flags
+ */
+
+void print_fs_flags(FILE * f, unsigned long flags);
diff --git a/tests/fuzz/.gitignore b/tests/fuzz/.gitignore
new file mode 100644
index 000000000..381b20a12
--- /dev/null
+++ b/tests/fuzz/.gitignore
@@ -0,0 +1,3 @@
+ext2fs_check_directory_fuzzer
+ext2fs_image_read_write_fuzzer
+ext2fs_read_bitmap_fuzzer
diff --git a/tests/fuzz/Makefile.in b/tests/fuzz/Makefile.in
new file mode 100644
index 000000000..a6d80639f
--- /dev/null
+++ b/tests/fuzz/Makefile.in
@@ -0,0 +1,83 @@
+#
+# Makefile for the tests/fuzz directory
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+top_builddir = ../..
+my_dir = tests/fuzz
+
+@MCONFIG@
+
+PROGS= ext2fs_check_directory_fuzzer \
+ ext2fs_image_read_write_fuzzer \
+ ext2fs_read_bitmap_fuzzer
+
+SRCS= $(srcdir)/ext2fs_check_directory_fuzzer.cc \
+ $(srcdir)/ext2fs_image_read_write_fuzzer.cc \
+ $(srcdir)/ext2fs_read_bitmap_fuzzer.cc
+
+LOCAL_CFLAGS= @fuzzer_cflags@
+LOCAL_LDFLAGS= @fuzzer_ldflags@
+
+LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBSUPPORT)
+DEPLIBS= $(LIBEXT2FS) $(DEPLIBCOM_ERR) $(DEPLIBSUPPORT)
+
+STATIC_LIBS= $(LIBSUPPORT) $(STATIC_LIBE2P) $(STATIC_LIBEXT2FS) \
+ $(STATIC_LIBCOM_ERR)
+STATIC_DEPLIBS= $(DEPLIBSUPPORT) $(STATIC_LIBE2P) $(STATIC_LIBEXT2FS) \
+ $(DEPSTATIC_LIBCOM_ERR)
+
+FUZZ_LDFLAGS= $(ALL_LDFLAGS)
+FUZZ_DEP= $(STATIC_DEPLIBS) $(srcdir)/Makefile.in
+
+.cc.o:
+ $(E) " CXX $<"
+ $(Q) $(CXX) -c $(ALL_CFLAGS) $< -o $@
+
+@FUZZING_CMT@all:: $(PROGS)
+
+clean::
+ $(RM) -f $(PROGS) *.o
+
+ext2fs_check_directory_fuzzer: ext2fs_check_directory_fuzzer.o $(FUZZ_DEP)
+ $(E) " LD $@"
+ $(Q) $(CXX) $(FUZZ_LDFLAGS) -o $@ $< $(STATIC_LIBS) $(SYSLIBS)
+
+ext2fs_image_read_write_fuzzer: ext2fs_image_read_write_fuzzer.o $(FUZZ_DEP)
+ $(E) " LD $@"
+ $(Q) $(CXX) $(FUZZ_LDFLAGS) -o $@ $< $(STATIC_LIBS) $(SYSLIBS)
+
+ext2fs_read_bitmap_fuzzer: ext2fs_read_bitmap_fuzzer.o $(FUZZ_DEP)
+ $(E) " LD $@"
+ $(Q) $(CXX) $(FUZZ_LDFLAGS) -o $@ $< $(STATIC_LIBS) $(SYSLIBS)
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+ext2fs_check_directory_fuzzer.o: $(srcdir)/ext2fs_check_directory_fuzzer.cc \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
+ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \
+ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h
+ext2fs_image_read_write_fuzzer.o: $(srcdir)/ext2fs_image_read_write_fuzzer.cc \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
+ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \
+ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/e2p/e2p.h \
+ $(top_srcdir)/lib/support/print_fs_flags.h
+ext2fs_read_bitmap_fuzzer.o: $(srcdir)/ext2fs_read_bitmap_fuzzer.cc \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
+ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \
+ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/e2p/e2p.h \
+ $(top_srcdir)/lib/support/print_fs_flags.h
diff --git a/tests/fuzz/ext2fs_check_directory_fuzzer.cc b/tests/fuzz/ext2fs_check_directory_fuzzer.cc
new file mode 100644
index 000000000..61cf42fa5
--- /dev/null
+++ b/tests/fuzz/ext2fs_check_directory_fuzzer.cc
@@ -0,0 +1,43 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stddef.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "ext2fs/ext2fs.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ static const char* fname = "/tmp/ext2_test_file";
+
+ // Write our data to a temp file.
+ int fd = open(fname, O_RDWR|O_CREAT|O_TRUNC);
+ write(fd, data, size);
+ close(fd);
+
+ ext2_filsys fs;
+ errcode_t retval = ext2fs_open(
+ fname,
+ EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0,
+ unix_io_manager,
+ &fs);
+
+ if (!retval) {
+ retval = ext2fs_check_directory(fs, EXT2_ROOT_INO);
+ ext2fs_close(fs);
+ }
+
+ return 0;
+}
diff --git a/tests/fuzz/ext2fs_image_read_write_fuzzer.cc b/tests/fuzz/ext2fs_image_read_write_fuzzer.cc
new file mode 100644
index 000000000..8aa0cb845
--- /dev/null
+++ b/tests/fuzz/ext2fs_image_read_write_fuzzer.cc
@@ -0,0 +1,135 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// #define USE_FLAGS
+// #define DUMP_SUPER
+// #define SAVE_FS_IMAGE
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <sys/syscall.h>
+#include <linux/memfd.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "ext2fs/ext2fs.h"
+extern "C" {
+#include "e2p/e2p.h"
+#include "support/print_fs_flags.h"
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+ const char *progname = "ext2fs_image_read_write_fuzzer";
+ add_error_table(&et_ext2_error_table);
+
+ enum FuzzerType {
+ ext2fsImageBitmapRead,
+ ext2fsImageInodeRead,
+ ext2fsImageSuperRead,
+ ext2fsImageBitmapWrite,
+ ext2fsImageInodeWrite,
+ ext2fsImageSuperWrite,
+ kMaxValue = ext2fsImageSuperWrite
+ };
+
+ FuzzedDataProvider stream(data, size);
+ const FuzzerType f = stream.ConsumeEnum<FuzzerType>();
+ int flags = stream.ConsumeIntegral<int>();
+#ifndef USE_FLAGS
+ flags = 0;
+#endif
+
+ static const char* fname = "/tmp/ext2_test_file";
+
+ // Write our data to a temp file.
+#ifdef SAVE_FS_IMAGE
+ int fd = open(fname, O_CREAT|O_TRUNC|O_RDWR, 0644);
+#else
+ int fd = syscall(SYS_memfd_create, fname, 0);
+#endif
+ std::vector<char> buffer = stream.ConsumeRemainingBytes<char>();
+ write(fd, buffer.data(), buffer.size());
+
+ std::string fspath("/proc/self/fd/" + std::to_string(fd));
+
+ ext2_filsys fs;
+#ifdef USE_FLAGS
+ printf("Flags: 0x%08x ", flags);
+ print_fs_flags(stdout, flags);
+ flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;
+#endif
+ errcode_t retval = ext2fs_open(
+ fspath.c_str(),
+ flags | EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0,
+ unix_io_manager,
+ &fs);
+
+ if (retval) {
+ com_err(progname, retval, "while trying to open file system");
+ } else {
+#ifdef DUMP_SUPER
+ list_super2(fs->super, stdout);
+#endif
+ printf("FuzzerType: %d\n", (int) f);
+ switch (f) {
+ case ext2fsImageBitmapRead: {
+ retval = ext2fs_image_bitmap_read(fs, fd, 0);
+ if (retval)
+ com_err(progname, retval, "while trying to read image bitmap");
+ break;
+ }
+ case ext2fsImageInodeRead: {
+ retval = ext2fs_image_inode_read(fs, fd, 0);
+ if (retval)
+ com_err(progname, retval, "while trying to read image inode");
+ break;
+ }
+ case ext2fsImageSuperRead: {
+ retval = ext2fs_image_super_read(fs, fd, 0);
+ if (retval)
+ com_err(progname, retval, "while trying to read image superblock");
+ break;
+ }
+ case ext2fsImageBitmapWrite: {
+ retval = ext2fs_image_bitmap_write(fs, fd, 0);
+ if (retval)
+ com_err(progname, retval, "while trying to write image bitmap");
+ break;
+ }
+ case ext2fsImageInodeWrite: {
+ retval = ext2fs_image_inode_write(fs, fd, 0);
+ if (retval)
+ com_err(progname, retval, "while trying to write image inode");
+ break;
+ }
+ case ext2fsImageSuperWrite: {
+ retval = ext2fs_image_super_write(fs, fd, 0);
+ if (retval)
+ com_err(progname, retval, "while trying to write image superblock");
+ break;
+ }
+ default: {
+ assert(false);
+ }
+ }
+ ext2fs_close(fs);
+ }
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/fuzz/ext2fs_read_bitmap_fuzzer.cc b/tests/fuzz/ext2fs_read_bitmap_fuzzer.cc
new file mode 100644
index 000000000..fa3d7e7d2
--- /dev/null
+++ b/tests/fuzz/ext2fs_read_bitmap_fuzzer.cc
@@ -0,0 +1,108 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// #define USE_FLAGS
+// #define DUMP_SUPER
+// #define SAVE_FS_IMAGE
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <sys/syscall.h>
+#include <linux/memfd.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "ext2fs/ext2fs.h"
+extern "C" {
+#include "e2p/e2p.h"
+#include "support/print_fs_flags.h"
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+ const char *progname = "ext2fs_read_bitmap_fuzzer";
+ add_error_table(&et_ext2_error_table);
+
+ enum FuzzerType {
+ ext2fsReadBlockBitmap,
+ ext2fsReadInodeBitmap,
+ kMaxValue = ext2fsReadInodeBitmap
+ };
+
+ FuzzedDataProvider stream(data, size);
+ const FuzzerType f = stream.ConsumeEnum<FuzzerType>();
+ int flags = stream.ConsumeIntegral<int>();
+#ifndef USE_FLAGS
+ flags = 0;
+#endif
+
+ static const char* fname = "/tmp/ext2_test_file";
+
+ // Write our data to a temp file.
+#ifdef SAVE_FS_IMAGE
+ int fd = open(fname, O_CREAT|O_TRUNC|O_RDWR, 0644);
+#else
+ int fd = syscall(SYS_memfd_create, fname, 0);
+#endif
+ std::vector<char> buffer = stream.ConsumeRemainingBytes<char>();
+ write(fd, buffer.data(), buffer.size());
+
+ std::string fspath("/proc/self/fd/" + std::to_string(fd));
+
+ ext2_filsys fs;
+#ifdef USE_FLAGS
+ printf("Flags: 0x%08x ", flags);
+ print_fs_flags(stdout, flags);
+ flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;
+#endif
+ errcode_t retval = ext2fs_open(
+ fspath.c_str(),
+ flags | EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0,
+ unix_io_manager,
+ &fs);
+
+ if (retval) {
+ com_err(progname, retval, "while trying to open file system");
+ } else {
+#ifdef DUMP_SUPER
+ list_super2(fs->super, stdout);
+#endif
+ switch (f) {
+ case ext2fsReadBlockBitmap: {
+ retval = ext2fs_read_block_bitmap(fs);
+ if (retval)
+ com_err(progname, retval, "while trying to read block bitmap");
+ break;
+ }
+ case ext2fsReadInodeBitmap: {
+ retval = ext2fs_read_inode_bitmap(fs);
+ if (retval)
+ com_err(progname, retval, "while trying to read inode bitmap");
+ break;
+ }
+ default: {
+ assert(false);
+ }
+ }
+ retval = ext2fs_close(fs);
+ if (retval)
+ com_err(progname, retval, "while trying to close file system");
+ }
+ close(fd);
+
+ return 0;
+}