From: <sv...@op...> - 2024-05-11 20:26:42
|
Author: sagamusix Date: Sat May 11 22:26:30 2024 New Revision: 20769 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20769 Log: Merged revision(s) 20756 from branches/OpenMPT-1.31: Merged revision(s) 20749-20750, 20755 from trunk/OpenMPT: [Mod] Reduce static variable usage in fuzzer program to eventually allow using __AFL_LOOP. ........ [Imp] mptRandom: Add reinit_global_random() function for fuzzer builds to allow deterministic consecutive fuzzer runs in the same process. ........ [Imp] Speed up fuzzing by using persistent mode and shared memory file input. Note: afl++ will report a stability of about 99.x%. According to its debug output, the unstable edges are in WavesReverb and I3DL2Reverb implementations, however the unstable edges that it finds don't make any sense. As a tiny bit of instability in these parts of the code should not hurt overall code coverage, we trade this for the significant gains in speed that persistent mode gives us. ........ ........ Added: branches/OpenMPT-1.30/contrib/fuzzing/fuzz.cpp - copied, changed from r20768, branches/OpenMPT-1.30/contrib/fuzzing/fuzz.c Deleted: branches/OpenMPT-1.30/contrib/fuzzing/fuzz.c Modified: branches/OpenMPT-1.30/ (props changed) branches/OpenMPT-1.30/Makefile branches/OpenMPT-1.30/common/mptRandom.cpp branches/OpenMPT-1.30/common/mptRandom.h Modified: branches/OpenMPT-1.30/Makefile ============================================================================== --- branches/OpenMPT-1.30/Makefile Sat May 11 22:25:28 2024 (r20768) +++ branches/OpenMPT-1.30/Makefile Sat May 11 22:26:30 2024 (r20769) @@ -1747,10 +1747,10 @@ endif endif -contrib/fuzzing/fuzz.o: contrib/fuzzing/fuzz.c - $(INFO) [CC] $< - $(VERYSILENT)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -M -MT$@ $< > $*.d - $(SILENT)$(COMPILE.c) $(OUTPUT_OPTION) $< +contrib/fuzzing/fuzz.o: contrib/fuzzing/fuzz.cpp + $(INFO) [CXX] $< + $(VERYSILENT)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -M -MT$@ $< > $*.d + $(SILENT)$(COMPILE.cc) $(OUTPUT_OPTION) $< bin/fuzz$(EXESUFFIX): contrib/fuzzing/fuzz.o $(OBJECTS_LIBOPENMPT) $(OUTPUT_LIBOPENMPT) $(INFO) [LD] $@ $(SILENT)$(LINK.cc) $(LDFLAGS_LIBOPENMPT) contrib/fuzzing/fuzz.o $(OBJECTS_LIBOPENMPT) $(LOADLIBES) $(LDLIBS) $(LDLIBS_LIBOPENMPT) -o $@ Modified: branches/OpenMPT-1.30/common/mptRandom.cpp ============================================================================== --- branches/OpenMPT-1.30/common/mptRandom.cpp Sat May 11 22:25:28 2024 (r20768) +++ branches/OpenMPT-1.30/common/mptRandom.cpp Sat May 11 22:26:30 2024 (r20769) @@ -55,6 +55,16 @@ return g_global_prng; } +#ifdef MPT_BUILD_FUZZER +void reinit_global_random() +{ + global_prng().~thread_safe_prng<mpt::default_prng>(); + global_random_device().~random_device(); + new(&global_random_device()) mpt::random_device{}; + new(&global_prng()) thread_safe_prng<mpt::default_prng>{global_random_device()}; +} +#endif // MPT_BUILD_FUZZER + #endif // MODPLUG_TRACKER && !MPT_BUILD_WINESUPPORT } // namespace mpt Modified: branches/OpenMPT-1.30/common/mptRandom.h ============================================================================== --- branches/OpenMPT-1.30/common/mptRandom.h Sat May 11 22:25:28 2024 (r20768) +++ branches/OpenMPT-1.30/common/mptRandom.h Sat May 11 22:26:30 2024 (r20769) @@ -128,6 +128,10 @@ mpt::random_device & global_random_device(); mpt::thread_safe_prng<mpt::default_prng> & global_prng(); +#ifdef MPT_BUILD_FUZZER +void reinit_global_random(); +#endif // MPT_BUILD_FUZZER + #if defined(MODPLUG_TRACKER) && !defined(MPT_BUILD_WINESUPPORT) void set_global_random_device(mpt::random_device *rd); void set_global_prng(mpt::thread_safe_prng<mpt::default_prng> *rng); Copied and modified: branches/OpenMPT-1.30/contrib/fuzzing/fuzz.cpp (from r20768, branches/OpenMPT-1.30/contrib/fuzzing/fuzz.c) ============================================================================== --- branches/OpenMPT-1.30/contrib/fuzzing/fuzz.c Sat May 11 22:25:28 2024 (r20768, copy source) +++ branches/OpenMPT-1.30/contrib/fuzzing/fuzz.cpp Sat May 11 22:26:30 2024 (r20769) @@ -1,59 +1,88 @@ /* - * fuzz.c - * ------ + * fuzz.cpp + * -------- * Purpose: Tiny libopenmpt user to be used by fuzzing tools * Notes : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ -#include <memory.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> +#include <memory> +#include <cstdint> +#include <cstdlib> -#include <errno.h> +#include <cerrno> #include <unistd.h> #include <libopenmpt/libopenmpt.h> -#include <libopenmpt/libopenmpt_stream_callbacks_file.h> + +#include "../../common/mptRandom.h" #define BUFFERSIZE 450 // shouldn't match OpenMPT's internal mix buffer size (512) #define SAMPLERATE 22050 static int16_t buffer[BUFFERSIZE]; +static int ErrFunc (int error, void *) +{ + switch (error) + { + case OPENMPT_ERROR_INVALID_ARGUMENT: + case OPENMPT_ERROR_OUT_OF_RANGE: + case OPENMPT_ERROR_LENGTH: + case OPENMPT_ERROR_DOMAIN: + case OPENMPT_ERROR_LOGIC: + case OPENMPT_ERROR_UNDERFLOW: + case OPENMPT_ERROR_OVERFLOW: + case OPENMPT_ERROR_RANGE: + case OPENMPT_ERROR_RUNTIME: + case OPENMPT_ERROR_EXCEPTION: + std::abort(); + default: + return OPENMPT_ERROR_FUNC_RESULT_NONE; + } +} + +__AFL_FUZZ_INIT(); + int main( int argc, char * argv[] ) { - static FILE * file = NULL; - static openmpt_module * mod = NULL; - static size_t count = 0; - static int i = 0; (void)argc; + (void)argv; + openmpt_module_create_from_memory2( buffer, BUFFERSIZE, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr ); #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); #endif - file = fopen( argv[1], "rb" ); - mod = openmpt_module_create( openmpt_stream_get_file_callbacks(), file, NULL, NULL, NULL ); - fclose( file ); - if ( mod == NULL ) return 1; - openmpt_module_ctl_set( mod, "render.resampler.emulate_amiga", (openmpt_module_get_num_orders( mod ) & 1) ? "0" : "1" ); - /* render about a second of the module for fuzzing the actual mix routines */ - for(; i < 50; i++) { - count = openmpt_module_read_mono( mod, SAMPLERATE, BUFFERSIZE, buffer ); - if ( count == 0 ) { - break; + + unsigned char *fileBuffer = __AFL_FUZZ_TESTCASE_BUF; // must be after __AFL_INIT and before __AFL_LOOP! + + while (__AFL_LOOP(10000)) { + int fileSize = __AFL_FUZZ_TESTCASE_LEN; + OpenMPT::mpt::reinit_global_random(); + openmpt_module * mod = openmpt_module_create_from_memory2( fileBuffer, fileSize, nullptr, nullptr, ErrFunc, nullptr, nullptr, nullptr, nullptr); + if ( mod == NULL ) + return 1; + + // verify API contract: If the file can be loaded, header probing must be successful too. + if ( openmpt_probe_file_header( OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT, fileBuffer, fileSize, fileSize, nullptr, nullptr, ErrFunc, nullptr, nullptr, nullptr ) == OPENMPT_PROBE_FILE_HEADER_RESULT_FAILURE ) + std::abort(); + + openmpt_module_ctl_set( mod, "render.resampler.emulate_amiga", (openmpt_module_get_num_orders( mod ) & 1) ? "0" : "1" ); + // render about a second of the module for fuzzing the actual mix routines + for(int i = 0; i < 50; i++) { + size_t count = openmpt_module_read_mono( mod, SAMPLERATE, BUFFERSIZE, buffer ); + if ( count == 0 ) { + break; + } } + openmpt_module_set_position_seconds( mod, 1.0 ); + openmpt_module_read_mono( mod, SAMPLERATE, BUFFERSIZE, buffer ); + openmpt_module_set_position_order_row( mod, 3, 16 ); + openmpt_module_read_mono( mod, SAMPLERATE, BUFFERSIZE, buffer ); + + // fuzz string-related stuff + openmpt_free_string ( openmpt_module_get_metadata( mod, "date" ) ); + openmpt_free_string ( openmpt_module_get_metadata( mod, "message" ) ); + openmpt_module_destroy( mod ); } - openmpt_module_set_position_seconds( mod, 1.0 ); - openmpt_module_read_mono( mod, SAMPLERATE, BUFFERSIZE, buffer ); - openmpt_module_set_position_order_row( mod, 3, 16 ); - openmpt_module_read_mono( mod, SAMPLERATE, BUFFERSIZE, buffer ); - - /* fuzz string-related stuff */ - openmpt_free_string ( openmpt_module_get_metadata( mod, "date" ) ); - openmpt_free_string ( openmpt_module_get_metadata( mod, "message" ) ); - openmpt_module_destroy( mod ); return 0; } |