~ubuntu-branches/ubuntu/utopic/libxml2/utopic

« back to all changes in this revision

Viewing changes to .pc/0030-Avoid-Possible-null-pointer-dereference-in-memory-de.patch/xmlmemory.c

  • Committer: Package Import Robot
  • Author(s): Aron Xu, Christian Svensson, Daniel Schepler, Helmut Grohne, Adam Conrad, Matthias Klose, Aron Xu
  • Date: 2014-07-09 05:40:15 UTC
  • mfrom: (43.2.6 sid)
  • Revision ID: package-import@ubuntu.com-20140709054015-1q7dyagza4p2gkm0
Tags: 2.9.1+dfsg1-4
[ Christian Svensson ]
* Do not build-depend on readline (Closes: #742350)

[ Daniel Schepler ]
* Patch to bootstrap without python (Closes: #738080)

[ Helmut Grohne ]
* Drop unneeded B-D on perl and binutils (Closes: #753005)

[ Adam Conrad ]
* Actually run dh_autoreconf, which the old/new mixed rules file misses.

[ Matthias Klose ]
* Add patch to fix python multiarch issue
* Allow the package to cross-build by tweaking B-Ds on python
* Set PYTHON_LIBS for cross builds

[ Aron Xu ]
* Use correct $CC
* Configure udeb without python
* New round of cherry-picking upstream fixes
  - Includes fixes for CVE-2014-0191 (Closes: #747309).
* Call prename with -vf
* Require python-all-dev (>= 2.7.5-5~)
* Bump std-ver: 3.9.4 -> 3.9.5, no change

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * xmlmemory.c:  libxml memory allocator wrapper.
 
3
 *
 
4
 * daniel@veillard.com
 
5
 */
 
6
 
 
7
#define IN_LIBXML
 
8
#include "libxml.h"
 
9
 
 
10
#include <string.h>
 
11
 
 
12
#ifdef HAVE_SYS_TYPES_H
 
13
#include <sys/types.h>
 
14
#endif
 
15
 
 
16
#ifdef HAVE_TIME_H
 
17
#include <time.h>
 
18
#endif
 
19
 
 
20
#ifdef HAVE_STDLIB_H
 
21
#include <stdlib.h>
 
22
#else
 
23
#ifdef HAVE_MALLOC_H
 
24
#include <malloc.h>
 
25
#endif
 
26
#endif
 
27
 
 
28
#ifdef HAVE_CTYPE_H
 
29
#include <ctype.h>
 
30
#endif
 
31
 
 
32
/* #define DEBUG_MEMORY */
 
33
 
 
34
/**
 
35
 * MEM_LIST:
 
36
 *
 
37
 * keep track of all allocated blocks for error reporting
 
38
 * Always build the memory list !
 
39
 */
 
40
#ifdef DEBUG_MEMORY_LOCATION
 
41
#ifndef MEM_LIST
 
42
#define MEM_LIST /* keep a list of all the allocated memory blocks */
 
43
#endif
 
44
#endif
 
45
 
 
46
#include <libxml/globals.h>     /* must come before xmlmemory.h */
 
47
#include <libxml/xmlmemory.h>
 
48
#include <libxml/xmlerror.h>
 
49
#include <libxml/threads.h>
 
50
 
 
51
static int xmlMemInitialized = 0;
 
52
static unsigned long  debugMemSize = 0;
 
53
static unsigned long  debugMemBlocks = 0;
 
54
static unsigned long  debugMaxMemSize = 0;
 
55
static xmlMutexPtr xmlMemMutex = NULL;
 
56
 
 
57
void xmlMallocBreakpoint(void);
 
58
 
 
59
/************************************************************************
 
60
 *                                                                      *
 
61
 *              Macros, variables and associated types                  *
 
62
 *                                                                      *
 
63
 ************************************************************************/
 
64
 
 
65
#if !defined(LIBXML_THREAD_ENABLED) && !defined(LIBXML_THREAD_ALLOC_ENABLED)
 
66
#ifdef xmlMalloc
 
67
#undef xmlMalloc
 
68
#endif
 
69
#ifdef xmlRealloc
 
70
#undef xmlRealloc
 
71
#endif
 
72
#ifdef xmlMemStrdup
 
73
#undef xmlMemStrdup
 
74
#endif
 
75
#endif
 
76
 
 
77
/*
 
78
 * Each of the blocks allocated begin with a header containing informations
 
79
 */
 
80
 
 
81
#define MEMTAG 0x5aa5
 
82
 
 
83
#define MALLOC_TYPE 1
 
84
#define REALLOC_TYPE 2
 
85
#define STRDUP_TYPE 3
 
86
#define MALLOC_ATOMIC_TYPE 4
 
87
#define REALLOC_ATOMIC_TYPE 5
 
88
 
 
89
typedef struct memnod {
 
90
    unsigned int   mh_tag;
 
91
    unsigned int   mh_type;
 
92
    unsigned long  mh_number;
 
93
    size_t         mh_size;
 
94
#ifdef MEM_LIST
 
95
   struct memnod *mh_next;
 
96
   struct memnod *mh_prev;
 
97
#endif
 
98
   const char    *mh_file;
 
99
   unsigned int   mh_line;
 
100
}  MEMHDR;
 
101
 
 
102
 
 
103
#ifdef SUN4
 
104
#define ALIGN_SIZE  16
 
105
#else
 
106
#define ALIGN_SIZE  sizeof(double)
 
107
#endif
 
108
#define HDR_SIZE    sizeof(MEMHDR)
 
109
#define RESERVE_SIZE (((HDR_SIZE + (ALIGN_SIZE-1)) \
 
110
                      / ALIGN_SIZE ) * ALIGN_SIZE)
 
111
 
 
112
 
 
113
#define CLIENT_2_HDR(a) ((MEMHDR *) (((char *) (a)) - RESERVE_SIZE))
 
114
#define HDR_2_CLIENT(a)    ((void *) (((char *) (a)) + RESERVE_SIZE))
 
115
 
 
116
 
 
117
static unsigned int block=0;
 
118
static unsigned int xmlMemStopAtBlock = 0;
 
119
static void *xmlMemTraceBlockAt = NULL;
 
120
#ifdef MEM_LIST
 
121
static MEMHDR *memlist = NULL;
 
122
#endif
 
123
 
 
124
static void debugmem_tag_error(void *addr);
 
125
#ifdef MEM_LIST
 
126
static void  debugmem_list_add(MEMHDR *);
 
127
static void debugmem_list_delete(MEMHDR *);
 
128
#endif
 
129
#define Mem_Tag_Err(a) debugmem_tag_error(a);
 
130
 
 
131
#ifndef TEST_POINT
 
132
#define TEST_POINT
 
133
#endif
 
134
 
 
135
/**
 
136
 * xmlMallocBreakpoint:
 
137
 *
 
138
 * Breakpoint to use in conjunction with xmlMemStopAtBlock. When the block
 
139
 * number reaches the specified value this function is called. One need to add a breakpoint
 
140
 * to it to get the context in which the given block is allocated.
 
141
 */
 
142
 
 
143
void
 
144
xmlMallocBreakpoint(void) {
 
145
    xmlGenericError(xmlGenericErrorContext,
 
146
            "xmlMallocBreakpoint reached on block %d\n", xmlMemStopAtBlock);
 
147
}
 
148
 
 
149
/**
 
150
 * xmlMallocLoc:
 
151
 * @size:  an int specifying the size in byte to allocate.
 
152
 * @file:  the file name or NULL
 
153
 * @line:  the line number
 
154
 *
 
155
 * a malloc() equivalent, with logging of the allocation info.
 
156
 *
 
157
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
 
158
 */
 
159
 
 
160
void *
 
161
xmlMallocLoc(size_t size, const char * file, int line)
 
162
{
 
163
    MEMHDR *p;
 
164
    void *ret;
 
165
 
 
166
    if (!xmlMemInitialized) xmlInitMemory();
 
167
#ifdef DEBUG_MEMORY
 
168
    xmlGenericError(xmlGenericErrorContext,
 
169
            "Malloc(%d)\n",size);
 
170
#endif
 
171
 
 
172
    TEST_POINT
 
173
 
 
174
    p = (MEMHDR *) malloc(RESERVE_SIZE+size);
 
175
 
 
176
    if (!p) {
 
177
        xmlGenericError(xmlGenericErrorContext,
 
178
                "xmlMallocLoc : Out of free space\n");
 
179
        xmlMemoryDump();
 
180
        return(NULL);
 
181
    }
 
182
    p->mh_tag = MEMTAG;
 
183
    p->mh_size = size;
 
184
    p->mh_type = MALLOC_TYPE;
 
185
    p->mh_file = file;
 
186
    p->mh_line = line;
 
187
    xmlMutexLock(xmlMemMutex);
 
188
    p->mh_number = ++block;
 
189
    debugMemSize += size;
 
190
    debugMemBlocks++;
 
191
    if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
 
192
#ifdef MEM_LIST
 
193
    debugmem_list_add(p);
 
194
#endif
 
195
    xmlMutexUnlock(xmlMemMutex);
 
196
 
 
197
#ifdef DEBUG_MEMORY
 
198
    xmlGenericError(xmlGenericErrorContext,
 
199
            "Malloc(%d) Ok\n",size);
 
200
#endif
 
201
 
 
202
    if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
 
203
 
 
204
    ret = HDR_2_CLIENT(p);
 
205
 
 
206
    if (xmlMemTraceBlockAt == ret) {
 
207
        xmlGenericError(xmlGenericErrorContext,
 
208
                        "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
 
209
                        (long unsigned)size);
 
210
        xmlMallocBreakpoint();
 
211
    }
 
212
 
 
213
    TEST_POINT
 
214
 
 
215
    return(ret);
 
216
}
 
217
 
 
218
/**
 
219
 * xmlMallocAtomicLoc:
 
220
 * @size:  an int specifying the size in byte to allocate.
 
221
 * @file:  the file name or NULL
 
222
 * @line:  the line number
 
223
 *
 
224
 * a malloc() equivalent, with logging of the allocation info.
 
225
 *
 
226
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
 
227
 */
 
228
 
 
229
void *
 
230
xmlMallocAtomicLoc(size_t size, const char * file, int line)
 
231
{
 
232
    MEMHDR *p;
 
233
    void *ret;
 
234
 
 
235
    if (!xmlMemInitialized) xmlInitMemory();
 
236
#ifdef DEBUG_MEMORY
 
237
    xmlGenericError(xmlGenericErrorContext,
 
238
            "Malloc(%d)\n",size);
 
239
#endif
 
240
 
 
241
    TEST_POINT
 
242
 
 
243
    p = (MEMHDR *) malloc(RESERVE_SIZE+size);
 
244
 
 
245
    if (!p) {
 
246
        xmlGenericError(xmlGenericErrorContext,
 
247
                "xmlMallocLoc : Out of free space\n");
 
248
        xmlMemoryDump();
 
249
        return(NULL);
 
250
    }
 
251
    p->mh_tag = MEMTAG;
 
252
    p->mh_size = size;
 
253
    p->mh_type = MALLOC_ATOMIC_TYPE;
 
254
    p->mh_file = file;
 
255
    p->mh_line = line;
 
256
    xmlMutexLock(xmlMemMutex);
 
257
    p->mh_number = ++block;
 
258
    debugMemSize += size;
 
259
    debugMemBlocks++;
 
260
    if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
 
261
#ifdef MEM_LIST
 
262
    debugmem_list_add(p);
 
263
#endif
 
264
    xmlMutexUnlock(xmlMemMutex);
 
265
 
 
266
#ifdef DEBUG_MEMORY
 
267
    xmlGenericError(xmlGenericErrorContext,
 
268
            "Malloc(%d) Ok\n",size);
 
269
#endif
 
270
 
 
271
    if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
 
272
 
 
273
    ret = HDR_2_CLIENT(p);
 
274
 
 
275
    if (xmlMemTraceBlockAt == ret) {
 
276
        xmlGenericError(xmlGenericErrorContext,
 
277
                        "%p : Malloc(%lu) Ok\n", xmlMemTraceBlockAt,
 
278
                        (long unsigned)size);
 
279
        xmlMallocBreakpoint();
 
280
    }
 
281
 
 
282
    TEST_POINT
 
283
 
 
284
    return(ret);
 
285
}
 
286
/**
 
287
 * xmlMemMalloc:
 
288
 * @size:  an int specifying the size in byte to allocate.
 
289
 *
 
290
 * a malloc() equivalent, with logging of the allocation info.
 
291
 *
 
292
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
 
293
 */
 
294
 
 
295
void *
 
296
xmlMemMalloc(size_t size)
 
297
{
 
298
    return(xmlMallocLoc(size, "none", 0));
 
299
}
 
300
 
 
301
/**
 
302
 * xmlReallocLoc:
 
303
 * @ptr:  the initial memory block pointer
 
304
 * @size:  an int specifying the size in byte to allocate.
 
305
 * @file:  the file name or NULL
 
306
 * @line:  the line number
 
307
 *
 
308
 * a realloc() equivalent, with logging of the allocation info.
 
309
 *
 
310
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
 
311
 */
 
312
 
 
313
void *
 
314
xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
 
315
{
 
316
    MEMHDR *p;
 
317
    unsigned long number;
 
318
#ifdef DEBUG_MEMORY
 
319
    size_t oldsize;
 
320
#endif
 
321
 
 
322
    if (ptr == NULL)
 
323
        return(xmlMallocLoc(size, file, line));
 
324
 
 
325
    if (!xmlMemInitialized) xmlInitMemory();
 
326
    TEST_POINT
 
327
 
 
328
    p = CLIENT_2_HDR(ptr);
 
329
    number = p->mh_number;
 
330
    if (xmlMemStopAtBlock == number) xmlMallocBreakpoint();
 
331
    if (p->mh_tag != MEMTAG) {
 
332
       Mem_Tag_Err(p);
 
333
         goto error;
 
334
    }
 
335
    p->mh_tag = ~MEMTAG;
 
336
    xmlMutexLock(xmlMemMutex);
 
337
    debugMemSize -= p->mh_size;
 
338
    debugMemBlocks--;
 
339
#ifdef DEBUG_MEMORY
 
340
    oldsize = p->mh_size;
 
341
#endif
 
342
#ifdef MEM_LIST
 
343
    debugmem_list_delete(p);
 
344
#endif
 
345
    xmlMutexUnlock(xmlMemMutex);
 
346
 
 
347
    p = (MEMHDR *) realloc(p,RESERVE_SIZE+size);
 
348
    if (!p) {
 
349
         goto error;
 
350
    }
 
351
    if (xmlMemTraceBlockAt == ptr) {
 
352
        xmlGenericError(xmlGenericErrorContext,
 
353
                        "%p : Realloced(%lu -> %lu) Ok\n",
 
354
                        xmlMemTraceBlockAt, (long unsigned)p->mh_size,
 
355
                        (long unsigned)size);
 
356
        xmlMallocBreakpoint();
 
357
    }
 
358
    p->mh_tag = MEMTAG;
 
359
    p->mh_number = number;
 
360
    p->mh_type = REALLOC_TYPE;
 
361
    p->mh_size = size;
 
362
    p->mh_file = file;
 
363
    p->mh_line = line;
 
364
    xmlMutexLock(xmlMemMutex);
 
365
    debugMemSize += size;
 
366
    debugMemBlocks++;
 
367
    if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
 
368
#ifdef MEM_LIST
 
369
    debugmem_list_add(p);
 
370
#endif
 
371
    xmlMutexUnlock(xmlMemMutex);
 
372
 
 
373
    TEST_POINT
 
374
 
 
375
#ifdef DEBUG_MEMORY
 
376
    xmlGenericError(xmlGenericErrorContext,
 
377
            "Realloced(%d to %d) Ok\n", oldsize, size);
 
378
#endif
 
379
    return(HDR_2_CLIENT(p));
 
380
 
 
381
error:
 
382
    return(NULL);
 
383
}
 
384
 
 
385
/**
 
386
 * xmlMemRealloc:
 
387
 * @ptr:  the initial memory block pointer
 
388
 * @size:  an int specifying the size in byte to allocate.
 
389
 *
 
390
 * a realloc() equivalent, with logging of the allocation info.
 
391
 *
 
392
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
 
393
 */
 
394
 
 
395
void *
 
396
xmlMemRealloc(void *ptr,size_t size) {
 
397
    return(xmlReallocLoc(ptr, size, "none", 0));
 
398
}
 
399
 
 
400
/**
 
401
 * xmlMemFree:
 
402
 * @ptr:  the memory block pointer
 
403
 *
 
404
 * a free() equivalent, with error checking.
 
405
 */
 
406
void
 
407
xmlMemFree(void *ptr)
 
408
{
 
409
    MEMHDR *p;
 
410
    char *target;
 
411
#ifdef DEBUG_MEMORY
 
412
    size_t size;
 
413
#endif
 
414
 
 
415
    if (ptr == NULL)
 
416
        return;
 
417
 
 
418
    if (ptr == (void *) -1) {
 
419
        xmlGenericError(xmlGenericErrorContext,
 
420
            "trying to free pointer from freed area\n");
 
421
        goto error;
 
422
    }
 
423
 
 
424
    if (xmlMemTraceBlockAt == ptr) {
 
425
        xmlGenericError(xmlGenericErrorContext,
 
426
                        "%p : Freed()\n", xmlMemTraceBlockAt);
 
427
        xmlMallocBreakpoint();
 
428
    }
 
429
 
 
430
    TEST_POINT
 
431
 
 
432
    target = (char *) ptr;
 
433
 
 
434
    p = CLIENT_2_HDR(ptr);
 
435
    if (p->mh_tag != MEMTAG) {
 
436
        Mem_Tag_Err(p);
 
437
        goto error;
 
438
    }
 
439
    if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
 
440
    p->mh_tag = ~MEMTAG;
 
441
    memset(target, -1, p->mh_size);
 
442
    xmlMutexLock(xmlMemMutex);
 
443
    debugMemSize -= p->mh_size;
 
444
    debugMemBlocks--;
 
445
#ifdef DEBUG_MEMORY
 
446
    size = p->mh_size;
 
447
#endif
 
448
#ifdef MEM_LIST
 
449
    debugmem_list_delete(p);
 
450
#endif
 
451
    xmlMutexUnlock(xmlMemMutex);
 
452
 
 
453
    free(p);
 
454
 
 
455
    TEST_POINT
 
456
 
 
457
#ifdef DEBUG_MEMORY
 
458
    xmlGenericError(xmlGenericErrorContext,
 
459
            "Freed(%d) Ok\n", size);
 
460
#endif
 
461
 
 
462
    return;
 
463
 
 
464
error:
 
465
    xmlGenericError(xmlGenericErrorContext,
 
466
            "xmlMemFree(%lX) error\n", (unsigned long) ptr);
 
467
    xmlMallocBreakpoint();
 
468
    return;
 
469
}
 
470
 
 
471
/**
 
472
 * xmlMemStrdupLoc:
 
473
 * @str:  the initial string pointer
 
474
 * @file:  the file name or NULL
 
475
 * @line:  the line number
 
476
 *
 
477
 * a strdup() equivalent, with logging of the allocation info.
 
478
 *
 
479
 * Returns a pointer to the new string or NULL if allocation error occurred.
 
480
 */
 
481
 
 
482
char *
 
483
xmlMemStrdupLoc(const char *str, const char *file, int line)
 
484
{
 
485
    char *s;
 
486
    size_t size = strlen(str) + 1;
 
487
    MEMHDR *p;
 
488
 
 
489
    if (!xmlMemInitialized) xmlInitMemory();
 
490
    TEST_POINT
 
491
 
 
492
    p = (MEMHDR *) malloc(RESERVE_SIZE+size);
 
493
    if (!p) {
 
494
      goto error;
 
495
    }
 
496
    p->mh_tag = MEMTAG;
 
497
    p->mh_size = size;
 
498
    p->mh_type = STRDUP_TYPE;
 
499
    p->mh_file = file;
 
500
    p->mh_line = line;
 
501
    xmlMutexLock(xmlMemMutex);
 
502
    p->mh_number = ++block;
 
503
    debugMemSize += size;
 
504
    debugMemBlocks++;
 
505
    if (debugMemSize > debugMaxMemSize) debugMaxMemSize = debugMemSize;
 
506
#ifdef MEM_LIST
 
507
    debugmem_list_add(p);
 
508
#endif
 
509
    xmlMutexUnlock(xmlMemMutex);
 
510
 
 
511
    s = (char *) HDR_2_CLIENT(p);
 
512
 
 
513
    if (xmlMemStopAtBlock == p->mh_number) xmlMallocBreakpoint();
 
514
 
 
515
    if (s != NULL)
 
516
      strcpy(s,str);
 
517
    else
 
518
      goto error;
 
519
 
 
520
    TEST_POINT
 
521
 
 
522
    if (xmlMemTraceBlockAt == s) {
 
523
        xmlGenericError(xmlGenericErrorContext,
 
524
                        "%p : Strdup() Ok\n", xmlMemTraceBlockAt);
 
525
        xmlMallocBreakpoint();
 
526
    }
 
527
 
 
528
    return(s);
 
529
 
 
530
error:
 
531
    return(NULL);
 
532
}
 
533
 
 
534
/**
 
535
 * xmlMemoryStrdup:
 
536
 * @str:  the initial string pointer
 
537
 *
 
538
 * a strdup() equivalent, with logging of the allocation info.
 
539
 *
 
540
 * Returns a pointer to the new string or NULL if allocation error occurred.
 
541
 */
 
542
 
 
543
char *
 
544
xmlMemoryStrdup(const char *str) {
 
545
    return(xmlMemStrdupLoc(str, "none", 0));
 
546
}
 
547
 
 
548
/**
 
549
 * xmlMemUsed:
 
550
 *
 
551
 * Provides the amount of memory currently allocated
 
552
 *
 
553
 * Returns an int representing the amount of memory allocated.
 
554
 */
 
555
 
 
556
int
 
557
xmlMemUsed(void) {
 
558
     return(debugMemSize);
 
559
}
 
560
 
 
561
/**
 
562
 * xmlMemBlocks:
 
563
 *
 
564
 * Provides the number of memory areas currently allocated
 
565
 *
 
566
 * Returns an int representing the number of blocks
 
567
 */
 
568
 
 
569
int
 
570
xmlMemBlocks(void) {
 
571
     return(debugMemBlocks);
 
572
}
 
573
 
 
574
#ifdef MEM_LIST
 
575
/**
 
576
 * xmlMemContentShow:
 
577
 * @fp:  a FILE descriptor used as the output file
 
578
 * @p:  a memory block header
 
579
 *
 
580
 * tries to show some content from the memory block
 
581
 */
 
582
 
 
583
static void
 
584
xmlMemContentShow(FILE *fp, MEMHDR *p)
 
585
{
 
586
    int i,j,k,len = p->mh_size;
 
587
    const char *buf = (const char *) HDR_2_CLIENT(p);
 
588
 
 
589
    if (p == NULL) {
 
590
        fprintf(fp, " NULL");
 
591
        return;
 
592
    }
 
593
 
 
594
    for (i = 0;i < len;i++) {
 
595
        if (buf[i] == 0) break;
 
596
        if (!isprint((unsigned char) buf[i])) break;
 
597
    }
 
598
    if ((i < 4) && ((buf[i] != 0) || (i == 0))) {
 
599
        if (len >= 4) {
 
600
            MEMHDR *q;
 
601
            void *cur;
 
602
 
 
603
            for (j = 0;(j < len -3) && (j < 40);j += 4) {
 
604
                cur = *((void **) &buf[j]);
 
605
                q = CLIENT_2_HDR(cur);
 
606
                p = memlist;
 
607
                k = 0;
 
608
                while (p != NULL) {
 
609
                    if (p == q) break;
 
610
                    p = p->mh_next;
 
611
                    if (k++ > 100) break;
 
612
                }
 
613
                if ((p != NULL) && (p == q)) {
 
614
                    fprintf(fp, " pointer to #%lu at index %d",
 
615
                            p->mh_number, j);
 
616
                    return;
 
617
                }
 
618
            }
 
619
        }
 
620
    } else if ((i == 0) && (buf[i] == 0)) {
 
621
        fprintf(fp," null");
 
622
    } else {
 
623
        if (buf[i] == 0) fprintf(fp," \"%.25s\"", buf);
 
624
        else {
 
625
            fprintf(fp," [");
 
626
            for (j = 0;j < i;j++)
 
627
                fprintf(fp,"%c", buf[j]);
 
628
            fprintf(fp,"]");
 
629
        }
 
630
    }
 
631
}
 
632
#endif
 
633
 
 
634
/**
 
635
 * xmlMemDisplayLast:
 
636
 * @fp:  a FILE descriptor used as the output file, if NULL, the result is
 
637
 *       written to the file .memorylist
 
638
 * @nbBytes: the amount of memory to dump
 
639
 *
 
640
 * the last nbBytes of memory allocated and not freed, useful for dumping
 
641
 * the memory left allocated between two places at runtime.
 
642
 */
 
643
 
 
644
void
 
645
xmlMemDisplayLast(FILE *fp, long nbBytes)
 
646
{
 
647
#ifdef MEM_LIST
 
648
    MEMHDR *p;
 
649
    unsigned idx;
 
650
    int     nb = 0;
 
651
#endif
 
652
    FILE *old_fp = fp;
 
653
 
 
654
    if (nbBytes <= 0)
 
655
        return;
 
656
 
 
657
    if (fp == NULL) {
 
658
        fp = fopen(".memorylist", "w");
 
659
        if (fp == NULL)
 
660
            return;
 
661
    }
 
662
 
 
663
#ifdef MEM_LIST
 
664
    fprintf(fp,"   Last %li MEMORY ALLOCATED : %lu, MAX was %lu\n",
 
665
            nbBytes, debugMemSize, debugMaxMemSize);
 
666
    fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
 
667
    idx = 0;
 
668
    xmlMutexLock(xmlMemMutex);
 
669
    p = memlist;
 
670
    while ((p) && (nbBytes > 0)) {
 
671
          fprintf(fp,"%-5u  %6lu %6lu ",idx++,p->mh_number,
 
672
                  (unsigned long)p->mh_size);
 
673
        switch (p->mh_type) {
 
674
           case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
 
675
           case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
 
676
           case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
 
677
           case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
 
678
           case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
 
679
           default:
 
680
                fprintf(fp,"Unknown memory block, may be corrupted");
 
681
                xmlMutexUnlock(xmlMemMutex);
 
682
                if (old_fp == NULL)
 
683
                    fclose(fp);
 
684
                return;
 
685
        }
 
686
        if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
 
687
        if (p->mh_tag != MEMTAG)
 
688
              fprintf(fp,"  INVALID");
 
689
        nb++;
 
690
        if (nb < 100)
 
691
            xmlMemContentShow(fp, p);
 
692
        else
 
693
            fprintf(fp," skip");
 
694
 
 
695
        fprintf(fp,"\n");
 
696
        nbBytes -= (unsigned long)p->mh_size;
 
697
        p = p->mh_next;
 
698
    }
 
699
    xmlMutexUnlock(xmlMemMutex);
 
700
#else
 
701
    fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
 
702
#endif
 
703
    if (old_fp == NULL)
 
704
        fclose(fp);
 
705
}
 
706
 
 
707
/**
 
708
 * xmlMemDisplay:
 
709
 * @fp:  a FILE descriptor used as the output file, if NULL, the result is
 
710
 *       written to the file .memorylist
 
711
 *
 
712
 * show in-extenso the memory blocks allocated
 
713
 */
 
714
 
 
715
void
 
716
xmlMemDisplay(FILE *fp)
 
717
{
 
718
#ifdef MEM_LIST
 
719
    MEMHDR *p;
 
720
    unsigned idx;
 
721
    int     nb = 0;
 
722
#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
 
723
    time_t currentTime;
 
724
    char buf[500];
 
725
    struct tm * tstruct;
 
726
#endif
 
727
#endif
 
728
    FILE *old_fp = fp;
 
729
 
 
730
    if (fp == NULL) {
 
731
        fp = fopen(".memorylist", "w");
 
732
        if (fp == NULL)
 
733
            return;
 
734
    }
 
735
 
 
736
#ifdef MEM_LIST
 
737
#if defined(HAVE_LOCALTIME) && defined(HAVE_STRFTIME)
 
738
    currentTime = time(NULL);
 
739
    tstruct = localtime(&currentTime);
 
740
    strftime(buf, sizeof(buf) - 1, "%I:%M:%S %p", tstruct);
 
741
    fprintf(fp,"      %s\n\n", buf);
 
742
#endif
 
743
 
 
744
 
 
745
    fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
 
746
            debugMemSize, debugMaxMemSize);
 
747
    fprintf(fp,"BLOCK  NUMBER   SIZE  TYPE\n");
 
748
    idx = 0;
 
749
    xmlMutexLock(xmlMemMutex);
 
750
    p = memlist;
 
751
    while (p) {
 
752
          fprintf(fp,"%-5u  %6lu %6lu ",idx++,p->mh_number,
 
753
                  (unsigned long)p->mh_size);
 
754
        switch (p->mh_type) {
 
755
           case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
 
756
           case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
 
757
           case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
 
758
           case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
 
759
           case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
 
760
           default:
 
761
                fprintf(fp,"Unknown memory block, may be corrupted");
 
762
                xmlMutexUnlock(xmlMemMutex);
 
763
                if (old_fp == NULL)
 
764
                    fclose(fp);
 
765
                return;
 
766
        }
 
767
        if (p->mh_file != NULL) fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
 
768
        if (p->mh_tag != MEMTAG)
 
769
              fprintf(fp,"  INVALID");
 
770
        nb++;
 
771
        if (nb < 100)
 
772
            xmlMemContentShow(fp, p);
 
773
        else
 
774
            fprintf(fp," skip");
 
775
 
 
776
        fprintf(fp,"\n");
 
777
        p = p->mh_next;
 
778
    }
 
779
    xmlMutexUnlock(xmlMemMutex);
 
780
#else
 
781
    fprintf(fp,"Memory list not compiled (MEM_LIST not defined !)\n");
 
782
#endif
 
783
    if (old_fp == NULL)
 
784
        fclose(fp);
 
785
}
 
786
 
 
787
#ifdef MEM_LIST
 
788
 
 
789
static void debugmem_list_add(MEMHDR *p)
 
790
{
 
791
     p->mh_next = memlist;
 
792
     p->mh_prev = NULL;
 
793
     if (memlist) memlist->mh_prev = p;
 
794
     memlist = p;
 
795
#ifdef MEM_LIST_DEBUG
 
796
     if (stderr)
 
797
     Mem_Display(stderr);
 
798
#endif
 
799
}
 
800
 
 
801
static void debugmem_list_delete(MEMHDR *p)
 
802
{
 
803
     if (p->mh_next)
 
804
     p->mh_next->mh_prev = p->mh_prev;
 
805
     if (p->mh_prev)
 
806
     p->mh_prev->mh_next = p->mh_next;
 
807
     else memlist = p->mh_next;
 
808
#ifdef MEM_LIST_DEBUG
 
809
     if (stderr)
 
810
     Mem_Display(stderr);
 
811
#endif
 
812
}
 
813
 
 
814
#endif
 
815
 
 
816
/*
 
817
 * debugmem_tag_error:
 
818
 *
 
819
 * internal error function.
 
820
 */
 
821
 
 
822
static void debugmem_tag_error(void *p)
 
823
{
 
824
     xmlGenericError(xmlGenericErrorContext,
 
825
             "Memory tag error occurs :%p \n\t bye\n", p);
 
826
#ifdef MEM_LIST
 
827
     if (stderr)
 
828
     xmlMemDisplay(stderr);
 
829
#endif
 
830
}
 
831
 
 
832
#ifdef MEM_LIST
 
833
static FILE *xmlMemoryDumpFile = NULL;
 
834
#endif
 
835
 
 
836
/**
 
837
 * xmlMemShow:
 
838
 * @fp:  a FILE descriptor used as the output file
 
839
 * @nr:  number of entries to dump
 
840
 *
 
841
 * show a show display of the memory allocated, and dump
 
842
 * the @nr last allocated areas which were not freed
 
843
 */
 
844
 
 
845
void
 
846
xmlMemShow(FILE *fp, int nr ATTRIBUTE_UNUSED)
 
847
{
 
848
#ifdef MEM_LIST
 
849
    MEMHDR *p;
 
850
#endif
 
851
 
 
852
    if (fp != NULL)
 
853
        fprintf(fp,"      MEMORY ALLOCATED : %lu, MAX was %lu\n",
 
854
                debugMemSize, debugMaxMemSize);
 
855
#ifdef MEM_LIST
 
856
    xmlMutexLock(xmlMemMutex);
 
857
    if (nr > 0) {
 
858
        fprintf(fp,"NUMBER   SIZE  TYPE   WHERE\n");
 
859
        p = memlist;
 
860
        while ((p) && nr > 0) {
 
861
              fprintf(fp,"%6lu %6lu ",p->mh_number,(unsigned long)p->mh_size);
 
862
            switch (p->mh_type) {
 
863
               case STRDUP_TYPE:fprintf(fp,"strdup()  in ");break;
 
864
               case MALLOC_TYPE:fprintf(fp,"malloc()  in ");break;
 
865
               case MALLOC_ATOMIC_TYPE:fprintf(fp,"atomicmalloc()  in ");break;
 
866
              case REALLOC_TYPE:fprintf(fp,"realloc() in ");break;
 
867
              case REALLOC_ATOMIC_TYPE:fprintf(fp,"atomicrealloc() in ");break;
 
868
                default:fprintf(fp,"   ???    in ");break;
 
869
            }
 
870
            if (p->mh_file != NULL)
 
871
                fprintf(fp,"%s(%u)", p->mh_file, p->mh_line);
 
872
            if (p->mh_tag != MEMTAG)
 
873
                fprintf(fp,"  INVALID");
 
874
            xmlMemContentShow(fp, p);
 
875
            fprintf(fp,"\n");
 
876
            nr--;
 
877
            p = p->mh_next;
 
878
        }
 
879
    }
 
880
    xmlMutexUnlock(xmlMemMutex);
 
881
#endif /* MEM_LIST */
 
882
}
 
883
 
 
884
/**
 
885
 * xmlMemoryDump:
 
886
 *
 
887
 * Dump in-extenso the memory blocks allocated to the file .memorylist
 
888
 */
 
889
 
 
890
void
 
891
xmlMemoryDump(void)
 
892
{
 
893
#ifdef MEM_LIST
 
894
    FILE *dump;
 
895
 
 
896
    if (debugMaxMemSize == 0)
 
897
        return;
 
898
    dump = fopen(".memdump", "w");
 
899
    if (dump == NULL)
 
900
        xmlMemoryDumpFile = stderr;
 
901
    else xmlMemoryDumpFile = dump;
 
902
 
 
903
    xmlMemDisplay(xmlMemoryDumpFile);
 
904
 
 
905
    if (dump != NULL) fclose(dump);
 
906
#endif /* MEM_LIST */
 
907
}
 
908
 
 
909
 
 
910
/****************************************************************
 
911
 *                                                              *
 
912
 *              Initialization Routines                         *
 
913
 *                                                              *
 
914
 ****************************************************************/
 
915
 
 
916
/**
 
917
 * xmlInitMemory:
 
918
 *
 
919
 * Initialize the memory layer.
 
920
 *
 
921
 * Returns 0 on success
 
922
 */
 
923
int
 
924
xmlInitMemory(void)
 
925
{
 
926
#ifdef HAVE_STDLIB_H
 
927
     char *breakpoint;
 
928
#endif
 
929
#ifdef DEBUG_MEMORY
 
930
     xmlGenericError(xmlGenericErrorContext,
 
931
             "xmlInitMemory()\n");
 
932
#endif
 
933
    /*
 
934
     This is really not good code (see Bug 130419).  Suggestions for
 
935
     improvement will be welcome!
 
936
    */
 
937
     if (xmlMemInitialized) return(-1);
 
938
     xmlMemInitialized = 1;
 
939
     xmlMemMutex = xmlNewMutex();
 
940
 
 
941
#ifdef HAVE_STDLIB_H
 
942
     breakpoint = getenv("XML_MEM_BREAKPOINT");
 
943
     if (breakpoint != NULL) {
 
944
         sscanf(breakpoint, "%ud", &xmlMemStopAtBlock);
 
945
     }
 
946
#endif
 
947
#ifdef HAVE_STDLIB_H
 
948
     breakpoint = getenv("XML_MEM_TRACE");
 
949
     if (breakpoint != NULL) {
 
950
         sscanf(breakpoint, "%p", &xmlMemTraceBlockAt);
 
951
     }
 
952
#endif
 
953
 
 
954
#ifdef DEBUG_MEMORY
 
955
     xmlGenericError(xmlGenericErrorContext,
 
956
             "xmlInitMemory() Ok\n");
 
957
#endif
 
958
     return(0);
 
959
}
 
960
 
 
961
/**
 
962
 * xmlCleanupMemory:
 
963
 *
 
964
 * Free up all the memory allocated by the library for its own
 
965
 * use. This should not be called by user level code.
 
966
 */
 
967
void
 
968
xmlCleanupMemory(void) {
 
969
#ifdef DEBUG_MEMORY
 
970
     xmlGenericError(xmlGenericErrorContext,
 
971
             "xmlCleanupMemory()\n");
 
972
#endif
 
973
    if (xmlMemInitialized == 0)
 
974
        return;
 
975
 
 
976
    xmlFreeMutex(xmlMemMutex);
 
977
    xmlMemMutex = NULL;
 
978
    xmlMemInitialized = 0;
 
979
#ifdef DEBUG_MEMORY
 
980
     xmlGenericError(xmlGenericErrorContext,
 
981
             "xmlCleanupMemory() Ok\n");
 
982
#endif
 
983
}
 
984
 
 
985
/**
 
986
 * xmlMemSetup:
 
987
 * @freeFunc: the free() function to use
 
988
 * @mallocFunc: the malloc() function to use
 
989
 * @reallocFunc: the realloc() function to use
 
990
 * @strdupFunc: the strdup() function to use
 
991
 *
 
992
 * Override the default memory access functions with a new set
 
993
 * This has to be called before any other libxml routines !
 
994
 *
 
995
 * Should this be blocked if there was already some allocations
 
996
 * done ?
 
997
 *
 
998
 * Returns 0 on success
 
999
 */
 
1000
int
 
1001
xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
 
1002
            xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
 
1003
#ifdef DEBUG_MEMORY
 
1004
     xmlGenericError(xmlGenericErrorContext,
 
1005
             "xmlMemSetup()\n");
 
1006
#endif
 
1007
    if (freeFunc == NULL)
 
1008
        return(-1);
 
1009
    if (mallocFunc == NULL)
 
1010
        return(-1);
 
1011
    if (reallocFunc == NULL)
 
1012
        return(-1);
 
1013
    if (strdupFunc == NULL)
 
1014
        return(-1);
 
1015
    xmlFree = freeFunc;
 
1016
    xmlMalloc = mallocFunc;
 
1017
    xmlMallocAtomic = mallocFunc;
 
1018
    xmlRealloc = reallocFunc;
 
1019
    xmlMemStrdup = strdupFunc;
 
1020
#ifdef DEBUG_MEMORY
 
1021
     xmlGenericError(xmlGenericErrorContext,
 
1022
             "xmlMemSetup() Ok\n");
 
1023
#endif
 
1024
    return(0);
 
1025
}
 
1026
 
 
1027
/**
 
1028
 * xmlMemGet:
 
1029
 * @freeFunc: place to save the free() function in use
 
1030
 * @mallocFunc: place to save the malloc() function in use
 
1031
 * @reallocFunc: place to save the realloc() function in use
 
1032
 * @strdupFunc: place to save the strdup() function in use
 
1033
 *
 
1034
 * Provides the memory access functions set currently in use
 
1035
 *
 
1036
 * Returns 0 on success
 
1037
 */
 
1038
int
 
1039
xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
 
1040
          xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
 
1041
    if (freeFunc != NULL) *freeFunc = xmlFree;
 
1042
    if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
 
1043
    if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
 
1044
    if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
 
1045
    return(0);
 
1046
}
 
1047
 
 
1048
/**
 
1049
 * xmlGcMemSetup:
 
1050
 * @freeFunc: the free() function to use
 
1051
 * @mallocFunc: the malloc() function to use
 
1052
 * @mallocAtomicFunc: the malloc() function to use for atomic allocations
 
1053
 * @reallocFunc: the realloc() function to use
 
1054
 * @strdupFunc: the strdup() function to use
 
1055
 *
 
1056
 * Override the default memory access functions with a new set
 
1057
 * This has to be called before any other libxml routines !
 
1058
 * The mallocAtomicFunc is specialized for atomic block
 
1059
 * allocations (i.e. of areas  useful for garbage collected memory allocators
 
1060
 *
 
1061
 * Should this be blocked if there was already some allocations
 
1062
 * done ?
 
1063
 *
 
1064
 * Returns 0 on success
 
1065
 */
 
1066
int
 
1067
xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
 
1068
              xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
 
1069
              xmlStrdupFunc strdupFunc) {
 
1070
#ifdef DEBUG_MEMORY
 
1071
     xmlGenericError(xmlGenericErrorContext,
 
1072
             "xmlGcMemSetup()\n");
 
1073
#endif
 
1074
    if (freeFunc == NULL)
 
1075
        return(-1);
 
1076
    if (mallocFunc == NULL)
 
1077
        return(-1);
 
1078
    if (mallocAtomicFunc == NULL)
 
1079
        return(-1);
 
1080
    if (reallocFunc == NULL)
 
1081
        return(-1);
 
1082
    if (strdupFunc == NULL)
 
1083
        return(-1);
 
1084
    xmlFree = freeFunc;
 
1085
    xmlMalloc = mallocFunc;
 
1086
    xmlMallocAtomic = mallocAtomicFunc;
 
1087
    xmlRealloc = reallocFunc;
 
1088
    xmlMemStrdup = strdupFunc;
 
1089
#ifdef DEBUG_MEMORY
 
1090
     xmlGenericError(xmlGenericErrorContext,
 
1091
             "xmlGcMemSetup() Ok\n");
 
1092
#endif
 
1093
    return(0);
 
1094
}
 
1095
 
 
1096
/**
 
1097
 * xmlGcMemGet:
 
1098
 * @freeFunc: place to save the free() function in use
 
1099
 * @mallocFunc: place to save the malloc() function in use
 
1100
 * @mallocAtomicFunc: place to save the atomic malloc() function in use
 
1101
 * @reallocFunc: place to save the realloc() function in use
 
1102
 * @strdupFunc: place to save the strdup() function in use
 
1103
 *
 
1104
 * Provides the memory access functions set currently in use
 
1105
 * The mallocAtomicFunc is specialized for atomic block
 
1106
 * allocations (i.e. of areas  useful for garbage collected memory allocators
 
1107
 *
 
1108
 * Returns 0 on success
 
1109
 */
 
1110
int
 
1111
xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
 
1112
            xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc,
 
1113
            xmlStrdupFunc *strdupFunc) {
 
1114
    if (freeFunc != NULL) *freeFunc = xmlFree;
 
1115
    if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
 
1116
    if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic;
 
1117
    if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
 
1118
    if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
 
1119
    return(0);
 
1120
}
 
1121
 
 
1122
#define bottom_xmlmemory
 
1123
#include "elfgcchack.h"