[ftrandom] Various fixes.

* src/tools/ftrandom/ftrandom.c (GOOD_FONTS_DIR): Provide better
default.
(error_fraction): Make it of type `double' to work as advertized –
this was completely broken.
Update all related code.
(error_count, fcnt): Make it unsigned to fix compiler warnings.
Update all related code.
(fontlist): Change `len' member to `long' to fix compiler warnings.
(FT_MoveTo, FT_LineTo, FT_ConicTo, FT_CubicTo, abort_test): Tag
unused variables.
(TestFace, FindFonts, copyfont, do_test): Fix compiler warnings.
(ExecuteTest): Ditto.
Call `FT_Done_FreeType'.
(getErrorCnt): Replace `ceil' with an ordinary cast to `unsigned
int'.
(usage): Improve output.
(main): Fix compiler warnings.

* src/tools/ftrandom/README: Updated.
This commit is contained in:
Werner Lemberg 2016-09-03 13:06:16 +02:00
parent b98dfda392
commit ca8e98d94a
3 changed files with 148 additions and 59 deletions

View File

@ -1,3 +1,27 @@
2016-09-03 Werner Lemberg <wl@gnu.org>
[ftrandom] Various fixes.
* src/tools/ftrandom/ftrandom.c (GOOD_FONTS_DIR): Provide better
default.
(error_fraction): Make it of type `double' to work as advertized
this was completely broken.
Update all related code.
(error_count, fcnt): Make it unsigned to fix compiler warnings.
Update all related code.
(fontlist): Change `len' member to `long' to fix compiler warnings.
(FT_MoveTo, FT_LineTo, FT_ConicTo, FT_CubicTo, abort_test): Tag
unused variables.
(TestFace, FindFonts, copyfont, do_test): Fix compiler warnings.
(ExecuteTest): Ditto.
Call `FT_Done_FreeType'.
(getErrorCnt): Replace `ceil' with an ordinary cast to `unsigned
int'.
(usage): Improve output.
(main): Fix compiler warnings.
* src/tools/ftrandom/README: Updated.
2016-09-03 Werner Lemberg <wl@gnu.org>
[base] Avoid negative bitmap stroke dimensions (#48985).

View File

@ -1,48 +1,69 @@
ftrandom
--------
========
This program expects a set of directories containing good fonts, and a set
of extensions of fonts to be tested. It will randomly pick a font, copy it,
introduce and error and then test it.
introduce an error and then test it.
The FreeType tests are quite basic:
The FreeType tests are quite basic; for each erroneous font ftrandom
For each erroneous font it
forks off a new tester;
initializes the library;
opens each font in the file;
loads each glyph;
(optionally reviewing the contours of the glyph)
(optionally rasterizing)
closes the face.
. forks off a new tester,
. initializes the library,
. opens each font in the file,
. loads each glyph,
. optionally reviews the contours of the glyph,
. optionally rasterizes the glyph, and
. closes the face.
If the tester exits with a signal, or takes longer than 20 seconds then
ftrandom saves the erroneous font and continues. If the tester exits
normally or with an error, then the superstructure removes the test font and
continues.
If a tester takes longer than 20 seconds, ftrandom saves the erroneous font
and continues. If the tester exits normally or with an error, then the
superstructure removes the test font and continues.
Arguments are:
Command line options
--------------------
--all Test every font in the directory(ies) no matter
what its extension (some CID-keyed fonts have no
extension).
--check-outlines Call FT_Outline_Decompose on each glyph.
what its extension.
--check-outlines Call `FT_Outline_Decompose' on each glyph.
--dir <dir> Append <dir> to the list of directories to search
for good fonts.
for good fonts. No recursive search.
--error-count <cnt> Introduce <cnt> single-byte errors into the
erroneous fonts.
erroneous fonts (default: 1).
--error-fraction <frac> Multiply the file size of the font by <frac> and
introduce that many errors into the erroneous
font file.
--ext <ext> Add <ext> to the set of font types tested. Known
extensions are `ttf', `otf', `ttc', `cid', `pfb',
`pfa', `bdf', `pcf', `pfr', `fon', `otb', and
`cff'.
font file. <frac> should be in the range [0;1]
(default: 0.0).
--ext <ext> Add <ext> to the set of font types tested.
--help Print out this list of options.
--nohints Specify FT_LOAD_NO_HINTING when loading glyphs.
--rasterize Call FT_Render_Glyph as well as loading it.
--rasterize Call `FT_Render_Glyph' as well as loading it.
--result <dir> This is the directory in which test files are
placed.
--test <file> Run a single test on a pre-generated testcase.
Done in the current process so it can be debugged
more easily.
This is done in the current process so it can be
debugged more easily.
The default font extensions tested by ftrandom are
.ttf .otf .ttc .cid .pfb .pfa .bdf .pcf .pfr .fon .otb .cff
The default font directory is controlled by the macro `GOOD_FONTS_DIR' in
the source code (and can be thus specified during compilation); its default
value is
/usr/local/share/fonts
The default result directory is `results' (in the current directory).
Compilation
-----------
Two possible solutions.
. Run ftrandom within a debugging tool like `valgrind' to catch various
memory issues.
. Compile FreeType with sanitizer flags as provided by gcc or clang, for
example, then link it with ftrandom.

View File

@ -38,7 +38,6 @@
#include <sys/wait.h>
#include <unistd.h>
#include <dirent.h>
#include <math.h>
#include <signal.h>
#include <time.h>
@ -56,7 +55,7 @@
static int rasterize = false;
static char* results_dir = "results";
#define GOOD_FONTS_DIR "/home/wl/freetype-testfonts"
#define GOOD_FONTS_DIR "/usr/local/share/fonts"
static char* default_dir_list[] =
{
@ -81,28 +80,31 @@
NULL
};
static int error_count = 1;
static int error_fraction = 0;
static unsigned int error_count = 1;
static double error_fraction = 0.0;
static FT_F26Dot6 font_size = 12 * 64;
static struct fontlist
{
char* name;
int len;
long len;
unsigned int isbinary: 1;
unsigned int isascii: 1;
unsigned int ishex: 1;
} *fontlist;
static int fcnt;
static unsigned int fcnt;
static int
FT_MoveTo( const FT_Vector *to,
void *user )
{
FT_UNUSED( to );
FT_UNUSED( user );
return 0;
}
@ -111,6 +113,9 @@
FT_LineTo( const FT_Vector *to,
void *user )
{
FT_UNUSED( to );
FT_UNUSED( user );
return 0;
}
@ -120,6 +125,10 @@
const FT_Vector *to,
void *user )
{
FT_UNUSED( _cp );
FT_UNUSED( to );
FT_UNUSED( user );
return 0;
}
@ -130,6 +139,11 @@
const FT_Vector *to,
void *user )
{
FT_UNUSED( cp1 );
FT_UNUSED( cp2 );
FT_UNUSED( to );
FT_UNUSED( user );
return 0;
}
@ -147,8 +161,8 @@
static void
TestFace( FT_Face face )
{
int gid;
int load_flags = FT_LOAD_DEFAULT;
unsigned int gid;
int load_flags = FT_LOAD_DEFAULT;
if ( check_outlines &&
@ -202,7 +216,7 @@
TestFace( face );
else
{
int i, num;
long i, num;
num = face->num_faces;
@ -215,6 +229,8 @@
}
}
FT_Done_FreeType( context );
exit( 0 );
}
@ -329,9 +345,10 @@
FindFonts( char** fontdirs,
char** extensions )
{
int i, max;
char buffer[1025];
struct stat statb;
int i;
unsigned int max;
char buffer[1025];
struct stat statb;
max = 0;
@ -392,13 +409,13 @@
}
static int
static unsigned int
getErrorCnt( struct fontlist* item )
{
if ( error_count == 0 && error_fraction == 0 )
if ( error_count == 0 && error_fraction == 0.0 )
return 0;
return error_count + ceil( error_fraction * item->len );
return error_count + (unsigned int)( error_fraction * item->len );
}
@ -417,10 +434,10 @@
copyfont( struct fontlist* item,
char* newfont )
{
static char buffer[8096];
FILE *good, *new;
int len;
int i, err_cnt;
static char buffer[8096];
FILE *good, *new;
size_t len;
unsigned int i, err_cnt;
good = fopen( item->name, "r" );
@ -446,7 +463,7 @@
err_cnt = getErrorCnt( item );
for ( i = 0; i < err_cnt; ++i )
{
fseek( new, getRandom( 0, item->len - 1 ), SEEK_SET );
fseek( new, getRandom( 0, (int)( item->len - 1 ) ), SEEK_SET );
if ( item->isbinary )
putc( getRandom( 0, 0xFF ), new );
@ -484,6 +501,8 @@
static void
abort_test( int sig )
{
FT_UNUSED( sig );
/* If a time-out happens, then kill the child */
kill( child_pid, SIGFPE );
write( 2, "Timeout... ", 11 );
@ -493,7 +512,7 @@
static void
do_test( void )
{
int i = getRandom( 0, fcnt - 1 );
int i = getRandom( 0, (int)( fcnt - 1 ) );
static int test_num = 0;
char buffer[1024];
@ -534,22 +553,42 @@
usage( FILE* out,
char* name )
{
char** d = default_dir_list;
char** e = default_ext_list;
fprintf( out, "%s [options] -- Generate random erroneous fonts\n"
" and attempt to parse them with FreeType.\n\n", name );
fprintf( out, " --all All non-directory files are assumed to be fonts.\n" );
fprintf( out, " --check-outlines Make sure we can parse the outlines of each glyph.\n" );
fprintf( out, " --dir <path> Append <path> to list of font search directories.\n" );
fprintf( out, " --error-count <cnt> Introduce <cnt> single byte errors into each font.\n" );
fprintf( out, " --dir <path> Append <path> to list of font search directories\n"
" (no recursive search).\n" );
fprintf( out, " --error-count <cnt> Introduce <cnt> single byte errors into each font\n"
" (default: 1)\n" );
fprintf( out, " --error-fraction <frac> Introduce <frac>*filesize single byte errors\n"
" into each font.\n" );
" into each font (default: 0.0).\n" );
fprintf( out, " --ext <ext> Add <ext> to list of extensions indicating fonts.\n" );
fprintf( out, " --help Print this.\n" );
fprintf( out, " --nohints Turn off hinting.\n" );
fprintf( out, " --rasterize Attempt to rasterize each glyph.\n" );
fprintf( out, " --results <dir> Directory in which to place the test fonts.\n" );
fprintf( out, " --results <path> Place the created test fonts into <path>\n"
" (default: `results')\n" );
fprintf( out, " --size <float> Use the given font size for the tests.\n" );
fprintf( out, " --test <file> Run a single test on an already existing file.\n" );
fprintf( out, "\n" );
fprintf( out, "Default font extensions:\n" );
fprintf( out, " " );
while ( *e )
fprintf( out, " .%s", *e++ );
fprintf( out, "\n" );
fprintf( out, "Default font directories:\n" );
fprintf( out, " " );
while ( *d )
fprintf( out, " %s", *d++ );
fprintf( out, "\n" );
}
@ -564,8 +603,8 @@
char* testfile = NULL;
dirs = calloc( argc + 1, sizeof ( char ** ) );
exts = calloc( argc + 1, sizeof ( char ** ) );
dirs = calloc( (size_t)( argc + 1 ), sizeof ( char ** ) );
exts = calloc( (size_t)( argc + 1 ), sizeof ( char ** ) );
for ( i = 1; i < argc; ++i )
{
@ -585,9 +624,9 @@
else if ( strcmp( pt, "-error-count" ) == 0 )
{
if ( !rset )
error_fraction = 0;
error_fraction = 0.0;
rset = true;
error_count = strtol( argv[++i], &end, 10 );
error_count = (unsigned int)strtoul( argv[++i], &end, 10 );
if ( *end != '\0' )
{
fprintf( stderr, "Bad value for error-count: %s\n", argv[i] );
@ -605,6 +644,11 @@
fprintf( stderr, "Bad value for error-fraction: %s\n", argv[i] );
exit( 1 );
}
if ( error_fraction < 0.0 || error_fraction > 1.0 )
{
fprintf( stderr, "error-fraction must be in the range [0;1]\n" );
exit( 1 );
}
}
else if ( strcmp( pt, "-ext" ) == 0 )
exts[ecnt++] = argv[++i];
@ -658,7 +702,7 @@
ExecuteTest( testfile ); /* This should never return */
time( &now );
srandom( now );
srandom( (unsigned int)now );
FindFonts( dirs, exts );
mkdir( results_dir, 0755 );