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>
This commit is contained in:
Theodore Ts'o 2022-08-06 18:35:30 -04:00
parent 27504bcf89
commit 2869485be9
13 changed files with 1214 additions and 6 deletions

View File

@ -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@

View File

@ -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

715
configure vendored
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

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

View File

@ -0,0 +1,5 @@
/*
* print_flags.h -- header file for printing the fs flags
*/
void print_fs_flags(FILE * f, unsigned long flags);

3
tests/fuzz/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
ext2fs_check_directory_fuzzer
ext2fs_image_read_write_fuzzer
ext2fs_read_bitmap_fuzzer

83
tests/fuzz/Makefile.in Normal file
View File

@ -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

View File

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

View File

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

View File

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