Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/libxml2/globals.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * globals.c: definition and handling of the set of global variables
3
 *            of the library
4
 *
5
 * See Copyright for the status of this software.
6
 *
7
 * Gary Pennington <Gary.Pennington@uk.sun.com>
8
 * daniel@veillard.com
9
 */
10
11
#define IN_LIBXML
12
#include "libxml.h"
13
14
#include <stdlib.h>
15
#include <string.h>
16
17
#define XML_GLOBALS_NO_REDEFINITION
18
#include <libxml/xmlerror.h>
19
#include <libxml/xmlmemory.h>
20
#include <libxml/xmlIO.h>
21
#include <libxml/parser.h>
22
#include <libxml/threads.h>
23
#include <libxml/tree.h>
24
#include <libxml/xmlsave.h>
25
#include <libxml/SAX2.h>
26
27
#include "private/dict.h"
28
#include "private/error.h"
29
#include "private/globals.h"
30
#include "private/threads.h"
31
#include "private/tree.h"
32
33
/*
34
 * Mutex to protect "ForNewThreads" variables
35
 */
36
static xmlMutex xmlThrDefMutex;
37
38
/*
39
 * Thread-local storage emulation.
40
 *
41
 * This works by replacing a global variable
42
 *
43
 *     extern xmlError xmlLastError;
44
 *
45
 * with a macro that calls a function returning a pointer to the global in
46
 * thread-local storage:
47
 *
48
 *     xmlError *__xmlLastError(void);
49
 *     #define xmlError (*__xmlLastError());
50
 *
51
 * The code can operate in a multitude of ways depending on the environment.
52
 * First we support POSIX and Windows threads. Then we support both
53
 * thread-local storage provided by the compiler and older methods like
54
 * thread-specific data (pthreads) or TlsAlloc (Windows).
55
 *
56
 * To clean up thread-local storage, we use thread-specific data on POSIX.
57
 * On Windows, we either use DllMain when compiling a DLL or a registered
58
 * wait function for static builds.
59
 *
60
 * Compiler TLS isn't really useful for now. It can make allocation more
61
 * robust on some platforms but it also increases the memory consumption
62
 * of each thread by ~250 bytes whether it uses libxml2 or not. The main
63
 * problem is that we have to deallocate strings in xmlLastError and C
64
 * offers no simple way to deallocate dynamic data in _Thread_local
65
 * variables. In C++, one could simply use a thread_local variable with a
66
 * destructor.
67
 *
68
 * At some point, many of the deprecated globals can be removed,
69
 * although things like global error handlers will take a while.
70
 * Ultimately, the only crucial things seem to be xmlLastError and
71
 * RNG state. xmlLastError already involves dynamic allocation, so it
72
 * could be allocated dynamically as well, only storing a global
73
 * pointer.
74
 */
75
76
#ifdef LIBXML_THREAD_ENABLED
77
78
#ifdef HAVE_WIN32_THREADS
79
  #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
80
    #define USE_WAIT_DTOR
81
  #else
82
    #define USE_DLL_MAIN
83
  #endif
84
#endif
85
86
/*
87
 * On Darwin, thread-local storage destructors seem to be run before
88
 * pthread thread-specific data destructors. This causes ASan to
89
 * report a use-after-free.
90
 *
91
 * On Windows, we can't use TLS in static builds. The RegisterWait
92
 * callback would run after TLS was deallocated.
93
 */
94
#if defined(XML_THREAD_LOCAL) && \
95
    !defined(__APPLE__) && \
96
    !defined(USE_WAIT_DTOR)
97
#define USE_TLS
98
#endif
99
100
#ifdef HAVE_POSIX_THREADS
101
102
/*
103
 * On POSIX, we need thread-specific data even with thread-local storage
104
 * to destroy indirect references from global state (xmlLastError) at
105
 * thread exit.
106
 */
107
static pthread_key_t globalkey;
108
109
#elif defined HAVE_WIN32_THREADS
110
111
#ifndef USE_TLS
112
static DWORD globalkey = TLS_OUT_OF_INDEXES;
113
#endif
114
115
#endif /* HAVE_WIN32_THREADS */
116
117
static void
118
xmlFreeGlobalState(void *state);
119
120
#endif /* LIBXML_THREAD_ENABLED */
121
122
struct _xmlGlobalState {
123
#ifdef USE_TLS
124
    int initialized;
125
#endif
126
127
#ifdef USE_WAIT_DTOR
128
    void *threadHandle;
129
    void *waitHandle;
130
#endif
131
132
    unsigned localRngState[2];
133
134
    xmlError lastError;
135
136
#ifdef LIBXML_THREAD_ALLOC_ENABLED
137
    xmlMallocFunc malloc;
138
    xmlMallocFunc mallocAtomic;
139
    xmlReallocFunc realloc;
140
    xmlFreeFunc free;
141
    xmlStrdupFunc memStrdup;
142
#endif
143
144
    int doValidityCheckingDefaultValue;
145
    int getWarningsDefaultValue;
146
    int keepBlanksDefaultValue;
147
    int lineNumbersDefaultValue;
148
    int loadExtDtdDefaultValue;
149
    int pedanticParserDefaultValue;
150
    int substituteEntitiesDefaultValue;
151
152
#ifdef LIBXML_OUTPUT_ENABLED
153
    int indentTreeOutput;
154
    const char *treeIndentString;
155
    int saveNoEmptyTags;
156
#endif
157
158
    xmlGenericErrorFunc genericError;
159
    void *genericErrorContext;
160
    xmlStructuredErrorFunc structuredError;
161
    void *structuredErrorContext;
162
163
    xmlRegisterNodeFunc registerNodeDefaultValue;
164
    xmlDeregisterNodeFunc deregisterNodeDefaultValue;
165
166
    xmlParserInputBufferCreateFilenameFunc parserInputBufferCreateFilenameValue;
167
    xmlOutputBufferCreateFilenameFunc outputBufferCreateFilenameValue;
168
};
169
170
typedef struct _xmlGlobalState xmlGlobalState;
171
typedef xmlGlobalState *xmlGlobalStatePtr;
172
173
#ifdef LIBXML_THREAD_ENABLED
174
175
#ifdef USE_TLS
176
static XML_THREAD_LOCAL xmlGlobalState globalState;
177
#endif
178
179
#else /* LIBXML_THREAD_ENABLED */
180
181
static xmlGlobalState globalState;
182
183
#endif /* LIBXML_THREAD_ENABLED */
184
185
/************************************************************************
186
 *                  *
187
 *  All the user accessible global variables of the library   *
188
 *                  *
189
 ************************************************************************/
190
191
/*
192
 * Memory allocation routines
193
 */
194
195
/**
196
 * xmlFree:
197
 * @mem: an already allocated block of memory
198
 *
199
 * The variable holding the libxml free() implementation
200
 */
201
xmlFreeFunc xmlFree = free;
202
/**
203
 * xmlMalloc:
204
 * @size:  the size requested in bytes
205
 *
206
 * The variable holding the libxml malloc() implementation
207
 *
208
 * Returns a pointer to the newly allocated block or NULL in case of error
209
 */
210
xmlMallocFunc xmlMalloc = malloc;
211
/**
212
 * xmlMallocAtomic:
213
 * @size:  the size requested in bytes
214
 *
215
 * The variable holding the libxml malloc() implementation for atomic
216
 * data (i.e. blocks not containing pointers), useful when using a
217
 * garbage collecting allocator.
218
 *
219
 * Returns a pointer to the newly allocated block or NULL in case of error
220
 */
221
xmlMallocFunc xmlMallocAtomic = malloc;
222
/**
223
 * xmlRealloc:
224
 * @mem: an already allocated block of memory
225
 * @size:  the new size requested in bytes
226
 *
227
 * The variable holding the libxml realloc() implementation
228
 *
229
 * Returns a pointer to the newly reallocated block or NULL in case of error
230
 */
231
xmlReallocFunc xmlRealloc = realloc;
232
/**
233
 * xmlPosixStrdup
234
 * @cur:  the input char *
235
 *
236
 * a strdup implementation with a type signature matching POSIX
237
 *
238
 * Returns a new xmlChar * or NULL
239
 */
240
static char *
241
0
xmlPosixStrdup(const char *cur) {
242
0
    return((char*) xmlCharStrdup(cur));
243
0
}
244
/**
245
 * xmlMemStrdup:
246
 * @str: a zero terminated string
247
 *
248
 * The variable holding the libxml strdup() implementation
249
 *
250
 * Returns the copy of the string or NULL in case of error
251
 */
252
xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup;
253
254
/*
255
 * Parser defaults
256
 */
257
258
static int xmlDoValidityCheckingDefaultValueThrDef = 0;
259
static int xmlGetWarningsDefaultValueThrDef = 1;
260
static int xmlLoadExtDtdDefaultValueThrDef = 0;
261
static int xmlPedanticParserDefaultValueThrDef = 0;
262
static int xmlLineNumbersDefaultValueThrDef = 0;
263
static int xmlKeepBlanksDefaultValueThrDef = 1;
264
static int xmlSubstituteEntitiesDefaultValueThrDef = 0;
265
266
static xmlRegisterNodeFunc xmlRegisterNodeDefaultValueThrDef = NULL;
267
static xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValueThrDef = NULL;
268
269
static xmlParserInputBufferCreateFilenameFunc
270
xmlParserInputBufferCreateFilenameValueThrDef = NULL;
271
static xmlOutputBufferCreateFilenameFunc
272
xmlOutputBufferCreateFilenameValueThrDef = NULL;
273
274
static xmlGenericErrorFunc xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
275
static xmlStructuredErrorFunc xmlStructuredErrorThrDef = NULL;
276
static void *xmlGenericErrorContextThrDef = NULL;
277
static void *xmlStructuredErrorContextThrDef = NULL;
278
279
#ifdef LIBXML_OUTPUT_ENABLED
280
static int xmlIndentTreeOutputThrDef = 1;
281
static const char *xmlTreeIndentStringThrDef = "  ";
282
static int xmlSaveNoEmptyTagsThrDef = 0;
283
#endif /* LIBXML_OUTPUT_ENABLED */
284
285
#ifdef LIBXML_SAX1_ENABLED
286
/**
287
 * xmlDefaultSAXHandler:
288
 *
289
 * DEPRECATED: This handler is unused and will be removed from future
290
 * versions.
291
 *
292
 * Default SAX version1 handler for XML, builds the DOM tree
293
 */
294
const xmlSAXHandlerV1 xmlDefaultSAXHandler = {
295
    xmlSAX2InternalSubset,
296
    xmlSAX2IsStandalone,
297
    xmlSAX2HasInternalSubset,
298
    xmlSAX2HasExternalSubset,
299
    xmlSAX2ResolveEntity,
300
    xmlSAX2GetEntity,
301
    xmlSAX2EntityDecl,
302
    xmlSAX2NotationDecl,
303
    xmlSAX2AttributeDecl,
304
    xmlSAX2ElementDecl,
305
    xmlSAX2UnparsedEntityDecl,
306
    xmlSAX2SetDocumentLocator,
307
    xmlSAX2StartDocument,
308
    xmlSAX2EndDocument,
309
    xmlSAX2StartElement,
310
    xmlSAX2EndElement,
311
    xmlSAX2Reference,
312
    xmlSAX2Characters,
313
    xmlSAX2Characters,
314
    xmlSAX2ProcessingInstruction,
315
    xmlSAX2Comment,
316
    xmlParserWarning,
317
    xmlParserError,
318
    xmlParserError,
319
    xmlSAX2GetParameterEntity,
320
    xmlSAX2CDataBlock,
321
    xmlSAX2ExternalSubset,
322
    1,
323
};
324
#endif /* LIBXML_SAX1_ENABLED */
325
326
/**
327
 * xmlDefaultSAXLocator:
328
 *
329
 * DEPRECATED: Don't use
330
 *
331
 * The default SAX Locator
332
 * { getPublicId, getSystemId, getLineNumber, getColumnNumber}
333
 */
334
const xmlSAXLocator xmlDefaultSAXLocator = {
335
    xmlSAX2GetPublicId,
336
    xmlSAX2GetSystemId,
337
    xmlSAX2GetLineNumber,
338
    xmlSAX2GetColumnNumber
339
};
340
341
#if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_SAX1_ENABLED)
342
/**
343
 * htmlDefaultSAXHandler:
344
 *
345
 * DEPRECATED: This handler is unused and will be removed from future
346
 * versions.
347
 *
348
 * Default old SAX v1 handler for HTML, builds the DOM tree
349
 */
350
const xmlSAXHandlerV1 htmlDefaultSAXHandler = {
351
    xmlSAX2InternalSubset,
352
    NULL,
353
    NULL,
354
    NULL,
355
    NULL,
356
    xmlSAX2GetEntity,
357
    NULL,
358
    NULL,
359
    NULL,
360
    NULL,
361
    NULL,
362
    xmlSAX2SetDocumentLocator,
363
    xmlSAX2StartDocument,
364
    xmlSAX2EndDocument,
365
    xmlSAX2StartElement,
366
    xmlSAX2EndElement,
367
    NULL,
368
    xmlSAX2Characters,
369
    xmlSAX2IgnorableWhitespace,
370
    xmlSAX2ProcessingInstruction,
371
    xmlSAX2Comment,
372
    xmlParserWarning,
373
    xmlParserError,
374
    xmlParserError,
375
    NULL,
376
    xmlSAX2CDataBlock,
377
    NULL,
378
    1,
379
};
380
#endif /* LIBXML_HTML_ENABLED */
381
382
static void
383
xmlInitGlobalState(xmlGlobalStatePtr gs);
384
385
/************************************************************************
386
 *                  *
387
 *      Per thread global state handling    *
388
 *                  *
389
 ************************************************************************/
390
391
/**
392
 * xmlInitGlobals:
393
 *
394
 * DEPRECATED: Alias for xmlInitParser.
395
 */
396
0
void xmlInitGlobals(void) {
397
0
    xmlInitParser();
398
0
}
399
400
/**
401
 * xmlInitGlobalsInternal:
402
 *
403
 * Additional initialisation for multi-threading
404
 */
405
18
void xmlInitGlobalsInternal(void) {
406
18
    xmlInitMutex(&xmlThrDefMutex);
407
408
18
#ifdef HAVE_POSIX_THREADS
409
18
    pthread_key_create(&globalkey, xmlFreeGlobalState);
410
#elif defined(HAVE_WIN32_THREADS)
411
#ifndef USE_TLS
412
    if (globalkey == TLS_OUT_OF_INDEXES)
413
        globalkey = TlsAlloc();
414
#endif
415
#else /* no thread support */
416
    xmlInitGlobalState(&globalState);
417
#endif
418
18
}
419
420
/**
421
 * xmlCleanupGlobals:
422
 *
423
 * DEPRECATED: This function is a no-op. Call xmlCleanupParser
424
 * to free global state but see the warnings there. xmlCleanupParser
425
 * should be only called once at program exit. In most cases, you don't
426
 * have call cleanup functions at all.
427
 */
428
0
void xmlCleanupGlobals(void) {
429
0
}
430
431
/**
432
 * xmlCleanupGlobalsInternal:
433
 *
434
 * Additional cleanup for multi-threading
435
 */
436
0
void xmlCleanupGlobalsInternal(void) {
437
    /*
438
     * We assume that all other threads using the library have
439
     * terminated and the last remaining thread calls
440
     * xmlCleanupParser.
441
     */
442
443
0
#ifdef HAVE_POSIX_THREADS
444
    /*
445
     * Free thread-specific data of last thread before calling
446
     * pthread_key_delete.
447
     */
448
0
    xmlGlobalState *gs = pthread_getspecific(globalkey);
449
0
    if (gs != NULL)
450
0
        xmlFreeGlobalState(gs);
451
0
    pthread_key_delete(globalkey);
452
#elif defined(HAVE_WIN32_THREADS)
453
#if defined(USE_WAIT_DTOR) && !defined(USE_TLS)
454
    if (globalkey != TLS_OUT_OF_INDEXES) {
455
        TlsFree(globalkey);
456
        globalkey = TLS_OUT_OF_INDEXES;
457
    }
458
#endif
459
#else /* no thread support */
460
    xmlResetError(&globalState.lastError);
461
#endif
462
463
0
    xmlCleanupMutex(&xmlThrDefMutex);
464
0
}
465
466
#ifdef LIBXML_THREAD_ENABLED
467
468
static void
469
xmlFreeGlobalState(void *state)
470
8.74k
{
471
8.74k
    xmlGlobalState *gs = (xmlGlobalState *) state;
472
473
    /*
474
     * Free any memory allocated in the thread's error struct. If it
475
     * weren't for this indirect allocation, we wouldn't need
476
     * a destructor with thread-local storage at all!
477
     */
478
8.74k
    xmlResetError(&gs->lastError);
479
8.74k
#ifndef USE_TLS
480
8.74k
    free(state);
481
8.74k
#endif
482
8.74k
}
483
484
#if defined(USE_WAIT_DTOR)
485
static void WINAPI
486
xmlGlobalStateDtor(void *ctxt, unsigned char timedOut ATTRIBUTE_UNUSED) {
487
    xmlGlobalStatePtr gs = ctxt;
488
489
    UnregisterWait(gs->waitHandle);
490
    CloseHandle(gs->threadHandle);
491
    xmlFreeGlobalState(gs);
492
}
493
494
static int
495
xmlRegisterGlobalStateDtor(xmlGlobalState *gs) {
496
    void *processHandle = GetCurrentProcess();
497
    void *threadHandle;
498
    void *waitHandle;
499
500
    if (DuplicateHandle(processHandle, GetCurrentThread(), processHandle,
501
                &threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {
502
        return(-1);
503
    }
504
505
    if (RegisterWaitForSingleObject(&waitHandle, threadHandle,
506
                xmlGlobalStateDtor, gs, INFINITE, WT_EXECUTEONLYONCE) == 0) {
507
        CloseHandle(threadHandle);
508
        return(-1);
509
    }
510
511
    gs->threadHandle = threadHandle;
512
    gs->waitHandle = waitHandle;
513
    return(0);
514
}
515
#endif /* USE_WAIT_DTOR */
516
517
#ifndef USE_TLS
518
/**
519
 * xmlNewGlobalState:
520
 *
521
 * xmlNewGlobalState() allocates a global state. This structure is used to
522
 * hold all data for use by a thread when supporting backwards compatibility
523
 * of libxml2 to pre-thread-safe behaviour.
524
 *
525
 * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
526
 */
527
static xmlGlobalStatePtr
528
xmlNewGlobalState(int allowFailure)
529
8.75k
{
530
8.75k
    xmlGlobalState *gs;
531
532
    /*
533
     * We use malloc/free to allow accessing globals before setting
534
     * custom memory allocators.
535
     */
536
8.75k
    gs = malloc(sizeof(xmlGlobalState));
537
8.75k
    if (gs == NULL) {
538
0
        if (allowFailure)
539
0
            return(NULL);
540
541
        /*
542
         * If an application didn't call xmlCheckThreadLocalStorage to make
543
         * sure that global state could be allocated, it's too late to
544
         * handle the error.
545
         */
546
0
        xmlAbort("libxml2: Failed to allocate globals for thread\n"
547
0
                 "libxml2: See xmlCheckThreadLocalStorage\n");
548
0
    }
549
550
8.75k
    memset(gs, 0, sizeof(xmlGlobalState));
551
8.75k
    xmlInitGlobalState(gs);
552
8.75k
    return (gs);
553
8.75k
}
554
#endif
555
556
static xmlGlobalStatePtr
557
8.01M
xmlGetThreadLocalStorage(int allowFailure) {
558
8.01M
    xmlGlobalState *gs;
559
560
8.01M
    (void) allowFailure;
561
562
8.01M
    xmlInitParser();
563
564
#ifdef USE_TLS
565
    gs = &globalState;
566
    if (gs->initialized == 0)
567
        xmlInitGlobalState(gs);
568
#elif defined(HAVE_POSIX_THREADS)
569
    gs = (xmlGlobalState *) pthread_getspecific(globalkey);
570
8.01M
    if (gs == NULL)
571
8.75k
        gs = xmlNewGlobalState(allowFailure);
572
#elif defined(HAVE_WIN32_THREADS)
573
    gs = (xmlGlobalState *) TlsGetValue(globalkey);
574
    if (gs == NULL)
575
        gs = xmlNewGlobalState(allowFailure);
576
#else
577
    gs = NULL;
578
#endif
579
580
8.01M
    return(gs);
581
8.01M
}
582
583
#else /* LIBXML_THREAD_ENABLED */
584
585
static xmlGlobalStatePtr
586
xmlGetThreadLocalStorage(int allowFailure ATTRIBUTE_UNUSED) {
587
    return(&globalState);
588
}
589
590
#endif /* LIBXML_THREAD_ENABLED */
591
592
static void
593
8.75k
xmlInitGlobalState(xmlGlobalStatePtr gs) {
594
8.75k
    gs->localRngState[0] = xmlGlobalRandom();
595
8.75k
    gs->localRngState[1] = xmlGlobalRandom();
596
597
8.75k
    memset(&gs->lastError, 0, sizeof(xmlError));
598
599
#ifdef LIBXML_THREAD_ALLOC_ENABLED
600
    /* XML_GLOBALS_ALLOC */
601
    gs->free = free;
602
    gs->malloc = malloc;
603
    gs->mallocAtomic = malloc;
604
    gs->realloc = realloc;
605
    gs->memStrdup = xmlPosixStrdup;
606
#endif
607
608
8.75k
    xmlMutexLock(&xmlThrDefMutex);
609
610
    /* XML_GLOBALS_PARSER */
611
8.75k
    gs->doValidityCheckingDefaultValue =
612
8.75k
         xmlDoValidityCheckingDefaultValueThrDef;
613
8.75k
    gs->getWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
614
8.75k
    gs->keepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
615
8.75k
    gs->lineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
616
8.75k
    gs->loadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
617
8.75k
    gs->pedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
618
8.75k
    gs->substituteEntitiesDefaultValue =
619
8.75k
        xmlSubstituteEntitiesDefaultValueThrDef;
620
8.75k
#ifdef LIBXML_OUTPUT_ENABLED
621
8.75k
    gs->indentTreeOutput = xmlIndentTreeOutputThrDef;
622
8.75k
    gs->treeIndentString = xmlTreeIndentStringThrDef;
623
8.75k
    gs->saveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
624
8.75k
#endif
625
626
    /* XML_GLOBALS_ERROR */
627
8.75k
    gs->genericError = xmlGenericErrorThrDef;
628
8.75k
    gs->structuredError = xmlStructuredErrorThrDef;
629
8.75k
    gs->genericErrorContext = xmlGenericErrorContextThrDef;
630
8.75k
    gs->structuredErrorContext = xmlStructuredErrorContextThrDef;
631
632
    /* XML_GLOBALS_TREE */
633
8.75k
    gs->registerNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
634
8.75k
    gs->deregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
635
636
    /* XML_GLOBALS_IO */
637
8.75k
    gs->parserInputBufferCreateFilenameValue =
638
8.75k
        xmlParserInputBufferCreateFilenameValueThrDef;
639
8.75k
    gs->outputBufferCreateFilenameValue =
640
8.75k
        xmlOutputBufferCreateFilenameValueThrDef;
641
642
8.75k
    xmlMutexUnlock(&xmlThrDefMutex);
643
644
#ifdef USE_TLS
645
    gs->initialized = 1;
646
#endif
647
648
8.75k
#ifdef HAVE_POSIX_THREADS
649
8.75k
    pthread_setspecific(globalkey, gs);
650
#elif defined HAVE_WIN32_THREADS
651
#ifndef USE_TLS
652
    TlsSetValue(globalkey, gs);
653
#endif
654
#ifdef USE_WAIT_DTOR
655
    xmlRegisterGlobalStateDtor(gs);
656
#endif
657
#endif
658
8.75k
}
659
660
const xmlError *
661
0
__xmlLastError(void) {
662
0
    return(&xmlGetThreadLocalStorage(0)->lastError);
663
0
}
664
665
int *
666
272k
__xmlDoValidityCheckingDefaultValue(void) {
667
272k
    return(&xmlGetThreadLocalStorage(0)->doValidityCheckingDefaultValue);
668
272k
}
669
670
int *
671
2.21M
__xmlGetWarningsDefaultValue(void) {
672
2.21M
    return(&xmlGetThreadLocalStorage(0)->getWarningsDefaultValue);
673
2.21M
}
674
675
int *
676
272k
__xmlKeepBlanksDefaultValue(void) {
677
272k
    return(&xmlGetThreadLocalStorage(0)->keepBlanksDefaultValue);
678
272k
}
679
680
int *
681
272k
__xmlLineNumbersDefaultValue(void) {
682
272k
    return(&xmlGetThreadLocalStorage(0)->lineNumbersDefaultValue);
683
272k
}
684
685
int *
686
272k
__xmlLoadExtDtdDefaultValue(void) {
687
272k
    return(&xmlGetThreadLocalStorage(0)->loadExtDtdDefaultValue);
688
272k
}
689
690
int *
691
272k
__xmlPedanticParserDefaultValue(void) {
692
272k
    return(&xmlGetThreadLocalStorage(0)->pedanticParserDefaultValue);
693
272k
}
694
695
int *
696
272k
__xmlSubstituteEntitiesDefaultValue(void) {
697
272k
    return(&xmlGetThreadLocalStorage(0)->substituteEntitiesDefaultValue);
698
272k
}
699
700
#ifdef LIBXML_OUTPUT_ENABLED
701
int *
702
0
__xmlIndentTreeOutput(void) {
703
0
    return(&xmlGetThreadLocalStorage(0)->indentTreeOutput);
704
0
}
705
706
const char **
707
0
__xmlTreeIndentString(void) {
708
0
    return(&xmlGetThreadLocalStorage(0)->treeIndentString);
709
0
}
710
711
int *
712
0
__xmlSaveNoEmptyTags(void) {
713
0
    return(&xmlGetThreadLocalStorage(0)->saveNoEmptyTags);
714
0
}
715
#endif
716
717
xmlGenericErrorFunc *
718
1.18k
__xmlGenericError(void) {
719
1.18k
    return(&xmlGetThreadLocalStorage(0)->genericError);
720
1.18k
}
721
722
void **
723
1.18k
__xmlGenericErrorContext(void) {
724
1.18k
    return(&xmlGetThreadLocalStorage(0)->genericErrorContext);
725
1.18k
}
726
727
xmlStructuredErrorFunc *
728
1.94M
__xmlStructuredError(void) {
729
1.94M
    return(&xmlGetThreadLocalStorage(0)->structuredError);
730
1.94M
}
731
732
void **
733
0
__xmlStructuredErrorContext(void) {
734
0
    return(&xmlGetThreadLocalStorage(0)->structuredErrorContext);
735
0
}
736
737
xmlRegisterNodeFunc *
738
0
__xmlRegisterNodeDefaultValue(void) {
739
0
    return(&xmlGetThreadLocalStorage(0)->registerNodeDefaultValue);
740
0
}
741
742
xmlDeregisterNodeFunc *
743
0
__xmlDeregisterNodeDefaultValue(void) {
744
0
    return(&xmlGetThreadLocalStorage(0)->deregisterNodeDefaultValue);
745
0
}
746
747
xmlParserInputBufferCreateFilenameFunc *
748
0
__xmlParserInputBufferCreateFilenameValue(void) {
749
0
    return(&xmlGetThreadLocalStorage(0)->parserInputBufferCreateFilenameValue);
750
0
}
751
752
xmlOutputBufferCreateFilenameFunc *
753
0
__xmlOutputBufferCreateFilenameValue(void) {
754
0
    return(&xmlGetThreadLocalStorage(0)->outputBufferCreateFilenameValue);
755
0
}
756
757
#ifdef LIBXML_THREAD_ALLOC_ENABLED
758
xmlMallocFunc *
759
__xmlMalloc(void) {
760
    return(&xmlGetThreadLocalStorage(0)->malloc);
761
}
762
763
xmlMallocFunc *
764
__xmlMallocAtomic(void) {
765
    return(&xmlGetThreadLocalStorage(0)->mallocAtomic);
766
}
767
768
xmlReallocFunc *
769
__xmlRealloc(void) {
770
    return(&xmlGetThreadLocalStorage(0)->realloc);
771
}
772
773
xmlFreeFunc *
774
__xmlFree(void) {
775
    return(&xmlGetThreadLocalStorage(0)->free);
776
}
777
778
xmlStrdupFunc *
779
__xmlMemStrdup(void) {
780
    return(&xmlGetThreadLocalStorage(0)->memStrdup);
781
}
782
#endif /* LIBXML_THREAD_ALLOC_ENABLED */
783
784
/**
785
 * xmlGetLocalRngState:
786
 *
787
 * Returns the local RNG state.
788
 */
789
unsigned *
790
280k
xmlGetLocalRngState(void) {
791
280k
    return(xmlGetThreadLocalStorage(0)->localRngState);
792
280k
}
793
794
/**
795
 * xmlCheckThreadLocalStorage:
796
 *
797
 * Check whether thread-local storage could be allocated.
798
 *
799
 * In cross-platform code running in multithreaded environments, this
800
 * function should be called once in each thread before calling other
801
 * library functions to make sure that thread-local storage was
802
 * allocated properly.
803
 *
804
 * Returns 0 on success or -1 if a memory allocation failed. A failed
805
 * allocation signals a typically fatal and irrecoverable out-of-memory
806
 * situation. Don't call any library functions in this case.
807
 *
808
 * Available since 2.12.0.
809
 */
810
int
811
0
xmlCheckThreadLocalStorage(void) {
812
0
#if defined(LIBXML_THREAD_ENABLED) && !defined(USE_TLS)
813
0
    if (xmlGetThreadLocalStorage(1) == NULL)
814
0
        return(-1);
815
0
#endif
816
0
    return(0);
817
0
}
818
819
/**
820
 * xmlGetLastErrorInternal:
821
 *
822
 * Returns a pointer to the global error struct.
823
 */
824
xmlError *
825
1.94M
xmlGetLastErrorInternal(void) {
826
1.94M
    return(&xmlGetThreadLocalStorage(0)->lastError);
827
1.94M
}
828
829
/** DOC_DISABLE */
830
831
/**
832
 * DllMain:
833
 * @hinstDLL: handle to DLL instance
834
 * @fdwReason: Reason code for entry
835
 * @lpvReserved: generic pointer (depends upon reason code)
836
 *
837
 * Entry point for Windows library. It is being used to free thread-specific
838
 * storage.
839
 *
840
 * Returns TRUE always
841
 */
842
#ifdef USE_DLL_MAIN
843
#if defined(LIBXML_STATIC_FOR_DLL)
844
int
845
xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
846
           ATTRIBUTE_UNUSED void *lpvReserved)
847
#else
848
/* declare to avoid "no previous prototype for 'DllMain'" warning */
849
/* Note that we do NOT want to include this function declaration in
850
   a public header because it's meant to be called by Windows itself,
851
   not a program that uses this library.  This also has to be exported. */
852
853
XMLPUBFUN BOOL WINAPI
854
DllMain (HINSTANCE hinstDLL,
855
         DWORD     fdwReason,
856
         LPVOID    lpvReserved);
857
858
BOOL WINAPI
859
DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
860
        ATTRIBUTE_UNUSED LPVOID lpvReserved)
861
#endif
862
{
863
    switch (fdwReason) {
864
        case DLL_THREAD_DETACH:
865
#ifdef USE_TLS
866
            xmlFreeGlobalState(&globalState);
867
#else
868
            if (globalkey != TLS_OUT_OF_INDEXES) {
869
                xmlGlobalState *globalval;
870
871
                globalval = (xmlGlobalState *) TlsGetValue(globalkey);
872
                if (globalval) {
873
                    xmlFreeGlobalState(globalval);
874
                    TlsSetValue(globalkey, NULL);
875
                }
876
            }
877
#endif
878
            break;
879
880
#ifndef LIBXML_THREAD_ALLOC_ENABLED
881
        case DLL_PROCESS_DETACH:
882
            if (xmlFree == free)
883
                xmlCleanupParser();
884
            if (globalkey != TLS_OUT_OF_INDEXES) {
885
                TlsFree(globalkey);
886
                globalkey = TLS_OUT_OF_INDEXES;
887
            }
888
            break;
889
#endif
890
    }
891
    return TRUE;
892
}
893
#endif /* USE_DLL_MAIN */
894
895
void
896
0
xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
897
0
    xmlMutexLock(&xmlThrDefMutex);
898
0
    xmlGenericErrorContextThrDef = ctx;
899
0
    if (handler != NULL)
900
0
  xmlGenericErrorThrDef = handler;
901
0
    else
902
0
  xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
903
0
    xmlMutexUnlock(&xmlThrDefMutex);
904
0
}
905
906
void
907
0
xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
908
0
    xmlMutexLock(&xmlThrDefMutex);
909
0
    xmlStructuredErrorContextThrDef = ctx;
910
0
    xmlStructuredErrorThrDef = handler;
911
0
    xmlMutexUnlock(&xmlThrDefMutex);
912
0
}
913
914
0
int xmlThrDefDoValidityCheckingDefaultValue(int v) {
915
0
    int ret;
916
0
    xmlMutexLock(&xmlThrDefMutex);
917
0
    ret = xmlDoValidityCheckingDefaultValueThrDef;
918
0
    xmlDoValidityCheckingDefaultValueThrDef = v;
919
0
    xmlMutexUnlock(&xmlThrDefMutex);
920
0
    return ret;
921
0
}
922
923
0
int xmlThrDefGetWarningsDefaultValue(int v) {
924
0
    int ret;
925
0
    xmlMutexLock(&xmlThrDefMutex);
926
0
    ret = xmlGetWarningsDefaultValueThrDef;
927
0
    xmlGetWarningsDefaultValueThrDef = v;
928
0
    xmlMutexUnlock(&xmlThrDefMutex);
929
0
    return ret;
930
0
}
931
932
#ifdef LIBXML_OUTPUT_ENABLED
933
0
int xmlThrDefIndentTreeOutput(int v) {
934
0
    int ret;
935
0
    xmlMutexLock(&xmlThrDefMutex);
936
0
    ret = xmlIndentTreeOutputThrDef;
937
0
    xmlIndentTreeOutputThrDef = v;
938
0
    xmlMutexUnlock(&xmlThrDefMutex);
939
0
    return ret;
940
0
}
941
942
0
const char * xmlThrDefTreeIndentString(const char * v) {
943
0
    const char * ret;
944
0
    xmlMutexLock(&xmlThrDefMutex);
945
0
    ret = xmlTreeIndentStringThrDef;
946
0
    xmlTreeIndentStringThrDef = v;
947
0
    xmlMutexUnlock(&xmlThrDefMutex);
948
0
    return ret;
949
0
}
950
951
0
int xmlThrDefSaveNoEmptyTags(int v) {
952
0
    int ret;
953
0
    xmlMutexLock(&xmlThrDefMutex);
954
0
    ret = xmlSaveNoEmptyTagsThrDef;
955
0
    xmlSaveNoEmptyTagsThrDef = v;
956
0
    xmlMutexUnlock(&xmlThrDefMutex);
957
0
    return ret;
958
0
}
959
#endif
960
961
0
int xmlThrDefKeepBlanksDefaultValue(int v) {
962
0
    int ret;
963
0
    xmlMutexLock(&xmlThrDefMutex);
964
0
    ret = xmlKeepBlanksDefaultValueThrDef;
965
0
    xmlKeepBlanksDefaultValueThrDef = v;
966
0
    xmlMutexUnlock(&xmlThrDefMutex);
967
0
    return ret;
968
0
}
969
970
0
int xmlThrDefLineNumbersDefaultValue(int v) {
971
0
    int ret;
972
0
    xmlMutexLock(&xmlThrDefMutex);
973
0
    ret = xmlLineNumbersDefaultValueThrDef;
974
0
    xmlLineNumbersDefaultValueThrDef = v;
975
0
    xmlMutexUnlock(&xmlThrDefMutex);
976
0
    return ret;
977
0
}
978
979
0
int xmlThrDefLoadExtDtdDefaultValue(int v) {
980
0
    int ret;
981
0
    xmlMutexLock(&xmlThrDefMutex);
982
0
    ret = xmlLoadExtDtdDefaultValueThrDef;
983
0
    xmlLoadExtDtdDefaultValueThrDef = v;
984
0
    xmlMutexUnlock(&xmlThrDefMutex);
985
0
    return ret;
986
0
}
987
988
0
int xmlThrDefPedanticParserDefaultValue(int v) {
989
0
    int ret;
990
0
    xmlMutexLock(&xmlThrDefMutex);
991
0
    ret = xmlPedanticParserDefaultValueThrDef;
992
0
    xmlPedanticParserDefaultValueThrDef = v;
993
0
    xmlMutexUnlock(&xmlThrDefMutex);
994
0
    return ret;
995
0
}
996
997
0
int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
998
0
    int ret;
999
0
    xmlMutexLock(&xmlThrDefMutex);
1000
0
    ret = xmlSubstituteEntitiesDefaultValueThrDef;
1001
0
    xmlSubstituteEntitiesDefaultValueThrDef = v;
1002
0
    xmlMutexUnlock(&xmlThrDefMutex);
1003
0
    return ret;
1004
0
}
1005
1006
xmlRegisterNodeFunc
1007
xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
1008
0
{
1009
0
    xmlRegisterNodeFunc old;
1010
1011
0
    xmlMutexLock(&xmlThrDefMutex);
1012
0
    old = xmlRegisterNodeDefaultValueThrDef;
1013
1014
0
    xmlRegisterCallbacks = 1;
1015
0
    xmlRegisterNodeDefaultValueThrDef = func;
1016
0
    xmlMutexUnlock(&xmlThrDefMutex);
1017
1018
0
    return(old);
1019
0
}
1020
1021
xmlDeregisterNodeFunc
1022
xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
1023
0
{
1024
0
    xmlDeregisterNodeFunc old;
1025
1026
0
    xmlMutexLock(&xmlThrDefMutex);
1027
0
    old = xmlDeregisterNodeDefaultValueThrDef;
1028
1029
0
    xmlRegisterCallbacks = 1;
1030
0
    xmlDeregisterNodeDefaultValueThrDef = func;
1031
0
    xmlMutexUnlock(&xmlThrDefMutex);
1032
1033
0
    return(old);
1034
0
}
1035
1036
xmlParserInputBufferCreateFilenameFunc
1037
xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
1038
0
{
1039
0
    xmlParserInputBufferCreateFilenameFunc old;
1040
1041
0
    xmlMutexLock(&xmlThrDefMutex);
1042
0
    old = xmlParserInputBufferCreateFilenameValueThrDef;
1043
0
    if (old == NULL) {
1044
0
    old = __xmlParserInputBufferCreateFilename;
1045
0
  }
1046
1047
0
    xmlParserInputBufferCreateFilenameValueThrDef = func;
1048
0
    xmlMutexUnlock(&xmlThrDefMutex);
1049
1050
0
    return(old);
1051
0
}
1052
1053
xmlOutputBufferCreateFilenameFunc
1054
xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
1055
0
{
1056
0
    xmlOutputBufferCreateFilenameFunc old;
1057
1058
0
    xmlMutexLock(&xmlThrDefMutex);
1059
0
    old = xmlOutputBufferCreateFilenameValueThrDef;
1060
0
#ifdef LIBXML_OUTPUT_ENABLED
1061
0
    if (old == NULL) {
1062
0
    old = __xmlOutputBufferCreateFilename;
1063
0
  }
1064
0
#endif
1065
0
    xmlOutputBufferCreateFilenameValueThrDef = func;
1066
0
    xmlMutexUnlock(&xmlThrDefMutex);
1067
1068
0
    return(old);
1069
0
}
1070
1071
/** DOC_ENABLE */
1072