xref: /aosp_15_r20/external/cronet/third_party/libxml/src/globals.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 <[email protected]>
8  * [email protected]
9  */
10 
11 #define IN_LIBXML
12 #include "libxml.h"
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 
18 #define XML_GLOBALS_NO_REDEFINITION
19 #include <libxml/globals.h>
20 #include <libxml/xmlerror.h>
21 #include <libxml/xmlmemory.h>
22 #include <libxml/xmlIO.h>
23 #include <libxml/parser.h>
24 #include <libxml/threads.h>
25 #include <libxml/tree.h>
26 #include <libxml/SAX.h>
27 #include <libxml/SAX2.h>
28 
29 #include "private/dict.h"
30 #include "private/error.h"
31 #include "private/globals.h"
32 #include "private/threads.h"
33 #include "private/tree.h"
34 
35 /*
36  * Thread-local storage emulation.
37  *
38  * This works by replacing a global variable
39  *
40  *     extern xmlError xmlLastError;
41  *
42  * with a macro that calls a function returning a pointer to the global in
43  * thread-local storage:
44  *
45  *     xmlError *__xmlLastError(void);
46  *     #define xmlError (*__xmlLastError());
47  *
48  * The code can operate in a multitude of ways depending on the environment.
49  * First we support POSIX and Windows threads. Then we support both thread-local
50  * storage provided by the compiler and older methods like thread-specific data
51  * (pthreads) or TlsAlloc (Windows).
52  *
53  * To clean up thread-local storage, we use thread-specific data on POSIX.
54  * On Windows, we either use DllMain when compiling a DLL or a registered wait
55  * function for static builds.
56  */
57 
58 /*
59  * Helpful Macro
60  */
61 #ifdef LIBXML_THREAD_ENABLED
62 #define IS_MAIN_THREAD (xmlIsMainThreadInternal())
63 #else
64 #define IS_MAIN_THREAD 1
65 #endif
66 
67 #define XML_DECLARE_MEMBER(name, type, attrs) \
68   type gs_##name;
69 
70 struct _xmlGlobalState {
71     int initialized;
72 
73 #if defined(HAVE_WIN32_THREADS) && \
74     defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
75     void *threadHandle;
76     void *waitHandle;
77 #endif
78 
79 #ifdef LIBXML_THREAD_ENABLED
80     unsigned localRngState[2];
81 #endif
82 
83 #define XML_OP XML_DECLARE_MEMBER
84 XML_GLOBALS_ALLOC
85 XML_GLOBALS_ERROR
86 XML_GLOBALS_IO
87 XML_GLOBALS_PARSER
88 XML_GLOBALS_TREE
89 #undef XML_OP
90 };
91 
92 static int parserInitialized;
93 
94 /*
95  * Mutex to protect "ForNewThreads" variables
96  */
97 static xmlMutex xmlThrDefMutex;
98 
99 #ifdef LIBXML_THREAD_ENABLED
100 
101 /*
102  * On Darwin, thread-local storage destructors seem to be run before
103  * pthread thread-specific data destructors. This causes ASan to
104  * report a use-after-free.
105  *
106  * On Windows, we can't use TLS in static builds. The RegisterWait
107  * callback would run after TLS was deallocated.
108  */
109 #if defined(XML_THREAD_LOCAL) && \
110     !defined(__APPLE__) && \
111     (!defined(HAVE_WIN32_THREADS) || \
112      !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
113 #define USE_TLS
114 #endif
115 
116 #ifdef USE_TLS
117 static XML_THREAD_LOCAL xmlGlobalState globalState;
118 #endif
119 
120 #ifdef HAVE_POSIX_THREADS
121 
122 /*
123  * Weak symbol hack, see threads.c
124  */
125 #if defined(__GNUC__) && \
126     defined(__GLIBC__) && \
127     __GLIBC__ * 100 + __GLIBC_MINOR__ < 234
128 
129 #pragma weak pthread_getspecific
130 #pragma weak pthread_setspecific
131 #pragma weak pthread_key_create
132 #pragma weak pthread_key_delete
133 #pragma weak pthread_equal
134 #pragma weak pthread_self
135 
136 #define XML_PTHREAD_WEAK
137 
138 static int libxml_is_threaded = -1;
139 
140 #endif
141 
142 /*
143  * On POSIX, we need thread-specific data even with thread-local storage
144  * to destroy indirect references from global state (xmlLastError) at
145  * thread exit.
146  */
147 static pthread_key_t globalkey;
148 static pthread_t mainthread;
149 
150 #elif defined HAVE_WIN32_THREADS
151 
152 #ifndef USE_TLS
153 static DWORD globalkey = TLS_OUT_OF_INDEXES;
154 #endif
155 static DWORD mainthread;
156 
157 #endif /* HAVE_WIN32_THREADS */
158 
159 static void
160 xmlFreeGlobalState(void *state);
161 
162 #endif /* LIBXML_THREAD_ENABLED */
163 
164 /************************************************************************
165  *									*
166  *	All the user accessible global variables of the library		*
167  *									*
168  ************************************************************************/
169 
170 #ifdef LIBXML_THREAD_ENABLED
171 static unsigned xmlMainThreadRngState[2];
172 #endif
173 
174 /*
175  * Memory allocation routines
176  */
177 
178 #if defined(DEBUG_MEMORY_LOCATION)
179 xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
180 xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
181 xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc;
182 xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
183 xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
184 #else
185 /**
186  * xmlFree:
187  * @mem: an already allocated block of memory
188  *
189  * The variable holding the libxml free() implementation
190  */
191 xmlFreeFunc xmlFree = free;
192 /**
193  * xmlMalloc:
194  * @size:  the size requested in bytes
195  *
196  * The variable holding the libxml malloc() implementation
197  *
198  * Returns a pointer to the newly allocated block or NULL in case of error
199  */
200 xmlMallocFunc xmlMalloc = malloc;
201 /**
202  * xmlMallocAtomic:
203  * @size:  the size requested in bytes
204  *
205  * The variable holding the libxml malloc() implementation for atomic
206  * data (i.e. blocks not containing pointers), useful when using a
207  * garbage collecting allocator.
208  *
209  * Returns a pointer to the newly allocated block or NULL in case of error
210  */
211 xmlMallocFunc xmlMallocAtomic = malloc;
212 /**
213  * xmlRealloc:
214  * @mem: an already allocated block of memory
215  * @size:  the new size requested in bytes
216  *
217  * The variable holding the libxml realloc() implementation
218  *
219  * Returns a pointer to the newly reallocated block or NULL in case of error
220  */
221 xmlReallocFunc xmlRealloc = realloc;
222 /**
223  * xmlPosixStrdup
224  * @cur:  the input char *
225  *
226  * a strdup implementation with a type signature matching POSIX
227  *
228  * Returns a new xmlChar * or NULL
229  */
230 static char *
xmlPosixStrdup(const char * cur)231 xmlPosixStrdup(const char *cur) {
232     return((char*) xmlCharStrdup(cur));
233 }
234 /**
235  * xmlMemStrdup:
236  * @str: a zero terminated string
237  *
238  * The variable holding the libxml strdup() implementation
239  *
240  * Returns the copy of the string or NULL in case of error
241  */
242 xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup;
243 #endif /* DEBUG_MEMORY_LOCATION */
244 
245 /**
246  * xmlBufferAllocScheme:
247  *
248  * DEPRECATED: Don't use.
249  *
250  * Global setting, default allocation policy for buffers, default is
251  * XML_BUFFER_ALLOC_EXACT
252  */
253 xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
254 static xmlBufferAllocationScheme xmlBufferAllocSchemeThrDef = XML_BUFFER_ALLOC_EXACT;
255 /**
256  * xmlDefaultBufferSize:
257  *
258  * DEPRECATED: Don't use.
259  *
260  * Global setting, default buffer size. Default value is BASE_BUFFER_SIZE
261  */
262 int xmlDefaultBufferSize = BASE_BUFFER_SIZE;
263 static int xmlDefaultBufferSizeThrDef = BASE_BUFFER_SIZE;
264 
265 /*
266  * Parser defaults
267  */
268 
269 /**
270  * oldXMLWDcompatibility:
271  *
272  * Global setting, DEPRECATED.
273  */
274 const int oldXMLWDcompatibility = 0; /* DEPRECATED */
275 /**
276  * xmlParserDebugEntities:
277  *
278  * DEPRECATED: Don't use
279  *
280  * Global setting, asking the parser to print out debugging information.
281  * while handling entities.
282  * Disabled by default
283  */
284 const int xmlParserDebugEntities = 0;
285 /**
286  * xmlDoValidityCheckingDefaultValue:
287  *
288  * DEPRECATED: Use the modern options API with XML_PARSE_DTDVALID.
289  *
290  * Global setting, indicate that the parser should work in validating mode.
291  * Disabled by default.
292  */
293 int xmlDoValidityCheckingDefaultValue = 0;
294 static int xmlDoValidityCheckingDefaultValueThrDef = 0;
295 /**
296  * xmlGetWarningsDefaultValue:
297  *
298  * DEPRECATED: Use the modern options API with XML_PARSE_NOWARNING.
299  *
300  * Global setting, indicate that the DTD validation should provide warnings.
301  * Activated by default.
302  */
303 int xmlGetWarningsDefaultValue = 1;
304 static int xmlGetWarningsDefaultValueThrDef = 1;
305 /**
306  * xmlLoadExtDtdDefaultValue:
307  *
308  * DEPRECATED: Use the modern options API with XML_PARSE_DTDLOAD.
309  *
310  * Global setting, indicate that the parser should load DTD while not
311  * validating.
312  * Disabled by default.
313  */
314 int xmlLoadExtDtdDefaultValue = 0;
315 static int xmlLoadExtDtdDefaultValueThrDef = 0;
316 /**
317  * xmlPedanticParserDefaultValue:
318  *
319  * DEPRECATED: Use the modern options API with XML_PARSE_PEDANTIC.
320  *
321  * Global setting, indicate that the parser be pedantic
322  * Disabled by default.
323  */
324 int xmlPedanticParserDefaultValue = 0;
325 static int xmlPedanticParserDefaultValueThrDef = 0;
326 /**
327  * xmlLineNumbersDefaultValue:
328  *
329  * DEPRECATED: The modern options API always enables line numbers.
330  *
331  * Global setting, indicate that the parser should store the line number
332  * in the content field of elements in the DOM tree.
333  * Disabled by default since this may not be safe for old classes of
334  * application.
335  */
336 int xmlLineNumbersDefaultValue = 0;
337 static int xmlLineNumbersDefaultValueThrDef = 0;
338 /**
339  * xmlKeepBlanksDefaultValue:
340  *
341  * DEPRECATED: Use the modern options API with XML_PARSE_NOBLANKS.
342  *
343  * Global setting, indicate that the parser should keep all blanks
344  * nodes found in the content
345  * Activated by default, this is actually needed to have the parser
346  * conformant to the XML Recommendation, however the option is kept
347  * for some applications since this was libxml1 default behaviour.
348  */
349 int xmlKeepBlanksDefaultValue = 1;
350 static int xmlKeepBlanksDefaultValueThrDef = 1;
351 /**
352  * xmlSubstituteEntitiesDefaultValue:
353  *
354  * DEPRECATED: Use the modern options API with XML_PARSE_NOENT.
355  *
356  * Global setting, indicate that the parser should not generate entity
357  * references but replace them with the actual content of the entity
358  * Disabled by default, this should be activated when using XPath since
359  * the XPath data model requires entities replacement and the XPath
360  * engine does not handle entities references transparently.
361  */
362 int xmlSubstituteEntitiesDefaultValue = 0;
363 static int xmlSubstituteEntitiesDefaultValueThrDef = 0;
364 
365 /**
366  * xmlRegisterNodeDefaultValue:
367  *
368  * DEPRECATED: Don't use
369  */
370 xmlRegisterNodeFunc xmlRegisterNodeDefaultValue = NULL;
371 static xmlRegisterNodeFunc xmlRegisterNodeDefaultValueThrDef = NULL;
372 
373 /**
374  * xmlDeregisterNodeDefaultValue:
375  *
376  * DEPRECATED: Don't use
377  */
378 xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue = NULL;
379 static xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValueThrDef = NULL;
380 
381 /**
382  * xmlParserInputBufferCreateFilenameValue:
383  *
384  * DEPRECATED: Don't use
385  */
386 xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue = NULL;
387 static xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValueThrDef = NULL;
388 
389 /**
390  * xmlOutputBufferCreateFilenameValue:
391  *
392  * DEPRECATED: Don't use
393  */
394 xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue = NULL;
395 static xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValueThrDef = NULL;
396 
397 /**
398  * xmlGenericError:
399  *
400  * Global setting: function used for generic error callbacks
401  */
402 xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
403 static xmlGenericErrorFunc xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
404 /**
405  * xmlStructuredError:
406  *
407  * Global setting: function used for structured error callbacks
408  */
409 xmlStructuredErrorFunc xmlStructuredError = NULL;
410 static xmlStructuredErrorFunc xmlStructuredErrorThrDef = NULL;
411 /**
412  * xmlGenericErrorContext:
413  *
414  * Global setting passed to generic error callbacks
415  */
416 void *xmlGenericErrorContext = NULL;
417 static void *xmlGenericErrorContextThrDef = NULL;
418 /**
419  * xmlStructuredErrorContext:
420  *
421  * Global setting passed to structured error callbacks
422  */
423 void *xmlStructuredErrorContext = NULL;
424 static void *xmlStructuredErrorContextThrDef = NULL;
425 xmlError xmlLastError;
426 
427 #ifdef LIBXML_OUTPUT_ENABLED
428 /*
429  * output defaults
430  */
431 /**
432  * xmlIndentTreeOutput:
433  *
434  * Global setting, asking the serializer to indent the output tree by default
435  * Enabled by default
436  */
437 int xmlIndentTreeOutput = 1;
438 static int xmlIndentTreeOutputThrDef = 1;
439 
440 /**
441  * xmlTreeIndentString:
442  *
443  * The string used to do one-level indent. By default is equal to "  " (two spaces)
444  */
445 const char *xmlTreeIndentString = "  ";
446 static const char *xmlTreeIndentStringThrDef = "  ";
447 
448 /**
449  * xmlSaveNoEmptyTags:
450  *
451  * Global setting, asking the serializer to not output empty tags
452  * as <empty/> but <empty></empty>. those two forms are indistinguishable
453  * once parsed.
454  * Disabled by default
455  */
456 int xmlSaveNoEmptyTags = 0;
457 static int xmlSaveNoEmptyTagsThrDef = 0;
458 #endif /* LIBXML_OUTPUT_ENABLED */
459 
460 #ifdef LIBXML_SAX1_ENABLED
461 /**
462  * xmlDefaultSAXHandler:
463  *
464  * DEPRECATED: This handler is unused and will be removed from future
465  * versions.
466  *
467  * Default SAX version1 handler for XML, builds the DOM tree
468  */
469 const xmlSAXHandlerV1 xmlDefaultSAXHandler = {
470     xmlSAX2InternalSubset,
471     xmlSAX2IsStandalone,
472     xmlSAX2HasInternalSubset,
473     xmlSAX2HasExternalSubset,
474     xmlSAX2ResolveEntity,
475     xmlSAX2GetEntity,
476     xmlSAX2EntityDecl,
477     xmlSAX2NotationDecl,
478     xmlSAX2AttributeDecl,
479     xmlSAX2ElementDecl,
480     xmlSAX2UnparsedEntityDecl,
481     xmlSAX2SetDocumentLocator,
482     xmlSAX2StartDocument,
483     xmlSAX2EndDocument,
484     xmlSAX2StartElement,
485     xmlSAX2EndElement,
486     xmlSAX2Reference,
487     xmlSAX2Characters,
488     xmlSAX2Characters,
489     xmlSAX2ProcessingInstruction,
490     xmlSAX2Comment,
491     xmlParserWarning,
492     xmlParserError,
493     xmlParserError,
494     xmlSAX2GetParameterEntity,
495     xmlSAX2CDataBlock,
496     xmlSAX2ExternalSubset,
497     1,
498 };
499 #endif /* LIBXML_SAX1_ENABLED */
500 
501 /**
502  * xmlDefaultSAXLocator:
503  *
504  * DEPRECATED: Don't use
505  *
506  * The default SAX Locator
507  * { getPublicId, getSystemId, getLineNumber, getColumnNumber}
508  */
509 const xmlSAXLocator xmlDefaultSAXLocator = {
510     xmlSAX2GetPublicId,
511     xmlSAX2GetSystemId,
512     xmlSAX2GetLineNumber,
513     xmlSAX2GetColumnNumber
514 };
515 
516 #if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_SAX1_ENABLED)
517 /**
518  * htmlDefaultSAXHandler:
519  *
520  * DEPRECATED: This handler is unused and will be removed from future
521  * versions.
522  *
523  * Default old SAX v1 handler for HTML, builds the DOM tree
524  */
525 const xmlSAXHandlerV1 htmlDefaultSAXHandler = {
526     xmlSAX2InternalSubset,
527     NULL,
528     NULL,
529     NULL,
530     NULL,
531     xmlSAX2GetEntity,
532     NULL,
533     NULL,
534     NULL,
535     NULL,
536     NULL,
537     xmlSAX2SetDocumentLocator,
538     xmlSAX2StartDocument,
539     xmlSAX2EndDocument,
540     xmlSAX2StartElement,
541     xmlSAX2EndElement,
542     NULL,
543     xmlSAX2Characters,
544     xmlSAX2IgnorableWhitespace,
545     xmlSAX2ProcessingInstruction,
546     xmlSAX2Comment,
547     xmlParserWarning,
548     xmlParserError,
549     xmlParserError,
550     NULL,
551     xmlSAX2CDataBlock,
552     NULL,
553     1,
554 };
555 #endif /* LIBXML_HTML_ENABLED */
556 
557 /************************************************************************
558  *									*
559  *			Per thread global state handling		*
560  *									*
561  ************************************************************************/
562 
563 /**
564  * xmlInitGlobals:
565  *
566  * DEPRECATED: Alias for xmlInitParser.
567  */
xmlInitGlobals(void)568 void xmlInitGlobals(void) {
569     xmlInitParser();
570 }
571 
572 /**
573  * xmlInitGlobalsInternal:
574  *
575  * Additional initialisation for multi-threading
576  */
xmlInitGlobalsInternal(void)577 void xmlInitGlobalsInternal(void) {
578     xmlInitMutex(&xmlThrDefMutex);
579 
580 #ifdef HAVE_POSIX_THREADS
581 #ifdef XML_PTHREAD_WEAK
582     if (libxml_is_threaded == -1)
583         libxml_is_threaded =
584             (pthread_getspecific != NULL) &&
585             (pthread_setspecific != NULL) &&
586             (pthread_key_create != NULL) &&
587             (pthread_key_delete != NULL) &&
588             /*
589              * pthread_equal can be inline, resuting in -Waddress warnings.
590              * Let's assume it's available if all the other functions are.
591              */
592             /* (pthread_equal != NULL) && */
593             (pthread_self != NULL);
594     if (libxml_is_threaded == 0)
595         return;
596 #endif /* XML_PTHREAD_WEAK */
597     pthread_key_create(&globalkey, xmlFreeGlobalState);
598     mainthread = pthread_self();
599 #elif defined(HAVE_WIN32_THREADS)
600 #ifndef USE_TLS
601     globalkey = TlsAlloc();
602 #endif
603     mainthread = GetCurrentThreadId();
604 #endif
605 
606 #ifdef LIBXML_THREAD_ENABLED
607     xmlMainThreadRngState[0] = xmlGlobalRandom();
608     xmlMainThreadRngState[1] = xmlGlobalRandom();
609 #endif
610 }
611 
612 /**
613  * xmlCleanupGlobals:
614  *
615  * DEPRECATED: This function is a no-op. Call xmlCleanupParser
616  * to free global state but see the warnings there. xmlCleanupParser
617  * should be only called once at program exit. In most cases, you don't
618  * have call cleanup functions at all.
619  */
xmlCleanupGlobals(void)620 void xmlCleanupGlobals(void) {
621 }
622 
623 /**
624  * xmlCleanupGlobalsInternal:
625  *
626  * Additional cleanup for multi-threading
627  */
xmlCleanupGlobalsInternal(void)628 void xmlCleanupGlobalsInternal(void) {
629     xmlResetError(&xmlLastError);
630 
631     xmlCleanupMutex(&xmlThrDefMutex);
632 
633 #ifdef HAVE_POSIX_THREADS
634 #ifdef XML_PTHREAD_WEAK
635     if (libxml_is_threaded == 0)
636         return;
637 #endif /* XML_PTHREAD_WEAK */
638     pthread_key_delete(globalkey);
639 #elif defined(HAVE_WIN32_THREADS)
640 #ifndef USE_TLS
641     if (globalkey != TLS_OUT_OF_INDEXES) {
642         TlsFree(globalkey);
643         globalkey = TLS_OUT_OF_INDEXES;
644     }
645 #endif
646 #endif
647 
648     parserInitialized = 0;
649 }
650 
651 /**
652  * xmlInitializeGlobalState:
653  * @gs: a pointer to a newly allocated global state
654  *
655  * DEPRECATED: No-op.
656  */
657 void
xmlInitializeGlobalState(xmlGlobalStatePtr gs ATTRIBUTE_UNUSED)658 xmlInitializeGlobalState(xmlGlobalStatePtr gs ATTRIBUTE_UNUSED)
659 {
660 }
661 
662 /**
663  * xmlGetGlobalState:
664  *
665  * DEPRECATED
666  *
667  * Returns NULL.
668  */
669 xmlGlobalStatePtr
xmlGetGlobalState(void)670 xmlGetGlobalState(void)
671 {
672     return(NULL);
673 }
674 
675 static int
xmlIsMainThreadInternal(void)676 xmlIsMainThreadInternal(void) {
677     if (parserInitialized == 0) {
678         xmlInitParser();
679         parserInitialized = 1;
680     }
681 
682 #ifdef HAVE_POSIX_THREADS
683 #ifdef XML_PTHREAD_WEAK
684     if (libxml_is_threaded == 0)
685         return (1);
686 #endif
687     return (pthread_equal(mainthread, pthread_self()));
688 #elif defined HAVE_WIN32_THREADS
689     return (mainthread == GetCurrentThreadId());
690 #else
691     return (1);
692 #endif
693 }
694 
695 /**
696  * xmlIsMainThread:
697  *
698  * DEPRECATED: Internal function, do not use.
699  *
700  * Check whether the current thread is the main thread.
701  *
702  * Returns 1 if the current thread is the main thread, 0 otherwise
703  */
704 int
xmlIsMainThread(void)705 xmlIsMainThread(void) {
706     return(xmlIsMainThreadInternal());
707 }
708 
709 #ifdef LIBXML_THREAD_ENABLED
710 
711 static void
xmlFreeGlobalState(void * state)712 xmlFreeGlobalState(void *state)
713 {
714     xmlGlobalState *gs = (xmlGlobalState *) state;
715 
716     /*
717      * Free any memory allocated in the thread's xmlLastError. If it
718      * weren't for this indirect allocation, we wouldn't need
719      * a destructor with thread-local storage at all!
720      *
721      * It would be nice if we could make xmlLastError a special error
722      * type which uses statically allocated, fixed-size buffers.
723      * But the xmlError struct is fully public and widely used,
724      * so changes are dangerous.
725      */
726     xmlResetError(&(gs->gs_xmlLastError));
727 #ifndef USE_TLS
728     free(state);
729 #endif
730 }
731 
732 #if defined(HAVE_WIN32_THREADS) && \
733     defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
734 static void WINAPI
xmlGlobalStateDtor(void * ctxt,unsigned char timedOut ATTRIBUTE_UNUSED)735 xmlGlobalStateDtor(void *ctxt, unsigned char timedOut ATTRIBUTE_UNUSED) {
736     xmlGlobalStatePtr gs = ctxt;
737 
738     UnregisterWait(gs->waitHandle);
739     CloseHandle(gs->threadHandle);
740     xmlFreeGlobalState(gs);
741 }
742 
743 static int
xmlRegisterGlobalStateDtor(xmlGlobalState * gs)744 xmlRegisterGlobalStateDtor(xmlGlobalState *gs) {
745     void *processHandle = GetCurrentProcess();
746     void *threadHandle;
747     void *waitHandle;
748 
749     if (DuplicateHandle(processHandle, GetCurrentThread(), processHandle,
750                 &threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {
751         return(-1);
752     }
753 
754     if (RegisterWaitForSingleObject(&waitHandle, threadHandle,
755                 xmlGlobalStateDtor, gs, INFINITE, WT_EXECUTEONLYONCE) == 0) {
756         CloseHandle(threadHandle);
757         return(-1);
758     }
759 
760     gs->threadHandle = threadHandle;
761     gs->waitHandle = waitHandle;
762     return(0);
763 }
764 #endif /* LIBXML_STATIC */
765 
766 static void
xmlInitGlobalState(xmlGlobalStatePtr gs)767 xmlInitGlobalState(xmlGlobalStatePtr gs) {
768     xmlMutexLock(&xmlThrDefMutex);
769 
770 #ifdef LIBXML_THREAD_ENABLED
771     gs->localRngState[0] = xmlGlobalRandom();
772     gs->localRngState[1] = xmlGlobalRandom();
773 #endif
774 
775     gs->gs_xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
776     gs->gs_xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
777     gs->gs_xmlDoValidityCheckingDefaultValue =
778          xmlDoValidityCheckingDefaultValueThrDef;
779 #ifdef LIBXML_THREAD_ALLOC_ENABLED
780 #ifdef DEBUG_MEMORY_LOCATION
781     gs->gs_xmlFree = xmlMemFree;
782     gs->gs_xmlMalloc = xmlMemMalloc;
783     gs->gs_xmlMallocAtomic = xmlMemMalloc;
784     gs->gs_xmlRealloc = xmlMemRealloc;
785     gs->gs_xmlMemStrdup = xmlMemoryStrdup;
786 #else
787     gs->gs_xmlFree = free;
788     gs->gs_xmlMalloc = malloc;
789     gs->gs_xmlMallocAtomic = malloc;
790     gs->gs_xmlRealloc = realloc;
791     gs->gs_xmlMemStrdup = xmlPosixStrdup;
792 #endif
793 #endif
794     gs->gs_xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
795 #ifdef LIBXML_OUTPUT_ENABLED
796     gs->gs_xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
797     gs->gs_xmlTreeIndentString = xmlTreeIndentStringThrDef;
798     gs->gs_xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
799 #endif
800     gs->gs_xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
801     gs->gs_xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
802     gs->gs_xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
803     gs->gs_xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
804     gs->gs_xmlSubstituteEntitiesDefaultValue =
805         xmlSubstituteEntitiesDefaultValueThrDef;
806 
807     gs->gs_xmlGenericError = xmlGenericErrorThrDef;
808     gs->gs_xmlStructuredError = xmlStructuredErrorThrDef;
809     gs->gs_xmlGenericErrorContext = xmlGenericErrorContextThrDef;
810     gs->gs_xmlStructuredErrorContext = xmlStructuredErrorContextThrDef;
811     gs->gs_xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
812     gs->gs_xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
813 
814     gs->gs_xmlParserInputBufferCreateFilenameValue =
815         xmlParserInputBufferCreateFilenameValueThrDef;
816     gs->gs_xmlOutputBufferCreateFilenameValue =
817         xmlOutputBufferCreateFilenameValueThrDef;
818     memset(&gs->gs_xmlLastError, 0, sizeof(xmlError));
819 
820     xmlMutexUnlock(&xmlThrDefMutex);
821 
822 #ifdef HAVE_POSIX_THREADS
823     pthread_setspecific(globalkey, gs);
824 #elif defined HAVE_WIN32_THREADS
825 #ifndef USE_TLS
826     TlsSetValue(globalkey, gs);
827 #endif
828 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
829     xmlRegisterGlobalStateDtor(gs);
830 #endif
831 #endif
832 
833     gs->initialized = 1;
834 }
835 
836 #ifndef USE_TLS
837 /**
838  * xmlNewGlobalState:
839  *
840  * xmlNewGlobalState() allocates a global state. This structure is used to
841  * hold all data for use by a thread when supporting backwards compatibility
842  * of libxml2 to pre-thread-safe behaviour.
843  *
844  * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
845  */
846 static xmlGlobalStatePtr
xmlNewGlobalState(int allowFailure)847 xmlNewGlobalState(int allowFailure)
848 {
849     xmlGlobalState *gs;
850 
851     gs = malloc(sizeof(xmlGlobalState));
852     if (gs == NULL) {
853         if (allowFailure)
854             return(NULL);
855 
856         /*
857          * If an application didn't call xmlCheckThreadLocalStorage to make
858          * sure that global state could be allocated, it's too late to
859          * handle the error.
860          */
861         fprintf(stderr, "libxml2: Failed to allocate globals for thread\n"
862                         "libxml2: See xmlCheckThreadLocalStorage\n");
863         abort();
864     }
865 
866     memset(gs, 0, sizeof(xmlGlobalState));
867     xmlInitGlobalState(gs);
868     return (gs);
869 }
870 #endif
871 
872 static xmlGlobalStatePtr
xmlGetThreadLocalStorage(int allowFailure)873 xmlGetThreadLocalStorage(int allowFailure) {
874     xmlGlobalState *gs;
875 
876     (void) allowFailure;
877 
878 #ifdef USE_TLS
879     gs = &globalState;
880     if (gs->initialized == 0)
881         xmlInitGlobalState(gs);
882 #elif defined(HAVE_POSIX_THREADS)
883     gs = (xmlGlobalState *) pthread_getspecific(globalkey);
884     if (gs == NULL)
885         gs = xmlNewGlobalState(allowFailure);
886 #elif defined(HAVE_WIN32_THREADS)
887     gs = (xmlGlobalState *) TlsGetValue(globalkey);
888     if (gs == NULL)
889         gs = xmlNewGlobalState(allowFailure);
890 #else
891     gs = NULL;
892 #endif
893 
894     return(gs);
895 }
896 
897 /* Define thread-local storage accessors with macro magic */
898 
899 #define XML_DEFINE_GLOBAL_WRAPPER(name, type, attrs) \
900     type *__##name(void) { \
901         if (IS_MAIN_THREAD) \
902             return (&name); \
903         else \
904             return (&xmlGetThreadLocalStorage(0)->gs_##name); \
905     }
906 
907 #define XML_OP XML_DEFINE_GLOBAL_WRAPPER
908 XML_GLOBALS_ALLOC
909 XML_GLOBALS_ERROR
910 XML_GLOBALS_IO
911 XML_GLOBALS_PARSER
912 XML_GLOBALS_TREE
913 #undef XML_OP
914 
915 #ifdef LIBXML_THREAD_ENABLED
916 unsigned *
xmlGetLocalRngState(void)917 xmlGetLocalRngState(void) {
918     if (IS_MAIN_THREAD)
919         return(xmlMainThreadRngState);
920     else
921         return(xmlGetThreadLocalStorage(0)->localRngState);
922 }
923 #endif
924 
925 /* For backward compatibility */
926 
927 const char *const *
__xmlParserVersion(void)928 __xmlParserVersion(void) {
929     return &xmlParserVersion;
930 }
931 
932 const int *
__oldXMLWDcompatibility(void)933 __oldXMLWDcompatibility(void) {
934     return &oldXMLWDcompatibility;
935 }
936 
937 const int *
__xmlParserDebugEntities(void)938 __xmlParserDebugEntities(void) {
939     return &xmlParserDebugEntities;
940 }
941 
942 const xmlSAXLocator *
__xmlDefaultSAXLocator(void)943 __xmlDefaultSAXLocator(void) {
944     return &xmlDefaultSAXLocator;
945 }
946 
947 #ifdef LIBXML_SAX1_ENABLED
948 const xmlSAXHandlerV1 *
__xmlDefaultSAXHandler(void)949 __xmlDefaultSAXHandler(void) {
950     return &xmlDefaultSAXHandler;
951 }
952 
953 #ifdef LIBXML_HTML_ENABLED
954 const xmlSAXHandlerV1 *
__htmlDefaultSAXHandler(void)955 __htmlDefaultSAXHandler(void) {
956     return &htmlDefaultSAXHandler;
957 }
958 #endif /* LIBXML_HTML_ENABLED */
959 #endif /* LIBXML_SAX1_ENABLED */
960 
961 #endif /* LIBXML_THREAD_ENABLED */
962 
963 /**
964  * xmlCheckThreadLocalStorage:
965  *
966  * Check whether thread-local storage could be allocated.
967  *
968  * In cross-platform code running in multithreaded environments, this
969  * function should be called once in each thread before calling other
970  * library functions to make sure that thread-local storage was
971  * allocated properly.
972  *
973  * Returns 0 on success or -1 if a memory allocation failed. A failed
974  * allocation signals a typically fatal and irrecoverable out-of-memory
975  * situation. Don't call any library functions in this case.
976  *
977  * This function never fails if the library is compiled with support
978  * for thread-local storage.
979  *
980  * This function never fails for the "main" thread which is the first
981  * thread calling xmlInitParser.
982  *
983  * Available since v2.12.0.
984  */
985 int
xmlCheckThreadLocalStorage(void)986 xmlCheckThreadLocalStorage(void) {
987 #if defined(LIBXML_THREAD_ENABLED) && !defined(USE_TLS)
988     if ((!xmlIsMainThreadInternal()) && (xmlGetThreadLocalStorage(1) == NULL))
989         return(-1);
990 #endif
991     return(0);
992 }
993 
994 /**
995  * DllMain:
996  * @hinstDLL: handle to DLL instance
997  * @fdwReason: Reason code for entry
998  * @lpvReserved: generic pointer (depends upon reason code)
999  *
1000  * Entry point for Windows library. It is being used to free thread-specific
1001  * storage.
1002  *
1003  * Returns TRUE always
1004  */
1005 #if defined(HAVE_WIN32_THREADS) && \
1006     (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
1007 #if defined(LIBXML_STATIC_FOR_DLL)
1008 int
xmlDllMain(ATTRIBUTE_UNUSED void * hinstDLL,unsigned long fdwReason,ATTRIBUTE_UNUSED void * lpvReserved)1009 xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
1010            ATTRIBUTE_UNUSED void *lpvReserved)
1011 #else
1012 /* declare to avoid "no previous prototype for 'DllMain'" warning */
1013 /* Note that we do NOT want to include this function declaration in
1014    a public header because it's meant to be called by Windows itself,
1015    not a program that uses this library.  This also has to be exported. */
1016 
1017 XMLPUBFUN BOOL WINAPI
1018 DllMain (HINSTANCE hinstDLL,
1019          DWORD     fdwReason,
1020          LPVOID    lpvReserved);
1021 
1022 BOOL WINAPI
1023 DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
1024         ATTRIBUTE_UNUSED LPVOID lpvReserved)
1025 #endif
1026 {
1027     switch (fdwReason) {
1028         case DLL_THREAD_DETACH:
1029 #ifdef USE_TLS
1030             xmlFreeGlobalState(&globalState);
1031 #else
1032             if (globalkey != TLS_OUT_OF_INDEXES) {
1033                 xmlGlobalState *globalval;
1034 
1035                 globalval = (xmlGlobalState *) TlsGetValue(globalkey);
1036                 if (globalval) {
1037                     xmlFreeGlobalState(globalval);
1038                     TlsSetValue(globalkey, NULL);
1039                 }
1040             }
1041 #endif
1042             break;
1043     }
1044     return TRUE;
1045 }
1046 #endif
1047 
1048 void
xmlThrDefSetGenericErrorFunc(void * ctx,xmlGenericErrorFunc handler)1049 xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
1050     xmlMutexLock(&xmlThrDefMutex);
1051     xmlGenericErrorContextThrDef = ctx;
1052     if (handler != NULL)
1053 	xmlGenericErrorThrDef = handler;
1054     else
1055 	xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
1056     xmlMutexUnlock(&xmlThrDefMutex);
1057 }
1058 
1059 void
xmlThrDefSetStructuredErrorFunc(void * ctx,xmlStructuredErrorFunc handler)1060 xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
1061     xmlMutexLock(&xmlThrDefMutex);
1062     xmlStructuredErrorContextThrDef = ctx;
1063     xmlStructuredErrorThrDef = handler;
1064     xmlMutexUnlock(&xmlThrDefMutex);
1065 }
1066 
xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v)1067 xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
1068     xmlBufferAllocationScheme ret;
1069     xmlMutexLock(&xmlThrDefMutex);
1070     ret = xmlBufferAllocSchemeThrDef;
1071     xmlBufferAllocSchemeThrDef = v;
1072     xmlMutexUnlock(&xmlThrDefMutex);
1073     return ret;
1074 }
1075 
xmlThrDefDefaultBufferSize(int v)1076 int xmlThrDefDefaultBufferSize(int v) {
1077     int ret;
1078     xmlMutexLock(&xmlThrDefMutex);
1079     ret = xmlDefaultBufferSizeThrDef;
1080     xmlDefaultBufferSizeThrDef = v;
1081     xmlMutexUnlock(&xmlThrDefMutex);
1082     return ret;
1083 }
1084 
xmlThrDefDoValidityCheckingDefaultValue(int v)1085 int xmlThrDefDoValidityCheckingDefaultValue(int v) {
1086     int ret;
1087     xmlMutexLock(&xmlThrDefMutex);
1088     ret = xmlDoValidityCheckingDefaultValueThrDef;
1089     xmlDoValidityCheckingDefaultValueThrDef = v;
1090     xmlMutexUnlock(&xmlThrDefMutex);
1091     return ret;
1092 }
1093 
xmlThrDefGetWarningsDefaultValue(int v)1094 int xmlThrDefGetWarningsDefaultValue(int v) {
1095     int ret;
1096     xmlMutexLock(&xmlThrDefMutex);
1097     ret = xmlGetWarningsDefaultValueThrDef;
1098     xmlGetWarningsDefaultValueThrDef = v;
1099     xmlMutexUnlock(&xmlThrDefMutex);
1100     return ret;
1101 }
1102 
1103 #ifdef LIBXML_OUTPUT_ENABLED
xmlThrDefIndentTreeOutput(int v)1104 int xmlThrDefIndentTreeOutput(int v) {
1105     int ret;
1106     xmlMutexLock(&xmlThrDefMutex);
1107     ret = xmlIndentTreeOutputThrDef;
1108     xmlIndentTreeOutputThrDef = v;
1109     xmlMutexUnlock(&xmlThrDefMutex);
1110     return ret;
1111 }
1112 
xmlThrDefTreeIndentString(const char * v)1113 const char * xmlThrDefTreeIndentString(const char * v) {
1114     const char * ret;
1115     xmlMutexLock(&xmlThrDefMutex);
1116     ret = xmlTreeIndentStringThrDef;
1117     xmlTreeIndentStringThrDef = v;
1118     xmlMutexUnlock(&xmlThrDefMutex);
1119     return ret;
1120 }
1121 
xmlThrDefSaveNoEmptyTags(int v)1122 int xmlThrDefSaveNoEmptyTags(int v) {
1123     int ret;
1124     xmlMutexLock(&xmlThrDefMutex);
1125     ret = xmlSaveNoEmptyTagsThrDef;
1126     xmlSaveNoEmptyTagsThrDef = v;
1127     xmlMutexUnlock(&xmlThrDefMutex);
1128     return ret;
1129 }
1130 #endif
1131 
xmlThrDefKeepBlanksDefaultValue(int v)1132 int xmlThrDefKeepBlanksDefaultValue(int v) {
1133     int ret;
1134     xmlMutexLock(&xmlThrDefMutex);
1135     ret = xmlKeepBlanksDefaultValueThrDef;
1136     xmlKeepBlanksDefaultValueThrDef = v;
1137     xmlMutexUnlock(&xmlThrDefMutex);
1138     return ret;
1139 }
1140 
xmlThrDefLineNumbersDefaultValue(int v)1141 int xmlThrDefLineNumbersDefaultValue(int v) {
1142     int ret;
1143     xmlMutexLock(&xmlThrDefMutex);
1144     ret = xmlLineNumbersDefaultValueThrDef;
1145     xmlLineNumbersDefaultValueThrDef = v;
1146     xmlMutexUnlock(&xmlThrDefMutex);
1147     return ret;
1148 }
1149 
xmlThrDefLoadExtDtdDefaultValue(int v)1150 int xmlThrDefLoadExtDtdDefaultValue(int v) {
1151     int ret;
1152     xmlMutexLock(&xmlThrDefMutex);
1153     ret = xmlLoadExtDtdDefaultValueThrDef;
1154     xmlLoadExtDtdDefaultValueThrDef = v;
1155     xmlMutexUnlock(&xmlThrDefMutex);
1156     return ret;
1157 }
1158 
xmlThrDefParserDebugEntities(int v ATTRIBUTE_UNUSED)1159 int xmlThrDefParserDebugEntities(int v ATTRIBUTE_UNUSED) {
1160     return(xmlParserDebugEntities);
1161 }
1162 
xmlThrDefPedanticParserDefaultValue(int v)1163 int xmlThrDefPedanticParserDefaultValue(int v) {
1164     int ret;
1165     xmlMutexLock(&xmlThrDefMutex);
1166     ret = xmlPedanticParserDefaultValueThrDef;
1167     xmlPedanticParserDefaultValueThrDef = v;
1168     xmlMutexUnlock(&xmlThrDefMutex);
1169     return ret;
1170 }
1171 
xmlThrDefSubstituteEntitiesDefaultValue(int v)1172 int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
1173     int ret;
1174     xmlMutexLock(&xmlThrDefMutex);
1175     ret = xmlSubstituteEntitiesDefaultValueThrDef;
1176     xmlSubstituteEntitiesDefaultValueThrDef = v;
1177     xmlMutexUnlock(&xmlThrDefMutex);
1178     return ret;
1179 }
1180 
1181 xmlRegisterNodeFunc
xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)1182 xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
1183 {
1184     xmlRegisterNodeFunc old;
1185 
1186     xmlMutexLock(&xmlThrDefMutex);
1187     old = xmlRegisterNodeDefaultValueThrDef;
1188 
1189     __xmlRegisterCallbacks = 1;
1190     xmlRegisterNodeDefaultValueThrDef = func;
1191     xmlMutexUnlock(&xmlThrDefMutex);
1192 
1193     return(old);
1194 }
1195 
1196 xmlDeregisterNodeFunc
xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)1197 xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
1198 {
1199     xmlDeregisterNodeFunc old;
1200 
1201     xmlMutexLock(&xmlThrDefMutex);
1202     old = xmlDeregisterNodeDefaultValueThrDef;
1203 
1204     __xmlRegisterCallbacks = 1;
1205     xmlDeregisterNodeDefaultValueThrDef = func;
1206     xmlMutexUnlock(&xmlThrDefMutex);
1207 
1208     return(old);
1209 }
1210 
1211 xmlParserInputBufferCreateFilenameFunc
xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)1212 xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
1213 {
1214     xmlParserInputBufferCreateFilenameFunc old;
1215 
1216     xmlMutexLock(&xmlThrDefMutex);
1217     old = xmlParserInputBufferCreateFilenameValueThrDef;
1218     if (old == NULL) {
1219 		old = __xmlParserInputBufferCreateFilename;
1220 	}
1221 
1222     xmlParserInputBufferCreateFilenameValueThrDef = func;
1223     xmlMutexUnlock(&xmlThrDefMutex);
1224 
1225     return(old);
1226 }
1227 
1228 xmlOutputBufferCreateFilenameFunc
xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)1229 xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
1230 {
1231     xmlOutputBufferCreateFilenameFunc old;
1232 
1233     xmlMutexLock(&xmlThrDefMutex);
1234     old = xmlOutputBufferCreateFilenameValueThrDef;
1235 #ifdef LIBXML_OUTPUT_ENABLED
1236     if (old == NULL) {
1237 		old = __xmlOutputBufferCreateFilename;
1238 	}
1239 #endif
1240     xmlOutputBufferCreateFilenameValueThrDef = func;
1241     xmlMutexUnlock(&xmlThrDefMutex);
1242 
1243     return(old);
1244 }
1245 
1246