Compare commits

...

14 Commits

Author SHA1 Message Date
suzuki toshiya d7aacf9ecf add note to docs/DEBUG 2011-01-15 02:39:37 +09:00
suzuki toshiya fa0acc4589 fix dir separator handling 2011-01-10 00:43:40 +09:00
suzuki toshiya 97c96f2995 use basename only in the site identification in alloc limiter 2011-01-10 00:43:40 +09:00
suzuki toshiya f6af979d2e introduce ft_basename(): if libgen.h is available, it is a macro to system basename() 2011-01-10 00:43:40 +09:00
suzuki toshiya dfaf70a056 s/PLATFORM_PATH_SEPARATOR/PLATFORM_DIR_SEPARATOR/ 2011-01-10 00:43:39 +09:00
suzuki toshiya b440828b6c use cpp-macro PLATFORM_PATH_SEPARATOR instead of raw ascii slash 2011-01-10 00:43:39 +09:00
suzuki toshiya 8967a174cd fix a bug to cause OOM 2011-01-10 00:42:22 +09:00
suzuki toshiya 82da8590f3 formatting 2011-01-09 23:33:29 +09:00
suzuki toshiya a434c5ab0a remove ft_basename() 2011-01-09 23:33:29 +09:00
suzuki toshiya d1543e350a update ft_mem_check_site_alloc_environment() for new syntax 2011-01-09 23:33:29 +09:00
suzuki toshiya 48b3386853 fix trace message bug in ft_mem_debug_alloc() 2011-01-09 23:33:29 +09:00
suzuki toshiya 09fe3e314b use ft_strchr() instead of index() 2011-01-09 23:33:28 +09:00
suzuki toshiya 2acbc01f74 fix trace levels 2011-01-09 23:33:28 +09:00
suzuki toshiya c6e0cdacfa introduce FT2_ALLOC_{TOTAL,CUR}_MAX_SITE environment to restrict memory allocation locally 2011-01-09 23:31:35 +09:00
14 changed files with 340 additions and 10 deletions

View File

@ -111,7 +111,7 @@ esac
# checks for header files
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h unistd.h])
AC_CHECK_HEADERS([fcntl.h unistd.h libgen.h])
# checks for typedefs, structures, and compiler characteristics

View File

@ -60,6 +60,7 @@ FT_BEGIN_HEADER
#undef HAVE_UNISTD_H
#undef HAVE_FCNTL_H
#undef HAVE_STDINT_H
#undef HAVE_LIBGEN_H
/* There are systems (like the Texas Instruments 'C54x) where a `char' */
@ -167,6 +168,26 @@ FT_BEGIN_HEADER
#endif
/*************************************************************************/
/* */
/* Pathname separator used by resource-fork accessor & ft_basename() */
/* */
#ifdef PLATFORM_DIR_SEPARATOR
/* explicitly defined, do nothing */
#elif defined( __DOS__ ) || defined( __OS2__ ) || defined( _WIN32 ) || \
defined( __SYMBIAN32__ )
#define PLATFORM_DIR_SEPARATOR "\\"
#elif defined( FT_MACINTOSH ) && !defined( __MACH__ )
#define PLATFORM_DIR_SEPARATOR ":"
#elif defined( __riscos__ ) || defined( VMS )
#define PLATFORM_DIR_SEPARATOR "."
#else
#define PLATFORM_DIR_SEPARATOR "/"
#endif
/* Fix compiler warning with sgi compiler */
#if defined( __sgi ) && !defined( __GNUC__ )
#if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )

View File

@ -187,9 +187,41 @@ behaviour of FreeType at runtime.
If it is undefined, or if its value is not strictly positive, then
no allocation bounds are checked at runtime.
FT2_ALLOC_CUR_MAX_SITE
This variable is ignored if FT2_DEBUG_MEMORY is not defined. It
allows you to specify a maximum size of the memory buffer allocated
at the specific site in the source code of FreeType. The variable is
a list of the per-site limits, separated by the space. The per-site
limit is a pair of the site specification and the limiting value in
digits, separated by a comma. The site specification is a pair of
the path name of source code and the line number in digits, as the
summary report given by setting FT2_DEBUG_MEMORY.
Example:
FT2_ALLOC_CUR_MAX_SITE=/tmp/freetype2/src/base/ftobjs.c:302,300000 \
/tmp/freetype2/src/base/ftglyph.c:290,10000 \
...
This is useful to check the recovery from an out of memory error at
the specific site of the source code. If it is undefined, or if its
value is negative, then no allocation bounds are checked at runtime.
FT2_ALLOC_TOTAL_MAX_SITE
This variable is almost same with FT2_ALLOC_CUR_MAX_SITE in above,
but it counts the summary of historical allocations at the specified
site of the source code. It does not care about whether the buffers
are freed. When the limiting value for a site is set to 1000 bytes
and repeating 100 bytes allocation and free it, the 11th allocation
will fail.
------------------------------------------------------------------------
Copyright 2002, 2003, 2004, 2005, 2009 by
Copyright 2002, 2003, 2004, 2005, 2009, 2011 by
David Turner, Robert Wilhelm, and Werner Lemberg.
This file is part of the FreeType project, and may only be used,

View File

@ -145,6 +145,25 @@ FT_BEGIN_HEADER
#endif
/*************************************************************************/
/* */
/* Pathname separator used by resource-fork accessor & ft_basename() */
/* */
#ifdef PLATFORM_DIR_SEPARATOR
/* explicitly defined, do nothing */
#elif defined( __DOS__ ) || defined( __OS2__ ) || defined( _WIN32 ) || \
defined( __SYMBIAN32__ )
#define PLATFORM_DIR_SEPARATOR "\\"
#elif defined( FT_MACINTOSH ) && !defined( __MACH__ )
#define PLATFORM_DIR_SEPARATOR ":"
#elif defined( __riscos__ ) || defined( VMS )
#define PLATFORM_DIR_SEPARATOR "."
#else
#define PLATFORM_DIR_SEPARATOR "/"
#endif
/*************************************************************************/
/* */
/* <Section> */

View File

@ -81,6 +81,7 @@
#define ft_memmove memmove
#define ft_memset memset
#define ft_strcat strcat
#define ft_strchr strchr
#define ft_strcmp strcmp
#define ft_strcpy strcpy
#define ft_strlen strlen

View File

@ -108,6 +108,14 @@ FT_BEGIN_HEADER
#define ft_isalpha( x ) ( ft_isupper( x ) || ft_islower( x ) )
#define ft_isalnum( x ) ( ft_isdigit( x ) || ft_isalpha( x ) )
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#define ft_basename( p ) basename( ( p ) )
#else
FT_BASE( char* )
ft_basename( char* path );
#endif
/*************************************************************************/
/*************************************************************************/

View File

@ -24,6 +24,7 @@ FT_TRACE_DEF( any )
/* base components */
FT_TRACE_DEF( calc ) /* calculations (ftcalc.c) */
FT_TRACE_DEF( memory ) /* memory manager (ftobjs.c) */
FT_TRACE_DEF( dbgmem ) /* memory debugger (ftdbgmem.c) */
FT_TRACE_DEF( stream ) /* stream manager (ftstream.c) */
FT_TRACE_DEF( io ) /* i/o interface (ftsystem.c) */
FT_TRACE_DEF( list ) /* list management (ftlist.c) */

View File

@ -25,6 +25,10 @@
#include FT_TYPES_H
#undef FT_COMPONENT
#define FT_COMPONENT trace_dbgmem
#ifdef FT_DEBUG_MEMORY
#define KEEPALIVE /* `Keep alive' means that freed blocks aren't released
@ -505,6 +509,72 @@
}
/*
* ft_mem_get_val_for_source( source, env_var_name )
*
* Get a numerical value from named environmental variable
* for the site specified by FT_MemSource. For the syntax
* of the environmental variable, see docs/DEBUG.
*
*/
static int
ft_mem_get_env_val_for_source( FT_MemSource source,
const char* env_var_name )
{
char *file_name = ft_basename( (char*)source->file_name );
char *c, *c0;
/* return if specified environment is unset */
c = c0 = getenv( env_var_name );
if ( !c )
return -1;
/* return if basename not found anymore */
while ( NULL != ( c = ft_strstr( c, file_name ) ) )
{
/* matched token is 1st or after separator space? */
if ( c != c0 && *(c-1) != ' ' &&
#ifdef PLATFORM_DIR_SEPARATOR
*(c-1) != PLATFORM_DIR_SEPARATOR[0] )
#elif defined( macintosh )
*(c-1) != ':' )
#else
*(c-1) != '/' && *(c-1) != '\\' )
#endif
goto NextToken;
/* check ':', a separator between pathname & line number */
c = c + ft_strlen( file_name );
if ( ':' != *c || !ft_isdigit( c[1] ) )
goto NextToken;
c++;
/* check the line number */
if ( atoi( c ) != source->line_no )
goto NextToken;
/* line number matched, skip digits */
while ( ft_isdigit( *c ) )
c++;
/* check ',', a separator between line number & value */
if ( ',' != *c || !ft_isdigit( c[1] ) )
goto NextToken;
c++;
return atoi( c );
NextToken:
c = ft_strchr( c, ' ' );
if ( !c ) /* no token anymore */
break;
c++;
}
return -1;
}
static void
ft_mem_table_set( FT_MemTable table,
FT_Byte* address,
@ -676,17 +746,89 @@
}
static FT_Bool
ft_mem_check_alloc_limiter_for_source( FT_MemSource source,
FT_Long size )
{
int mem_limit_site_total = -1; /* negative means unlimited */
int mem_limit_site_cur = -1; /* negative means unlimited */
FT_Bool exceeds_limit_site_total = FALSE;
FT_Bool exceeds_limit_site_cur = FALSE;
long req_all = source->all_size + size;
long req_cur = source->cur_size + size;
#define FT_HAS_LIMITER( key ) \
( mem_limit_ ## key ## _total >= 0 || mem_limit_ ## key ## _cur >= 0 )
#define FT_HAS_MULTI_LIMITERS( key ) \
( mem_limit_ ## key ## _total >= 0 && mem_limit_ ## key ## _cur >= 0 )
#define FT_TRACE6_DEFINED_LIMIT( req, limit ) \
{ \
if ( limit >= 0 ) \
FT_TRACE6(( "%ld =< %ld", req, limit )); \
}
mem_limit_site_total =
ft_mem_get_env_val_for_source( source,
"FT2_ALLOC_TOTAL_MAX_SITE" );
mem_limit_site_cur =
ft_mem_get_env_val_for_source( source,
"FT2_ALLOC_CUR_MAX_SITE" );
if ( FT_HAS_LIMITER( site ) )
FT_TRACE6(( "ft_mem_table_set() invoked by %s:%lu, limit:( ",
ft_basename( (char*)source->file_name ),
source->line_no ));
FT_TRACE6_DEFINED_LIMIT( req_all, mem_limit_site_total );
if ( FT_HAS_MULTI_LIMITERS( site ) )
FT_TRACE6(( " && " ));
FT_TRACE6_DEFINED_LIMIT( req_cur, mem_limit_site_cur );
if ( FT_HAS_LIMITER( site ) )
FT_TRACE6((" )\n"));
if ( mem_limit_site_total >= 0 && mem_limit_site_total < req_all )
exceeds_limit_site_total = TRUE;
if ( mem_limit_site_cur >= 0 && mem_limit_site_cur < req_cur )
exceeds_limit_site_cur = TRUE;
if ( exceeds_limit_site_total || exceeds_limit_site_cur )
{
FT_TRACE6(( "ft_mem_table_set() returns NULL to %s:%lu,"
" allocation request exceeds %s-limit (%lu > %lu)\n",
ft_basename( (char*)source->file_name ),
source->line_no,
( exceeds_limit_site_total ? "site-total" :
"site-current" ),
( exceeds_limit_site_total ? req_all :
req_cur ),
( exceeds_limit_site_total ? mem_limit_site_total :
mem_limit_site_cur )
));
return FALSE;
}
return TRUE;
#undef FT_HAS_LIMITER
#undef FT_HAS_MULTI_LIMITERS
#undef FT_TRACE6_DEFINED_LIMIT
}
extern FT_Pointer
ft_mem_debug_alloc( FT_Memory memory,
FT_Long size )
{
FT_MemTable table = (FT_MemTable)memory->user;
FT_Byte* block;
FT_MemTable table = (FT_MemTable)memory->user;
FT_MemSource source = NULL;
FT_Byte* block;
if ( size <= 0 )
ft_mem_debug_panic( "negative block size allocation (%ld)", size );
source = ft_mem_table_get_source( table );
if ( source )
if ( !ft_mem_check_alloc_limiter_for_source( source, size ) )
return NULL;
/* return NULL if the maximum number of allocations was reached */
if ( table->bound_count &&
table->alloc_count >= table->alloc_count_max )

View File

@ -1226,6 +1226,27 @@
}
#ifndef HAVE_LIBGEN_H
FT_BASE_DEF( char* )
ft_basename( char* pathname )
{
char* c;
c = pathname + ft_strlen( pathname );
/* skip trailing separator */
while ( pathname < c && *c == PLATFORM_DIR_SEPARATOR[0] )
c--;
while ( pathname < c && *(c-1) != PLATFORM_DIR_SEPARATOR[0] )
c--;
return c;
}
#endif
#ifdef FT_CONFIG_OPTION_MAC_FONTS
/* The behavior here is very similar to that in base/ftmac.c, but it */

View File

@ -25,6 +25,7 @@
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_RFORK_H
@ -543,7 +544,8 @@
return error;
FT_MEM_COPY( newpath, base_file_name, base_file_len );
FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
FT_MEM_COPY( newpath + base_file_len,
PLATFORM_DIR_SEPARATOR "rsrc", 6 );
*result_file_name = newpath;
*result_offset = 0;
@ -579,7 +581,9 @@
return error;
FT_MEM_COPY( newpath, base_file_name, base_file_len );
FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
FT_MEM_COPY( newpath + base_file_len,
PLATFORM_DIR_SEPARATOR "..namedfork"
PLATFORM_DIR_SEPARATOR "rsrc", 18 );
*result_file_name = newpath;
*result_offset = 0;
@ -604,7 +608,8 @@
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
"resource.frk/" );
"resource.frk"
PLATFORM_DIR_SEPARATOR );
if ( !newpath )
return FT_Err_Out_Of_Memory;
@ -630,7 +635,9 @@
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
newpath = raccess_make_file_name( memory, base_file_name,
".resource"
PLATFORM_DIR_SEPARATOR );
if ( !newpath )
return FT_Err_Out_Of_Memory;
@ -689,7 +696,8 @@
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
".AppleDouble/" );
".AppleDouble"
PLATFORM_DIR_SEPARATOR );
if ( !newpath )
return FT_Err_Out_Of_Memory;
@ -814,7 +822,7 @@
if ( FT_ALLOC( new_name, new_length + 1 ) )
return NULL;
tmp = ft_strrchr( original_name, '/' );
tmp = ft_strrchr( original_name, PLATFORM_DIR_SEPARATOR[0] );
if ( tmp )
{
ft_strncpy( new_name, original_name, tmp - original_name + 1 );

23
src/cache/ftccache.c vendored
View File

@ -478,6 +478,29 @@
}
FT_LOCAL_DEF( FT_Size )
ftc_get_list_length( FTC_Cache cache,
FT_PtrDist hash )
{
FT_Size len = 0;
FTC_Node* bucket;
FTC_Node* pnode;
FT_UFast idx;
idx = hash & cache->mask;
if ( idx < cache->p )
idx = hash & ( cache->mask * 2 + 1 );
bucket = cache->buckets + idx;
pnode = bucket;
for ( ; pnode && *pnode; pnode = &((*pnode)->link) )
len++;
return len;
}
#ifndef FTC_INLINE
FT_LOCAL_DEF( FT_Error )

14
src/cache/ftccache.h vendored
View File

@ -210,6 +210,10 @@ FT_BEGIN_HEADER
FTC_Cache_RemoveFaceID( FTC_Cache cache,
FTC_FaceID face_id );
FT_LOCAL( FT_Size )
ftc_get_list_length( FTC_Cache cache,
FT_PtrDist hash );
#ifdef FTC_INLINE
@ -222,6 +226,12 @@ FT_BEGIN_HEADER
FT_Bool _list_changed = FALSE; \
\
\
FT_TRACE6(("FTC_CACHE_LOOKUP_CMP() lookup object for ")); \
FT_TRACE6(("hash=0x%08x in cache ", _hash )); \
FT_TRACE6(("mask=0x%08x p=0x%08x ", _cache->mask, _cache->p )); \
FT_TRACE7(("list length=%d", ftc_get_list_length( _cache, _hash ) )); \
FT_TRACE6(("\n")); \
\
error = FTC_Err_Ok; \
node = NULL; \
\
@ -245,6 +255,8 @@ FT_BEGIN_HEADER
\
if ( _list_changed ) \
{ \
FT_TRACE7(("(_bucket,_pnode)=(%p,%p)", _bucket, _pnode)); \
\
/* Update _bucket by possibly modified linked list */ \
_bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \
\
@ -259,6 +271,8 @@ FT_BEGIN_HEADER
else \
_pnode = &((*_pnode)->link); \
} \
\
FT_TRACE7(("-> (%p,%p)\n", _bucket, _pnode)); \
} \
\
/* Reorder the list to move the found node to the `top' */ \

30
src/cache/ftcmanag.c vendored
View File

@ -622,6 +622,24 @@
}
static int
ft_get_length_nodes_list( FTC_Node node0 )
{
FTC_Node node = node0;
int len = 0;
while ( node )
{
len ++;
node = node->link;
if ( node == node0 )
return len;
}
return len;
}
FT_LOCAL_DEF( FT_UInt )
FTC_Manager_FlushN( FTC_Manager manager,
FT_UInt count )
@ -631,9 +649,17 @@
FT_UInt result;
FT_TRACE2(( "FTC_Manager_FlushN() tries to"
" free %d nodes from list length=%d\n",
count,
ft_get_length_nodes_list( manager->nodes_list ) ));
/* try to remove `count' nodes from the list */
if ( first == NULL ) /* empty list! */
{
FT_TRACE2(("FTC_Manager_FlushN() cannot change empty list\n" ));
return 0;
}
/* go to last node - it's a circular list */
node = FTC_NODE__PREV(first);
@ -654,6 +680,10 @@
node = prev;
}
FT_TRACE2(( "FTC_Manager_FlushN() freed %d nodes,"
" list length=%d\n",
result,
ft_get_length_nodes_list( manager->nodes_list ) ));
return result;
}

10
src/cache/ftcsbits.c vendored
View File

@ -125,6 +125,11 @@
sbit->buffer = 0;
error = clazz->family_load_glyph( family, gindex, manager, &face );
FT_TRACE2(( "ftc_snode_load() got %s from "
"family_load_glyph() err=0x%02x%s\n",
error ? "error" : "ok",
error,
error ? " fallback to BadGlyph" : "" ));
if ( error )
goto BadGlyph;
@ -200,6 +205,8 @@
*asize = 0;
}
FT_TRACE2(( "ftc_snode_load() load glyph for gid=%d, err=0x%02x\n",
gindex, error));
return error;
}
@ -334,6 +341,7 @@
FT_Bool result;
FT_TRACE2(( "ftc_snode_compare() work for gindex=%d\n", gindex ));
if (list_changed)
*list_changed = FALSE;
result = FT_BOOL( gnode->family == gquery->family &&
@ -400,6 +408,8 @@
}
}
FT_TRACE2(( "ftc_snode_compare() returns %s\n",
result ? "TRUE" : "FALSE" ));
return result;
}