mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 03:24:56 +08:00
engine: add sprite model loading fuzzing, decouple fuzzing from tests
This commit is contained in:
@@ -274,7 +274,7 @@ void FS_FreeStream( stream_t *stream )
|
||||
stream->format->freefunc( stream );
|
||||
}
|
||||
|
||||
#if XASH_ENGINE_TESTS
|
||||
#if XASH_LLVM_LIBFUZZER
|
||||
#define IMPLEMENT_SOUNDLIB_FUZZ_TARGET( export, target ) \
|
||||
int EXPORT export( const uint8_t *Data, size_t Size ); \
|
||||
int EXPORT export( const uint8_t *Data, size_t Size ) \
|
||||
@@ -294,4 +294,4 @@ int EXPORT export( const uint8_t *Data, size_t Size ) \
|
||||
|
||||
IMPLEMENT_SOUNDLIB_FUZZ_TARGET( Fuzz_Sound_LoadMPG, Sound_LoadMPG )
|
||||
IMPLEMENT_SOUNDLIB_FUZZ_TARGET( Fuzz_Sound_LoadWAV, Sound_LoadWAV )
|
||||
#endif
|
||||
#endif // XASH_LLVM_LIBFUZZER
|
||||
|
||||
@@ -185,7 +185,7 @@ static qboolean Sound_ParseID3Tag( const byte *buffer, fs_offset_t filesize )
|
||||
return true;
|
||||
}
|
||||
|
||||
#if XASH_ENGINE_TESTS
|
||||
#if XASH_LLVM_LIBFUZZER
|
||||
int EXPORT Fuzz_Sound_ParseID3Tag( const uint8_t *Data, size_t Size );
|
||||
int EXPORT Fuzz_Sound_ParseID3Tag( const uint8_t *Data, size_t Size )
|
||||
{
|
||||
@@ -193,7 +193,7 @@ int EXPORT Fuzz_Sound_ParseID3Tag( const uint8_t *Data, size_t Size )
|
||||
Sound_ParseID3Tag( Data, Size );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif // XASH_LLVM_LIBFUZZER
|
||||
|
||||
/*
|
||||
=================================================================
|
||||
|
||||
@@ -701,6 +701,10 @@ void Test_RunImagelib( void )
|
||||
|
||||
Z_Free( rgb.buffer );
|
||||
}
|
||||
#endif // XASH_ENGINE_TESTS
|
||||
|
||||
#if XASH_LLVM_LIBFUZZER
|
||||
#include "sprite.h"
|
||||
|
||||
#define IMPLEMENT_IMAGELIB_FUZZ_TARGET( export, target ) \
|
||||
int EXPORT export( const uint8_t *Data, size_t Size ); \
|
||||
@@ -724,4 +728,29 @@ IMPLEMENT_IMAGELIB_FUZZ_TARGET( Fuzz_Image_LoadPNG, Image_LoadPNG )
|
||||
IMPLEMENT_IMAGELIB_FUZZ_TARGET( Fuzz_Image_LoadDDS, Image_LoadDDS )
|
||||
IMPLEMENT_IMAGELIB_FUZZ_TARGET( Fuzz_Image_LoadTGA, Image_LoadTGA )
|
||||
|
||||
#endif /* XASH_ENGINE_TESTS */
|
||||
int EXPORT Fuzz_Image_LoadSPR( const uint8_t *Data, size_t Size );
|
||||
int EXPORT Fuzz_Image_LoadSPR( const uint8_t *Data, size_t Size )
|
||||
{
|
||||
rgbdata_t *rgb;
|
||||
|
||||
// the real caller passes only the pixel data size, the frame header is extra
|
||||
if( Size < sizeof( dspriteframe_t ))
|
||||
return 0;
|
||||
|
||||
host.type = HOST_NORMAL;
|
||||
Memory_Init();
|
||||
Image_Init();
|
||||
|
||||
image.hint = IL_HINT_Q1; // installs the Quake palette so the decoder runs
|
||||
|
||||
if( Image_LoadSPR( "#internal.spr", Data, Size - sizeof( dspriteframe_t )))
|
||||
{
|
||||
rgb = ImagePack( "#internal.spr" );
|
||||
FS_FreeImage( rgb );
|
||||
}
|
||||
|
||||
Image_Shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // XASH_LLVM_LIBFUZZER
|
||||
|
||||
@@ -302,3 +302,34 @@ void Mod_LoadSpriteModel( model_t *mod, void *buffer, size_t buffersize, qboolea
|
||||
Mod_SpriteLoadTextures( mod, buffer );
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XASH_LLVM_LIBFUZZER
|
||||
int EXPORT Fuzz_Mod_LoadSpriteModel( const uint8_t *Data, size_t Size );
|
||||
int EXPORT Fuzz_Mod_LoadSpriteModel( const uint8_t *Data, size_t Size )
|
||||
{
|
||||
model_t mod = { .name = "#internal.spr", .needload = NL_NEEDS_LOADED };
|
||||
qboolean loaded = false;
|
||||
byte *buf;
|
||||
|
||||
if( Size == 0 )
|
||||
return 0;
|
||||
|
||||
Memory_Init();
|
||||
|
||||
// dedicated mode exercises the parser/validator without needing a renderer
|
||||
host.type = HOST_DEDICATED;
|
||||
host.mempool = Mem_AllocPool( "fuzzing pool" );
|
||||
|
||||
// the loader byteswaps the buffer in place, so hand it a writable copy
|
||||
buf = Mem_Malloc( host.mempool, Size );
|
||||
memcpy( buf, Data, Size );
|
||||
|
||||
Mod_LoadSpriteModel( &mod, buf, Size, &loaded );
|
||||
|
||||
if( mod.mempool )
|
||||
Mem_FreePool( &mod.mempool );
|
||||
Mem_FreePool( &host.mempool );
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // XASH_LLVM_LIBFUZZER
|
||||
|
||||
@@ -653,7 +653,7 @@ void Mod_NeedCRC( const char *name, qboolean needCRC )
|
||||
else ClearBits( p->flags, FCRC_SHOULD_CHECKSUM );
|
||||
}
|
||||
|
||||
#if XASH_ENGINE_TESTS
|
||||
#if XASH_LLVM_LIBFUZZER
|
||||
|
||||
static const uint8_t *fuzz_data;
|
||||
static size_t fuzz_size;
|
||||
@@ -689,4 +689,4 @@ int EXPORT Fuzz_Mod_LoadModel( const uint8_t *Data, size_t Size )
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // XASH_ENGINE_TESTS
|
||||
#endif // XASH_LLVM_LIBFUZZER
|
||||
|
||||
@@ -47,9 +47,6 @@ def options(opt):
|
||||
grp.add_option('--enable-static-binary', action = 'store_true', dest = 'STATIC', default = False,
|
||||
help = 'build static binary(not recommended, --single-binary required) [default: %(default)s]')
|
||||
|
||||
grp.add_option('--enable-engine-fuzz', action = 'store_true', dest = 'ENGINE_FUZZ', default = False,
|
||||
help = 'add LLVM libFuzzer [default: %(default)s]' )
|
||||
|
||||
grp.add_option('--enable-ffmpeg', action = 'store_true', dest = 'FFMPEG', default = False,
|
||||
help = 'enable ffmpeg based movie playback [default: %(default)s')
|
||||
|
||||
@@ -89,9 +86,10 @@ def configure(conf):
|
||||
elif conf.env.DEST_OS == 'dos':
|
||||
conf.options.STATIC = True
|
||||
|
||||
if conf.options.ENGINE_FUZZ:
|
||||
if conf.options.ENABLE_FUZZER:
|
||||
conf.define('XASH_LLVM_LIBFUZZER', 1)
|
||||
conf.env.append_unique('CFLAGS', '-fsanitize=fuzzer-no-link')
|
||||
conf.env.append_unique('LINKFLAGS', '-fsanitize=fuzzer')
|
||||
conf.env.append_unique('LINKFLAGS', '-fsanitize=fuzzer-no-link')
|
||||
|
||||
# Client-only dependencies
|
||||
if conf.env.CLIENT:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <dlfcn.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -6,12 +7,13 @@
|
||||
#error
|
||||
#endif
|
||||
|
||||
typedef int (*FuzzFunc)(const char *Data, size_t Size);
|
||||
typedef int (*FuzzFunc)(const uint8_t *Data, size_t Size);
|
||||
|
||||
void *handle = NULL;
|
||||
FuzzFunc f = NULL;
|
||||
static void *handle = NULL;
|
||||
static FuzzFunc f = NULL;
|
||||
|
||||
int LLVMFuzzerTestOneInput( const char *Data, size_t Size )
|
||||
int LLVMFuzzerTestOneInput( const uint8_t *Data, size_t Size );
|
||||
int LLVMFuzzerTestOneInput( const uint8_t *Data, size_t Size )
|
||||
{
|
||||
if( !handle )
|
||||
handle = dlopen( LIB, RTLD_NOW );
|
||||
|
||||
@@ -37,4 +37,6 @@ def build(bld):
|
||||
add_runner_target(bld, 'libxash.so', 'Image_LoadPNG')
|
||||
add_runner_target(bld, 'libxash.so', 'Image_LoadDDS')
|
||||
add_runner_target(bld, 'libxash.so', 'Image_LoadTGA')
|
||||
add_runner_target(bld, 'libxash.so', 'Image_LoadSPR')
|
||||
add_runner_target(bld, 'libxash.so', 'Mod_LoadModel')
|
||||
add_runner_target(bld, 'libxash.so', 'Mod_LoadSpriteModel')
|
||||
|
||||
2
wscript
2
wscript
@@ -86,6 +86,7 @@ SUBDIRS = [
|
||||
Subproject('3rdparty/libbacktrace'),
|
||||
Subproject('3rdparty/library_suffix'),
|
||||
Subproject('3rdparty/yy-thunks'),
|
||||
Subproject('utils/run-fuzzer', lambda x: x.env.ENABLE_FUZZER),
|
||||
|
||||
# disable only by engine feature, makes no sense to even parse subprojects in dedicated mode
|
||||
Subproject('3rdparty/extras', lambda x: x.env.CLIENT and x.env.DEST_OS != 'android'),
|
||||
@@ -114,7 +115,6 @@ SUBDIRS = [
|
||||
# enabled optionally
|
||||
Subproject('utils/mdldec', lambda x: x.env.ENABLE_UTILS),
|
||||
Subproject('utils/xar', lambda x: x.env.ENABLE_UTILS and x.env.ENABLE_XAR),
|
||||
Subproject('utils/run-fuzzer', lambda x: x.env.ENABLE_FUZZER),
|
||||
|
||||
# enabled on PSVita only
|
||||
Subproject('ref/gl/vgl_shim', lambda x: x.env.DEST_OS == 'psvita'),
|
||||
|
||||
Reference in New Issue
Block a user