diff options
author | wawaka <wawaka@yandex-team.ru> | 2022-02-10 16:47:48 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:47:48 +0300 |
commit | ed524783c88c81047033c5d6e5543db3a2251ad5 (patch) | |
tree | 5c595c0ac1b14fbb70e7e71df44b52e47f850387 /contrib/libs/libxml/xmlmemory.c | |
parent | 11ec0273ab97c87692cd0004865c7f24d14f9902 (diff) | |
download | ydb-ed524783c88c81047033c5d6e5543db3a2251ad5.tar.gz |
Restoring authorship annotation for <wawaka@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/libxml/xmlmemory.c')
-rw-r--r-- | contrib/libs/libxml/xmlmemory.c | 2236 |
1 files changed, 1118 insertions, 1118 deletions
diff --git a/contrib/libs/libxml/xmlmemory.c b/contrib/libs/libxml/xmlmemory.c index 6f16c4b3ca..e161a8e608 100644 --- a/contrib/libs/libxml/xmlmemory.c +++ b/contrib/libs/libxml/xmlmemory.c @@ -1,177 +1,177 @@ -/* - * xmlmemory.c: libxml memory allocator wrapper. - * - * daniel@veillard.com - */ - -#define IN_LIBXML -#include "libxml.h" - -#include <string.h> - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#ifdef HAVE_TIME_H -#include <time.h> -#endif - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#else -#ifdef HAVE_MALLOC_H -#include <malloc.h> -#endif -#endif - -#ifdef HAVE_CTYPE_H -#include <ctype.h> -#endif - -/* #define DEBUG_MEMORY */ - -/** - * MEM_LIST: - * - * keep track of all allocated blocks for error reporting - * Always build the memory list ! - */ -#ifdef DEBUG_MEMORY_LOCATION -#ifndef MEM_LIST -#define MEM_LIST /* keep a list of all the allocated memory blocks */ -#endif -#endif - -#include <libxml/globals.h> /* must come before xmlmemory.h */ -#include <libxml/xmlmemory.h> -#include <libxml/xmlerror.h> -#include <libxml/threads.h> - -static int xmlMemInitialized = 0; -static unsigned long debugMemSize = 0; -static unsigned long debugMemBlocks = 0; -static unsigned long debugMaxMemSize = 0; -static xmlMutexPtr xmlMemMutex = NULL; - -void xmlMallocBreakpoint(void); - -/************************************************************************ - * * - * Macros, variables and associated types * - * * - ************************************************************************/ - -#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED) -#ifdef xmlMalloc -#undef xmlMalloc -#endif -#ifdef xmlRealloc -#undef xmlRealloc -#endif -#ifdef xmlMemStrdup -#undef xmlMemStrdup -#endif -#endif - -/* - * Each of the blocks allocated begin with a header containing informations - */ - -#define MEMTAG 0x5aa5 - -#define MALLOC_TYPE 1 -#define REALLOC_TYPE 2 -#define STRDUP_TYPE 3 -#define MALLOC_ATOMIC_TYPE 4 -#define REALLOC_ATOMIC_TYPE 5 - -typedef struct memnod { - unsigned int mh_tag; - unsigned int mh_type; - unsigned long mh_number; - size_t mh_size; -#ifdef MEM_LIST - struct memnod *mh_next; - struct memnod *mh_prev; -#endif - const char *mh_file; - unsigned int mh_line; -} MEMHDR; - - -#ifdef SUN4 -#define ALIGN_SIZE 16 -#else -#define ALIGN_SIZE sizeof(double) -#endif -#define HDR_SIZE sizeof(MEMHDR) -#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \ - / ALIGN_SIZE ) * ALIGN_SIZE) - +/* + * xmlmemory.c: libxml memory allocator wrapper. + * + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include <string.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_TIME_H +#include <time.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#else +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif +#endif + +#ifdef HAVE_CTYPE_H +#include <ctype.h> +#endif + +/* #define DEBUG_MEMORY */ + +/** + * MEM_LIST: + * + * keep track of all allocated blocks for error reporting + * Always build the memory list ! + */ +#ifdef DEBUG_MEMORY_LOCATION +#ifndef MEM_LIST +#define MEM_LIST /* keep a list of all the allocated memory blocks */ +#endif +#endif + +#include <libxml/globals.h> /* must come before xmlmemory.h */ +#include <libxml/xmlmemory.h> +#include <libxml/xmlerror.h> +#include <libxml/threads.h> + +static int xmlMemInitialized = 0; +static unsigned long debugMemSize = 0; +static unsigned long debugMemBlocks = 0; +static unsigned long debugMaxMemSize = 0; +static xmlMutexPtr xmlMemMutex = NULL; + +void xmlMallocBreakpoint(void); + +/************************************************************************ + * * + * Macros, variables and associated types * + * * + ************************************************************************/ + +#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED) +#ifdef xmlMalloc +#undef xmlMalloc +#endif +#ifdef xmlRealloc +#undef xmlRealloc +#endif +#ifdef xmlMemStrdup +#undef xmlMemStrdup +#endif +#endif + +/* + * Each of the blocks allocated begin with a header containing informations + */ + +#define MEMTAG 0x5aa5 + +#define MALLOC_TYPE 1 +#define REALLOC_TYPE 2 +#define STRDUP_TYPE 3 +#define MALLOC_ATOMIC_TYPE 4 +#define REALLOC_ATOMIC_TYPE 5 + +typedef struct memnod { + unsigned int mh_tag; + unsigned int mh_type; + unsigned long mh_number; + size_t mh_size; +#ifdef MEM_LIST + struct memnod *mh_next; + struct memnod *mh_prev; +#endif + const char *mh_file; + unsigned int mh_line; +} MEMHDR; + + +#ifdef SUN4 +#define ALIGN_SIZE 16 +#else +#define ALIGN_SIZE sizeof(double) +#endif +#define HDR_SIZE sizeof(MEMHDR) +#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \ + / ALIGN_SIZE ) * ALIGN_SIZE) + #define MAX_SIZE_T ((size_t)-1) - + #define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE)) -#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE)) - - -static unsigned int block=0; -static unsigned int xmlMemStopAtBlock = 0; -static void *xmlMemTraceBlockAt = NULL; -#ifdef MEM_LIST -static MEMHDR *memlist = NULL; -#endif - -static void debugmem_tag_error(void *addr); -#ifdef MEM_LIST -static void debugmem_list_add(MEMHDR *); -static void debugmem_list_delete(MEMHDR *); -#endif -#define Mem_Tag_Err(a) debugmem_tag_error(a); - -#ifndef TEST_POINT -#define TEST_POINT -#endif - -/** - * xmlMallocBreakpoint: - * - * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block - * number reaches the specified value this function is called. One need to add a breakpoint - * to it to get the context in which the given block is allocated. - */ - -void -xmlMallocBreakpoint(void) { - xmlGenericError(xmlGenericErrorContext, - "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock); -} - -/** - * xmlMallocLoc: - * @size: an int specifying the size in byte to allocate. - * @file: the file name or NULL - * @line: the line number - * - * a malloc() equivalent, with logging of the allocation info. - * - * Returns a pointer to the allocated area or NULL in case of lack of memory. - */ - -void * -xmlMallocLoc(size_t size, const char * file, int line) -{ - MEMHDR *p; - void *ret; - - if (!xmlMemInitialized) xmlInitMemory(); -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Malloc(%d)\n",size); -#endif - - TEST_POINT - +#define HDR_2_CLIENT(a) ((void *) (((char *) (a)) + RESERVE_SIZE)) + + +static unsigned int block=0; +static unsigned int xmlMemStopAtBlock = 0; +static void *xmlMemTraceBlockAt = NULL; +#ifdef MEM_LIST +static MEMHDR *memlist = NULL; +#endif + +static void debugmem_tag_error(void *addr); +#ifdef MEM_LIST +static void debugmem_list_add(MEMHDR *); +static void debugmem_list_delete(MEMHDR *); +#endif +#define Mem_Tag_Err(a) debugmem_tag_error(a); + +#ifndef TEST_POINT +#define TEST_POINT +#endif + +/** + * xmlMallocBreakpoint: + * + * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block + * number reaches the specified value this function is called. One need to add a breakpoint + * to it to get the context in which the given block is allocated. + */ + +void +xmlMallocBreakpoint(void) { + xmlGenericError(xmlGenericErrorContext, + "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock); +} + +/** + * xmlMallocLoc: + * @size: an int specifying the size in byte to allocate. + * @file: the file name or NULL + * @line: the line number + * + * a malloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlMallocLoc(size_t size, const char * file, int line) +{ + MEMHDR *p; + void *ret; + + if (!xmlMemInitialized) xmlInitMemory(); +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Malloc(%d)\n",size); +#endif + + TEST_POINT + if (size > (MAX_SIZE_T - RESERVE_SIZE)) { xmlGenericError(xmlGenericErrorContext, "xmlMallocLoc : Unsigned overflow\n"); @@ -179,75 +179,75 @@ xmlMallocLoc(size_t size, const char * file, int line) return(NULL); } - p = (MEMHDR *) malloc(RESERVE_SIZE+size); - - if (!p) { - xmlGenericError(xmlGenericErrorContext, - "xmlMallocLoc : Out of free space\n"); - xmlMemoryDump(); - return(NULL); - } - p->mh_tag = MEMTAG; - p->mh_size = size; - p->mh_type = MALLOC_TYPE; - p->mh_file = file; - p->mh_line = line; - xmlMutexLock(xmlMemMutex); - p->mh_number = ++block; - debugMemSize += size; - debugMemBlocks++; - if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; -#ifdef MEM_LIST - debugmem_list_add(p); -#endif - xmlMutexUnlock(xmlMemMutex); - -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Malloc(%d) Ok\n",size); -#endif - - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); - - ret = HDR_2_CLIENT(p); - - if (xmlMemTraceBlockAt == ret) { - xmlGenericError(xmlGenericErrorContext, - "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt, - (long unsigned)size); - xmlMallocBreakpoint(); - } - - TEST_POINT - - return(ret); -} - -/** - * xmlMallocAtomicLoc: + p = (MEMHDR *) malloc(RESERVE_SIZE+size); + + if (!p) { + xmlGenericError(xmlGenericErrorContext, + "xmlMallocLoc : Out of free space\n"); + xmlMemoryDump(); + return(NULL); + } + p->mh_tag = MEMTAG; + p->mh_size = size; + p->mh_type = MALLOC_TYPE; + p->mh_file = file; + p->mh_line = line; + xmlMutexLock(xmlMemMutex); + p->mh_number = ++block; + debugMemSize += size; + debugMemBlocks++; + if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; +#ifdef MEM_LIST + debugmem_list_add(p); +#endif + xmlMutexUnlock(xmlMemMutex); + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Malloc(%d) Ok\n",size); +#endif + + if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); + + ret = HDR_2_CLIENT(p); + + if (xmlMemTraceBlockAt == ret) { + xmlGenericError(xmlGenericErrorContext, + "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt, + (long unsigned)size); + xmlMallocBreakpoint(); + } + + TEST_POINT + + return(ret); +} + +/** + * xmlMallocAtomicLoc: * @size: an unsigned int specifying the size in byte to allocate. - * @file: the file name or NULL - * @line: the line number - * - * a malloc() equivalent, with logging of the allocation info. - * - * Returns a pointer to the allocated area or NULL in case of lack of memory. - */ - -void * -xmlMallocAtomicLoc(size_t size, const char * file, int line) -{ - MEMHDR *p; - void *ret; - - if (!xmlMemInitialized) xmlInitMemory(); -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Malloc(%d)\n",size); -#endif - - TEST_POINT - + * @file: the file name or NULL + * @line: the line number + * + * a malloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlMallocAtomicLoc(size_t size, const char * file, int line) +{ + MEMHDR *p; + void *ret; + + if (!xmlMemInitialized) xmlInitMemory(); +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Malloc(%d)\n",size); +#endif + + TEST_POINT + if (size > (MAX_SIZE_T - RESERVE_SIZE)) { xmlGenericError(xmlGenericErrorContext, "xmlMallocAtomicLoc : Unsigned overflow\n"); @@ -255,110 +255,110 @@ xmlMallocAtomicLoc(size_t size, const char * file, int line) return(NULL); } - p = (MEMHDR *) malloc(RESERVE_SIZE+size); - - if (!p) { - xmlGenericError(xmlGenericErrorContext, + p = (MEMHDR *) malloc(RESERVE_SIZE+size); + + if (!p) { + xmlGenericError(xmlGenericErrorContext, "xmlMallocAtomicLoc : Out of free space\n"); - xmlMemoryDump(); - return(NULL); - } - p->mh_tag = MEMTAG; - p->mh_size = size; - p->mh_type = MALLOC_ATOMIC_TYPE; - p->mh_file = file; - p->mh_line = line; - xmlMutexLock(xmlMemMutex); - p->mh_number = ++block; - debugMemSize += size; - debugMemBlocks++; - if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; -#ifdef MEM_LIST - debugmem_list_add(p); -#endif - xmlMutexUnlock(xmlMemMutex); - -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Malloc(%d) Ok\n",size); -#endif - - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); - - ret = HDR_2_CLIENT(p); - - if (xmlMemTraceBlockAt == ret) { - xmlGenericError(xmlGenericErrorContext, - "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt, - (long unsigned)size); - xmlMallocBreakpoint(); - } - - TEST_POINT - - return(ret); -} -/** - * xmlMemMalloc: - * @size: an int specifying the size in byte to allocate. - * - * a malloc() equivalent, with logging of the allocation info. - * - * Returns a pointer to the allocated area or NULL in case of lack of memory. - */ - -void * -xmlMemMalloc(size_t size) -{ - return(xmlMallocLoc(size, "none", 0)); -} - -/** - * xmlReallocLoc: - * @ptr: the initial memory block pointer - * @size: an int specifying the size in byte to allocate. - * @file: the file name or NULL - * @line: the line number - * - * a realloc() equivalent, with logging of the allocation info. - * - * Returns a pointer to the allocated area or NULL in case of lack of memory. - */ - -void * -xmlReallocLoc(void *ptr,size_t size, const char * file, int line) -{ - MEMHDR *p, *tmp; - unsigned long number; -#ifdef DEBUG_MEMORY - size_t oldsize; -#endif - - if (ptr == NULL) - return(xmlMallocLoc(size, file, line)); - - if (!xmlMemInitialized) xmlInitMemory(); - TEST_POINT - - p = CLIENT_2_HDR(ptr); - number = p->mh_number; - if (xmlMemStopAtBlock == number) xmlMallocBreakpoint(); - if (p->mh_tag != MEMTAG) { - Mem_Tag_Err(p); - goto error; - } - p->mh_tag = ~MEMTAG; - xmlMutexLock(xmlMemMutex); - debugMemSize -= p->mh_size; - debugMemBlocks--; -#ifdef DEBUG_MEMORY - oldsize = p->mh_size; -#endif -#ifdef MEM_LIST - debugmem_list_delete(p); -#endif - xmlMutexUnlock(xmlMemMutex); - + xmlMemoryDump(); + return(NULL); + } + p->mh_tag = MEMTAG; + p->mh_size = size; + p->mh_type = MALLOC_ATOMIC_TYPE; + p->mh_file = file; + p->mh_line = line; + xmlMutexLock(xmlMemMutex); + p->mh_number = ++block; + debugMemSize += size; + debugMemBlocks++; + if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; +#ifdef MEM_LIST + debugmem_list_add(p); +#endif + xmlMutexUnlock(xmlMemMutex); + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Malloc(%d) Ok\n",size); +#endif + + if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); + + ret = HDR_2_CLIENT(p); + + if (xmlMemTraceBlockAt == ret) { + xmlGenericError(xmlGenericErrorContext, + "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt, + (long unsigned)size); + xmlMallocBreakpoint(); + } + + TEST_POINT + + return(ret); +} +/** + * xmlMemMalloc: + * @size: an int specifying the size in byte to allocate. + * + * a malloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlMemMalloc(size_t size) +{ + return(xmlMallocLoc(size, "none", 0)); +} + +/** + * xmlReallocLoc: + * @ptr: the initial memory block pointer + * @size: an int specifying the size in byte to allocate. + * @file: the file name or NULL + * @line: the line number + * + * a realloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlReallocLoc(void *ptr,size_t size, const char * file, int line) +{ + MEMHDR *p, *tmp; + unsigned long number; +#ifdef DEBUG_MEMORY + size_t oldsize; +#endif + + if (ptr == NULL) + return(xmlMallocLoc(size, file, line)); + + if (!xmlMemInitialized) xmlInitMemory(); + TEST_POINT + + p = CLIENT_2_HDR(ptr); + number = p->mh_number; + if (xmlMemStopAtBlock == number) xmlMallocBreakpoint(); + if (p->mh_tag != MEMTAG) { + Mem_Tag_Err(p); + goto error; + } + p->mh_tag = ~MEMTAG; + xmlMutexLock(xmlMemMutex); + debugMemSize -= p->mh_size; + debugMemBlocks--; +#ifdef DEBUG_MEMORY + oldsize = p->mh_size; +#endif +#ifdef MEM_LIST + debugmem_list_delete(p); +#endif + xmlMutexUnlock(xmlMemMutex); + if (size > (MAX_SIZE_T - RESERVE_SIZE)) { xmlGenericError(xmlGenericErrorContext, "xmlReallocLoc : Unsigned overflow\n"); @@ -366,153 +366,153 @@ xmlReallocLoc(void *ptr,size_t size, const char * file, int line) return(NULL); } - tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size); - if (!tmp) { - free(p); - goto error; - } - p = tmp; - if (xmlMemTraceBlockAt == ptr) { - xmlGenericError(xmlGenericErrorContext, - "%p : Realloced(%lu -> %lu) Ok\n", - xmlMemTraceBlockAt, (long unsigned)p->mh_size, - (long unsigned)size); - xmlMallocBreakpoint(); - } - p->mh_tag = MEMTAG; - p->mh_number = number; - p->mh_type = REALLOC_TYPE; - p->mh_size = size; - p->mh_file = file; - p->mh_line = line; - xmlMutexLock(xmlMemMutex); - debugMemSize += size; - debugMemBlocks++; - if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; -#ifdef MEM_LIST - debugmem_list_add(p); -#endif - xmlMutexUnlock(xmlMemMutex); - - TEST_POINT - -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Realloced(%d to %d) Ok\n", oldsize, size); -#endif - return(HDR_2_CLIENT(p)); - -error: - return(NULL); -} - -/** - * xmlMemRealloc: - * @ptr: the initial memory block pointer - * @size: an int specifying the size in byte to allocate. - * - * a realloc() equivalent, with logging of the allocation info. - * - * Returns a pointer to the allocated area or NULL in case of lack of memory. - */ - -void * -xmlMemRealloc(void *ptr,size_t size) { - return(xmlReallocLoc(ptr, size, "none", 0)); -} - -/** - * xmlMemFree: - * @ptr: the memory block pointer - * - * a free() equivalent, with error checking. - */ -void -xmlMemFree(void *ptr) -{ - MEMHDR *p; - char *target; -#ifdef DEBUG_MEMORY - size_t size; -#endif - - if (ptr == NULL) - return; - - if (ptr == (void *) -1) { - xmlGenericError(xmlGenericErrorContext, - "trying to free pointer from freed area\n"); - goto error; - } - - if (xmlMemTraceBlockAt == ptr) { - xmlGenericError(xmlGenericErrorContext, - "%p : Freed()\n", xmlMemTraceBlockAt); - xmlMallocBreakpoint(); - } - - TEST_POINT - - target = (char *) ptr; - - p = CLIENT_2_HDR(ptr); - if (p->mh_tag != MEMTAG) { - Mem_Tag_Err(p); - goto error; - } - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); - p->mh_tag = ~MEMTAG; - memset(target, -1, p->mh_size); - xmlMutexLock(xmlMemMutex); - debugMemSize -= p->mh_size; - debugMemBlocks--; -#ifdef DEBUG_MEMORY - size = p->mh_size; -#endif -#ifdef MEM_LIST - debugmem_list_delete(p); -#endif - xmlMutexUnlock(xmlMemMutex); - - free(p); - - TEST_POINT - -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "Freed(%d) Ok\n", size); -#endif - - return; - -error: - xmlGenericError(xmlGenericErrorContext, + tmp = (MEMHDR *) realloc(p,RESERVE_SIZE+size); + if (!tmp) { + free(p); + goto error; + } + p = tmp; + if (xmlMemTraceBlockAt == ptr) { + xmlGenericError(xmlGenericErrorContext, + "%p : Realloced(%lu -> %lu) Ok\n", + xmlMemTraceBlockAt, (long unsigned)p->mh_size, + (long unsigned)size); + xmlMallocBreakpoint(); + } + p->mh_tag = MEMTAG; + p->mh_number = number; + p->mh_type = REALLOC_TYPE; + p->mh_size = size; + p->mh_file = file; + p->mh_line = line; + xmlMutexLock(xmlMemMutex); + debugMemSize += size; + debugMemBlocks++; + if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; +#ifdef MEM_LIST + debugmem_list_add(p); +#endif + xmlMutexUnlock(xmlMemMutex); + + TEST_POINT + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Realloced(%d to %d) Ok\n", oldsize, size); +#endif + return(HDR_2_CLIENT(p)); + +error: + return(NULL); +} + +/** + * xmlMemRealloc: + * @ptr: the initial memory block pointer + * @size: an int specifying the size in byte to allocate. + * + * a realloc() equivalent, with logging of the allocation info. + * + * Returns a pointer to the allocated area or NULL in case of lack of memory. + */ + +void * +xmlMemRealloc(void *ptr,size_t size) { + return(xmlReallocLoc(ptr, size, "none", 0)); +} + +/** + * xmlMemFree: + * @ptr: the memory block pointer + * + * a free() equivalent, with error checking. + */ +void +xmlMemFree(void *ptr) +{ + MEMHDR *p; + char *target; +#ifdef DEBUG_MEMORY + size_t size; +#endif + + if (ptr == NULL) + return; + + if (ptr == (void *) -1) { + xmlGenericError(xmlGenericErrorContext, + "trying to free pointer from freed area\n"); + goto error; + } + + if (xmlMemTraceBlockAt == ptr) { + xmlGenericError(xmlGenericErrorContext, + "%p : Freed()\n", xmlMemTraceBlockAt); + xmlMallocBreakpoint(); + } + + TEST_POINT + + target = (char *) ptr; + + p = CLIENT_2_HDR(ptr); + if (p->mh_tag != MEMTAG) { + Mem_Tag_Err(p); + goto error; + } + if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); + p->mh_tag = ~MEMTAG; + memset(target, -1, p->mh_size); + xmlMutexLock(xmlMemMutex); + debugMemSize -= p->mh_size; + debugMemBlocks--; +#ifdef DEBUG_MEMORY + size = p->mh_size; +#endif +#ifdef MEM_LIST + debugmem_list_delete(p); +#endif + xmlMutexUnlock(xmlMemMutex); + + free(p); + + TEST_POINT + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "Freed(%d) Ok\n", size); +#endif + + return; + +error: + xmlGenericError(xmlGenericErrorContext, "xmlMemFree(%p) error\n", ptr); - xmlMallocBreakpoint(); - return; -} - -/** - * xmlMemStrdupLoc: - * @str: the initial string pointer - * @file: the file name or NULL - * @line: the line number - * - * a strdup() equivalent, with logging of the allocation info. - * - * Returns a pointer to the new string or NULL if allocation error occurred. - */ - -char * -xmlMemStrdupLoc(const char *str, const char *file, int line) -{ - char *s; - size_t size = strlen(str) + 1; - MEMHDR *p; - - if (!xmlMemInitialized) xmlInitMemory(); - TEST_POINT - + xmlMallocBreakpoint(); + return; +} + +/** + * xmlMemStrdupLoc: + * @str: the initial string pointer + * @file: the file name or NULL + * @line: the line number + * + * a strdup() equivalent, with logging of the allocation info. + * + * Returns a pointer to the new string or NULL if allocation error occurred. + */ + +char * +xmlMemStrdupLoc(const char *str, const char *file, int line) +{ + char *s; + size_t size = strlen(str) + 1; + MEMHDR *p; + + if (!xmlMemInitialized) xmlInitMemory(); + TEST_POINT + if (size > (MAX_SIZE_T - RESERVE_SIZE)) { xmlGenericError(xmlGenericErrorContext, "xmlMemStrdupLoc : Unsigned overflow\n"); @@ -520,644 +520,644 @@ xmlMemStrdupLoc(const char *str, const char *file, int line) return(NULL); } - p = (MEMHDR *) malloc(RESERVE_SIZE+size); - if (!p) { - goto error; - } - p->mh_tag = MEMTAG; - p->mh_size = size; - p->mh_type = STRDUP_TYPE; - p->mh_file = file; - p->mh_line = line; - xmlMutexLock(xmlMemMutex); - p->mh_number = ++block; - debugMemSize += size; - debugMemBlocks++; - if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; -#ifdef MEM_LIST - debugmem_list_add(p); -#endif - xmlMutexUnlock(xmlMemMutex); - - s = (char *) HDR_2_CLIENT(p); - - if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); - - strcpy(s,str); - - TEST_POINT - - if (xmlMemTraceBlockAt == s) { - xmlGenericError(xmlGenericErrorContext, - "%p : Strdup() Ok\n", xmlMemTraceBlockAt); - xmlMallocBreakpoint(); - } - - return(s); - -error: - return(NULL); -} - -/** - * xmlMemoryStrdup: - * @str: the initial string pointer - * - * a strdup() equivalent, with logging of the allocation info. - * - * Returns a pointer to the new string or NULL if allocation error occurred. - */ - -char * -xmlMemoryStrdup(const char *str) { - return(xmlMemStrdupLoc(str, "none", 0)); -} - -/** - * xmlMemUsed: - * - * Provides the amount of memory currently allocated - * - * Returns an int representing the amount of memory allocated. - */ - -int -xmlMemUsed(void) { + p = (MEMHDR *) malloc(RESERVE_SIZE+size); + if (!p) { + goto error; + } + p->mh_tag = MEMTAG; + p->mh_size = size; + p->mh_type = STRDUP_TYPE; + p->mh_file = file; + p->mh_line = line; + xmlMutexLock(xmlMemMutex); + p->mh_number = ++block; + debugMemSize += size; + debugMemBlocks++; + if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize; +#ifdef MEM_LIST + debugmem_list_add(p); +#endif + xmlMutexUnlock(xmlMemMutex); + + s = (char *) HDR_2_CLIENT(p); + + if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint(); + + strcpy(s,str); + + TEST_POINT + + if (xmlMemTraceBlockAt == s) { + xmlGenericError(xmlGenericErrorContext, + "%p : Strdup() Ok\n", xmlMemTraceBlockAt); + xmlMallocBreakpoint(); + } + + return(s); + +error: + return(NULL); +} + +/** + * xmlMemoryStrdup: + * @str: the initial string pointer + * + * a strdup() equivalent, with logging of the allocation info. + * + * Returns a pointer to the new string or NULL if allocation error occurred. + */ + +char * +xmlMemoryStrdup(const char *str) { + return(xmlMemStrdupLoc(str, "none", 0)); +} + +/** + * xmlMemUsed: + * + * Provides the amount of memory currently allocated + * + * Returns an int representing the amount of memory allocated. + */ + +int +xmlMemUsed(void) { int res; xmlMutexLock(xmlMemMutex); res = debugMemSize; xmlMutexUnlock(xmlMemMutex); return(res); -} - -/** - * xmlMemBlocks: - * - * Provides the number of memory areas currently allocated - * - * Returns an int representing the number of blocks - */ - -int -xmlMemBlocks(void) { +} + +/** + * xmlMemBlocks: + * + * Provides the number of memory areas currently allocated + * + * Returns an int representing the number of blocks + */ + +int +xmlMemBlocks(void) { int res; xmlMutexLock(xmlMemMutex); res = debugMemBlocks; xmlMutexUnlock(xmlMemMutex); return(res); -} - -#ifdef MEM_LIST -/** - * xmlMemContentShow: - * @fp: a FILE descriptor used as the output file - * @p: a memory block header - * - * tries to show some content from the memory block - */ - -static void -xmlMemContentShow(FILE *fp, MEMHDR *p) -{ - int i,j,k,len; - const char *buf; - - if (p == NULL) { - fprintf(fp, " NULL"); - return; - } - len = p->mh_size; - buf = (const char *) HDR_2_CLIENT(p); - - for (i = 0;i < len;i++) { - if (buf[i] == 0) break; - if (!isprint((unsigned char) buf[i])) break; - } - if ((i < 4) && ((buf[i] != 0) || (i == 0))) { - if (len >= 4) { - MEMHDR *q; - void *cur; - - for (j = 0;(j < len -3) && (j < 40);j += 4) { - cur = *((void **) &buf[j]); - q = CLIENT_2_HDR(cur); - p = memlist; - k = 0; - while (p != NULL) { - if (p == q) break; - p = p->mh_next; - if (k++ > 100) break; - } - if ((p != NULL) && (p == q)) { - fprintf(fp, " pointer to #%lu at index %d", - p->mh_number, j); - return; - } - } - } - } else if ((i == 0) && (buf[i] == 0)) { - fprintf(fp," null"); - } else { - if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf); - else { - fprintf(fp," ["); - for (j = 0;j < i;j++) - fprintf(fp,"%c", buf[j]); - fprintf(fp,"]"); - } - } -} -#endif - -/** - * xmlMemDisplayLast: - * @fp: a FILE descriptor used as the output file, if NULL, the result is - * written to the file .memorylist - * @nbBytes: the amount of memory to dump - * - * the last nbBytes of memory allocated and not freed, useful for dumping - * the memory left allocated between two places at runtime. - */ - -void -xmlMemDisplayLast(FILE *fp, long nbBytes) -{ -#ifdef MEM_LIST - MEMHDR *p; - unsigned idx; - int nb = 0; -#endif - FILE *old_fp = fp; - - if (nbBytes <= 0) - return; - - if (fp == NULL) { - fp = fopen(".memorylist", "w"); - if (fp == NULL) - return; - } - -#ifdef MEM_LIST - fprintf(fp," Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n", - nbBytes, debugMemSize, debugMaxMemSize); - fprintf(fp,"BLOCK NUMBER SIZE TYPE\n"); - idx = 0; - xmlMutexLock(xmlMemMutex); - p = memlist; - while ((p) && (nbBytes > 0)) { - fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number, - (unsigned long)p->mh_size); - switch (p->mh_type) { - case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; - case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; - case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; - case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; - case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; - default: - fprintf(fp,"Unknown memory block, may be corrupted"); - xmlMutexUnlock(xmlMemMutex); - if (old_fp == NULL) - fclose(fp); - return; - } - if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); - if (p->mh_tag != MEMTAG) - fprintf(fp," INVALID"); - nb++; - if (nb < 100) - xmlMemContentShow(fp, p); - else - fprintf(fp," skip"); - - fprintf(fp,"\n"); - nbBytes -= (unsigned long)p->mh_size; - p = p->mh_next; - } - xmlMutexUnlock(xmlMemMutex); -#else - fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n"); -#endif - if (old_fp == NULL) - fclose(fp); -} - -/** - * xmlMemDisplay: - * @fp: a FILE descriptor used as the output file, if NULL, the result is - * written to the file .memorylist - * - * show in-extenso the memory blocks allocated - */ - -void -xmlMemDisplay(FILE *fp) -{ -#ifdef MEM_LIST - MEMHDR *p; - unsigned idx; - int nb = 0; -#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME) - time_t currentTime; - char buf[500]; - struct tm * tstruct; -#endif -#endif - FILE *old_fp = fp; - - if (fp == NULL) { - fp = fopen(".memorylist", "w"); - if (fp == NULL) - return; - } - -#ifdef MEM_LIST -#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME) - currentTime = time(NULL); - tstruct = localtime(¤tTime); - strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct); - fprintf(fp," %s\n\n", buf); -#endif - - - fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n", - debugMemSize, debugMaxMemSize); - fprintf(fp,"BLOCK NUMBER SIZE TYPE\n"); - idx = 0; - xmlMutexLock(xmlMemMutex); - p = memlist; - while (p) { - fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number, - (unsigned long)p->mh_size); - switch (p->mh_type) { - case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; - case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; - case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; - case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; - case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; - default: - fprintf(fp,"Unknown memory block, may be corrupted"); - xmlMutexUnlock(xmlMemMutex); - if (old_fp == NULL) - fclose(fp); - return; - } - if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); - if (p->mh_tag != MEMTAG) - fprintf(fp," INVALID"); - nb++; - if (nb < 100) - xmlMemContentShow(fp, p); - else - fprintf(fp," skip"); - - fprintf(fp,"\n"); - p = p->mh_next; - } - xmlMutexUnlock(xmlMemMutex); -#else - fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n"); -#endif - if (old_fp == NULL) - fclose(fp); -} - -#ifdef MEM_LIST - -static void debugmem_list_add(MEMHDR *p) -{ - p->mh_next = memlist; - p->mh_prev = NULL; - if (memlist) memlist->mh_prev = p; - memlist = p; -#ifdef MEM_LIST_DEBUG - if (stderr) - Mem_Display(stderr); -#endif -} - -static void debugmem_list_delete(MEMHDR *p) -{ - if (p->mh_next) - p->mh_next->mh_prev = p->mh_prev; - if (p->mh_prev) - p->mh_prev->mh_next = p->mh_next; - else memlist = p->mh_next; -#ifdef MEM_LIST_DEBUG - if (stderr) - Mem_Display(stderr); -#endif -} - -#endif - -/* - * debugmem_tag_error: - * - * internal error function. - */ - -static void debugmem_tag_error(void *p) -{ - xmlGenericError(xmlGenericErrorContext, - "Memory tag error occurs :%p \n\t bye\n", p); -#ifdef MEM_LIST - if (stderr) - xmlMemDisplay(stderr); -#endif -} - -#ifdef MEM_LIST -static FILE *xmlMemoryDumpFile = NULL; -#endif - -/** - * xmlMemShow: - * @fp: a FILE descriptor used as the output file - * @nr: number of entries to dump - * - * show a show display of the memory allocated, and dump - * the @nr last allocated areas which were not freed - */ - -void -xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED) -{ -#ifdef MEM_LIST - MEMHDR *p; -#endif - - if (fp != NULL) - fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n", - debugMemSize, debugMaxMemSize); -#ifdef MEM_LIST - xmlMutexLock(xmlMemMutex); - if (nr > 0) { - fprintf(fp,"NUMBER SIZE TYPE WHERE\n"); - p = memlist; - while ((p) && nr > 0) { - fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size); - switch (p->mh_type) { - case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; - case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; - case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; - case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; - case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; - default:fprintf(fp," ??? in ");break; - } - if (p->mh_file != NULL) - fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); - if (p->mh_tag != MEMTAG) - fprintf(fp," INVALID"); - xmlMemContentShow(fp, p); - fprintf(fp,"\n"); - nr--; - p = p->mh_next; - } - } - xmlMutexUnlock(xmlMemMutex); -#endif /* MEM_LIST */ -} - -/** - * xmlMemoryDump: - * - * Dump in-extenso the memory blocks allocated to the file .memorylist - */ - -void -xmlMemoryDump(void) -{ -#ifdef MEM_LIST - FILE *dump; - - if (debugMaxMemSize == 0) - return; - dump = fopen(".memdump", "w"); - if (dump == NULL) - xmlMemoryDumpFile = stderr; - else xmlMemoryDumpFile = dump; - - xmlMemDisplay(xmlMemoryDumpFile); - - if (dump != NULL) fclose(dump); -#endif /* MEM_LIST */ -} - - -/**************************************************************** - * * - * Initialization Routines * - * * - ****************************************************************/ - -/** - * xmlInitMemory: - * - * Initialize the memory layer. - * - * Returns 0 on success - */ -int -xmlInitMemory(void) -{ -#ifdef HAVE_STDLIB_H - char *breakpoint; -#endif -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlInitMemory()\n"); -#endif - /* - This is really not good code (see Bug 130419). Suggestions for - improvement will be welcome! - */ - if (xmlMemInitialized) return(-1); - xmlMemInitialized = 1; - xmlMemMutex = xmlNewMutex(); - -#ifdef HAVE_STDLIB_H - breakpoint = getenv("XML_MEM_BREAKPOINT"); - if (breakpoint != NULL) { - sscanf(breakpoint, "%ud", &xmlMemStopAtBlock); - } -#endif -#ifdef HAVE_STDLIB_H - breakpoint = getenv("XML_MEM_TRACE"); - if (breakpoint != NULL) { - sscanf(breakpoint, "%p", &xmlMemTraceBlockAt); - } -#endif - -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlInitMemory() Ok\n"); -#endif - return(0); -} - -/** - * xmlCleanupMemory: - * - * Free up all the memory allocated by the library for its own - * use. This should not be called by user level code. - */ -void -xmlCleanupMemory(void) { -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlCleanupMemory()\n"); -#endif - if (xmlMemInitialized == 0) - return; - - xmlFreeMutex(xmlMemMutex); - xmlMemMutex = NULL; - xmlMemInitialized = 0; -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlCleanupMemory() Ok\n"); -#endif -} - -/** - * xmlMemSetup: - * @freeFunc: the free() function to use - * @mallocFunc: the malloc() function to use - * @reallocFunc: the realloc() function to use - * @strdupFunc: the strdup() function to use - * - * Override the default memory access functions with a new set - * This has to be called before any other libxml routines ! - * - * Should this be blocked if there was already some allocations - * done ? - * - * Returns 0 on success - */ -int -xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, - xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) { -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlMemSetup()\n"); -#endif - if (freeFunc == NULL) - return(-1); - if (mallocFunc == NULL) - return(-1); - if (reallocFunc == NULL) - return(-1); - if (strdupFunc == NULL) - return(-1); - xmlFree = freeFunc; - xmlMalloc = mallocFunc; - xmlMallocAtomic = mallocFunc; - xmlRealloc = reallocFunc; - xmlMemStrdup = strdupFunc; -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlMemSetup() Ok\n"); -#endif - return(0); -} - -/** - * xmlMemGet: - * @freeFunc: place to save the free() function in use - * @mallocFunc: place to save the malloc() function in use - * @reallocFunc: place to save the realloc() function in use - * @strdupFunc: place to save the strdup() function in use - * - * Provides the memory access functions set currently in use - * - * Returns 0 on success - */ -int -xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc, - xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) { - if (freeFunc != NULL) *freeFunc = xmlFree; - if (mallocFunc != NULL) *mallocFunc = xmlMalloc; - if (reallocFunc != NULL) *reallocFunc = xmlRealloc; - if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup; - return(0); -} - -/** - * xmlGcMemSetup: - * @freeFunc: the free() function to use - * @mallocFunc: the malloc() function to use - * @mallocAtomicFunc: the malloc() function to use for atomic allocations - * @reallocFunc: the realloc() function to use - * @strdupFunc: the strdup() function to use - * - * Override the default memory access functions with a new set - * This has to be called before any other libxml routines ! - * The mallocAtomicFunc is specialized for atomic block - * allocations (i.e. of areas useful for garbage collected memory allocators - * - * Should this be blocked if there was already some allocations - * done ? - * - * Returns 0 on success - */ -int -xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, - xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc, - xmlStrdupFunc strdupFunc) { -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlGcMemSetup()\n"); -#endif - if (freeFunc == NULL) - return(-1); - if (mallocFunc == NULL) - return(-1); - if (mallocAtomicFunc == NULL) - return(-1); - if (reallocFunc == NULL) - return(-1); - if (strdupFunc == NULL) - return(-1); - xmlFree = freeFunc; - xmlMalloc = mallocFunc; - xmlMallocAtomic = mallocAtomicFunc; - xmlRealloc = reallocFunc; - xmlMemStrdup = strdupFunc; -#ifdef DEBUG_MEMORY - xmlGenericError(xmlGenericErrorContext, - "xmlGcMemSetup() Ok\n"); -#endif - return(0); -} - -/** - * xmlGcMemGet: - * @freeFunc: place to save the free() function in use - * @mallocFunc: place to save the malloc() function in use - * @mallocAtomicFunc: place to save the atomic malloc() function in use - * @reallocFunc: place to save the realloc() function in use - * @strdupFunc: place to save the strdup() function in use - * - * Provides the memory access functions set currently in use - * The mallocAtomicFunc is specialized for atomic block - * allocations (i.e. of areas useful for garbage collected memory allocators - * - * Returns 0 on success - */ -int -xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc, - xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc, - xmlStrdupFunc *strdupFunc) { - if (freeFunc != NULL) *freeFunc = xmlFree; - if (mallocFunc != NULL) *mallocFunc = xmlMalloc; - if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic; - if (reallocFunc != NULL) *reallocFunc = xmlRealloc; - if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup; - return(0); -} - -#define bottom_xmlmemory -#include "elfgcchack.h" +} + +#ifdef MEM_LIST +/** + * xmlMemContentShow: + * @fp: a FILE descriptor used as the output file + * @p: a memory block header + * + * tries to show some content from the memory block + */ + +static void +xmlMemContentShow(FILE *fp, MEMHDR *p) +{ + int i,j,k,len; + const char *buf; + + if (p == NULL) { + fprintf(fp, " NULL"); + return; + } + len = p->mh_size; + buf = (const char *) HDR_2_CLIENT(p); + + for (i = 0;i < len;i++) { + if (buf[i] == 0) break; + if (!isprint((unsigned char) buf[i])) break; + } + if ((i < 4) && ((buf[i] != 0) || (i == 0))) { + if (len >= 4) { + MEMHDR *q; + void *cur; + + for (j = 0;(j < len -3) && (j < 40);j += 4) { + cur = *((void **) &buf[j]); + q = CLIENT_2_HDR(cur); + p = memlist; + k = 0; + while (p != NULL) { + if (p == q) break; + p = p->mh_next; + if (k++ > 100) break; + } + if ((p != NULL) && (p == q)) { + fprintf(fp, " pointer to #%lu at index %d", + p->mh_number, j); + return; + } + } + } + } else if ((i == 0) && (buf[i] == 0)) { + fprintf(fp," null"); + } else { + if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf); + else { + fprintf(fp," ["); + for (j = 0;j < i;j++) + fprintf(fp,"%c", buf[j]); + fprintf(fp,"]"); + } + } +} +#endif + +/** + * xmlMemDisplayLast: + * @fp: a FILE descriptor used as the output file, if NULL, the result is + * written to the file .memorylist + * @nbBytes: the amount of memory to dump + * + * the last nbBytes of memory allocated and not freed, useful for dumping + * the memory left allocated between two places at runtime. + */ + +void +xmlMemDisplayLast(FILE *fp, long nbBytes) +{ +#ifdef MEM_LIST + MEMHDR *p; + unsigned idx; + int nb = 0; +#endif + FILE *old_fp = fp; + + if (nbBytes <= 0) + return; + + if (fp == NULL) { + fp = fopen(".memorylist", "w"); + if (fp == NULL) + return; + } + +#ifdef MEM_LIST + fprintf(fp," Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n", + nbBytes, debugMemSize, debugMaxMemSize); + fprintf(fp,"BLOCK NUMBER SIZE TYPE\n"); + idx = 0; + xmlMutexLock(xmlMemMutex); + p = memlist; + while ((p) && (nbBytes > 0)) { + fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number, + (unsigned long)p->mh_size); + switch (p->mh_type) { + case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; + case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; + case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; + case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; + case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; + default: + fprintf(fp,"Unknown memory block, may be corrupted"); + xmlMutexUnlock(xmlMemMutex); + if (old_fp == NULL) + fclose(fp); + return; + } + if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); + if (p->mh_tag != MEMTAG) + fprintf(fp," INVALID"); + nb++; + if (nb < 100) + xmlMemContentShow(fp, p); + else + fprintf(fp," skip"); + + fprintf(fp,"\n"); + nbBytes -= (unsigned long)p->mh_size; + p = p->mh_next; + } + xmlMutexUnlock(xmlMemMutex); +#else + fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n"); +#endif + if (old_fp == NULL) + fclose(fp); +} + +/** + * xmlMemDisplay: + * @fp: a FILE descriptor used as the output file, if NULL, the result is + * written to the file .memorylist + * + * show in-extenso the memory blocks allocated + */ + +void +xmlMemDisplay(FILE *fp) +{ +#ifdef MEM_LIST + MEMHDR *p; + unsigned idx; + int nb = 0; +#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME) + time_t currentTime; + char buf[500]; + struct tm * tstruct; +#endif +#endif + FILE *old_fp = fp; + + if (fp == NULL) { + fp = fopen(".memorylist", "w"); + if (fp == NULL) + return; + } + +#ifdef MEM_LIST +#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME) + currentTime = time(NULL); + tstruct = localtime(¤tTime); + strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct); + fprintf(fp," %s\n\n", buf); +#endif + + + fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n", + debugMemSize, debugMaxMemSize); + fprintf(fp,"BLOCK NUMBER SIZE TYPE\n"); + idx = 0; + xmlMutexLock(xmlMemMutex); + p = memlist; + while (p) { + fprintf(fp,"%-5u %6lu %6lu ",idx++,p->mh_number, + (unsigned long)p->mh_size); + switch (p->mh_type) { + case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; + case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; + case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; + case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; + case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; + default: + fprintf(fp,"Unknown memory block, may be corrupted"); + xmlMutexUnlock(xmlMemMutex); + if (old_fp == NULL) + fclose(fp); + return; + } + if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); + if (p->mh_tag != MEMTAG) + fprintf(fp," INVALID"); + nb++; + if (nb < 100) + xmlMemContentShow(fp, p); + else + fprintf(fp," skip"); + + fprintf(fp,"\n"); + p = p->mh_next; + } + xmlMutexUnlock(xmlMemMutex); +#else + fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n"); +#endif + if (old_fp == NULL) + fclose(fp); +} + +#ifdef MEM_LIST + +static void debugmem_list_add(MEMHDR *p) +{ + p->mh_next = memlist; + p->mh_prev = NULL; + if (memlist) memlist->mh_prev = p; + memlist = p; +#ifdef MEM_LIST_DEBUG + if (stderr) + Mem_Display(stderr); +#endif +} + +static void debugmem_list_delete(MEMHDR *p) +{ + if (p->mh_next) + p->mh_next->mh_prev = p->mh_prev; + if (p->mh_prev) + p->mh_prev->mh_next = p->mh_next; + else memlist = p->mh_next; +#ifdef MEM_LIST_DEBUG + if (stderr) + Mem_Display(stderr); +#endif +} + +#endif + +/* + * debugmem_tag_error: + * + * internal error function. + */ + +static void debugmem_tag_error(void *p) +{ + xmlGenericError(xmlGenericErrorContext, + "Memory tag error occurs :%p \n\t bye\n", p); +#ifdef MEM_LIST + if (stderr) + xmlMemDisplay(stderr); +#endif +} + +#ifdef MEM_LIST +static FILE *xmlMemoryDumpFile = NULL; +#endif + +/** + * xmlMemShow: + * @fp: a FILE descriptor used as the output file + * @nr: number of entries to dump + * + * show a show display of the memory allocated, and dump + * the @nr last allocated areas which were not freed + */ + +void +xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED) +{ +#ifdef MEM_LIST + MEMHDR *p; +#endif + + if (fp != NULL) + fprintf(fp," MEMORY ALLOCATED : %lu, MAX was %lu\n", + debugMemSize, debugMaxMemSize); +#ifdef MEM_LIST + xmlMutexLock(xmlMemMutex); + if (nr > 0) { + fprintf(fp,"NUMBER SIZE TYPE WHERE\n"); + p = memlist; + while ((p) && nr > 0) { + fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size); + switch (p->mh_type) { + case STRDUP_TYPE:fprintf(fp,"strdup() in ");break; + case MALLOC_TYPE:fprintf(fp,"malloc() in ");break; + case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc() in ");break; + case REALLOC_TYPE:fprintf(fp,"realloc() in ");break; + case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break; + default:fprintf(fp," ??? in ");break; + } + if (p->mh_file != NULL) + fprintf(fp,"%s(%u)", p->mh_file, p->mh_line); + if (p->mh_tag != MEMTAG) + fprintf(fp," INVALID"); + xmlMemContentShow(fp, p); + fprintf(fp,"\n"); + nr--; + p = p->mh_next; + } + } + xmlMutexUnlock(xmlMemMutex); +#endif /* MEM_LIST */ +} + +/** + * xmlMemoryDump: + * + * Dump in-extenso the memory blocks allocated to the file .memorylist + */ + +void +xmlMemoryDump(void) +{ +#ifdef MEM_LIST + FILE *dump; + + if (debugMaxMemSize == 0) + return; + dump = fopen(".memdump", "w"); + if (dump == NULL) + xmlMemoryDumpFile = stderr; + else xmlMemoryDumpFile = dump; + + xmlMemDisplay(xmlMemoryDumpFile); + + if (dump != NULL) fclose(dump); +#endif /* MEM_LIST */ +} + + +/**************************************************************** + * * + * Initialization Routines * + * * + ****************************************************************/ + +/** + * xmlInitMemory: + * + * Initialize the memory layer. + * + * Returns 0 on success + */ +int +xmlInitMemory(void) +{ +#ifdef HAVE_STDLIB_H + char *breakpoint; +#endif +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlInitMemory()\n"); +#endif + /* + This is really not good code (see Bug 130419). Suggestions for + improvement will be welcome! + */ + if (xmlMemInitialized) return(-1); + xmlMemInitialized = 1; + xmlMemMutex = xmlNewMutex(); + +#ifdef HAVE_STDLIB_H + breakpoint = getenv("XML_MEM_BREAKPOINT"); + if (breakpoint != NULL) { + sscanf(breakpoint, "%ud", &xmlMemStopAtBlock); + } +#endif +#ifdef HAVE_STDLIB_H + breakpoint = getenv("XML_MEM_TRACE"); + if (breakpoint != NULL) { + sscanf(breakpoint, "%p", &xmlMemTraceBlockAt); + } +#endif + +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlInitMemory() Ok\n"); +#endif + return(0); +} + +/** + * xmlCleanupMemory: + * + * Free up all the memory allocated by the library for its own + * use. This should not be called by user level code. + */ +void +xmlCleanupMemory(void) { +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlCleanupMemory()\n"); +#endif + if (xmlMemInitialized == 0) + return; + + xmlFreeMutex(xmlMemMutex); + xmlMemMutex = NULL; + xmlMemInitialized = 0; +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlCleanupMemory() Ok\n"); +#endif +} + +/** + * xmlMemSetup: + * @freeFunc: the free() function to use + * @mallocFunc: the malloc() function to use + * @reallocFunc: the realloc() function to use + * @strdupFunc: the strdup() function to use + * + * Override the default memory access functions with a new set + * This has to be called before any other libxml routines ! + * + * Should this be blocked if there was already some allocations + * done ? + * + * Returns 0 on success + */ +int +xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, + xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) { +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlMemSetup()\n"); +#endif + if (freeFunc == NULL) + return(-1); + if (mallocFunc == NULL) + return(-1); + if (reallocFunc == NULL) + return(-1); + if (strdupFunc == NULL) + return(-1); + xmlFree = freeFunc; + xmlMalloc = mallocFunc; + xmlMallocAtomic = mallocFunc; + xmlRealloc = reallocFunc; + xmlMemStrdup = strdupFunc; +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlMemSetup() Ok\n"); +#endif + return(0); +} + +/** + * xmlMemGet: + * @freeFunc: place to save the free() function in use + * @mallocFunc: place to save the malloc() function in use + * @reallocFunc: place to save the realloc() function in use + * @strdupFunc: place to save the strdup() function in use + * + * Provides the memory access functions set currently in use + * + * Returns 0 on success + */ +int +xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc, + xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) { + if (freeFunc != NULL) *freeFunc = xmlFree; + if (mallocFunc != NULL) *mallocFunc = xmlMalloc; + if (reallocFunc != NULL) *reallocFunc = xmlRealloc; + if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup; + return(0); +} + +/** + * xmlGcMemSetup: + * @freeFunc: the free() function to use + * @mallocFunc: the malloc() function to use + * @mallocAtomicFunc: the malloc() function to use for atomic allocations + * @reallocFunc: the realloc() function to use + * @strdupFunc: the strdup() function to use + * + * Override the default memory access functions with a new set + * This has to be called before any other libxml routines ! + * The mallocAtomicFunc is specialized for atomic block + * allocations (i.e. of areas useful for garbage collected memory allocators + * + * Should this be blocked if there was already some allocations + * done ? + * + * Returns 0 on success + */ +int +xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, + xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc, + xmlStrdupFunc strdupFunc) { +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlGcMemSetup()\n"); +#endif + if (freeFunc == NULL) + return(-1); + if (mallocFunc == NULL) + return(-1); + if (mallocAtomicFunc == NULL) + return(-1); + if (reallocFunc == NULL) + return(-1); + if (strdupFunc == NULL) + return(-1); + xmlFree = freeFunc; + xmlMalloc = mallocFunc; + xmlMallocAtomic = mallocAtomicFunc; + xmlRealloc = reallocFunc; + xmlMemStrdup = strdupFunc; +#ifdef DEBUG_MEMORY + xmlGenericError(xmlGenericErrorContext, + "xmlGcMemSetup() Ok\n"); +#endif + return(0); +} + +/** + * xmlGcMemGet: + * @freeFunc: place to save the free() function in use + * @mallocFunc: place to save the malloc() function in use + * @mallocAtomicFunc: place to save the atomic malloc() function in use + * @reallocFunc: place to save the realloc() function in use + * @strdupFunc: place to save the strdup() function in use + * + * Provides the memory access functions set currently in use + * The mallocAtomicFunc is specialized for atomic block + * allocations (i.e. of areas useful for garbage collected memory allocators + * + * Returns 0 on success + */ +int +xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc, + xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc, + xmlStrdupFunc *strdupFunc) { + if (freeFunc != NULL) *freeFunc = xmlFree; + if (mallocFunc != NULL) *mallocFunc = xmlMalloc; + if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic; + if (reallocFunc != NULL) *reallocFunc = xmlRealloc; + if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup; + return(0); +} + +#define bottom_xmlmemory +#include "elfgcchack.h" |