Move the legacy fuzz target to the `freetype-testing' repository.

It can now be found at

  https://github.com/freetype/freetype2-testing/tree/master/fuzzing/src/legacy

* src/tools/ftfuzzer: Remove this folder and its contents from the
repository.
This commit is contained in:
Armin Hasitzka 2018-07-20 19:32:13 +02:00
parent 14032290bf
commit 154832d466
6 changed files with 11 additions and 1010 deletions

View File

@ -1,3 +1,14 @@
2018-07-20 Armin Hasitzka <prince.cherusker@gmail.com>
Move the legacy fuzz target to the `freetype-testing' repository.
It can now be found at
https://github.com/freetype/freetype2-testing/tree/master/fuzzing/src/legacy
* src/tools/ftfuzzer: Remove this folder and its contents from the
repository.
2018-07-20 Werner Lemberg <wl@gnu.org>
[cff] Avoid left-shift of negative numbers (#54322).

View File

@ -1,81 +0,0 @@
ftfuzzer
========
ftfuzzer.cc
-----------
This file contains a target function for FreeType fuzzing. It can be
used with libFuzzer (https://llvm.org/docs/LibFuzzer.html) or
potentially any other similar fuzzer.
Usage:
1. Build `libfreetype.a' and `ftfuzzer.cc' using the most recent
clang compiler with these flags:
# for fuzzer coverage feedback
-fsanitize-coverage=edge,8bit-counters
# for bug checking
-fsanitize=address,signed-integer-overflow,shift
You also need the header files from the `libarchive' library
(https://www.libarchive.org/) for handling tar files (see file
`ftmutator.cc' below for more).
2. Link with `libFuzzer' (it contains `main') and `libarchive'.
3. Run the fuzzer on some test corpus.
The exact flags and commands may vary.
https://github.com/google/oss-fuzz/tree/master/projects/freetype2
There is a continuous fuzzing bot that runs ftfuzzer.
https://oss-fuzz.com
(You need an account to be able to see coverage reports and the like
on oss-fuzz.com.)
Check the bot configuration for the most current settings.
ftmutator.cc
------------
FreeType has the ability to `attach' auxiliary files to a font file,
providing additional information. The main usage is to load AFM files
for PostScript Type 1 fonts.
However, libFuzzer currently only supports mutation of a single input
file. For this reason, `ftmutator.cc' contains a custom fuzzer
mutator that uses an uncompressed tar file archive as the input. The
first file in such a tarball gets opened by FreeType as a font, all
other files are treated as input for `FT_Attach_Stream'.
Compilation is similar to `ftfuzzer.c'.
runinput.cc
-----------
To run the target function on a set of input files, this file contains
a convenience `main' function. Link it with `ftfuzzer.cc',
`libfreetype.a', and `libarchive' and run like
./a.out my_tests_inputs/*
----------------------------------------------------------------------
Copyright 2015-2018 by
David Turner, Robert Wilhelm, and Werner Lemberg.
This file is part of the FreeType project, and may only be used,
modified, and distributed under the terms of the FreeType project
license, LICENSE.TXT. By continuing to use, modify, or distribute
this file you indicate that you have read the license and understand
and accept it fully.
--- end of README ---

View File

@ -1,428 +0,0 @@
// ftfuzzer.cc
//
// A fuzzing function to test FreeType with libFuzzer.
//
// Copyright 2015-2018 by
// David Turner, Robert Wilhelm, and Werner Lemberg.
//
// This file is part of the FreeType project, and may only be used,
// modified, and distributed under the terms of the FreeType project
// license, LICENSE.TXT. By continuing to use, modify, or distribute
// this file you indicate that you have read the license and
// understand and accept it fully.
// we use `unique_ptr', `decltype', and other gimmicks defined since C++11
#if __cplusplus < 201103L
# error "a C++11 compiler is needed"
#endif
#include <archive.h>
#include <archive_entry.h>
#include <assert.h>
#include <stdint.h>
#include <memory>
#include <vector>
using namespace std;
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_CACHE_H
#include FT_CACHE_CHARMAP_H
#include FT_CACHE_IMAGE_H
#include FT_CACHE_SMALL_BITMAPS_H
#include FT_SYNTHESIS_H
#include FT_ADVANCES_H
#include FT_OUTLINE_H
#include FT_BBOX_H
#include FT_MODULE_H
#include FT_DRIVER_H
#include FT_MULTIPLE_MASTERS_H
static FT_Library library;
static int InitResult;
struct FT_Global
{
FT_Global()
{
InitResult = FT_Init_FreeType( &library );
if ( InitResult )
return;
// try to activate Adobe's CFF engine; it might not be the default
unsigned int cff_hinting_engine = FT_HINTING_ADOBE;
FT_Property_Set( library,
"cff",
"hinting-engine", &cff_hinting_engine );
}
~FT_Global()
{
FT_Done_FreeType( library );
}
};
FT_Global global_ft;
// We want to select n values at random (without repetition),
// with 0 < n <= N. The algorithm is taken from TAoCP, Vol. 2
// (Algorithm S, selection sampling technique)
struct Random
{
int n;
int N;
int t; // total number of values so far
int m; // number of selected values so far
uint32_t r; // the current pseudo-random number
Random( int n_,
int N_ )
: n( n_ ),
N( N_ )
{
t = 0;
m = 0;
// Ideally, this should depend on the input file,
// for example, taking the sha256 as input;
// however, this is overkill for fuzzying tests.
r = 12345;
}
int get()
{
if ( m >= n )
return -1;
Redo:
// We can't use `rand': different C libraries might provide
// different implementations of this function. As a replacement,
// we use a 32bit version of the `xorshift' algorithm.
r ^= r << 13;
r ^= r >> 17;
r ^= r << 5;
double U = double( r ) / UINT32_MAX;
if ( ( N - t ) * U >= ( n - m ) )
{
t++;
goto Redo;
}
t++;
m++;
return t;
}
};
static int
archive_read_entry_data( struct archive *ar,
vector<FT_Byte> *vw )
{
int r;
const FT_Byte* buff;
size_t size;
int64_t offset;
for (;;)
{
r = archive_read_data_block( ar,
reinterpret_cast<const void**>( &buff ),
&size,
&offset );
if ( r == ARCHIVE_EOF )
return ARCHIVE_OK;
if ( r != ARCHIVE_OK )
return r;
vw->insert( vw->end(), buff, buff + size );
}
}
static vector<vector<FT_Byte>>
parse_data( const uint8_t* data,
size_t size )
{
struct archive_entry* entry;
int r;
vector<vector<FT_Byte>> files;
unique_ptr<struct archive,
decltype ( archive_read_free )*> a( archive_read_new(),
archive_read_free );
// activate reading of uncompressed tar archives
archive_read_support_format_tar( a.get() );
// the need for `const_cast' was removed with libarchive commit be4d4dd
if ( !( r = archive_read_open_memory(
a.get(),
const_cast<void*>(static_cast<const void*>( data ) ),
size ) ) )
{
unique_ptr<struct archive,
decltype ( archive_read_close )*> a_open( a.get(),
archive_read_close );
// read files contained in archive
for (;;)
{
r = archive_read_next_header( a_open.get(), &entry );
if ( r == ARCHIVE_EOF )
break;
if ( r != ARCHIVE_OK )
break;
vector<FT_Byte> entry_data;
r = archive_read_entry_data( a.get(), &entry_data );
if ( r != ARCHIVE_OK )
break;
files.push_back( move( entry_data ) );
}
}
if ( files.size() == 0 )
files.emplace_back( data, data + size );
return files;
}
static void
setIntermediateAxis( FT_Face face )
{
// only handle Multiple Masters and GX variation fonts
if ( !FT_HAS_MULTIPLE_MASTERS( face ) )
return;
// get variation data for current instance
FT_MM_Var* variations_ptr = nullptr;
if ( FT_Get_MM_Var( face, &variations_ptr ) )
return;
unique_ptr<FT_MM_Var,
decltype ( free )*> variations( variations_ptr, free );
vector<FT_Fixed> coords( variations->num_axis );
// select an arbitrary instance
for ( unsigned int i = 0; i < variations->num_axis; i++ )
coords[i] = ( variations->axis[i].minimum +
variations->axis[i].def ) / 2;
if ( FT_Set_Var_Design_Coordinates( face,
FT_UInt( coords.size() ),
coords.data() ) )
return;
}
// the interface function to the libFuzzer library
extern "C" int
LLVMFuzzerTestOneInput( const uint8_t* data,
size_t size_ )
{
assert( !InitResult );
if ( size_ < 1 )
return 0;
const vector<vector<FT_Byte>>& files = parse_data( data, size_ );
FT_Face face;
FT_Int32 load_flags = FT_LOAD_DEFAULT;
#if 0
FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
#endif
// We use a conservative approach here, at the cost of calling
// `FT_New_Face' quite often. The idea is that the fuzzer should be
// able to try all faces and named instances of a font, expecting that
// some faces don't work for various reasons, e.g., a broken subfont, or
// an unsupported NFNT bitmap font in a Mac dfont resource that holds
// more than a single font.
// get number of faces
if ( FT_New_Memory_Face( library,
files[0].data(),
(FT_Long)files[0].size(),
-1,
&face ) )
return 0;
long num_faces = face->num_faces;
FT_Done_Face( face );
// loop over up to 20 arbitrarily selected faces
// from index range [0;num-faces-1]
long max_face_cnt = num_faces < 20
? num_faces
: 20;
Random faces_pool( (int)max_face_cnt, (int)num_faces );
for ( long face_cnt = 0;
face_cnt < max_face_cnt;
face_cnt++ )
{
long face_index = faces_pool.get() - 1;
// get number of instances
if ( FT_New_Memory_Face( library,
files[0].data(),
(FT_Long)files[0].size(),
-( face_index + 1 ),
&face ) )
continue;
long num_instances = face->style_flags >> 16;
FT_Done_Face( face );
// loop over the face without instance (index 0)
// and up to 20 arbitrarily selected instances
// from index range [1;num_instances]
long max_instance_cnt = num_instances < 20
? num_instances
: 20;
Random instances_pool( (int)max_instance_cnt, (int)num_instances );
for ( long instance_cnt = 0;
instance_cnt <= max_instance_cnt;
instance_cnt++ )
{
long instance_index = 0;
if ( !instance_cnt )
{
if ( FT_New_Memory_Face( library,
files[0].data(),
(FT_Long)files[0].size(),
face_index,
&face ) )
continue;
}
else
{
instance_index = instances_pool.get();
if ( FT_New_Memory_Face( library,
files[0].data(),
(FT_Long)files[0].size(),
( instance_index << 16 ) + face_index,
&face ) )
continue;
}
// if we have more than a single input file coming from an archive,
// attach them (starting with the second file) using the order given
// in the archive
for ( size_t files_index = 1;
files_index < files.size();
files_index++ )
{
FT_Open_Args open_args = {};
open_args.flags = FT_OPEN_MEMORY;
open_args.memory_base = files[files_index].data();
open_args.memory_size = (FT_Long)files[files_index].size();
// the last archive element will be eventually used as the
// attachment
FT_Attach_Stream( face, &open_args );
}
// loop over an arbitrary size for outlines
// and up to ten arbitrarily selected bitmap strike sizes
// from the range [0;num_fixed_sizes - 1]
int max_size_cnt = face->num_fixed_sizes < 10
? face->num_fixed_sizes
: 10;
Random sizes_pool( max_size_cnt, face->num_fixed_sizes );
for ( int size_cnt = 0;
size_cnt <= max_size_cnt;
size_cnt++ )
{
FT_Int32 flags = load_flags;
int size_index = 0;
if ( !size_cnt )
{
// set up 20pt at 72dpi as an arbitrary size
if ( FT_Set_Char_Size( face, 20 * 64, 20 * 64, 72, 72 ) )
continue;
flags |= FT_LOAD_NO_BITMAP;
}
else
{
// bitmap strikes are not active for font variations
if ( instance_index )
continue;
size_index = sizes_pool.get() - 1;
if ( FT_Select_Size( face, size_index ) )
continue;
flags |= FT_LOAD_COLOR;
}
// test MM interface only for a face without a selected instance
// and without a selected bitmap strike
if ( !instance_index && !size_cnt )
setIntermediateAxis( face );
// loop over all glyphs
for ( unsigned int glyph_index = 0;
glyph_index < (unsigned int)face->num_glyphs;
glyph_index++ )
{
if ( FT_Load_Glyph( face, glyph_index, flags ) )
continue;
// Rendering is the most expensive and the least interesting part.
//
// if ( FT_Render_Glyph( face->glyph, render_mode) )
// continue;
// FT_GlyphSlot_Embolden( face->glyph );
#if 0
FT_Glyph glyph;
if ( !FT_Get_Glyph( face->glyph, &glyph ) )
FT_Done_Glyph( glyph );
FT_Outline* outline = &face->glyph->outline;
FT_Matrix rot30 = { 0xDDB4, -0x8000, 0x8000, 0xDDB4 };
FT_Outline_Transform( outline, &rot30 );
FT_BBox bbox;
FT_Outline_Get_BBox( outline, &bbox );
#endif
}
}
FT_Done_Face( face );
}
}
return 0;
}
// END

View File

@ -1,314 +0,0 @@
// ftmutator.cc
//
// A custom fuzzer mutator to test for FreeType with libFuzzer.
//
// Copyright 2015-2018 by
// David Turner, Robert Wilhelm, and Werner Lemberg.
//
// This file is part of the FreeType project, and may only be used,
// modified, and distributed under the terms of the FreeType project
// license, LICENSE.TXT. By continuing to use, modify, or distribute
// this file you indicate that you have read the license and
// understand and accept it fully.
// Since `tar' is not a valid format for input to FreeType, treat any input
// that looks like `tar' as multiple files and mutate them separately.
//
// In the future, a variation of this may be used to guide mutation on a
// logically higher level.
// we use `unique_ptr', `decltype', and other gimmicks defined since C++11
#if __cplusplus < 201103L
# error "a C++11 compiler is needed"
#endif
#include <cstdint>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstddef>
#include <cstring>
#include <iostream>
#include <memory>
#include <vector>
#include <archive.h>
#include <archive_entry.h>
#include "FuzzerInterface.h"
using namespace std;
// This function should be defined by `ftfuzzer.cc'.
extern "C" int
LLVMFuzzerTestOneInput( const uint8_t* Data,
size_t Size );
static void
check_result( struct archive* a,
int r )
{
if ( r == ARCHIVE_OK )
return;
const char* m = archive_error_string( a );
write( 1, m, strlen( m ) );
exit( 1 );
}
static int
archive_read_entry_data( struct archive *ar,
vector<uint8_t> *vw )
{
int r;
const uint8_t* buff;
size_t size;
int64_t offset;
for (;;)
{
r = archive_read_data_block( ar,
reinterpret_cast<const void**>( &buff ),
&size,
&offset );
if ( r == ARCHIVE_EOF )
return ARCHIVE_OK;
if ( r != ARCHIVE_OK )
return r;
vw->insert( vw->end(), buff, buff + size );
}
}
static vector<vector<uint8_t>>
parse_data( const uint8_t* data,
size_t size )
{
struct archive_entry* entry;
int r;
vector<vector<uint8_t>> files;
unique_ptr<struct archive,
decltype ( archive_read_free )*> a( archive_read_new(),
archive_read_free );
// activate reading of uncompressed tar archives
archive_read_support_format_tar( a.get() );
// the need for `const_cast' was removed with libarchive commit be4d4dd
if ( !( r = archive_read_open_memory(
a.get(),
const_cast<void*>(static_cast<const void*>( data ) ),
size ) ) )
{
unique_ptr<struct archive,
decltype ( archive_read_close )*> a_open( a.get(),
archive_read_close );
// read files contained in archive
for (;;)
{
r = archive_read_next_header( a_open.get(), &entry );
if ( r == ARCHIVE_EOF )
break;
if ( r != ARCHIVE_OK )
break;
vector<uint8_t> entry_data;
r = archive_read_entry_data( a.get(), &entry_data );
if ( entry_data.size() == 0 )
continue;
files.push_back( move( entry_data ) );
if ( r != ARCHIVE_OK )
break;
}
}
return files;
}
class FTFuzzer
: public fuzzer::UserSuppliedFuzzer
{
public:
FTFuzzer( fuzzer::FuzzerRandomBase* Rand )
: fuzzer::UserSuppliedFuzzer( Rand ) {}
int
TargetFunction( const uint8_t* Data,
size_t Size )
{
return LLVMFuzzerTestOneInput( Data, Size );
}
// Custom mutator.
virtual size_t
Mutate( uint8_t* Data,
size_t Size,
size_t MaxSize )
{
vector<vector<uint8_t>> files = parse_data( Data, Size );
// If the file was not recognized as a tar file, treat it as non-tar.
if ( files.size() == 0 )
return fuzzer::UserSuppliedFuzzer::Mutate( Data, Size, MaxSize );
// This is somewhat `white box' on tar. The tar format uses 512 byte
// blocks. One block as header for each file, two empty blocks of 0's
// at the end. File data is padded to fill its last block.
size_t used_blocks = files.size() + 2;
for ( const auto& file : files )
used_blocks += ( file.size() + 511 ) / 512;
size_t max_blocks = MaxSize / 512;
// If the input is big, it will need to be downsized. If the original
// tar file was too big, it may have been clipped to fit. In this
// case it may not be possible to properly write out the data, as
// there may not be enough space for the trailing two blocks. Start
// dropping file data or files from the end.
for ( size_t i = files.size();
i-- > 1 && used_blocks > max_blocks; )
{
size_t blocks_to_free = used_blocks - max_blocks;
size_t blocks_currently_used_by_file_data =
( files[i].size() + 511 ) / 512;
if ( blocks_currently_used_by_file_data >= blocks_to_free )
{
files[i].resize( ( blocks_currently_used_by_file_data -
blocks_to_free ) * 512 );
used_blocks -= blocks_to_free;
continue;
}
files.pop_back();
used_blocks -= blocks_currently_used_by_file_data + 1;
}
// If we get down to one file, don't use tar.
if ( files.size() == 1 )
{
memcpy( Data, files[0].data(), files[0].size() );
return fuzzer::UserSuppliedFuzzer::Mutate( Data,
files[0].size(),
MaxSize );
}
size_t free_blocks = max_blocks - used_blocks;
// Allow each file to use up as much of the currently available space
// it can. If it uses or gives up blocks, add them or remove them
// from the pool.
for ( auto&& file : files )
{
size_t blocks_currently_used_by_file = ( file.size() + 511 ) / 512;
size_t blocks_available = blocks_currently_used_by_file +
free_blocks;
size_t max_size = blocks_available * 512;
size_t data_size = file.size();
file.resize( max_size );
file.resize( fuzzer::UserSuppliedFuzzer::Mutate( file.data(),
data_size,
max_size ) );
size_t blocks_now_used_by_file = ( file.size() + 511 ) / 512;
free_blocks = free_blocks +
blocks_currently_used_by_file -
blocks_now_used_by_file;
}
unique_ptr<struct archive,
decltype ( archive_write_free )*> a( archive_write_new(),
archive_write_free );
check_result( a.get(), archive_write_add_filter_none( a.get() ) );
check_result( a.get(), archive_write_set_format_ustar( a.get() ) );
// `used' may not be correct until after the archive is closed.
size_t used = 0xbadbeef;
check_result( a.get(), archive_write_open_memory( a.get(),
Data,
MaxSize,
&used ) );
{
unique_ptr<struct archive,
decltype ( archive_write_close )*> a_open( a.get(),
archive_write_close );
int file_index = 0;
for ( const auto& file : files )
{
unique_ptr<struct archive_entry,
decltype ( archive_entry_free )*>
e( archive_entry_new2( a_open.get() ),
archive_entry_free );
char name_buffer[100];
snprintf( name_buffer, 100, "file%d", file_index++ );
archive_entry_set_pathname( e.get(), name_buffer );
archive_entry_set_size( e.get(), file.size() );
archive_entry_set_filetype( e.get(), AE_IFREG );
archive_entry_set_perm( e.get(), 0644 );
check_result( a_open.get(),
archive_write_header( a_open.get(), e.get() ) );
archive_write_data( a_open.get(), file.data(), file.size() );
check_result( a_open.get(),
archive_write_finish_entry( a_open.get() ) );
}
}
return used;
}
// Cross `Data1' and `Data2', write up to `MaxOutSize' bytes into `Out',
// return the number of bytes written, which should be positive.
virtual size_t
CrossOver( const uint8_t* Data1,
size_t Size1,
const uint8_t* Data2,
size_t Size2,
uint8_t* Out,
size_t MaxOutSize )
{
return fuzzer::UserSuppliedFuzzer::CrossOver( Data1,
Size1,
Data2,
Size2,
Out,
MaxOutSize );
}
}; // end of FTFuzzer class
int
main( int argc,
char* *argv )
{
fuzzer::FuzzerRandomLibc Rand( 0 );
FTFuzzer F( &Rand );
fuzzer::FuzzerDriver( argc, argv, F );
}
// END

View File

@ -1,129 +0,0 @@
// rasterfuzzer.cc
//
// A fuzzing function to test FreeType's rasterizers with libFuzzer.
//
// Copyright 2016-2018 by
// David Turner, Robert Wilhelm, and Werner Lemberg.
//
// This file is part of the FreeType project, and may only be used,
// modified, and distributed under the terms of the FreeType project
// license, LICENSE.TXT. By continuing to use, modify, or distribute
// this file you indicate that you have read the license and
// understand and accept it fully.
#include <stdint.h>
#include <vector>
using namespace std;
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_IMAGE_H
#include FT_OUTLINE_H
static FT_Library library;
static int InitResult;
struct FT_Global {
FT_Global() {
InitResult = FT_Init_FreeType( &library );
}
~FT_Global() {
FT_Done_FreeType( library );
}
};
FT_Global global_ft;
extern "C" int
LLVMFuzzerTestOneInput( const uint8_t* data,
size_t size_ )
{
unsigned char pixels[4];
FT_Bitmap bitmap_mono = {
1, // rows
1, // width
4, // pitch
pixels, // buffer
2, // num_grays
FT_PIXEL_MODE_MONO, // pixel_mode
0, // palette_mode
NULL // palette
};
FT_Bitmap bitmap_gray = {
1, // rows
1, // width
4, // pitch
pixels, // buffer
256, // num_grays
FT_PIXEL_MODE_GRAY, // pixel_mode
0, // palette_mode
NULL // palette
};
const size_t vsize = sizeof ( FT_Vector );
const size_t tsize = sizeof ( char );
// we use the input data for both points and tags
short n_points = short( size_ / ( vsize + tsize ) );
if ( n_points <= 2 )
return 0;
FT_Vector* points = reinterpret_cast<FT_Vector*>(
const_cast<uint8_t*>(
data ) );
char* tags = reinterpret_cast<char*>(
const_cast<uint8_t*>(
data + size_t( n_points ) * vsize ) );
// to reduce the number of invalid outlines that are immediately
// rejected in `FT_Outline_Render', limit values to 2^18 pixels
// (i.e., 2^24 bits)
for ( short i = 0; i < n_points; i++ )
{
if ( points[i].x == LONG_MIN )
points[i].x = 0;
else if ( points[i].x < 0 )
points[i].x = -( -points[i].x & 0xFFFFFF ) - 1;
else
points[i].x = ( points[i].x & 0xFFFFFF ) + 1;
if ( points[i].y == LONG_MIN )
points[i].y = 0;
else if ( points[i].y < 0 )
points[i].y = -( -points[i].y & 0xFFFFFF ) - 1;
else
points[i].y = ( points[i].y & 0xFFFFFF ) + 1;
}
short contours[1];
contours[0] = n_points - 1;
FT_Outline outline =
{
1, // n_contours
n_points, // n_points
points, // points
tags, // tags
contours, // contours
FT_OUTLINE_NONE // flags
};
FT_Outline_Get_Bitmap( library, &outline, &bitmap_mono );
FT_Outline_Get_Bitmap( library, &outline, &bitmap_gray );
return 0;
}
// END

View File

@ -1,58 +0,0 @@
// runinput.cc
//
// A `main' function for fuzzers like `ftfuzzer.cc'.
//
// Copyright 2015-2018 by
// David Turner, Robert Wilhelm, and Werner Lemberg.
//
// This file is part of the FreeType project, and may only be used,
// modified, and distributed under the terms of the FreeType project
// license, LICENSE.TXT. By continuing to use, modify, or distribute
// this file you indicate that you have read the license and
// understand and accept it fully.
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
extern "C" void
LLVMFuzzerTestOneInput( const uint8_t* data,
size_t size );
unsigned char a[1 << 24];
int
main( int argc,
char* *argv )
{
assert( argc >= 2 );
for ( int i = 1; i < argc; i++ )
{
fprintf( stderr, "%s\n", argv[i] );
FILE* f = fopen( argv[i], "r" );
assert( f );
size_t n = fread( a, 1, sizeof ( a ), f );
fclose( f );
if ( !n )
continue;
unsigned char* b = (unsigned char*)malloc( n );
memcpy( b, a, n );
LLVMFuzzerTestOneInput( b, n );
free( b );
}
}
// END