Coverage Report

Created: 2025-11-16 09:57

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