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