Coverage Report

Created: 2024-09-06 07:53

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