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