cpython/Modules/expat/xmlparse.c

/* c5625880f4bf417c1463deee4eb92d86ff413f802048621c57e25fe483eb59e4 (2.6.4+)
                            __  __            _
                         ___\ \/ /_ __   __ _| |_
                        / _ \\  /| '_ \ / _` | __|
                       |  __//  \| |_) | (_| | |_
                        \___/_/\_\ .__/ \__,_|\__|
                                 |_| XML parser

   Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
   Copyright (c) 2000      Clark Cooper <[email protected]>
   Copyright (c) 2000-2006 Fred L. Drake, Jr. <[email protected]>
   Copyright (c) 2001-2002 Greg Stein <[email protected]>
   Copyright (c) 2002-2016 Karl Waclawek <[email protected]>
   Copyright (c) 2005-2009 Steven Solie <[email protected]>
   Copyright (c) 2016      Eric Rahm <[email protected]>
   Copyright (c) 2016-2024 Sebastian Pipping <[email protected]>
   Copyright (c) 2016      Gaurav <[email protected]>
   Copyright (c) 2016      Thomas Beutlich <[email protected]>
   Copyright (c) 2016      Gustavo Grieco <[email protected]>
   Copyright (c) 2016      Pascal Cuoq <[email protected]>
   Copyright (c) 2016      Ed Schouten <[email protected]>
   Copyright (c) 2017-2022 Rhodri James <[email protected]>
   Copyright (c) 2017      Václav Slavík <[email protected]>
   Copyright (c) 2017      Viktor Szakats <[email protected]>
   Copyright (c) 2017      Chanho Park <[email protected]>
   Copyright (c) 2017      Rolf Eike Beer <[email protected]>
   Copyright (c) 2017      Hans Wennborg <[email protected]>
   Copyright (c) 2018      Anton Maklakov <[email protected]>
   Copyright (c) 2018      Benjamin Peterson <[email protected]>
   Copyright (c) 2018      Marco Maggi <[email protected]>
   Copyright (c) 2018      Mariusz Zaborski <[email protected]>
   Copyright (c) 2019      David Loffredo <[email protected]>
   Copyright (c) 2019-2020 Ben Wagner <[email protected]>
   Copyright (c) 2019      Vadim Zeitlin <[email protected]>
   Copyright (c) 2021      Donghee Na <[email protected]>
   Copyright (c) 2022      Samanta Navarro <[email protected]>
   Copyright (c) 2022      Jeffrey Walton <[email protected]>
   Copyright (c) 2022      Jann Horn <[email protected]>
   Copyright (c) 2022      Sean McBride <[email protected]>
   Copyright (c) 2023      Owain Davies <[email protected]>
   Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <[email protected]>
   Copyright (c) 2024      Berkay Eren Ürün <[email protected]>
   Copyright (c) 2024      Hanno Böck <[email protected]>
   Licensed under the MIT license:

   Permission is  hereby granted,  free of charge,  to any  person obtaining
   a  copy  of  this  software   and  associated  documentation  files  (the
   "Software"),  to  deal in  the  Software  without restriction,  including
   without  limitation the  rights  to use,  copy,  modify, merge,  publish,
   distribute, sublicense, and/or sell copies of the Software, and to permit
   persons  to whom  the Software  is  furnished to  do so,  subject to  the
   following conditions:

   The above copyright  notice and this permission notice  shall be included
   in all copies or substantial portions of the Software.

   THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
   EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
   NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
   DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
   OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
   USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#define XML_BUILDING_EXPAT

#include "expat_config.h"

#if ! defined(XML_GE) || (1 - XML_GE - 1 == 2) || (XML_GE < 0) || (XML_GE > 1)
#  error XML_GE (for general entities) must be defined, non-empty, either 1 or 0 (0 to disable, 1 to enable; 1 is a common default)
#endif

#if defined(XML_DTD) && XML_GE == 0
#  error Either undefine XML_DTD or define XML_GE to 1.
#endif

#if ! defined(XML_CONTEXT_BYTES) || (1 - XML_CONTEXT_BYTES - 1 == 2)           \
    || (XML_CONTEXT_BYTES + 0 < 0)
#  error XML_CONTEXT_BYTES must be defined, non-empty and >=0 (0 to disable, >=1 to enable; 1024 is a common default)
#endif

#if defined(HAVE_SYSCALL_GETRANDOM)
#  if ! defined(_GNU_SOURCE)
#define _GNU_SOURCE
#  endif
#endif

#ifdef _WIN32
/* force stdlib to define rand_s() */
#  if ! defined(_CRT_RAND_S)
#define _CRT_RAND_S
#  endif
#endif

#include <stdbool.h>
#include <stddef.h>
#include <string.h> /* memset(), memcpy() */
#include <assert.h>
#include <limits.h> /* UINT_MAX */
#include <stdio.h>  /* fprintf */
#include <stdlib.h> /* getenv, rand_s */
#include <stdint.h> /* uintptr_t */
#include <math.h>   /* isnan */

#ifdef _WIN32
#define getpid
#else
#  include <sys/time.h>  /* gettimeofday() */
#  include <sys/types.h> /* getpid() */
#  include <unistd.h>    /* getpid() */
#  include <fcntl.h>     /* O_RDONLY */
#  include <errno.h>
#endif

#ifdef _WIN32
#  include "winconfig.h"
#endif

#include "ascii.h"
#include "expat.h"
#include "siphash.h"

#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
#  if defined(HAVE_GETRANDOM)
#    include <sys/random.h> /* getrandom */
#  else
#    include <unistd.h>      /* syscall */
#    include <sys/syscall.h> /* SYS_getrandom */
#  endif
#  if ! defined(GRND_NONBLOCK)
#define GRND_NONBLOCK
#  endif /* defined(GRND_NONBLOCK) */
#endif   /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */

#if defined(HAVE_LIBBSD)                                                       \
    && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
#  include <bsd/stdlib.h>
#endif

#if defined(_WIN32) && ! defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
#define LOAD_LIBRARY_SEARCH_SYSTEM32
#endif

#if ! defined(HAVE_GETRANDOM) && ! defined(HAVE_SYSCALL_GETRANDOM)             \
    && ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)            \
    && ! defined(XML_DEV_URANDOM) && ! defined(_WIN32)                         \
    && ! defined(XML_POOR_ENTROPY)
#  error You do not have support for any sources of high quality entropy \
    enabled.  For end user security, that is probably not what you want. \
    \
    Your options include: \
      * Linux >=3.17 + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \
      * Linux >=3.17 + glibc (including <2.25) (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \
      * BSD / macOS >=10.7 / glibc >=2.36 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \
      * BSD / macOS (including <10.7) / glibc >=2.36 (arc4random): HAVE_ARC4RANDOM, \
      * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
      * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
      * Linux (including <3.17) / BSD / macOS (including <10.7) / Solaris >=8 (/dev/urandom): XML_DEV_URANDOM, \
      * Windows >=Vista (rand_s): _WIN32. \
    \
    If insist on not using any of these, bypass this error by defining \
    XML_POOR_ENTROPY; you have been warned. \
    \
    If you have reasons to patch this detection code away or need changes \
    to the build system, please open a bug.  Thank you!
#endif

#ifdef XML_UNICODE
#define XML_ENCODE_MAX
#define XmlConvert
#define XmlGetInternalEncoding
#define XmlGetInternalEncodingNS
#define XmlEncode
#define MUST_CONVERT
typedef unsigned short ICHAR;
#else
#define XML_ENCODE_MAX
#define XmlConvert
#define XmlGetInternalEncoding
#define XmlGetInternalEncodingNS
#define XmlEncode
#define MUST_CONVERT(enc, s)
ICHAR;
#endif

#ifndef XML_NS

#define XmlInitEncodingNS
#define XmlInitUnknownEncodingNS
#  undef XmlGetInternalEncodingNS
#define XmlGetInternalEncodingNS
#define XmlParseXmlDeclNS

#endif

#ifdef XML_UNICODE

#  ifdef XML_UNICODE_WCHAR_T
#define XML_T
#define XML_L
#  else
#define XML_T
#define XML_L
#  endif

#else

#define XML_T(x)
#define XML_L(x)

#endif

/* Round up n to be a multiple of sz, where sz is a power of 2. */
#define ROUND_UP(n, sz)

/* Do safe (NULL-aware) pointer arithmetic */
#define EXPAT_SAFE_PTR_DIFF(p, q)

#define EXPAT_MIN(a, b)

#include "internal.h"
#include "xmltok.h"
#include "xmlrole.h"

KEY;

NAMED;

HASH_TABLE;

static size_t keylen(KEY s);

static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key);

/* For probing (after a collision) we need a step size relative prime
   to the hash table size, which is a power of 2. We use double-hashing,
   since we can calculate a second hash value cheaply by taking those bits
   of the first hash value that were discarded (masked out) when the table
   index was calculated: index = hash & mask, where mask = table->size - 1.
   We limit the maximum step size to table->size / 4 (mask >> 2) and make
   it odd, since odd numbers are always relative prime to a power of 2.
*/
#define SECOND_HASH(hash, mask, power)
#define PROBE_STEP(hash, mask, power)

HASH_TABLE_ITER;

#define INIT_TAG_BUF_SIZE
#define INIT_DATA_BUF_SIZE
#define INIT_ATTS_SIZE
#define INIT_ATTS_VERSION
#define INIT_BLOCK_SIZE
#define INIT_BUFFER_SIZE

#define EXPAND_SPARE

BINDING;

PREFIX;

TAG_NAME;

/* TAG represents an open element.
   The name of the element is stored in both the document and API
   encodings.  The memory buffer 'buf' is a separately-allocated
   memory area which stores the name.  During the XML_Parse()/
   XML_ParseBuffer() when the element is open, the memory for the 'raw'
   version of the name (in the document encoding) is shared with the
   document buffer.  If the element is open across calls to
   XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
   contain the 'raw' name as well.

   A parser reuses these structures, maintaining a list of allocated
   TAG objects in a free list.
*/
TAG;

ENTITY;

CONTENT_SCAFFOLD;

#define INIT_SCAFFOLD_ELEMENTS

BLOCK;

STRING_POOL;

/* The XML_Char before the name is used to determine whether
   an attribute has been specified. */
ATTRIBUTE_ID;

DEFAULT_ATTRIBUTE;

NS_ATT;

ELEMENT_TYPE;

DTD;

OPEN_INTERNAL_ENTITY;

enum XML_Account {};

#if XML_GE == 1
XmlBigCount;
ACCOUNTING;

ENTITY_STATS;
#endif /* XML_GE == 1 */

Processor;

static Processor prologProcessor;
static Processor prologInitProcessor;
static Processor contentProcessor;
static Processor cdataSectionProcessor;
#ifdef XML_DTD
static Processor ignoreSectionProcessor;
static Processor externalParEntProcessor;
static Processor externalParEntInitProcessor;
static Processor entityValueProcessor;
static Processor entityValueInitProcessor;
#endif /* XML_DTD */
static Processor epilogProcessor;
static Processor errorProcessor;
static Processor externalEntityInitProcessor;
static Processor externalEntityInitProcessor2;
static Processor externalEntityInitProcessor3;
static Processor externalEntityContentProcessor;
static Processor internalEntityProcessor;

static enum XML_Error handleUnknownEncoding(XML_Parser parser,
                                            const XML_Char *encodingName);
static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
                                     const char *s, const char *next);
static enum XML_Error initializeEncoding(XML_Parser parser);
static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
                               const char *s, const char *end, int tok,
                               const char *next, const char **nextPtr,
                               XML_Bool haveMore, XML_Bool allowClosingDoctype,
                               enum XML_Account account);
static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
                                            XML_Bool betweenDecl);
static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
                                const ENCODING *enc, const char *start,
                                const char *end, const char **endPtr,
                                XML_Bool haveMore, enum XML_Account account);
static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *enc,
                                     const char **startPtr, const char *end,
                                     const char **nextPtr, XML_Bool haveMore,
                                     enum XML_Account account);
#ifdef XML_DTD
static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *enc,
                                      const char **startPtr, const char *end,
                                      const char **nextPtr, XML_Bool haveMore);
#endif /* XML_DTD */

static void freeBindings(XML_Parser parser, BINDING *bindings);
static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
                                const char *attStr, TAG_NAME *tagNamePtr,
                                BINDING **bindingsPtr,
                                enum XML_Account account);
static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
                                 const ATTRIBUTE_ID *attId, const XML_Char *uri,
                                 BINDING **bindingsPtr);
static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId,
                           XML_Bool isCdata, XML_Bool isId,
                           const XML_Char *value, XML_Parser parser);
static enum XML_Error storeAttributeValue(XML_Parser parser,
                                          const ENCODING *enc, XML_Bool isCdata,
                                          const char *ptr, const char *end,
                                          STRING_POOL *pool,
                                          enum XML_Account account);
static enum XML_Error appendAttributeValue(XML_Parser parser,
                                           const ENCODING *enc,
                                           XML_Bool isCdata, const char *ptr,
                                           const char *end, STRING_POOL *pool,
                                           enum XML_Account account);
static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
                                    const char *start, const char *end);
static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType);
#if XML_GE == 1
static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
                                       const char *start, const char *end,
                                       enum XML_Account account);
#else
static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity);
#endif
static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
                                       const char *start, const char *end);
static int reportComment(XML_Parser parser, const ENCODING *enc,
                         const char *start, const char *end);
static void reportDefault(XML_Parser parser, const ENCODING *enc,
                          const char *start, const char *end);

static const XML_Char *getContext(XML_Parser parser);
static XML_Bool setContext(XML_Parser parser, const XML_Char *context);

static void FASTCALL normalizePublicId(XML_Char *s);

static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms);
/* do not call if m_parentParser != NULL */
static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
static void dtdDestroy(DTD *p, XML_Bool isDocEntity,
                       const XML_Memory_Handling_Suite *ms);
static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
                   const XML_Memory_Handling_Suite *ms);
static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
                           STRING_POOL *newPool, const HASH_TABLE *oldTable);
static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
                     size_t createSize);
static void FASTCALL hashTableInit(HASH_TABLE *table,
                                   const XML_Memory_Handling_Suite *ms);
static void FASTCALL hashTableClear(HASH_TABLE *table);
static void FASTCALL hashTableDestroy(HASH_TABLE *table);
static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter,
                                       const HASH_TABLE *table);
static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter);

static void FASTCALL poolInit(STRING_POOL *pool,
                              const XML_Memory_Handling_Suite *ms);
static void FASTCALL poolClear(STRING_POOL *pool);
static void FASTCALL poolDestroy(STRING_POOL *pool);
static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
                            const char *ptr, const char *end);
static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
                                 const char *ptr, const char *end);
static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
                                               const XML_Char *s);
static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
                                       int n);
static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
                                                 const XML_Char *s);

static int FASTCALL nextScaffoldPart(XML_Parser parser);
static XML_Content *build_model(XML_Parser parser);
static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
                                    const char *ptr, const char *end);

static XML_Char *copyString(const XML_Char *s,
                            const XML_Memory_Handling_Suite *memsuite);

static unsigned long generate_hash_secret_salt(XML_Parser parser);
static XML_Bool startParsing(XML_Parser parser);

static XML_Parser parserCreate(const XML_Char *encodingName,
                               const XML_Memory_Handling_Suite *memsuite,
                               const XML_Char *nameSep, DTD *dtd);

static void parserInit(XML_Parser parser, const XML_Char *encodingName);

#if XML_GE == 1
static float accountingGetCurrentAmplification(XML_Parser rootParser);
static void accountingReportStats(XML_Parser originParser, const char *epilog);
static void accountingOnAbort(XML_Parser originParser);
static void accountingReportDiff(XML_Parser rootParser,
                                 unsigned int levelsAwayFromRootParser,
                                 const char *before, const char *after,
                                 ptrdiff_t bytesMore, int source_line,
                                 enum XML_Account account);
static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok,
                                        const char *before, const char *after,
                                        int source_line,
                                        enum XML_Account account);

static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity,
                                      const char *action, int sourceLine);
static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity,
                                 int sourceLine);
static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity,
                                  int sourceLine);

static XML_Parser getRootParserOf(XML_Parser parser,
                                  unsigned int *outLevelDiff);
#endif /* XML_GE == 1 */

static unsigned long getDebugLevel(const char *variableName,
                                   unsigned long defaultDebugLevel);

#define poolStart(pool)
#define poolLength(pool)
#define poolChop(pool)
#define poolLastChar(pool)
#define poolDiscard(pool)
#define poolFinish(pool)
#define poolAppendChar(pool, c)

#if ! defined(XML_TESTING)
const
#endif
    XML_Bool g_reparseDeferralEnabledDefault
    =; // write ONLY in runtests.c
#if defined(XML_TESTING)
unsigned int g_bytesScanned = 0; // used for testing only
#endif

struct XML_ParserStruct {};

#define MALLOC(parser, s)
#define REALLOC(parser, p, s)
#define FREE(parser, p)

XML_Parser XMLCALL
XML_ParserCreate(const XML_Char *encodingName) {}

XML_Parser XMLCALL
XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {}

// "xml=http://www.w3.org/XML/1998/namespace"
static const XML_Char implicitContext[]
    =;

/* To avoid warnings about unused functions: */
#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)

#  if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)

/* Obtain entropy on Linux 3.17+ */
static int
writeRandomBytes_getrandom_nonblock(void *target, size_t count) {}

#  endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */

#  if ! defined(_WIN32) && defined(XML_DEV_URANDOM)

/* Extract entropy from /dev/urandom */
static int
writeRandomBytes_dev_urandom(void *target, size_t count) {
  int success = 0; /* full count bytes written? */
  size_t bytesWrittenTotal = 0;

  const int fd = open("/dev/urandom", O_RDONLY);
  if (fd < 0) {
    return 0;
  }

  do {
    void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
    const size_t bytesToWrite = count - bytesWrittenTotal;

    const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);

    if (bytesWrittenMore > 0) {
      bytesWrittenTotal += bytesWrittenMore;
      if (bytesWrittenTotal >= count)
        success = 1;
    }
  } while (! success && (errno == EINTR));

  close(fd);
  return success;
}

#  endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */

#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */

#if defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF)

static void
writeRandomBytes_arc4random(void *target, size_t count) {
  size_t bytesWrittenTotal = 0;

  while (bytesWrittenTotal < count) {
    const uint32_t random32 = arc4random();
    size_t i = 0;

    for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
         i++, bytesWrittenTotal++) {
      const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
      ((uint8_t *)target)[bytesWrittenTotal] = random8;
    }
  }
}

#endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */

#ifdef _WIN32

/* Provide declaration of rand_s() for MinGW-32 (not 64, which has it),
   as it didn't declare it in its header prior to version 5.3.0 of its
   runtime package (mingwrt, containing stdlib.h).  The upstream fix
   was introduced at https://osdn.net/projects/mingw/ticket/39658 . */
#  if defined(__MINGW32__) && defined(__MINGW32_VERSION)                       \
      && __MINGW32_VERSION < 5003000L && ! defined(__MINGW64_VERSION_MAJOR)
__declspec(dllimport) int rand_s(unsigned int *);
#  endif

/* Obtain entropy on Windows using the rand_s() function which
 * generates cryptographically secure random numbers.  Internally it
 * uses RtlGenRandom API which is present in Windows XP and later.
 */
static int
writeRandomBytes_rand_s(void *target, size_t count) {
  size_t bytesWrittenTotal = 0;

  while (bytesWrittenTotal < count) {
    unsigned int random32 = 0;
    size_t i = 0;

    if (rand_s(&random32))
      return 0; /* failure */

    for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
         i++, bytesWrittenTotal++) {
      const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
      ((uint8_t *)target)[bytesWrittenTotal] = random8;
    }
  }
  return 1; /* success */
}

#endif /* _WIN32 */

#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)

static unsigned long
gather_time_entropy(void) {}

#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */

static unsigned long
ENTROPY_DEBUG(const char *label, unsigned long entropy) {}

static unsigned long
generate_hash_secret_salt(XML_Parser parser) {}

static unsigned long
get_hash_secret_salt(XML_Parser parser) {}

static enum XML_Error
callProcessor(XML_Parser parser, const char *start, const char *end,
              const char **endPtr) {}

static XML_Bool /* only valid for root parser */
startParsing(XML_Parser parser) {}

XML_Parser XMLCALL
XML_ParserCreate_MM(const XML_Char *encodingName,
                    const XML_Memory_Handling_Suite *memsuite,
                    const XML_Char *nameSep) {}

static XML_Parser
parserCreate(const XML_Char *encodingName,
             const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep,
             DTD *dtd) {}

static void
parserInit(XML_Parser parser, const XML_Char *encodingName) {}

/* moves list of bindings to m_freeBindingList */
static void FASTCALL
moveToFreeBindingList(XML_Parser parser, BINDING *bindings) {}

XML_Bool XMLCALL
XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {}

enum XML_Status XMLCALL
XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {}

XML_Parser XMLCALL
XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
                               const XML_Char *encodingName) {}

static void FASTCALL
destroyBindings(BINDING *bindings, XML_Parser parser) {}

void XMLCALL
XML_ParserFree(XML_Parser parser) {}

void XMLCALL
XML_UseParserAsHandlerArg(XML_Parser parser) {}

enum XML_Error XMLCALL
XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) {}

void XMLCALL
XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {}

void XMLCALL
XML_SetUserData(XML_Parser parser, void *p) {}

enum XML_Status XMLCALL
XML_SetBase(XML_Parser parser, const XML_Char *p) {}

const XML_Char *XMLCALL
XML_GetBase(XML_Parser parser) {}

int XMLCALL
XML_GetSpecifiedAttributeCount(XML_Parser parser) {}

int XMLCALL
XML_GetIdAttributeIndex(XML_Parser parser) {}

#ifdef XML_ATTR_INFO
const XML_AttrInfo *XMLCALL
XML_GetAttributeInfo(XML_Parser parser) {
  if (parser == NULL)
    return NULL;
  return parser->m_attInfo;
}
#endif

void XMLCALL
XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start,
                      XML_EndElementHandler end) {}

void XMLCALL
XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) {}

void XMLCALL
XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) {}

void XMLCALL
XML_SetCharacterDataHandler(XML_Parser parser,
                            XML_CharacterDataHandler handler) {}

void XMLCALL
XML_SetProcessingInstructionHandler(XML_Parser parser,
                                    XML_ProcessingInstructionHandler handler) {}

void XMLCALL
XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) {}

void XMLCALL
XML_SetCdataSectionHandler(XML_Parser parser,
                           XML_StartCdataSectionHandler start,
                           XML_EndCdataSectionHandler end) {}

void XMLCALL
XML_SetStartCdataSectionHandler(XML_Parser parser,
                                XML_StartCdataSectionHandler start) {}

void XMLCALL
XML_SetEndCdataSectionHandler(XML_Parser parser,
                              XML_EndCdataSectionHandler end) {}

void XMLCALL
XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) {}

void XMLCALL
XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) {}

void XMLCALL
XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start,
                          XML_EndDoctypeDeclHandler end) {}

void XMLCALL
XML_SetStartDoctypeDeclHandler(XML_Parser parser,
                               XML_StartDoctypeDeclHandler start) {}

void XMLCALL
XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) {}

void XMLCALL
XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
                                 XML_UnparsedEntityDeclHandler handler) {}

void XMLCALL
XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) {}

void XMLCALL
XML_SetNamespaceDeclHandler(XML_Parser parser,
                            XML_StartNamespaceDeclHandler start,
                            XML_EndNamespaceDeclHandler end) {}

void XMLCALL
XML_SetStartNamespaceDeclHandler(XML_Parser parser,
                                 XML_StartNamespaceDeclHandler start) {}

void XMLCALL
XML_SetEndNamespaceDeclHandler(XML_Parser parser,
                               XML_EndNamespaceDeclHandler end) {}

void XMLCALL
XML_SetNotStandaloneHandler(XML_Parser parser,
                            XML_NotStandaloneHandler handler) {}

void XMLCALL
XML_SetExternalEntityRefHandler(XML_Parser parser,
                                XML_ExternalEntityRefHandler handler) {}

void XMLCALL
XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) {}

void XMLCALL
XML_SetSkippedEntityHandler(XML_Parser parser,
                            XML_SkippedEntityHandler handler) {}

void XMLCALL
XML_SetUnknownEncodingHandler(XML_Parser parser,
                              XML_UnknownEncodingHandler handler, void *data) {}

void XMLCALL
XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) {}

void XMLCALL
XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) {}

void XMLCALL
XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) {}

void XMLCALL
XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) {}

int XMLCALL
XML_SetParamEntityParsing(XML_Parser parser,
                          enum XML_ParamEntityParsing peParsing) {}

int XMLCALL
XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {}

enum XML_Status XMLCALL
XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {}

enum XML_Status XMLCALL
XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {}

void *XMLCALL
XML_GetBuffer(XML_Parser parser, int len) {}

enum XML_Status XMLCALL
XML_StopParser(XML_Parser parser, XML_Bool resumable) {}

enum XML_Status XMLCALL
XML_ResumeParser(XML_Parser parser) {}

void XMLCALL
XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) {}

enum XML_Error XMLCALL
XML_GetErrorCode(XML_Parser parser) {}

XML_Index XMLCALL
XML_GetCurrentByteIndex(XML_Parser parser) {}

int XMLCALL
XML_GetCurrentByteCount(XML_Parser parser) {}

const char *XMLCALL
XML_GetInputContext(XML_Parser parser, int *offset, int *size) {}

XML_Size XMLCALL
XML_GetCurrentLineNumber(XML_Parser parser) {}

XML_Size XMLCALL
XML_GetCurrentColumnNumber(XML_Parser parser) {}

void XMLCALL
XML_FreeContentModel(XML_Parser parser, XML_Content *model) {}

void *XMLCALL
XML_MemMalloc(XML_Parser parser, size_t size) {}

void *XMLCALL
XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) {}

void XMLCALL
XML_MemFree(XML_Parser parser, void *ptr) {}

void XMLCALL
XML_DefaultCurrent(XML_Parser parser) {}

const XML_LChar *XMLCALL
XML_ErrorString(enum XML_Error code) {}

const XML_LChar *XMLCALL
XML_ExpatVersion(void) {}

XML_Expat_Version XMLCALL
XML_ExpatVersionInfo(void) {}

const XML_Feature *XMLCALL
XML_GetFeatureList(void) {}

#if XML_GE == 1
XML_Bool XMLCALL
XML_SetBillionLaughsAttackProtectionMaximumAmplification(
    XML_Parser parser, float maximumAmplificationFactor) {}

XML_Bool XMLCALL
XML_SetBillionLaughsAttackProtectionActivationThreshold(
    XML_Parser parser, unsigned long long activationThresholdBytes) {}
#endif /* XML_GE == 1 */

XML_Bool XMLCALL
XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled) {}

/* Initially tag->rawName always points into the parse buffer;
   for those TAG instances opened while the current parse buffer was
   processed, and not yet closed, we need to store tag->rawName in a more
   permanent location, since the parse buffer is about to be discarded.
*/
static XML_Bool
storeRawNames(XML_Parser parser) {}

static enum XML_Error PTRCALL
contentProcessor(XML_Parser parser, const char *start, const char *end,
                 const char **endPtr) {}

static enum XML_Error PTRCALL
externalEntityInitProcessor(XML_Parser parser, const char *start,
                            const char *end, const char **endPtr) {}

static enum XML_Error PTRCALL
externalEntityInitProcessor2(XML_Parser parser, const char *start,
                             const char *end, const char **endPtr) {}

static enum XML_Error PTRCALL
externalEntityInitProcessor3(XML_Parser parser, const char *start,
                             const char *end, const char **endPtr) {}

static enum XML_Error PTRCALL
externalEntityContentProcessor(XML_Parser parser, const char *start,
                               const char *end, const char **endPtr) {}

static enum XML_Error
doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
          const char *s, const char *end, const char **nextPtr,
          XML_Bool haveMore, enum XML_Account account) {}

/* This function does not call free() on the allocated memory, merely
 * moving it to the parser's m_freeBindingList where it can be freed or
 * reused as appropriate.
 */
static void
freeBindings(XML_Parser parser, BINDING *bindings) {}

/* Precondition: all arguments must be non-NULL;
   Purpose:
   - normalize attributes
   - check attributes for well-formedness
   - generate namespace aware attribute names (URI, prefix)
   - build list of attributes for startElementHandler
   - default attributes
   - process namespace declarations (check and report them)
   - generate namespace aware element name (URI, prefix)
*/
static enum XML_Error
storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
          TAG_NAME *tagNamePtr, BINDING **bindingsPtr,
          enum XML_Account account) {}

static XML_Bool
is_rfc3986_uri_char(XML_Char candidate) {}

/* addBinding() overwrites the value of prefix->binding without checking.
   Therefore one must keep track of the old value outside of addBinding().
*/
static enum XML_Error
addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
           const XML_Char *uri, BINDING **bindingsPtr) {}

/* The idea here is to avoid using stack for each CDATA section when
   the whole file is parsed with one call.
*/
static enum XML_Error PTRCALL
cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
                      const char **endPtr) {}

/* startPtr gets set to non-null if the section is closed, and to null if
   the section is not yet closed.
*/
static enum XML_Error
doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
               const char *end, const char **nextPtr, XML_Bool haveMore,
               enum XML_Account account) {}

#ifdef XML_DTD

/* The idea here is to avoid using stack for each IGNORE section when
   the whole file is parsed with one call.
*/
static enum XML_Error PTRCALL
ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end,
                       const char **endPtr) {}

/* startPtr gets set to non-null is the section is closed, and to null
   if the section is not yet closed.
*/
static enum XML_Error
doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
                const char *end, const char **nextPtr, XML_Bool haveMore) {}

#endif /* XML_DTD */

static enum XML_Error
initializeEncoding(XML_Parser parser) {}

static enum XML_Error
processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
               const char *next) {}

static enum XML_Error
handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) {}

static enum XML_Error PTRCALL
prologInitProcessor(XML_Parser parser, const char *s, const char *end,
                    const char **nextPtr) {}

#ifdef XML_DTD

static enum XML_Error PTRCALL
externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
                            const char **nextPtr) {}

static enum XML_Error PTRCALL
entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
                         const char **nextPtr) {}

static enum XML_Error PTRCALL
externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
                        const char **nextPtr) {}

static enum XML_Error PTRCALL
entityValueProcessor(XML_Parser parser, const char *s, const char *end,
                     const char **nextPtr) {}

#endif /* XML_DTD */

static enum XML_Error PTRCALL
prologProcessor(XML_Parser parser, const char *s, const char *end,
                const char **nextPtr) {}

static enum XML_Error
doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
         int tok, const char *next, const char **nextPtr, XML_Bool haveMore,
         XML_Bool allowClosingDoctype, enum XML_Account account) {}

static enum XML_Error PTRCALL
epilogProcessor(XML_Parser parser, const char *s, const char *end,
                const char **nextPtr) {}

static enum XML_Error
processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {}

static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
                        const char **nextPtr) {}

static enum XML_Error PTRCALL
errorProcessor(XML_Parser parser, const char *s, const char *end,
               const char **nextPtr) {}

static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
                    const char *ptr, const char *end, STRING_POOL *pool,
                    enum XML_Account account) {}

static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
                     const char *ptr, const char *end, STRING_POOL *pool,
                     enum XML_Account account) {}

#if XML_GE == 1
static enum XML_Error
storeEntityValue(XML_Parser parser, const ENCODING *enc,
                 const char *entityTextPtr, const char *entityTextEnd,
                 enum XML_Account account) {}

#else /* XML_GE == 0 */

static enum XML_Error
storeSelfEntityValue(XML_Parser parser, ENTITY *entity) {
  // This will store "&amp;entity123;" in entity->textPtr
  // to end up as "&entity123;" in the handler.
  const char *const entity_start = "&amp;";
  const char *const entity_end = ";";

  STRING_POOL *const pool = &(parser->m_dtd->entityValuePool);
  if (! poolAppendString(pool, entity_start)
      || ! poolAppendString(pool, entity->name)
      || ! poolAppendString(pool, entity_end)) {
    poolDiscard(pool);
    return XML_ERROR_NO_MEMORY;
  }

  entity->textPtr = poolStart(pool);
  entity->textLen = (int)(poolLength(pool));
  poolFinish(pool);

  return XML_ERROR_NONE;
}

#endif /* XML_GE == 0 */

static void FASTCALL
normalizeLines(XML_Char *s) {}

static int
reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
                            const char *start, const char *end) {}

static int
reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
              const char *end) {}

static void
reportDefault(XML_Parser parser, const ENCODING *enc, const char *s,
              const char *end) {}

static int
defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
                XML_Bool isId, const XML_Char *value, XML_Parser parser) {}

static int
setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) {}

static ATTRIBUTE_ID *
getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
               const char *end) {}

#define CONTEXT_SEP

static const XML_Char *
getContext(XML_Parser parser) {}

static XML_Bool
setContext(XML_Parser parser, const XML_Char *context) {}

static void FASTCALL
normalizePublicId(XML_Char *publicId) {}

static DTD *
dtdCreate(const XML_Memory_Handling_Suite *ms) {}

static void
dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {}

static void
dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {}

/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
   The new DTD has already been initialized.
*/
static int
dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
        const XML_Memory_Handling_Suite *ms) {} /* End dtdCopy */

static int
copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
                STRING_POOL *newPool, const HASH_TABLE *oldTable) {}

#define INIT_POWER

static XML_Bool FASTCALL
keyeq(KEY s1, KEY s2) {}

static size_t
keylen(KEY s) {}

static void
copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {}

static unsigned long FASTCALL
hash(XML_Parser parser, KEY s) {}

static NAMED *
lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {}

static void FASTCALL
hashTableClear(HASH_TABLE *table) {}

static void FASTCALL
hashTableDestroy(HASH_TABLE *table) {}

static void FASTCALL
hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) {}

static void FASTCALL
hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {}

static NAMED *FASTCALL
hashTableIterNext(HASH_TABLE_ITER *iter) {}

static void FASTCALL
poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) {}

static void FASTCALL
poolClear(STRING_POOL *pool) {}

static void FASTCALL
poolDestroy(STRING_POOL *pool) {}

static XML_Char *
poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
           const char *end) {}

static const XML_Char *FASTCALL
poolCopyString(STRING_POOL *pool, const XML_Char *s) {}

static const XML_Char *
poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) {}

static const XML_Char *FASTCALL
poolAppendString(STRING_POOL *pool, const XML_Char *s) {}

static XML_Char *
poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
                const char *end) {}

static size_t
poolBytesToAllocateFor(int blockSize) {}

static XML_Bool FASTCALL
poolGrow(STRING_POOL *pool) {}

static int FASTCALL
nextScaffoldPart(XML_Parser parser) {}

static XML_Content *
build_model(XML_Parser parser) {}

static ELEMENT_TYPE *
getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
               const char *end) {}

static XML_Char *
copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {}

#if XML_GE == 1

static float
accountingGetCurrentAmplification(XML_Parser rootParser) {}

static void
accountingReportStats(XML_Parser originParser, const char *epilog) {}

static void
accountingOnAbort(XML_Parser originParser) {}

static void
accountingReportDiff(XML_Parser rootParser,
                     unsigned int levelsAwayFromRootParser, const char *before,
                     const char *after, ptrdiff_t bytesMore, int source_line,
                     enum XML_Account account) {}

static XML_Bool
accountingDiffTolerated(XML_Parser originParser, int tok, const char *before,
                        const char *after, int source_line,
                        enum XML_Account account) {}

unsigned long long
testingAccountingGetCountBytesDirect(XML_Parser parser) {}

unsigned long long
testingAccountingGetCountBytesIndirect(XML_Parser parser) {}

static void
entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
                          const char *action, int sourceLine) {}

static void
entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) {}

static void
entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) {}

static XML_Parser
getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {}

const char *
unsignedCharToPrintable(unsigned char c) {}

#endif /* XML_GE == 1 */

static unsigned long
getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {}