summaryrefslogtreecommitdiff
path: root/src/base/ftdbgmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/ftdbgmem.c')
-rw-r--r--src/base/ftdbgmem.c90
1 files changed, 88 insertions, 2 deletions
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index 12fed04bb..16620afa2 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.c
@@ -16,6 +16,8 @@
/***************************************************************************/
+#include <strings.h>
+#include <libgen.h>
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include FT_INTERNAL_DEBUG_H
@@ -25,6 +27,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 +511,47 @@
}
+ static int
+ ft_mem_check_site_alloc_environment( FT_MemSource source,
+ const char* env_var_name )
+ {
+ char *source_basename = basename( (char *)source->file_name );
+ char *c, *c0;
+
+
+ /* environment is unset */
+ c = c0 = getenv( env_var_name );
+ if ( !c )
+ return -1;
+
+ /* basename not found */
+ if ( NULL == ( c = strstr( c, source_basename ) ) )
+ return -1;
+
+ /* found position was substring */
+ if ( c != c0 && *(c-1) != ',' && *(c-1) != '/' )
+ return -1;
+
+ /* invalid syntax without line number */
+ c = c + strlen( source_basename );
+ if ( ':' != *c )
+ return -1;
+
+ /* line number differs */
+ if ( atoi( c + 1 ) != source->line_no )
+ return -1;
+
+ /* invalid syntax without max memory space */
+ if ( NULL == index( c + 1, ':' ) )
+ return -1;
+ c = index( c + 1, ':' );
+ if ( !ft_isdigit( c[1] ) )
+ return -1;
+
+ return atoi( c + 1 );
+ }
+
+
static void
ft_mem_table_set( FT_MemTable table,
FT_Byte* address,
@@ -680,13 +727,52 @@
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 );
+ {
+ 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;
+
+
+ source = ft_mem_table_get_source( table );
+ mem_limit_site_total = ft_mem_check_site_alloc_environment( source, "FT2_ALLOC_TOTAL_MAX_SITE" );
+ mem_limit_site_cur = ft_mem_check_site_alloc_environment( source, "FT2_ALLOC_CUR_MAX_SITE" );
+ if ( mem_limit_site_total >= 0 || mem_limit_site_cur >= 0 )
+ FT_TRACE1(("ft_mem_table_set() invoked by %s:%lu, limit:( "));
+ if ( mem_limit_site_total >= 0 )
+ FT_TRACE1(("%ld =< %ld", source->all_size + size, mem_limit_site_total ));
+ if ( mem_limit_site_total >= 0 && mem_limit_site_cur >= 0 )
+ FT_TRACE1((" && "));
+ if ( mem_limit_site_cur >= 0 )
+ FT_TRACE1(("%ld =< %ld", source->cur_size + size, mem_limit_site_cur ));
+ if ( mem_limit_site_total >= 0 || mem_limit_site_cur >= 0 )
+ FT_TRACE1((" )\n"));
+
+ if ( mem_limit_site_total >= 0 && mem_limit_site_total < ( source->all_size + size ) )
+ exceeds_limit_site_total = TRUE;
+ if ( mem_limit_site_cur >= 0 && mem_limit_site_cur < ( source->cur_size + size ) )
+ exceeds_limit_site_cur = TRUE;
+
+ if ( exceeds_limit_site_total || exceeds_limit_site_cur )
+ {
+ FT_TRACE1(("ft_mem_table_set() returns NULL to %s:%lu, allocation request exceeds %s-limit (%lu > %lu)\n",
+ basename( (char*)source->file_name ), source->line_no,
+ ( exceeds_limit_site_total ? "site-total" : "site-current" ),
+ ( exceeds_limit_site_total ? source->all_size : source->cur_size ) + size,
+ ( exceeds_limit_site_total ? mem_limit_site_total : mem_limit_site_cur )
+ ));
+ return NULL;
+ }
+ }
+
/* return NULL if the maximum number of allocations was reached */
if ( table->bound_count &&
table->alloc_count >= table->alloc_count_max )