Coverage Report

Created: 2025-11-02 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tinysparql/subprojects/libxml2-2.13.1/xmlmemory.c
Line
Count
Source
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
#include <stdlib.h>
12
#include <ctype.h>
13
#include <time.h>
14
15
#include <libxml/xmlmemory.h>
16
#include <libxml/xmlerror.h>
17
#include <libxml/parser.h>
18
#include <libxml/threads.h>
19
20
#include "private/memory.h"
21
#include "private/threads.h"
22
23
static unsigned long  debugMemSize = 0;
24
static unsigned long  debugMemBlocks = 0;
25
static xmlMutex xmlMemMutex;
26
27
/************************************************************************
28
 *                  *
29
 *    Macros, variables and associated types      *
30
 *                  *
31
 ************************************************************************/
32
33
/*
34
 * Each of the blocks allocated begin with a header containing information
35
 */
36
37
0
#define MEMTAG 0x5aa5U
38
39
typedef struct memnod {
40
    unsigned int   mh_tag;
41
    size_t         mh_size;
42
} MEMHDR;
43
44
#ifdef SUN4
45
#define ALIGN_SIZE  16
46
#else
47
0
#define ALIGN_SIZE  sizeof(double)
48
#endif
49
0
#define RESERVE_SIZE (((sizeof(MEMHDR) + ALIGN_SIZE - 1) \
50
0
          / ALIGN_SIZE ) * ALIGN_SIZE)
51
52
0
#define MAX_SIZE_T ((size_t)-1)
53
54
0
#define CLIENT_2_HDR(a) ((void *) (((char *) (a)) - RESERVE_SIZE))
55
0
#define HDR_2_CLIENT(a)    ((void *) (((char *) (a)) + RESERVE_SIZE))
56
57
/**
58
 * xmlMallocLoc:
59
 * @size:  an int specifying the size in byte to allocate.
60
 * @file:  the file name or NULL
61
 * @line:  the line number
62
 *
63
 * DEPRECATED: don't use
64
 *
65
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
66
 */
67
void *
68
xmlMallocLoc(size_t size, const char *file ATTRIBUTE_UNUSED,
69
             int line ATTRIBUTE_UNUSED)
70
0
{
71
0
    return(xmlMemMalloc(size));
72
0
}
73
74
/**
75
 * xmlMallocAtomicLoc:
76
 * @size:  an unsigned int specifying the size in byte to allocate.
77
 * @file:  the file name or NULL
78
 * @line:  the line number
79
 *
80
 * DEPRECATED: don't use
81
 *
82
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
83
 */
84
void *
85
xmlMallocAtomicLoc(size_t size, const char *file ATTRIBUTE_UNUSED,
86
                   int line ATTRIBUTE_UNUSED)
87
0
{
88
0
    return(xmlMemMalloc(size));
89
0
}
90
91
/**
92
 * xmlMemMalloc:
93
 * @size:  an int specifying the size in byte to allocate.
94
 *
95
 * a malloc() equivalent, with logging of the allocation info.
96
 *
97
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
98
 */
99
void *
100
xmlMemMalloc(size_t size)
101
0
{
102
0
    MEMHDR *p;
103
104
0
    xmlInitParser();
105
106
0
    if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
107
0
        fprintf(stderr, "xmlMemMalloc: Unsigned overflow\n");
108
0
        return(NULL);
109
0
    }
110
111
0
    p = (MEMHDR *) malloc(RESERVE_SIZE + size);
112
0
    if (!p) {
113
0
        fprintf(stderr, "xmlMemMalloc: Out of memory\n");
114
0
        return(NULL);
115
0
    }
116
0
    p->mh_tag = MEMTAG;
117
0
    p->mh_size = size;
118
119
0
    xmlMutexLock(&xmlMemMutex);
120
0
    debugMemSize += size;
121
0
    debugMemBlocks++;
122
0
    xmlMutexUnlock(&xmlMemMutex);
123
124
0
    return(HDR_2_CLIENT(p));
125
0
}
126
127
/**
128
 * xmlReallocLoc:
129
 * @ptr:  the initial memory block pointer
130
 * @size:  an int specifying the size in byte to allocate.
131
 * @file:  the file name or NULL
132
 * @line:  the line number
133
 *
134
 * DEPRECATED: don't use
135
 *
136
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
137
 */
138
void *
139
xmlReallocLoc(void *ptr, size_t size, const char *file ATTRIBUTE_UNUSED,
140
              int line ATTRIBUTE_UNUSED)
141
0
{
142
0
    return(xmlMemRealloc(ptr, size));
143
0
}
144
145
/**
146
 * xmlMemRealloc:
147
 * @ptr:  the initial memory block pointer
148
 * @size:  an int specifying the size in byte to allocate.
149
 *
150
 * a realloc() equivalent, with logging of the allocation info.
151
 *
152
 * Returns a pointer to the allocated area or NULL in case of lack of memory.
153
 */
154
void *
155
0
xmlMemRealloc(void *ptr, size_t size) {
156
0
    MEMHDR *p, *tmp;
157
0
    size_t oldSize;
158
159
0
    if (ptr == NULL)
160
0
        return(xmlMemMalloc(size));
161
162
0
    xmlInitParser();
163
164
0
    if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
165
0
        fprintf(stderr, "xmlMemRealloc: Unsigned overflow\n");
166
0
        return(NULL);
167
0
    }
168
169
0
    p = CLIENT_2_HDR(ptr);
170
0
    if (p->mh_tag != MEMTAG) {
171
0
        fprintf(stderr, "xmlMemRealloc: Tag error\n");
172
0
        return(NULL);
173
0
    }
174
0
    oldSize = p->mh_size;
175
0
    p->mh_tag = ~MEMTAG;
176
177
0
    tmp = (MEMHDR *) realloc(p, RESERVE_SIZE + size);
178
0
    if (!tmp) {
179
0
        p->mh_tag = MEMTAG;
180
0
        fprintf(stderr, "xmlMemRealloc: Out of memory\n");
181
0
        return(NULL);
182
0
    }
183
0
    p = tmp;
184
0
    p->mh_tag = MEMTAG;
185
0
    p->mh_size = size;
186
187
0
    xmlMutexLock(&xmlMemMutex);
188
0
    debugMemSize -= oldSize;
189
0
    debugMemSize += size;
190
0
    xmlMutexUnlock(&xmlMemMutex);
191
192
0
    return(HDR_2_CLIENT(p));
193
0
}
194
195
/**
196
 * xmlMemFree:
197
 * @ptr:  the memory block pointer
198
 *
199
 * a free() equivalent, with error checking.
200
 */
201
void
202
xmlMemFree(void *ptr)
203
0
{
204
0
    MEMHDR *p;
205
206
0
    if (ptr == NULL)
207
0
        return;
208
209
0
    if (ptr == (void *) -1) {
210
0
        fprintf(stderr, "xmlMemFree: Pointer from freed area\n");
211
0
        return;
212
0
    }
213
214
0
    p = CLIENT_2_HDR(ptr);
215
0
    if (p->mh_tag != MEMTAG) {
216
0
        fprintf(stderr, "xmlMemFree: Tag error\n");
217
0
        return;
218
0
    }
219
0
    p->mh_tag = ~MEMTAG;
220
0
    memset(ptr, -1, p->mh_size);
221
222
0
    xmlMutexLock(&xmlMemMutex);
223
0
    debugMemSize -= p->mh_size;
224
0
    debugMemBlocks--;
225
0
    xmlMutexUnlock(&xmlMemMutex);
226
227
0
    free(p);
228
229
0
    return;
230
0
}
231
232
/**
233
 * xmlMemStrdupLoc:
234
 * @str:  the initial string pointer
235
 * @file:  the file name or NULL
236
 * @line:  the line number
237
 *
238
 * DEPRECATED: don't use
239
 *
240
 * Returns a pointer to the new string or NULL if allocation error occurred.
241
 */
242
char *
243
xmlMemStrdupLoc(const char *str, const char *file ATTRIBUTE_UNUSED,
244
                int line ATTRIBUTE_UNUSED)
245
0
{
246
0
    return(xmlMemoryStrdup(str));
247
0
}
248
249
/**
250
 * xmlMemoryStrdup:
251
 * @str:  the initial string pointer
252
 *
253
 * a strdup() equivalent, with logging of the allocation info.
254
 *
255
 * Returns a pointer to the new string or NULL if allocation error occurred.
256
 */
257
char *
258
0
xmlMemoryStrdup(const char *str) {
259
0
    char *s;
260
0
    size_t size = strlen(str) + 1;
261
0
    MEMHDR *p;
262
263
0
    xmlInitParser();
264
265
0
    if (size > (MAX_SIZE_T - RESERVE_SIZE)) {
266
0
        fprintf(stderr, "xmlMemoryStrdup: Unsigned overflow\n");
267
0
        return(NULL);
268
0
    }
269
270
0
    p = (MEMHDR *) malloc(RESERVE_SIZE + size);
271
0
    if (!p) {
272
0
        fprintf(stderr, "xmlMemoryStrdup: Out of memory\n");
273
0
        return(NULL);
274
0
    }
275
0
    p->mh_tag = MEMTAG;
276
0
    p->mh_size = size;
277
278
0
    xmlMutexLock(&xmlMemMutex);
279
0
    debugMemSize += size;
280
0
    debugMemBlocks++;
281
0
    xmlMutexUnlock(&xmlMemMutex);
282
283
0
    s = (char *) HDR_2_CLIENT(p);
284
285
0
    memcpy(s, str, size);
286
287
0
    return(s);
288
0
}
289
290
/**
291
 * xmlMemSize:
292
 * @ptr:  pointer to the memory allocation
293
 *
294
 * Returns the size of a memory allocation.
295
 */
296
297
size_t
298
0
xmlMemSize(void *ptr) {
299
0
    MEMHDR *p;
300
301
0
    if (ptr == NULL)
302
0
  return(0);
303
304
0
    p = CLIENT_2_HDR(ptr);
305
0
    if (p->mh_tag != MEMTAG)
306
0
        return(0);
307
308
0
    return(p->mh_size);
309
0
}
310
311
/**
312
 * xmlMemUsed:
313
 *
314
 * Provides the amount of memory currently allocated
315
 *
316
 * Returns an int representing the amount of memory allocated.
317
 */
318
319
int
320
0
xmlMemUsed(void) {
321
0
    return(debugMemSize);
322
0
}
323
324
/**
325
 * xmlMemBlocks:
326
 *
327
 * Provides the number of memory areas currently allocated
328
 *
329
 * Returns an int representing the number of blocks
330
 */
331
332
int
333
0
xmlMemBlocks(void) {
334
0
    int res;
335
336
0
    xmlMutexLock(&xmlMemMutex);
337
0
    res = debugMemBlocks;
338
0
    xmlMutexUnlock(&xmlMemMutex);
339
0
    return(res);
340
0
}
341
342
/**
343
 * xmlMemDisplayLast:
344
 * @fp:  a FILE descriptor
345
 * @nbBytes: the amount of memory to dump
346
 *
347
 * DEPRECATED: This feature was removed.
348
 */
349
void
350
xmlMemDisplayLast(FILE *fp ATTRIBUTE_UNUSED, long nbBytes ATTRIBUTE_UNUSED)
351
0
{
352
0
}
353
354
/**
355
 * xmlMemDisplay:
356
 * @fp:  a FILE descriptor
357
 *
358
 * DEPRECATED: This feature was removed.
359
 */
360
void
361
xmlMemDisplay(FILE *fp ATTRIBUTE_UNUSED)
362
0
{
363
0
}
364
365
/**
366
 * xmlMemShow:
367
 * @fp:  a FILE descriptor
368
 * @nr:  number of entries to dump
369
 *
370
 * DEPRECATED: This feature was removed.
371
 */
372
void
373
xmlMemShow(FILE *fp ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED)
374
0
{
375
0
}
376
377
/**
378
 * xmlMemoryDump:
379
 *
380
 * DEPRECATED: This feature was removed.
381
 */
382
void
383
xmlMemoryDump(void)
384
0
{
385
0
}
386
387
388
/****************************************************************
389
 *                *
390
 *    Initialization Routines       *
391
 *                *
392
 ****************************************************************/
393
394
/**
395
 * xmlInitMemory:
396
 *
397
 * DEPRECATED: Alias for xmlInitParser.
398
 *
399
 * Returns 0.
400
 */
401
int
402
0
xmlInitMemory(void) {
403
0
    xmlInitParser();
404
0
    return(0);
405
0
}
406
407
/**
408
 * xmlInitMemoryInternal:
409
 *
410
 * Initialize the memory layer.
411
 */
412
void
413
0
xmlInitMemoryInternal(void) {
414
0
    xmlInitMutex(&xmlMemMutex);
415
0
}
416
417
/**
418
 * xmlCleanupMemory:
419
 *
420
 * DEPRECATED: This function is a no-op. Call xmlCleanupParser
421
 * to free global state but see the warnings there. xmlCleanupParser
422
 * should be only called once at program exit. In most cases, you don't
423
 * have call cleanup functions at all.
424
 */
425
void
426
0
xmlCleanupMemory(void) {
427
0
}
428
429
/**
430
 * xmlCleanupMemoryInternal:
431
 *
432
 * Free up all the memory allocated by the library for its own
433
 * use. This should not be called by user level code.
434
 */
435
void
436
0
xmlCleanupMemoryInternal(void) {
437
    /*
438
     * Don't clean up mutex on Windows. Global state destructors can call
439
     * malloc functions after xmlCleanupParser was called. If memory
440
     * debugging is enabled, xmlMemMutex can be used after cleanup.
441
     *
442
     * See python/tests/thread2.py
443
     */
444
0
#if !defined(LIBXML_THREAD_ENABLED) || !defined(_WIN32)
445
0
    xmlCleanupMutex(&xmlMemMutex);
446
0
#endif
447
0
}
448
449
/**
450
 * xmlMemSetup:
451
 * @freeFunc: the free() function to use
452
 * @mallocFunc: the malloc() function to use
453
 * @reallocFunc: the realloc() function to use
454
 * @strdupFunc: the strdup() function to use
455
 *
456
 * Override the default memory access functions with a new set
457
 * This has to be called before any other libxml routines !
458
 *
459
 * Should this be blocked if there was already some allocations
460
 * done ?
461
 *
462
 * Returns 0 on success
463
 */
464
int
465
xmlMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
466
0
            xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc) {
467
0
    if (freeFunc == NULL)
468
0
  return(-1);
469
0
    if (mallocFunc == NULL)
470
0
  return(-1);
471
0
    if (reallocFunc == NULL)
472
0
  return(-1);
473
0
    if (strdupFunc == NULL)
474
0
  return(-1);
475
0
    xmlFree = freeFunc;
476
0
    xmlMalloc = mallocFunc;
477
0
    xmlMallocAtomic = mallocFunc;
478
0
    xmlRealloc = reallocFunc;
479
0
    xmlMemStrdup = strdupFunc;
480
0
    return(0);
481
0
}
482
483
/**
484
 * xmlMemGet:
485
 * @freeFunc: place to save the free() function in use
486
 * @mallocFunc: place to save the malloc() function in use
487
 * @reallocFunc: place to save the realloc() function in use
488
 * @strdupFunc: place to save the strdup() function in use
489
 *
490
 * Provides the memory access functions set currently in use
491
 *
492
 * Returns 0 on success
493
 */
494
int
495
xmlMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
496
0
    xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc) {
497
0
    if (freeFunc != NULL) *freeFunc = xmlFree;
498
0
    if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
499
0
    if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
500
0
    if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
501
0
    return(0);
502
0
}
503
504
/**
505
 * xmlGcMemSetup:
506
 * @freeFunc: the free() function to use
507
 * @mallocFunc: the malloc() function to use
508
 * @mallocAtomicFunc: the malloc() function to use for atomic allocations
509
 * @reallocFunc: the realloc() function to use
510
 * @strdupFunc: the strdup() function to use
511
 *
512
 * Override the default memory access functions with a new set
513
 * This has to be called before any other libxml routines !
514
 * The mallocAtomicFunc is specialized for atomic block
515
 * allocations (i.e. of areas  useful for garbage collected memory allocators
516
 *
517
 * Should this be blocked if there was already some allocations
518
 * done ?
519
 *
520
 * Returns 0 on success
521
 */
522
int
523
xmlGcMemSetup(xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc,
524
              xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc,
525
0
        xmlStrdupFunc strdupFunc) {
526
0
    if (freeFunc == NULL)
527
0
  return(-1);
528
0
    if (mallocFunc == NULL)
529
0
  return(-1);
530
0
    if (mallocAtomicFunc == NULL)
531
0
  return(-1);
532
0
    if (reallocFunc == NULL)
533
0
  return(-1);
534
0
    if (strdupFunc == NULL)
535
0
  return(-1);
536
0
    xmlFree = freeFunc;
537
0
    xmlMalloc = mallocFunc;
538
0
    xmlMallocAtomic = mallocAtomicFunc;
539
0
    xmlRealloc = reallocFunc;
540
0
    xmlMemStrdup = strdupFunc;
541
0
    return(0);
542
0
}
543
544
/**
545
 * xmlGcMemGet:
546
 * @freeFunc: place to save the free() function in use
547
 * @mallocFunc: place to save the malloc() function in use
548
 * @mallocAtomicFunc: place to save the atomic malloc() function in use
549
 * @reallocFunc: place to save the realloc() function in use
550
 * @strdupFunc: place to save the strdup() function in use
551
 *
552
 * Provides the memory access functions set currently in use
553
 * The mallocAtomicFunc is specialized for atomic block
554
 * allocations (i.e. of areas  useful for garbage collected memory allocators
555
 *
556
 * Returns 0 on success
557
 */
558
int
559
xmlGcMemGet(xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc,
560
            xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc,
561
0
      xmlStrdupFunc *strdupFunc) {
562
0
    if (freeFunc != NULL) *freeFunc = xmlFree;
563
0
    if (mallocFunc != NULL) *mallocFunc = xmlMalloc;
564
0
    if (mallocAtomicFunc != NULL) *mallocAtomicFunc = xmlMallocAtomic;
565
0
    if (reallocFunc != NULL) *reallocFunc = xmlRealloc;
566
0
    if (strdupFunc != NULL) *strdupFunc = xmlMemStrdup;
567
0
    return(0);
568
0
}
569