Home | History | Annotate | Line # | Download | only in lib
      1  1.11       wiz /* d19ae032c224863c1527ba44d228cc34b99192c3a4c5a27af1f4e054d45ee031 (2.7.1+)
      2   1.8      maya                             __  __            _
      3   1.8      maya                          ___\ \/ /_ __   __ _| |_
      4   1.8      maya                         / _ \\  /| '_ \ / _` | __|
      5   1.8      maya                        |  __//  \| |_) | (_| | |_
      6   1.8      maya                         \___/_/\_\ .__/ \__,_|\__|
      7   1.8      maya                                  |_| XML parser
      8   1.8      maya 
      9   1.8      maya    Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
     10   1.9  christos    Copyright (c) 2000      Clark Cooper <coopercc (at) users.sourceforge.net>
     11   1.9  christos    Copyright (c) 2000-2006 Fred L. Drake, Jr. <fdrake (at) users.sourceforge.net>
     12   1.9  christos    Copyright (c) 2001-2002 Greg Stein <gstein (at) users.sourceforge.net>
     13   1.9  christos    Copyright (c) 2002-2016 Karl Waclawek <karl (at) waclawek.net>
     14   1.9  christos    Copyright (c) 2005-2009 Steven Solie <steven (at) solie.ca>
     15   1.9  christos    Copyright (c) 2016      Eric Rahm <erahm (at) mozilla.com>
     16  1.10       wiz    Copyright (c) 2016-2025 Sebastian Pipping <sebastian (at) pipping.org>
     17   1.9  christos    Copyright (c) 2016      Gaurav <g.gupta (at) samsung.com>
     18   1.9  christos    Copyright (c) 2016      Thomas Beutlich <tc (at) tbeu.de>
     19   1.9  christos    Copyright (c) 2016      Gustavo Grieco <gustavo.grieco (at) imag.fr>
     20   1.9  christos    Copyright (c) 2016      Pascal Cuoq <cuoq (at) trust-in-soft.com>
     21   1.9  christos    Copyright (c) 2016      Ed Schouten <ed (at) nuxi.nl>
     22  1.10       wiz    Copyright (c) 2017-2022 Rhodri James <rhodri (at) wildebeest.org.uk>
     23   1.9  christos    Copyright (c) 2017      Vclav Slavk <vaclav (at) slavik.io>
     24   1.9  christos    Copyright (c) 2017      Viktor Szakats <commit (at) vsz.me>
     25   1.9  christos    Copyright (c) 2017      Chanho Park <chanho61.park (at) samsung.com>
     26   1.9  christos    Copyright (c) 2017      Rolf Eike Beer <eike (at) sf-mail.de>
     27   1.9  christos    Copyright (c) 2017      Hans Wennborg <hans (at) chromium.org>
     28   1.9  christos    Copyright (c) 2018      Anton Maklakov <antmak.pub (at) gmail.com>
     29   1.9  christos    Copyright (c) 2018      Benjamin Peterson <benjamin (at) python.org>
     30   1.9  christos    Copyright (c) 2018      Marco Maggi <marco.maggi-ipsu (at) poste.it>
     31   1.9  christos    Copyright (c) 2018      Mariusz Zaborski <oshogbo (at) vexillium.org>
     32   1.9  christos    Copyright (c) 2019      David Loffredo <loffredo (at) steptools.com>
     33   1.9  christos    Copyright (c) 2019-2020 Ben Wagner <bungeman (at) chromium.org>
     34   1.9  christos    Copyright (c) 2019      Vadim Zeitlin <vadim (at) zeitlins.org>
     35  1.10       wiz    Copyright (c) 2021      Donghee Na <donghee.na (at) python.org>
     36   1.9  christos    Copyright (c) 2022      Samanta Navarro <ferivoz (at) riseup.net>
     37  1.10       wiz    Copyright (c) 2022      Jeffrey Walton <noloader (at) gmail.com>
     38  1.10       wiz    Copyright (c) 2022      Jann Horn <jannh (at) google.com>
     39  1.10       wiz    Copyright (c) 2022      Sean McBride <sean (at) rogue-research.com>
     40  1.10       wiz    Copyright (c) 2023      Owain Davies <owaind (at) bath.edu>
     41  1.10       wiz    Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild (at) sony.com>
     42  1.10       wiz    Copyright (c) 2024-2025 Berkay Eren rn <berkay.ueruen (at) siemens.com>
     43  1.10       wiz    Copyright (c) 2024      Hanno Bck <hanno (at) gentoo.org>
     44   1.8      maya    Licensed under the MIT license:
     45   1.8      maya 
     46   1.8      maya    Permission is  hereby granted,  free of charge,  to any  person obtaining
     47   1.8      maya    a  copy  of  this  software   and  associated  documentation  files  (the
     48   1.8      maya    "Software"),  to  deal in  the  Software  without restriction,  including
     49   1.8      maya    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
     50   1.8      maya    distribute, sublicense, and/or sell copies of the Software, and to permit
     51   1.8      maya    persons  to whom  the Software  is  furnished to  do so,  subject to  the
     52   1.8      maya    following conditions:
     53   1.8      maya 
     54   1.8      maya    The above copyright  notice and this permission notice  shall be included
     55   1.8      maya    in all copies or substantial portions of the Software.
     56   1.8      maya 
     57   1.8      maya    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
     58   1.8      maya    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
     59   1.8      maya    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
     60   1.8      maya    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
     61   1.8      maya    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
     62   1.8      maya    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     63   1.8      maya    USE OR OTHER DEALINGS IN THE SOFTWARE.
     64   1.8      maya */
     65   1.7  christos 
     66   1.9  christos #define XML_BUILDING_EXPAT 1
     67   1.9  christos 
     68  1.10       wiz #include "expat_config.h"
     69   1.9  christos 
     70  1.10       wiz #if ! defined(XML_GE) || (1 - XML_GE - 1 == 2) || (XML_GE < 0) || (XML_GE > 1)
     71  1.10       wiz #  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)
     72  1.10       wiz #endif
     73  1.10       wiz 
     74  1.10       wiz #if defined(XML_DTD) && XML_GE == 0
     75  1.10       wiz #  error Either undefine XML_DTD or define XML_GE to 1.
     76  1.10       wiz #endif
     77  1.10       wiz 
     78  1.10       wiz #if ! defined(XML_CONTEXT_BYTES) || (1 - XML_CONTEXT_BYTES - 1 == 2)           \
     79  1.10       wiz     || (XML_CONTEXT_BYTES + 0 < 0)
     80  1.10       wiz #  error XML_CONTEXT_BYTES must be defined, non-empty and >=0 (0 to disable, >=1 to enable; 1024 is a common default)
     81  1.10       wiz #endif
     82  1.10       wiz 
     83  1.10       wiz #if defined(HAVE_SYSCALL_GETRANDOM)
     84  1.10       wiz #  if ! defined(_GNU_SOURCE)
     85  1.10       wiz #    define _GNU_SOURCE 1 /* syscall prototype */
     86  1.10       wiz #  endif
     87   1.8      maya #endif
     88   1.1      tron 
     89   1.8      maya #ifdef _WIN32
     90   1.8      maya /* force stdlib to define rand_s() */
     91   1.9  christos #  if ! defined(_CRT_RAND_S)
     92   1.9  christos #    define _CRT_RAND_S
     93   1.9  christos #  endif
     94   1.8      maya #endif
     95   1.7  christos 
     96  1.10       wiz #include <stdbool.h>
     97   1.1      tron #include <stddef.h>
     98   1.8      maya #include <string.h> /* memset(), memcpy() */
     99   1.1      tron #include <assert.h>
    100   1.8      maya #include <limits.h> /* UINT_MAX */
    101   1.8      maya #include <stdio.h>  /* fprintf */
    102   1.8      maya #include <stdlib.h> /* getenv, rand_s */
    103   1.9  christos #include <stdint.h> /* uintptr_t */
    104   1.9  christos #include <math.h>   /* isnan */
    105   1.6       spz 
    106   1.7  christos #ifdef _WIN32
    107   1.8      maya #  define getpid GetCurrentProcessId
    108   1.6       spz #else
    109   1.8      maya #  include <sys/time.h>  /* gettimeofday() */
    110   1.8      maya #  include <sys/types.h> /* getpid() */
    111   1.8      maya #  include <unistd.h>    /* getpid() */
    112   1.8      maya #  include <fcntl.h>     /* O_RDONLY */
    113   1.8      maya #  include <errno.h>
    114   1.6       spz #endif
    115   1.1      tron 
    116   1.7  christos #ifdef _WIN32
    117   1.8      maya #  include "winconfig.h"
    118   1.9  christos #endif
    119   1.1      tron 
    120   1.1      tron #include "ascii.h"
    121   1.1      tron #include "expat.h"
    122   1.7  christos #include "siphash.h"
    123   1.1      tron 
    124   1.8      maya #if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
    125   1.8      maya #  if defined(HAVE_GETRANDOM)
    126   1.8      maya #    include <sys/random.h> /* getrandom */
    127   1.8      maya #  else
    128   1.8      maya #    include <unistd.h>      /* syscall */
    129   1.8      maya #    include <sys/syscall.h> /* SYS_getrandom */
    130   1.8      maya #  endif
    131   1.8      maya #  if ! defined(GRND_NONBLOCK)
    132   1.8      maya #    define GRND_NONBLOCK 0x0001
    133   1.8      maya #  endif /* defined(GRND_NONBLOCK) */
    134   1.8      maya #endif   /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
    135   1.8      maya 
    136   1.8      maya #if defined(HAVE_LIBBSD)                                                       \
    137   1.8      maya     && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
    138   1.8      maya #  include <bsd/stdlib.h>
    139   1.8      maya #endif
    140   1.8      maya 
    141   1.8      maya #if defined(_WIN32) && ! defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
    142   1.8      maya #  define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
    143   1.8      maya #endif
    144   1.8      maya 
    145   1.8      maya #if ! defined(HAVE_GETRANDOM) && ! defined(HAVE_SYSCALL_GETRANDOM)             \
    146   1.8      maya     && ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)            \
    147   1.8      maya     && ! defined(XML_DEV_URANDOM) && ! defined(_WIN32)                         \
    148   1.8      maya     && ! defined(XML_POOR_ENTROPY)
    149   1.8      maya #  error You do not have support for any sources of high quality entropy \
    150   1.8      maya     enabled.  For end user security, that is probably not what you want. \
    151   1.8      maya     \
    152   1.8      maya     Your options include: \
    153   1.9  christos       * Linux >=3.17 + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \
    154   1.9  christos       * Linux >=3.17 + glibc (including <2.25) (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \
    155  1.10       wiz       * BSD / macOS >=10.7 / glibc >=2.36 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \
    156  1.10       wiz       * BSD / macOS (including <10.7) / glibc >=2.36 (arc4random): HAVE_ARC4RANDOM, \
    157   1.8      maya       * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
    158   1.8      maya       * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
    159  1.10       wiz       * Linux (including <3.17) / BSD / macOS (including <10.7) / Solaris >=8 (/dev/urandom): XML_DEV_URANDOM, \
    160   1.9  christos       * Windows >=Vista (rand_s): _WIN32. \
    161   1.8      maya     \
    162   1.8      maya     If insist on not using any of these, bypass this error by defining \
    163   1.8      maya     XML_POOR_ENTROPY; you have been warned. \
    164   1.8      maya     \
    165   1.8      maya     If you have reasons to patch this detection code away or need changes \
    166   1.8      maya     to the build system, please open a bug.  Thank you!
    167   1.8      maya #endif
    168   1.8      maya 
    169   1.1      tron #ifdef XML_UNICODE
    170   1.8      maya #  define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
    171   1.8      maya #  define XmlConvert XmlUtf16Convert
    172   1.8      maya #  define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
    173   1.8      maya #  define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
    174   1.8      maya #  define XmlEncode XmlUtf16Encode
    175   1.9  christos #  define MUST_CONVERT(enc, s) (! (enc)->isUtf16 || (((uintptr_t)(s)) & 1))
    176   1.1      tron typedef unsigned short ICHAR;
    177   1.1      tron #else
    178   1.8      maya #  define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
    179   1.8      maya #  define XmlConvert XmlUtf8Convert
    180   1.8      maya #  define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
    181   1.8      maya #  define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
    182   1.8      maya #  define XmlEncode XmlUtf8Encode
    183   1.8      maya #  define MUST_CONVERT(enc, s) (! (enc)->isUtf8)
    184   1.1      tron typedef char ICHAR;
    185   1.1      tron #endif
    186   1.1      tron 
    187   1.1      tron #ifndef XML_NS
    188   1.1      tron 
    189   1.8      maya #  define XmlInitEncodingNS XmlInitEncoding
    190   1.8      maya #  define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
    191   1.8      maya #  undef XmlGetInternalEncodingNS
    192   1.8      maya #  define XmlGetInternalEncodingNS XmlGetInternalEncoding
    193   1.8      maya #  define XmlParseXmlDeclNS XmlParseXmlDecl
    194   1.1      tron 
    195   1.1      tron #endif
    196   1.1      tron 
    197   1.1      tron #ifdef XML_UNICODE
    198   1.1      tron 
    199   1.8      maya #  ifdef XML_UNICODE_WCHAR_T
    200   1.8      maya #    define XML_T(x) (const wchar_t) x
    201   1.8      maya #    define XML_L(x) L##x
    202   1.8      maya #  else
    203   1.8      maya #    define XML_T(x) (const unsigned short)x
    204   1.8      maya #    define XML_L(x) x
    205   1.8      maya #  endif
    206   1.1      tron 
    207   1.1      tron #else
    208   1.1      tron 
    209   1.8      maya #  define XML_T(x) x
    210   1.8      maya #  define XML_L(x) x
    211   1.1      tron 
    212   1.1      tron #endif
    213   1.1      tron 
    214   1.1      tron /* Round up n to be a multiple of sz, where sz is a power of 2. */
    215  1.10       wiz #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
    216   1.1      tron 
    217   1.8      maya /* Do safe (NULL-aware) pointer arithmetic */
    218   1.8      maya #define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
    219   1.1      tron 
    220  1.10       wiz #define EXPAT_MIN(a, b) (((a) < (b)) ? (a) : (b))
    221  1.10       wiz 
    222   1.1      tron #include "internal.h"
    223   1.1      tron #include "xmltok.h"
    224   1.1      tron #include "xmlrole.h"
    225   1.1      tron 
    226   1.1      tron typedef const XML_Char *KEY;
    227   1.1      tron 
    228   1.1      tron typedef struct {
    229   1.1      tron   KEY name;
    230   1.1      tron } NAMED;
    231   1.1      tron 
    232   1.1      tron typedef struct {
    233   1.1      tron   NAMED **v;
    234   1.1      tron   unsigned char power;
    235   1.1      tron   size_t size;
    236   1.1      tron   size_t used;
    237   1.1      tron   const XML_Memory_Handling_Suite *mem;
    238   1.1      tron } HASH_TABLE;
    239   1.1      tron 
    240   1.8      maya static size_t keylen(KEY s);
    241   1.1      tron 
    242   1.8      maya static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key);
    243   1.1      tron 
    244   1.1      tron /* For probing (after a collision) we need a step size relative prime
    245   1.1      tron    to the hash table size, which is a power of 2. We use double-hashing,
    246   1.1      tron    since we can calculate a second hash value cheaply by taking those bits
    247   1.1      tron    of the first hash value that were discarded (masked out) when the table
    248   1.1      tron    index was calculated: index = hash & mask, where mask = table->size - 1.
    249   1.1      tron    We limit the maximum step size to table->size / 4 (mask >> 2) and make
    250   1.1      tron    it odd, since odd numbers are always relative prime to a power of 2.
    251   1.1      tron */
    252   1.8      maya #define SECOND_HASH(hash, mask, power)                                         \
    253  1.10       wiz   ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
    254   1.8      maya #define PROBE_STEP(hash, mask, power)                                          \
    255   1.1      tron   ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
    256   1.1      tron 
    257   1.1      tron typedef struct {
    258   1.1      tron   NAMED **p;
    259   1.1      tron   NAMED **end;
    260   1.1      tron } HASH_TABLE_ITER;
    261   1.1      tron 
    262   1.8      maya #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
    263   1.1      tron #define INIT_DATA_BUF_SIZE 1024
    264   1.1      tron #define INIT_ATTS_SIZE 16
    265   1.1      tron #define INIT_ATTS_VERSION 0xFFFFFFFF
    266   1.1      tron #define INIT_BLOCK_SIZE 1024
    267   1.1      tron #define INIT_BUFFER_SIZE 1024
    268   1.1      tron 
    269   1.1      tron #define EXPAND_SPARE 24
    270   1.1      tron 
    271   1.1      tron typedef struct binding {
    272   1.1      tron   struct prefix *prefix;
    273   1.1      tron   struct binding *nextTagBinding;
    274   1.1      tron   struct binding *prevPrefixBinding;
    275   1.1      tron   const struct attribute_id *attId;
    276   1.1      tron   XML_Char *uri;
    277   1.1      tron   int uriLen;
    278   1.1      tron   int uriAlloc;
    279   1.1      tron } BINDING;
    280   1.1      tron 
    281   1.1      tron typedef struct prefix {
    282   1.1      tron   const XML_Char *name;
    283   1.1      tron   BINDING *binding;
    284   1.1      tron } PREFIX;
    285   1.1      tron 
    286   1.1      tron typedef struct {
    287   1.1      tron   const XML_Char *str;
    288   1.1      tron   const XML_Char *localPart;
    289   1.1      tron   const XML_Char *prefix;
    290   1.1      tron   int strLen;
    291   1.1      tron   int uriLen;
    292   1.1      tron   int prefixLen;
    293   1.1      tron } TAG_NAME;
    294   1.1      tron 
    295   1.1      tron /* TAG represents an open element.
    296   1.1      tron    The name of the element is stored in both the document and API
    297   1.1      tron    encodings.  The memory buffer 'buf' is a separately-allocated
    298   1.1      tron    memory area which stores the name.  During the XML_Parse()/
    299  1.10       wiz    XML_ParseBuffer() when the element is open, the memory for the 'raw'
    300   1.1      tron    version of the name (in the document encoding) is shared with the
    301   1.1      tron    document buffer.  If the element is open across calls to
    302   1.1      tron    XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
    303   1.1      tron    contain the 'raw' name as well.
    304   1.1      tron 
    305  1.10       wiz    A parser reuses these structures, maintaining a list of allocated
    306   1.1      tron    TAG objects in a free list.
    307   1.1      tron */
    308   1.1      tron typedef struct tag {
    309   1.8      maya   struct tag *parent;  /* parent of this element */
    310   1.8      maya   const char *rawName; /* tagName in the original encoding */
    311   1.1      tron   int rawNameLength;
    312   1.8      maya   TAG_NAME name; /* tagName in the API encoding */
    313   1.8      maya   char *buf;     /* buffer for name components */
    314   1.8      maya   char *bufEnd;  /* end of the buffer */
    315   1.1      tron   BINDING *bindings;
    316   1.1      tron } TAG;
    317   1.1      tron 
    318   1.1      tron typedef struct {
    319   1.1      tron   const XML_Char *name;
    320   1.1      tron   const XML_Char *textPtr;
    321   1.8      maya   int textLen;   /* length in XML_Chars */
    322   1.8      maya   int processed; /* # of processed bytes - when suspended */
    323   1.1      tron   const XML_Char *systemId;
    324   1.1      tron   const XML_Char *base;
    325   1.1      tron   const XML_Char *publicId;
    326   1.1      tron   const XML_Char *notation;
    327   1.1      tron   XML_Bool open;
    328  1.10       wiz   XML_Bool hasMore; /* true if entity has not been completely processed */
    329  1.10       wiz   /* An entity can be open while being already completely processed (hasMore ==
    330  1.10       wiz     XML_FALSE). The reason is the delayed closing of entities until their inner
    331  1.10       wiz     entities are processed and closed */
    332   1.1      tron   XML_Bool is_param;
    333   1.1      tron   XML_Bool is_internal; /* true if declared in internal subset outside PE */
    334   1.1      tron } ENTITY;
    335   1.1      tron 
    336   1.1      tron typedef struct {
    337   1.8      maya   enum XML_Content_Type type;
    338   1.8      maya   enum XML_Content_Quant quant;
    339   1.8      maya   const XML_Char *name;
    340   1.8      maya   int firstchild;
    341   1.8      maya   int lastchild;
    342   1.8      maya   int childcnt;
    343   1.8      maya   int nextsib;
    344   1.1      tron } CONTENT_SCAFFOLD;
    345   1.1      tron 
    346   1.1      tron #define INIT_SCAFFOLD_ELEMENTS 32
    347   1.1      tron 
    348   1.1      tron typedef struct block {
    349   1.1      tron   struct block *next;
    350   1.1      tron   int size;
    351   1.1      tron   XML_Char s[1];
    352   1.1      tron } BLOCK;
    353   1.1      tron 
    354   1.1      tron typedef struct {
    355   1.1      tron   BLOCK *blocks;
    356   1.1      tron   BLOCK *freeBlocks;
    357   1.1      tron   const XML_Char *end;
    358   1.1      tron   XML_Char *ptr;
    359   1.1      tron   XML_Char *start;
    360   1.1      tron   const XML_Memory_Handling_Suite *mem;
    361   1.1      tron } STRING_POOL;
    362   1.1      tron 
    363   1.1      tron /* The XML_Char before the name is used to determine whether
    364   1.1      tron    an attribute has been specified. */
    365   1.1      tron typedef struct attribute_id {
    366   1.1      tron   XML_Char *name;
    367   1.1      tron   PREFIX *prefix;
    368   1.1      tron   XML_Bool maybeTokenized;
    369   1.1      tron   XML_Bool xmlns;
    370   1.1      tron } ATTRIBUTE_ID;
    371   1.1      tron 
    372   1.1      tron typedef struct {
    373   1.1      tron   const ATTRIBUTE_ID *id;
    374   1.1      tron   XML_Bool isCdata;
    375   1.1      tron   const XML_Char *value;
    376   1.1      tron } DEFAULT_ATTRIBUTE;
    377   1.1      tron 
    378   1.1      tron typedef struct {
    379   1.1      tron   unsigned long version;
    380   1.1      tron   unsigned long hash;
    381   1.1      tron   const XML_Char *uriName;
    382   1.1      tron } NS_ATT;
    383   1.1      tron 
    384   1.1      tron typedef struct {
    385   1.1      tron   const XML_Char *name;
    386   1.1      tron   PREFIX *prefix;
    387   1.1      tron   const ATTRIBUTE_ID *idAtt;
    388   1.1      tron   int nDefaultAtts;
    389   1.1      tron   int allocDefaultAtts;
    390   1.1      tron   DEFAULT_ATTRIBUTE *defaultAtts;
    391   1.1      tron } ELEMENT_TYPE;
    392   1.1      tron 
    393   1.1      tron typedef struct {
    394   1.1      tron   HASH_TABLE generalEntities;
    395   1.1      tron   HASH_TABLE elementTypes;
    396   1.1      tron   HASH_TABLE attributeIds;
    397   1.1      tron   HASH_TABLE prefixes;
    398   1.1      tron   STRING_POOL pool;
    399   1.1      tron   STRING_POOL entityValuePool;
    400   1.1      tron   /* false once a parameter entity reference has been skipped */
    401   1.1      tron   XML_Bool keepProcessing;
    402   1.1      tron   /* true once an internal or external PE reference has been encountered;
    403   1.1      tron      this includes the reference to an external subset */
    404   1.1      tron   XML_Bool hasParamEntityRefs;
    405   1.1      tron   XML_Bool standalone;
    406   1.1      tron #ifdef XML_DTD
    407   1.1      tron   /* indicates if external PE has been read */
    408   1.1      tron   XML_Bool paramEntityRead;
    409   1.1      tron   HASH_TABLE paramEntities;
    410   1.1      tron #endif /* XML_DTD */
    411   1.1      tron   PREFIX defaultPrefix;
    412   1.1      tron   /* === scaffolding for building content model === */
    413   1.1      tron   XML_Bool in_eldecl;
    414   1.1      tron   CONTENT_SCAFFOLD *scaffold;
    415   1.1      tron   unsigned contentStringLen;
    416   1.1      tron   unsigned scaffSize;
    417   1.1      tron   unsigned scaffCount;
    418   1.1      tron   int scaffLevel;
    419   1.1      tron   int *scaffIndex;
    420   1.1      tron } DTD;
    421   1.1      tron 
    422  1.10       wiz enum EntityType {
    423  1.10       wiz   ENTITY_INTERNAL,
    424  1.10       wiz   ENTITY_ATTRIBUTE,
    425  1.10       wiz   ENTITY_VALUE,
    426  1.10       wiz };
    427  1.10       wiz 
    428   1.1      tron typedef struct open_internal_entity {
    429   1.1      tron   const char *internalEventPtr;
    430   1.1      tron   const char *internalEventEndPtr;
    431   1.1      tron   struct open_internal_entity *next;
    432   1.1      tron   ENTITY *entity;
    433   1.1      tron   int startTagLevel;
    434   1.1      tron   XML_Bool betweenDecl; /* WFC: PE Between Declarations */
    435  1.10       wiz   enum EntityType type;
    436   1.1      tron } OPEN_INTERNAL_ENTITY;
    437   1.1      tron 
    438   1.9  christos enum XML_Account {
    439   1.9  christos   XML_ACCOUNT_DIRECT,           /* bytes directly passed to the Expat parser */
    440   1.9  christos   XML_ACCOUNT_ENTITY_EXPANSION, /* intermediate bytes produced during entity
    441   1.9  christos                                    expansion */
    442   1.9  christos   XML_ACCOUNT_NONE              /* i.e. do not account, was accounted already */
    443   1.9  christos };
    444   1.9  christos 
    445  1.10       wiz #if XML_GE == 1
    446   1.9  christos typedef unsigned long long XmlBigCount;
    447   1.9  christos typedef struct accounting {
    448   1.9  christos   XmlBigCount countBytesDirect;
    449   1.9  christos   XmlBigCount countBytesIndirect;
    450  1.10       wiz   unsigned long debugLevel;
    451   1.9  christos   float maximumAmplificationFactor; // >=1.0
    452   1.9  christos   unsigned long long activationThresholdBytes;
    453   1.9  christos } ACCOUNTING;
    454   1.9  christos 
    455   1.9  christos typedef struct entity_stats {
    456   1.9  christos   unsigned int countEverOpened;
    457   1.9  christos   unsigned int currentDepth;
    458   1.9  christos   unsigned int maximumDepthSeen;
    459  1.10       wiz   unsigned long debugLevel;
    460   1.9  christos } ENTITY_STATS;
    461  1.10       wiz #endif /* XML_GE == 1 */
    462   1.9  christos 
    463   1.8      maya typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
    464   1.8      maya                                          const char *end, const char **endPtr);
    465   1.1      tron 
    466   1.1      tron static Processor prologProcessor;
    467   1.1      tron static Processor prologInitProcessor;
    468   1.1      tron static Processor contentProcessor;
    469   1.1      tron static Processor cdataSectionProcessor;
    470   1.1      tron #ifdef XML_DTD
    471   1.1      tron static Processor ignoreSectionProcessor;
    472   1.1      tron static Processor externalParEntProcessor;
    473   1.1      tron static Processor externalParEntInitProcessor;
    474   1.1      tron static Processor entityValueProcessor;
    475   1.1      tron static Processor entityValueInitProcessor;
    476   1.1      tron #endif /* XML_DTD */
    477   1.1      tron static Processor epilogProcessor;
    478   1.1      tron static Processor errorProcessor;
    479   1.1      tron static Processor externalEntityInitProcessor;
    480   1.1      tron static Processor externalEntityInitProcessor2;
    481   1.1      tron static Processor externalEntityInitProcessor3;
    482   1.1      tron static Processor externalEntityContentProcessor;
    483   1.1      tron static Processor internalEntityProcessor;
    484   1.1      tron 
    485   1.8      maya static enum XML_Error handleUnknownEncoding(XML_Parser parser,
    486   1.8      maya                                             const XML_Char *encodingName);
    487   1.8      maya static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
    488   1.8      maya                                      const char *s, const char *next);
    489   1.8      maya static enum XML_Error initializeEncoding(XML_Parser parser);
    490   1.8      maya static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
    491   1.8      maya                                const char *s, const char *end, int tok,
    492   1.8      maya                                const char *next, const char **nextPtr,
    493   1.9  christos                                XML_Bool haveMore, XML_Bool allowClosingDoctype,
    494   1.9  christos                                enum XML_Account account);
    495  1.10       wiz static enum XML_Error processEntity(XML_Parser parser, ENTITY *entity,
    496  1.10       wiz                                     XML_Bool betweenDecl, enum EntityType type);
    497   1.8      maya static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
    498   1.8      maya                                 const ENCODING *enc, const char *start,
    499   1.8      maya                                 const char *end, const char **endPtr,
    500   1.9  christos                                 XML_Bool haveMore, enum XML_Account account);
    501  1.10       wiz static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *enc,
    502   1.8      maya                                      const char **startPtr, const char *end,
    503   1.9  christos                                      const char **nextPtr, XML_Bool haveMore,
    504   1.9  christos                                      enum XML_Account account);
    505   1.8      maya #ifdef XML_DTD
    506  1.10       wiz static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *enc,
    507   1.8      maya                                       const char **startPtr, const char *end,
    508   1.8      maya                                       const char **nextPtr, XML_Bool haveMore);
    509   1.1      tron #endif /* XML_DTD */
    510   1.1      tron 
    511   1.8      maya static void freeBindings(XML_Parser parser, BINDING *bindings);
    512  1.10       wiz static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
    513  1.10       wiz                                 const char *attStr, TAG_NAME *tagNamePtr,
    514   1.9  christos                                 BINDING **bindingsPtr,
    515   1.9  christos                                 enum XML_Account account);
    516   1.8      maya static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
    517   1.8      maya                                  const ATTRIBUTE_ID *attId, const XML_Char *uri,
    518   1.8      maya                                  BINDING **bindingsPtr);
    519  1.10       wiz static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId,
    520  1.10       wiz                            XML_Bool isCdata, XML_Bool isId,
    521  1.10       wiz                            const XML_Char *value, XML_Parser parser);
    522  1.10       wiz static enum XML_Error storeAttributeValue(XML_Parser parser,
    523  1.10       wiz                                           const ENCODING *enc, XML_Bool isCdata,
    524  1.10       wiz                                           const char *ptr, const char *end,
    525  1.10       wiz                                           STRING_POOL *pool,
    526   1.9  christos                                           enum XML_Account account);
    527  1.10       wiz static enum XML_Error
    528  1.10       wiz appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
    529  1.10       wiz                      const char *ptr, const char *end, STRING_POOL *pool,
    530  1.10       wiz                      enum XML_Account account, const char **nextPtr);
    531   1.8      maya static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
    532   1.8      maya                                     const char *start, const char *end);
    533  1.10       wiz static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType);
    534  1.10       wiz #if XML_GE == 1
    535   1.8      maya static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
    536   1.9  christos                                        const char *start, const char *end,
    537  1.10       wiz                                        enum XML_Account account,
    538  1.10       wiz                                        const char **nextPtr);
    539  1.10       wiz static enum XML_Error callStoreEntityValue(XML_Parser parser,
    540  1.10       wiz                                            const ENCODING *enc,
    541  1.10       wiz                                            const char *start, const char *end,
    542  1.10       wiz                                            enum XML_Account account);
    543  1.10       wiz #else
    544  1.10       wiz static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity);
    545  1.10       wiz #endif
    546   1.8      maya static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
    547   1.8      maya                                        const char *start, const char *end);
    548   1.8      maya static int reportComment(XML_Parser parser, const ENCODING *enc,
    549   1.8      maya                          const char *start, const char *end);
    550   1.8      maya static void reportDefault(XML_Parser parser, const ENCODING *enc,
    551   1.8      maya                           const char *start, const char *end);
    552   1.1      tron 
    553   1.8      maya static const XML_Char *getContext(XML_Parser parser);
    554   1.8      maya static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
    555   1.1      tron 
    556   1.1      tron static void FASTCALL normalizePublicId(XML_Char *s);
    557   1.1      tron 
    558   1.8      maya static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms);
    559   1.8      maya /* do not call if m_parentParser != NULL */
    560   1.1      tron static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
    561   1.8      maya static void dtdDestroy(DTD *p, XML_Bool isDocEntity,
    562   1.8      maya                        const XML_Memory_Handling_Suite *ms);
    563   1.8      maya static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
    564   1.8      maya                    const XML_Memory_Handling_Suite *ms);
    565  1.10       wiz static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
    566  1.10       wiz                            STRING_POOL *newPool, const HASH_TABLE *oldTable);
    567   1.8      maya static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
    568   1.8      maya                      size_t createSize);
    569  1.10       wiz static void FASTCALL hashTableInit(HASH_TABLE *table,
    570   1.8      maya                                    const XML_Memory_Handling_Suite *ms);
    571  1.10       wiz static void FASTCALL hashTableClear(HASH_TABLE *table);
    572  1.10       wiz static void FASTCALL hashTableDestroy(HASH_TABLE *table);
    573  1.10       wiz static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter,
    574  1.10       wiz                                        const HASH_TABLE *table);
    575  1.10       wiz static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter);
    576   1.1      tron 
    577  1.10       wiz static void FASTCALL poolInit(STRING_POOL *pool,
    578   1.8      maya                               const XML_Memory_Handling_Suite *ms);
    579  1.10       wiz static void FASTCALL poolClear(STRING_POOL *pool);
    580  1.10       wiz static void FASTCALL poolDestroy(STRING_POOL *pool);
    581   1.8      maya static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
    582   1.8      maya                             const char *ptr, const char *end);
    583   1.8      maya static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
    584   1.8      maya                                  const char *ptr, const char *end);
    585   1.1      tron static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
    586   1.8      maya static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
    587   1.8      maya                                                const XML_Char *s);
    588   1.8      maya static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
    589   1.8      maya                                        int n);
    590   1.8      maya static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
    591   1.8      maya                                                  const XML_Char *s);
    592   1.1      tron 
    593   1.1      tron static int FASTCALL nextScaffoldPart(XML_Parser parser);
    594   1.8      maya static XML_Content *build_model(XML_Parser parser);
    595   1.8      maya static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
    596   1.8      maya                                     const char *ptr, const char *end);
    597   1.8      maya 
    598   1.8      maya static XML_Char *copyString(const XML_Char *s,
    599   1.8      maya                             const XML_Memory_Handling_Suite *memsuite);
    600   1.1      tron 
    601   1.6       spz static unsigned long generate_hash_secret_salt(XML_Parser parser);
    602   1.3       spz static XML_Bool startParsing(XML_Parser parser);
    603   1.3       spz 
    604   1.8      maya static XML_Parser parserCreate(const XML_Char *encodingName,
    605   1.8      maya                                const XML_Memory_Handling_Suite *memsuite,
    606   1.8      maya                                const XML_Char *nameSep, DTD *dtd);
    607   1.3       spz 
    608   1.8      maya static void parserInit(XML_Parser parser, const XML_Char *encodingName);
    609   1.1      tron 
    610  1.10       wiz #if XML_GE == 1
    611   1.9  christos static float accountingGetCurrentAmplification(XML_Parser rootParser);
    612   1.9  christos static void accountingReportStats(XML_Parser originParser, const char *epilog);
    613   1.9  christos static void accountingOnAbort(XML_Parser originParser);
    614   1.9  christos static void accountingReportDiff(XML_Parser rootParser,
    615   1.9  christos                                  unsigned int levelsAwayFromRootParser,
    616   1.9  christos                                  const char *before, const char *after,
    617   1.9  christos                                  ptrdiff_t bytesMore, int source_line,
    618   1.9  christos                                  enum XML_Account account);
    619   1.9  christos static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok,
    620   1.9  christos                                         const char *before, const char *after,
    621   1.9  christos                                         int source_line,
    622   1.9  christos                                         enum XML_Account account);
    623   1.9  christos 
    624   1.9  christos static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity,
    625   1.9  christos                                       const char *action, int sourceLine);
    626   1.9  christos static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity,
    627   1.9  christos                                  int sourceLine);
    628   1.9  christos static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity,
    629   1.9  christos                                   int sourceLine);
    630   1.9  christos 
    631   1.9  christos static XML_Parser getRootParserOf(XML_Parser parser,
    632   1.9  christos                                   unsigned int *outLevelDiff);
    633  1.10       wiz #endif /* XML_GE == 1 */
    634   1.9  christos 
    635   1.9  christos static unsigned long getDebugLevel(const char *variableName,
    636   1.9  christos                                    unsigned long defaultDebugLevel);
    637   1.9  christos 
    638   1.1      tron #define poolStart(pool) ((pool)->start)
    639   1.1      tron #define poolLength(pool) ((pool)->ptr - (pool)->start)
    640   1.1      tron #define poolChop(pool) ((void)--(pool->ptr))
    641   1.1      tron #define poolLastChar(pool) (((pool)->ptr)[-1])
    642   1.1      tron #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
    643   1.1      tron #define poolFinish(pool) ((pool)->start = (pool)->ptr)
    644   1.8      maya #define poolAppendChar(pool, c)                                                \
    645   1.8      maya   (((pool)->ptr == (pool)->end && ! poolGrow(pool))                            \
    646   1.8      maya        ? 0                                                                     \
    647   1.8      maya        : ((*((pool)->ptr)++ = c), 1))
    648   1.1      tron 
    649  1.10       wiz #if ! defined(XML_TESTING)
    650  1.10       wiz const
    651  1.10       wiz #endif
    652  1.10       wiz     XML_Bool g_reparseDeferralEnabledDefault
    653  1.10       wiz     = XML_TRUE; // write ONLY in runtests.c
    654  1.10       wiz #if defined(XML_TESTING)
    655  1.10       wiz unsigned int g_bytesScanned = 0; // used for testing only
    656  1.10       wiz #endif
    657  1.10       wiz 
    658   1.1      tron struct XML_ParserStruct {
    659   1.8      maya   /* The first member must be m_userData so that the XML_GetUserData
    660   1.1      tron      macro works. */
    661   1.1      tron   void *m_userData;
    662   1.1      tron   void *m_handlerArg;
    663  1.10       wiz 
    664  1.10       wiz   // How the four parse buffer pointers below relate in time and space:
    665  1.10       wiz   //
    666  1.10       wiz   //   m_buffer <= m_bufferPtr <= m_bufferEnd  <= m_bufferLim
    667  1.10       wiz   //   |           |              |               |
    668  1.10       wiz   //   <--parsed-->|              |               |
    669  1.10       wiz   //               <---parsing--->|               |
    670  1.10       wiz   //                              <--unoccupied-->|
    671  1.10       wiz   //   <---------total-malloced/realloced-------->|
    672  1.10       wiz 
    673  1.10       wiz   char *m_buffer; // malloc/realloc base pointer of parse buffer
    674   1.1      tron   const XML_Memory_Handling_Suite m_mem;
    675  1.10       wiz   const char *m_bufferPtr; // first character to be parsed
    676  1.10       wiz   char *m_bufferEnd;       // past last character to be parsed
    677  1.10       wiz   const char *m_bufferLim; // allocated end of m_buffer
    678  1.10       wiz 
    679   1.1      tron   XML_Index m_parseEndByteIndex;
    680   1.1      tron   const char *m_parseEndPtr;
    681  1.10       wiz   size_t m_partialTokenBytesBefore; /* used in heuristic to avoid O(n^2) */
    682  1.10       wiz   XML_Bool m_reparseDeferralEnabled;
    683  1.10       wiz   int m_lastBufferRequestSize;
    684   1.1      tron   XML_Char *m_dataBuf;
    685   1.1      tron   XML_Char *m_dataBufEnd;
    686   1.1      tron   XML_StartElementHandler m_startElementHandler;
    687   1.1      tron   XML_EndElementHandler m_endElementHandler;
    688   1.1      tron   XML_CharacterDataHandler m_characterDataHandler;
    689   1.1      tron   XML_ProcessingInstructionHandler m_processingInstructionHandler;
    690   1.1      tron   XML_CommentHandler m_commentHandler;
    691   1.1      tron   XML_StartCdataSectionHandler m_startCdataSectionHandler;
    692   1.1      tron   XML_EndCdataSectionHandler m_endCdataSectionHandler;
    693   1.1      tron   XML_DefaultHandler m_defaultHandler;
    694   1.1      tron   XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
    695   1.1      tron   XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
    696   1.1      tron   XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
    697   1.1      tron   XML_NotationDeclHandler m_notationDeclHandler;
    698   1.1      tron   XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
    699   1.1      tron   XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
    700   1.1      tron   XML_NotStandaloneHandler m_notStandaloneHandler;
    701   1.1      tron   XML_ExternalEntityRefHandler m_externalEntityRefHandler;
    702   1.1      tron   XML_Parser m_externalEntityRefHandlerArg;
    703   1.1      tron   XML_SkippedEntityHandler m_skippedEntityHandler;
    704   1.1      tron   XML_UnknownEncodingHandler m_unknownEncodingHandler;
    705   1.1      tron   XML_ElementDeclHandler m_elementDeclHandler;
    706   1.1      tron   XML_AttlistDeclHandler m_attlistDeclHandler;
    707   1.1      tron   XML_EntityDeclHandler m_entityDeclHandler;
    708   1.1      tron   XML_XmlDeclHandler m_xmlDeclHandler;
    709   1.1      tron   const ENCODING *m_encoding;
    710   1.1      tron   INIT_ENCODING m_initEncoding;
    711   1.1      tron   const ENCODING *m_internalEncoding;
    712   1.1      tron   const XML_Char *m_protocolEncodingName;
    713   1.1      tron   XML_Bool m_ns;
    714   1.1      tron   XML_Bool m_ns_triplets;
    715   1.1      tron   void *m_unknownEncodingMem;
    716   1.1      tron   void *m_unknownEncodingData;
    717   1.1      tron   void *m_unknownEncodingHandlerData;
    718   1.8      maya   void(XMLCALL *m_unknownEncodingRelease)(void *);
    719   1.1      tron   PROLOG_STATE m_prologState;
    720   1.1      tron   Processor *m_processor;
    721   1.1      tron   enum XML_Error m_errorCode;
    722   1.1      tron   const char *m_eventPtr;
    723   1.1      tron   const char *m_eventEndPtr;
    724   1.1      tron   const char *m_positionPtr;
    725   1.1      tron   OPEN_INTERNAL_ENTITY *m_openInternalEntities;
    726   1.1      tron   OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
    727  1.10       wiz   OPEN_INTERNAL_ENTITY *m_openAttributeEntities;
    728  1.10       wiz   OPEN_INTERNAL_ENTITY *m_freeAttributeEntities;
    729  1.10       wiz   OPEN_INTERNAL_ENTITY *m_openValueEntities;
    730  1.10       wiz   OPEN_INTERNAL_ENTITY *m_freeValueEntities;
    731   1.1      tron   XML_Bool m_defaultExpandInternalEntities;
    732   1.1      tron   int m_tagLevel;
    733   1.1      tron   ENTITY *m_declEntity;
    734   1.1      tron   const XML_Char *m_doctypeName;
    735   1.1      tron   const XML_Char *m_doctypeSysid;
    736   1.1      tron   const XML_Char *m_doctypePubid;
    737   1.1      tron   const XML_Char *m_declAttributeType;
    738   1.1      tron   const XML_Char *m_declNotationName;
    739   1.1      tron   const XML_Char *m_declNotationPublicId;
    740   1.1      tron   ELEMENT_TYPE *m_declElementType;
    741   1.1      tron   ATTRIBUTE_ID *m_declAttributeId;
    742   1.1      tron   XML_Bool m_declAttributeIsCdata;
    743   1.1      tron   XML_Bool m_declAttributeIsId;
    744   1.1      tron   DTD *m_dtd;
    745   1.1      tron   const XML_Char *m_curBase;
    746   1.1      tron   TAG *m_tagStack;
    747   1.1      tron   TAG *m_freeTagList;
    748   1.1      tron   BINDING *m_inheritedBindings;
    749   1.1      tron   BINDING *m_freeBindingList;
    750   1.1      tron   int m_attsSize;
    751   1.1      tron   int m_nSpecifiedAtts;
    752   1.1      tron   int m_idAttIndex;
    753   1.1      tron   ATTRIBUTE *m_atts;
    754   1.1      tron   NS_ATT *m_nsAtts;
    755   1.1      tron   unsigned long m_nsAttsVersion;
    756   1.1      tron   unsigned char m_nsAttsPower;
    757   1.3       spz #ifdef XML_ATTR_INFO
    758   1.3       spz   XML_AttrInfo *m_attInfo;
    759   1.3       spz #endif
    760   1.1      tron   POSITION m_position;
    761   1.1      tron   STRING_POOL m_tempPool;
    762   1.1      tron   STRING_POOL m_temp2Pool;
    763   1.1      tron   char *m_groupConnector;
    764   1.1      tron   unsigned int m_groupSize;
    765   1.1      tron   XML_Char m_namespaceSeparator;
    766   1.1      tron   XML_Parser m_parentParser;
    767   1.1      tron   XML_ParsingStatus m_parsingStatus;
    768   1.1      tron #ifdef XML_DTD
    769   1.1      tron   XML_Bool m_isParamEntity;
    770   1.1      tron   XML_Bool m_useForeignDTD;
    771   1.1      tron   enum XML_ParamEntityParsing m_paramEntityParsing;
    772   1.1      tron #endif
    773   1.3       spz   unsigned long m_hash_secret_salt;
    774  1.10       wiz #if XML_GE == 1
    775   1.9  christos   ACCOUNTING m_accounting;
    776   1.9  christos   ENTITY_STATS m_entity_stats;
    777   1.9  christos #endif
    778  1.10       wiz   XML_Bool m_reenter;
    779   1.1      tron };
    780   1.1      tron 
    781   1.8      maya #define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
    782   1.8      maya #define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
    783   1.8      maya #define FREE(parser, p) (parser->m_mem.free_fcn((p)))
    784   1.1      tron 
    785   1.1      tron XML_Parser XMLCALL
    786   1.8      maya XML_ParserCreate(const XML_Char *encodingName) {
    787   1.1      tron   return XML_ParserCreate_MM(encodingName, NULL, NULL);
    788   1.1      tron }
    789   1.1      tron 
    790   1.1      tron XML_Parser XMLCALL
    791   1.8      maya XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
    792   1.9  christos   XML_Char tmp[2] = {nsSep, 0};
    793   1.1      tron   return XML_ParserCreate_MM(encodingName, NULL, tmp);
    794   1.1      tron }
    795   1.1      tron 
    796  1.10       wiz // "xml=http://www.w3.org/XML/1998/namespace"
    797   1.8      maya static const XML_Char implicitContext[]
    798   1.8      maya     = {ASCII_x,     ASCII_m,     ASCII_l,      ASCII_EQUALS, ASCII_h,
    799   1.8      maya        ASCII_t,     ASCII_t,     ASCII_p,      ASCII_COLON,  ASCII_SLASH,
    800   1.8      maya        ASCII_SLASH, ASCII_w,     ASCII_w,      ASCII_w,      ASCII_PERIOD,
    801   1.8      maya        ASCII_w,     ASCII_3,     ASCII_PERIOD, ASCII_o,      ASCII_r,
    802   1.8      maya        ASCII_g,     ASCII_SLASH, ASCII_X,      ASCII_M,      ASCII_L,
    803   1.8      maya        ASCII_SLASH, ASCII_1,     ASCII_9,      ASCII_9,      ASCII_8,
    804   1.8      maya        ASCII_SLASH, ASCII_n,     ASCII_a,      ASCII_m,      ASCII_e,
    805   1.8      maya        ASCII_s,     ASCII_p,     ASCII_a,      ASCII_c,      ASCII_e,
    806   1.8      maya        '\0'};
    807   1.7  christos 
    808   1.8      maya /* To avoid warnings about unused functions: */
    809   1.8      maya #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
    810   1.7  christos 
    811   1.8      maya #  if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
    812   1.7  christos 
    813   1.7  christos /* Obtain entropy on Linux 3.17+ */
    814   1.7  christos static int
    815   1.8      maya writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
    816   1.8      maya   int success = 0; /* full count bytes written? */
    817   1.7  christos   size_t bytesWrittenTotal = 0;
    818   1.8      maya   const unsigned int getrandomFlags = GRND_NONBLOCK;
    819   1.7  christos 
    820   1.7  christos   do {
    821   1.8      maya     void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
    822   1.7  christos     const size_t bytesToWrite = count - bytesWrittenTotal;
    823   1.7  christos 
    824   1.7  christos     const int bytesWrittenMore =
    825   1.8      maya #    if defined(HAVE_GETRANDOM)
    826   1.7  christos         getrandom(currentTarget, bytesToWrite, getrandomFlags);
    827   1.8      maya #    else
    828   1.7  christos         syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
    829   1.8      maya #    endif
    830   1.8      maya 
    831   1.8      maya     if (bytesWrittenMore > 0) {
    832   1.8      maya       bytesWrittenTotal += bytesWrittenMore;
    833   1.8      maya       if (bytesWrittenTotal >= count)
    834   1.8      maya         success = 1;
    835   1.8      maya     }
    836   1.8      maya   } while (! success && (errno == EINTR));
    837   1.8      maya 
    838   1.8      maya   return success;
    839   1.8      maya }
    840   1.8      maya 
    841   1.8      maya #  endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
    842   1.8      maya 
    843   1.8      maya #  if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
    844   1.8      maya 
    845   1.8      maya /* Extract entropy from /dev/urandom */
    846   1.8      maya static int
    847   1.8      maya writeRandomBytes_dev_urandom(void *target, size_t count) {
    848   1.8      maya   int success = 0; /* full count bytes written? */
    849   1.8      maya   size_t bytesWrittenTotal = 0;
    850   1.8      maya 
    851   1.8      maya   const int fd = open("/dev/urandom", O_RDONLY);
    852   1.8      maya   if (fd < 0) {
    853   1.8      maya     return 0;
    854   1.8      maya   }
    855   1.8      maya 
    856   1.8      maya   do {
    857   1.8      maya     void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
    858   1.8      maya     const size_t bytesToWrite = count - bytesWrittenTotal;
    859   1.8      maya 
    860   1.8      maya     const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
    861   1.7  christos 
    862   1.7  christos     if (bytesWrittenMore > 0) {
    863   1.7  christos       bytesWrittenTotal += bytesWrittenMore;
    864   1.7  christos       if (bytesWrittenTotal >= count)
    865   1.7  christos         success = 1;
    866   1.7  christos     }
    867   1.8      maya   } while (! success && (errno == EINTR));
    868   1.7  christos 
    869   1.8      maya   close(fd);
    870   1.7  christos   return success;
    871   1.7  christos }
    872   1.7  christos 
    873   1.8      maya #  endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
    874   1.7  christos 
    875   1.8      maya #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
    876   1.8      maya 
    877   1.8      maya #if defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF)
    878   1.8      maya 
    879   1.8      maya static void
    880   1.8      maya writeRandomBytes_arc4random(void *target, size_t count) {
    881   1.8      maya   size_t bytesWrittenTotal = 0;
    882   1.8      maya 
    883   1.8      maya   while (bytesWrittenTotal < count) {
    884   1.8      maya     const uint32_t random32 = arc4random();
    885   1.8      maya     size_t i = 0;
    886   1.8      maya 
    887   1.8      maya     for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
    888   1.8      maya          i++, bytesWrittenTotal++) {
    889   1.8      maya       const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
    890   1.8      maya       ((uint8_t *)target)[bytesWrittenTotal] = random8;
    891   1.8      maya     }
    892   1.8      maya   }
    893   1.8      maya }
    894   1.8      maya 
    895   1.8      maya #endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */
    896   1.7  christos 
    897   1.7  christos #ifdef _WIN32
    898   1.7  christos 
    899   1.9  christos /* Provide declaration of rand_s() for MinGW-32 (not 64, which has it),
    900   1.9  christos    as it didn't declare it in its header prior to version 5.3.0 of its
    901   1.9  christos    runtime package (mingwrt, containing stdlib.h).  The upstream fix
    902   1.9  christos    was introduced at https://osdn.net/projects/mingw/ticket/39658 . */
    903   1.9  christos #  if defined(__MINGW32__) && defined(__MINGW32_VERSION)                       \
    904   1.9  christos       && __MINGW32_VERSION < 5003000L && ! defined(__MINGW64_VERSION_MAJOR)
    905   1.9  christos __declspec(dllimport) int rand_s(unsigned int *);
    906   1.9  christos #  endif
    907   1.9  christos 
    908   1.8      maya /* Obtain entropy on Windows using the rand_s() function which
    909   1.8      maya  * generates cryptographically secure random numbers.  Internally it
    910   1.8      maya  * uses RtlGenRandom API which is present in Windows XP and later.
    911   1.7  christos  */
    912   1.7  christos static int
    913   1.8      maya writeRandomBytes_rand_s(void *target, size_t count) {
    914   1.8      maya   size_t bytesWrittenTotal = 0;
    915   1.8      maya 
    916   1.8      maya   while (bytesWrittenTotal < count) {
    917   1.8      maya     unsigned int random32 = 0;
    918   1.8      maya     size_t i = 0;
    919   1.8      maya 
    920   1.8      maya     if (rand_s(&random32))
    921   1.8      maya       return 0; /* failure */
    922   1.8      maya 
    923   1.8      maya     for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
    924   1.8      maya          i++, bytesWrittenTotal++) {
    925   1.8      maya       const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
    926   1.8      maya       ((uint8_t *)target)[bytesWrittenTotal] = random8;
    927   1.7  christos     }
    928   1.7  christos   }
    929   1.8      maya   return 1; /* success */
    930   1.7  christos }
    931   1.7  christos 
    932   1.7  christos #endif /* _WIN32 */
    933   1.7  christos 
    934   1.8      maya #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
    935   1.7  christos 
    936   1.3       spz static unsigned long
    937   1.8      maya gather_time_entropy(void) {
    938   1.8      maya #  ifdef _WIN32
    939   1.6       spz   FILETIME ft;
    940   1.6       spz   GetSystemTimeAsFileTime(&ft); /* never fails */
    941   1.6       spz   return ft.dwHighDateTime ^ ft.dwLowDateTime;
    942   1.8      maya #  else
    943   1.6       spz   struct timeval tv;
    944   1.6       spz   int gettimeofday_res;
    945   1.6       spz 
    946   1.6       spz   gettimeofday_res = gettimeofday(&tv, NULL);
    947   1.8      maya 
    948   1.8      maya #    if defined(NDEBUG)
    949   1.8      maya   (void)gettimeofday_res;
    950   1.8      maya #    else
    951   1.8      maya   assert(gettimeofday_res == 0);
    952   1.8      maya #    endif /* defined(NDEBUG) */
    953   1.6       spz 
    954   1.6       spz   /* Microseconds time is <20 bits entropy */
    955   1.6       spz   return tv.tv_usec;
    956   1.8      maya #  endif
    957   1.6       spz }
    958   1.6       spz 
    959   1.8      maya #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
    960   1.7  christos 
    961   1.7  christos static unsigned long
    962   1.8      maya ENTROPY_DEBUG(const char *label, unsigned long entropy) {
    963   1.9  christos   if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) {
    964   1.9  christos     fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
    965   1.8      maya             (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
    966   1.7  christos   }
    967   1.7  christos   return entropy;
    968   1.7  christos }
    969   1.7  christos 
    970   1.6       spz static unsigned long
    971   1.8      maya generate_hash_secret_salt(XML_Parser parser) {
    972   1.7  christos   unsigned long entropy;
    973   1.7  christos   (void)parser;
    974   1.8      maya 
    975   1.8      maya   /* "Failproof" high quality providers: */
    976   1.8      maya #if defined(HAVE_ARC4RANDOM_BUF)
    977   1.7  christos   arc4random_buf(&entropy, sizeof(entropy));
    978   1.7  christos   return ENTROPY_DEBUG("arc4random_buf", entropy);
    979   1.8      maya #elif defined(HAVE_ARC4RANDOM)
    980   1.8      maya   writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
    981   1.8      maya   return ENTROPY_DEBUG("arc4random", entropy);
    982   1.7  christos #else
    983   1.7  christos   /* Try high quality providers first .. */
    984   1.8      maya #  ifdef _WIN32
    985   1.8      maya   if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
    986   1.8      maya     return ENTROPY_DEBUG("rand_s", entropy);
    987   1.7  christos   }
    988   1.8      maya #  elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
    989   1.8      maya   if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
    990   1.7  christos     return ENTROPY_DEBUG("getrandom", entropy);
    991   1.7  christos   }
    992   1.8      maya #  endif
    993   1.8      maya #  if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
    994   1.8      maya   if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
    995   1.8      maya     return ENTROPY_DEBUG("/dev/urandom", entropy);
    996   1.8      maya   }
    997   1.8      maya #  endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
    998   1.7  christos   /* .. and self-made low quality for backup: */
    999   1.7  christos 
   1000   1.7  christos   /* Process ID is 0 bits entropy if attacker has local access */
   1001   1.7  christos   entropy = gather_time_entropy() ^ getpid();
   1002   1.6       spz 
   1003   1.6       spz   /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
   1004   1.6       spz   if (sizeof(unsigned long) == 4) {
   1005   1.7  christos     return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
   1006   1.6       spz   } else {
   1007   1.7  christos     return ENTROPY_DEBUG("fallback(8)",
   1008   1.8      maya                          entropy * (unsigned long)2305843009213693951ULL);
   1009   1.6       spz   }
   1010   1.7  christos #endif
   1011   1.7  christos }
   1012   1.7  christos 
   1013   1.7  christos static unsigned long
   1014   1.7  christos get_hash_secret_salt(XML_Parser parser) {
   1015   1.7  christos   if (parser->m_parentParser != NULL)
   1016   1.7  christos     return get_hash_secret_salt(parser->m_parentParser);
   1017   1.7  christos   return parser->m_hash_secret_salt;
   1018   1.3       spz }
   1019   1.3       spz 
   1020  1.10       wiz static enum XML_Error
   1021  1.10       wiz callProcessor(XML_Parser parser, const char *start, const char *end,
   1022  1.10       wiz               const char **endPtr) {
   1023  1.10       wiz   const size_t have_now = EXPAT_SAFE_PTR_DIFF(end, start);
   1024  1.10       wiz 
   1025  1.10       wiz   if (parser->m_reparseDeferralEnabled
   1026  1.10       wiz       && ! parser->m_parsingStatus.finalBuffer) {
   1027  1.10       wiz     // Heuristic: don't try to parse a partial token again until the amount of
   1028  1.10       wiz     // available data has increased significantly.
   1029  1.10       wiz     const size_t had_before = parser->m_partialTokenBytesBefore;
   1030  1.10       wiz     // ...but *do* try anyway if we're close to causing a reallocation.
   1031  1.10       wiz     size_t available_buffer
   1032  1.10       wiz         = EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
   1033  1.10       wiz #if XML_CONTEXT_BYTES > 0
   1034  1.10       wiz     available_buffer -= EXPAT_MIN(available_buffer, XML_CONTEXT_BYTES);
   1035  1.10       wiz #endif
   1036  1.10       wiz     available_buffer
   1037  1.10       wiz         += EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd);
   1038  1.10       wiz     // m_lastBufferRequestSize is never assigned a value < 0, so the cast is ok
   1039  1.10       wiz     const bool enough
   1040  1.10       wiz         = (have_now >= 2 * had_before)
   1041  1.10       wiz           || ((size_t)parser->m_lastBufferRequestSize > available_buffer);
   1042  1.10       wiz 
   1043  1.10       wiz     if (! enough) {
   1044  1.10       wiz       *endPtr = start; // callers may expect this to be set
   1045  1.10       wiz       return XML_ERROR_NONE;
   1046  1.10       wiz     }
   1047  1.10       wiz   }
   1048  1.10       wiz #if defined(XML_TESTING)
   1049  1.10       wiz   g_bytesScanned += (unsigned)have_now;
   1050  1.10       wiz #endif
   1051  1.10       wiz   // Run in a loop to eliminate dangerous recursion depths
   1052  1.10       wiz   enum XML_Error ret;
   1053  1.10       wiz   *endPtr = start;
   1054  1.10       wiz   while (1) {
   1055  1.10       wiz     // Use endPtr as the new start in each iteration, since it will
   1056  1.10       wiz     // be set to the next start point by m_processor.
   1057  1.10       wiz     ret = parser->m_processor(parser, *endPtr, end, endPtr);
   1058  1.10       wiz 
   1059  1.10       wiz     // Make parsing status (and in particular XML_SUSPENDED) take
   1060  1.10       wiz     // precedence over re-enter flag when they disagree
   1061  1.10       wiz     if (parser->m_parsingStatus.parsing != XML_PARSING) {
   1062  1.10       wiz       parser->m_reenter = XML_FALSE;
   1063  1.10       wiz     }
   1064  1.10       wiz 
   1065  1.10       wiz     if (! parser->m_reenter) {
   1066  1.10       wiz       break;
   1067  1.10       wiz     }
   1068  1.10       wiz 
   1069  1.10       wiz     parser->m_reenter = XML_FALSE;
   1070  1.10       wiz     if (ret != XML_ERROR_NONE)
   1071  1.10       wiz       return ret;
   1072  1.10       wiz   }
   1073  1.10       wiz 
   1074  1.10       wiz   if (ret == XML_ERROR_NONE) {
   1075  1.10       wiz     // if we consumed nothing, remember what we had on this parse attempt.
   1076  1.10       wiz     if (*endPtr == start) {
   1077  1.10       wiz       parser->m_partialTokenBytesBefore = have_now;
   1078  1.10       wiz     } else {
   1079  1.10       wiz       parser->m_partialTokenBytesBefore = 0;
   1080  1.10       wiz     }
   1081  1.10       wiz   }
   1082  1.10       wiz   return ret;
   1083  1.10       wiz }
   1084  1.10       wiz 
   1085   1.8      maya static XML_Bool /* only valid for root parser */
   1086   1.8      maya startParsing(XML_Parser parser) {
   1087   1.8      maya   /* hash functions must be initialized before setContext() is called */
   1088   1.8      maya   if (parser->m_hash_secret_salt == 0)
   1089   1.8      maya     parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
   1090   1.8      maya   if (parser->m_ns) {
   1091   1.8      maya     /* implicit context only set for root parser, since child
   1092   1.8      maya        parsers (i.e. external entity parsers) will inherit it
   1093   1.8      maya     */
   1094   1.8      maya     return setContext(parser, implicitContext);
   1095   1.8      maya   }
   1096   1.8      maya   return XML_TRUE;
   1097   1.3       spz }
   1098   1.3       spz 
   1099   1.1      tron XML_Parser XMLCALL
   1100   1.1      tron XML_ParserCreate_MM(const XML_Char *encodingName,
   1101   1.1      tron                     const XML_Memory_Handling_Suite *memsuite,
   1102   1.8      maya                     const XML_Char *nameSep) {
   1103   1.3       spz   return parserCreate(encodingName, memsuite, nameSep, NULL);
   1104   1.1      tron }
   1105   1.1      tron 
   1106   1.1      tron static XML_Parser
   1107   1.1      tron parserCreate(const XML_Char *encodingName,
   1108   1.8      maya              const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep,
   1109   1.8      maya              DTD *dtd) {
   1110   1.1      tron   XML_Parser parser;
   1111   1.1      tron 
   1112   1.1      tron   if (memsuite) {
   1113   1.1      tron     XML_Memory_Handling_Suite *mtemp;
   1114   1.9  christos     parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
   1115   1.1      tron     if (parser != NULL) {
   1116   1.1      tron       mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
   1117   1.1      tron       mtemp->malloc_fcn = memsuite->malloc_fcn;
   1118   1.1      tron       mtemp->realloc_fcn = memsuite->realloc_fcn;
   1119   1.1      tron       mtemp->free_fcn = memsuite->free_fcn;
   1120   1.1      tron     }
   1121   1.8      maya   } else {
   1122   1.1      tron     XML_Memory_Handling_Suite *mtemp;
   1123   1.1      tron     parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
   1124   1.1      tron     if (parser != NULL) {
   1125   1.1      tron       mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
   1126   1.1      tron       mtemp->malloc_fcn = malloc;
   1127   1.1      tron       mtemp->realloc_fcn = realloc;
   1128   1.1      tron       mtemp->free_fcn = free;
   1129   1.1      tron     }
   1130   1.1      tron   }
   1131   1.1      tron 
   1132   1.8      maya   if (! parser)
   1133   1.1      tron     return parser;
   1134   1.1      tron 
   1135   1.8      maya   parser->m_buffer = NULL;
   1136   1.8      maya   parser->m_bufferLim = NULL;
   1137   1.1      tron 
   1138   1.8      maya   parser->m_attsSize = INIT_ATTS_SIZE;
   1139   1.8      maya   parser->m_atts
   1140   1.8      maya       = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
   1141   1.8      maya   if (parser->m_atts == NULL) {
   1142   1.8      maya     FREE(parser, parser);
   1143   1.1      tron     return NULL;
   1144   1.1      tron   }
   1145   1.3       spz #ifdef XML_ATTR_INFO
   1146   1.8      maya   parser->m_attInfo = (XML_AttrInfo *)MALLOC(
   1147   1.8      maya       parser, parser->m_attsSize * sizeof(XML_AttrInfo));
   1148   1.8      maya   if (parser->m_attInfo == NULL) {
   1149   1.8      maya     FREE(parser, parser->m_atts);
   1150   1.8      maya     FREE(parser, parser);
   1151   1.3       spz     return NULL;
   1152   1.3       spz   }
   1153   1.3       spz #endif
   1154   1.8      maya   parser->m_dataBuf
   1155   1.8      maya       = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
   1156   1.8      maya   if (parser->m_dataBuf == NULL) {
   1157   1.8      maya     FREE(parser, parser->m_atts);
   1158   1.3       spz #ifdef XML_ATTR_INFO
   1159   1.8      maya     FREE(parser, parser->m_attInfo);
   1160   1.3       spz #endif
   1161   1.8      maya     FREE(parser, parser);
   1162   1.1      tron     return NULL;
   1163   1.1      tron   }
   1164   1.8      maya   parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
   1165   1.1      tron 
   1166   1.1      tron   if (dtd)
   1167   1.8      maya     parser->m_dtd = dtd;
   1168   1.1      tron   else {
   1169   1.8      maya     parser->m_dtd = dtdCreate(&parser->m_mem);
   1170   1.8      maya     if (parser->m_dtd == NULL) {
   1171   1.8      maya       FREE(parser, parser->m_dataBuf);
   1172   1.8      maya       FREE(parser, parser->m_atts);
   1173   1.3       spz #ifdef XML_ATTR_INFO
   1174   1.8      maya       FREE(parser, parser->m_attInfo);
   1175   1.3       spz #endif
   1176   1.8      maya       FREE(parser, parser);
   1177   1.1      tron       return NULL;
   1178   1.1      tron     }
   1179   1.1      tron   }
   1180   1.1      tron 
   1181   1.8      maya   parser->m_freeBindingList = NULL;
   1182   1.8      maya   parser->m_freeTagList = NULL;
   1183   1.8      maya   parser->m_freeInternalEntities = NULL;
   1184  1.10       wiz   parser->m_freeAttributeEntities = NULL;
   1185  1.10       wiz   parser->m_freeValueEntities = NULL;
   1186   1.8      maya 
   1187   1.8      maya   parser->m_groupSize = 0;
   1188   1.8      maya   parser->m_groupConnector = NULL;
   1189   1.1      tron 
   1190   1.8      maya   parser->m_unknownEncodingHandler = NULL;
   1191   1.8      maya   parser->m_unknownEncodingHandlerData = NULL;
   1192   1.8      maya 
   1193   1.8      maya   parser->m_namespaceSeparator = ASCII_EXCL;
   1194   1.8      maya   parser->m_ns = XML_FALSE;
   1195   1.8      maya   parser->m_ns_triplets = XML_FALSE;
   1196   1.8      maya 
   1197   1.8      maya   parser->m_nsAtts = NULL;
   1198   1.8      maya   parser->m_nsAttsVersion = 0;
   1199   1.8      maya   parser->m_nsAttsPower = 0;
   1200   1.8      maya 
   1201   1.8      maya   parser->m_protocolEncodingName = NULL;
   1202   1.8      maya 
   1203   1.8      maya   poolInit(&parser->m_tempPool, &(parser->m_mem));
   1204   1.8      maya   poolInit(&parser->m_temp2Pool, &(parser->m_mem));
   1205   1.1      tron   parserInit(parser, encodingName);
   1206   1.1      tron 
   1207   1.8      maya   if (encodingName && ! parser->m_protocolEncodingName) {
   1208  1.10       wiz     if (dtd) {
   1209  1.10       wiz       // We need to stop the upcoming call to XML_ParserFree from happily
   1210  1.10       wiz       // destroying parser->m_dtd because the DTD is shared with the parent
   1211  1.10       wiz       // parser and the only guard that keeps XML_ParserFree from destroying
   1212  1.10       wiz       // parser->m_dtd is parser->m_isParamEntity but it will be set to
   1213  1.10       wiz       // XML_TRUE only later in XML_ExternalEntityParserCreate (or not at all).
   1214  1.10       wiz       parser->m_dtd = NULL;
   1215  1.10       wiz     }
   1216   1.1      tron     XML_ParserFree(parser);
   1217   1.1      tron     return NULL;
   1218   1.1      tron   }
   1219   1.1      tron 
   1220   1.1      tron   if (nameSep) {
   1221   1.8      maya     parser->m_ns = XML_TRUE;
   1222   1.8      maya     parser->m_internalEncoding = XmlGetInternalEncodingNS();
   1223   1.8      maya     parser->m_namespaceSeparator = *nameSep;
   1224   1.8      maya   } else {
   1225   1.8      maya     parser->m_internalEncoding = XmlGetInternalEncoding();
   1226   1.1      tron   }
   1227   1.1      tron 
   1228   1.1      tron   return parser;
   1229   1.1      tron }
   1230   1.1      tron 
   1231   1.1      tron static void
   1232   1.8      maya parserInit(XML_Parser parser, const XML_Char *encodingName) {
   1233   1.8      maya   parser->m_processor = prologInitProcessor;
   1234   1.8      maya   XmlPrologStateInit(&parser->m_prologState);
   1235   1.8      maya   if (encodingName != NULL) {
   1236   1.8      maya     parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
   1237   1.8      maya   }
   1238   1.8      maya   parser->m_curBase = NULL;
   1239   1.8      maya   XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
   1240   1.8      maya   parser->m_userData = NULL;
   1241   1.8      maya   parser->m_handlerArg = NULL;
   1242   1.8      maya   parser->m_startElementHandler = NULL;
   1243   1.8      maya   parser->m_endElementHandler = NULL;
   1244   1.8      maya   parser->m_characterDataHandler = NULL;
   1245   1.8      maya   parser->m_processingInstructionHandler = NULL;
   1246   1.8      maya   parser->m_commentHandler = NULL;
   1247   1.8      maya   parser->m_startCdataSectionHandler = NULL;
   1248   1.8      maya   parser->m_endCdataSectionHandler = NULL;
   1249   1.8      maya   parser->m_defaultHandler = NULL;
   1250   1.8      maya   parser->m_startDoctypeDeclHandler = NULL;
   1251   1.8      maya   parser->m_endDoctypeDeclHandler = NULL;
   1252   1.8      maya   parser->m_unparsedEntityDeclHandler = NULL;
   1253   1.8      maya   parser->m_notationDeclHandler = NULL;
   1254   1.8      maya   parser->m_startNamespaceDeclHandler = NULL;
   1255   1.8      maya   parser->m_endNamespaceDeclHandler = NULL;
   1256   1.8      maya   parser->m_notStandaloneHandler = NULL;
   1257   1.8      maya   parser->m_externalEntityRefHandler = NULL;
   1258   1.8      maya   parser->m_externalEntityRefHandlerArg = parser;
   1259   1.8      maya   parser->m_skippedEntityHandler = NULL;
   1260   1.8      maya   parser->m_elementDeclHandler = NULL;
   1261   1.8      maya   parser->m_attlistDeclHandler = NULL;
   1262   1.8      maya   parser->m_entityDeclHandler = NULL;
   1263   1.8      maya   parser->m_xmlDeclHandler = NULL;
   1264   1.8      maya   parser->m_bufferPtr = parser->m_buffer;
   1265   1.8      maya   parser->m_bufferEnd = parser->m_buffer;
   1266   1.8      maya   parser->m_parseEndByteIndex = 0;
   1267   1.8      maya   parser->m_parseEndPtr = NULL;
   1268  1.10       wiz   parser->m_partialTokenBytesBefore = 0;
   1269  1.10       wiz   parser->m_reparseDeferralEnabled = g_reparseDeferralEnabledDefault;
   1270  1.10       wiz   parser->m_lastBufferRequestSize = 0;
   1271   1.8      maya   parser->m_declElementType = NULL;
   1272   1.8      maya   parser->m_declAttributeId = NULL;
   1273   1.8      maya   parser->m_declEntity = NULL;
   1274   1.8      maya   parser->m_doctypeName = NULL;
   1275   1.8      maya   parser->m_doctypeSysid = NULL;
   1276   1.8      maya   parser->m_doctypePubid = NULL;
   1277   1.8      maya   parser->m_declAttributeType = NULL;
   1278   1.8      maya   parser->m_declNotationName = NULL;
   1279   1.8      maya   parser->m_declNotationPublicId = NULL;
   1280   1.8      maya   parser->m_declAttributeIsCdata = XML_FALSE;
   1281   1.8      maya   parser->m_declAttributeIsId = XML_FALSE;
   1282   1.8      maya   memset(&parser->m_position, 0, sizeof(POSITION));
   1283   1.8      maya   parser->m_errorCode = XML_ERROR_NONE;
   1284   1.8      maya   parser->m_eventPtr = NULL;
   1285   1.8      maya   parser->m_eventEndPtr = NULL;
   1286   1.8      maya   parser->m_positionPtr = NULL;
   1287   1.8      maya   parser->m_openInternalEntities = NULL;
   1288  1.10       wiz   parser->m_openAttributeEntities = NULL;
   1289  1.10       wiz   parser->m_openValueEntities = NULL;
   1290   1.8      maya   parser->m_defaultExpandInternalEntities = XML_TRUE;
   1291   1.8      maya   parser->m_tagLevel = 0;
   1292   1.8      maya   parser->m_tagStack = NULL;
   1293   1.8      maya   parser->m_inheritedBindings = NULL;
   1294   1.8      maya   parser->m_nSpecifiedAtts = 0;
   1295   1.8      maya   parser->m_unknownEncodingMem = NULL;
   1296   1.8      maya   parser->m_unknownEncodingRelease = NULL;
   1297   1.8      maya   parser->m_unknownEncodingData = NULL;
   1298   1.8      maya   parser->m_parentParser = NULL;
   1299   1.8      maya   parser->m_parsingStatus.parsing = XML_INITIALIZED;
   1300  1.10       wiz   // Reentry can only be triggered inside m_processor calls
   1301  1.10       wiz   parser->m_reenter = XML_FALSE;
   1302   1.8      maya #ifdef XML_DTD
   1303   1.8      maya   parser->m_isParamEntity = XML_FALSE;
   1304   1.8      maya   parser->m_useForeignDTD = XML_FALSE;
   1305   1.8      maya   parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
   1306   1.1      tron #endif
   1307   1.8      maya   parser->m_hash_secret_salt = 0;
   1308   1.9  christos 
   1309  1.10       wiz #if XML_GE == 1
   1310   1.9  christos   memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
   1311   1.9  christos   parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
   1312   1.9  christos   parser->m_accounting.maximumAmplificationFactor
   1313   1.9  christos       = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT;
   1314   1.9  christos   parser->m_accounting.activationThresholdBytes
   1315   1.9  christos       = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT;
   1316   1.9  christos 
   1317   1.9  christos   memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS));
   1318   1.9  christos   parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u);
   1319   1.9  christos #endif
   1320   1.1      tron }
   1321   1.1      tron 
   1322   1.8      maya /* moves list of bindings to m_freeBindingList */
   1323   1.1      tron static void FASTCALL
   1324   1.8      maya moveToFreeBindingList(XML_Parser parser, BINDING *bindings) {
   1325   1.1      tron   while (bindings) {
   1326   1.1      tron     BINDING *b = bindings;
   1327   1.1      tron     bindings = bindings->nextTagBinding;
   1328   1.8      maya     b->nextTagBinding = parser->m_freeBindingList;
   1329   1.8      maya     parser->m_freeBindingList = b;
   1330   1.1      tron   }
   1331   1.1      tron }
   1332   1.1      tron 
   1333   1.1      tron XML_Bool XMLCALL
   1334   1.8      maya XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
   1335   1.1      tron   TAG *tStk;
   1336   1.1      tron   OPEN_INTERNAL_ENTITY *openEntityList;
   1337   1.7  christos 
   1338   1.7  christos   if (parser == NULL)
   1339   1.8      maya     return XML_FALSE;
   1340   1.7  christos 
   1341   1.8      maya   if (parser->m_parentParser)
   1342   1.1      tron     return XML_FALSE;
   1343   1.8      maya   /* move m_tagStack to m_freeTagList */
   1344   1.8      maya   tStk = parser->m_tagStack;
   1345   1.1      tron   while (tStk) {
   1346   1.1      tron     TAG *tag = tStk;
   1347   1.1      tron     tStk = tStk->parent;
   1348   1.8      maya     tag->parent = parser->m_freeTagList;
   1349   1.1      tron     moveToFreeBindingList(parser, tag->bindings);
   1350   1.1      tron     tag->bindings = NULL;
   1351   1.8      maya     parser->m_freeTagList = tag;
   1352   1.1      tron   }
   1353   1.8      maya   /* move m_openInternalEntities to m_freeInternalEntities */
   1354   1.8      maya   openEntityList = parser->m_openInternalEntities;
   1355   1.1      tron   while (openEntityList) {
   1356   1.1      tron     OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
   1357   1.1      tron     openEntityList = openEntity->next;
   1358   1.8      maya     openEntity->next = parser->m_freeInternalEntities;
   1359   1.8      maya     parser->m_freeInternalEntities = openEntity;
   1360   1.1      tron   }
   1361  1.10       wiz   /* move m_openAttributeEntities to m_freeAttributeEntities (i.e. same task but
   1362  1.10       wiz    * for attributes) */
   1363  1.10       wiz   openEntityList = parser->m_openAttributeEntities;
   1364  1.10       wiz   while (openEntityList) {
   1365  1.10       wiz     OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
   1366  1.10       wiz     openEntityList = openEntity->next;
   1367  1.10       wiz     openEntity->next = parser->m_freeAttributeEntities;
   1368  1.10       wiz     parser->m_freeAttributeEntities = openEntity;
   1369  1.10       wiz   }
   1370  1.10       wiz   /* move m_openValueEntities to m_freeValueEntities (i.e. same task but
   1371  1.10       wiz    * for value entities) */
   1372  1.10       wiz   openEntityList = parser->m_openValueEntities;
   1373  1.10       wiz   while (openEntityList) {
   1374  1.10       wiz     OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
   1375  1.10       wiz     openEntityList = openEntity->next;
   1376  1.10       wiz     openEntity->next = parser->m_freeValueEntities;
   1377  1.10       wiz     parser->m_freeValueEntities = openEntity;
   1378  1.10       wiz   }
   1379   1.8      maya   moveToFreeBindingList(parser, parser->m_inheritedBindings);
   1380   1.8      maya   FREE(parser, parser->m_unknownEncodingMem);
   1381   1.8      maya   if (parser->m_unknownEncodingRelease)
   1382   1.8      maya     parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
   1383   1.8      maya   poolClear(&parser->m_tempPool);
   1384   1.8      maya   poolClear(&parser->m_temp2Pool);
   1385   1.8      maya   FREE(parser, (void *)parser->m_protocolEncodingName);
   1386   1.8      maya   parser->m_protocolEncodingName = NULL;
   1387   1.1      tron   parserInit(parser, encodingName);
   1388   1.8      maya   dtdReset(parser->m_dtd, &parser->m_mem);
   1389   1.3       spz   return XML_TRUE;
   1390   1.1      tron }
   1391   1.1      tron 
   1392  1.10       wiz static XML_Bool
   1393  1.10       wiz parserBusy(XML_Parser parser) {
   1394  1.10       wiz   switch (parser->m_parsingStatus.parsing) {
   1395  1.10       wiz   case XML_PARSING:
   1396  1.10       wiz   case XML_SUSPENDED:
   1397  1.10       wiz     return XML_TRUE;
   1398  1.10       wiz   case XML_INITIALIZED:
   1399  1.10       wiz   case XML_FINISHED:
   1400  1.10       wiz   default:
   1401  1.10       wiz     return XML_FALSE;
   1402  1.10       wiz   }
   1403  1.10       wiz }
   1404  1.10       wiz 
   1405   1.1      tron enum XML_Status XMLCALL
   1406   1.8      maya XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
   1407   1.7  christos   if (parser == NULL)
   1408   1.8      maya     return XML_STATUS_ERROR;
   1409   1.1      tron   /* Block after XML_Parse()/XML_ParseBuffer() has been called.
   1410   1.1      tron      XXX There's no way for the caller to determine which of the
   1411   1.1      tron      XXX possible error cases caused the XML_STATUS_ERROR return.
   1412   1.1      tron   */
   1413  1.10       wiz   if (parserBusy(parser))
   1414   1.1      tron     return XML_STATUS_ERROR;
   1415   1.8      maya 
   1416   1.8      maya   /* Get rid of any previous encoding name */
   1417   1.8      maya   FREE(parser, (void *)parser->m_protocolEncodingName);
   1418   1.8      maya 
   1419   1.1      tron   if (encodingName == NULL)
   1420   1.8      maya     /* No new encoding name */
   1421   1.8      maya     parser->m_protocolEncodingName = NULL;
   1422   1.1      tron   else {
   1423   1.8      maya     /* Copy the new encoding name into allocated memory */
   1424   1.8      maya     parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
   1425   1.8      maya     if (! parser->m_protocolEncodingName)
   1426   1.1      tron       return XML_STATUS_ERROR;
   1427   1.1      tron   }
   1428   1.1      tron   return XML_STATUS_OK;
   1429   1.1      tron }
   1430   1.1      tron 
   1431   1.1      tron XML_Parser XMLCALL
   1432   1.8      maya XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
   1433   1.8      maya                                const XML_Char *encodingName) {
   1434   1.1      tron   XML_Parser parser = oldParser;
   1435   1.1      tron   DTD *newDtd = NULL;
   1436   1.7  christos   DTD *oldDtd;
   1437   1.7  christos   XML_StartElementHandler oldStartElementHandler;
   1438   1.7  christos   XML_EndElementHandler oldEndElementHandler;
   1439   1.7  christos   XML_CharacterDataHandler oldCharacterDataHandler;
   1440   1.7  christos   XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
   1441   1.7  christos   XML_CommentHandler oldCommentHandler;
   1442   1.7  christos   XML_StartCdataSectionHandler oldStartCdataSectionHandler;
   1443   1.7  christos   XML_EndCdataSectionHandler oldEndCdataSectionHandler;
   1444   1.7  christos   XML_DefaultHandler oldDefaultHandler;
   1445   1.7  christos   XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
   1446   1.7  christos   XML_NotationDeclHandler oldNotationDeclHandler;
   1447   1.7  christos   XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
   1448   1.7  christos   XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
   1449   1.7  christos   XML_NotStandaloneHandler oldNotStandaloneHandler;
   1450   1.7  christos   XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
   1451   1.7  christos   XML_SkippedEntityHandler oldSkippedEntityHandler;
   1452   1.7  christos   XML_UnknownEncodingHandler oldUnknownEncodingHandler;
   1453   1.7  christos   XML_ElementDeclHandler oldElementDeclHandler;
   1454   1.7  christos   XML_AttlistDeclHandler oldAttlistDeclHandler;
   1455   1.7  christos   XML_EntityDeclHandler oldEntityDeclHandler;
   1456   1.7  christos   XML_XmlDeclHandler oldXmlDeclHandler;
   1457   1.8      maya   ELEMENT_TYPE *oldDeclElementType;
   1458   1.7  christos 
   1459   1.7  christos   void *oldUserData;
   1460   1.7  christos   void *oldHandlerArg;
   1461   1.7  christos   XML_Bool oldDefaultExpandInternalEntities;
   1462   1.7  christos   XML_Parser oldExternalEntityRefHandlerArg;
   1463   1.1      tron #ifdef XML_DTD
   1464   1.7  christos   enum XML_ParamEntityParsing oldParamEntityParsing;
   1465   1.7  christos   int oldInEntityValue;
   1466   1.7  christos #endif
   1467   1.7  christos   XML_Bool oldns_triplets;
   1468   1.7  christos   /* Note that the new parser shares the same hash secret as the old
   1469   1.7  christos      parser, so that dtdCopy and copyEntityTable can lookup values
   1470   1.7  christos      from hash tables associated with either parser without us having
   1471   1.7  christos      to worry which hash secrets each table has.
   1472   1.7  christos   */
   1473   1.7  christos   unsigned long oldhash_secret_salt;
   1474  1.10       wiz   XML_Bool oldReparseDeferralEnabled;
   1475   1.7  christos 
   1476   1.7  christos   /* Validate the oldParser parameter before we pull everything out of it */
   1477   1.7  christos   if (oldParser == NULL)
   1478   1.7  christos     return NULL;
   1479   1.7  christos 
   1480   1.7  christos   /* Stash the original parser contents on the stack */
   1481   1.8      maya   oldDtd = parser->m_dtd;
   1482   1.8      maya   oldStartElementHandler = parser->m_startElementHandler;
   1483   1.8      maya   oldEndElementHandler = parser->m_endElementHandler;
   1484   1.8      maya   oldCharacterDataHandler = parser->m_characterDataHandler;
   1485   1.8      maya   oldProcessingInstructionHandler = parser->m_processingInstructionHandler;
   1486   1.8      maya   oldCommentHandler = parser->m_commentHandler;
   1487   1.8      maya   oldStartCdataSectionHandler = parser->m_startCdataSectionHandler;
   1488   1.8      maya   oldEndCdataSectionHandler = parser->m_endCdataSectionHandler;
   1489   1.8      maya   oldDefaultHandler = parser->m_defaultHandler;
   1490   1.8      maya   oldUnparsedEntityDeclHandler = parser->m_unparsedEntityDeclHandler;
   1491   1.8      maya   oldNotationDeclHandler = parser->m_notationDeclHandler;
   1492   1.8      maya   oldStartNamespaceDeclHandler = parser->m_startNamespaceDeclHandler;
   1493   1.8      maya   oldEndNamespaceDeclHandler = parser->m_endNamespaceDeclHandler;
   1494   1.8      maya   oldNotStandaloneHandler = parser->m_notStandaloneHandler;
   1495   1.8      maya   oldExternalEntityRefHandler = parser->m_externalEntityRefHandler;
   1496   1.8      maya   oldSkippedEntityHandler = parser->m_skippedEntityHandler;
   1497   1.8      maya   oldUnknownEncodingHandler = parser->m_unknownEncodingHandler;
   1498   1.8      maya   oldElementDeclHandler = parser->m_elementDeclHandler;
   1499   1.8      maya   oldAttlistDeclHandler = parser->m_attlistDeclHandler;
   1500   1.8      maya   oldEntityDeclHandler = parser->m_entityDeclHandler;
   1501   1.8      maya   oldXmlDeclHandler = parser->m_xmlDeclHandler;
   1502   1.8      maya   oldDeclElementType = parser->m_declElementType;
   1503   1.8      maya 
   1504   1.8      maya   oldUserData = parser->m_userData;
   1505   1.8      maya   oldHandlerArg = parser->m_handlerArg;
   1506   1.8      maya   oldDefaultExpandInternalEntities = parser->m_defaultExpandInternalEntities;
   1507   1.8      maya   oldExternalEntityRefHandlerArg = parser->m_externalEntityRefHandlerArg;
   1508   1.7  christos #ifdef XML_DTD
   1509   1.8      maya   oldParamEntityParsing = parser->m_paramEntityParsing;
   1510   1.8      maya   oldInEntityValue = parser->m_prologState.inEntityValue;
   1511   1.1      tron #endif
   1512   1.8      maya   oldns_triplets = parser->m_ns_triplets;
   1513   1.3       spz   /* Note that the new parser shares the same hash secret as the old
   1514   1.3       spz      parser, so that dtdCopy and copyEntityTable can lookup values
   1515   1.3       spz      from hash tables associated with either parser without us having
   1516   1.3       spz      to worry which hash secrets each table has.
   1517   1.3       spz   */
   1518   1.8      maya   oldhash_secret_salt = parser->m_hash_secret_salt;
   1519  1.10       wiz   oldReparseDeferralEnabled = parser->m_reparseDeferralEnabled;
   1520   1.1      tron 
   1521   1.1      tron #ifdef XML_DTD
   1522   1.8      maya   if (! context)
   1523   1.1      tron     newDtd = oldDtd;
   1524   1.1      tron #endif /* XML_DTD */
   1525   1.1      tron 
   1526   1.1      tron   /* Note that the magical uses of the pre-processor to make field
   1527   1.1      tron      access look more like C++ require that `parser' be overwritten
   1528   1.1      tron      here.  This makes this function more painful to follow than it
   1529   1.1      tron      would be otherwise.
   1530   1.1      tron   */
   1531   1.8      maya   if (parser->m_ns) {
   1532   1.9  christos     XML_Char tmp[2] = {parser->m_namespaceSeparator, 0};
   1533   1.1      tron     parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
   1534   1.8      maya   } else {
   1535   1.1      tron     parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
   1536   1.1      tron   }
   1537   1.1      tron 
   1538   1.8      maya   if (! parser)
   1539   1.1      tron     return NULL;
   1540   1.1      tron 
   1541   1.8      maya   parser->m_startElementHandler = oldStartElementHandler;
   1542   1.8      maya   parser->m_endElementHandler = oldEndElementHandler;
   1543   1.8      maya   parser->m_characterDataHandler = oldCharacterDataHandler;
   1544   1.8      maya   parser->m_processingInstructionHandler = oldProcessingInstructionHandler;
   1545   1.8      maya   parser->m_commentHandler = oldCommentHandler;
   1546   1.8      maya   parser->m_startCdataSectionHandler = oldStartCdataSectionHandler;
   1547   1.8      maya   parser->m_endCdataSectionHandler = oldEndCdataSectionHandler;
   1548   1.8      maya   parser->m_defaultHandler = oldDefaultHandler;
   1549   1.8      maya   parser->m_unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
   1550   1.8      maya   parser->m_notationDeclHandler = oldNotationDeclHandler;
   1551   1.8      maya   parser->m_startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
   1552   1.8      maya   parser->m_endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
   1553   1.8      maya   parser->m_notStandaloneHandler = oldNotStandaloneHandler;
   1554   1.8      maya   parser->m_externalEntityRefHandler = oldExternalEntityRefHandler;
   1555   1.8      maya   parser->m_skippedEntityHandler = oldSkippedEntityHandler;
   1556   1.8      maya   parser->m_unknownEncodingHandler = oldUnknownEncodingHandler;
   1557   1.8      maya   parser->m_elementDeclHandler = oldElementDeclHandler;
   1558   1.8      maya   parser->m_attlistDeclHandler = oldAttlistDeclHandler;
   1559   1.8      maya   parser->m_entityDeclHandler = oldEntityDeclHandler;
   1560   1.8      maya   parser->m_xmlDeclHandler = oldXmlDeclHandler;
   1561   1.8      maya   parser->m_declElementType = oldDeclElementType;
   1562   1.8      maya   parser->m_userData = oldUserData;
   1563   1.1      tron   if (oldUserData == oldHandlerArg)
   1564   1.8      maya     parser->m_handlerArg = parser->m_userData;
   1565   1.1      tron   else
   1566   1.8      maya     parser->m_handlerArg = parser;
   1567   1.1      tron   if (oldExternalEntityRefHandlerArg != oldParser)
   1568   1.8      maya     parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
   1569   1.8      maya   parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
   1570   1.8      maya   parser->m_ns_triplets = oldns_triplets;
   1571   1.8      maya   parser->m_hash_secret_salt = oldhash_secret_salt;
   1572  1.10       wiz   parser->m_reparseDeferralEnabled = oldReparseDeferralEnabled;
   1573   1.8      maya   parser->m_parentParser = oldParser;
   1574   1.1      tron #ifdef XML_DTD
   1575   1.8      maya   parser->m_paramEntityParsing = oldParamEntityParsing;
   1576   1.8      maya   parser->m_prologState.inEntityValue = oldInEntityValue;
   1577   1.1      tron   if (context) {
   1578   1.1      tron #endif /* XML_DTD */
   1579   1.8      maya     if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
   1580   1.8      maya         || ! setContext(parser, context)) {
   1581   1.1      tron       XML_ParserFree(parser);
   1582   1.1      tron       return NULL;
   1583   1.1      tron     }
   1584   1.8      maya     parser->m_processor = externalEntityInitProcessor;
   1585   1.1      tron #ifdef XML_DTD
   1586   1.8      maya   } else {
   1587   1.8      maya     /* The DTD instance referenced by parser->m_dtd is shared between the
   1588   1.8      maya        document's root parser and external PE parsers, therefore one does not
   1589   1.8      maya        need to call setContext. In addition, one also *must* not call
   1590   1.8      maya        setContext, because this would overwrite existing prefix->binding
   1591   1.8      maya        pointers in parser->m_dtd with ones that get destroyed with the external
   1592   1.8      maya        PE parser. This would leave those prefixes with dangling pointers.
   1593   1.1      tron     */
   1594   1.8      maya     parser->m_isParamEntity = XML_TRUE;
   1595   1.8      maya     XmlPrologStateInitExternalEntity(&parser->m_prologState);
   1596   1.8      maya     parser->m_processor = externalParEntInitProcessor;
   1597   1.1      tron   }
   1598   1.1      tron #endif /* XML_DTD */
   1599   1.1      tron   return parser;
   1600   1.1      tron }
   1601   1.1      tron 
   1602   1.1      tron static void FASTCALL
   1603   1.8      maya destroyBindings(BINDING *bindings, XML_Parser parser) {
   1604   1.1      tron   for (;;) {
   1605   1.1      tron     BINDING *b = bindings;
   1606   1.8      maya     if (! b)
   1607   1.1      tron       break;
   1608   1.1      tron     bindings = b->nextTagBinding;
   1609   1.8      maya     FREE(parser, b->uri);
   1610   1.8      maya     FREE(parser, b);
   1611   1.1      tron   }
   1612   1.1      tron }
   1613   1.1      tron 
   1614   1.1      tron void XMLCALL
   1615   1.8      maya XML_ParserFree(XML_Parser parser) {
   1616   1.1      tron   TAG *tagList;
   1617   1.1      tron   OPEN_INTERNAL_ENTITY *entityList;
   1618   1.1      tron   if (parser == NULL)
   1619   1.1      tron     return;
   1620   1.8      maya   /* free m_tagStack and m_freeTagList */
   1621   1.8      maya   tagList = parser->m_tagStack;
   1622   1.1      tron   for (;;) {
   1623   1.1      tron     TAG *p;
   1624   1.1      tron     if (tagList == NULL) {
   1625   1.8      maya       if (parser->m_freeTagList == NULL)
   1626   1.1      tron         break;
   1627   1.8      maya       tagList = parser->m_freeTagList;
   1628   1.8      maya       parser->m_freeTagList = NULL;
   1629   1.1      tron     }
   1630   1.1      tron     p = tagList;
   1631   1.1      tron     tagList = tagList->parent;
   1632   1.8      maya     FREE(parser, p->buf);
   1633   1.1      tron     destroyBindings(p->bindings, parser);
   1634   1.8      maya     FREE(parser, p);
   1635   1.1      tron   }
   1636   1.8      maya   /* free m_openInternalEntities and m_freeInternalEntities */
   1637   1.8      maya   entityList = parser->m_openInternalEntities;
   1638   1.1      tron   for (;;) {
   1639   1.1      tron     OPEN_INTERNAL_ENTITY *openEntity;
   1640   1.1      tron     if (entityList == NULL) {
   1641   1.8      maya       if (parser->m_freeInternalEntities == NULL)
   1642   1.1      tron         break;
   1643   1.8      maya       entityList = parser->m_freeInternalEntities;
   1644   1.8      maya       parser->m_freeInternalEntities = NULL;
   1645   1.1      tron     }
   1646   1.1      tron     openEntity = entityList;
   1647   1.1      tron     entityList = entityList->next;
   1648   1.8      maya     FREE(parser, openEntity);
   1649   1.1      tron   }
   1650  1.10       wiz   /* free m_openAttributeEntities and m_freeAttributeEntities */
   1651  1.10       wiz   entityList = parser->m_openAttributeEntities;
   1652  1.10       wiz   for (;;) {
   1653  1.10       wiz     OPEN_INTERNAL_ENTITY *openEntity;
   1654  1.10       wiz     if (entityList == NULL) {
   1655  1.10       wiz       if (parser->m_freeAttributeEntities == NULL)
   1656  1.10       wiz         break;
   1657  1.10       wiz       entityList = parser->m_freeAttributeEntities;
   1658  1.10       wiz       parser->m_freeAttributeEntities = NULL;
   1659  1.10       wiz     }
   1660  1.10       wiz     openEntity = entityList;
   1661  1.10       wiz     entityList = entityList->next;
   1662  1.10       wiz     FREE(parser, openEntity);
   1663  1.10       wiz   }
   1664  1.10       wiz   /* free m_openValueEntities and m_freeValueEntities */
   1665  1.10       wiz   entityList = parser->m_openValueEntities;
   1666  1.10       wiz   for (;;) {
   1667  1.10       wiz     OPEN_INTERNAL_ENTITY *openEntity;
   1668  1.10       wiz     if (entityList == NULL) {
   1669  1.10       wiz       if (parser->m_freeValueEntities == NULL)
   1670  1.10       wiz         break;
   1671  1.10       wiz       entityList = parser->m_freeValueEntities;
   1672  1.10       wiz       parser->m_freeValueEntities = NULL;
   1673  1.10       wiz     }
   1674  1.10       wiz     openEntity = entityList;
   1675  1.10       wiz     entityList = entityList->next;
   1676  1.10       wiz     FREE(parser, openEntity);
   1677  1.10       wiz   }
   1678   1.8      maya   destroyBindings(parser->m_freeBindingList, parser);
   1679   1.8      maya   destroyBindings(parser->m_inheritedBindings, parser);
   1680   1.8      maya   poolDestroy(&parser->m_tempPool);
   1681   1.8      maya   poolDestroy(&parser->m_temp2Pool);
   1682   1.8      maya   FREE(parser, (void *)parser->m_protocolEncodingName);
   1683   1.1      tron #ifdef XML_DTD
   1684   1.1      tron   /* external parameter entity parsers share the DTD structure
   1685   1.1      tron      parser->m_dtd with the root parser, so we must not destroy it
   1686   1.1      tron   */
   1687   1.8      maya   if (! parser->m_isParamEntity && parser->m_dtd)
   1688   1.1      tron #else
   1689   1.8      maya   if (parser->m_dtd)
   1690   1.1      tron #endif /* XML_DTD */
   1691   1.8      maya     dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser,
   1692   1.8      maya                &parser->m_mem);
   1693   1.8      maya   FREE(parser, (void *)parser->m_atts);
   1694   1.3       spz #ifdef XML_ATTR_INFO
   1695   1.8      maya   FREE(parser, (void *)parser->m_attInfo);
   1696   1.3       spz #endif
   1697   1.8      maya   FREE(parser, parser->m_groupConnector);
   1698   1.8      maya   FREE(parser, parser->m_buffer);
   1699   1.8      maya   FREE(parser, parser->m_dataBuf);
   1700   1.8      maya   FREE(parser, parser->m_nsAtts);
   1701   1.8      maya   FREE(parser, parser->m_unknownEncodingMem);
   1702   1.8      maya   if (parser->m_unknownEncodingRelease)
   1703   1.8      maya     parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
   1704   1.8      maya   FREE(parser, parser);
   1705   1.1      tron }
   1706   1.1      tron 
   1707   1.1      tron void XMLCALL
   1708   1.8      maya XML_UseParserAsHandlerArg(XML_Parser parser) {
   1709   1.7  christos   if (parser != NULL)
   1710   1.8      maya     parser->m_handlerArg = parser;
   1711   1.1      tron }
   1712   1.1      tron 
   1713   1.1      tron enum XML_Error XMLCALL
   1714   1.8      maya XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) {
   1715   1.7  christos   if (parser == NULL)
   1716   1.7  christos     return XML_ERROR_INVALID_ARGUMENT;
   1717   1.1      tron #ifdef XML_DTD
   1718   1.1      tron   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   1719  1.10       wiz   if (parserBusy(parser))
   1720   1.1      tron     return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
   1721   1.8      maya   parser->m_useForeignDTD = useDTD;
   1722   1.1      tron   return XML_ERROR_NONE;
   1723   1.1      tron #else
   1724   1.9  christos   UNUSED_P(useDTD);
   1725   1.1      tron   return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
   1726   1.1      tron #endif
   1727   1.1      tron }
   1728   1.1      tron 
   1729   1.1      tron void XMLCALL
   1730   1.8      maya XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
   1731   1.7  christos   if (parser == NULL)
   1732   1.7  christos     return;
   1733   1.1      tron   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   1734  1.10       wiz   if (parserBusy(parser))
   1735   1.1      tron     return;
   1736   1.8      maya   parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
   1737   1.1      tron }
   1738   1.1      tron 
   1739   1.1      tron void XMLCALL
   1740   1.8      maya XML_SetUserData(XML_Parser parser, void *p) {
   1741   1.7  christos   if (parser == NULL)
   1742   1.7  christos     return;
   1743   1.8      maya   if (parser->m_handlerArg == parser->m_userData)
   1744   1.8      maya     parser->m_handlerArg = parser->m_userData = p;
   1745   1.1      tron   else
   1746   1.8      maya     parser->m_userData = p;
   1747   1.1      tron }
   1748   1.1      tron 
   1749   1.1      tron enum XML_Status XMLCALL
   1750   1.8      maya XML_SetBase(XML_Parser parser, const XML_Char *p) {
   1751   1.7  christos   if (parser == NULL)
   1752   1.7  christos     return XML_STATUS_ERROR;
   1753   1.1      tron   if (p) {
   1754   1.8      maya     p = poolCopyString(&parser->m_dtd->pool, p);
   1755   1.8      maya     if (! p)
   1756   1.1      tron       return XML_STATUS_ERROR;
   1757   1.8      maya     parser->m_curBase = p;
   1758   1.8      maya   } else
   1759   1.8      maya     parser->m_curBase = NULL;
   1760   1.1      tron   return XML_STATUS_OK;
   1761   1.1      tron }
   1762   1.1      tron 
   1763   1.8      maya const XML_Char *XMLCALL
   1764   1.8      maya XML_GetBase(XML_Parser parser) {
   1765   1.7  christos   if (parser == NULL)
   1766   1.7  christos     return NULL;
   1767   1.8      maya   return parser->m_curBase;
   1768   1.1      tron }
   1769   1.1      tron 
   1770   1.1      tron int XMLCALL
   1771   1.8      maya XML_GetSpecifiedAttributeCount(XML_Parser parser) {
   1772   1.7  christos   if (parser == NULL)
   1773   1.7  christos     return -1;
   1774   1.8      maya   return parser->m_nSpecifiedAtts;
   1775   1.1      tron }
   1776   1.1      tron 
   1777   1.1      tron int XMLCALL
   1778   1.8      maya XML_GetIdAttributeIndex(XML_Parser parser) {
   1779   1.7  christos   if (parser == NULL)
   1780   1.7  christos     return -1;
   1781   1.8      maya   return parser->m_idAttIndex;
   1782   1.1      tron }
   1783   1.1      tron 
   1784   1.3       spz #ifdef XML_ATTR_INFO
   1785   1.8      maya const XML_AttrInfo *XMLCALL
   1786   1.8      maya XML_GetAttributeInfo(XML_Parser parser) {
   1787   1.7  christos   if (parser == NULL)
   1788   1.7  christos     return NULL;
   1789   1.8      maya   return parser->m_attInfo;
   1790   1.3       spz }
   1791   1.3       spz #endif
   1792   1.3       spz 
   1793   1.1      tron void XMLCALL
   1794   1.8      maya XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start,
   1795   1.8      maya                       XML_EndElementHandler end) {
   1796   1.7  christos   if (parser == NULL)
   1797   1.7  christos     return;
   1798   1.8      maya   parser->m_startElementHandler = start;
   1799   1.8      maya   parser->m_endElementHandler = end;
   1800   1.1      tron }
   1801   1.1      tron 
   1802   1.1      tron void XMLCALL
   1803   1.8      maya XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) {
   1804   1.7  christos   if (parser != NULL)
   1805   1.8      maya     parser->m_startElementHandler = start;
   1806   1.1      tron }
   1807   1.1      tron 
   1808   1.1      tron void XMLCALL
   1809   1.8      maya XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) {
   1810   1.7  christos   if (parser != NULL)
   1811   1.8      maya     parser->m_endElementHandler = end;
   1812   1.1      tron }
   1813   1.1      tron 
   1814   1.1      tron void XMLCALL
   1815   1.1      tron XML_SetCharacterDataHandler(XML_Parser parser,
   1816   1.8      maya                             XML_CharacterDataHandler handler) {
   1817   1.7  christos   if (parser != NULL)
   1818   1.8      maya     parser->m_characterDataHandler = handler;
   1819   1.1      tron }
   1820   1.1      tron 
   1821   1.1      tron void XMLCALL
   1822   1.1      tron XML_SetProcessingInstructionHandler(XML_Parser parser,
   1823   1.8      maya                                     XML_ProcessingInstructionHandler handler) {
   1824   1.7  christos   if (parser != NULL)
   1825   1.8      maya     parser->m_processingInstructionHandler = handler;
   1826   1.1      tron }
   1827   1.1      tron 
   1828   1.1      tron void XMLCALL
   1829   1.8      maya XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) {
   1830   1.7  christos   if (parser != NULL)
   1831   1.8      maya     parser->m_commentHandler = handler;
   1832   1.1      tron }
   1833   1.1      tron 
   1834   1.1      tron void XMLCALL
   1835   1.1      tron XML_SetCdataSectionHandler(XML_Parser parser,
   1836   1.1      tron                            XML_StartCdataSectionHandler start,
   1837   1.8      maya                            XML_EndCdataSectionHandler end) {
   1838   1.7  christos   if (parser == NULL)
   1839   1.7  christos     return;
   1840   1.8      maya   parser->m_startCdataSectionHandler = start;
   1841   1.8      maya   parser->m_endCdataSectionHandler = end;
   1842   1.1      tron }
   1843   1.1      tron 
   1844   1.1      tron void XMLCALL
   1845   1.1      tron XML_SetStartCdataSectionHandler(XML_Parser parser,
   1846   1.1      tron                                 XML_StartCdataSectionHandler start) {
   1847   1.7  christos   if (parser != NULL)
   1848   1.8      maya     parser->m_startCdataSectionHandler = start;
   1849   1.1      tron }
   1850   1.1      tron 
   1851   1.1      tron void XMLCALL
   1852   1.1      tron XML_SetEndCdataSectionHandler(XML_Parser parser,
   1853   1.1      tron                               XML_EndCdataSectionHandler end) {
   1854   1.7  christos   if (parser != NULL)
   1855   1.8      maya     parser->m_endCdataSectionHandler = end;
   1856   1.1      tron }
   1857   1.1      tron 
   1858   1.1      tron void XMLCALL
   1859   1.8      maya XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) {
   1860   1.7  christos   if (parser == NULL)
   1861   1.7  christos     return;
   1862   1.8      maya   parser->m_defaultHandler = handler;
   1863   1.8      maya   parser->m_defaultExpandInternalEntities = XML_FALSE;
   1864   1.1      tron }
   1865   1.1      tron 
   1866   1.1      tron void XMLCALL
   1867   1.8      maya XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) {
   1868   1.7  christos   if (parser == NULL)
   1869   1.7  christos     return;
   1870   1.8      maya   parser->m_defaultHandler = handler;
   1871   1.8      maya   parser->m_defaultExpandInternalEntities = XML_TRUE;
   1872   1.1      tron }
   1873   1.1      tron 
   1874   1.1      tron void XMLCALL
   1875   1.8      maya XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start,
   1876   1.8      maya                           XML_EndDoctypeDeclHandler end) {
   1877   1.7  christos   if (parser == NULL)
   1878   1.7  christos     return;
   1879   1.8      maya   parser->m_startDoctypeDeclHandler = start;
   1880   1.8      maya   parser->m_endDoctypeDeclHandler = end;
   1881   1.1      tron }
   1882   1.1      tron 
   1883   1.1      tron void XMLCALL
   1884   1.1      tron XML_SetStartDoctypeDeclHandler(XML_Parser parser,
   1885   1.1      tron                                XML_StartDoctypeDeclHandler start) {
   1886   1.7  christos   if (parser != NULL)
   1887   1.8      maya     parser->m_startDoctypeDeclHandler = start;
   1888   1.1      tron }
   1889   1.1      tron 
   1890   1.1      tron void XMLCALL
   1891   1.8      maya XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) {
   1892   1.7  christos   if (parser != NULL)
   1893   1.8      maya     parser->m_endDoctypeDeclHandler = end;
   1894   1.1      tron }
   1895   1.1      tron 
   1896   1.1      tron void XMLCALL
   1897   1.1      tron XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
   1898   1.8      maya                                  XML_UnparsedEntityDeclHandler handler) {
   1899   1.7  christos   if (parser != NULL)
   1900   1.8      maya     parser->m_unparsedEntityDeclHandler = handler;
   1901   1.1      tron }
   1902   1.1      tron 
   1903   1.1      tron void XMLCALL
   1904   1.8      maya XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) {
   1905   1.7  christos   if (parser != NULL)
   1906   1.8      maya     parser->m_notationDeclHandler = handler;
   1907   1.1      tron }
   1908   1.1      tron 
   1909   1.1      tron void XMLCALL
   1910   1.1      tron XML_SetNamespaceDeclHandler(XML_Parser parser,
   1911   1.1      tron                             XML_StartNamespaceDeclHandler start,
   1912   1.8      maya                             XML_EndNamespaceDeclHandler end) {
   1913   1.7  christos   if (parser == NULL)
   1914   1.7  christos     return;
   1915   1.8      maya   parser->m_startNamespaceDeclHandler = start;
   1916   1.8      maya   parser->m_endNamespaceDeclHandler = end;
   1917   1.1      tron }
   1918   1.1      tron 
   1919   1.1      tron void XMLCALL
   1920   1.1      tron XML_SetStartNamespaceDeclHandler(XML_Parser parser,
   1921   1.1      tron                                  XML_StartNamespaceDeclHandler start) {
   1922   1.7  christos   if (parser != NULL)
   1923   1.8      maya     parser->m_startNamespaceDeclHandler = start;
   1924   1.1      tron }
   1925   1.1      tron 
   1926   1.1      tron void XMLCALL
   1927   1.1      tron XML_SetEndNamespaceDeclHandler(XML_Parser parser,
   1928   1.1      tron                                XML_EndNamespaceDeclHandler end) {
   1929   1.7  christos   if (parser != NULL)
   1930   1.8      maya     parser->m_endNamespaceDeclHandler = end;
   1931   1.1      tron }
   1932   1.1      tron 
   1933   1.1      tron void XMLCALL
   1934   1.1      tron XML_SetNotStandaloneHandler(XML_Parser parser,
   1935   1.8      maya                             XML_NotStandaloneHandler handler) {
   1936   1.7  christos   if (parser != NULL)
   1937   1.8      maya     parser->m_notStandaloneHandler = handler;
   1938   1.1      tron }
   1939   1.1      tron 
   1940   1.1      tron void XMLCALL
   1941   1.1      tron XML_SetExternalEntityRefHandler(XML_Parser parser,
   1942   1.8      maya                                 XML_ExternalEntityRefHandler handler) {
   1943   1.7  christos   if (parser != NULL)
   1944   1.8      maya     parser->m_externalEntityRefHandler = handler;
   1945   1.1      tron }
   1946   1.1      tron 
   1947   1.1      tron void XMLCALL
   1948   1.8      maya XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) {
   1949   1.7  christos   if (parser == NULL)
   1950   1.7  christos     return;
   1951   1.1      tron   if (arg)
   1952   1.8      maya     parser->m_externalEntityRefHandlerArg = (XML_Parser)arg;
   1953   1.1      tron   else
   1954   1.8      maya     parser->m_externalEntityRefHandlerArg = parser;
   1955   1.1      tron }
   1956   1.1      tron 
   1957   1.1      tron void XMLCALL
   1958   1.1      tron XML_SetSkippedEntityHandler(XML_Parser parser,
   1959   1.8      maya                             XML_SkippedEntityHandler handler) {
   1960   1.7  christos   if (parser != NULL)
   1961   1.8      maya     parser->m_skippedEntityHandler = handler;
   1962   1.1      tron }
   1963   1.1      tron 
   1964   1.1      tron void XMLCALL
   1965   1.1      tron XML_SetUnknownEncodingHandler(XML_Parser parser,
   1966   1.8      maya                               XML_UnknownEncodingHandler handler, void *data) {
   1967   1.7  christos   if (parser == NULL)
   1968   1.7  christos     return;
   1969   1.8      maya   parser->m_unknownEncodingHandler = handler;
   1970   1.8      maya   parser->m_unknownEncodingHandlerData = data;
   1971   1.1      tron }
   1972   1.1      tron 
   1973   1.1      tron void XMLCALL
   1974   1.8      maya XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) {
   1975   1.7  christos   if (parser != NULL)
   1976   1.8      maya     parser->m_elementDeclHandler = eldecl;
   1977   1.1      tron }
   1978   1.1      tron 
   1979   1.1      tron void XMLCALL
   1980   1.8      maya XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) {
   1981   1.7  christos   if (parser != NULL)
   1982   1.8      maya     parser->m_attlistDeclHandler = attdecl;
   1983   1.1      tron }
   1984   1.1      tron 
   1985   1.1      tron void XMLCALL
   1986   1.8      maya XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) {
   1987   1.7  christos   if (parser != NULL)
   1988   1.8      maya     parser->m_entityDeclHandler = handler;
   1989   1.1      tron }
   1990   1.1      tron 
   1991   1.1      tron void XMLCALL
   1992   1.8      maya XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) {
   1993   1.7  christos   if (parser != NULL)
   1994   1.8      maya     parser->m_xmlDeclHandler = handler;
   1995   1.1      tron }
   1996   1.1      tron 
   1997   1.1      tron int XMLCALL
   1998   1.1      tron XML_SetParamEntityParsing(XML_Parser parser,
   1999   1.8      maya                           enum XML_ParamEntityParsing peParsing) {
   2000   1.7  christos   if (parser == NULL)
   2001   1.7  christos     return 0;
   2002   1.1      tron   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   2003  1.10       wiz   if (parserBusy(parser))
   2004   1.1      tron     return 0;
   2005   1.1      tron #ifdef XML_DTD
   2006   1.8      maya   parser->m_paramEntityParsing = peParsing;
   2007   1.1      tron   return 1;
   2008   1.1      tron #else
   2009   1.1      tron   return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
   2010   1.1      tron #endif
   2011   1.1      tron }
   2012   1.1      tron 
   2013   1.3       spz int XMLCALL
   2014   1.8      maya XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
   2015   1.7  christos   if (parser == NULL)
   2016   1.7  christos     return 0;
   2017   1.7  christos   if (parser->m_parentParser)
   2018   1.7  christos     return XML_SetHashSalt(parser->m_parentParser, hash_salt);
   2019   1.3       spz   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   2020  1.10       wiz   if (parserBusy(parser))
   2021   1.3       spz     return 0;
   2022   1.8      maya   parser->m_hash_secret_salt = hash_salt;
   2023   1.3       spz   return 1;
   2024   1.3       spz }
   2025   1.3       spz 
   2026   1.1      tron enum XML_Status XMLCALL
   2027   1.8      maya XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
   2028   1.7  christos   if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
   2029   1.8      maya     if (parser != NULL)
   2030   1.8      maya       parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
   2031   1.7  christos     return XML_STATUS_ERROR;
   2032   1.7  christos   }
   2033   1.8      maya   switch (parser->m_parsingStatus.parsing) {
   2034   1.1      tron   case XML_SUSPENDED:
   2035   1.8      maya     parser->m_errorCode = XML_ERROR_SUSPENDED;
   2036   1.1      tron     return XML_STATUS_ERROR;
   2037   1.1      tron   case XML_FINISHED:
   2038   1.8      maya     parser->m_errorCode = XML_ERROR_FINISHED;
   2039   1.1      tron     return XML_STATUS_ERROR;
   2040   1.3       spz   case XML_INITIALIZED:
   2041   1.8      maya     if (parser->m_parentParser == NULL && ! startParsing(parser)) {
   2042   1.8      maya       parser->m_errorCode = XML_ERROR_NO_MEMORY;
   2043   1.3       spz       return XML_STATUS_ERROR;
   2044   1.3       spz     }
   2045   1.8      maya     /* fall through */
   2046   1.1      tron   default:
   2047   1.8      maya     parser->m_parsingStatus.parsing = XML_PARSING;
   2048   1.1      tron   }
   2049   1.1      tron 
   2050  1.10       wiz #if XML_CONTEXT_BYTES == 0
   2051  1.10       wiz   if (parser->m_bufferPtr == parser->m_bufferEnd) {
   2052   1.1      tron     const char *end;
   2053   1.1      tron     int nLeftOver;
   2054   1.4       spz     enum XML_Status result;
   2055   1.7  christos     /* Detect overflow (a+b > MAX <==> b > MAX-a) */
   2056   1.9  christos     if ((XML_Size)len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) {
   2057   1.8      maya       parser->m_errorCode = XML_ERROR_NO_MEMORY;
   2058   1.8      maya       parser->m_eventPtr = parser->m_eventEndPtr = NULL;
   2059   1.8      maya       parser->m_processor = errorProcessor;
   2060   1.1      tron       return XML_STATUS_ERROR;
   2061   1.1      tron     }
   2062  1.10       wiz     // though this isn't a buffer request, we assume that `len` is the app's
   2063  1.10       wiz     // preferred buffer fill size, and therefore save it here.
   2064  1.10       wiz     parser->m_lastBufferRequestSize = len;
   2065   1.8      maya     parser->m_parseEndByteIndex += len;
   2066   1.8      maya     parser->m_positionPtr = s;
   2067   1.8      maya     parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
   2068   1.8      maya 
   2069   1.8      maya     parser->m_errorCode
   2070  1.10       wiz         = callProcessor(parser, s, parser->m_parseEndPtr = s + len, &end);
   2071   1.8      maya 
   2072   1.8      maya     if (parser->m_errorCode != XML_ERROR_NONE) {
   2073   1.8      maya       parser->m_eventEndPtr = parser->m_eventPtr;
   2074   1.8      maya       parser->m_processor = errorProcessor;
   2075   1.8      maya       return XML_STATUS_ERROR;
   2076   1.8      maya     } else {
   2077   1.8      maya       switch (parser->m_parsingStatus.parsing) {
   2078   1.1      tron       case XML_SUSPENDED:
   2079   1.1      tron         result = XML_STATUS_SUSPENDED;
   2080   1.1      tron         break;
   2081   1.1      tron       case XML_INITIALIZED:
   2082   1.1      tron       case XML_PARSING:
   2083   1.1      tron         if (isFinal) {
   2084   1.8      maya           parser->m_parsingStatus.parsing = XML_FINISHED;
   2085   1.3       spz           return XML_STATUS_OK;
   2086   1.1      tron         }
   2087   1.3       spz       /* fall through */
   2088   1.3       spz       default:
   2089   1.3       spz         result = XML_STATUS_OK;
   2090   1.1      tron       }
   2091   1.1      tron     }
   2092   1.1      tron 
   2093   1.8      maya     XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end,
   2094   1.8      maya                       &parser->m_position);
   2095   1.1      tron     nLeftOver = s + len - end;
   2096   1.1      tron     if (nLeftOver) {
   2097  1.10       wiz       // Back up and restore the parsing status to avoid XML_ERROR_SUSPENDED
   2098  1.10       wiz       // (and XML_ERROR_FINISHED) from XML_GetBuffer.
   2099  1.10       wiz       const enum XML_Parsing originalStatus = parser->m_parsingStatus.parsing;
   2100  1.10       wiz       parser->m_parsingStatus.parsing = XML_PARSING;
   2101  1.10       wiz       void *const temp = XML_GetBuffer(parser, nLeftOver);
   2102  1.10       wiz       parser->m_parsingStatus.parsing = originalStatus;
   2103  1.10       wiz       // GetBuffer may have overwritten this, but we want to remember what the
   2104  1.10       wiz       // app requested, not how many bytes were left over after parsing.
   2105  1.10       wiz       parser->m_lastBufferRequestSize = len;
   2106  1.10       wiz       if (temp == NULL) {
   2107  1.10       wiz         // NOTE: parser->m_errorCode has already been set by XML_GetBuffer().
   2108  1.10       wiz         parser->m_eventPtr = parser->m_eventEndPtr = NULL;
   2109  1.10       wiz         parser->m_processor = errorProcessor;
   2110  1.10       wiz         return XML_STATUS_ERROR;
   2111   1.1      tron       }
   2112  1.10       wiz       // Since we know that the buffer was empty and XML_CONTEXT_BYTES is 0, we
   2113  1.10       wiz       // don't have any data to preserve, and can copy straight into the start
   2114  1.10       wiz       // of the buffer rather than the GetBuffer return pointer (which may be
   2115  1.10       wiz       // pointing further into the allocated buffer).
   2116   1.8      maya       memcpy(parser->m_buffer, end, nLeftOver);
   2117   1.1      tron     }
   2118   1.8      maya     parser->m_bufferPtr = parser->m_buffer;
   2119   1.8      maya     parser->m_bufferEnd = parser->m_buffer + nLeftOver;
   2120   1.8      maya     parser->m_positionPtr = parser->m_bufferPtr;
   2121   1.8      maya     parser->m_parseEndPtr = parser->m_bufferEnd;
   2122   1.8      maya     parser->m_eventPtr = parser->m_bufferPtr;
   2123   1.8      maya     parser->m_eventEndPtr = parser->m_bufferPtr;
   2124   1.1      tron     return result;
   2125   1.1      tron   }
   2126  1.10       wiz #endif /* XML_CONTEXT_BYTES == 0 */
   2127  1.10       wiz   void *buff = XML_GetBuffer(parser, len);
   2128  1.10       wiz   if (buff == NULL)
   2129  1.10       wiz     return XML_STATUS_ERROR;
   2130  1.10       wiz   if (len > 0) {
   2131  1.10       wiz     assert(s != NULL); // make sure s==NULL && len!=0 was rejected above
   2132  1.10       wiz     memcpy(buff, s, len);
   2133   1.1      tron   }
   2134  1.10       wiz   return XML_ParseBuffer(parser, len, isFinal);
   2135   1.1      tron }
   2136   1.1      tron 
   2137   1.1      tron enum XML_Status XMLCALL
   2138   1.8      maya XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
   2139   1.1      tron   const char *start;
   2140   1.1      tron   enum XML_Status result = XML_STATUS_OK;
   2141   1.1      tron 
   2142   1.7  christos   if (parser == NULL)
   2143   1.7  christos     return XML_STATUS_ERROR;
   2144  1.10       wiz 
   2145  1.10       wiz   if (len < 0) {
   2146  1.10       wiz     parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
   2147  1.10       wiz     return XML_STATUS_ERROR;
   2148  1.10       wiz   }
   2149  1.10       wiz 
   2150   1.8      maya   switch (parser->m_parsingStatus.parsing) {
   2151   1.1      tron   case XML_SUSPENDED:
   2152   1.8      maya     parser->m_errorCode = XML_ERROR_SUSPENDED;
   2153   1.1      tron     return XML_STATUS_ERROR;
   2154   1.1      tron   case XML_FINISHED:
   2155   1.8      maya     parser->m_errorCode = XML_ERROR_FINISHED;
   2156   1.1      tron     return XML_STATUS_ERROR;
   2157   1.3       spz   case XML_INITIALIZED:
   2158   1.9  christos     /* Has someone called XML_GetBuffer successfully before? */
   2159   1.9  christos     if (! parser->m_bufferPtr) {
   2160   1.9  christos       parser->m_errorCode = XML_ERROR_NO_BUFFER;
   2161   1.9  christos       return XML_STATUS_ERROR;
   2162   1.9  christos     }
   2163   1.9  christos 
   2164   1.8      maya     if (parser->m_parentParser == NULL && ! startParsing(parser)) {
   2165   1.8      maya       parser->m_errorCode = XML_ERROR_NO_MEMORY;
   2166   1.3       spz       return XML_STATUS_ERROR;
   2167   1.3       spz     }
   2168   1.8      maya     /* fall through */
   2169   1.1      tron   default:
   2170   1.8      maya     parser->m_parsingStatus.parsing = XML_PARSING;
   2171   1.1      tron   }
   2172   1.1      tron 
   2173   1.8      maya   start = parser->m_bufferPtr;
   2174   1.8      maya   parser->m_positionPtr = start;
   2175   1.8      maya   parser->m_bufferEnd += len;
   2176   1.8      maya   parser->m_parseEndPtr = parser->m_bufferEnd;
   2177   1.8      maya   parser->m_parseEndByteIndex += len;
   2178   1.8      maya   parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
   2179   1.8      maya 
   2180  1.10       wiz   parser->m_errorCode = callProcessor(parser, start, parser->m_parseEndPtr,
   2181  1.10       wiz                                       &parser->m_bufferPtr);
   2182   1.8      maya 
   2183   1.8      maya   if (parser->m_errorCode != XML_ERROR_NONE) {
   2184   1.8      maya     parser->m_eventEndPtr = parser->m_eventPtr;
   2185   1.8      maya     parser->m_processor = errorProcessor;
   2186   1.1      tron     return XML_STATUS_ERROR;
   2187   1.8      maya   } else {
   2188   1.8      maya     switch (parser->m_parsingStatus.parsing) {
   2189   1.1      tron     case XML_SUSPENDED:
   2190   1.1      tron       result = XML_STATUS_SUSPENDED;
   2191   1.1      tron       break;
   2192   1.3       spz     case XML_INITIALIZED:
   2193   1.1      tron     case XML_PARSING:
   2194   1.1      tron       if (isFinal) {
   2195   1.8      maya         parser->m_parsingStatus.parsing = XML_FINISHED;
   2196   1.1      tron         return result;
   2197   1.1      tron       }
   2198   1.8      maya     default:; /* should not happen */
   2199   1.1      tron     }
   2200   1.1      tron   }
   2201   1.1      tron 
   2202   1.8      maya   XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
   2203   1.8      maya                     parser->m_bufferPtr, &parser->m_position);
   2204   1.8      maya   parser->m_positionPtr = parser->m_bufferPtr;
   2205   1.1      tron   return result;
   2206   1.1      tron }
   2207   1.1      tron 
   2208   1.8      maya void *XMLCALL
   2209   1.8      maya XML_GetBuffer(XML_Parser parser, int len) {
   2210   1.7  christos   if (parser == NULL)
   2211   1.7  christos     return NULL;
   2212   1.4       spz   if (len < 0) {
   2213   1.8      maya     parser->m_errorCode = XML_ERROR_NO_MEMORY;
   2214   1.4       spz     return NULL;
   2215   1.4       spz   }
   2216   1.8      maya   switch (parser->m_parsingStatus.parsing) {
   2217   1.1      tron   case XML_SUSPENDED:
   2218   1.8      maya     parser->m_errorCode = XML_ERROR_SUSPENDED;
   2219   1.1      tron     return NULL;
   2220   1.1      tron   case XML_FINISHED:
   2221   1.8      maya     parser->m_errorCode = XML_ERROR_FINISHED;
   2222   1.1      tron     return NULL;
   2223   1.8      maya   default:;
   2224   1.1      tron   }
   2225   1.1      tron 
   2226  1.10       wiz   // whether or not the request succeeds, `len` seems to be the app's preferred
   2227  1.10       wiz   // buffer fill size; remember it.
   2228  1.10       wiz   parser->m_lastBufferRequestSize = len;
   2229  1.10       wiz   if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)
   2230  1.10       wiz       || parser->m_buffer == NULL) {
   2231  1.10       wiz #if XML_CONTEXT_BYTES > 0
   2232   1.6       spz     int keep;
   2233  1.10       wiz #endif /* XML_CONTEXT_BYTES > 0 */
   2234   1.5       spz     /* Do not invoke signed arithmetic overflow: */
   2235   1.8      maya     int neededSize = (int)((unsigned)len
   2236   1.8      maya                            + (unsigned)EXPAT_SAFE_PTR_DIFF(
   2237   1.8      maya                                parser->m_bufferEnd, parser->m_bufferPtr));
   2238   1.4       spz     if (neededSize < 0) {
   2239   1.8      maya       parser->m_errorCode = XML_ERROR_NO_MEMORY;
   2240   1.4       spz       return NULL;
   2241   1.4       spz     }
   2242  1.10       wiz #if XML_CONTEXT_BYTES > 0
   2243   1.8      maya     keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
   2244   1.1      tron     if (keep > XML_CONTEXT_BYTES)
   2245   1.1      tron       keep = XML_CONTEXT_BYTES;
   2246   1.9  christos     /* Detect and prevent integer overflow */
   2247   1.9  christos     if (keep > INT_MAX - neededSize) {
   2248   1.9  christos       parser->m_errorCode = XML_ERROR_NO_MEMORY;
   2249   1.9  christos       return NULL;
   2250   1.9  christos     }
   2251   1.1      tron     neededSize += keep;
   2252  1.10       wiz #endif /* XML_CONTEXT_BYTES > 0 */
   2253  1.10       wiz     if (parser->m_buffer && parser->m_bufferPtr
   2254  1.10       wiz         && neededSize
   2255  1.10       wiz                <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) {
   2256  1.10       wiz #if XML_CONTEXT_BYTES > 0
   2257   1.8      maya       if (keep < EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)) {
   2258   1.8      maya         int offset
   2259   1.8      maya             = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)
   2260   1.8      maya               - keep;
   2261   1.8      maya         /* The buffer pointers cannot be NULL here; we have at least some bytes
   2262   1.8      maya          * in the buffer */
   2263   1.8      maya         memmove(parser->m_buffer, &parser->m_buffer[offset],
   2264   1.8      maya                 parser->m_bufferEnd - parser->m_bufferPtr + keep);
   2265   1.8      maya         parser->m_bufferEnd -= offset;
   2266   1.8      maya         parser->m_bufferPtr -= offset;
   2267   1.1      tron       }
   2268   1.1      tron #else
   2269  1.10       wiz       memmove(parser->m_buffer, parser->m_bufferPtr,
   2270  1.10       wiz               EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
   2271  1.10       wiz       parser->m_bufferEnd
   2272  1.10       wiz           = parser->m_buffer
   2273  1.10       wiz             + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
   2274  1.10       wiz       parser->m_bufferPtr = parser->m_buffer;
   2275  1.10       wiz #endif /* XML_CONTEXT_BYTES > 0 */
   2276   1.8      maya     } else {
   2277   1.1      tron       char *newBuf;
   2278   1.8      maya       int bufferSize
   2279  1.10       wiz           = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer);
   2280   1.1      tron       if (bufferSize == 0)
   2281   1.1      tron         bufferSize = INIT_BUFFER_SIZE;
   2282   1.1      tron       do {
   2283   1.5       spz         /* Do not invoke signed arithmetic overflow: */
   2284   1.8      maya         bufferSize = (int)(2U * (unsigned)bufferSize);
   2285   1.4       spz       } while (bufferSize < neededSize && bufferSize > 0);
   2286   1.4       spz       if (bufferSize <= 0) {
   2287   1.8      maya         parser->m_errorCode = XML_ERROR_NO_MEMORY;
   2288   1.4       spz         return NULL;
   2289   1.4       spz       }
   2290   1.8      maya       newBuf = (char *)MALLOC(parser, bufferSize);
   2291   1.1      tron       if (newBuf == 0) {
   2292   1.8      maya         parser->m_errorCode = XML_ERROR_NO_MEMORY;
   2293   1.1      tron         return NULL;
   2294   1.1      tron       }
   2295   1.8      maya       parser->m_bufferLim = newBuf + bufferSize;
   2296  1.10       wiz #if XML_CONTEXT_BYTES > 0
   2297   1.8      maya       if (parser->m_bufferPtr) {
   2298   1.8      maya         memcpy(newBuf, &parser->m_bufferPtr[-keep],
   2299   1.8      maya                EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
   2300   1.8      maya                    + keep);
   2301   1.8      maya         FREE(parser, parser->m_buffer);
   2302   1.8      maya         parser->m_buffer = newBuf;
   2303   1.8      maya         parser->m_bufferEnd
   2304   1.8      maya             = parser->m_buffer
   2305   1.8      maya               + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
   2306   1.8      maya               + keep;
   2307   1.8      maya         parser->m_bufferPtr = parser->m_buffer + keep;
   2308   1.8      maya       } else {
   2309   1.8      maya         /* This must be a brand new buffer with no data in it yet */
   2310   1.8      maya         parser->m_bufferEnd = newBuf;
   2311   1.8      maya         parser->m_bufferPtr = parser->m_buffer = newBuf;
   2312   1.1      tron       }
   2313   1.8      maya #else
   2314   1.8      maya       if (parser->m_bufferPtr) {
   2315   1.8      maya         memcpy(newBuf, parser->m_bufferPtr,
   2316   1.8      maya                EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
   2317   1.8      maya         FREE(parser, parser->m_buffer);
   2318   1.8      maya         parser->m_bufferEnd
   2319   1.8      maya             = newBuf
   2320   1.8      maya               + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
   2321   1.8      maya       } else {
   2322   1.8      maya         /* This must be a brand new buffer with no data in it yet */
   2323   1.8      maya         parser->m_bufferEnd = newBuf;
   2324   1.1      tron       }
   2325   1.8      maya       parser->m_bufferPtr = parser->m_buffer = newBuf;
   2326  1.10       wiz #endif /* XML_CONTEXT_BYTES > 0 */
   2327   1.1      tron     }
   2328   1.8      maya     parser->m_eventPtr = parser->m_eventEndPtr = NULL;
   2329   1.8      maya     parser->m_positionPtr = NULL;
   2330   1.1      tron   }
   2331   1.8      maya   return parser->m_bufferEnd;
   2332   1.1      tron }
   2333   1.1      tron 
   2334  1.10       wiz static void
   2335  1.10       wiz triggerReenter(XML_Parser parser) {
   2336  1.10       wiz   parser->m_reenter = XML_TRUE;
   2337  1.10       wiz }
   2338  1.10       wiz 
   2339   1.1      tron enum XML_Status XMLCALL
   2340   1.8      maya XML_StopParser(XML_Parser parser, XML_Bool resumable) {
   2341   1.7  christos   if (parser == NULL)
   2342   1.7  christos     return XML_STATUS_ERROR;
   2343   1.8      maya   switch (parser->m_parsingStatus.parsing) {
   2344  1.10       wiz   case XML_INITIALIZED:
   2345  1.10       wiz     parser->m_errorCode = XML_ERROR_NOT_STARTED;
   2346  1.10       wiz     return XML_STATUS_ERROR;
   2347   1.1      tron   case XML_SUSPENDED:
   2348   1.1      tron     if (resumable) {
   2349   1.8      maya       parser->m_errorCode = XML_ERROR_SUSPENDED;
   2350   1.1      tron       return XML_STATUS_ERROR;
   2351   1.1      tron     }
   2352   1.8      maya     parser->m_parsingStatus.parsing = XML_FINISHED;
   2353   1.1      tron     break;
   2354   1.1      tron   case XML_FINISHED:
   2355   1.8      maya     parser->m_errorCode = XML_ERROR_FINISHED;
   2356   1.1      tron     return XML_STATUS_ERROR;
   2357  1.10       wiz   case XML_PARSING:
   2358   1.1      tron     if (resumable) {
   2359   1.1      tron #ifdef XML_DTD
   2360   1.8      maya       if (parser->m_isParamEntity) {
   2361   1.8      maya         parser->m_errorCode = XML_ERROR_SUSPEND_PE;
   2362   1.1      tron         return XML_STATUS_ERROR;
   2363   1.1      tron       }
   2364   1.1      tron #endif
   2365   1.8      maya       parser->m_parsingStatus.parsing = XML_SUSPENDED;
   2366   1.8      maya     } else
   2367   1.8      maya       parser->m_parsingStatus.parsing = XML_FINISHED;
   2368  1.10       wiz     break;
   2369  1.10       wiz   default:
   2370  1.10       wiz     assert(0);
   2371   1.1      tron   }
   2372   1.1      tron   return XML_STATUS_OK;
   2373   1.1      tron }
   2374   1.1      tron 
   2375   1.1      tron enum XML_Status XMLCALL
   2376   1.8      maya XML_ResumeParser(XML_Parser parser) {
   2377   1.1      tron   enum XML_Status result = XML_STATUS_OK;
   2378   1.1      tron 
   2379   1.7  christos   if (parser == NULL)
   2380   1.7  christos     return XML_STATUS_ERROR;
   2381   1.8      maya   if (parser->m_parsingStatus.parsing != XML_SUSPENDED) {
   2382   1.8      maya     parser->m_errorCode = XML_ERROR_NOT_SUSPENDED;
   2383   1.1      tron     return XML_STATUS_ERROR;
   2384   1.1      tron   }
   2385   1.8      maya   parser->m_parsingStatus.parsing = XML_PARSING;
   2386   1.1      tron 
   2387  1.10       wiz   parser->m_errorCode = callProcessor(
   2388   1.8      maya       parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr);
   2389   1.1      tron 
   2390   1.8      maya   if (parser->m_errorCode != XML_ERROR_NONE) {
   2391   1.8      maya     parser->m_eventEndPtr = parser->m_eventPtr;
   2392   1.8      maya     parser->m_processor = errorProcessor;
   2393   1.1      tron     return XML_STATUS_ERROR;
   2394   1.8      maya   } else {
   2395   1.8      maya     switch (parser->m_parsingStatus.parsing) {
   2396   1.1      tron     case XML_SUSPENDED:
   2397   1.1      tron       result = XML_STATUS_SUSPENDED;
   2398   1.1      tron       break;
   2399   1.3       spz     case XML_INITIALIZED:
   2400   1.1      tron     case XML_PARSING:
   2401   1.8      maya       if (parser->m_parsingStatus.finalBuffer) {
   2402   1.8      maya         parser->m_parsingStatus.parsing = XML_FINISHED;
   2403   1.1      tron         return result;
   2404   1.1      tron       }
   2405   1.8      maya     default:;
   2406   1.1      tron     }
   2407   1.1      tron   }
   2408   1.1      tron 
   2409   1.8      maya   XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
   2410   1.8      maya                     parser->m_bufferPtr, &parser->m_position);
   2411   1.8      maya   parser->m_positionPtr = parser->m_bufferPtr;
   2412   1.1      tron   return result;
   2413   1.1      tron }
   2414   1.1      tron 
   2415   1.1      tron void XMLCALL
   2416   1.8      maya XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) {
   2417   1.7  christos   if (parser == NULL)
   2418   1.7  christos     return;
   2419   1.1      tron   assert(status != NULL);
   2420   1.1      tron   *status = parser->m_parsingStatus;
   2421   1.1      tron }
   2422   1.1      tron 
   2423   1.1      tron enum XML_Error XMLCALL
   2424   1.8      maya XML_GetErrorCode(XML_Parser parser) {
   2425   1.7  christos   if (parser == NULL)
   2426   1.7  christos     return XML_ERROR_INVALID_ARGUMENT;
   2427   1.8      maya   return parser->m_errorCode;
   2428   1.1      tron }
   2429   1.1      tron 
   2430   1.1      tron XML_Index XMLCALL
   2431   1.8      maya XML_GetCurrentByteIndex(XML_Parser parser) {
   2432   1.7  christos   if (parser == NULL)
   2433   1.7  christos     return -1;
   2434   1.8      maya   if (parser->m_eventPtr)
   2435   1.8      maya     return (XML_Index)(parser->m_parseEndByteIndex
   2436   1.8      maya                        - (parser->m_parseEndPtr - parser->m_eventPtr));
   2437   1.1      tron   return -1;
   2438   1.1      tron }
   2439   1.1      tron 
   2440   1.1      tron int XMLCALL
   2441   1.8      maya XML_GetCurrentByteCount(XML_Parser parser) {
   2442   1.7  christos   if (parser == NULL)
   2443   1.7  christos     return 0;
   2444   1.8      maya   if (parser->m_eventEndPtr && parser->m_eventPtr)
   2445   1.8      maya     return (int)(parser->m_eventEndPtr - parser->m_eventPtr);
   2446   1.1      tron   return 0;
   2447   1.1      tron }
   2448   1.1      tron 
   2449   1.8      maya const char *XMLCALL
   2450   1.8      maya XML_GetInputContext(XML_Parser parser, int *offset, int *size) {
   2451  1.10       wiz #if XML_CONTEXT_BYTES > 0
   2452   1.7  christos   if (parser == NULL)
   2453   1.7  christos     return NULL;
   2454   1.8      maya   if (parser->m_eventPtr && parser->m_buffer) {
   2455   1.7  christos     if (offset != NULL)
   2456   1.8      maya       *offset = (int)(parser->m_eventPtr - parser->m_buffer);
   2457   1.7  christos     if (size != NULL)
   2458   1.8      maya       *size = (int)(parser->m_bufferEnd - parser->m_buffer);
   2459   1.8      maya     return parser->m_buffer;
   2460   1.1      tron   }
   2461   1.7  christos #else
   2462   1.7  christos   (void)parser;
   2463   1.7  christos   (void)offset;
   2464   1.7  christos   (void)size;
   2465  1.10       wiz #endif /* XML_CONTEXT_BYTES > 0 */
   2466   1.9  christos   return (const char *)0;
   2467   1.1      tron }
   2468   1.1      tron 
   2469   1.1      tron XML_Size XMLCALL
   2470   1.8      maya XML_GetCurrentLineNumber(XML_Parser parser) {
   2471   1.7  christos   if (parser == NULL)
   2472   1.7  christos     return 0;
   2473   1.8      maya   if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
   2474   1.8      maya     XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
   2475   1.8      maya                       parser->m_eventPtr, &parser->m_position);
   2476   1.8      maya     parser->m_positionPtr = parser->m_eventPtr;
   2477   1.1      tron   }
   2478   1.8      maya   return parser->m_position.lineNumber + 1;
   2479   1.1      tron }
   2480   1.1      tron 
   2481   1.1      tron XML_Size XMLCALL
   2482   1.8      maya XML_GetCurrentColumnNumber(XML_Parser parser) {
   2483   1.7  christos   if (parser == NULL)
   2484   1.7  christos     return 0;
   2485   1.8      maya   if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
   2486   1.8      maya     XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
   2487   1.8      maya                       parser->m_eventPtr, &parser->m_position);
   2488   1.8      maya     parser->m_positionPtr = parser->m_eventPtr;
   2489   1.1      tron   }
   2490   1.8      maya   return parser->m_position.columnNumber;
   2491   1.1      tron }
   2492   1.1      tron 
   2493   1.1      tron void XMLCALL
   2494   1.8      maya XML_FreeContentModel(XML_Parser parser, XML_Content *model) {
   2495   1.7  christos   if (parser != NULL)
   2496   1.8      maya     FREE(parser, model);
   2497   1.1      tron }
   2498   1.1      tron 
   2499   1.8      maya void *XMLCALL
   2500   1.8      maya XML_MemMalloc(XML_Parser parser, size_t size) {
   2501   1.7  christos   if (parser == NULL)
   2502   1.7  christos     return NULL;
   2503   1.8      maya   return MALLOC(parser, size);
   2504   1.1      tron }
   2505   1.1      tron 
   2506   1.8      maya void *XMLCALL
   2507   1.8      maya XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) {
   2508   1.7  christos   if (parser == NULL)
   2509   1.7  christos     return NULL;
   2510   1.8      maya   return REALLOC(parser, ptr, size);
   2511   1.1      tron }
   2512   1.1      tron 
   2513   1.1      tron void XMLCALL
   2514   1.8      maya XML_MemFree(XML_Parser parser, void *ptr) {
   2515   1.7  christos   if (parser != NULL)
   2516   1.8      maya     FREE(parser, ptr);
   2517   1.1      tron }
   2518   1.1      tron 
   2519   1.1      tron void XMLCALL
   2520   1.8      maya XML_DefaultCurrent(XML_Parser parser) {
   2521   1.7  christos   if (parser == NULL)
   2522   1.7  christos     return;
   2523   1.8      maya   if (parser->m_defaultHandler) {
   2524   1.8      maya     if (parser->m_openInternalEntities)
   2525   1.8      maya       reportDefault(parser, parser->m_internalEncoding,
   2526   1.8      maya                     parser->m_openInternalEntities->internalEventPtr,
   2527   1.8      maya                     parser->m_openInternalEntities->internalEventEndPtr);
   2528   1.1      tron     else
   2529   1.8      maya       reportDefault(parser, parser->m_encoding, parser->m_eventPtr,
   2530   1.8      maya                     parser->m_eventEndPtr);
   2531   1.1      tron   }
   2532   1.1      tron }
   2533   1.1      tron 
   2534   1.8      maya const XML_LChar *XMLCALL
   2535   1.8      maya XML_ErrorString(enum XML_Error code) {
   2536   1.8      maya   switch (code) {
   2537   1.8      maya   case XML_ERROR_NONE:
   2538   1.8      maya     return NULL;
   2539   1.8      maya   case XML_ERROR_NO_MEMORY:
   2540   1.8      maya     return XML_L("out of memory");
   2541   1.8      maya   case XML_ERROR_SYNTAX:
   2542   1.8      maya     return XML_L("syntax error");
   2543   1.8      maya   case XML_ERROR_NO_ELEMENTS:
   2544   1.8      maya     return XML_L("no element found");
   2545   1.8      maya   case XML_ERROR_INVALID_TOKEN:
   2546   1.8      maya     return XML_L("not well-formed (invalid token)");
   2547   1.8      maya   case XML_ERROR_UNCLOSED_TOKEN:
   2548   1.8      maya     return XML_L("unclosed token");
   2549   1.8      maya   case XML_ERROR_PARTIAL_CHAR:
   2550   1.8      maya     return XML_L("partial character");
   2551   1.8      maya   case XML_ERROR_TAG_MISMATCH:
   2552   1.8      maya     return XML_L("mismatched tag");
   2553   1.8      maya   case XML_ERROR_DUPLICATE_ATTRIBUTE:
   2554   1.8      maya     return XML_L("duplicate attribute");
   2555   1.8      maya   case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
   2556   1.8      maya     return XML_L("junk after document element");
   2557   1.8      maya   case XML_ERROR_PARAM_ENTITY_REF:
   2558   1.8      maya     return XML_L("illegal parameter entity reference");
   2559   1.8      maya   case XML_ERROR_UNDEFINED_ENTITY:
   2560   1.8      maya     return XML_L("undefined entity");
   2561   1.8      maya   case XML_ERROR_RECURSIVE_ENTITY_REF:
   2562   1.8      maya     return XML_L("recursive entity reference");
   2563   1.8      maya   case XML_ERROR_ASYNC_ENTITY:
   2564   1.8      maya     return XML_L("asynchronous entity");
   2565   1.8      maya   case XML_ERROR_BAD_CHAR_REF:
   2566   1.8      maya     return XML_L("reference to invalid character number");
   2567   1.8      maya   case XML_ERROR_BINARY_ENTITY_REF:
   2568   1.8      maya     return XML_L("reference to binary entity");
   2569   1.8      maya   case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
   2570   1.8      maya     return XML_L("reference to external entity in attribute");
   2571   1.8      maya   case XML_ERROR_MISPLACED_XML_PI:
   2572   1.8      maya     return XML_L("XML or text declaration not at start of entity");
   2573   1.8      maya   case XML_ERROR_UNKNOWN_ENCODING:
   2574   1.8      maya     return XML_L("unknown encoding");
   2575   1.8      maya   case XML_ERROR_INCORRECT_ENCODING:
   2576   1.8      maya     return XML_L("encoding specified in XML declaration is incorrect");
   2577   1.8      maya   case XML_ERROR_UNCLOSED_CDATA_SECTION:
   2578   1.8      maya     return XML_L("unclosed CDATA section");
   2579   1.8      maya   case XML_ERROR_EXTERNAL_ENTITY_HANDLING:
   2580   1.8      maya     return XML_L("error in processing external entity reference");
   2581   1.8      maya   case XML_ERROR_NOT_STANDALONE:
   2582   1.8      maya     return XML_L("document is not standalone");
   2583   1.8      maya   case XML_ERROR_UNEXPECTED_STATE:
   2584   1.8      maya     return XML_L("unexpected parser state - please send a bug report");
   2585   1.8      maya   case XML_ERROR_ENTITY_DECLARED_IN_PE:
   2586   1.8      maya     return XML_L("entity declared in parameter entity");
   2587   1.8      maya   case XML_ERROR_FEATURE_REQUIRES_XML_DTD:
   2588   1.8      maya     return XML_L("requested feature requires XML_DTD support in Expat");
   2589   1.8      maya   case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:
   2590   1.8      maya     return XML_L("cannot change setting once parsing has begun");
   2591   1.8      maya   /* Added in 1.95.7. */
   2592   1.8      maya   case XML_ERROR_UNBOUND_PREFIX:
   2593   1.8      maya     return XML_L("unbound prefix");
   2594   1.8      maya   /* Added in 1.95.8. */
   2595   1.8      maya   case XML_ERROR_UNDECLARING_PREFIX:
   2596   1.8      maya     return XML_L("must not undeclare prefix");
   2597   1.8      maya   case XML_ERROR_INCOMPLETE_PE:
   2598   1.8      maya     return XML_L("incomplete markup in parameter entity");
   2599   1.8      maya   case XML_ERROR_XML_DECL:
   2600   1.8      maya     return XML_L("XML declaration not well-formed");
   2601   1.8      maya   case XML_ERROR_TEXT_DECL:
   2602   1.8      maya     return XML_L("text declaration not well-formed");
   2603   1.8      maya   case XML_ERROR_PUBLICID:
   2604   1.8      maya     return XML_L("illegal character(s) in public id");
   2605   1.8      maya   case XML_ERROR_SUSPENDED:
   2606   1.8      maya     return XML_L("parser suspended");
   2607   1.8      maya   case XML_ERROR_NOT_SUSPENDED:
   2608   1.8      maya     return XML_L("parser not suspended");
   2609   1.8      maya   case XML_ERROR_ABORTED:
   2610   1.8      maya     return XML_L("parsing aborted");
   2611   1.8      maya   case XML_ERROR_FINISHED:
   2612   1.8      maya     return XML_L("parsing finished");
   2613   1.8      maya   case XML_ERROR_SUSPEND_PE:
   2614   1.8      maya     return XML_L("cannot suspend in external parameter entity");
   2615   1.8      maya   /* Added in 2.0.0. */
   2616   1.8      maya   case XML_ERROR_RESERVED_PREFIX_XML:
   2617   1.8      maya     return XML_L(
   2618   1.8      maya         "reserved prefix (xml) must not be undeclared or bound to another namespace name");
   2619   1.8      maya   case XML_ERROR_RESERVED_PREFIX_XMLNS:
   2620   1.8      maya     return XML_L("reserved prefix (xmlns) must not be declared or undeclared");
   2621   1.8      maya   case XML_ERROR_RESERVED_NAMESPACE_URI:
   2622   1.8      maya     return XML_L(
   2623   1.8      maya         "prefix must not be bound to one of the reserved namespace names");
   2624   1.8      maya   /* Added in 2.2.5. */
   2625   1.8      maya   case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
   2626   1.8      maya     return XML_L("invalid argument");
   2627   1.9  christos     /* Added in 2.3.0. */
   2628   1.9  christos   case XML_ERROR_NO_BUFFER:
   2629   1.9  christos     return XML_L(
   2630   1.9  christos         "a successful prior call to function XML_GetBuffer is required");
   2631   1.9  christos   /* Added in 2.4.0. */
   2632   1.9  christos   case XML_ERROR_AMPLIFICATION_LIMIT_BREACH:
   2633   1.9  christos     return XML_L(
   2634   1.9  christos         "limit on input amplification factor (from DTD and entities) breached");
   2635  1.10       wiz   /* Added in 2.6.4. */
   2636  1.10       wiz   case XML_ERROR_NOT_STARTED:
   2637  1.10       wiz     return XML_L("parser not started");
   2638   1.8      maya   }
   2639   1.1      tron   return NULL;
   2640   1.1      tron }
   2641   1.1      tron 
   2642   1.8      maya const XML_LChar *XMLCALL
   2643   1.1      tron XML_ExpatVersion(void) {
   2644   1.1      tron   /* V1 is used to string-ize the version number. However, it would
   2645   1.1      tron      string-ize the actual version macro *names* unless we get them
   2646   1.1      tron      substituted before being passed to V1. CPP is defined to expand
   2647   1.1      tron      a macro, then rescan for more expansions. Thus, we use V2 to expand
   2648   1.1      tron      the version macros, then CPP will expand the resulting V1() macro
   2649   1.1      tron      with the correct numerals. */
   2650   1.1      tron   /* ### I'm assuming cpp is portable in this respect... */
   2651   1.1      tron 
   2652   1.8      maya #define V1(a, b, c) XML_L(#a) XML_L(".") XML_L(#b) XML_L(".") XML_L(#c)
   2653   1.8      maya #define V2(a, b, c) XML_L("expat_") V1(a, b, c)
   2654   1.1      tron 
   2655   1.1      tron   return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
   2656   1.1      tron 
   2657   1.1      tron #undef V1
   2658   1.1      tron #undef V2
   2659   1.1      tron }
   2660   1.1      tron 
   2661   1.1      tron XML_Expat_Version XMLCALL
   2662   1.8      maya XML_ExpatVersionInfo(void) {
   2663   1.1      tron   XML_Expat_Version version;
   2664   1.1      tron 
   2665   1.1      tron   version.major = XML_MAJOR_VERSION;
   2666   1.1      tron   version.minor = XML_MINOR_VERSION;
   2667   1.1      tron   version.micro = XML_MICRO_VERSION;
   2668   1.1      tron 
   2669   1.1      tron   return version;
   2670   1.1      tron }
   2671   1.1      tron 
   2672   1.8      maya const XML_Feature *XMLCALL
   2673   1.8      maya XML_GetFeatureList(void) {
   2674   1.9  christos   static const XML_Feature features[] = {
   2675   1.9  christos       {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
   2676   1.9  christos        sizeof(XML_Char)},
   2677   1.9  christos       {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
   2678   1.9  christos        sizeof(XML_LChar)},
   2679   1.1      tron #ifdef XML_UNICODE
   2680   1.9  christos       {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
   2681   1.1      tron #endif
   2682   1.1      tron #ifdef XML_UNICODE_WCHAR_T
   2683   1.9  christos       {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
   2684   1.1      tron #endif
   2685   1.1      tron #ifdef XML_DTD
   2686   1.9  christos       {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
   2687   1.1      tron #endif
   2688  1.10       wiz #if XML_CONTEXT_BYTES > 0
   2689   1.9  christos       {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
   2690   1.9  christos        XML_CONTEXT_BYTES},
   2691   1.1      tron #endif
   2692   1.1      tron #ifdef XML_MIN_SIZE
   2693   1.9  christos       {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
   2694   1.1      tron #endif
   2695   1.1      tron #ifdef XML_NS
   2696   1.9  christos       {XML_FEATURE_NS, XML_L("XML_NS"), 0},
   2697   1.1      tron #endif
   2698   1.1      tron #ifdef XML_LARGE_SIZE
   2699   1.9  christos       {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
   2700   1.3       spz #endif
   2701   1.3       spz #ifdef XML_ATTR_INFO
   2702   1.9  christos       {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
   2703   1.9  christos #endif
   2704  1.10       wiz #if XML_GE == 1
   2705  1.10       wiz       /* Added in Expat 2.4.0 for XML_DTD defined and
   2706  1.10       wiz        * added in Expat 2.6.0 for XML_GE == 1. */
   2707   1.9  christos       {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
   2708   1.9  christos        XML_L("XML_BLAP_MAX_AMP"),
   2709   1.9  christos        (long int)
   2710   1.9  christos            EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT},
   2711   1.9  christos       {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
   2712   1.9  christos        XML_L("XML_BLAP_ACT_THRES"),
   2713   1.9  christos        EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT},
   2714  1.10       wiz       /* Added in Expat 2.6.0. */
   2715  1.10       wiz       {XML_FEATURE_GE, XML_L("XML_GE"), 0},
   2716   1.3       spz #endif
   2717   1.9  christos       {XML_FEATURE_END, NULL, 0}};
   2718   1.1      tron 
   2719   1.1      tron   return features;
   2720   1.1      tron }
   2721   1.1      tron 
   2722  1.10       wiz #if XML_GE == 1
   2723   1.9  christos XML_Bool XMLCALL
   2724   1.9  christos XML_SetBillionLaughsAttackProtectionMaximumAmplification(
   2725   1.9  christos     XML_Parser parser, float maximumAmplificationFactor) {
   2726   1.9  christos   if ((parser == NULL) || (parser->m_parentParser != NULL)
   2727   1.9  christos       || isnan(maximumAmplificationFactor)
   2728   1.9  christos       || (maximumAmplificationFactor < 1.0f)) {
   2729   1.9  christos     return XML_FALSE;
   2730   1.9  christos   }
   2731   1.9  christos   parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor;
   2732   1.9  christos   return XML_TRUE;
   2733   1.9  christos }
   2734   1.9  christos 
   2735   1.9  christos XML_Bool XMLCALL
   2736   1.9  christos XML_SetBillionLaughsAttackProtectionActivationThreshold(
   2737   1.9  christos     XML_Parser parser, unsigned long long activationThresholdBytes) {
   2738   1.9  christos   if ((parser == NULL) || (parser->m_parentParser != NULL)) {
   2739   1.9  christos     return XML_FALSE;
   2740   1.9  christos   }
   2741   1.9  christos   parser->m_accounting.activationThresholdBytes = activationThresholdBytes;
   2742   1.9  christos   return XML_TRUE;
   2743   1.9  christos }
   2744  1.10       wiz #endif /* XML_GE == 1 */
   2745  1.10       wiz 
   2746  1.10       wiz XML_Bool XMLCALL
   2747  1.10       wiz XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled) {
   2748  1.10       wiz   if (parser != NULL && (enabled == XML_TRUE || enabled == XML_FALSE)) {
   2749  1.10       wiz     parser->m_reparseDeferralEnabled = enabled;
   2750  1.10       wiz     return XML_TRUE;
   2751  1.10       wiz   }
   2752  1.10       wiz   return XML_FALSE;
   2753  1.10       wiz }
   2754   1.9  christos 
   2755   1.1      tron /* Initially tag->rawName always points into the parse buffer;
   2756   1.1      tron    for those TAG instances opened while the current parse buffer was
   2757   1.1      tron    processed, and not yet closed, we need to store tag->rawName in a more
   2758   1.1      tron    permanent location, since the parse buffer is about to be discarded.
   2759   1.1      tron */
   2760   1.1      tron static XML_Bool
   2761   1.8      maya storeRawNames(XML_Parser parser) {
   2762   1.8      maya   TAG *tag = parser->m_tagStack;
   2763   1.1      tron   while (tag) {
   2764   1.1      tron     int bufSize;
   2765   1.1      tron     int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
   2766   1.9  christos     size_t rawNameLen;
   2767   1.1      tron     char *rawNameBuf = tag->buf + nameLen;
   2768   1.8      maya     /* Stop if already stored.  Since m_tagStack is a stack, we can stop
   2769   1.1      tron        at the first entry that has already been copied; everything
   2770   1.1      tron        below it in the stack is already been accounted for in a
   2771   1.1      tron        previous call to this function.
   2772   1.1      tron     */
   2773   1.1      tron     if (tag->rawName == rawNameBuf)
   2774   1.1      tron       break;
   2775  1.10       wiz     /* For reuse purposes we need to ensure that the
   2776   1.1      tron        size of tag->buf is a multiple of sizeof(XML_Char).
   2777   1.1      tron     */
   2778   1.9  christos     rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
   2779   1.9  christos     /* Detect and prevent integer overflow. */
   2780   1.9  christos     if (rawNameLen > (size_t)INT_MAX - nameLen)
   2781   1.9  christos       return XML_FALSE;
   2782   1.9  christos     bufSize = nameLen + (int)rawNameLen;
   2783   1.1      tron     if (bufSize > tag->bufEnd - tag->buf) {
   2784   1.8      maya       char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
   2785   1.1      tron       if (temp == NULL)
   2786   1.1      tron         return XML_FALSE;
   2787   1.1      tron       /* if tag->name.str points to tag->buf (only when namespace
   2788   1.1      tron          processing is off) then we have to update it
   2789   1.1      tron       */
   2790   1.1      tron       if (tag->name.str == (XML_Char *)tag->buf)
   2791   1.1      tron         tag->name.str = (XML_Char *)temp;
   2792   1.1      tron       /* if tag->name.localPart is set (when namespace processing is on)
   2793   1.1      tron          then update it as well, since it will always point into tag->buf
   2794   1.1      tron       */
   2795   1.1      tron       if (tag->name.localPart)
   2796   1.8      maya         tag->name.localPart
   2797   1.8      maya             = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf);
   2798   1.1      tron       tag->buf = temp;
   2799   1.1      tron       tag->bufEnd = temp + bufSize;
   2800   1.1      tron       rawNameBuf = temp + nameLen;
   2801   1.1      tron     }
   2802   1.1      tron     memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
   2803   1.1      tron     tag->rawName = rawNameBuf;
   2804   1.1      tron     tag = tag->parent;
   2805   1.1      tron   }
   2806   1.1      tron   return XML_TRUE;
   2807   1.1      tron }
   2808   1.1      tron 
   2809   1.1      tron static enum XML_Error PTRCALL
   2810   1.8      maya contentProcessor(XML_Parser parser, const char *start, const char *end,
   2811   1.8      maya                  const char **endPtr) {
   2812   1.9  christos   enum XML_Error result = doContent(
   2813  1.10       wiz       parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, start, end,
   2814  1.10       wiz       endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer,
   2815  1.10       wiz       XML_ACCOUNT_DIRECT);
   2816   1.1      tron   if (result == XML_ERROR_NONE) {
   2817   1.8      maya     if (! storeRawNames(parser))
   2818   1.1      tron       return XML_ERROR_NO_MEMORY;
   2819   1.1      tron   }
   2820   1.1      tron   return result;
   2821   1.1      tron }
   2822   1.1      tron 
   2823   1.1      tron static enum XML_Error PTRCALL
   2824   1.8      maya externalEntityInitProcessor(XML_Parser parser, const char *start,
   2825   1.8      maya                             const char *end, const char **endPtr) {
   2826   1.1      tron   enum XML_Error result = initializeEncoding(parser);
   2827   1.1      tron   if (result != XML_ERROR_NONE)
   2828   1.1      tron     return result;
   2829   1.8      maya   parser->m_processor = externalEntityInitProcessor2;
   2830   1.1      tron   return externalEntityInitProcessor2(parser, start, end, endPtr);
   2831   1.1      tron }
   2832   1.1      tron 
   2833   1.1      tron static enum XML_Error PTRCALL
   2834   1.8      maya externalEntityInitProcessor2(XML_Parser parser, const char *start,
   2835   1.8      maya                              const char *end, const char **endPtr) {
   2836   1.1      tron   const char *next = start; /* XmlContentTok doesn't always set the last arg */
   2837   1.8      maya   int tok = XmlContentTok(parser->m_encoding, start, end, &next);
   2838   1.1      tron   switch (tok) {
   2839   1.1      tron   case XML_TOK_BOM:
   2840  1.10       wiz #if XML_GE == 1
   2841   1.9  christos     if (! accountingDiffTolerated(parser, tok, start, next, __LINE__,
   2842   1.9  christos                                   XML_ACCOUNT_DIRECT)) {
   2843   1.9  christos       accountingOnAbort(parser);
   2844   1.9  christos       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   2845   1.9  christos     }
   2846  1.10       wiz #endif /* XML_GE == 1 */
   2847   1.9  christos 
   2848   1.1      tron     /* If we are at the end of the buffer, this would cause the next stage,
   2849   1.1      tron        i.e. externalEntityInitProcessor3, to pass control directly to
   2850   1.1      tron        doContent (by detecting XML_TOK_NONE) without processing any xml text
   2851   1.1      tron        declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
   2852   1.1      tron     */
   2853   1.8      maya     if (next == end && ! parser->m_parsingStatus.finalBuffer) {
   2854   1.1      tron       *endPtr = next;
   2855   1.1      tron       return XML_ERROR_NONE;
   2856   1.1      tron     }
   2857   1.1      tron     start = next;
   2858   1.1      tron     break;
   2859   1.1      tron   case XML_TOK_PARTIAL:
   2860   1.8      maya     if (! parser->m_parsingStatus.finalBuffer) {
   2861   1.1      tron       *endPtr = start;
   2862   1.1      tron       return XML_ERROR_NONE;
   2863   1.1      tron     }
   2864   1.8      maya     parser->m_eventPtr = start;
   2865   1.1      tron     return XML_ERROR_UNCLOSED_TOKEN;
   2866   1.1      tron   case XML_TOK_PARTIAL_CHAR:
   2867   1.8      maya     if (! parser->m_parsingStatus.finalBuffer) {
   2868   1.1      tron       *endPtr = start;
   2869   1.1      tron       return XML_ERROR_NONE;
   2870   1.1      tron     }
   2871   1.8      maya     parser->m_eventPtr = start;
   2872   1.1      tron     return XML_ERROR_PARTIAL_CHAR;
   2873   1.1      tron   }
   2874   1.8      maya   parser->m_processor = externalEntityInitProcessor3;
   2875   1.1      tron   return externalEntityInitProcessor3(parser, start, end, endPtr);
   2876   1.1      tron }
   2877   1.1      tron 
   2878   1.1      tron static enum XML_Error PTRCALL
   2879   1.8      maya externalEntityInitProcessor3(XML_Parser parser, const char *start,
   2880   1.8      maya                              const char *end, const char **endPtr) {
   2881   1.1      tron   int tok;
   2882   1.1      tron   const char *next = start; /* XmlContentTok doesn't always set the last arg */
   2883   1.8      maya   parser->m_eventPtr = start;
   2884   1.8      maya   tok = XmlContentTok(parser->m_encoding, start, end, &next);
   2885   1.9  christos   /* Note: These bytes are accounted later in:
   2886   1.9  christos            - processXmlDecl
   2887   1.9  christos            - externalEntityContentProcessor
   2888   1.9  christos   */
   2889   1.8      maya   parser->m_eventEndPtr = next;
   2890   1.1      tron 
   2891   1.1      tron   switch (tok) {
   2892   1.8      maya   case XML_TOK_XML_DECL: {
   2893   1.8      maya     enum XML_Error result;
   2894   1.8      maya     result = processXmlDecl(parser, 1, start, next);
   2895   1.8      maya     if (result != XML_ERROR_NONE)
   2896   1.8      maya       return result;
   2897   1.8      maya     switch (parser->m_parsingStatus.parsing) {
   2898   1.8      maya     case XML_SUSPENDED:
   2899   1.8      maya       *endPtr = next;
   2900   1.8      maya       return XML_ERROR_NONE;
   2901   1.8      maya     case XML_FINISHED:
   2902   1.8      maya       return XML_ERROR_ABORTED;
   2903  1.10       wiz     case XML_PARSING:
   2904  1.10       wiz       if (parser->m_reenter) {
   2905  1.10       wiz         return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
   2906  1.10       wiz       }
   2907  1.10       wiz       /* Fall through */
   2908   1.8      maya     default:
   2909   1.8      maya       start = next;
   2910   1.1      tron     }
   2911   1.8      maya   } break;
   2912   1.1      tron   case XML_TOK_PARTIAL:
   2913   1.8      maya     if (! parser->m_parsingStatus.finalBuffer) {
   2914   1.1      tron       *endPtr = start;
   2915   1.1      tron       return XML_ERROR_NONE;
   2916   1.1      tron     }
   2917   1.1      tron     return XML_ERROR_UNCLOSED_TOKEN;
   2918   1.1      tron   case XML_TOK_PARTIAL_CHAR:
   2919   1.8      maya     if (! parser->m_parsingStatus.finalBuffer) {
   2920   1.1      tron       *endPtr = start;
   2921   1.1      tron       return XML_ERROR_NONE;
   2922   1.1      tron     }
   2923   1.1      tron     return XML_ERROR_PARTIAL_CHAR;
   2924   1.1      tron   }
   2925   1.8      maya   parser->m_processor = externalEntityContentProcessor;
   2926   1.8      maya   parser->m_tagLevel = 1;
   2927   1.1      tron   return externalEntityContentProcessor(parser, start, end, endPtr);
   2928   1.1      tron }
   2929   1.1      tron 
   2930   1.1      tron static enum XML_Error PTRCALL
   2931   1.8      maya externalEntityContentProcessor(XML_Parser parser, const char *start,
   2932   1.8      maya                                const char *end, const char **endPtr) {
   2933   1.8      maya   enum XML_Error result
   2934   1.8      maya       = doContent(parser, 1, parser->m_encoding, start, end, endPtr,
   2935   1.9  christos                   (XML_Bool)! parser->m_parsingStatus.finalBuffer,
   2936   1.9  christos                   XML_ACCOUNT_ENTITY_EXPANSION);
   2937   1.1      tron   if (result == XML_ERROR_NONE) {
   2938   1.8      maya     if (! storeRawNames(parser))
   2939   1.1      tron       return XML_ERROR_NO_MEMORY;
   2940   1.1      tron   }
   2941   1.1      tron   return result;
   2942   1.1      tron }
   2943   1.1      tron 
   2944   1.1      tron static enum XML_Error
   2945   1.8      maya doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
   2946   1.8      maya           const char *s, const char *end, const char **nextPtr,
   2947   1.9  christos           XML_Bool haveMore, enum XML_Account account) {
   2948   1.1      tron   /* save one level of indirection */
   2949   1.8      maya   DTD *const dtd = parser->m_dtd;
   2950   1.1      tron 
   2951   1.1      tron   const char **eventPP;
   2952   1.1      tron   const char **eventEndPP;
   2953   1.8      maya   if (enc == parser->m_encoding) {
   2954   1.8      maya     eventPP = &parser->m_eventPtr;
   2955   1.8      maya     eventEndPP = &parser->m_eventEndPtr;
   2956   1.8      maya   } else {
   2957   1.8      maya     eventPP = &(parser->m_openInternalEntities->internalEventPtr);
   2958   1.8      maya     eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
   2959   1.1      tron   }
   2960   1.1      tron   *eventPP = s;
   2961   1.1      tron 
   2962   1.1      tron   for (;;) {
   2963   1.1      tron     const char *next = s; /* XmlContentTok doesn't always set the last arg */
   2964   1.1      tron     int tok = XmlContentTok(enc, s, end, &next);
   2965  1.10       wiz #if XML_GE == 1
   2966   1.9  christos     const char *accountAfter
   2967   1.9  christos         = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR))
   2968   1.9  christos               ? (haveMore ? s /* i.e. 0 bytes */ : end)
   2969   1.9  christos               : next;
   2970   1.9  christos     if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__,
   2971   1.9  christos                                   account)) {
   2972   1.9  christos       accountingOnAbort(parser);
   2973   1.9  christos       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   2974   1.9  christos     }
   2975   1.9  christos #endif
   2976   1.1      tron     *eventEndPP = next;
   2977   1.1      tron     switch (tok) {
   2978   1.1      tron     case XML_TOK_TRAILING_CR:
   2979   1.1      tron       if (haveMore) {
   2980   1.1      tron         *nextPtr = s;
   2981   1.1      tron         return XML_ERROR_NONE;
   2982   1.1      tron       }
   2983   1.1      tron       *eventEndPP = end;
   2984   1.8      maya       if (parser->m_characterDataHandler) {
   2985   1.1      tron         XML_Char c = 0xA;
   2986   1.8      maya         parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
   2987   1.8      maya       } else if (parser->m_defaultHandler)
   2988   1.1      tron         reportDefault(parser, enc, s, end);
   2989   1.3       spz       /* We are at the end of the final buffer, should we check for
   2990   1.3       spz          XML_SUSPENDED, XML_FINISHED?
   2991   1.1      tron       */
   2992   1.1      tron       if (startTagLevel == 0)
   2993   1.1      tron         return XML_ERROR_NO_ELEMENTS;
   2994   1.8      maya       if (parser->m_tagLevel != startTagLevel)
   2995   1.1      tron         return XML_ERROR_ASYNC_ENTITY;
   2996   1.1      tron       *nextPtr = end;
   2997   1.1      tron       return XML_ERROR_NONE;
   2998   1.1      tron     case XML_TOK_NONE:
   2999   1.1      tron       if (haveMore) {
   3000   1.1      tron         *nextPtr = s;
   3001   1.1      tron         return XML_ERROR_NONE;
   3002   1.1      tron       }
   3003   1.1      tron       if (startTagLevel > 0) {
   3004   1.8      maya         if (parser->m_tagLevel != startTagLevel)
   3005   1.1      tron           return XML_ERROR_ASYNC_ENTITY;
   3006   1.1      tron         *nextPtr = s;
   3007   1.1      tron         return XML_ERROR_NONE;
   3008   1.1      tron       }
   3009   1.1      tron       return XML_ERROR_NO_ELEMENTS;
   3010   1.1      tron     case XML_TOK_INVALID:
   3011   1.1      tron       *eventPP = next;
   3012   1.1      tron       return XML_ERROR_INVALID_TOKEN;
   3013   1.1      tron     case XML_TOK_PARTIAL:
   3014   1.1      tron       if (haveMore) {
   3015   1.1      tron         *nextPtr = s;
   3016   1.1      tron         return XML_ERROR_NONE;
   3017   1.1      tron       }
   3018   1.1      tron       return XML_ERROR_UNCLOSED_TOKEN;
   3019   1.1      tron     case XML_TOK_PARTIAL_CHAR:
   3020   1.1      tron       if (haveMore) {
   3021   1.1      tron         *nextPtr = s;
   3022   1.1      tron         return XML_ERROR_NONE;
   3023   1.1      tron       }
   3024   1.1      tron       return XML_ERROR_PARTIAL_CHAR;
   3025   1.8      maya     case XML_TOK_ENTITY_REF: {
   3026   1.8      maya       const XML_Char *name;
   3027   1.8      maya       ENTITY *entity;
   3028   1.8      maya       XML_Char ch = (XML_Char)XmlPredefinedEntityName(
   3029   1.8      maya           enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
   3030   1.8      maya       if (ch) {
   3031  1.10       wiz #if XML_GE == 1
   3032   1.9  christos         /* NOTE: We are replacing 4-6 characters original input for 1 character
   3033   1.9  christos          *       so there is no amplification and hence recording without
   3034   1.9  christos          *       protection. */
   3035   1.9  christos         accountingDiffTolerated(parser, tok, (char *)&ch,
   3036   1.9  christos                                 ((char *)&ch) + sizeof(XML_Char), __LINE__,
   3037   1.9  christos                                 XML_ACCOUNT_ENTITY_EXPANSION);
   3038  1.10       wiz #endif /* XML_GE == 1 */
   3039   1.8      maya         if (parser->m_characterDataHandler)
   3040   1.8      maya           parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
   3041   1.8      maya         else if (parser->m_defaultHandler)
   3042   1.8      maya           reportDefault(parser, enc, s, next);
   3043   1.8      maya         break;
   3044   1.8      maya       }
   3045   1.8      maya       name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
   3046   1.8      maya                              next - enc->minBytesPerChar);
   3047   1.8      maya       if (! name)
   3048   1.8      maya         return XML_ERROR_NO_MEMORY;
   3049   1.8      maya       entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
   3050   1.8      maya       poolDiscard(&dtd->pool);
   3051   1.8      maya       /* First, determine if a check for an existing declaration is needed;
   3052   1.8      maya          if yes, check that the entity exists, and that it is internal,
   3053   1.8      maya          otherwise call the skipped entity or default handler.
   3054   1.8      maya       */
   3055   1.8      maya       if (! dtd->hasParamEntityRefs || dtd->standalone) {
   3056   1.8      maya         if (! entity)
   3057   1.8      maya           return XML_ERROR_UNDEFINED_ENTITY;
   3058   1.8      maya         else if (! entity->is_internal)
   3059   1.8      maya           return XML_ERROR_ENTITY_DECLARED_IN_PE;
   3060   1.8      maya       } else if (! entity) {
   3061   1.8      maya         if (parser->m_skippedEntityHandler)
   3062   1.8      maya           parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
   3063   1.8      maya         else if (parser->m_defaultHandler)
   3064   1.8      maya           reportDefault(parser, enc, s, next);
   3065   1.8      maya         break;
   3066   1.8      maya       }
   3067   1.8      maya       if (entity->open)
   3068   1.8      maya         return XML_ERROR_RECURSIVE_ENTITY_REF;
   3069   1.8      maya       if (entity->notation)
   3070   1.8      maya         return XML_ERROR_BINARY_ENTITY_REF;
   3071   1.8      maya       if (entity->textPtr) {
   3072   1.8      maya         enum XML_Error result;
   3073   1.8      maya         if (! parser->m_defaultExpandInternalEntities) {
   3074   1.8      maya           if (parser->m_skippedEntityHandler)
   3075   1.8      maya             parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name,
   3076   1.8      maya                                            0);
   3077   1.8      maya           else if (parser->m_defaultHandler)
   3078   1.1      tron             reportDefault(parser, enc, s, next);
   3079   1.1      tron           break;
   3080   1.1      tron         }
   3081  1.10       wiz         result = processEntity(parser, entity, XML_FALSE, ENTITY_INTERNAL);
   3082   1.8      maya         if (result != XML_ERROR_NONE)
   3083   1.8      maya           return result;
   3084   1.8      maya       } else if (parser->m_externalEntityRefHandler) {
   3085   1.8      maya         const XML_Char *context;
   3086   1.8      maya         entity->open = XML_TRUE;
   3087   1.8      maya         context = getContext(parser);
   3088   1.8      maya         entity->open = XML_FALSE;
   3089   1.8      maya         if (! context)
   3090   1.8      maya           return XML_ERROR_NO_MEMORY;
   3091   1.8      maya         if (! parser->m_externalEntityRefHandler(
   3092   1.8      maya                 parser->m_externalEntityRefHandlerArg, context, entity->base,
   3093   1.8      maya                 entity->systemId, entity->publicId))
   3094   1.8      maya           return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   3095   1.8      maya         poolDiscard(&parser->m_tempPool);
   3096   1.8      maya       } else if (parser->m_defaultHandler)
   3097   1.8      maya         reportDefault(parser, enc, s, next);
   3098   1.8      maya       break;
   3099   1.8      maya     }
   3100   1.8      maya     case XML_TOK_START_TAG_NO_ATTS:
   3101   1.8      maya       /* fall through */
   3102   1.8      maya     case XML_TOK_START_TAG_WITH_ATTS: {
   3103   1.8      maya       TAG *tag;
   3104   1.8      maya       enum XML_Error result;
   3105   1.8      maya       XML_Char *toPtr;
   3106   1.8      maya       if (parser->m_freeTagList) {
   3107   1.8      maya         tag = parser->m_freeTagList;
   3108   1.8      maya         parser->m_freeTagList = parser->m_freeTagList->parent;
   3109   1.8      maya       } else {
   3110   1.8      maya         tag = (TAG *)MALLOC(parser, sizeof(TAG));
   3111   1.8      maya         if (! tag)
   3112   1.8      maya           return XML_ERROR_NO_MEMORY;
   3113   1.8      maya         tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
   3114   1.8      maya         if (! tag->buf) {
   3115   1.8      maya           FREE(parser, tag);
   3116   1.1      tron           return XML_ERROR_NO_MEMORY;
   3117   1.1      tron         }
   3118   1.8      maya         tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
   3119   1.1      tron       }
   3120   1.8      maya       tag->bindings = NULL;
   3121   1.8      maya       tag->parent = parser->m_tagStack;
   3122   1.8      maya       parser->m_tagStack = tag;
   3123   1.8      maya       tag->name.localPart = NULL;
   3124   1.8      maya       tag->name.prefix = NULL;
   3125   1.8      maya       tag->rawName = s + enc->minBytesPerChar;
   3126   1.8      maya       tag->rawNameLength = XmlNameLength(enc, tag->rawName);
   3127   1.8      maya       ++parser->m_tagLevel;
   3128   1.1      tron       {
   3129   1.8      maya         const char *rawNameEnd = tag->rawName + tag->rawNameLength;
   3130   1.8      maya         const char *fromPtr = tag->rawName;
   3131   1.8      maya         toPtr = (XML_Char *)tag->buf;
   3132   1.8      maya         for (;;) {
   3133   1.8      maya           int bufSize;
   3134   1.8      maya           int convLen;
   3135   1.8      maya           const enum XML_Convert_Result convert_res
   3136   1.8      maya               = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr,
   3137   1.8      maya                            (ICHAR *)tag->bufEnd - 1);
   3138   1.8      maya           convLen = (int)(toPtr - (XML_Char *)tag->buf);
   3139   1.8      maya           if ((fromPtr >= rawNameEnd)
   3140   1.8      maya               || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
   3141   1.8      maya             tag->name.strLen = convLen;
   3142   1.8      maya             break;
   3143   1.1      tron           }
   3144   1.8      maya           bufSize = (int)(tag->bufEnd - tag->buf) << 1;
   3145   1.8      maya           {
   3146   1.8      maya             char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
   3147   1.8      maya             if (temp == NULL)
   3148   1.8      maya               return XML_ERROR_NO_MEMORY;
   3149   1.8      maya             tag->buf = temp;
   3150   1.8      maya             tag->bufEnd = temp + bufSize;
   3151   1.8      maya             toPtr = (XML_Char *)temp + convLen;
   3152   1.1      tron           }
   3153   1.1      tron         }
   3154   1.1      tron       }
   3155   1.8      maya       tag->name.str = (XML_Char *)tag->buf;
   3156   1.8      maya       *toPtr = XML_T('\0');
   3157   1.9  christos       result
   3158   1.9  christos           = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account);
   3159   1.8      maya       if (result)
   3160   1.8      maya         return result;
   3161   1.8      maya       if (parser->m_startElementHandler)
   3162   1.8      maya         parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
   3163   1.8      maya                                       (const XML_Char **)parser->m_atts);
   3164   1.8      maya       else if (parser->m_defaultHandler)
   3165   1.8      maya         reportDefault(parser, enc, s, next);
   3166   1.8      maya       poolClear(&parser->m_tempPool);
   3167   1.8      maya       break;
   3168   1.8      maya     }
   3169   1.1      tron     case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
   3170   1.1      tron       /* fall through */
   3171   1.8      maya     case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: {
   3172   1.8      maya       const char *rawName = s + enc->minBytesPerChar;
   3173   1.8      maya       enum XML_Error result;
   3174   1.8      maya       BINDING *bindings = NULL;
   3175   1.8      maya       XML_Bool noElmHandlers = XML_TRUE;
   3176   1.8      maya       TAG_NAME name;
   3177   1.8      maya       name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
   3178   1.8      maya                                  rawName + XmlNameLength(enc, rawName));
   3179   1.8      maya       if (! name.str)
   3180   1.8      maya         return XML_ERROR_NO_MEMORY;
   3181   1.8      maya       poolFinish(&parser->m_tempPool);
   3182   1.9  christos       result = storeAtts(parser, enc, s, &name, &bindings,
   3183   1.9  christos                          XML_ACCOUNT_NONE /* token spans whole start tag */);
   3184   1.8      maya       if (result != XML_ERROR_NONE) {
   3185   1.7  christos         freeBindings(parser, bindings);
   3186   1.8      maya         return result;
   3187   1.8      maya       }
   3188   1.8      maya       poolFinish(&parser->m_tempPool);
   3189   1.8      maya       if (parser->m_startElementHandler) {
   3190   1.8      maya         parser->m_startElementHandler(parser->m_handlerArg, name.str,
   3191   1.8      maya                                       (const XML_Char **)parser->m_atts);
   3192   1.8      maya         noElmHandlers = XML_FALSE;
   3193   1.8      maya       }
   3194   1.8      maya       if (parser->m_endElementHandler) {
   3195   1.8      maya         if (parser->m_startElementHandler)
   3196   1.8      maya           *eventPP = *eventEndPP;
   3197   1.8      maya         parser->m_endElementHandler(parser->m_handlerArg, name.str);
   3198   1.8      maya         noElmHandlers = XML_FALSE;
   3199   1.8      maya       }
   3200   1.8      maya       if (noElmHandlers && parser->m_defaultHandler)
   3201   1.8      maya         reportDefault(parser, enc, s, next);
   3202   1.8      maya       poolClear(&parser->m_tempPool);
   3203   1.8      maya       freeBindings(parser, bindings);
   3204   1.8      maya     }
   3205   1.8      maya       if ((parser->m_tagLevel == 0)
   3206   1.8      maya           && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
   3207  1.10       wiz         if (parser->m_parsingStatus.parsing == XML_SUSPENDED
   3208  1.10       wiz             || (parser->m_parsingStatus.parsing == XML_PARSING
   3209  1.10       wiz                 && parser->m_reenter))
   3210   1.8      maya           parser->m_processor = epilogProcessor;
   3211   1.8      maya         else
   3212   1.8      maya           return epilogProcessor(parser, next, end, nextPtr);
   3213   1.1      tron       }
   3214   1.1      tron       break;
   3215   1.1      tron     case XML_TOK_END_TAG:
   3216   1.8      maya       if (parser->m_tagLevel == startTagLevel)
   3217   1.1      tron         return XML_ERROR_ASYNC_ENTITY;
   3218   1.1      tron       else {
   3219   1.1      tron         int len;
   3220   1.1      tron         const char *rawName;
   3221   1.8      maya         TAG *tag = parser->m_tagStack;
   3222   1.8      maya         rawName = s + enc->minBytesPerChar * 2;
   3223   1.1      tron         len = XmlNameLength(enc, rawName);
   3224   1.1      tron         if (len != tag->rawNameLength
   3225   1.1      tron             || memcmp(tag->rawName, rawName, len) != 0) {
   3226   1.1      tron           *eventPP = rawName;
   3227   1.1      tron           return XML_ERROR_TAG_MISMATCH;
   3228   1.1      tron         }
   3229  1.10       wiz         parser->m_tagStack = tag->parent;
   3230  1.10       wiz         tag->parent = parser->m_freeTagList;
   3231  1.10       wiz         parser->m_freeTagList = tag;
   3232   1.8      maya         --parser->m_tagLevel;
   3233   1.8      maya         if (parser->m_endElementHandler) {
   3234   1.1      tron           const XML_Char *localPart;
   3235   1.1      tron           const XML_Char *prefix;
   3236   1.1      tron           XML_Char *uri;
   3237   1.1      tron           localPart = tag->name.localPart;
   3238   1.8      maya           if (parser->m_ns && localPart) {
   3239   1.1      tron             /* localPart and prefix may have been overwritten in
   3240   1.1      tron                tag->name.str, since this points to the binding->uri
   3241  1.10       wiz                buffer which gets reused; so we have to add them again
   3242   1.1      tron             */
   3243   1.1      tron             uri = (XML_Char *)tag->name.str + tag->name.uriLen;
   3244   1.1      tron             /* don't need to check for space - already done in storeAtts() */
   3245   1.8      maya             while (*localPart)
   3246   1.8      maya               *uri++ = *localPart++;
   3247  1.10       wiz             prefix = tag->name.prefix;
   3248   1.8      maya             if (parser->m_ns_triplets && prefix) {
   3249   1.8      maya               *uri++ = parser->m_namespaceSeparator;
   3250   1.8      maya               while (*prefix)
   3251   1.8      maya                 *uri++ = *prefix++;
   3252   1.8      maya             }
   3253   1.1      tron             *uri = XML_T('\0');
   3254   1.1      tron           }
   3255   1.8      maya           parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
   3256   1.8      maya         } else if (parser->m_defaultHandler)
   3257   1.1      tron           reportDefault(parser, enc, s, next);
   3258   1.1      tron         while (tag->bindings) {
   3259   1.1      tron           BINDING *b = tag->bindings;
   3260   1.8      maya           if (parser->m_endNamespaceDeclHandler)
   3261   1.8      maya             parser->m_endNamespaceDeclHandler(parser->m_handlerArg,
   3262   1.8      maya                                               b->prefix->name);
   3263   1.1      tron           tag->bindings = tag->bindings->nextTagBinding;
   3264   1.8      maya           b->nextTagBinding = parser->m_freeBindingList;
   3265   1.8      maya           parser->m_freeBindingList = b;
   3266   1.1      tron           b->prefix->binding = b->prevPrefixBinding;
   3267   1.1      tron         }
   3268   1.8      maya         if ((parser->m_tagLevel == 0)
   3269   1.8      maya             && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
   3270  1.10       wiz           if (parser->m_parsingStatus.parsing == XML_SUSPENDED
   3271  1.10       wiz               || (parser->m_parsingStatus.parsing == XML_PARSING
   3272  1.10       wiz                   && parser->m_reenter))
   3273   1.8      maya             parser->m_processor = epilogProcessor;
   3274   1.8      maya           else
   3275   1.8      maya             return epilogProcessor(parser, next, end, nextPtr);
   3276   1.1      tron         }
   3277   1.1      tron       }
   3278   1.1      tron       break;
   3279   1.8      maya     case XML_TOK_CHAR_REF: {
   3280   1.8      maya       int n = XmlCharRefNumber(enc, s);
   3281   1.8      maya       if (n < 0)
   3282   1.8      maya         return XML_ERROR_BAD_CHAR_REF;
   3283   1.8      maya       if (parser->m_characterDataHandler) {
   3284   1.8      maya         XML_Char buf[XML_ENCODE_MAX];
   3285   1.8      maya         parser->m_characterDataHandler(parser->m_handlerArg, buf,
   3286   1.8      maya                                        XmlEncode(n, (ICHAR *)buf));
   3287   1.8      maya       } else if (parser->m_defaultHandler)
   3288   1.8      maya         reportDefault(parser, enc, s, next);
   3289   1.8      maya     } break;
   3290   1.1      tron     case XML_TOK_XML_DECL:
   3291   1.1      tron       return XML_ERROR_MISPLACED_XML_PI;
   3292   1.1      tron     case XML_TOK_DATA_NEWLINE:
   3293   1.8      maya       if (parser->m_characterDataHandler) {
   3294   1.1      tron         XML_Char c = 0xA;
   3295   1.8      maya         parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
   3296   1.8      maya       } else if (parser->m_defaultHandler)
   3297   1.1      tron         reportDefault(parser, enc, s, next);
   3298   1.1      tron       break;
   3299   1.8      maya     case XML_TOK_CDATA_SECT_OPEN: {
   3300   1.8      maya       enum XML_Error result;
   3301   1.8      maya       if (parser->m_startCdataSectionHandler)
   3302   1.8      maya         parser->m_startCdataSectionHandler(parser->m_handlerArg);
   3303   1.8      maya       /* BEGIN disabled code */
   3304   1.8      maya       /* Suppose you doing a transformation on a document that involves
   3305   1.8      maya          changing only the character data.  You set up a defaultHandler
   3306   1.8      maya          and a characterDataHandler.  The defaultHandler simply copies
   3307   1.8      maya          characters through.  The characterDataHandler does the
   3308   1.8      maya          transformation and writes the characters out escaping them as
   3309   1.8      maya          necessary.  This case will fail to work if we leave out the
   3310   1.8      maya          following two lines (because & and < inside CDATA sections will
   3311   1.8      maya          be incorrectly escaped).
   3312   1.1      tron 
   3313   1.8      maya          However, now we have a start/endCdataSectionHandler, so it seems
   3314   1.8      maya          easier to let the user deal with this.
   3315   1.8      maya       */
   3316  1.10       wiz       else if ((0) && parser->m_characterDataHandler)
   3317   1.8      maya         parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
   3318   1.8      maya                                        0);
   3319   1.8      maya       /* END disabled code */
   3320   1.8      maya       else if (parser->m_defaultHandler)
   3321   1.8      maya         reportDefault(parser, enc, s, next);
   3322   1.9  christos       result
   3323   1.9  christos           = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account);
   3324   1.8      maya       if (result != XML_ERROR_NONE)
   3325   1.8      maya         return result;
   3326   1.8      maya       else if (! next) {
   3327   1.8      maya         parser->m_processor = cdataSectionProcessor;
   3328   1.8      maya         return result;
   3329   1.1      tron       }
   3330   1.8      maya     } break;
   3331   1.1      tron     case XML_TOK_TRAILING_RSQB:
   3332   1.1      tron       if (haveMore) {
   3333   1.1      tron         *nextPtr = s;
   3334   1.1      tron         return XML_ERROR_NONE;
   3335   1.1      tron       }
   3336   1.8      maya       if (parser->m_characterDataHandler) {
   3337   1.1      tron         if (MUST_CONVERT(enc, s)) {
   3338   1.8      maya           ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
   3339   1.8      maya           XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
   3340   1.8      maya           parser->m_characterDataHandler(
   3341   1.8      maya               parser->m_handlerArg, parser->m_dataBuf,
   3342   1.8      maya               (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
   3343   1.8      maya         } else
   3344   1.8      maya           parser->m_characterDataHandler(
   3345  1.10       wiz               parser->m_handlerArg, (const XML_Char *)s,
   3346  1.10       wiz               (int)((const XML_Char *)end - (const XML_Char *)s));
   3347   1.8      maya       } else if (parser->m_defaultHandler)
   3348   1.1      tron         reportDefault(parser, enc, s, end);
   3349   1.3       spz       /* We are at the end of the final buffer, should we check for
   3350   1.3       spz          XML_SUSPENDED, XML_FINISHED?
   3351   1.1      tron       */
   3352   1.1      tron       if (startTagLevel == 0) {
   3353   1.1      tron         *eventPP = end;
   3354   1.1      tron         return XML_ERROR_NO_ELEMENTS;
   3355   1.1      tron       }
   3356   1.8      maya       if (parser->m_tagLevel != startTagLevel) {
   3357   1.1      tron         *eventPP = end;
   3358   1.1      tron         return XML_ERROR_ASYNC_ENTITY;
   3359   1.1      tron       }
   3360   1.1      tron       *nextPtr = end;
   3361   1.1      tron       return XML_ERROR_NONE;
   3362   1.8      maya     case XML_TOK_DATA_CHARS: {
   3363   1.8      maya       XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
   3364   1.8      maya       if (charDataHandler) {
   3365   1.8      maya         if (MUST_CONVERT(enc, s)) {
   3366   1.8      maya           for (;;) {
   3367   1.8      maya             ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
   3368   1.8      maya             const enum XML_Convert_Result convert_res = XmlConvert(
   3369   1.8      maya                 enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
   3370   1.8      maya             *eventEndPP = s;
   3371   1.8      maya             charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
   3372   1.8      maya                             (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
   3373   1.8      maya             if ((convert_res == XML_CONVERT_COMPLETED)
   3374   1.8      maya                 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
   3375   1.8      maya               break;
   3376   1.8      maya             *eventPP = s;
   3377   1.1      tron           }
   3378   1.8      maya         } else
   3379  1.10       wiz           charDataHandler(parser->m_handlerArg, (const XML_Char *)s,
   3380  1.10       wiz                           (int)((const XML_Char *)next - (const XML_Char *)s));
   3381   1.8      maya       } else if (parser->m_defaultHandler)
   3382   1.8      maya         reportDefault(parser, enc, s, next);
   3383   1.8      maya     } break;
   3384   1.1      tron     case XML_TOK_PI:
   3385   1.8      maya       if (! reportProcessingInstruction(parser, enc, s, next))
   3386   1.1      tron         return XML_ERROR_NO_MEMORY;
   3387   1.1      tron       break;
   3388   1.1      tron     case XML_TOK_COMMENT:
   3389   1.8      maya       if (! reportComment(parser, enc, s, next))
   3390   1.1      tron         return XML_ERROR_NO_MEMORY;
   3391   1.1      tron       break;
   3392   1.1      tron     default:
   3393   1.8      maya       /* All of the tokens produced by XmlContentTok() have their own
   3394   1.8      maya        * explicit cases, so this default is not strictly necessary.
   3395   1.8      maya        * However it is a useful safety net, so we retain the code and
   3396   1.8      maya        * simply exclude it from the coverage tests.
   3397   1.8      maya        *
   3398   1.8      maya        * LCOV_EXCL_START
   3399   1.8      maya        */
   3400   1.8      maya       if (parser->m_defaultHandler)
   3401   1.1      tron         reportDefault(parser, enc, s, next);
   3402   1.1      tron       break;
   3403   1.8      maya       /* LCOV_EXCL_STOP */
   3404   1.1      tron     }
   3405   1.8      maya     switch (parser->m_parsingStatus.parsing) {
   3406   1.3       spz     case XML_SUSPENDED:
   3407  1.11       wiz       *eventPP = next;
   3408   1.1      tron       *nextPtr = next;
   3409   1.1      tron       return XML_ERROR_NONE;
   3410   1.1      tron     case XML_FINISHED:
   3411  1.11       wiz       *eventPP = next;
   3412   1.1      tron       return XML_ERROR_ABORTED;
   3413  1.10       wiz     case XML_PARSING:
   3414  1.10       wiz       if (parser->m_reenter) {
   3415  1.10       wiz         *nextPtr = next;
   3416  1.10       wiz         return XML_ERROR_NONE;
   3417  1.10       wiz       }
   3418  1.10       wiz       /* Fall through */
   3419   1.8      maya     default:;
   3420  1.11       wiz       *eventPP = s = next;
   3421   1.1      tron     }
   3422   1.1      tron   }
   3423   1.1      tron   /* not reached */
   3424   1.1      tron }
   3425   1.1      tron 
   3426   1.7  christos /* This function does not call free() on the allocated memory, merely
   3427   1.8      maya  * moving it to the parser's m_freeBindingList where it can be freed or
   3428   1.7  christos  * reused as appropriate.
   3429   1.7  christos  */
   3430   1.7  christos static void
   3431   1.8      maya freeBindings(XML_Parser parser, BINDING *bindings) {
   3432   1.7  christos   while (bindings) {
   3433   1.7  christos     BINDING *b = bindings;
   3434   1.7  christos 
   3435   1.8      maya     /* m_startNamespaceDeclHandler will have been called for this
   3436   1.7  christos      * binding in addBindings(), so call the end handler now.
   3437   1.7  christos      */
   3438   1.8      maya     if (parser->m_endNamespaceDeclHandler)
   3439   1.8      maya       parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
   3440   1.7  christos 
   3441   1.7  christos     bindings = bindings->nextTagBinding;
   3442   1.8      maya     b->nextTagBinding = parser->m_freeBindingList;
   3443   1.8      maya     parser->m_freeBindingList = b;
   3444   1.7  christos     b->prefix->binding = b->prevPrefixBinding;
   3445   1.7  christos   }
   3446   1.7  christos }
   3447   1.7  christos 
   3448   1.1      tron /* Precondition: all arguments must be non-NULL;
   3449   1.1      tron    Purpose:
   3450   1.1      tron    - normalize attributes
   3451   1.1      tron    - check attributes for well-formedness
   3452   1.1      tron    - generate namespace aware attribute names (URI, prefix)
   3453   1.1      tron    - build list of attributes for startElementHandler
   3454   1.1      tron    - default attributes
   3455   1.1      tron    - process namespace declarations (check and report them)
   3456   1.1      tron    - generate namespace aware element name (URI, prefix)
   3457   1.1      tron */
   3458   1.1      tron static enum XML_Error
   3459   1.8      maya storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
   3460   1.9  christos           TAG_NAME *tagNamePtr, BINDING **bindingsPtr,
   3461   1.9  christos           enum XML_Account account) {
   3462   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   3463   1.1      tron   ELEMENT_TYPE *elementType;
   3464   1.1      tron   int nDefaultAtts;
   3465   1.8      maya   const XML_Char **appAtts; /* the attribute list for the application */
   3466   1.1      tron   int attIndex = 0;
   3467   1.1      tron   int prefixLen;
   3468   1.1      tron   int i;
   3469   1.1      tron   int n;
   3470   1.1      tron   XML_Char *uri;
   3471   1.1      tron   int nPrefixes = 0;
   3472   1.1      tron   BINDING *binding;
   3473   1.1      tron   const XML_Char *localPart;
   3474   1.1      tron 
   3475   1.1      tron   /* lookup the element type name */
   3476   1.8      maya   elementType
   3477   1.8      maya       = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str, 0);
   3478   1.8      maya   if (! elementType) {
   3479   1.1      tron     const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
   3480   1.8      maya     if (! name)
   3481   1.1      tron       return XML_ERROR_NO_MEMORY;
   3482   1.3       spz     elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
   3483   1.1      tron                                          sizeof(ELEMENT_TYPE));
   3484   1.8      maya     if (! elementType)
   3485   1.1      tron       return XML_ERROR_NO_MEMORY;
   3486   1.8      maya     if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
   3487   1.1      tron       return XML_ERROR_NO_MEMORY;
   3488   1.1      tron   }
   3489   1.1      tron   nDefaultAtts = elementType->nDefaultAtts;
   3490   1.1      tron 
   3491   1.1      tron   /* get the attributes from the tokenizer */
   3492   1.8      maya   n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
   3493   1.9  christos 
   3494   1.9  christos   /* Detect and prevent integer overflow */
   3495   1.9  christos   if (n > INT_MAX - nDefaultAtts) {
   3496   1.9  christos     return XML_ERROR_NO_MEMORY;
   3497   1.9  christos   }
   3498   1.9  christos 
   3499   1.8      maya   if (n + nDefaultAtts > parser->m_attsSize) {
   3500   1.8      maya     int oldAttsSize = parser->m_attsSize;
   3501   1.1      tron     ATTRIBUTE *temp;
   3502   1.3       spz #ifdef XML_ATTR_INFO
   3503   1.3       spz     XML_AttrInfo *temp2;
   3504   1.3       spz #endif
   3505   1.9  christos 
   3506   1.9  christos     /* Detect and prevent integer overflow */
   3507   1.9  christos     if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE)
   3508   1.9  christos         || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
   3509   1.9  christos       return XML_ERROR_NO_MEMORY;
   3510   1.9  christos     }
   3511   1.9  christos 
   3512   1.8      maya     parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
   3513   1.9  christos 
   3514   1.9  christos     /* Detect and prevent integer overflow.
   3515   1.9  christos      * The preprocessor guard addresses the "always false" warning
   3516   1.9  christos      * from -Wtype-limits on platforms where
   3517   1.9  christos      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   3518   1.9  christos #if UINT_MAX >= SIZE_MAX
   3519   1.9  christos     if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) {
   3520   1.9  christos       parser->m_attsSize = oldAttsSize;
   3521   1.9  christos       return XML_ERROR_NO_MEMORY;
   3522   1.9  christos     }
   3523   1.9  christos #endif
   3524   1.9  christos 
   3525   1.8      maya     temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
   3526   1.8      maya                                 parser->m_attsSize * sizeof(ATTRIBUTE));
   3527   1.8      maya     if (temp == NULL) {
   3528   1.8      maya       parser->m_attsSize = oldAttsSize;
   3529   1.1      tron       return XML_ERROR_NO_MEMORY;
   3530   1.8      maya     }
   3531   1.8      maya     parser->m_atts = temp;
   3532   1.3       spz #ifdef XML_ATTR_INFO
   3533   1.9  christos     /* Detect and prevent integer overflow.
   3534   1.9  christos      * The preprocessor guard addresses the "always false" warning
   3535   1.9  christos      * from -Wtype-limits on platforms where
   3536   1.9  christos      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   3537   1.9  christos #  if UINT_MAX >= SIZE_MAX
   3538   1.9  christos     if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) {
   3539   1.9  christos       parser->m_attsSize = oldAttsSize;
   3540   1.9  christos       return XML_ERROR_NO_MEMORY;
   3541   1.9  christos     }
   3542   1.9  christos #  endif
   3543   1.9  christos 
   3544   1.8      maya     temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
   3545   1.8      maya                                     parser->m_attsSize * sizeof(XML_AttrInfo));
   3546   1.8      maya     if (temp2 == NULL) {
   3547   1.8      maya       parser->m_attsSize = oldAttsSize;
   3548   1.3       spz       return XML_ERROR_NO_MEMORY;
   3549   1.8      maya     }
   3550   1.8      maya     parser->m_attInfo = temp2;
   3551   1.3       spz #endif
   3552   1.1      tron     if (n > oldAttsSize)
   3553   1.8      maya       XmlGetAttributes(enc, attStr, n, parser->m_atts);
   3554   1.1      tron   }
   3555   1.1      tron 
   3556   1.8      maya   appAtts = (const XML_Char **)parser->m_atts;
   3557   1.1      tron   for (i = 0; i < n; i++) {
   3558   1.8      maya     ATTRIBUTE *currAtt = &parser->m_atts[i];
   3559   1.3       spz #ifdef XML_ATTR_INFO
   3560   1.8      maya     XML_AttrInfo *currAttInfo = &parser->m_attInfo[i];
   3561   1.3       spz #endif
   3562   1.1      tron     /* add the name and value to the attribute list */
   3563   1.8      maya     ATTRIBUTE_ID *attId
   3564   1.8      maya         = getAttributeId(parser, enc, currAtt->name,
   3565   1.8      maya                          currAtt->name + XmlNameLength(enc, currAtt->name));
   3566   1.8      maya     if (! attId)
   3567   1.1      tron       return XML_ERROR_NO_MEMORY;
   3568   1.3       spz #ifdef XML_ATTR_INFO
   3569   1.8      maya     currAttInfo->nameStart
   3570   1.8      maya         = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name);
   3571   1.8      maya     currAttInfo->nameEnd
   3572   1.8      maya         = currAttInfo->nameStart + XmlNameLength(enc, currAtt->name);
   3573   1.8      maya     currAttInfo->valueStart = parser->m_parseEndByteIndex
   3574   1.8      maya                               - (parser->m_parseEndPtr - currAtt->valuePtr);
   3575   1.8      maya     currAttInfo->valueEnd = parser->m_parseEndByteIndex
   3576   1.8      maya                             - (parser->m_parseEndPtr - currAtt->valueEnd);
   3577   1.3       spz #endif
   3578   1.1      tron     /* Detect duplicate attributes by their QNames. This does not work when
   3579   1.1      tron        namespace processing is turned on and different prefixes for the same
   3580   1.1      tron        namespace are used. For this case we have a check further down.
   3581   1.1      tron     */
   3582   1.1      tron     if ((attId->name)[-1]) {
   3583   1.8      maya       if (enc == parser->m_encoding)
   3584   1.8      maya         parser->m_eventPtr = parser->m_atts[i].name;
   3585   1.1      tron       return XML_ERROR_DUPLICATE_ATTRIBUTE;
   3586   1.1      tron     }
   3587   1.1      tron     (attId->name)[-1] = 1;
   3588   1.1      tron     appAtts[attIndex++] = attId->name;
   3589   1.8      maya     if (! parser->m_atts[i].normalized) {
   3590   1.1      tron       enum XML_Error result;
   3591   1.1      tron       XML_Bool isCdata = XML_TRUE;
   3592   1.1      tron 
   3593   1.1      tron       /* figure out whether declared as other than CDATA */
   3594   1.1      tron       if (attId->maybeTokenized) {
   3595   1.1      tron         int j;
   3596   1.1      tron         for (j = 0; j < nDefaultAtts; j++) {
   3597   1.1      tron           if (attId == elementType->defaultAtts[j].id) {
   3598   1.1      tron             isCdata = elementType->defaultAtts[j].isCdata;
   3599   1.1      tron             break;
   3600   1.1      tron           }
   3601   1.1      tron         }
   3602   1.1      tron       }
   3603   1.1      tron 
   3604   1.1      tron       /* normalize the attribute value */
   3605   1.8      maya       result = storeAttributeValue(
   3606   1.8      maya           parser, enc, isCdata, parser->m_atts[i].valuePtr,
   3607   1.9  christos           parser->m_atts[i].valueEnd, &parser->m_tempPool, account);
   3608   1.1      tron       if (result)
   3609   1.1      tron         return result;
   3610   1.8      maya       appAtts[attIndex] = poolStart(&parser->m_tempPool);
   3611   1.8      maya       poolFinish(&parser->m_tempPool);
   3612   1.8      maya     } else {
   3613   1.1      tron       /* the value did not need normalizing */
   3614   1.8      maya       appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc,
   3615   1.8      maya                                           parser->m_atts[i].valuePtr,
   3616   1.8      maya                                           parser->m_atts[i].valueEnd);
   3617   1.1      tron       if (appAtts[attIndex] == 0)
   3618   1.1      tron         return XML_ERROR_NO_MEMORY;
   3619   1.8      maya       poolFinish(&parser->m_tempPool);
   3620   1.1      tron     }
   3621   1.1      tron     /* handle prefixed attribute names */
   3622   1.1      tron     if (attId->prefix) {
   3623   1.1      tron       if (attId->xmlns) {
   3624   1.1      tron         /* deal with namespace declarations here */
   3625   1.1      tron         enum XML_Error result = addBinding(parser, attId->prefix, attId,
   3626   1.1      tron                                            appAtts[attIndex], bindingsPtr);
   3627   1.1      tron         if (result)
   3628   1.1      tron           return result;
   3629   1.1      tron         --attIndex;
   3630   1.8      maya       } else {
   3631   1.1      tron         /* deal with other prefixed names later */
   3632   1.1      tron         attIndex++;
   3633   1.1      tron         nPrefixes++;
   3634   1.1      tron         (attId->name)[-1] = 2;
   3635   1.1      tron       }
   3636   1.8      maya     } else
   3637   1.1      tron       attIndex++;
   3638   1.1      tron   }
   3639   1.1      tron 
   3640   1.1      tron   /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
   3641   1.8      maya   parser->m_nSpecifiedAtts = attIndex;
   3642   1.1      tron   if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
   3643   1.1      tron     for (i = 0; i < attIndex; i += 2)
   3644   1.1      tron       if (appAtts[i] == elementType->idAtt->name) {
   3645   1.8      maya         parser->m_idAttIndex = i;
   3646   1.1      tron         break;
   3647   1.1      tron       }
   3648   1.8      maya   } else
   3649   1.8      maya     parser->m_idAttIndex = -1;
   3650   1.1      tron 
   3651   1.1      tron   /* do attribute defaulting */
   3652   1.1      tron   for (i = 0; i < nDefaultAtts; i++) {
   3653   1.1      tron     const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
   3654   1.8      maya     if (! (da->id->name)[-1] && da->value) {
   3655   1.1      tron       if (da->id->prefix) {
   3656   1.1      tron         if (da->id->xmlns) {
   3657   1.1      tron           enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
   3658   1.1      tron                                              da->value, bindingsPtr);
   3659   1.1      tron           if (result)
   3660   1.1      tron             return result;
   3661   1.8      maya         } else {
   3662   1.1      tron           (da->id->name)[-1] = 2;
   3663   1.1      tron           nPrefixes++;
   3664   1.1      tron           appAtts[attIndex++] = da->id->name;
   3665   1.1      tron           appAtts[attIndex++] = da->value;
   3666   1.1      tron         }
   3667   1.8      maya       } else {
   3668   1.1      tron         (da->id->name)[-1] = 1;
   3669   1.1      tron         appAtts[attIndex++] = da->id->name;
   3670   1.1      tron         appAtts[attIndex++] = da->value;
   3671   1.1      tron       }
   3672   1.1      tron     }
   3673   1.1      tron   }
   3674   1.1      tron   appAtts[attIndex] = 0;
   3675   1.1      tron 
   3676   1.1      tron   /* expand prefixed attribute names, check for duplicates,
   3677   1.1      tron      and clear flags that say whether attributes were specified */
   3678   1.1      tron   i = 0;
   3679   1.1      tron   if (nPrefixes) {
   3680   1.8      maya     int j; /* hash table index */
   3681   1.8      maya     unsigned long version = parser->m_nsAttsVersion;
   3682   1.9  christos 
   3683   1.9  christos     /* Detect and prevent invalid shift */
   3684   1.9  christos     if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
   3685   1.9  christos       return XML_ERROR_NO_MEMORY;
   3686   1.9  christos     }
   3687   1.9  christos 
   3688   1.9  christos     unsigned int nsAttsSize = 1u << parser->m_nsAttsPower;
   3689   1.8      maya     unsigned char oldNsAttsPower = parser->m_nsAttsPower;
   3690   1.1      tron     /* size of hash table must be at least 2 * (# of prefixed attributes) */
   3691   1.8      maya     if ((nPrefixes << 1)
   3692   1.8      maya         >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
   3693   1.1      tron       NS_ATT *temp;
   3694   1.1      tron       /* hash table size must also be a power of 2 and >= 8 */
   3695   1.8      maya       while (nPrefixes >> parser->m_nsAttsPower++)
   3696   1.8      maya         ;
   3697   1.8      maya       if (parser->m_nsAttsPower < 3)
   3698   1.8      maya         parser->m_nsAttsPower = 3;
   3699   1.9  christos 
   3700   1.9  christos       /* Detect and prevent invalid shift */
   3701   1.9  christos       if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) {
   3702   1.9  christos         /* Restore actual size of memory in m_nsAtts */
   3703   1.9  christos         parser->m_nsAttsPower = oldNsAttsPower;
   3704   1.9  christos         return XML_ERROR_NO_MEMORY;
   3705   1.9  christos       }
   3706   1.9  christos 
   3707   1.9  christos       nsAttsSize = 1u << parser->m_nsAttsPower;
   3708   1.9  christos 
   3709   1.9  christos       /* Detect and prevent integer overflow.
   3710   1.9  christos        * The preprocessor guard addresses the "always false" warning
   3711   1.9  christos        * from -Wtype-limits on platforms where
   3712   1.9  christos        * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   3713   1.9  christos #if UINT_MAX >= SIZE_MAX
   3714   1.9  christos       if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) {
   3715   1.9  christos         /* Restore actual size of memory in m_nsAtts */
   3716   1.9  christos         parser->m_nsAttsPower = oldNsAttsPower;
   3717   1.9  christos         return XML_ERROR_NO_MEMORY;
   3718   1.9  christos       }
   3719   1.9  christos #endif
   3720   1.9  christos 
   3721   1.8      maya       temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
   3722   1.8      maya                                nsAttsSize * sizeof(NS_ATT));
   3723   1.8      maya       if (! temp) {
   3724   1.8      maya         /* Restore actual size of memory in m_nsAtts */
   3725   1.8      maya         parser->m_nsAttsPower = oldNsAttsPower;
   3726   1.1      tron         return XML_ERROR_NO_MEMORY;
   3727   1.8      maya       }
   3728   1.8      maya       parser->m_nsAtts = temp;
   3729   1.8      maya       version = 0; /* force re-initialization of m_nsAtts hash table */
   3730   1.1      tron     }
   3731   1.8      maya     /* using a version flag saves us from initializing m_nsAtts every time */
   3732   1.8      maya     if (! version) { /* initialize version flags when version wraps around */
   3733   1.1      tron       version = INIT_ATTS_VERSION;
   3734   1.8      maya       for (j = nsAttsSize; j != 0;)
   3735   1.8      maya         parser->m_nsAtts[--j].version = version;
   3736   1.1      tron     }
   3737   1.8      maya     parser->m_nsAttsVersion = --version;
   3738   1.1      tron 
   3739   1.1      tron     /* expand prefixed names and check for duplicates */
   3740   1.1      tron     for (; i < attIndex; i += 2) {
   3741   1.1      tron       const XML_Char *s = appAtts[i];
   3742   1.8      maya       if (s[-1] == 2) { /* prefixed */
   3743   1.1      tron         ATTRIBUTE_ID *id;
   3744   1.1      tron         const BINDING *b;
   3745   1.7  christos         unsigned long uriHash;
   3746   1.7  christos         struct siphash sip_state;
   3747   1.7  christos         struct sipkey sip_key;
   3748   1.7  christos 
   3749   1.7  christos         copy_salt_to_sipkey(parser, &sip_key);
   3750   1.7  christos         sip24_init(&sip_state, &sip_key);
   3751   1.7  christos 
   3752   1.8      maya         ((XML_Char *)s)[-1] = 0; /* clear flag */
   3753   1.3       spz         id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
   3754   1.8      maya         if (! id || ! id->prefix) {
   3755   1.8      maya           /* This code is walking through the appAtts array, dealing
   3756   1.8      maya            * with (in this case) a prefixed attribute name.  To be in
   3757   1.8      maya            * the array, the attribute must have already been bound, so
   3758   1.8      maya            * has to have passed through the hash table lookup once
   3759   1.8      maya            * already.  That implies that an entry for it already
   3760   1.8      maya            * exists, so the lookup above will return a pointer to
   3761   1.8      maya            * already allocated memory.  There is no opportunaity for
   3762   1.8      maya            * the allocator to fail, so the condition above cannot be
   3763   1.8      maya            * fulfilled.
   3764   1.8      maya            *
   3765   1.8      maya            * Since it is difficult to be certain that the above
   3766   1.8      maya            * analysis is complete, we retain the test and merely
   3767   1.8      maya            * remove the code from coverage tests.
   3768   1.8      maya            */
   3769   1.8      maya           return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
   3770   1.8      maya         }
   3771   1.1      tron         b = id->prefix->binding;
   3772   1.8      maya         if (! b)
   3773   1.1      tron           return XML_ERROR_UNBOUND_PREFIX;
   3774   1.1      tron 
   3775   1.1      tron         for (j = 0; j < b->uriLen; j++) {
   3776   1.1      tron           const XML_Char c = b->uri[j];
   3777   1.8      maya           if (! poolAppendChar(&parser->m_tempPool, c))
   3778   1.1      tron             return XML_ERROR_NO_MEMORY;
   3779   1.1      tron         }
   3780   1.7  christos 
   3781   1.7  christos         sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
   3782   1.7  christos 
   3783   1.1      tron         while (*s++ != XML_T(ASCII_COLON))
   3784   1.1      tron           ;
   3785   1.7  christos 
   3786   1.7  christos         sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
   3787   1.7  christos 
   3788   1.8      maya         do { /* copies null terminator */
   3789   1.8      maya           if (! poolAppendChar(&parser->m_tempPool, *s))
   3790   1.1      tron             return XML_ERROR_NO_MEMORY;
   3791   1.1      tron         } while (*s++);
   3792   1.1      tron 
   3793   1.7  christos         uriHash = (unsigned long)sip24_final(&sip_state);
   3794   1.7  christos 
   3795   1.1      tron         { /* Check hash table for duplicate of expanded name (uriName).
   3796   1.3       spz              Derived from code in lookup(parser, HASH_TABLE *table, ...).
   3797   1.1      tron           */
   3798   1.1      tron           unsigned char step = 0;
   3799   1.1      tron           unsigned long mask = nsAttsSize - 1;
   3800   1.8      maya           j = uriHash & mask; /* index into hash table */
   3801   1.8      maya           while (parser->m_nsAtts[j].version == version) {
   3802   1.1      tron             /* for speed we compare stored hash values first */
   3803   1.8      maya             if (uriHash == parser->m_nsAtts[j].hash) {
   3804   1.8      maya               const XML_Char *s1 = poolStart(&parser->m_tempPool);
   3805   1.8      maya               const XML_Char *s2 = parser->m_nsAtts[j].uriName;
   3806   1.1      tron               /* s1 is null terminated, but not s2 */
   3807   1.8      maya               for (; *s1 == *s2 && *s1 != 0; s1++, s2++)
   3808   1.8      maya                 ;
   3809   1.1      tron               if (*s1 == 0)
   3810   1.1      tron                 return XML_ERROR_DUPLICATE_ATTRIBUTE;
   3811   1.1      tron             }
   3812   1.8      maya             if (! step)
   3813   1.8      maya               step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower);
   3814   1.1      tron             j < step ? (j += nsAttsSize - step) : (j -= step);
   3815   1.1      tron           }
   3816   1.1      tron         }
   3817   1.1      tron 
   3818   1.8      maya         if (parser->m_ns_triplets) { /* append namespace separator and prefix */
   3819   1.8      maya           parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator;
   3820   1.1      tron           s = b->prefix->name;
   3821   1.1      tron           do {
   3822   1.8      maya             if (! poolAppendChar(&parser->m_tempPool, *s))
   3823   1.1      tron               return XML_ERROR_NO_MEMORY;
   3824   1.1      tron           } while (*s++);
   3825   1.1      tron         }
   3826   1.1      tron 
   3827   1.1      tron         /* store expanded name in attribute list */
   3828   1.8      maya         s = poolStart(&parser->m_tempPool);
   3829   1.8      maya         poolFinish(&parser->m_tempPool);
   3830   1.1      tron         appAtts[i] = s;
   3831   1.1      tron 
   3832   1.1      tron         /* fill empty slot with new version, uriName and hash value */
   3833   1.8      maya         parser->m_nsAtts[j].version = version;
   3834   1.8      maya         parser->m_nsAtts[j].hash = uriHash;
   3835   1.8      maya         parser->m_nsAtts[j].uriName = s;
   3836   1.1      tron 
   3837   1.8      maya         if (! --nPrefixes) {
   3838   1.1      tron           i += 2;
   3839   1.1      tron           break;
   3840   1.1      tron         }
   3841   1.8      maya       } else                     /* not prefixed */
   3842   1.8      maya         ((XML_Char *)s)[-1] = 0; /* clear flag */
   3843   1.1      tron     }
   3844   1.1      tron   }
   3845   1.1      tron   /* clear flags for the remaining attributes */
   3846   1.1      tron   for (; i < attIndex; i += 2)
   3847   1.1      tron     ((XML_Char *)(appAtts[i]))[-1] = 0;
   3848   1.1      tron   for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
   3849   1.1      tron     binding->attId->name[-1] = 0;
   3850   1.1      tron 
   3851   1.8      maya   if (! parser->m_ns)
   3852   1.1      tron     return XML_ERROR_NONE;
   3853   1.1      tron 
   3854   1.1      tron   /* expand the element type name */
   3855   1.1      tron   if (elementType->prefix) {
   3856   1.1      tron     binding = elementType->prefix->binding;
   3857   1.8      maya     if (! binding)
   3858   1.1      tron       return XML_ERROR_UNBOUND_PREFIX;
   3859   1.1      tron     localPart = tagNamePtr->str;
   3860   1.1      tron     while (*localPart++ != XML_T(ASCII_COLON))
   3861   1.1      tron       ;
   3862   1.8      maya   } else if (dtd->defaultPrefix.binding) {
   3863   1.1      tron     binding = dtd->defaultPrefix.binding;
   3864   1.1      tron     localPart = tagNamePtr->str;
   3865   1.8      maya   } else
   3866   1.1      tron     return XML_ERROR_NONE;
   3867   1.1      tron   prefixLen = 0;
   3868   1.8      maya   if (parser->m_ns_triplets && binding->prefix->name) {
   3869   1.1      tron     for (; binding->prefix->name[prefixLen++];)
   3870   1.8      maya       ; /* prefixLen includes null terminator */
   3871   1.1      tron   }
   3872   1.1      tron   tagNamePtr->localPart = localPart;
   3873   1.1      tron   tagNamePtr->uriLen = binding->uriLen;
   3874   1.1      tron   tagNamePtr->prefix = binding->prefix->name;
   3875   1.1      tron   tagNamePtr->prefixLen = prefixLen;
   3876   1.1      tron   for (i = 0; localPart[i++];)
   3877   1.8      maya     ; /* i includes null terminator */
   3878   1.9  christos 
   3879   1.9  christos   /* Detect and prevent integer overflow */
   3880   1.9  christos   if (binding->uriLen > INT_MAX - prefixLen
   3881   1.9  christos       || i > INT_MAX - (binding->uriLen + prefixLen)) {
   3882   1.9  christos     return XML_ERROR_NO_MEMORY;
   3883   1.9  christos   }
   3884   1.9  christos 
   3885   1.1      tron   n = i + binding->uriLen + prefixLen;
   3886   1.1      tron   if (n > binding->uriAlloc) {
   3887   1.1      tron     TAG *p;
   3888   1.9  christos 
   3889   1.9  christos     /* Detect and prevent integer overflow */
   3890   1.9  christos     if (n > INT_MAX - EXPAND_SPARE) {
   3891   1.9  christos       return XML_ERROR_NO_MEMORY;
   3892   1.9  christos     }
   3893   1.9  christos     /* Detect and prevent integer overflow.
   3894   1.9  christos      * The preprocessor guard addresses the "always false" warning
   3895   1.9  christos      * from -Wtype-limits on platforms where
   3896   1.9  christos      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   3897   1.9  christos #if UINT_MAX >= SIZE_MAX
   3898   1.9  christos     if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
   3899   1.9  christos       return XML_ERROR_NO_MEMORY;
   3900   1.9  christos     }
   3901   1.9  christos #endif
   3902   1.9  christos 
   3903   1.8      maya     uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
   3904   1.8      maya     if (! uri)
   3905   1.1      tron       return XML_ERROR_NO_MEMORY;
   3906   1.1      tron     binding->uriAlloc = n + EXPAND_SPARE;
   3907   1.1      tron     memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
   3908   1.8      maya     for (p = parser->m_tagStack; p; p = p->parent)
   3909   1.1      tron       if (p->name.str == binding->uri)
   3910   1.1      tron         p->name.str = uri;
   3911   1.8      maya     FREE(parser, binding->uri);
   3912   1.1      tron     binding->uri = uri;
   3913   1.1      tron   }
   3914   1.8      maya   /* if m_namespaceSeparator != '\0' then uri includes it already */
   3915   1.1      tron   uri = binding->uri + binding->uriLen;
   3916   1.1      tron   memcpy(uri, localPart, i * sizeof(XML_Char));
   3917   1.1      tron   /* we always have a namespace separator between localPart and prefix */
   3918   1.1      tron   if (prefixLen) {
   3919   1.1      tron     uri += i - 1;
   3920   1.8      maya     *uri = parser->m_namespaceSeparator; /* replace null terminator */
   3921   1.1      tron     memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
   3922   1.1      tron   }
   3923   1.1      tron   tagNamePtr->str = binding->uri;
   3924   1.1      tron   return XML_ERROR_NONE;
   3925   1.1      tron }
   3926   1.1      tron 
   3927  1.10       wiz static XML_Bool
   3928  1.10       wiz is_rfc3986_uri_char(XML_Char candidate) {
   3929  1.10       wiz   // For the RFC 3986 ANBF grammar see
   3930  1.10       wiz   // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A
   3931  1.10       wiz 
   3932  1.10       wiz   switch (candidate) {
   3933  1.10       wiz   // From rule "ALPHA" (uppercase half)
   3934  1.10       wiz   case 'A':
   3935  1.10       wiz   case 'B':
   3936  1.10       wiz   case 'C':
   3937  1.10       wiz   case 'D':
   3938  1.10       wiz   case 'E':
   3939  1.10       wiz   case 'F':
   3940  1.10       wiz   case 'G':
   3941  1.10       wiz   case 'H':
   3942  1.10       wiz   case 'I':
   3943  1.10       wiz   case 'J':
   3944  1.10       wiz   case 'K':
   3945  1.10       wiz   case 'L':
   3946  1.10       wiz   case 'M':
   3947  1.10       wiz   case 'N':
   3948  1.10       wiz   case 'O':
   3949  1.10       wiz   case 'P':
   3950  1.10       wiz   case 'Q':
   3951  1.10       wiz   case 'R':
   3952  1.10       wiz   case 'S':
   3953  1.10       wiz   case 'T':
   3954  1.10       wiz   case 'U':
   3955  1.10       wiz   case 'V':
   3956  1.10       wiz   case 'W':
   3957  1.10       wiz   case 'X':
   3958  1.10       wiz   case 'Y':
   3959  1.10       wiz   case 'Z':
   3960  1.10       wiz 
   3961  1.10       wiz   // From rule "ALPHA" (lowercase half)
   3962  1.10       wiz   case 'a':
   3963  1.10       wiz   case 'b':
   3964  1.10       wiz   case 'c':
   3965  1.10       wiz   case 'd':
   3966  1.10       wiz   case 'e':
   3967  1.10       wiz   case 'f':
   3968  1.10       wiz   case 'g':
   3969  1.10       wiz   case 'h':
   3970  1.10       wiz   case 'i':
   3971  1.10       wiz   case 'j':
   3972  1.10       wiz   case 'k':
   3973  1.10       wiz   case 'l':
   3974  1.10       wiz   case 'm':
   3975  1.10       wiz   case 'n':
   3976  1.10       wiz   case 'o':
   3977  1.10       wiz   case 'p':
   3978  1.10       wiz   case 'q':
   3979  1.10       wiz   case 'r':
   3980  1.10       wiz   case 's':
   3981  1.10       wiz   case 't':
   3982  1.10       wiz   case 'u':
   3983  1.10       wiz   case 'v':
   3984  1.10       wiz   case 'w':
   3985  1.10       wiz   case 'x':
   3986  1.10       wiz   case 'y':
   3987  1.10       wiz   case 'z':
   3988  1.10       wiz 
   3989  1.10       wiz   // From rule "DIGIT"
   3990  1.10       wiz   case '0':
   3991  1.10       wiz   case '1':
   3992  1.10       wiz   case '2':
   3993  1.10       wiz   case '3':
   3994  1.10       wiz   case '4':
   3995  1.10       wiz   case '5':
   3996  1.10       wiz   case '6':
   3997  1.10       wiz   case '7':
   3998  1.10       wiz   case '8':
   3999  1.10       wiz   case '9':
   4000  1.10       wiz 
   4001  1.10       wiz   // From rule "pct-encoded"
   4002  1.10       wiz   case '%':
   4003  1.10       wiz 
   4004  1.10       wiz   // From rule "unreserved"
   4005  1.10       wiz   case '-':
   4006  1.10       wiz   case '.':
   4007  1.10       wiz   case '_':
   4008  1.10       wiz   case '~':
   4009  1.10       wiz 
   4010  1.10       wiz   // From rule "gen-delims"
   4011  1.10       wiz   case ':':
   4012  1.10       wiz   case '/':
   4013  1.10       wiz   case '?':
   4014  1.10       wiz   case '#':
   4015  1.10       wiz   case '[':
   4016  1.10       wiz   case ']':
   4017  1.10       wiz   case '@':
   4018  1.10       wiz 
   4019  1.10       wiz   // From rule "sub-delims"
   4020  1.10       wiz   case '!':
   4021  1.10       wiz   case '$':
   4022  1.10       wiz   case '&':
   4023  1.10       wiz   case '\'':
   4024  1.10       wiz   case '(':
   4025  1.10       wiz   case ')':
   4026  1.10       wiz   case '*':
   4027  1.10       wiz   case '+':
   4028  1.10       wiz   case ',':
   4029  1.10       wiz   case ';':
   4030  1.10       wiz   case '=':
   4031  1.10       wiz     return XML_TRUE;
   4032  1.10       wiz 
   4033  1.10       wiz   default:
   4034  1.10       wiz     return XML_FALSE;
   4035  1.10       wiz   }
   4036  1.10       wiz }
   4037  1.10       wiz 
   4038   1.1      tron /* addBinding() overwrites the value of prefix->binding without checking.
   4039   1.1      tron    Therefore one must keep track of the old value outside of addBinding().
   4040   1.1      tron */
   4041   1.1      tron static enum XML_Error
   4042   1.1      tron addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
   4043   1.8      maya            const XML_Char *uri, BINDING **bindingsPtr) {
   4044  1.10       wiz   // "http://www.w3.org/XML/1998/namespace"
   4045   1.8      maya   static const XML_Char xmlNamespace[]
   4046   1.8      maya       = {ASCII_h,      ASCII_t,     ASCII_t,     ASCII_p,      ASCII_COLON,
   4047   1.8      maya          ASCII_SLASH,  ASCII_SLASH, ASCII_w,     ASCII_w,      ASCII_w,
   4048   1.8      maya          ASCII_PERIOD, ASCII_w,     ASCII_3,     ASCII_PERIOD, ASCII_o,
   4049   1.8      maya          ASCII_r,      ASCII_g,     ASCII_SLASH, ASCII_X,      ASCII_M,
   4050   1.8      maya          ASCII_L,      ASCII_SLASH, ASCII_1,     ASCII_9,      ASCII_9,
   4051   1.8      maya          ASCII_8,      ASCII_SLASH, ASCII_n,     ASCII_a,      ASCII_m,
   4052   1.8      maya          ASCII_e,      ASCII_s,     ASCII_p,     ASCII_a,      ASCII_c,
   4053   1.8      maya          ASCII_e,      '\0'};
   4054   1.8      maya   static const int xmlLen = (int)sizeof(xmlNamespace) / sizeof(XML_Char) - 1;
   4055  1.10       wiz   // "http://www.w3.org/2000/xmlns/"
   4056   1.8      maya   static const XML_Char xmlnsNamespace[]
   4057   1.8      maya       = {ASCII_h,     ASCII_t,      ASCII_t, ASCII_p, ASCII_COLON,  ASCII_SLASH,
   4058   1.8      maya          ASCII_SLASH, ASCII_w,      ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w,
   4059   1.8      maya          ASCII_3,     ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,      ASCII_SLASH,
   4060   1.8      maya          ASCII_2,     ASCII_0,      ASCII_0, ASCII_0, ASCII_SLASH,  ASCII_x,
   4061   1.8      maya          ASCII_m,     ASCII_l,      ASCII_n, ASCII_s, ASCII_SLASH,  '\0'};
   4062   1.8      maya   static const int xmlnsLen
   4063   1.8      maya       = (int)sizeof(xmlnsNamespace) / sizeof(XML_Char) - 1;
   4064   1.1      tron 
   4065   1.1      tron   XML_Bool mustBeXML = XML_FALSE;
   4066   1.1      tron   XML_Bool isXML = XML_TRUE;
   4067   1.1      tron   XML_Bool isXMLNS = XML_TRUE;
   4068   1.3       spz 
   4069   1.1      tron   BINDING *b;
   4070   1.1      tron   int len;
   4071   1.1      tron 
   4072   1.1      tron   /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
   4073   1.1      tron   if (*uri == XML_T('\0') && prefix->name)
   4074   1.1      tron     return XML_ERROR_UNDECLARING_PREFIX;
   4075   1.1      tron 
   4076   1.8      maya   if (prefix->name && prefix->name[0] == XML_T(ASCII_x)
   4077   1.1      tron       && prefix->name[1] == XML_T(ASCII_m)
   4078   1.1      tron       && prefix->name[2] == XML_T(ASCII_l)) {
   4079   1.1      tron     /* Not allowed to bind xmlns */
   4080   1.8      maya     if (prefix->name[3] == XML_T(ASCII_n) && prefix->name[4] == XML_T(ASCII_s)
   4081   1.1      tron         && prefix->name[5] == XML_T('\0'))
   4082   1.1      tron       return XML_ERROR_RESERVED_PREFIX_XMLNS;
   4083   1.1      tron 
   4084   1.1      tron     if (prefix->name[3] == XML_T('\0'))
   4085   1.1      tron       mustBeXML = XML_TRUE;
   4086   1.1      tron   }
   4087   1.1      tron 
   4088   1.1      tron   for (len = 0; uri[len]; len++) {
   4089   1.1      tron     if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
   4090   1.1      tron       isXML = XML_FALSE;
   4091   1.1      tron 
   4092   1.8      maya     if (! mustBeXML && isXMLNS
   4093   1.1      tron         && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
   4094   1.1      tron       isXMLNS = XML_FALSE;
   4095   1.9  christos 
   4096  1.10       wiz     // NOTE: While Expat does not validate namespace URIs against RFC 3986
   4097  1.10       wiz     //       today (and is not REQUIRED to do so with regard to the XML 1.0
   4098  1.10       wiz     //       namespaces specification) we have to at least make sure, that
   4099  1.10       wiz     //       the application on top of Expat (that is likely splitting expanded
   4100  1.10       wiz     //       element names ("qualified names") of form
   4101  1.10       wiz     //       "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces
   4102  1.10       wiz     //       in its element handler code) cannot be confused by an attacker
   4103  1.10       wiz     //       putting additional namespace separator characters into namespace
   4104  1.10       wiz     //       declarations.  That would be ambiguous and not to be expected.
   4105  1.10       wiz     //
   4106  1.10       wiz     //       While the HTML API docs of function XML_ParserCreateNS have been
   4107  1.10       wiz     //       advising against use of a namespace separator character that can
   4108  1.10       wiz     //       appear in a URI for >20 years now, some widespread applications
   4109  1.10       wiz     //       are using URI characters (':' (colon) in particular) for a
   4110  1.10       wiz     //       namespace separator, in practice.  To keep these applications
   4111  1.10       wiz     //       functional, we only reject namespaces URIs containing the
   4112  1.10       wiz     //       application-chosen namespace separator if the chosen separator
   4113  1.10       wiz     //       is a non-URI character with regard to RFC 3986.
   4114  1.10       wiz     if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)
   4115  1.10       wiz         && ! is_rfc3986_uri_char(uri[len])) {
   4116   1.9  christos       return XML_ERROR_SYNTAX;
   4117   1.9  christos     }
   4118   1.1      tron   }
   4119   1.1      tron   isXML = isXML && len == xmlLen;
   4120   1.1      tron   isXMLNS = isXMLNS && len == xmlnsLen;
   4121   1.1      tron 
   4122   1.1      tron   if (mustBeXML != isXML)
   4123   1.1      tron     return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
   4124   1.1      tron                      : XML_ERROR_RESERVED_NAMESPACE_URI;
   4125   1.1      tron 
   4126   1.1      tron   if (isXMLNS)
   4127   1.1      tron     return XML_ERROR_RESERVED_NAMESPACE_URI;
   4128   1.1      tron 
   4129   1.8      maya   if (parser->m_namespaceSeparator)
   4130   1.1      tron     len++;
   4131   1.8      maya   if (parser->m_freeBindingList) {
   4132   1.8      maya     b = parser->m_freeBindingList;
   4133   1.1      tron     if (len > b->uriAlloc) {
   4134   1.9  christos       /* Detect and prevent integer overflow */
   4135   1.9  christos       if (len > INT_MAX - EXPAND_SPARE) {
   4136   1.9  christos         return XML_ERROR_NO_MEMORY;
   4137   1.9  christos       }
   4138   1.9  christos 
   4139   1.9  christos       /* Detect and prevent integer overflow.
   4140   1.9  christos        * The preprocessor guard addresses the "always false" warning
   4141   1.9  christos        * from -Wtype-limits on platforms where
   4142   1.9  christos        * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   4143   1.9  christos #if UINT_MAX >= SIZE_MAX
   4144   1.9  christos       if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
   4145   1.9  christos         return XML_ERROR_NO_MEMORY;
   4146   1.9  christos       }
   4147   1.9  christos #endif
   4148   1.9  christos 
   4149   1.8      maya       XML_Char *temp = (XML_Char *)REALLOC(
   4150   1.8      maya           parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
   4151   1.1      tron       if (temp == NULL)
   4152   1.1      tron         return XML_ERROR_NO_MEMORY;
   4153   1.1      tron       b->uri = temp;
   4154   1.1      tron       b->uriAlloc = len + EXPAND_SPARE;
   4155   1.1      tron     }
   4156   1.8      maya     parser->m_freeBindingList = b->nextTagBinding;
   4157   1.8      maya   } else {
   4158   1.8      maya     b = (BINDING *)MALLOC(parser, sizeof(BINDING));
   4159   1.8      maya     if (! b)
   4160   1.1      tron       return XML_ERROR_NO_MEMORY;
   4161   1.9  christos 
   4162   1.9  christos     /* Detect and prevent integer overflow */
   4163   1.9  christos     if (len > INT_MAX - EXPAND_SPARE) {
   4164   1.9  christos       return XML_ERROR_NO_MEMORY;
   4165   1.9  christos     }
   4166   1.9  christos     /* Detect and prevent integer overflow.
   4167   1.9  christos      * The preprocessor guard addresses the "always false" warning
   4168   1.9  christos      * from -Wtype-limits on platforms where
   4169   1.9  christos      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   4170   1.9  christos #if UINT_MAX >= SIZE_MAX
   4171   1.9  christos     if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
   4172   1.9  christos       return XML_ERROR_NO_MEMORY;
   4173   1.9  christos     }
   4174   1.9  christos #endif
   4175   1.9  christos 
   4176   1.8      maya     b->uri
   4177   1.8      maya         = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
   4178   1.8      maya     if (! b->uri) {
   4179   1.8      maya       FREE(parser, b);
   4180   1.1      tron       return XML_ERROR_NO_MEMORY;
   4181   1.1      tron     }
   4182   1.1      tron     b->uriAlloc = len + EXPAND_SPARE;
   4183   1.1      tron   }
   4184   1.1      tron   b->uriLen = len;
   4185   1.1      tron   memcpy(b->uri, uri, len * sizeof(XML_Char));
   4186   1.8      maya   if (parser->m_namespaceSeparator)
   4187   1.8      maya     b->uri[len - 1] = parser->m_namespaceSeparator;
   4188   1.1      tron   b->prefix = prefix;
   4189   1.1      tron   b->attId = attId;
   4190   1.1      tron   b->prevPrefixBinding = prefix->binding;
   4191   1.1      tron   /* NULL binding when default namespace undeclared */
   4192   1.8      maya   if (*uri == XML_T('\0') && prefix == &parser->m_dtd->defaultPrefix)
   4193   1.1      tron     prefix->binding = NULL;
   4194   1.1      tron   else
   4195   1.1      tron     prefix->binding = b;
   4196   1.1      tron   b->nextTagBinding = *bindingsPtr;
   4197   1.1      tron   *bindingsPtr = b;
   4198   1.1      tron   /* if attId == NULL then we are not starting a namespace scope */
   4199   1.8      maya   if (attId && parser->m_startNamespaceDeclHandler)
   4200   1.8      maya     parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name,
   4201   1.8      maya                                         prefix->binding ? uri : 0);
   4202   1.1      tron   return XML_ERROR_NONE;
   4203   1.1      tron }
   4204   1.1      tron 
   4205   1.1      tron /* The idea here is to avoid using stack for each CDATA section when
   4206   1.1      tron    the whole file is parsed with one call.
   4207   1.1      tron */
   4208   1.1      tron static enum XML_Error PTRCALL
   4209   1.8      maya cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
   4210   1.8      maya                       const char **endPtr) {
   4211   1.9  christos   enum XML_Error result = doCdataSection(
   4212   1.9  christos       parser, parser->m_encoding, &start, end, endPtr,
   4213   1.9  christos       (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
   4214   1.1      tron   if (result != XML_ERROR_NONE)
   4215   1.1      tron     return result;
   4216   1.1      tron   if (start) {
   4217   1.8      maya     if (parser->m_parentParser) { /* we are parsing an external entity */
   4218   1.8      maya       parser->m_processor = externalEntityContentProcessor;
   4219   1.1      tron       return externalEntityContentProcessor(parser, start, end, endPtr);
   4220   1.8      maya     } else {
   4221   1.8      maya       parser->m_processor = contentProcessor;
   4222   1.1      tron       return contentProcessor(parser, start, end, endPtr);
   4223   1.1      tron     }
   4224   1.1      tron   }
   4225   1.1      tron   return result;
   4226   1.1      tron }
   4227   1.1      tron 
   4228   1.1      tron /* startPtr gets set to non-null if the section is closed, and to null if
   4229   1.1      tron    the section is not yet closed.
   4230   1.1      tron */
   4231   1.1      tron static enum XML_Error
   4232   1.8      maya doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
   4233   1.9  christos                const char *end, const char **nextPtr, XML_Bool haveMore,
   4234   1.9  christos                enum XML_Account account) {
   4235   1.1      tron   const char *s = *startPtr;
   4236   1.1      tron   const char **eventPP;
   4237   1.1      tron   const char **eventEndPP;
   4238   1.8      maya   if (enc == parser->m_encoding) {
   4239   1.8      maya     eventPP = &parser->m_eventPtr;
   4240   1.1      tron     *eventPP = s;
   4241   1.8      maya     eventEndPP = &parser->m_eventEndPtr;
   4242   1.8      maya   } else {
   4243   1.8      maya     eventPP = &(parser->m_openInternalEntities->internalEventPtr);
   4244   1.8      maya     eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
   4245   1.1      tron   }
   4246   1.1      tron   *eventPP = s;
   4247   1.1      tron   *startPtr = NULL;
   4248   1.1      tron 
   4249   1.1      tron   for (;;) {
   4250   1.9  christos     const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
   4251   1.1      tron     int tok = XmlCdataSectionTok(enc, s, end, &next);
   4252  1.10       wiz #if XML_GE == 1
   4253   1.9  christos     if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
   4254   1.9  christos       accountingOnAbort(parser);
   4255   1.9  christos       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   4256   1.9  christos     }
   4257   1.9  christos #else
   4258   1.9  christos     UNUSED_P(account);
   4259   1.9  christos #endif
   4260   1.1      tron     *eventEndPP = next;
   4261   1.1      tron     switch (tok) {
   4262   1.1      tron     case XML_TOK_CDATA_SECT_CLOSE:
   4263   1.8      maya       if (parser->m_endCdataSectionHandler)
   4264   1.8      maya         parser->m_endCdataSectionHandler(parser->m_handlerArg);
   4265   1.8      maya       /* BEGIN disabled code */
   4266   1.1      tron       /* see comment under XML_TOK_CDATA_SECT_OPEN */
   4267  1.10       wiz       else if ((0) && parser->m_characterDataHandler)
   4268   1.8      maya         parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
   4269   1.8      maya                                        0);
   4270   1.8      maya       /* END disabled code */
   4271   1.8      maya       else if (parser->m_defaultHandler)
   4272   1.1      tron         reportDefault(parser, enc, s, next);
   4273   1.1      tron       *startPtr = next;
   4274   1.1      tron       *nextPtr = next;
   4275   1.8      maya       if (parser->m_parsingStatus.parsing == XML_FINISHED)
   4276   1.1      tron         return XML_ERROR_ABORTED;
   4277   1.1      tron       else
   4278   1.1      tron         return XML_ERROR_NONE;
   4279   1.1      tron     case XML_TOK_DATA_NEWLINE:
   4280   1.8      maya       if (parser->m_characterDataHandler) {
   4281   1.1      tron         XML_Char c = 0xA;
   4282   1.8      maya         parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
   4283   1.8      maya       } else if (parser->m_defaultHandler)
   4284   1.1      tron         reportDefault(parser, enc, s, next);
   4285   1.1      tron       break;
   4286   1.8      maya     case XML_TOK_DATA_CHARS: {
   4287   1.8      maya       XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
   4288   1.8      maya       if (charDataHandler) {
   4289   1.8      maya         if (MUST_CONVERT(enc, s)) {
   4290   1.8      maya           for (;;) {
   4291   1.8      maya             ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
   4292   1.8      maya             const enum XML_Convert_Result convert_res = XmlConvert(
   4293   1.8      maya                 enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
   4294   1.8      maya             *eventEndPP = next;
   4295   1.8      maya             charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
   4296   1.8      maya                             (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
   4297   1.8      maya             if ((convert_res == XML_CONVERT_COMPLETED)
   4298   1.8      maya                 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
   4299   1.8      maya               break;
   4300   1.8      maya             *eventPP = s;
   4301   1.1      tron           }
   4302   1.8      maya         } else
   4303  1.10       wiz           charDataHandler(parser->m_handlerArg, (const XML_Char *)s,
   4304  1.10       wiz                           (int)((const XML_Char *)next - (const XML_Char *)s));
   4305   1.8      maya       } else if (parser->m_defaultHandler)
   4306   1.8      maya         reportDefault(parser, enc, s, next);
   4307   1.8      maya     } break;
   4308   1.1      tron     case XML_TOK_INVALID:
   4309   1.1      tron       *eventPP = next;
   4310   1.1      tron       return XML_ERROR_INVALID_TOKEN;
   4311   1.1      tron     case XML_TOK_PARTIAL_CHAR:
   4312   1.1      tron       if (haveMore) {
   4313   1.1      tron         *nextPtr = s;
   4314   1.1      tron         return XML_ERROR_NONE;
   4315   1.1      tron       }
   4316   1.1      tron       return XML_ERROR_PARTIAL_CHAR;
   4317   1.1      tron     case XML_TOK_PARTIAL:
   4318   1.1      tron     case XML_TOK_NONE:
   4319   1.1      tron       if (haveMore) {
   4320   1.1      tron         *nextPtr = s;
   4321   1.1      tron         return XML_ERROR_NONE;
   4322   1.1      tron       }
   4323   1.1      tron       return XML_ERROR_UNCLOSED_CDATA_SECTION;
   4324   1.1      tron     default:
   4325   1.8      maya       /* Every token returned by XmlCdataSectionTok() has its own
   4326   1.8      maya        * explicit case, so this default case will never be executed.
   4327   1.8      maya        * We retain it as a safety net and exclude it from the coverage
   4328   1.8      maya        * statistics.
   4329   1.8      maya        *
   4330   1.8      maya        * LCOV_EXCL_START
   4331   1.8      maya        */
   4332   1.1      tron       *eventPP = next;
   4333   1.1      tron       return XML_ERROR_UNEXPECTED_STATE;
   4334   1.8      maya       /* LCOV_EXCL_STOP */
   4335   1.1      tron     }
   4336   1.1      tron 
   4337   1.8      maya     switch (parser->m_parsingStatus.parsing) {
   4338   1.1      tron     case XML_SUSPENDED:
   4339  1.11       wiz       *eventPP = next;
   4340   1.1      tron       *nextPtr = next;
   4341   1.1      tron       return XML_ERROR_NONE;
   4342   1.1      tron     case XML_FINISHED:
   4343  1.11       wiz       *eventPP = next;
   4344   1.1      tron       return XML_ERROR_ABORTED;
   4345  1.10       wiz     case XML_PARSING:
   4346  1.10       wiz       if (parser->m_reenter) {
   4347  1.10       wiz         return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
   4348  1.10       wiz       }
   4349  1.10       wiz       /* Fall through */
   4350   1.8      maya     default:;
   4351  1.11       wiz       *eventPP = s = next;
   4352   1.1      tron     }
   4353   1.1      tron   }
   4354   1.1      tron   /* not reached */
   4355   1.1      tron }
   4356   1.1      tron 
   4357   1.1      tron #ifdef XML_DTD
   4358   1.1      tron 
   4359   1.1      tron /* The idea here is to avoid using stack for each IGNORE section when
   4360   1.1      tron    the whole file is parsed with one call.
   4361   1.1      tron */
   4362   1.1      tron static enum XML_Error PTRCALL
   4363   1.8      maya ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end,
   4364   1.8      maya                        const char **endPtr) {
   4365   1.8      maya   enum XML_Error result
   4366   1.8      maya       = doIgnoreSection(parser, parser->m_encoding, &start, end, endPtr,
   4367   1.8      maya                         (XML_Bool)! parser->m_parsingStatus.finalBuffer);
   4368   1.1      tron   if (result != XML_ERROR_NONE)
   4369   1.1      tron     return result;
   4370   1.1      tron   if (start) {
   4371   1.8      maya     parser->m_processor = prologProcessor;
   4372   1.1      tron     return prologProcessor(parser, start, end, endPtr);
   4373   1.1      tron   }
   4374   1.1      tron   return result;
   4375   1.1      tron }
   4376   1.1      tron 
   4377   1.1      tron /* startPtr gets set to non-null is the section is closed, and to null
   4378   1.1      tron    if the section is not yet closed.
   4379   1.1      tron */
   4380   1.1      tron static enum XML_Error
   4381   1.8      maya doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
   4382   1.8      maya                 const char *end, const char **nextPtr, XML_Bool haveMore) {
   4383   1.9  christos   const char *next = *startPtr; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
   4384   1.1      tron   int tok;
   4385   1.1      tron   const char *s = *startPtr;
   4386   1.1      tron   const char **eventPP;
   4387   1.1      tron   const char **eventEndPP;
   4388   1.8      maya   if (enc == parser->m_encoding) {
   4389   1.8      maya     eventPP = &parser->m_eventPtr;
   4390   1.1      tron     *eventPP = s;
   4391   1.8      maya     eventEndPP = &parser->m_eventEndPtr;
   4392   1.8      maya   } else {
   4393   1.8      maya     /* It's not entirely clear, but it seems the following two lines
   4394   1.8      maya      * of code cannot be executed.  The only occasions on which 'enc'
   4395   1.8      maya      * is not 'encoding' are when this function is called
   4396   1.8      maya      * from the internal entity processing, and IGNORE sections are an
   4397   1.8      maya      * error in internal entities.
   4398   1.8      maya      *
   4399   1.8      maya      * Since it really isn't clear that this is true, we keep the code
   4400   1.8      maya      * and just remove it from our coverage tests.
   4401   1.8      maya      *
   4402   1.8      maya      * LCOV_EXCL_START
   4403   1.8      maya      */
   4404   1.8      maya     eventPP = &(parser->m_openInternalEntities->internalEventPtr);
   4405   1.8      maya     eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
   4406   1.8      maya     /* LCOV_EXCL_STOP */
   4407   1.1      tron   }
   4408   1.1      tron   *eventPP = s;
   4409   1.1      tron   *startPtr = NULL;
   4410   1.1      tron   tok = XmlIgnoreSectionTok(enc, s, end, &next);
   4411  1.10       wiz #  if XML_GE == 1
   4412   1.9  christos   if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
   4413   1.9  christos                                 XML_ACCOUNT_DIRECT)) {
   4414   1.9  christos     accountingOnAbort(parser);
   4415   1.9  christos     return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   4416   1.9  christos   }
   4417   1.9  christos #  endif
   4418   1.1      tron   *eventEndPP = next;
   4419   1.1      tron   switch (tok) {
   4420   1.1      tron   case XML_TOK_IGNORE_SECT:
   4421   1.8      maya     if (parser->m_defaultHandler)
   4422   1.1      tron       reportDefault(parser, enc, s, next);
   4423   1.1      tron     *startPtr = next;
   4424   1.1      tron     *nextPtr = next;
   4425   1.8      maya     if (parser->m_parsingStatus.parsing == XML_FINISHED)
   4426   1.1      tron       return XML_ERROR_ABORTED;
   4427   1.1      tron     else
   4428   1.1      tron       return XML_ERROR_NONE;
   4429   1.1      tron   case XML_TOK_INVALID:
   4430   1.1      tron     *eventPP = next;
   4431   1.1      tron     return XML_ERROR_INVALID_TOKEN;
   4432   1.1      tron   case XML_TOK_PARTIAL_CHAR:
   4433   1.1      tron     if (haveMore) {
   4434   1.1      tron       *nextPtr = s;
   4435   1.1      tron       return XML_ERROR_NONE;
   4436   1.1      tron     }
   4437   1.1      tron     return XML_ERROR_PARTIAL_CHAR;
   4438   1.1      tron   case XML_TOK_PARTIAL:
   4439   1.1      tron   case XML_TOK_NONE:
   4440   1.1      tron     if (haveMore) {
   4441   1.1      tron       *nextPtr = s;
   4442   1.1      tron       return XML_ERROR_NONE;
   4443   1.1      tron     }
   4444   1.1      tron     return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
   4445   1.1      tron   default:
   4446   1.8      maya     /* All of the tokens that XmlIgnoreSectionTok() returns have
   4447   1.8      maya      * explicit cases to handle them, so this default case is never
   4448   1.8      maya      * executed.  We keep it as a safety net anyway, and remove it
   4449   1.8      maya      * from our test coverage statistics.
   4450   1.8      maya      *
   4451   1.8      maya      * LCOV_EXCL_START
   4452   1.8      maya      */
   4453   1.1      tron     *eventPP = next;
   4454   1.1      tron     return XML_ERROR_UNEXPECTED_STATE;
   4455   1.8      maya     /* LCOV_EXCL_STOP */
   4456   1.1      tron   }
   4457   1.1      tron   /* not reached */
   4458   1.1      tron }
   4459   1.1      tron 
   4460   1.1      tron #endif /* XML_DTD */
   4461   1.1      tron 
   4462   1.1      tron static enum XML_Error
   4463   1.8      maya initializeEncoding(XML_Parser parser) {
   4464   1.1      tron   const char *s;
   4465   1.1      tron #ifdef XML_UNICODE
   4466   1.1      tron   char encodingBuf[128];
   4467   1.9  christos   /* See comments about `protocolEncodingName` in parserInit() */
   4468   1.8      maya   if (! parser->m_protocolEncodingName)
   4469   1.1      tron     s = NULL;
   4470   1.1      tron   else {
   4471   1.1      tron     int i;
   4472   1.8      maya     for (i = 0; parser->m_protocolEncodingName[i]; i++) {
   4473   1.1      tron       if (i == sizeof(encodingBuf) - 1
   4474   1.8      maya           || (parser->m_protocolEncodingName[i] & ~0x7f) != 0) {
   4475   1.1      tron         encodingBuf[0] = '\0';
   4476   1.1      tron         break;
   4477   1.1      tron       }
   4478   1.8      maya       encodingBuf[i] = (char)parser->m_protocolEncodingName[i];
   4479   1.1      tron     }
   4480   1.1      tron     encodingBuf[i] = '\0';
   4481   1.1      tron     s = encodingBuf;
   4482   1.1      tron   }
   4483   1.1      tron #else
   4484   1.8      maya   s = parser->m_protocolEncodingName;
   4485   1.1      tron #endif
   4486   1.8      maya   if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(
   4487   1.8      maya           &parser->m_initEncoding, &parser->m_encoding, s))
   4488   1.1      tron     return XML_ERROR_NONE;
   4489   1.8      maya   return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
   4490   1.1      tron }
   4491   1.1      tron 
   4492   1.1      tron static enum XML_Error
   4493   1.8      maya processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
   4494   1.8      maya                const char *next) {
   4495   1.1      tron   const char *encodingName = NULL;
   4496   1.1      tron   const XML_Char *storedEncName = NULL;
   4497   1.1      tron   const ENCODING *newEncoding = NULL;
   4498   1.1      tron   const char *version = NULL;
   4499  1.10       wiz   const char *versionend = NULL;
   4500   1.1      tron   const XML_Char *storedversion = NULL;
   4501   1.1      tron   int standalone = -1;
   4502   1.9  christos 
   4503  1.10       wiz #if XML_GE == 1
   4504   1.9  christos   if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__,
   4505   1.9  christos                                 XML_ACCOUNT_DIRECT)) {
   4506   1.9  christos     accountingOnAbort(parser);
   4507   1.9  christos     return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   4508   1.9  christos   }
   4509   1.9  christos #endif
   4510   1.9  christos 
   4511   1.8      maya   if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
   4512   1.8      maya           isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
   4513   1.8      maya           &version, &versionend, &encodingName, &newEncoding, &standalone)) {
   4514   1.1      tron     if (isGeneralTextEntity)
   4515   1.1      tron       return XML_ERROR_TEXT_DECL;
   4516   1.1      tron     else
   4517   1.1      tron       return XML_ERROR_XML_DECL;
   4518   1.1      tron   }
   4519   1.8      maya   if (! isGeneralTextEntity && standalone == 1) {
   4520   1.8      maya     parser->m_dtd->standalone = XML_TRUE;
   4521   1.1      tron #ifdef XML_DTD
   4522   1.8      maya     if (parser->m_paramEntityParsing
   4523   1.8      maya         == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
   4524   1.8      maya       parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
   4525   1.1      tron #endif /* XML_DTD */
   4526   1.1      tron   }
   4527   1.8      maya   if (parser->m_xmlDeclHandler) {
   4528   1.1      tron     if (encodingName != NULL) {
   4529   1.8      maya       storedEncName = poolStoreString(
   4530   1.8      maya           &parser->m_temp2Pool, parser->m_encoding, encodingName,
   4531   1.8      maya           encodingName + XmlNameLength(parser->m_encoding, encodingName));
   4532   1.8      maya       if (! storedEncName)
   4533   1.8      maya         return XML_ERROR_NO_MEMORY;
   4534   1.8      maya       poolFinish(&parser->m_temp2Pool);
   4535   1.1      tron     }
   4536   1.1      tron     if (version) {
   4537   1.8      maya       storedversion
   4538   1.8      maya           = poolStoreString(&parser->m_temp2Pool, parser->m_encoding, version,
   4539   1.8      maya                             versionend - parser->m_encoding->minBytesPerChar);
   4540   1.8      maya       if (! storedversion)
   4541   1.1      tron         return XML_ERROR_NO_MEMORY;
   4542   1.1      tron     }
   4543   1.8      maya     parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName,
   4544   1.8      maya                              standalone);
   4545   1.8      maya   } else if (parser->m_defaultHandler)
   4546   1.8      maya     reportDefault(parser, parser->m_encoding, s, next);
   4547   1.8      maya   if (parser->m_protocolEncodingName == NULL) {
   4548   1.1      tron     if (newEncoding) {
   4549   1.8      maya       /* Check that the specified encoding does not conflict with what
   4550   1.8      maya        * the parser has already deduced.  Do we have the same number
   4551   1.8      maya        * of bytes in the smallest representation of a character?  If
   4552   1.8      maya        * this is UTF-16, is it the same endianness?
   4553   1.8      maya        */
   4554   1.8      maya       if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
   4555   1.8      maya           || (newEncoding->minBytesPerChar == 2
   4556   1.8      maya               && newEncoding != parser->m_encoding)) {
   4557   1.8      maya         parser->m_eventPtr = encodingName;
   4558   1.1      tron         return XML_ERROR_INCORRECT_ENCODING;
   4559   1.1      tron       }
   4560   1.8      maya       parser->m_encoding = newEncoding;
   4561   1.8      maya     } else if (encodingName) {
   4562   1.1      tron       enum XML_Error result;
   4563   1.8      maya       if (! storedEncName) {
   4564   1.1      tron         storedEncName = poolStoreString(
   4565   1.8      maya             &parser->m_temp2Pool, parser->m_encoding, encodingName,
   4566   1.8      maya             encodingName + XmlNameLength(parser->m_encoding, encodingName));
   4567   1.8      maya         if (! storedEncName)
   4568   1.1      tron           return XML_ERROR_NO_MEMORY;
   4569   1.1      tron       }
   4570   1.1      tron       result = handleUnknownEncoding(parser, storedEncName);
   4571   1.8      maya       poolClear(&parser->m_temp2Pool);
   4572   1.1      tron       if (result == XML_ERROR_UNKNOWN_ENCODING)
   4573   1.8      maya         parser->m_eventPtr = encodingName;
   4574   1.1      tron       return result;
   4575   1.1      tron     }
   4576   1.1      tron   }
   4577   1.1      tron 
   4578   1.1      tron   if (storedEncName || storedversion)
   4579   1.8      maya     poolClear(&parser->m_temp2Pool);
   4580   1.1      tron 
   4581   1.1      tron   return XML_ERROR_NONE;
   4582   1.1      tron }
   4583   1.1      tron 
   4584   1.1      tron static enum XML_Error
   4585   1.8      maya handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) {
   4586   1.8      maya   if (parser->m_unknownEncodingHandler) {
   4587   1.1      tron     XML_Encoding info;
   4588   1.1      tron     int i;
   4589   1.1      tron     for (i = 0; i < 256; i++)
   4590   1.1      tron       info.map[i] = -1;
   4591   1.1      tron     info.convert = NULL;
   4592   1.1      tron     info.data = NULL;
   4593   1.1      tron     info.release = NULL;
   4594   1.8      maya     if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData,
   4595   1.8      maya                                          encodingName, &info)) {
   4596   1.1      tron       ENCODING *enc;
   4597   1.8      maya       parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding());
   4598   1.8      maya       if (! parser->m_unknownEncodingMem) {
   4599   1.1      tron         if (info.release)
   4600   1.1      tron           info.release(info.data);
   4601   1.1      tron         return XML_ERROR_NO_MEMORY;
   4602   1.1      tron       }
   4603   1.8      maya       enc = (parser->m_ns ? XmlInitUnknownEncodingNS : XmlInitUnknownEncoding)(
   4604   1.8      maya           parser->m_unknownEncodingMem, info.map, info.convert, info.data);
   4605   1.1      tron       if (enc) {
   4606   1.8      maya         parser->m_unknownEncodingData = info.data;
   4607   1.8      maya         parser->m_unknownEncodingRelease = info.release;
   4608   1.8      maya         parser->m_encoding = enc;
   4609   1.1      tron         return XML_ERROR_NONE;
   4610   1.1      tron       }
   4611   1.1      tron     }
   4612   1.1      tron     if (info.release != NULL)
   4613   1.1      tron       info.release(info.data);
   4614   1.1      tron   }
   4615   1.1      tron   return XML_ERROR_UNKNOWN_ENCODING;
   4616   1.1      tron }
   4617   1.1      tron 
   4618   1.1      tron static enum XML_Error PTRCALL
   4619   1.8      maya prologInitProcessor(XML_Parser parser, const char *s, const char *end,
   4620   1.8      maya                     const char **nextPtr) {
   4621   1.1      tron   enum XML_Error result = initializeEncoding(parser);
   4622   1.1      tron   if (result != XML_ERROR_NONE)
   4623   1.1      tron     return result;
   4624   1.8      maya   parser->m_processor = prologProcessor;
   4625   1.1      tron   return prologProcessor(parser, s, end, nextPtr);
   4626   1.1      tron }
   4627   1.1      tron 
   4628   1.1      tron #ifdef XML_DTD
   4629   1.1      tron 
   4630   1.1      tron static enum XML_Error PTRCALL
   4631   1.8      maya externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
   4632   1.8      maya                             const char **nextPtr) {
   4633   1.1      tron   enum XML_Error result = initializeEncoding(parser);
   4634   1.1      tron   if (result != XML_ERROR_NONE)
   4635   1.1      tron     return result;
   4636   1.1      tron 
   4637   1.1      tron   /* we know now that XML_Parse(Buffer) has been called,
   4638   1.1      tron      so we consider the external parameter entity read */
   4639   1.8      maya   parser->m_dtd->paramEntityRead = XML_TRUE;
   4640   1.1      tron 
   4641   1.8      maya   if (parser->m_prologState.inEntityValue) {
   4642   1.8      maya     parser->m_processor = entityValueInitProcessor;
   4643   1.1      tron     return entityValueInitProcessor(parser, s, end, nextPtr);
   4644   1.8      maya   } else {
   4645   1.8      maya     parser->m_processor = externalParEntProcessor;
   4646   1.1      tron     return externalParEntProcessor(parser, s, end, nextPtr);
   4647   1.1      tron   }
   4648   1.1      tron }
   4649   1.1      tron 
   4650   1.1      tron static enum XML_Error PTRCALL
   4651   1.8      maya entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
   4652   1.8      maya                          const char **nextPtr) {
   4653   1.1      tron   int tok;
   4654   1.1      tron   const char *start = s;
   4655   1.1      tron   const char *next = start;
   4656   1.8      maya   parser->m_eventPtr = start;
   4657   1.1      tron 
   4658   1.3       spz   for (;;) {
   4659   1.8      maya     tok = XmlPrologTok(parser->m_encoding, start, end, &next);
   4660   1.9  christos     /* Note: Except for XML_TOK_BOM below, these bytes are accounted later in:
   4661   1.9  christos              - storeEntityValue
   4662   1.9  christos              - processXmlDecl
   4663   1.9  christos     */
   4664   1.8      maya     parser->m_eventEndPtr = next;
   4665   1.1      tron     if (tok <= 0) {
   4666   1.8      maya       if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
   4667   1.1      tron         *nextPtr = s;
   4668   1.1      tron         return XML_ERROR_NONE;
   4669   1.1      tron       }
   4670   1.1      tron       switch (tok) {
   4671   1.1      tron       case XML_TOK_INVALID:
   4672   1.1      tron         return XML_ERROR_INVALID_TOKEN;
   4673   1.1      tron       case XML_TOK_PARTIAL:
   4674   1.1      tron         return XML_ERROR_UNCLOSED_TOKEN;
   4675   1.1      tron       case XML_TOK_PARTIAL_CHAR:
   4676   1.1      tron         return XML_ERROR_PARTIAL_CHAR;
   4677   1.8      maya       case XML_TOK_NONE: /* start == end */
   4678   1.1      tron       default:
   4679   1.1      tron         break;
   4680   1.1      tron       }
   4681   1.1      tron       /* found end of entity value - can store it now */
   4682   1.9  christos       return storeEntityValue(parser, parser->m_encoding, s, end,
   4683  1.10       wiz                               XML_ACCOUNT_DIRECT, NULL);
   4684   1.8      maya     } else if (tok == XML_TOK_XML_DECL) {
   4685   1.1      tron       enum XML_Error result;
   4686   1.1      tron       result = processXmlDecl(parser, 0, start, next);
   4687   1.1      tron       if (result != XML_ERROR_NONE)
   4688   1.1      tron         return result;
   4689   1.8      maya       /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED.  For
   4690   1.8      maya        * that to happen, a parameter entity parsing handler must have attempted
   4691   1.8      maya        * to suspend the parser, which fails and raises an error.  The parser can
   4692   1.8      maya        * be aborted, but can't be suspended.
   4693   1.8      maya        */
   4694   1.8      maya       if (parser->m_parsingStatus.parsing == XML_FINISHED)
   4695   1.1      tron         return XML_ERROR_ABORTED;
   4696   1.8      maya       *nextPtr = next;
   4697   1.1      tron       /* stop scanning for text declaration - we found one */
   4698   1.8      maya       parser->m_processor = entityValueProcessor;
   4699   1.1      tron       return entityValueProcessor(parser, next, end, nextPtr);
   4700   1.1      tron     }
   4701  1.10       wiz     /* XmlPrologTok has now set the encoding based on the BOM it found, and we
   4702  1.10       wiz        must move s and nextPtr forward to consume the BOM.
   4703  1.10       wiz 
   4704  1.10       wiz        If we didn't, and got XML_TOK_NONE from the next XmlPrologTok call, we
   4705  1.10       wiz        would leave the BOM in the buffer and return. On the next call to this
   4706  1.10       wiz        function, our XmlPrologTok call would return XML_TOK_INVALID, since it
   4707  1.10       wiz        is not valid to have multiple BOMs.
   4708   1.1      tron     */
   4709  1.10       wiz     else if (tok == XML_TOK_BOM) {
   4710  1.10       wiz #  if XML_GE == 1
   4711   1.9  christos       if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
   4712   1.9  christos                                     XML_ACCOUNT_DIRECT)) {
   4713   1.9  christos         accountingOnAbort(parser);
   4714   1.9  christos         return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   4715   1.9  christos       }
   4716   1.9  christos #  endif
   4717   1.9  christos 
   4718   1.1      tron       *nextPtr = next;
   4719  1.10       wiz       s = next;
   4720   1.1      tron     }
   4721   1.7  christos     /* If we get this token, we have the start of what might be a
   4722   1.7  christos        normal tag, but not a declaration (i.e. it doesn't begin with
   4723   1.7  christos        "<!").  In a DTD context, that isn't legal.
   4724   1.7  christos     */
   4725   1.7  christos     else if (tok == XML_TOK_INSTANCE_START) {
   4726   1.7  christos       *nextPtr = next;
   4727   1.7  christos       return XML_ERROR_SYNTAX;
   4728   1.7  christos     }
   4729   1.1      tron     start = next;
   4730   1.8      maya     parser->m_eventPtr = start;
   4731   1.1      tron   }
   4732   1.1      tron }
   4733   1.1      tron 
   4734   1.1      tron static enum XML_Error PTRCALL
   4735   1.8      maya externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
   4736   1.8      maya                         const char **nextPtr) {
   4737   1.1      tron   const char *next = s;
   4738   1.1      tron   int tok;
   4739   1.1      tron 
   4740   1.8      maya   tok = XmlPrologTok(parser->m_encoding, s, end, &next);
   4741   1.1      tron   if (tok <= 0) {
   4742   1.8      maya     if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
   4743   1.1      tron       *nextPtr = s;
   4744   1.1      tron       return XML_ERROR_NONE;
   4745   1.1      tron     }
   4746   1.1      tron     switch (tok) {
   4747   1.1      tron     case XML_TOK_INVALID:
   4748   1.1      tron       return XML_ERROR_INVALID_TOKEN;
   4749   1.1      tron     case XML_TOK_PARTIAL:
   4750   1.1      tron       return XML_ERROR_UNCLOSED_TOKEN;
   4751   1.1      tron     case XML_TOK_PARTIAL_CHAR:
   4752   1.1      tron       return XML_ERROR_PARTIAL_CHAR;
   4753   1.8      maya     case XML_TOK_NONE: /* start == end */
   4754   1.1      tron     default:
   4755   1.1      tron       break;
   4756   1.1      tron     }
   4757   1.1      tron   }
   4758   1.1      tron   /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
   4759   1.1      tron      However, when parsing an external subset, doProlog will not accept a BOM
   4760   1.9  christos      as valid, and report a syntax error, so we have to skip the BOM, and
   4761   1.9  christos      account for the BOM bytes.
   4762   1.1      tron   */
   4763   1.1      tron   else if (tok == XML_TOK_BOM) {
   4764   1.9  christos     if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
   4765   1.9  christos                                   XML_ACCOUNT_DIRECT)) {
   4766   1.9  christos       accountingOnAbort(parser);
   4767   1.9  christos       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   4768   1.9  christos     }
   4769   1.9  christos 
   4770   1.1      tron     s = next;
   4771   1.8      maya     tok = XmlPrologTok(parser->m_encoding, s, end, &next);
   4772   1.1      tron   }
   4773   1.1      tron 
   4774   1.8      maya   parser->m_processor = prologProcessor;
   4775   1.8      maya   return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
   4776   1.9  christos                   (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
   4777   1.9  christos                   XML_ACCOUNT_DIRECT);
   4778   1.1      tron }
   4779   1.1      tron 
   4780   1.1      tron static enum XML_Error PTRCALL
   4781   1.8      maya entityValueProcessor(XML_Parser parser, const char *s, const char *end,
   4782   1.8      maya                      const char **nextPtr) {
   4783   1.1      tron   const char *start = s;
   4784   1.1      tron   const char *next = s;
   4785   1.8      maya   const ENCODING *enc = parser->m_encoding;
   4786   1.1      tron   int tok;
   4787   1.1      tron 
   4788   1.1      tron   for (;;) {
   4789   1.1      tron     tok = XmlPrologTok(enc, start, end, &next);
   4790   1.9  christos     /* Note: These bytes are accounted later in:
   4791   1.9  christos              - storeEntityValue
   4792   1.9  christos     */
   4793   1.1      tron     if (tok <= 0) {
   4794   1.8      maya       if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
   4795   1.1      tron         *nextPtr = s;
   4796   1.1      tron         return XML_ERROR_NONE;
   4797   1.1      tron       }
   4798   1.1      tron       switch (tok) {
   4799   1.1      tron       case XML_TOK_INVALID:
   4800   1.1      tron         return XML_ERROR_INVALID_TOKEN;
   4801   1.1      tron       case XML_TOK_PARTIAL:
   4802   1.1      tron         return XML_ERROR_UNCLOSED_TOKEN;
   4803   1.1      tron       case XML_TOK_PARTIAL_CHAR:
   4804   1.1      tron         return XML_ERROR_PARTIAL_CHAR;
   4805   1.8      maya       case XML_TOK_NONE: /* start == end */
   4806   1.1      tron       default:
   4807   1.1      tron         break;
   4808   1.1      tron       }
   4809   1.1      tron       /* found end of entity value - can store it now */
   4810  1.10       wiz       return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT, NULL);
   4811   1.1      tron     }
   4812   1.1      tron     start = next;
   4813   1.1      tron   }
   4814   1.1      tron }
   4815   1.1      tron 
   4816   1.1      tron #endif /* XML_DTD */
   4817   1.1      tron 
   4818   1.1      tron static enum XML_Error PTRCALL
   4819   1.8      maya prologProcessor(XML_Parser parser, const char *s, const char *end,
   4820   1.8      maya                 const char **nextPtr) {
   4821   1.1      tron   const char *next = s;
   4822   1.8      maya   int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
   4823   1.8      maya   return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
   4824   1.9  christos                   (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
   4825   1.9  christos                   XML_ACCOUNT_DIRECT);
   4826   1.1      tron }
   4827   1.1      tron 
   4828   1.1      tron static enum XML_Error
   4829   1.8      maya doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
   4830   1.8      maya          int tok, const char *next, const char **nextPtr, XML_Bool haveMore,
   4831   1.9  christos          XML_Bool allowClosingDoctype, enum XML_Account account) {
   4832   1.1      tron #ifdef XML_DTD
   4833   1.8      maya   static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
   4834   1.1      tron #endif /* XML_DTD */
   4835   1.8      maya   static const XML_Char atypeCDATA[]
   4836   1.8      maya       = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
   4837   1.8      maya   static const XML_Char atypeID[] = {ASCII_I, ASCII_D, '\0'};
   4838   1.8      maya   static const XML_Char atypeIDREF[]
   4839   1.8      maya       = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'};
   4840   1.8      maya   static const XML_Char atypeIDREFS[]
   4841   1.8      maya       = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0'};
   4842   1.8      maya   static const XML_Char atypeENTITY[]
   4843   1.8      maya       = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0'};
   4844   1.8      maya   static const XML_Char atypeENTITIES[]
   4845   1.8      maya       = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T,
   4846   1.8      maya          ASCII_I, ASCII_E, ASCII_S, '\0'};
   4847   1.8      maya   static const XML_Char atypeNMTOKEN[]
   4848   1.8      maya       = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0'};
   4849   1.8      maya   static const XML_Char atypeNMTOKENS[]
   4850   1.8      maya       = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K,
   4851   1.8      maya          ASCII_E, ASCII_N, ASCII_S, '\0'};
   4852   1.8      maya   static const XML_Char notationPrefix[]
   4853   1.8      maya       = {ASCII_N, ASCII_O, ASCII_T, ASCII_A,      ASCII_T,
   4854   1.8      maya          ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0'};
   4855   1.8      maya   static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
   4856   1.8      maya   static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
   4857   1.1      tron 
   4858   1.9  christos #ifndef XML_DTD
   4859   1.9  christos   UNUSED_P(account);
   4860   1.9  christos #endif
   4861   1.9  christos 
   4862   1.1      tron   /* save one level of indirection */
   4863   1.8      maya   DTD *const dtd = parser->m_dtd;
   4864   1.1      tron 
   4865   1.1      tron   const char **eventPP;
   4866   1.1      tron   const char **eventEndPP;
   4867   1.1      tron   enum XML_Content_Quant quant;
   4868   1.1      tron 
   4869   1.8      maya   if (enc == parser->m_encoding) {
   4870   1.8      maya     eventPP = &parser->m_eventPtr;
   4871   1.8      maya     eventEndPP = &parser->m_eventEndPtr;
   4872   1.8      maya   } else {
   4873   1.8      maya     eventPP = &(parser->m_openInternalEntities->internalEventPtr);
   4874   1.8      maya     eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
   4875   1.1      tron   }
   4876   1.1      tron 
   4877   1.1      tron   for (;;) {
   4878   1.1      tron     int role;
   4879   1.1      tron     XML_Bool handleDefault = XML_TRUE;
   4880   1.1      tron     *eventPP = s;
   4881   1.1      tron     *eventEndPP = next;
   4882   1.1      tron     if (tok <= 0) {
   4883   1.1      tron       if (haveMore && tok != XML_TOK_INVALID) {
   4884   1.1      tron         *nextPtr = s;
   4885   1.1      tron         return XML_ERROR_NONE;
   4886   1.1      tron       }
   4887   1.1      tron       switch (tok) {
   4888   1.1      tron       case XML_TOK_INVALID:
   4889   1.1      tron         *eventPP = next;
   4890   1.1      tron         return XML_ERROR_INVALID_TOKEN;
   4891   1.1      tron       case XML_TOK_PARTIAL:
   4892   1.1      tron         return XML_ERROR_UNCLOSED_TOKEN;
   4893   1.1      tron       case XML_TOK_PARTIAL_CHAR:
   4894   1.1      tron         return XML_ERROR_PARTIAL_CHAR;
   4895   1.2      tron       case -XML_TOK_PROLOG_S:
   4896   1.3       spz         tok = -tok;
   4897   1.3       spz         break;
   4898   1.1      tron       case XML_TOK_NONE:
   4899   1.1      tron #ifdef XML_DTD
   4900   1.1      tron         /* for internal PE NOT referenced between declarations */
   4901   1.8      maya         if (enc != parser->m_encoding
   4902   1.8      maya             && ! parser->m_openInternalEntities->betweenDecl) {
   4903   1.1      tron           *nextPtr = s;
   4904   1.1      tron           return XML_ERROR_NONE;
   4905   1.1      tron         }
   4906   1.1      tron         /* WFC: PE Between Declarations - must check that PE contains
   4907   1.1      tron            complete markup, not only for external PEs, but also for
   4908   1.1      tron            internal PEs if the reference occurs between declarations.
   4909   1.1      tron         */
   4910   1.8      maya         if (parser->m_isParamEntity || enc != parser->m_encoding) {
   4911   1.8      maya           if (XmlTokenRole(&parser->m_prologState, XML_TOK_NONE, end, end, enc)
   4912   1.1      tron               == XML_ROLE_ERROR)
   4913   1.1      tron             return XML_ERROR_INCOMPLETE_PE;
   4914   1.1      tron           *nextPtr = s;
   4915   1.1      tron           return XML_ERROR_NONE;
   4916   1.1      tron         }
   4917   1.1      tron #endif /* XML_DTD */
   4918   1.1      tron         return XML_ERROR_NO_ELEMENTS;
   4919   1.1      tron       default:
   4920   1.1      tron         tok = -tok;
   4921   1.1      tron         next = end;
   4922   1.1      tron         break;
   4923   1.1      tron       }
   4924   1.1      tron     }
   4925   1.8      maya     role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
   4926  1.10       wiz #if XML_GE == 1
   4927   1.9  christos     switch (role) {
   4928   1.9  christos     case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor
   4929   1.9  christos     case XML_ROLE_XML_DECL:       // bytes accounted in processXmlDecl
   4930  1.10       wiz #  ifdef XML_DTD
   4931  1.10       wiz     case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl
   4932  1.10       wiz #  endif
   4933   1.9  christos       break;
   4934   1.9  christos     default:
   4935   1.9  christos       if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
   4936   1.9  christos         accountingOnAbort(parser);
   4937   1.9  christos         return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   4938   1.9  christos       }
   4939   1.9  christos     }
   4940   1.9  christos #endif
   4941   1.1      tron     switch (role) {
   4942   1.8      maya     case XML_ROLE_XML_DECL: {
   4943   1.8      maya       enum XML_Error result = processXmlDecl(parser, 0, s, next);
   4944   1.8      maya       if (result != XML_ERROR_NONE)
   4945   1.8      maya         return result;
   4946   1.8      maya       enc = parser->m_encoding;
   4947   1.8      maya       handleDefault = XML_FALSE;
   4948   1.8      maya     } break;
   4949   1.1      tron     case XML_ROLE_DOCTYPE_NAME:
   4950   1.8      maya       if (parser->m_startDoctypeDeclHandler) {
   4951   1.8      maya         parser->m_doctypeName
   4952   1.8      maya             = poolStoreString(&parser->m_tempPool, enc, s, next);
   4953   1.8      maya         if (! parser->m_doctypeName)
   4954   1.1      tron           return XML_ERROR_NO_MEMORY;
   4955   1.8      maya         poolFinish(&parser->m_tempPool);
   4956   1.8      maya         parser->m_doctypePubid = NULL;
   4957   1.1      tron         handleDefault = XML_FALSE;
   4958   1.1      tron       }
   4959   1.8      maya       parser->m_doctypeSysid = NULL; /* always initialize to NULL */
   4960   1.1      tron       break;
   4961   1.1      tron     case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
   4962   1.8      maya       if (parser->m_startDoctypeDeclHandler) {
   4963   1.8      maya         parser->m_startDoctypeDeclHandler(
   4964   1.8      maya             parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
   4965   1.8      maya             parser->m_doctypePubid, 1);
   4966   1.8      maya         parser->m_doctypeName = NULL;
   4967   1.8      maya         poolClear(&parser->m_tempPool);
   4968   1.1      tron         handleDefault = XML_FALSE;
   4969   1.1      tron       }
   4970   1.1      tron       break;
   4971   1.1      tron #ifdef XML_DTD
   4972   1.8      maya     case XML_ROLE_TEXT_DECL: {
   4973   1.8      maya       enum XML_Error result = processXmlDecl(parser, 1, s, next);
   4974   1.8      maya       if (result != XML_ERROR_NONE)
   4975   1.8      maya         return result;
   4976   1.8      maya       enc = parser->m_encoding;
   4977   1.8      maya       handleDefault = XML_FALSE;
   4978   1.8      maya     } break;
   4979   1.1      tron #endif /* XML_DTD */
   4980   1.1      tron     case XML_ROLE_DOCTYPE_PUBLIC_ID:
   4981   1.1      tron #ifdef XML_DTD
   4982   1.8      maya       parser->m_useForeignDTD = XML_FALSE;
   4983   1.8      maya       parser->m_declEntity = (ENTITY *)lookup(
   4984   1.8      maya           parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
   4985   1.8      maya       if (! parser->m_declEntity)
   4986   1.1      tron         return XML_ERROR_NO_MEMORY;
   4987   1.1      tron #endif /* XML_DTD */
   4988   1.1      tron       dtd->hasParamEntityRefs = XML_TRUE;
   4989   1.8      maya       if (parser->m_startDoctypeDeclHandler) {
   4990   1.3       spz         XML_Char *pubId;
   4991   1.8      maya         if (! XmlIsPublicId(enc, s, next, eventPP))
   4992   1.1      tron           return XML_ERROR_PUBLICID;
   4993   1.8      maya         pubId = poolStoreString(&parser->m_tempPool, enc,
   4994   1.3       spz                                 s + enc->minBytesPerChar,
   4995   1.3       spz                                 next - enc->minBytesPerChar);
   4996   1.8      maya         if (! pubId)
   4997   1.1      tron           return XML_ERROR_NO_MEMORY;
   4998   1.3       spz         normalizePublicId(pubId);
   4999   1.8      maya         poolFinish(&parser->m_tempPool);
   5000   1.8      maya         parser->m_doctypePubid = pubId;
   5001   1.1      tron         handleDefault = XML_FALSE;
   5002   1.1      tron         goto alreadyChecked;
   5003   1.1      tron       }
   5004   1.1      tron       /* fall through */
   5005   1.1      tron     case XML_ROLE_ENTITY_PUBLIC_ID:
   5006   1.8      maya       if (! XmlIsPublicId(enc, s, next, eventPP))
   5007   1.1      tron         return XML_ERROR_PUBLICID;
   5008   1.1      tron     alreadyChecked:
   5009   1.8      maya       if (dtd->keepProcessing && parser->m_declEntity) {
   5010   1.8      maya         XML_Char *tem
   5011   1.8      maya             = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
   5012   1.8      maya                               next - enc->minBytesPerChar);
   5013   1.8      maya         if (! tem)
   5014   1.1      tron           return XML_ERROR_NO_MEMORY;
   5015   1.1      tron         normalizePublicId(tem);
   5016   1.8      maya         parser->m_declEntity->publicId = tem;
   5017   1.1      tron         poolFinish(&dtd->pool);
   5018   1.8      maya         /* Don't suppress the default handler if we fell through from
   5019   1.8      maya          * the XML_ROLE_DOCTYPE_PUBLIC_ID case.
   5020   1.8      maya          */
   5021   1.8      maya         if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID)
   5022   1.1      tron           handleDefault = XML_FALSE;
   5023   1.1      tron       }
   5024   1.1      tron       break;
   5025   1.1      tron     case XML_ROLE_DOCTYPE_CLOSE:
   5026   1.8      maya       if (allowClosingDoctype != XML_TRUE) {
   5027   1.8      maya         /* Must not close doctype from within expanded parameter entities */
   5028   1.8      maya         return XML_ERROR_INVALID_TOKEN;
   5029   1.8      maya       }
   5030   1.8      maya 
   5031   1.8      maya       if (parser->m_doctypeName) {
   5032   1.8      maya         parser->m_startDoctypeDeclHandler(
   5033   1.8      maya             parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
   5034   1.8      maya             parser->m_doctypePubid, 0);
   5035   1.8      maya         poolClear(&parser->m_tempPool);
   5036   1.1      tron         handleDefault = XML_FALSE;
   5037   1.1      tron       }
   5038   1.8      maya       /* parser->m_doctypeSysid will be non-NULL in the case of a previous
   5039   1.8      maya          XML_ROLE_DOCTYPE_SYSTEM_ID, even if parser->m_startDoctypeDeclHandler
   5040   1.1      tron          was not set, indicating an external subset
   5041   1.1      tron       */
   5042   1.1      tron #ifdef XML_DTD
   5043   1.8      maya       if (parser->m_doctypeSysid || parser->m_useForeignDTD) {
   5044   1.1      tron         XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
   5045   1.1      tron         dtd->hasParamEntityRefs = XML_TRUE;
   5046   1.8      maya         if (parser->m_paramEntityParsing
   5047   1.8      maya             && parser->m_externalEntityRefHandler) {
   5048   1.8      maya           ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
   5049   1.8      maya                                             externalSubsetName, sizeof(ENTITY));
   5050   1.8      maya           if (! entity) {
   5051   1.8      maya             /* The external subset name "#" will have already been
   5052   1.8      maya              * inserted into the hash table at the start of the
   5053   1.8      maya              * external entity parsing, so no allocation will happen
   5054   1.8      maya              * and lookup() cannot fail.
   5055   1.8      maya              */
   5056   1.8      maya             return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
   5057   1.8      maya           }
   5058   1.8      maya           if (parser->m_useForeignDTD)
   5059   1.8      maya             entity->base = parser->m_curBase;
   5060   1.1      tron           dtd->paramEntityRead = XML_FALSE;
   5061   1.8      maya           if (! parser->m_externalEntityRefHandler(
   5062   1.8      maya                   parser->m_externalEntityRefHandlerArg, 0, entity->base,
   5063   1.8      maya                   entity->systemId, entity->publicId))
   5064   1.1      tron             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   5065   1.1      tron           if (dtd->paramEntityRead) {
   5066   1.8      maya             if (! dtd->standalone && parser->m_notStandaloneHandler
   5067   1.8      maya                 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
   5068   1.1      tron               return XML_ERROR_NOT_STANDALONE;
   5069   1.1      tron           }
   5070   1.1      tron           /* if we didn't read the foreign DTD then this means that there
   5071   1.1      tron              is no external subset and we must reset dtd->hasParamEntityRefs
   5072   1.1      tron           */
   5073   1.8      maya           else if (! parser->m_doctypeSysid)
   5074   1.1      tron             dtd->hasParamEntityRefs = hadParamEntityRefs;
   5075   1.1      tron           /* end of DTD - no need to update dtd->keepProcessing */
   5076   1.1      tron         }
   5077   1.8      maya         parser->m_useForeignDTD = XML_FALSE;
   5078   1.1      tron       }
   5079   1.1      tron #endif /* XML_DTD */
   5080   1.8      maya       if (parser->m_endDoctypeDeclHandler) {
   5081   1.8      maya         parser->m_endDoctypeDeclHandler(parser->m_handlerArg);
   5082   1.1      tron         handleDefault = XML_FALSE;
   5083   1.1      tron       }
   5084   1.1      tron       break;
   5085   1.1      tron     case XML_ROLE_INSTANCE_START:
   5086   1.1      tron #ifdef XML_DTD
   5087   1.1      tron       /* if there is no DOCTYPE declaration then now is the
   5088   1.1      tron          last chance to read the foreign DTD
   5089   1.1      tron       */
   5090   1.8      maya       if (parser->m_useForeignDTD) {
   5091   1.1      tron         XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
   5092   1.1      tron         dtd->hasParamEntityRefs = XML_TRUE;
   5093   1.8      maya         if (parser->m_paramEntityParsing
   5094   1.8      maya             && parser->m_externalEntityRefHandler) {
   5095   1.3       spz           ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
   5096   1.8      maya                                             externalSubsetName, sizeof(ENTITY));
   5097   1.8      maya           if (! entity)
   5098   1.1      tron             return XML_ERROR_NO_MEMORY;
   5099   1.8      maya           entity->base = parser->m_curBase;
   5100   1.1      tron           dtd->paramEntityRead = XML_FALSE;
   5101   1.8      maya           if (! parser->m_externalEntityRefHandler(
   5102   1.8      maya                   parser->m_externalEntityRefHandlerArg, 0, entity->base,
   5103   1.8      maya                   entity->systemId, entity->publicId))
   5104   1.1      tron             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   5105   1.1      tron           if (dtd->paramEntityRead) {
   5106   1.8      maya             if (! dtd->standalone && parser->m_notStandaloneHandler
   5107   1.8      maya                 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
   5108   1.1      tron               return XML_ERROR_NOT_STANDALONE;
   5109   1.1      tron           }
   5110   1.1      tron           /* if we didn't read the foreign DTD then this means that there
   5111   1.1      tron              is no external subset and we must reset dtd->hasParamEntityRefs
   5112   1.1      tron           */
   5113   1.1      tron           else
   5114   1.1      tron             dtd->hasParamEntityRefs = hadParamEntityRefs;
   5115   1.1      tron           /* end of DTD - no need to update dtd->keepProcessing */
   5116   1.1      tron         }
   5117   1.1      tron       }
   5118   1.1      tron #endif /* XML_DTD */
   5119   1.8      maya       parser->m_processor = contentProcessor;
   5120   1.1      tron       return contentProcessor(parser, s, end, nextPtr);
   5121   1.1      tron     case XML_ROLE_ATTLIST_ELEMENT_NAME:
   5122   1.8      maya       parser->m_declElementType = getElementType(parser, enc, s, next);
   5123   1.8      maya       if (! parser->m_declElementType)
   5124   1.1      tron         return XML_ERROR_NO_MEMORY;
   5125   1.1      tron       goto checkAttListDeclHandler;
   5126   1.1      tron     case XML_ROLE_ATTRIBUTE_NAME:
   5127   1.8      maya       parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
   5128   1.8      maya       if (! parser->m_declAttributeId)
   5129   1.1      tron         return XML_ERROR_NO_MEMORY;
   5130   1.8      maya       parser->m_declAttributeIsCdata = XML_FALSE;
   5131   1.8      maya       parser->m_declAttributeType = NULL;
   5132   1.8      maya       parser->m_declAttributeIsId = XML_FALSE;
   5133   1.1      tron       goto checkAttListDeclHandler;
   5134   1.1      tron     case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
   5135   1.8      maya       parser->m_declAttributeIsCdata = XML_TRUE;
   5136   1.8      maya       parser->m_declAttributeType = atypeCDATA;
   5137   1.1      tron       goto checkAttListDeclHandler;
   5138   1.1      tron     case XML_ROLE_ATTRIBUTE_TYPE_ID:
   5139   1.8      maya       parser->m_declAttributeIsId = XML_TRUE;
   5140   1.8      maya       parser->m_declAttributeType = atypeID;
   5141   1.1      tron       goto checkAttListDeclHandler;
   5142   1.1      tron     case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
   5143   1.8      maya       parser->m_declAttributeType = atypeIDREF;
   5144   1.1      tron       goto checkAttListDeclHandler;
   5145   1.1      tron     case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
   5146   1.8      maya       parser->m_declAttributeType = atypeIDREFS;
   5147   1.1      tron       goto checkAttListDeclHandler;
   5148   1.1      tron     case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
   5149   1.8      maya       parser->m_declAttributeType = atypeENTITY;
   5150   1.1      tron       goto checkAttListDeclHandler;
   5151   1.1      tron     case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
   5152   1.8      maya       parser->m_declAttributeType = atypeENTITIES;
   5153   1.1      tron       goto checkAttListDeclHandler;
   5154   1.1      tron     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
   5155   1.8      maya       parser->m_declAttributeType = atypeNMTOKEN;
   5156   1.1      tron       goto checkAttListDeclHandler;
   5157   1.1      tron     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
   5158   1.8      maya       parser->m_declAttributeType = atypeNMTOKENS;
   5159   1.1      tron     checkAttListDeclHandler:
   5160   1.8      maya       if (dtd->keepProcessing && parser->m_attlistDeclHandler)
   5161   1.1      tron         handleDefault = XML_FALSE;
   5162   1.1      tron       break;
   5163   1.1      tron     case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
   5164   1.1      tron     case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
   5165   1.8      maya       if (dtd->keepProcessing && parser->m_attlistDeclHandler) {
   5166   1.1      tron         const XML_Char *prefix;
   5167   1.8      maya         if (parser->m_declAttributeType) {
   5168   1.1      tron           prefix = enumValueSep;
   5169   1.8      maya         } else {
   5170   1.8      maya           prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE ? notationPrefix
   5171   1.8      maya                                                               : enumValueStart);
   5172   1.1      tron         }
   5173   1.8      maya         if (! poolAppendString(&parser->m_tempPool, prefix))
   5174   1.1      tron           return XML_ERROR_NO_MEMORY;
   5175   1.8      maya         if (! poolAppend(&parser->m_tempPool, enc, s, next))
   5176   1.1      tron           return XML_ERROR_NO_MEMORY;
   5177   1.8      maya         parser->m_declAttributeType = parser->m_tempPool.start;
   5178   1.1      tron         handleDefault = XML_FALSE;
   5179   1.1      tron       }
   5180   1.1      tron       break;
   5181   1.1      tron     case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
   5182   1.1      tron     case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
   5183   1.1      tron       if (dtd->keepProcessing) {
   5184   1.8      maya         if (! defineAttribute(parser->m_declElementType,
   5185   1.8      maya                               parser->m_declAttributeId,
   5186   1.8      maya                               parser->m_declAttributeIsCdata,
   5187   1.8      maya                               parser->m_declAttributeIsId, 0, parser))
   5188   1.1      tron           return XML_ERROR_NO_MEMORY;
   5189   1.8      maya         if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
   5190   1.8      maya           if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
   5191   1.8      maya               || (*parser->m_declAttributeType == XML_T(ASCII_N)
   5192   1.8      maya                   && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
   5193   1.1      tron             /* Enumerated or Notation type */
   5194   1.8      maya             if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
   5195   1.8      maya                 || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
   5196   1.1      tron               return XML_ERROR_NO_MEMORY;
   5197   1.8      maya             parser->m_declAttributeType = parser->m_tempPool.start;
   5198   1.8      maya             poolFinish(&parser->m_tempPool);
   5199   1.1      tron           }
   5200   1.1      tron           *eventEndPP = s;
   5201   1.8      maya           parser->m_attlistDeclHandler(
   5202   1.8      maya               parser->m_handlerArg, parser->m_declElementType->name,
   5203   1.8      maya               parser->m_declAttributeId->name, parser->m_declAttributeType, 0,
   5204   1.8      maya               role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
   5205   1.1      tron           handleDefault = XML_FALSE;
   5206   1.1      tron         }
   5207   1.1      tron       }
   5208  1.10       wiz       poolClear(&parser->m_tempPool);
   5209   1.1      tron       break;
   5210   1.1      tron     case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
   5211   1.1      tron     case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
   5212   1.1      tron       if (dtd->keepProcessing) {
   5213   1.1      tron         const XML_Char *attVal;
   5214   1.8      maya         enum XML_Error result = storeAttributeValue(
   5215   1.8      maya             parser, enc, parser->m_declAttributeIsCdata,
   5216   1.9  christos             s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool,
   5217   1.9  christos             XML_ACCOUNT_NONE);
   5218   1.1      tron         if (result)
   5219   1.1      tron           return result;
   5220   1.1      tron         attVal = poolStart(&dtd->pool);
   5221   1.1      tron         poolFinish(&dtd->pool);
   5222   1.1      tron         /* ID attributes aren't allowed to have a default */
   5223   1.8      maya         if (! defineAttribute(
   5224   1.8      maya                 parser->m_declElementType, parser->m_declAttributeId,
   5225   1.8      maya                 parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
   5226   1.1      tron           return XML_ERROR_NO_MEMORY;
   5227   1.8      maya         if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
   5228   1.8      maya           if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
   5229   1.8      maya               || (*parser->m_declAttributeType == XML_T(ASCII_N)
   5230   1.8      maya                   && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
   5231   1.1      tron             /* Enumerated or Notation type */
   5232   1.8      maya             if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
   5233   1.8      maya                 || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
   5234   1.1      tron               return XML_ERROR_NO_MEMORY;
   5235   1.8      maya             parser->m_declAttributeType = parser->m_tempPool.start;
   5236   1.8      maya             poolFinish(&parser->m_tempPool);
   5237   1.1      tron           }
   5238   1.1      tron           *eventEndPP = s;
   5239   1.8      maya           parser->m_attlistDeclHandler(
   5240   1.8      maya               parser->m_handlerArg, parser->m_declElementType->name,
   5241   1.8      maya               parser->m_declAttributeId->name, parser->m_declAttributeType,
   5242   1.8      maya               attVal, role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
   5243   1.8      maya           poolClear(&parser->m_tempPool);
   5244   1.1      tron           handleDefault = XML_FALSE;
   5245   1.1      tron         }
   5246   1.1      tron       }
   5247   1.1      tron       break;
   5248   1.1      tron     case XML_ROLE_ENTITY_VALUE:
   5249   1.1      tron       if (dtd->keepProcessing) {
   5250  1.10       wiz #if XML_GE == 1
   5251  1.10       wiz         // This will store the given replacement text in
   5252  1.10       wiz         // parser->m_declEntity->textPtr.
   5253  1.10       wiz         enum XML_Error result = callStoreEntityValue(
   5254  1.10       wiz             parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar,
   5255  1.10       wiz             XML_ACCOUNT_NONE);
   5256   1.8      maya         if (parser->m_declEntity) {
   5257   1.8      maya           parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
   5258   1.8      maya           parser->m_declEntity->textLen
   5259   1.8      maya               = (int)(poolLength(&dtd->entityValuePool));
   5260   1.1      tron           poolFinish(&dtd->entityValuePool);
   5261   1.8      maya           if (parser->m_entityDeclHandler) {
   5262   1.1      tron             *eventEndPP = s;
   5263   1.8      maya             parser->m_entityDeclHandler(
   5264   1.8      maya                 parser->m_handlerArg, parser->m_declEntity->name,
   5265   1.8      maya                 parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
   5266   1.8      maya                 parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
   5267   1.1      tron             handleDefault = XML_FALSE;
   5268   1.1      tron           }
   5269   1.8      maya         } else
   5270   1.1      tron           poolDiscard(&dtd->entityValuePool);
   5271   1.1      tron         if (result != XML_ERROR_NONE)
   5272   1.1      tron           return result;
   5273  1.10       wiz #else
   5274  1.10       wiz         // This will store "&amp;entity123;" in parser->m_declEntity->textPtr
   5275  1.10       wiz         // to end up as "&entity123;" in the handler.
   5276  1.10       wiz         if (parser->m_declEntity != NULL) {
   5277  1.10       wiz           const enum XML_Error result
   5278  1.10       wiz               = storeSelfEntityValue(parser, parser->m_declEntity);
   5279  1.10       wiz           if (result != XML_ERROR_NONE)
   5280  1.10       wiz             return result;
   5281  1.10       wiz 
   5282  1.10       wiz           if (parser->m_entityDeclHandler) {
   5283  1.10       wiz             *eventEndPP = s;
   5284  1.10       wiz             parser->m_entityDeclHandler(
   5285  1.10       wiz                 parser->m_handlerArg, parser->m_declEntity->name,
   5286  1.10       wiz                 parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
   5287  1.10       wiz                 parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
   5288  1.10       wiz             handleDefault = XML_FALSE;
   5289  1.10       wiz           }
   5290  1.10       wiz         }
   5291  1.10       wiz #endif
   5292   1.1      tron       }
   5293   1.1      tron       break;
   5294   1.1      tron     case XML_ROLE_DOCTYPE_SYSTEM_ID:
   5295   1.1      tron #ifdef XML_DTD
   5296   1.8      maya       parser->m_useForeignDTD = XML_FALSE;
   5297   1.1      tron #endif /* XML_DTD */
   5298   1.1      tron       dtd->hasParamEntityRefs = XML_TRUE;
   5299   1.8      maya       if (parser->m_startDoctypeDeclHandler) {
   5300   1.8      maya         parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc,
   5301   1.8      maya                                                  s + enc->minBytesPerChar,
   5302   1.8      maya                                                  next - enc->minBytesPerChar);
   5303   1.8      maya         if (parser->m_doctypeSysid == NULL)
   5304   1.1      tron           return XML_ERROR_NO_MEMORY;
   5305   1.8      maya         poolFinish(&parser->m_tempPool);
   5306   1.1      tron         handleDefault = XML_FALSE;
   5307   1.1      tron       }
   5308   1.1      tron #ifdef XML_DTD
   5309   1.1      tron       else
   5310   1.8      maya         /* use externalSubsetName to make parser->m_doctypeSysid non-NULL
   5311   1.8      maya            for the case where no parser->m_startDoctypeDeclHandler is set */
   5312   1.8      maya         parser->m_doctypeSysid = externalSubsetName;
   5313   1.1      tron #endif /* XML_DTD */
   5314   1.8      maya       if (! dtd->standalone
   5315   1.1      tron #ifdef XML_DTD
   5316   1.8      maya           && ! parser->m_paramEntityParsing
   5317   1.1      tron #endif /* XML_DTD */
   5318   1.8      maya           && parser->m_notStandaloneHandler
   5319   1.8      maya           && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
   5320   1.1      tron         return XML_ERROR_NOT_STANDALONE;
   5321   1.1      tron #ifndef XML_DTD
   5322   1.1      tron       break;
   5323   1.8      maya #else  /* XML_DTD */
   5324   1.8      maya       if (! parser->m_declEntity) {
   5325   1.8      maya         parser->m_declEntity = (ENTITY *)lookup(
   5326   1.8      maya             parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
   5327   1.8      maya         if (! parser->m_declEntity)
   5328   1.1      tron           return XML_ERROR_NO_MEMORY;
   5329   1.8      maya         parser->m_declEntity->publicId = NULL;
   5330   1.1      tron       }
   5331   1.8      maya #endif /* XML_DTD */
   5332   1.1      tron       /* fall through */
   5333   1.1      tron     case XML_ROLE_ENTITY_SYSTEM_ID:
   5334   1.8      maya       if (dtd->keepProcessing && parser->m_declEntity) {
   5335   1.8      maya         parser->m_declEntity->systemId
   5336   1.8      maya             = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
   5337   1.8      maya                               next - enc->minBytesPerChar);
   5338   1.8      maya         if (! parser->m_declEntity->systemId)
   5339   1.1      tron           return XML_ERROR_NO_MEMORY;
   5340   1.8      maya         parser->m_declEntity->base = parser->m_curBase;
   5341   1.1      tron         poolFinish(&dtd->pool);
   5342   1.8      maya         /* Don't suppress the default handler if we fell through from
   5343   1.8      maya          * the XML_ROLE_DOCTYPE_SYSTEM_ID case.
   5344   1.8      maya          */
   5345   1.8      maya         if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID)
   5346   1.1      tron           handleDefault = XML_FALSE;
   5347   1.1      tron       }
   5348   1.1      tron       break;
   5349   1.1      tron     case XML_ROLE_ENTITY_COMPLETE:
   5350  1.10       wiz #if XML_GE == 0
   5351  1.10       wiz       // This will store "&amp;entity123;" in entity->textPtr
   5352  1.10       wiz       // to end up as "&entity123;" in the handler.
   5353  1.10       wiz       if (parser->m_declEntity != NULL) {
   5354  1.10       wiz         const enum XML_Error result
   5355  1.10       wiz             = storeSelfEntityValue(parser, parser->m_declEntity);
   5356  1.10       wiz         if (result != XML_ERROR_NONE)
   5357  1.10       wiz           return result;
   5358  1.10       wiz       }
   5359  1.10       wiz #endif
   5360   1.8      maya       if (dtd->keepProcessing && parser->m_declEntity
   5361   1.8      maya           && parser->m_entityDeclHandler) {
   5362   1.1      tron         *eventEndPP = s;
   5363   1.8      maya         parser->m_entityDeclHandler(
   5364   1.8      maya             parser->m_handlerArg, parser->m_declEntity->name,
   5365   1.8      maya             parser->m_declEntity->is_param, 0, 0, parser->m_declEntity->base,
   5366   1.8      maya             parser->m_declEntity->systemId, parser->m_declEntity->publicId, 0);
   5367   1.1      tron         handleDefault = XML_FALSE;
   5368   1.1      tron       }
   5369   1.1      tron       break;
   5370   1.1      tron     case XML_ROLE_ENTITY_NOTATION_NAME:
   5371   1.8      maya       if (dtd->keepProcessing && parser->m_declEntity) {
   5372   1.8      maya         parser->m_declEntity->notation
   5373   1.8      maya             = poolStoreString(&dtd->pool, enc, s, next);
   5374   1.8      maya         if (! parser->m_declEntity->notation)
   5375   1.1      tron           return XML_ERROR_NO_MEMORY;
   5376   1.1      tron         poolFinish(&dtd->pool);
   5377   1.8      maya         if (parser->m_unparsedEntityDeclHandler) {
   5378   1.1      tron           *eventEndPP = s;
   5379   1.8      maya           parser->m_unparsedEntityDeclHandler(
   5380   1.8      maya               parser->m_handlerArg, parser->m_declEntity->name,
   5381   1.8      maya               parser->m_declEntity->base, parser->m_declEntity->systemId,
   5382   1.8      maya               parser->m_declEntity->publicId, parser->m_declEntity->notation);
   5383   1.1      tron           handleDefault = XML_FALSE;
   5384   1.8      maya         } else if (parser->m_entityDeclHandler) {
   5385   1.1      tron           *eventEndPP = s;
   5386   1.8      maya           parser->m_entityDeclHandler(
   5387   1.8      maya               parser->m_handlerArg, parser->m_declEntity->name, 0, 0, 0,
   5388   1.8      maya               parser->m_declEntity->base, parser->m_declEntity->systemId,
   5389   1.8      maya               parser->m_declEntity->publicId, parser->m_declEntity->notation);
   5390   1.1      tron           handleDefault = XML_FALSE;
   5391   1.1      tron         }
   5392   1.1      tron       }
   5393   1.1      tron       break;
   5394   1.8      maya     case XML_ROLE_GENERAL_ENTITY_NAME: {
   5395   1.8      maya       if (XmlPredefinedEntityName(enc, s, next)) {
   5396   1.8      maya         parser->m_declEntity = NULL;
   5397   1.8      maya         break;
   5398   1.8      maya       }
   5399   1.8      maya       if (dtd->keepProcessing) {
   5400   1.8      maya         const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
   5401   1.8      maya         if (! name)
   5402   1.8      maya           return XML_ERROR_NO_MEMORY;
   5403   1.8      maya         parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities,
   5404   1.8      maya                                                 name, sizeof(ENTITY));
   5405   1.8      maya         if (! parser->m_declEntity)
   5406   1.8      maya           return XML_ERROR_NO_MEMORY;
   5407   1.8      maya         if (parser->m_declEntity->name != name) {
   5408   1.1      tron           poolDiscard(&dtd->pool);
   5409   1.8      maya           parser->m_declEntity = NULL;
   5410   1.8      maya         } else {
   5411   1.8      maya           poolFinish(&dtd->pool);
   5412   1.8      maya           parser->m_declEntity->publicId = NULL;
   5413   1.8      maya           parser->m_declEntity->is_param = XML_FALSE;
   5414   1.8      maya           /* if we have a parent parser or are reading an internal parameter
   5415   1.8      maya              entity, then the entity declaration is not considered "internal"
   5416   1.8      maya           */
   5417   1.8      maya           parser->m_declEntity->is_internal
   5418   1.8      maya               = ! (parser->m_parentParser || parser->m_openInternalEntities);
   5419   1.8      maya           if (parser->m_entityDeclHandler)
   5420   1.8      maya             handleDefault = XML_FALSE;
   5421   1.1      tron         }
   5422   1.8      maya       } else {
   5423   1.8      maya         poolDiscard(&dtd->pool);
   5424   1.8      maya         parser->m_declEntity = NULL;
   5425   1.1      tron       }
   5426   1.8      maya     } break;
   5427   1.1      tron     case XML_ROLE_PARAM_ENTITY_NAME:
   5428   1.1      tron #ifdef XML_DTD
   5429   1.1      tron       if (dtd->keepProcessing) {
   5430   1.1      tron         const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
   5431   1.8      maya         if (! name)
   5432   1.1      tron           return XML_ERROR_NO_MEMORY;
   5433   1.8      maya         parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
   5434   1.8      maya                                                 name, sizeof(ENTITY));
   5435   1.8      maya         if (! parser->m_declEntity)
   5436   1.1      tron           return XML_ERROR_NO_MEMORY;
   5437   1.8      maya         if (parser->m_declEntity->name != name) {
   5438   1.1      tron           poolDiscard(&dtd->pool);
   5439   1.8      maya           parser->m_declEntity = NULL;
   5440   1.8      maya         } else {
   5441   1.1      tron           poolFinish(&dtd->pool);
   5442   1.8      maya           parser->m_declEntity->publicId = NULL;
   5443   1.8      maya           parser->m_declEntity->is_param = XML_TRUE;
   5444   1.1      tron           /* if we have a parent parser or are reading an internal parameter
   5445   1.1      tron              entity, then the entity declaration is not considered "internal"
   5446   1.1      tron           */
   5447   1.8      maya           parser->m_declEntity->is_internal
   5448   1.8      maya               = ! (parser->m_parentParser || parser->m_openInternalEntities);
   5449   1.8      maya           if (parser->m_entityDeclHandler)
   5450   1.1      tron             handleDefault = XML_FALSE;
   5451   1.1      tron         }
   5452   1.8      maya       } else {
   5453   1.1      tron         poolDiscard(&dtd->pool);
   5454   1.8      maya         parser->m_declEntity = NULL;
   5455   1.1      tron       }
   5456   1.8      maya #else  /* not XML_DTD */
   5457   1.8      maya       parser->m_declEntity = NULL;
   5458   1.1      tron #endif /* XML_DTD */
   5459   1.1      tron       break;
   5460   1.1      tron     case XML_ROLE_NOTATION_NAME:
   5461   1.8      maya       parser->m_declNotationPublicId = NULL;
   5462   1.8      maya       parser->m_declNotationName = NULL;
   5463   1.8      maya       if (parser->m_notationDeclHandler) {
   5464   1.8      maya         parser->m_declNotationName
   5465   1.8      maya             = poolStoreString(&parser->m_tempPool, enc, s, next);
   5466   1.8      maya         if (! parser->m_declNotationName)
   5467   1.1      tron           return XML_ERROR_NO_MEMORY;
   5468   1.8      maya         poolFinish(&parser->m_tempPool);
   5469   1.1      tron         handleDefault = XML_FALSE;
   5470   1.1      tron       }
   5471   1.1      tron       break;
   5472   1.1      tron     case XML_ROLE_NOTATION_PUBLIC_ID:
   5473   1.8      maya       if (! XmlIsPublicId(enc, s, next, eventPP))
   5474   1.1      tron         return XML_ERROR_PUBLICID;
   5475   1.8      maya       if (parser
   5476   1.8      maya               ->m_declNotationName) { /* means m_notationDeclHandler != NULL */
   5477   1.8      maya         XML_Char *tem = poolStoreString(&parser->m_tempPool, enc,
   5478   1.1      tron                                         s + enc->minBytesPerChar,
   5479   1.1      tron                                         next - enc->minBytesPerChar);
   5480   1.8      maya         if (! tem)
   5481   1.1      tron           return XML_ERROR_NO_MEMORY;
   5482   1.1      tron         normalizePublicId(tem);
   5483   1.8      maya         parser->m_declNotationPublicId = tem;
   5484   1.8      maya         poolFinish(&parser->m_tempPool);
   5485   1.1      tron         handleDefault = XML_FALSE;
   5486   1.1      tron       }
   5487   1.1      tron       break;
   5488   1.1      tron     case XML_ROLE_NOTATION_SYSTEM_ID:
   5489   1.8      maya       if (parser->m_declNotationName && parser->m_notationDeclHandler) {
   5490   1.8      maya         const XML_Char *systemId = poolStoreString(&parser->m_tempPool, enc,
   5491   1.8      maya                                                    s + enc->minBytesPerChar,
   5492   1.8      maya                                                    next - enc->minBytesPerChar);
   5493   1.8      maya         if (! systemId)
   5494   1.1      tron           return XML_ERROR_NO_MEMORY;
   5495   1.1      tron         *eventEndPP = s;
   5496   1.8      maya         parser->m_notationDeclHandler(
   5497   1.8      maya             parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
   5498   1.8      maya             systemId, parser->m_declNotationPublicId);
   5499   1.1      tron         handleDefault = XML_FALSE;
   5500   1.1      tron       }
   5501   1.8      maya       poolClear(&parser->m_tempPool);
   5502   1.1      tron       break;
   5503   1.1      tron     case XML_ROLE_NOTATION_NO_SYSTEM_ID:
   5504   1.8      maya       if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) {
   5505   1.1      tron         *eventEndPP = s;
   5506   1.8      maya         parser->m_notationDeclHandler(
   5507   1.8      maya             parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
   5508   1.8      maya             0, parser->m_declNotationPublicId);
   5509   1.1      tron         handleDefault = XML_FALSE;
   5510   1.1      tron       }
   5511   1.8      maya       poolClear(&parser->m_tempPool);
   5512   1.1      tron       break;
   5513   1.1      tron     case XML_ROLE_ERROR:
   5514   1.1      tron       switch (tok) {
   5515   1.1      tron       case XML_TOK_PARAM_ENTITY_REF:
   5516   1.1      tron         /* PE references in internal subset are
   5517   1.3       spz            not allowed within declarations. */
   5518   1.1      tron         return XML_ERROR_PARAM_ENTITY_REF;
   5519   1.1      tron       case XML_TOK_XML_DECL:
   5520   1.1      tron         return XML_ERROR_MISPLACED_XML_PI;
   5521   1.1      tron       default:
   5522   1.1      tron         return XML_ERROR_SYNTAX;
   5523   1.1      tron       }
   5524   1.1      tron #ifdef XML_DTD
   5525   1.8      maya     case XML_ROLE_IGNORE_SECT: {
   5526   1.8      maya       enum XML_Error result;
   5527   1.8      maya       if (parser->m_defaultHandler)
   5528   1.8      maya         reportDefault(parser, enc, s, next);
   5529   1.8      maya       handleDefault = XML_FALSE;
   5530   1.8      maya       result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
   5531   1.8      maya       if (result != XML_ERROR_NONE)
   5532   1.8      maya         return result;
   5533   1.8      maya       else if (! next) {
   5534   1.8      maya         parser->m_processor = ignoreSectionProcessor;
   5535   1.8      maya         return result;
   5536   1.1      tron       }
   5537   1.8      maya     } break;
   5538   1.1      tron #endif /* XML_DTD */
   5539   1.1      tron     case XML_ROLE_GROUP_OPEN:
   5540   1.8      maya       if (parser->m_prologState.level >= parser->m_groupSize) {
   5541   1.8      maya         if (parser->m_groupSize) {
   5542   1.8      maya           {
   5543   1.9  christos             /* Detect and prevent integer overflow */
   5544   1.9  christos             if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
   5545   1.9  christos               return XML_ERROR_NO_MEMORY;
   5546   1.9  christos             }
   5547   1.9  christos 
   5548   1.8      maya             char *const new_connector = (char *)REALLOC(
   5549   1.8      maya                 parser, parser->m_groupConnector, parser->m_groupSize *= 2);
   5550   1.8      maya             if (new_connector == NULL) {
   5551   1.8      maya               parser->m_groupSize /= 2;
   5552   1.8      maya               return XML_ERROR_NO_MEMORY;
   5553   1.8      maya             }
   5554   1.8      maya             parser->m_groupConnector = new_connector;
   5555   1.8      maya           }
   5556   1.8      maya 
   5557   1.1      tron           if (dtd->scaffIndex) {
   5558   1.9  christos             /* Detect and prevent integer overflow.
   5559   1.9  christos              * The preprocessor guard addresses the "always false" warning
   5560   1.9  christos              * from -Wtype-limits on platforms where
   5561   1.9  christos              * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   5562   1.9  christos #if UINT_MAX >= SIZE_MAX
   5563   1.9  christos             if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) {
   5564   1.9  christos               return XML_ERROR_NO_MEMORY;
   5565   1.9  christos             }
   5566   1.9  christos #endif
   5567   1.9  christos 
   5568   1.8      maya             int *const new_scaff_index = (int *)REALLOC(
   5569   1.8      maya                 parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
   5570   1.8      maya             if (new_scaff_index == NULL)
   5571   1.1      tron               return XML_ERROR_NO_MEMORY;
   5572   1.8      maya             dtd->scaffIndex = new_scaff_index;
   5573   1.1      tron           }
   5574   1.8      maya         } else {
   5575   1.8      maya           parser->m_groupConnector
   5576   1.8      maya               = (char *)MALLOC(parser, parser->m_groupSize = 32);
   5577   1.8      maya           if (! parser->m_groupConnector) {
   5578   1.8      maya             parser->m_groupSize = 0;
   5579   1.1      tron             return XML_ERROR_NO_MEMORY;
   5580   1.8      maya           }
   5581   1.1      tron         }
   5582   1.1      tron       }
   5583   1.8      maya       parser->m_groupConnector[parser->m_prologState.level] = 0;
   5584   1.1      tron       if (dtd->in_eldecl) {
   5585   1.1      tron         int myindex = nextScaffoldPart(parser);
   5586   1.1      tron         if (myindex < 0)
   5587   1.1      tron           return XML_ERROR_NO_MEMORY;
   5588   1.8      maya         assert(dtd->scaffIndex != NULL);
   5589   1.1      tron         dtd->scaffIndex[dtd->scaffLevel] = myindex;
   5590   1.1      tron         dtd->scaffLevel++;
   5591   1.1      tron         dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
   5592   1.8      maya         if (parser->m_elementDeclHandler)
   5593   1.1      tron           handleDefault = XML_FALSE;
   5594   1.1      tron       }
   5595   1.1      tron       break;
   5596   1.1      tron     case XML_ROLE_GROUP_SEQUENCE:
   5597   1.8      maya       if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE)
   5598   1.1      tron         return XML_ERROR_SYNTAX;
   5599   1.8      maya       parser->m_groupConnector[parser->m_prologState.level] = ASCII_COMMA;
   5600   1.8      maya       if (dtd->in_eldecl && parser->m_elementDeclHandler)
   5601   1.1      tron         handleDefault = XML_FALSE;
   5602   1.1      tron       break;
   5603   1.1      tron     case XML_ROLE_GROUP_CHOICE:
   5604   1.8      maya       if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
   5605   1.1      tron         return XML_ERROR_SYNTAX;
   5606   1.1      tron       if (dtd->in_eldecl
   5607   1.8      maya           && ! parser->m_groupConnector[parser->m_prologState.level]
   5608   1.1      tron           && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
   5609   1.8      maya               != XML_CTYPE_MIXED)) {
   5610   1.1      tron         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
   5611   1.1      tron             = XML_CTYPE_CHOICE;
   5612   1.8      maya         if (parser->m_elementDeclHandler)
   5613   1.1      tron           handleDefault = XML_FALSE;
   5614   1.1      tron       }
   5615   1.8      maya       parser->m_groupConnector[parser->m_prologState.level] = ASCII_PIPE;
   5616   1.1      tron       break;
   5617   1.1      tron     case XML_ROLE_PARAM_ENTITY_REF:
   5618   1.1      tron #ifdef XML_DTD
   5619   1.1      tron     case XML_ROLE_INNER_PARAM_ENTITY_REF:
   5620   1.1      tron       dtd->hasParamEntityRefs = XML_TRUE;
   5621   1.8      maya       if (! parser->m_paramEntityParsing)
   5622   1.1      tron         dtd->keepProcessing = dtd->standalone;
   5623   1.1      tron       else {
   5624   1.1      tron         const XML_Char *name;
   5625   1.1      tron         ENTITY *entity;
   5626   1.8      maya         name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
   5627   1.8      maya                                next - enc->minBytesPerChar);
   5628   1.8      maya         if (! name)
   5629   1.1      tron           return XML_ERROR_NO_MEMORY;
   5630   1.3       spz         entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
   5631   1.1      tron         poolDiscard(&dtd->pool);
   5632   1.1      tron         /* first, determine if a check for an existing declaration is needed;
   5633   1.1      tron            if yes, check that the entity exists, and that it is internal,
   5634   1.1      tron            otherwise call the skipped entity handler
   5635   1.1      tron         */
   5636   1.8      maya         if (parser->m_prologState.documentEntity
   5637   1.8      maya             && (dtd->standalone ? ! parser->m_openInternalEntities
   5638   1.8      maya                                 : ! dtd->hasParamEntityRefs)) {
   5639   1.8      maya           if (! entity)
   5640   1.1      tron             return XML_ERROR_UNDEFINED_ENTITY;
   5641   1.8      maya           else if (! entity->is_internal) {
   5642   1.8      maya             /* It's hard to exhaustively search the code to be sure,
   5643   1.8      maya              * but there doesn't seem to be a way of executing the
   5644   1.8      maya              * following line.  There are two cases:
   5645   1.8      maya              *
   5646   1.8      maya              * If 'standalone' is false, the DTD must have no
   5647   1.8      maya              * parameter entities or we wouldn't have passed the outer
   5648  1.10       wiz              * 'if' statement.  That means the only entity in the hash
   5649   1.8      maya              * table is the external subset name "#" which cannot be
   5650   1.8      maya              * given as a parameter entity name in XML syntax, so the
   5651   1.8      maya              * lookup must have returned NULL and we don't even reach
   5652   1.8      maya              * the test for an internal entity.
   5653   1.8      maya              *
   5654   1.8      maya              * If 'standalone' is true, it does not seem to be
   5655   1.8      maya              * possible to create entities taking this code path that
   5656   1.8      maya              * are not internal entities, so fail the test above.
   5657   1.8      maya              *
   5658   1.8      maya              * Because this analysis is very uncertain, the code is
   5659   1.8      maya              * being left in place and merely removed from the
   5660   1.8      maya              * coverage test statistics.
   5661   1.8      maya              */
   5662   1.8      maya             return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
   5663   1.8      maya           }
   5664   1.8      maya         } else if (! entity) {
   5665   1.1      tron           dtd->keepProcessing = dtd->standalone;
   5666   1.1      tron           /* cannot report skipped entities in declarations */
   5667   1.8      maya           if ((role == XML_ROLE_PARAM_ENTITY_REF)
   5668   1.8      maya               && parser->m_skippedEntityHandler) {
   5669   1.8      maya             parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1);
   5670   1.1      tron             handleDefault = XML_FALSE;
   5671   1.1      tron           }
   5672   1.1      tron           break;
   5673   1.1      tron         }
   5674   1.1      tron         if (entity->open)
   5675   1.1      tron           return XML_ERROR_RECURSIVE_ENTITY_REF;
   5676   1.1      tron         if (entity->textPtr) {
   5677   1.1      tron           enum XML_Error result;
   5678   1.8      maya           XML_Bool betweenDecl
   5679   1.8      maya               = (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
   5680  1.10       wiz           result = processEntity(parser, entity, betweenDecl, ENTITY_INTERNAL);
   5681   1.1      tron           if (result != XML_ERROR_NONE)
   5682   1.1      tron             return result;
   5683   1.1      tron           handleDefault = XML_FALSE;
   5684   1.1      tron           break;
   5685   1.1      tron         }
   5686   1.8      maya         if (parser->m_externalEntityRefHandler) {
   5687   1.1      tron           dtd->paramEntityRead = XML_FALSE;
   5688   1.1      tron           entity->open = XML_TRUE;
   5689   1.9  christos           entityTrackingOnOpen(parser, entity, __LINE__);
   5690   1.8      maya           if (! parser->m_externalEntityRefHandler(
   5691   1.8      maya                   parser->m_externalEntityRefHandlerArg, 0, entity->base,
   5692   1.8      maya                   entity->systemId, entity->publicId)) {
   5693   1.9  christos             entityTrackingOnClose(parser, entity, __LINE__);
   5694   1.1      tron             entity->open = XML_FALSE;
   5695   1.1      tron             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   5696   1.1      tron           }
   5697   1.9  christos           entityTrackingOnClose(parser, entity, __LINE__);
   5698   1.1      tron           entity->open = XML_FALSE;
   5699   1.1      tron           handleDefault = XML_FALSE;
   5700   1.8      maya           if (! dtd->paramEntityRead) {
   5701   1.1      tron             dtd->keepProcessing = dtd->standalone;
   5702   1.1      tron             break;
   5703   1.1      tron           }
   5704   1.8      maya         } else {
   5705   1.1      tron           dtd->keepProcessing = dtd->standalone;
   5706   1.1      tron           break;
   5707   1.1      tron         }
   5708   1.1      tron       }
   5709   1.1      tron #endif /* XML_DTD */
   5710   1.8      maya       if (! dtd->standalone && parser->m_notStandaloneHandler
   5711   1.8      maya           && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
   5712   1.1      tron         return XML_ERROR_NOT_STANDALONE;
   5713   1.1      tron       break;
   5714   1.1      tron 
   5715   1.8      maya       /* Element declaration stuff */
   5716   1.1      tron 
   5717   1.1      tron     case XML_ROLE_ELEMENT_NAME:
   5718   1.8      maya       if (parser->m_elementDeclHandler) {
   5719   1.8      maya         parser->m_declElementType = getElementType(parser, enc, s, next);
   5720   1.8      maya         if (! parser->m_declElementType)
   5721   1.1      tron           return XML_ERROR_NO_MEMORY;
   5722   1.1      tron         dtd->scaffLevel = 0;
   5723   1.1      tron         dtd->scaffCount = 0;
   5724   1.1      tron         dtd->in_eldecl = XML_TRUE;
   5725   1.1      tron         handleDefault = XML_FALSE;
   5726   1.1      tron       }
   5727   1.1      tron       break;
   5728   1.1      tron 
   5729   1.1      tron     case XML_ROLE_CONTENT_ANY:
   5730   1.1      tron     case XML_ROLE_CONTENT_EMPTY:
   5731   1.1      tron       if (dtd->in_eldecl) {
   5732   1.8      maya         if (parser->m_elementDeclHandler) {
   5733   1.8      maya           XML_Content *content
   5734   1.8      maya               = (XML_Content *)MALLOC(parser, sizeof(XML_Content));
   5735   1.8      maya           if (! content)
   5736   1.1      tron             return XML_ERROR_NO_MEMORY;
   5737   1.1      tron           content->quant = XML_CQUANT_NONE;
   5738   1.1      tron           content->name = NULL;
   5739   1.1      tron           content->numchildren = 0;
   5740   1.1      tron           content->children = NULL;
   5741   1.8      maya           content->type = ((role == XML_ROLE_CONTENT_ANY) ? XML_CTYPE_ANY
   5742   1.8      maya                                                           : XML_CTYPE_EMPTY);
   5743   1.1      tron           *eventEndPP = s;
   5744   1.8      maya           parser->m_elementDeclHandler(
   5745   1.8      maya               parser->m_handlerArg, parser->m_declElementType->name, content);
   5746   1.1      tron           handleDefault = XML_FALSE;
   5747   1.1      tron         }
   5748   1.1      tron         dtd->in_eldecl = XML_FALSE;
   5749   1.1      tron       }
   5750   1.1      tron       break;
   5751   1.1      tron 
   5752   1.1      tron     case XML_ROLE_CONTENT_PCDATA:
   5753   1.1      tron       if (dtd->in_eldecl) {
   5754   1.1      tron         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
   5755   1.1      tron             = XML_CTYPE_MIXED;
   5756   1.8      maya         if (parser->m_elementDeclHandler)
   5757   1.1      tron           handleDefault = XML_FALSE;
   5758   1.1      tron       }
   5759   1.1      tron       break;
   5760   1.1      tron 
   5761   1.1      tron     case XML_ROLE_CONTENT_ELEMENT:
   5762   1.1      tron       quant = XML_CQUANT_NONE;
   5763   1.1      tron       goto elementContent;
   5764   1.1      tron     case XML_ROLE_CONTENT_ELEMENT_OPT:
   5765   1.1      tron       quant = XML_CQUANT_OPT;
   5766   1.1      tron       goto elementContent;
   5767   1.1      tron     case XML_ROLE_CONTENT_ELEMENT_REP:
   5768   1.1      tron       quant = XML_CQUANT_REP;
   5769   1.1      tron       goto elementContent;
   5770   1.1      tron     case XML_ROLE_CONTENT_ELEMENT_PLUS:
   5771   1.1      tron       quant = XML_CQUANT_PLUS;
   5772   1.1      tron     elementContent:
   5773   1.1      tron       if (dtd->in_eldecl) {
   5774   1.1      tron         ELEMENT_TYPE *el;
   5775   1.1      tron         const XML_Char *name;
   5776   1.9  christos         size_t nameLen;
   5777   1.8      maya         const char *nxt
   5778   1.8      maya             = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
   5779   1.1      tron         int myindex = nextScaffoldPart(parser);
   5780   1.1      tron         if (myindex < 0)
   5781   1.1      tron           return XML_ERROR_NO_MEMORY;
   5782   1.1      tron         dtd->scaffold[myindex].type = XML_CTYPE_NAME;
   5783   1.1      tron         dtd->scaffold[myindex].quant = quant;
   5784   1.1      tron         el = getElementType(parser, enc, s, nxt);
   5785   1.8      maya         if (! el)
   5786   1.1      tron           return XML_ERROR_NO_MEMORY;
   5787   1.1      tron         name = el->name;
   5788   1.1      tron         dtd->scaffold[myindex].name = name;
   5789   1.1      tron         nameLen = 0;
   5790   1.8      maya         for (; name[nameLen++];)
   5791   1.8      maya           ;
   5792   1.9  christos 
   5793   1.9  christos         /* Detect and prevent integer overflow */
   5794   1.9  christos         if (nameLen > UINT_MAX - dtd->contentStringLen) {
   5795   1.9  christos           return XML_ERROR_NO_MEMORY;
   5796   1.9  christos         }
   5797   1.9  christos 
   5798   1.9  christos         dtd->contentStringLen += (unsigned)nameLen;
   5799   1.8      maya         if (parser->m_elementDeclHandler)
   5800   1.1      tron           handleDefault = XML_FALSE;
   5801   1.1      tron       }
   5802   1.1      tron       break;
   5803   1.1      tron 
   5804   1.1      tron     case XML_ROLE_GROUP_CLOSE:
   5805   1.1      tron       quant = XML_CQUANT_NONE;
   5806   1.1      tron       goto closeGroup;
   5807   1.1      tron     case XML_ROLE_GROUP_CLOSE_OPT:
   5808   1.1      tron       quant = XML_CQUANT_OPT;
   5809   1.1      tron       goto closeGroup;
   5810   1.1      tron     case XML_ROLE_GROUP_CLOSE_REP:
   5811   1.1      tron       quant = XML_CQUANT_REP;
   5812   1.1      tron       goto closeGroup;
   5813   1.1      tron     case XML_ROLE_GROUP_CLOSE_PLUS:
   5814   1.1      tron       quant = XML_CQUANT_PLUS;
   5815   1.1      tron     closeGroup:
   5816   1.1      tron       if (dtd->in_eldecl) {
   5817   1.8      maya         if (parser->m_elementDeclHandler)
   5818   1.1      tron           handleDefault = XML_FALSE;
   5819   1.1      tron         dtd->scaffLevel--;
   5820   1.1      tron         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
   5821   1.1      tron         if (dtd->scaffLevel == 0) {
   5822   1.8      maya           if (! handleDefault) {
   5823   1.1      tron             XML_Content *model = build_model(parser);
   5824   1.8      maya             if (! model)
   5825   1.1      tron               return XML_ERROR_NO_MEMORY;
   5826   1.1      tron             *eventEndPP = s;
   5827   1.8      maya             parser->m_elementDeclHandler(
   5828   1.8      maya                 parser->m_handlerArg, parser->m_declElementType->name, model);
   5829   1.1      tron           }
   5830   1.1      tron           dtd->in_eldecl = XML_FALSE;
   5831   1.1      tron           dtd->contentStringLen = 0;
   5832   1.1      tron         }
   5833   1.1      tron       }
   5834   1.1      tron       break;
   5835   1.1      tron       /* End element declaration stuff */
   5836   1.1      tron 
   5837   1.1      tron     case XML_ROLE_PI:
   5838   1.8      maya       if (! reportProcessingInstruction(parser, enc, s, next))
   5839   1.1      tron         return XML_ERROR_NO_MEMORY;
   5840   1.1      tron       handleDefault = XML_FALSE;
   5841   1.1      tron       break;
   5842   1.1      tron     case XML_ROLE_COMMENT:
   5843   1.8      maya       if (! reportComment(parser, enc, s, next))
   5844   1.1      tron         return XML_ERROR_NO_MEMORY;
   5845   1.1      tron       handleDefault = XML_FALSE;
   5846   1.1      tron       break;
   5847   1.1      tron     case XML_ROLE_NONE:
   5848   1.1      tron       switch (tok) {
   5849   1.1      tron       case XML_TOK_BOM:
   5850   1.1      tron         handleDefault = XML_FALSE;
   5851   1.1      tron         break;
   5852   1.1      tron       }
   5853   1.1      tron       break;
   5854   1.1      tron     case XML_ROLE_DOCTYPE_NONE:
   5855   1.8      maya       if (parser->m_startDoctypeDeclHandler)
   5856   1.1      tron         handleDefault = XML_FALSE;
   5857   1.1      tron       break;
   5858   1.1      tron     case XML_ROLE_ENTITY_NONE:
   5859   1.8      maya       if (dtd->keepProcessing && parser->m_entityDeclHandler)
   5860   1.1      tron         handleDefault = XML_FALSE;
   5861   1.1      tron       break;
   5862   1.1      tron     case XML_ROLE_NOTATION_NONE:
   5863   1.8      maya       if (parser->m_notationDeclHandler)
   5864   1.1      tron         handleDefault = XML_FALSE;
   5865   1.1      tron       break;
   5866   1.1      tron     case XML_ROLE_ATTLIST_NONE:
   5867   1.8      maya       if (dtd->keepProcessing && parser->m_attlistDeclHandler)
   5868   1.1      tron         handleDefault = XML_FALSE;
   5869   1.1      tron       break;
   5870   1.1      tron     case XML_ROLE_ELEMENT_NONE:
   5871   1.8      maya       if (parser->m_elementDeclHandler)
   5872   1.1      tron         handleDefault = XML_FALSE;
   5873   1.1      tron       break;
   5874   1.1      tron     } /* end of big switch */
   5875   1.1      tron 
   5876   1.8      maya     if (handleDefault && parser->m_defaultHandler)
   5877   1.1      tron       reportDefault(parser, enc, s, next);
   5878   1.1      tron 
   5879   1.8      maya     switch (parser->m_parsingStatus.parsing) {
   5880   1.3       spz     case XML_SUSPENDED:
   5881   1.1      tron       *nextPtr = next;
   5882   1.1      tron       return XML_ERROR_NONE;
   5883   1.1      tron     case XML_FINISHED:
   5884   1.1      tron       return XML_ERROR_ABORTED;
   5885  1.10       wiz     case XML_PARSING:
   5886  1.10       wiz       if (parser->m_reenter) {
   5887  1.10       wiz         *nextPtr = next;
   5888  1.10       wiz         return XML_ERROR_NONE;
   5889  1.10       wiz       }
   5890  1.10       wiz     /* Fall through */
   5891   1.1      tron     default:
   5892   1.1      tron       s = next;
   5893   1.1      tron       tok = XmlPrologTok(enc, s, end, &next);
   5894   1.1      tron     }
   5895   1.1      tron   }
   5896   1.1      tron   /* not reached */
   5897   1.1      tron }
   5898   1.1      tron 
   5899   1.1      tron static enum XML_Error PTRCALL
   5900   1.8      maya epilogProcessor(XML_Parser parser, const char *s, const char *end,
   5901   1.8      maya                 const char **nextPtr) {
   5902   1.8      maya   parser->m_processor = epilogProcessor;
   5903   1.8      maya   parser->m_eventPtr = s;
   5904   1.1      tron   for (;;) {
   5905   1.1      tron     const char *next = NULL;
   5906   1.8      maya     int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
   5907  1.10       wiz #if XML_GE == 1
   5908   1.9  christos     if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
   5909   1.9  christos                                   XML_ACCOUNT_DIRECT)) {
   5910   1.9  christos       accountingOnAbort(parser);
   5911   1.9  christos       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   5912   1.9  christos     }
   5913   1.9  christos #endif
   5914   1.8      maya     parser->m_eventEndPtr = next;
   5915   1.1      tron     switch (tok) {
   5916   1.1      tron     /* report partial linebreak - it might be the last token */
   5917   1.1      tron     case -XML_TOK_PROLOG_S:
   5918   1.8      maya       if (parser->m_defaultHandler) {
   5919   1.8      maya         reportDefault(parser, parser->m_encoding, s, next);
   5920   1.8      maya         if (parser->m_parsingStatus.parsing == XML_FINISHED)
   5921   1.1      tron           return XML_ERROR_ABORTED;
   5922   1.1      tron       }
   5923   1.1      tron       *nextPtr = next;
   5924   1.1      tron       return XML_ERROR_NONE;
   5925   1.1      tron     case XML_TOK_NONE:
   5926   1.1      tron       *nextPtr = s;
   5927   1.1      tron       return XML_ERROR_NONE;
   5928   1.1      tron     case XML_TOK_PROLOG_S:
   5929   1.8      maya       if (parser->m_defaultHandler)
   5930   1.8      maya         reportDefault(parser, parser->m_encoding, s, next);
   5931   1.1      tron       break;
   5932   1.1      tron     case XML_TOK_PI:
   5933   1.8      maya       if (! reportProcessingInstruction(parser, parser->m_encoding, s, next))
   5934   1.1      tron         return XML_ERROR_NO_MEMORY;
   5935   1.1      tron       break;
   5936   1.1      tron     case XML_TOK_COMMENT:
   5937   1.8      maya       if (! reportComment(parser, parser->m_encoding, s, next))
   5938   1.1      tron         return XML_ERROR_NO_MEMORY;
   5939   1.1      tron       break;
   5940   1.1      tron     case XML_TOK_INVALID:
   5941   1.8      maya       parser->m_eventPtr = next;
   5942   1.1      tron       return XML_ERROR_INVALID_TOKEN;
   5943   1.1      tron     case XML_TOK_PARTIAL:
   5944   1.8      maya       if (! parser->m_parsingStatus.finalBuffer) {
   5945   1.1      tron         *nextPtr = s;
   5946   1.1      tron         return XML_ERROR_NONE;
   5947   1.1      tron       }
   5948   1.1      tron       return XML_ERROR_UNCLOSED_TOKEN;
   5949   1.1      tron     case XML_TOK_PARTIAL_CHAR:
   5950   1.8      maya       if (! parser->m_parsingStatus.finalBuffer) {
   5951   1.1      tron         *nextPtr = s;
   5952   1.1      tron         return XML_ERROR_NONE;
   5953   1.1      tron       }
   5954   1.1      tron       return XML_ERROR_PARTIAL_CHAR;
   5955   1.1      tron     default:
   5956   1.1      tron       return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
   5957   1.1      tron     }
   5958   1.8      maya     switch (parser->m_parsingStatus.parsing) {
   5959   1.3       spz     case XML_SUSPENDED:
   5960  1.11       wiz       parser->m_eventPtr = next;
   5961   1.1      tron       *nextPtr = next;
   5962   1.1      tron       return XML_ERROR_NONE;
   5963   1.1      tron     case XML_FINISHED:
   5964  1.11       wiz       parser->m_eventPtr = next;
   5965   1.1      tron       return XML_ERROR_ABORTED;
   5966  1.10       wiz     case XML_PARSING:
   5967  1.10       wiz       if (parser->m_reenter) {
   5968  1.10       wiz         return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
   5969  1.10       wiz       }
   5970  1.10       wiz     /* Fall through */
   5971   1.8      maya     default:;
   5972  1.11       wiz       parser->m_eventPtr = s = next;
   5973   1.1      tron     }
   5974   1.1      tron   }
   5975   1.1      tron }
   5976   1.1      tron 
   5977   1.1      tron static enum XML_Error
   5978  1.10       wiz processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
   5979  1.10       wiz               enum EntityType type) {
   5980  1.10       wiz   OPEN_INTERNAL_ENTITY *openEntity, **openEntityList, **freeEntityList;
   5981  1.10       wiz   switch (type) {
   5982  1.10       wiz   case ENTITY_INTERNAL:
   5983  1.10       wiz     parser->m_processor = internalEntityProcessor;
   5984  1.10       wiz     openEntityList = &parser->m_openInternalEntities;
   5985  1.10       wiz     freeEntityList = &parser->m_freeInternalEntities;
   5986  1.10       wiz     break;
   5987  1.10       wiz   case ENTITY_ATTRIBUTE:
   5988  1.10       wiz     openEntityList = &parser->m_openAttributeEntities;
   5989  1.10       wiz     freeEntityList = &parser->m_freeAttributeEntities;
   5990  1.10       wiz     break;
   5991  1.10       wiz   case ENTITY_VALUE:
   5992  1.10       wiz     openEntityList = &parser->m_openValueEntities;
   5993  1.10       wiz     freeEntityList = &parser->m_freeValueEntities;
   5994  1.10       wiz     break;
   5995  1.10       wiz     /* default case serves merely as a safety net in case of a
   5996  1.10       wiz      * wrong entityType. Therefore we exclude the following lines
   5997  1.10       wiz      * from the test coverage.
   5998  1.10       wiz      *
   5999  1.10       wiz      * LCOV_EXCL_START
   6000  1.10       wiz      */
   6001  1.10       wiz   default:
   6002  1.10       wiz     // Should not reach here
   6003  1.10       wiz     assert(0);
   6004  1.10       wiz     /* LCOV_EXCL_STOP */
   6005  1.10       wiz   }
   6006   1.1      tron 
   6007  1.10       wiz   if (*freeEntityList) {
   6008  1.10       wiz     openEntity = *freeEntityList;
   6009  1.10       wiz     *freeEntityList = openEntity->next;
   6010   1.8      maya   } else {
   6011   1.8      maya     openEntity
   6012   1.8      maya         = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
   6013   1.8      maya     if (! openEntity)
   6014   1.1      tron       return XML_ERROR_NO_MEMORY;
   6015   1.1      tron   }
   6016   1.1      tron   entity->open = XML_TRUE;
   6017  1.10       wiz   entity->hasMore = XML_TRUE;
   6018  1.10       wiz #if XML_GE == 1
   6019   1.9  christos   entityTrackingOnOpen(parser, entity, __LINE__);
   6020   1.9  christos #endif
   6021   1.1      tron   entity->processed = 0;
   6022  1.10       wiz   openEntity->next = *openEntityList;
   6023  1.10       wiz   *openEntityList = openEntity;
   6024   1.1      tron   openEntity->entity = entity;
   6025  1.10       wiz   openEntity->type = type;
   6026   1.8      maya   openEntity->startTagLevel = parser->m_tagLevel;
   6027   1.1      tron   openEntity->betweenDecl = betweenDecl;
   6028   1.1      tron   openEntity->internalEventPtr = NULL;
   6029   1.1      tron   openEntity->internalEventEndPtr = NULL;
   6030   1.1      tron 
   6031  1.10       wiz   // Only internal entities make use of the reenter flag
   6032  1.10       wiz   // therefore no need to set it for other entity types
   6033  1.10       wiz   if (type == ENTITY_INTERNAL) {
   6034  1.10       wiz     triggerReenter(parser);
   6035   1.1      tron   }
   6036  1.10       wiz   return XML_ERROR_NONE;
   6037   1.1      tron }
   6038   1.1      tron 
   6039   1.1      tron static enum XML_Error PTRCALL
   6040   1.8      maya internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
   6041   1.8      maya                         const char **nextPtr) {
   6042  1.10       wiz   UNUSED_P(s);
   6043  1.10       wiz   UNUSED_P(end);
   6044  1.10       wiz   UNUSED_P(nextPtr);
   6045   1.1      tron   ENTITY *entity;
   6046   1.1      tron   const char *textStart, *textEnd;
   6047   1.1      tron   const char *next;
   6048   1.1      tron   enum XML_Error result;
   6049   1.8      maya   OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
   6050   1.8      maya   if (! openEntity)
   6051   1.1      tron     return XML_ERROR_UNEXPECTED_STATE;
   6052   1.1      tron 
   6053   1.1      tron   entity = openEntity->entity;
   6054   1.1      tron 
   6055  1.10       wiz   // This will return early
   6056  1.10       wiz   if (entity->hasMore) {
   6057  1.10       wiz     textStart = ((const char *)entity->textPtr) + entity->processed;
   6058  1.10       wiz     textEnd = (const char *)(entity->textPtr + entity->textLen);
   6059  1.10       wiz     /* Set a safe default value in case 'next' does not get set */
   6060  1.10       wiz     next = textStart;
   6061  1.10       wiz 
   6062  1.10       wiz     if (entity->is_param) {
   6063  1.10       wiz       int tok
   6064  1.10       wiz           = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
   6065  1.10       wiz       result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
   6066  1.10       wiz                         tok, next, &next, XML_FALSE, XML_FALSE,
   6067  1.10       wiz                         XML_ACCOUNT_ENTITY_EXPANSION);
   6068  1.10       wiz     } else {
   6069  1.10       wiz       result = doContent(parser, openEntity->startTagLevel,
   6070  1.10       wiz                          parser->m_internalEncoding, textStart, textEnd, &next,
   6071  1.10       wiz                          XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
   6072  1.10       wiz     }
   6073  1.10       wiz 
   6074  1.10       wiz     if (result != XML_ERROR_NONE)
   6075  1.10       wiz       return result;
   6076  1.10       wiz     // Check if entity is complete, if not, mark down how much of it is
   6077  1.10       wiz     // processed
   6078  1.10       wiz     if (textEnd != next
   6079  1.10       wiz         && (parser->m_parsingStatus.parsing == XML_SUSPENDED
   6080  1.10       wiz             || (parser->m_parsingStatus.parsing == XML_PARSING
   6081  1.10       wiz                 && parser->m_reenter))) {
   6082  1.10       wiz       entity->processed = (int)(next - (const char *)entity->textPtr);
   6083  1.10       wiz       return result;
   6084  1.10       wiz     }
   6085   1.1      tron 
   6086  1.10       wiz     // Entity is complete. We cannot close it here since we need to first
   6087  1.10       wiz     // process its possible inner entities (which are added to the
   6088  1.10       wiz     // m_openInternalEntities during doProlog or doContent calls above)
   6089  1.10       wiz     entity->hasMore = XML_FALSE;
   6090  1.10       wiz     triggerReenter(parser);
   6091   1.1      tron     return result;
   6092  1.10       wiz   } // End of entity processing, "if" block will return here
   6093  1.10       wiz 
   6094  1.10       wiz   // Remove fully processed openEntity from open entity list.
   6095  1.10       wiz #if XML_GE == 1
   6096  1.10       wiz   entityTrackingOnClose(parser, entity, __LINE__);
   6097  1.10       wiz #endif
   6098  1.10       wiz   // openEntity is m_openInternalEntities' head, as we set it at the start of
   6099  1.10       wiz   // this function and we skipped doProlog and doContent calls with hasMore set
   6100  1.10       wiz   // to false. This means we can directly remove the head of
   6101  1.10       wiz   // m_openInternalEntities
   6102  1.10       wiz   assert(parser->m_openInternalEntities == openEntity);
   6103  1.10       wiz   entity->open = XML_FALSE;
   6104  1.10       wiz   parser->m_openInternalEntities = parser->m_openInternalEntities->next;
   6105  1.10       wiz 
   6106  1.10       wiz   /* put openEntity back in list of free instances */
   6107  1.10       wiz   openEntity->next = parser->m_freeInternalEntities;
   6108  1.10       wiz   parser->m_freeInternalEntities = openEntity;
   6109   1.1      tron 
   6110  1.10       wiz   if (parser->m_openInternalEntities == NULL) {
   6111  1.10       wiz     parser->m_processor = entity->is_param ? prologProcessor : contentProcessor;
   6112   1.3       spz   }
   6113  1.10       wiz   triggerReenter(parser);
   6114  1.10       wiz   return XML_ERROR_NONE;
   6115   1.1      tron }
   6116   1.1      tron 
   6117   1.1      tron static enum XML_Error PTRCALL
   6118   1.8      maya errorProcessor(XML_Parser parser, const char *s, const char *end,
   6119   1.8      maya                const char **nextPtr) {
   6120   1.8      maya   UNUSED_P(s);
   6121   1.8      maya   UNUSED_P(end);
   6122   1.8      maya   UNUSED_P(nextPtr);
   6123   1.8      maya   return parser->m_errorCode;
   6124   1.1      tron }
   6125   1.1      tron 
   6126   1.1      tron static enum XML_Error
   6127   1.1      tron storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
   6128   1.9  christos                     const char *ptr, const char *end, STRING_POOL *pool,
   6129   1.9  christos                     enum XML_Account account) {
   6130  1.10       wiz   const char *next = ptr;
   6131  1.10       wiz   enum XML_Error result = XML_ERROR_NONE;
   6132  1.10       wiz 
   6133  1.10       wiz   while (1) {
   6134  1.10       wiz     if (! parser->m_openAttributeEntities) {
   6135  1.10       wiz       result = appendAttributeValue(parser, enc, isCdata, next, end, pool,
   6136  1.10       wiz                                     account, &next);
   6137  1.10       wiz     } else {
   6138  1.10       wiz       OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openAttributeEntities;
   6139  1.10       wiz       if (! openEntity)
   6140  1.10       wiz         return XML_ERROR_UNEXPECTED_STATE;
   6141  1.10       wiz 
   6142  1.10       wiz       ENTITY *const entity = openEntity->entity;
   6143  1.10       wiz       const char *const textStart
   6144  1.10       wiz           = ((const char *)entity->textPtr) + entity->processed;
   6145  1.10       wiz       const char *const textEnd
   6146  1.10       wiz           = (const char *)(entity->textPtr + entity->textLen);
   6147  1.10       wiz       /* Set a safe default value in case 'next' does not get set */
   6148  1.10       wiz       const char *nextInEntity = textStart;
   6149  1.10       wiz       if (entity->hasMore) {
   6150  1.10       wiz         result = appendAttributeValue(
   6151  1.10       wiz             parser, parser->m_internalEncoding, isCdata, textStart, textEnd,
   6152  1.10       wiz             pool, XML_ACCOUNT_ENTITY_EXPANSION, &nextInEntity);
   6153  1.10       wiz         if (result != XML_ERROR_NONE)
   6154  1.10       wiz           break;
   6155  1.10       wiz         // Check if entity is complete, if not, mark down how much of it is
   6156  1.10       wiz         // processed. A XML_SUSPENDED check here is not required as
   6157  1.10       wiz         // appendAttributeValue will never suspend the parser.
   6158  1.10       wiz         if (textEnd != nextInEntity) {
   6159  1.10       wiz           entity->processed
   6160  1.10       wiz               = (int)(nextInEntity - (const char *)entity->textPtr);
   6161  1.10       wiz           continue;
   6162  1.10       wiz         }
   6163  1.10       wiz 
   6164  1.10       wiz         // Entity is complete. We cannot close it here since we need to first
   6165  1.10       wiz         // process its possible inner entities (which are added to the
   6166  1.10       wiz         // m_openAttributeEntities during appendAttributeValue)
   6167  1.10       wiz         entity->hasMore = XML_FALSE;
   6168  1.10       wiz         continue;
   6169  1.10       wiz       } // End of entity processing, "if" block skips the rest
   6170  1.10       wiz 
   6171  1.10       wiz       // Remove fully processed openEntity from open entity list.
   6172  1.10       wiz #if XML_GE == 1
   6173  1.10       wiz       entityTrackingOnClose(parser, entity, __LINE__);
   6174  1.10       wiz #endif
   6175  1.10       wiz       // openEntity is m_openAttributeEntities' head, since we set it at the
   6176  1.10       wiz       // start of this function and because we skipped appendAttributeValue call
   6177  1.10       wiz       // with hasMore set to false. This means we can directly remove the head
   6178  1.10       wiz       // of m_openAttributeEntities
   6179  1.10       wiz       assert(parser->m_openAttributeEntities == openEntity);
   6180  1.10       wiz       entity->open = XML_FALSE;
   6181  1.10       wiz       parser->m_openAttributeEntities = parser->m_openAttributeEntities->next;
   6182  1.10       wiz 
   6183  1.10       wiz       /* put openEntity back in list of free instances */
   6184  1.10       wiz       openEntity->next = parser->m_freeAttributeEntities;
   6185  1.10       wiz       parser->m_freeAttributeEntities = openEntity;
   6186  1.10       wiz     }
   6187  1.10       wiz 
   6188  1.10       wiz     // Break if an error occurred or there is nothing left to process
   6189  1.10       wiz     if (result || (parser->m_openAttributeEntities == NULL && end == next)) {
   6190  1.10       wiz       break;
   6191  1.10       wiz     }
   6192  1.10       wiz   }
   6193  1.10       wiz 
   6194   1.1      tron   if (result)
   6195   1.1      tron     return result;
   6196   1.8      maya   if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
   6197   1.1      tron     poolChop(pool);
   6198   1.8      maya   if (! poolAppendChar(pool, XML_T('\0')))
   6199   1.1      tron     return XML_ERROR_NO_MEMORY;
   6200   1.1      tron   return XML_ERROR_NONE;
   6201   1.1      tron }
   6202   1.1      tron 
   6203   1.1      tron static enum XML_Error
   6204   1.1      tron appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
   6205   1.9  christos                      const char *ptr, const char *end, STRING_POOL *pool,
   6206  1.10       wiz                      enum XML_Account account, const char **nextPtr) {
   6207   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   6208   1.9  christos #ifndef XML_DTD
   6209   1.9  christos   UNUSED_P(account);
   6210   1.9  christos #endif
   6211   1.9  christos 
   6212   1.1      tron   for (;;) {
   6213   1.9  christos     const char *next
   6214   1.9  christos         = ptr; /* XmlAttributeValueTok doesn't always set the last arg */
   6215   1.1      tron     int tok = XmlAttributeValueTok(enc, ptr, end, &next);
   6216  1.10       wiz #if XML_GE == 1
   6217   1.9  christos     if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) {
   6218   1.9  christos       accountingOnAbort(parser);
   6219   1.9  christos       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   6220   1.9  christos     }
   6221   1.9  christos #endif
   6222   1.1      tron     switch (tok) {
   6223   1.1      tron     case XML_TOK_NONE:
   6224  1.10       wiz       if (nextPtr) {
   6225  1.10       wiz         *nextPtr = next;
   6226  1.10       wiz       }
   6227   1.1      tron       return XML_ERROR_NONE;
   6228   1.1      tron     case XML_TOK_INVALID:
   6229   1.8      maya       if (enc == parser->m_encoding)
   6230   1.8      maya         parser->m_eventPtr = next;
   6231   1.1      tron       return XML_ERROR_INVALID_TOKEN;
   6232   1.1      tron     case XML_TOK_PARTIAL:
   6233   1.8      maya       if (enc == parser->m_encoding)
   6234   1.8      maya         parser->m_eventPtr = ptr;
   6235   1.1      tron       return XML_ERROR_INVALID_TOKEN;
   6236   1.8      maya     case XML_TOK_CHAR_REF: {
   6237   1.8      maya       XML_Char buf[XML_ENCODE_MAX];
   6238   1.8      maya       int i;
   6239   1.8      maya       int n = XmlCharRefNumber(enc, ptr);
   6240   1.8      maya       if (n < 0) {
   6241   1.8      maya         if (enc == parser->m_encoding)
   6242   1.8      maya           parser->m_eventPtr = ptr;
   6243   1.8      maya         return XML_ERROR_BAD_CHAR_REF;
   6244   1.8      maya       }
   6245   1.8      maya       if (! isCdata && n == 0x20 /* space */
   6246   1.8      maya           && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
   6247   1.8      maya         break;
   6248   1.8      maya       n = XmlEncode(n, (ICHAR *)buf);
   6249   1.8      maya       /* The XmlEncode() functions can never return 0 here.  That
   6250   1.8      maya        * error return happens if the code point passed in is either
   6251   1.8      maya        * negative or greater than or equal to 0x110000.  The
   6252   1.8      maya        * XmlCharRefNumber() functions will all return a number
   6253   1.8      maya        * strictly less than 0x110000 or a negative value if an error
   6254   1.8      maya        * occurred.  The negative value is intercepted above, so
   6255   1.8      maya        * XmlEncode() is never passed a value it might return an
   6256   1.8      maya        * error for.
   6257   1.8      maya        */
   6258   1.8      maya       for (i = 0; i < n; i++) {
   6259   1.8      maya         if (! poolAppendChar(pool, buf[i]))
   6260   1.8      maya           return XML_ERROR_NO_MEMORY;
   6261   1.1      tron       }
   6262   1.8      maya     } break;
   6263   1.1      tron     case XML_TOK_DATA_CHARS:
   6264   1.8      maya       if (! poolAppend(pool, enc, ptr, next))
   6265   1.1      tron         return XML_ERROR_NO_MEMORY;
   6266   1.1      tron       break;
   6267   1.1      tron     case XML_TOK_TRAILING_CR:
   6268   1.1      tron       next = ptr + enc->minBytesPerChar;
   6269   1.1      tron       /* fall through */
   6270   1.1      tron     case XML_TOK_ATTRIBUTE_VALUE_S:
   6271   1.1      tron     case XML_TOK_DATA_NEWLINE:
   6272   1.8      maya       if (! isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
   6273   1.1      tron         break;
   6274   1.8      maya       if (! poolAppendChar(pool, 0x20))
   6275   1.1      tron         return XML_ERROR_NO_MEMORY;
   6276   1.1      tron       break;
   6277   1.8      maya     case XML_TOK_ENTITY_REF: {
   6278   1.8      maya       const XML_Char *name;
   6279   1.8      maya       ENTITY *entity;
   6280   1.8      maya       char checkEntityDecl;
   6281   1.8      maya       XML_Char ch = (XML_Char)XmlPredefinedEntityName(
   6282   1.8      maya           enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
   6283   1.8      maya       if (ch) {
   6284  1.10       wiz #if XML_GE == 1
   6285   1.9  christos         /* NOTE: We are replacing 4-6 characters original input for 1 character
   6286   1.9  christos          *       so there is no amplification and hence recording without
   6287   1.9  christos          *       protection. */
   6288   1.9  christos         accountingDiffTolerated(parser, tok, (char *)&ch,
   6289   1.9  christos                                 ((char *)&ch) + sizeof(XML_Char), __LINE__,
   6290   1.9  christos                                 XML_ACCOUNT_ENTITY_EXPANSION);
   6291  1.10       wiz #endif /* XML_GE == 1 */
   6292   1.8      maya         if (! poolAppendChar(pool, ch))
   6293   1.1      tron           return XML_ERROR_NO_MEMORY;
   6294   1.8      maya         break;
   6295   1.8      maya       }
   6296   1.8      maya       name = poolStoreString(&parser->m_temp2Pool, enc,
   6297   1.8      maya                              ptr + enc->minBytesPerChar,
   6298   1.8      maya                              next - enc->minBytesPerChar);
   6299   1.8      maya       if (! name)
   6300   1.8      maya         return XML_ERROR_NO_MEMORY;
   6301   1.8      maya       entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
   6302   1.8      maya       poolDiscard(&parser->m_temp2Pool);
   6303   1.8      maya       /* First, determine if a check for an existing declaration is needed;
   6304   1.8      maya          if yes, check that the entity exists, and that it is internal.
   6305   1.8      maya       */
   6306   1.8      maya       if (pool == &dtd->pool) /* are we called from prolog? */
   6307   1.8      maya         checkEntityDecl =
   6308   1.1      tron #ifdef XML_DTD
   6309   1.8      maya             parser->m_prologState.documentEntity &&
   6310   1.1      tron #endif /* XML_DTD */
   6311   1.8      maya             (dtd->standalone ? ! parser->m_openInternalEntities
   6312   1.8      maya                              : ! dtd->hasParamEntityRefs);
   6313   1.8      maya       else /* if (pool == &parser->m_tempPool): we are called from content */
   6314   1.8      maya         checkEntityDecl = ! dtd->hasParamEntityRefs || dtd->standalone;
   6315   1.8      maya       if (checkEntityDecl) {
   6316   1.8      maya         if (! entity)
   6317   1.8      maya           return XML_ERROR_UNDEFINED_ENTITY;
   6318   1.8      maya         else if (! entity->is_internal)
   6319   1.8      maya           return XML_ERROR_ENTITY_DECLARED_IN_PE;
   6320   1.8      maya       } else if (! entity) {
   6321   1.8      maya         /* Cannot report skipped entity here - see comments on
   6322   1.8      maya            parser->m_skippedEntityHandler.
   6323   1.8      maya         if (parser->m_skippedEntityHandler)
   6324   1.8      maya           parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
   6325   1.8      maya         */
   6326   1.8      maya         /* Cannot call the default handler because this would be
   6327   1.8      maya            out of sync with the call to the startElementHandler.
   6328   1.8      maya         if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
   6329   1.8      maya           reportDefault(parser, enc, ptr, next);
   6330   1.8      maya         */
   6331   1.8      maya         break;
   6332   1.8      maya       }
   6333   1.8      maya       if (entity->open) {
   6334   1.8      maya         if (enc == parser->m_encoding) {
   6335   1.8      maya           /* It does not appear that this line can be executed.
   6336   1.8      maya            *
   6337   1.8      maya            * The "if (entity->open)" check catches recursive entity
   6338   1.8      maya            * definitions.  In order to be called with an open
   6339   1.8      maya            * entity, it must have gone through this code before and
   6340   1.8      maya            * been through the recursive call to
   6341   1.8      maya            * appendAttributeValue() some lines below.  That call
   6342   1.8      maya            * sets the local encoding ("enc") to the parser's
   6343   1.8      maya            * internal encoding (internal_utf8 or internal_utf16),
   6344   1.8      maya            * which can never be the same as the principle encoding.
   6345   1.8      maya            * It doesn't appear there is another code path that gets
   6346   1.8      maya            * here with entity->open being TRUE.
   6347   1.8      maya            *
   6348   1.8      maya            * Since it is not certain that this logic is watertight,
   6349   1.8      maya            * we keep the line and merely exclude it from coverage
   6350   1.8      maya            * tests.
   6351   1.8      maya            */
   6352   1.8      maya           parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
   6353   1.8      maya         }
   6354   1.8      maya         return XML_ERROR_RECURSIVE_ENTITY_REF;
   6355   1.8      maya       }
   6356   1.8      maya       if (entity->notation) {
   6357   1.8      maya         if (enc == parser->m_encoding)
   6358   1.8      maya           parser->m_eventPtr = ptr;
   6359   1.8      maya         return XML_ERROR_BINARY_ENTITY_REF;
   6360   1.8      maya       }
   6361   1.8      maya       if (! entity->textPtr) {
   6362   1.8      maya         if (enc == parser->m_encoding)
   6363   1.8      maya           parser->m_eventPtr = ptr;
   6364   1.8      maya         return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
   6365   1.8      maya       } else {
   6366   1.8      maya         enum XML_Error result;
   6367  1.10       wiz         result = processEntity(parser, entity, XML_FALSE, ENTITY_ATTRIBUTE);
   6368  1.10       wiz         if ((result == XML_ERROR_NONE) && (nextPtr != NULL)) {
   6369  1.10       wiz           *nextPtr = next;
   6370  1.10       wiz         }
   6371  1.10       wiz         return result;
   6372   1.1      tron       }
   6373   1.8      maya     } break;
   6374   1.1      tron     default:
   6375   1.8      maya       /* The only token returned by XmlAttributeValueTok() that does
   6376   1.8      maya        * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
   6377   1.8      maya        * Getting that would require an entity name to contain an
   6378   1.8      maya        * incomplete XML character (e.g. \xE2\x82); however previous
   6379   1.8      maya        * tokenisers will have already recognised and rejected such
   6380   1.8      maya        * names before XmlAttributeValueTok() gets a look-in.  This
   6381   1.8      maya        * default case should be retained as a safety net, but the code
   6382   1.8      maya        * excluded from coverage tests.
   6383   1.8      maya        *
   6384   1.8      maya        * LCOV_EXCL_START
   6385   1.8      maya        */
   6386   1.8      maya       if (enc == parser->m_encoding)
   6387   1.8      maya         parser->m_eventPtr = ptr;
   6388   1.1      tron       return XML_ERROR_UNEXPECTED_STATE;
   6389   1.8      maya       /* LCOV_EXCL_STOP */
   6390   1.1      tron     }
   6391   1.1      tron     ptr = next;
   6392   1.1      tron   }
   6393   1.1      tron   /* not reached */
   6394   1.1      tron }
   6395   1.1      tron 
   6396  1.10       wiz #if XML_GE == 1
   6397   1.1      tron static enum XML_Error
   6398   1.8      maya storeEntityValue(XML_Parser parser, const ENCODING *enc,
   6399   1.9  christos                  const char *entityTextPtr, const char *entityTextEnd,
   6400  1.10       wiz                  enum XML_Account account, const char **nextPtr) {
   6401   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   6402   1.1      tron   STRING_POOL *pool = &(dtd->entityValuePool);
   6403   1.1      tron   enum XML_Error result = XML_ERROR_NONE;
   6404  1.10       wiz #  ifdef XML_DTD
   6405   1.8      maya   int oldInEntityValue = parser->m_prologState.inEntityValue;
   6406   1.8      maya   parser->m_prologState.inEntityValue = 1;
   6407  1.10       wiz #  else
   6408   1.9  christos   UNUSED_P(account);
   6409  1.10       wiz #  endif /* XML_DTD */
   6410   1.1      tron   /* never return Null for the value argument in EntityDeclHandler,
   6411   1.1      tron      since this would indicate an external entity; therefore we
   6412   1.1      tron      have to make sure that entityValuePool.start is not null */
   6413   1.8      maya   if (! pool->blocks) {
   6414   1.8      maya     if (! poolGrow(pool))
   6415   1.1      tron       return XML_ERROR_NO_MEMORY;
   6416   1.1      tron   }
   6417   1.1      tron 
   6418  1.10       wiz   const char *next;
   6419   1.1      tron   for (;;) {
   6420  1.10       wiz     next
   6421   1.9  christos         = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
   6422   1.1      tron     int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
   6423   1.9  christos 
   6424   1.9  christos     if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__,
   6425   1.9  christos                                   account)) {
   6426   1.9  christos       accountingOnAbort(parser);
   6427   1.9  christos       result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
   6428   1.9  christos       goto endEntityValue;
   6429   1.9  christos     }
   6430   1.9  christos 
   6431   1.1      tron     switch (tok) {
   6432   1.1      tron     case XML_TOK_PARAM_ENTITY_REF:
   6433  1.10       wiz #  ifdef XML_DTD
   6434   1.8      maya       if (parser->m_isParamEntity || enc != parser->m_encoding) {
   6435   1.1      tron         const XML_Char *name;
   6436   1.1      tron         ENTITY *entity;
   6437   1.8      maya         name = poolStoreString(&parser->m_tempPool, enc,
   6438   1.1      tron                                entityTextPtr + enc->minBytesPerChar,
   6439   1.1      tron                                next - enc->minBytesPerChar);
   6440   1.8      maya         if (! name) {
   6441   1.1      tron           result = XML_ERROR_NO_MEMORY;
   6442   1.1      tron           goto endEntityValue;
   6443   1.1      tron         }
   6444   1.3       spz         entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
   6445   1.8      maya         poolDiscard(&parser->m_tempPool);
   6446   1.8      maya         if (! entity) {
   6447   1.1      tron           /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
   6448   1.1      tron           /* cannot report skipped entity here - see comments on
   6449   1.8      maya              parser->m_skippedEntityHandler
   6450   1.8      maya           if (parser->m_skippedEntityHandler)
   6451   1.8      maya             parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
   6452   1.1      tron           */
   6453   1.1      tron           dtd->keepProcessing = dtd->standalone;
   6454   1.1      tron           goto endEntityValue;
   6455   1.1      tron         }
   6456  1.10       wiz         if (entity->open || (entity == parser->m_declEntity)) {
   6457   1.8      maya           if (enc == parser->m_encoding)
   6458   1.8      maya             parser->m_eventPtr = entityTextPtr;
   6459   1.1      tron           result = XML_ERROR_RECURSIVE_ENTITY_REF;
   6460   1.1      tron           goto endEntityValue;
   6461   1.1      tron         }
   6462   1.1      tron         if (entity->systemId) {
   6463   1.8      maya           if (parser->m_externalEntityRefHandler) {
   6464   1.1      tron             dtd->paramEntityRead = XML_FALSE;
   6465   1.1      tron             entity->open = XML_TRUE;
   6466   1.9  christos             entityTrackingOnOpen(parser, entity, __LINE__);
   6467   1.8      maya             if (! parser->m_externalEntityRefHandler(
   6468   1.8      maya                     parser->m_externalEntityRefHandlerArg, 0, entity->base,
   6469   1.8      maya                     entity->systemId, entity->publicId)) {
   6470   1.9  christos               entityTrackingOnClose(parser, entity, __LINE__);
   6471   1.1      tron               entity->open = XML_FALSE;
   6472   1.1      tron               result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
   6473   1.1      tron               goto endEntityValue;
   6474   1.1      tron             }
   6475   1.9  christos             entityTrackingOnClose(parser, entity, __LINE__);
   6476   1.1      tron             entity->open = XML_FALSE;
   6477   1.8      maya             if (! dtd->paramEntityRead)
   6478   1.1      tron               dtd->keepProcessing = dtd->standalone;
   6479   1.8      maya           } else
   6480   1.1      tron             dtd->keepProcessing = dtd->standalone;
   6481   1.8      maya         } else {
   6482  1.10       wiz           result = processEntity(parser, entity, XML_FALSE, ENTITY_VALUE);
   6483  1.10       wiz           goto endEntityValue;
   6484   1.1      tron         }
   6485   1.1      tron         break;
   6486   1.1      tron       }
   6487  1.10       wiz #  endif /* XML_DTD */
   6488   1.1      tron       /* In the internal subset, PE references are not legal
   6489   1.1      tron          within markup declarations, e.g entity values in this case. */
   6490   1.8      maya       parser->m_eventPtr = entityTextPtr;
   6491   1.1      tron       result = XML_ERROR_PARAM_ENTITY_REF;
   6492   1.1      tron       goto endEntityValue;
   6493   1.1      tron     case XML_TOK_NONE:
   6494   1.1      tron       result = XML_ERROR_NONE;
   6495   1.1      tron       goto endEntityValue;
   6496   1.1      tron     case XML_TOK_ENTITY_REF:
   6497   1.1      tron     case XML_TOK_DATA_CHARS:
   6498   1.8      maya       if (! poolAppend(pool, enc, entityTextPtr, next)) {
   6499   1.1      tron         result = XML_ERROR_NO_MEMORY;
   6500   1.1      tron         goto endEntityValue;
   6501   1.1      tron       }
   6502   1.1      tron       break;
   6503   1.1      tron     case XML_TOK_TRAILING_CR:
   6504   1.1      tron       next = entityTextPtr + enc->minBytesPerChar;
   6505   1.1      tron       /* fall through */
   6506   1.1      tron     case XML_TOK_DATA_NEWLINE:
   6507   1.8      maya       if (pool->end == pool->ptr && ! poolGrow(pool)) {
   6508   1.8      maya         result = XML_ERROR_NO_MEMORY;
   6509   1.1      tron         goto endEntityValue;
   6510   1.1      tron       }
   6511   1.1      tron       *(pool->ptr)++ = 0xA;
   6512   1.1      tron       break;
   6513   1.8      maya     case XML_TOK_CHAR_REF: {
   6514   1.8      maya       XML_Char buf[XML_ENCODE_MAX];
   6515   1.8      maya       int i;
   6516   1.8      maya       int n = XmlCharRefNumber(enc, entityTextPtr);
   6517   1.8      maya       if (n < 0) {
   6518   1.8      maya         if (enc == parser->m_encoding)
   6519   1.8      maya           parser->m_eventPtr = entityTextPtr;
   6520   1.8      maya         result = XML_ERROR_BAD_CHAR_REF;
   6521   1.8      maya         goto endEntityValue;
   6522   1.8      maya       }
   6523   1.8      maya       n = XmlEncode(n, (ICHAR *)buf);
   6524   1.8      maya       /* The XmlEncode() functions can never return 0 here.  That
   6525   1.8      maya        * error return happens if the code point passed in is either
   6526   1.8      maya        * negative or greater than or equal to 0x110000.  The
   6527   1.8      maya        * XmlCharRefNumber() functions will all return a number
   6528   1.8      maya        * strictly less than 0x110000 or a negative value if an error
   6529   1.8      maya        * occurred.  The negative value is intercepted above, so
   6530   1.8      maya        * XmlEncode() is never passed a value it might return an
   6531   1.8      maya        * error for.
   6532   1.8      maya        */
   6533   1.8      maya       for (i = 0; i < n; i++) {
   6534   1.8      maya         if (pool->end == pool->ptr && ! poolGrow(pool)) {
   6535   1.8      maya           result = XML_ERROR_NO_MEMORY;
   6536   1.1      tron           goto endEntityValue;
   6537   1.1      tron         }
   6538   1.8      maya         *(pool->ptr)++ = buf[i];
   6539   1.1      tron       }
   6540   1.8      maya     } break;
   6541   1.1      tron     case XML_TOK_PARTIAL:
   6542   1.8      maya       if (enc == parser->m_encoding)
   6543   1.8      maya         parser->m_eventPtr = entityTextPtr;
   6544   1.1      tron       result = XML_ERROR_INVALID_TOKEN;
   6545   1.1      tron       goto endEntityValue;
   6546   1.1      tron     case XML_TOK_INVALID:
   6547   1.8      maya       if (enc == parser->m_encoding)
   6548   1.8      maya         parser->m_eventPtr = next;
   6549   1.1      tron       result = XML_ERROR_INVALID_TOKEN;
   6550   1.1      tron       goto endEntityValue;
   6551   1.1      tron     default:
   6552   1.8      maya       /* This default case should be unnecessary -- all the tokens
   6553   1.8      maya        * that XmlEntityValueTok() can return have their own explicit
   6554   1.8      maya        * cases -- but should be retained for safety.  We do however
   6555   1.8      maya        * exclude it from the coverage statistics.
   6556   1.8      maya        *
   6557   1.8      maya        * LCOV_EXCL_START
   6558   1.8      maya        */
   6559   1.8      maya       if (enc == parser->m_encoding)
   6560   1.8      maya         parser->m_eventPtr = entityTextPtr;
   6561   1.1      tron       result = XML_ERROR_UNEXPECTED_STATE;
   6562   1.1      tron       goto endEntityValue;
   6563   1.8      maya       /* LCOV_EXCL_STOP */
   6564   1.1      tron     }
   6565   1.1      tron     entityTextPtr = next;
   6566   1.1      tron   }
   6567   1.1      tron endEntityValue:
   6568  1.10       wiz #  ifdef XML_DTD
   6569   1.8      maya   parser->m_prologState.inEntityValue = oldInEntityValue;
   6570  1.10       wiz #  endif /* XML_DTD */
   6571  1.10       wiz   // If 'nextPtr' is given, it should be updated during the processing
   6572  1.10       wiz   if (nextPtr != NULL) {
   6573  1.10       wiz     *nextPtr = next;
   6574  1.10       wiz   }
   6575  1.10       wiz   return result;
   6576  1.10       wiz }
   6577  1.10       wiz 
   6578  1.10       wiz static enum XML_Error
   6579  1.10       wiz callStoreEntityValue(XML_Parser parser, const ENCODING *enc,
   6580  1.10       wiz                      const char *entityTextPtr, const char *entityTextEnd,
   6581  1.10       wiz                      enum XML_Account account) {
   6582  1.10       wiz   const char *next = entityTextPtr;
   6583  1.10       wiz   enum XML_Error result = XML_ERROR_NONE;
   6584  1.10       wiz   while (1) {
   6585  1.10       wiz     if (! parser->m_openValueEntities) {
   6586  1.10       wiz       result
   6587  1.10       wiz           = storeEntityValue(parser, enc, next, entityTextEnd, account, &next);
   6588  1.10       wiz     } else {
   6589  1.10       wiz       OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openValueEntities;
   6590  1.10       wiz       if (! openEntity)
   6591  1.10       wiz         return XML_ERROR_UNEXPECTED_STATE;
   6592  1.10       wiz 
   6593  1.10       wiz       ENTITY *const entity = openEntity->entity;
   6594  1.10       wiz       const char *const textStart
   6595  1.10       wiz           = ((const char *)entity->textPtr) + entity->processed;
   6596  1.10       wiz       const char *const textEnd
   6597  1.10       wiz           = (const char *)(entity->textPtr + entity->textLen);
   6598  1.10       wiz       /* Set a safe default value in case 'next' does not get set */
   6599  1.10       wiz       const char *nextInEntity = textStart;
   6600  1.10       wiz       if (entity->hasMore) {
   6601  1.10       wiz         result = storeEntityValue(parser, parser->m_internalEncoding, textStart,
   6602  1.10       wiz                                   textEnd, XML_ACCOUNT_ENTITY_EXPANSION,
   6603  1.10       wiz                                   &nextInEntity);
   6604  1.10       wiz         if (result != XML_ERROR_NONE)
   6605  1.10       wiz           break;
   6606  1.10       wiz         // Check if entity is complete, if not, mark down how much of it is
   6607  1.10       wiz         // processed. A XML_SUSPENDED check here is not required as
   6608  1.10       wiz         // appendAttributeValue will never suspend the parser.
   6609  1.10       wiz         if (textEnd != nextInEntity) {
   6610  1.10       wiz           entity->processed
   6611  1.10       wiz               = (int)(nextInEntity - (const char *)entity->textPtr);
   6612  1.10       wiz           continue;
   6613  1.10       wiz         }
   6614  1.10       wiz 
   6615  1.10       wiz         // Entity is complete. We cannot close it here since we need to first
   6616  1.10       wiz         // process its possible inner entities (which are added to the
   6617  1.10       wiz         // m_openValueEntities during storeEntityValue)
   6618  1.10       wiz         entity->hasMore = XML_FALSE;
   6619  1.10       wiz         continue;
   6620  1.10       wiz       } // End of entity processing, "if" block skips the rest
   6621  1.10       wiz 
   6622  1.10       wiz       // Remove fully processed openEntity from open entity list.
   6623  1.10       wiz #  if XML_GE == 1
   6624  1.10       wiz       entityTrackingOnClose(parser, entity, __LINE__);
   6625  1.10       wiz #  endif
   6626  1.10       wiz       // openEntity is m_openValueEntities' head, since we set it at the
   6627  1.10       wiz       // start of this function and because we skipped storeEntityValue call
   6628  1.10       wiz       // with hasMore set to false. This means we can directly remove the head
   6629  1.10       wiz       // of m_openValueEntities
   6630  1.10       wiz       assert(parser->m_openValueEntities == openEntity);
   6631  1.10       wiz       entity->open = XML_FALSE;
   6632  1.10       wiz       parser->m_openValueEntities = parser->m_openValueEntities->next;
   6633  1.10       wiz 
   6634  1.10       wiz       /* put openEntity back in list of free instances */
   6635  1.10       wiz       openEntity->next = parser->m_freeValueEntities;
   6636  1.10       wiz       parser->m_freeValueEntities = openEntity;
   6637  1.10       wiz     }
   6638  1.10       wiz 
   6639  1.10       wiz     // Break if an error occurred or there is nothing left to process
   6640  1.10       wiz     if (result
   6641  1.10       wiz         || (parser->m_openValueEntities == NULL && entityTextEnd == next)) {
   6642  1.10       wiz       break;
   6643  1.10       wiz     }
   6644  1.10       wiz   }
   6645  1.10       wiz 
   6646   1.1      tron   return result;
   6647   1.1      tron }
   6648   1.1      tron 
   6649  1.10       wiz #else /* XML_GE == 0 */
   6650  1.10       wiz 
   6651  1.10       wiz static enum XML_Error
   6652  1.10       wiz storeSelfEntityValue(XML_Parser parser, ENTITY *entity) {
   6653  1.10       wiz   // This will store "&amp;entity123;" in entity->textPtr
   6654  1.10       wiz   // to end up as "&entity123;" in the handler.
   6655  1.10       wiz   const char *const entity_start = "&amp;";
   6656  1.10       wiz   const char *const entity_end = ";";
   6657  1.10       wiz 
   6658  1.10       wiz   STRING_POOL *const pool = &(parser->m_dtd->entityValuePool);
   6659  1.10       wiz   if (! poolAppendString(pool, entity_start)
   6660  1.10       wiz       || ! poolAppendString(pool, entity->name)
   6661  1.10       wiz       || ! poolAppendString(pool, entity_end)) {
   6662  1.10       wiz     poolDiscard(pool);
   6663  1.10       wiz     return XML_ERROR_NO_MEMORY;
   6664  1.10       wiz   }
   6665  1.10       wiz 
   6666  1.10       wiz   entity->textPtr = poolStart(pool);
   6667  1.10       wiz   entity->textLen = (int)(poolLength(pool));
   6668  1.10       wiz   poolFinish(pool);
   6669  1.10       wiz 
   6670  1.10       wiz   return XML_ERROR_NONE;
   6671  1.10       wiz }
   6672  1.10       wiz 
   6673  1.10       wiz #endif /* XML_GE == 0 */
   6674  1.10       wiz 
   6675   1.1      tron static void FASTCALL
   6676   1.8      maya normalizeLines(XML_Char *s) {
   6677   1.1      tron   XML_Char *p;
   6678   1.1      tron   for (;; s++) {
   6679   1.1      tron     if (*s == XML_T('\0'))
   6680   1.1      tron       return;
   6681   1.1      tron     if (*s == 0xD)
   6682   1.1      tron       break;
   6683   1.1      tron   }
   6684   1.1      tron   p = s;
   6685   1.1      tron   do {
   6686   1.1      tron     if (*s == 0xD) {
   6687   1.1      tron       *p++ = 0xA;
   6688   1.1      tron       if (*++s == 0xA)
   6689   1.1      tron         s++;
   6690   1.8      maya     } else
   6691   1.1      tron       *p++ = *s++;
   6692   1.1      tron   } while (*s);
   6693   1.1      tron   *p = XML_T('\0');
   6694   1.1      tron }
   6695   1.1      tron 
   6696   1.1      tron static int
   6697   1.1      tron reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
   6698   1.8      maya                             const char *start, const char *end) {
   6699   1.1      tron   const XML_Char *target;
   6700   1.1      tron   XML_Char *data;
   6701   1.1      tron   const char *tem;
   6702   1.8      maya   if (! parser->m_processingInstructionHandler) {
   6703   1.8      maya     if (parser->m_defaultHandler)
   6704   1.1      tron       reportDefault(parser, enc, start, end);
   6705   1.1      tron     return 1;
   6706   1.1      tron   }
   6707   1.1      tron   start += enc->minBytesPerChar * 2;
   6708   1.1      tron   tem = start + XmlNameLength(enc, start);
   6709   1.8      maya   target = poolStoreString(&parser->m_tempPool, enc, start, tem);
   6710   1.8      maya   if (! target)
   6711   1.1      tron     return 0;
   6712   1.8      maya   poolFinish(&parser->m_tempPool);
   6713   1.8      maya   data = poolStoreString(&parser->m_tempPool, enc, XmlSkipS(enc, tem),
   6714   1.8      maya                          end - enc->minBytesPerChar * 2);
   6715   1.8      maya   if (! data)
   6716   1.1      tron     return 0;
   6717   1.1      tron   normalizeLines(data);
   6718   1.8      maya   parser->m_processingInstructionHandler(parser->m_handlerArg, target, data);
   6719   1.8      maya   poolClear(&parser->m_tempPool);
   6720   1.1      tron   return 1;
   6721   1.1      tron }
   6722   1.1      tron 
   6723   1.1      tron static int
   6724   1.8      maya reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
   6725   1.8      maya               const char *end) {
   6726   1.1      tron   XML_Char *data;
   6727   1.8      maya   if (! parser->m_commentHandler) {
   6728   1.8      maya     if (parser->m_defaultHandler)
   6729   1.1      tron       reportDefault(parser, enc, start, end);
   6730   1.1      tron     return 1;
   6731   1.1      tron   }
   6732   1.8      maya   data = poolStoreString(&parser->m_tempPool, enc,
   6733   1.1      tron                          start + enc->minBytesPerChar * 4,
   6734   1.1      tron                          end - enc->minBytesPerChar * 3);
   6735   1.8      maya   if (! data)
   6736   1.1      tron     return 0;
   6737   1.1      tron   normalizeLines(data);
   6738   1.8      maya   parser->m_commentHandler(parser->m_handlerArg, data);
   6739   1.8      maya   poolClear(&parser->m_tempPool);
   6740   1.1      tron   return 1;
   6741   1.1      tron }
   6742   1.1      tron 
   6743   1.1      tron static void
   6744   1.8      maya reportDefault(XML_Parser parser, const ENCODING *enc, const char *s,
   6745   1.8      maya               const char *end) {
   6746   1.1      tron   if (MUST_CONVERT(enc, s)) {
   6747   1.5       spz     enum XML_Convert_Result convert_res;
   6748   1.1      tron     const char **eventPP;
   6749   1.1      tron     const char **eventEndPP;
   6750   1.8      maya     if (enc == parser->m_encoding) {
   6751   1.8      maya       eventPP = &parser->m_eventPtr;
   6752   1.8      maya       eventEndPP = &parser->m_eventEndPtr;
   6753   1.8      maya     } else {
   6754   1.8      maya       /* To get here, two things must be true; the parser must be
   6755   1.8      maya        * using a character encoding that is not the same as the
   6756   1.8      maya        * encoding passed in, and the encoding passed in must need
   6757   1.8      maya        * conversion to the internal format (UTF-8 unless XML_UNICODE
   6758   1.8      maya        * is defined).  The only occasions on which the encoding passed
   6759   1.8      maya        * in is not the same as the parser's encoding are when it is
   6760   1.8      maya        * the internal encoding (e.g. a previously defined parameter
   6761   1.8      maya        * entity, already converted to internal format).  This by
   6762   1.8      maya        * definition doesn't need conversion, so the whole branch never
   6763   1.8      maya        * gets executed.
   6764   1.8      maya        *
   6765   1.8      maya        * For safety's sake we don't delete these lines and merely
   6766   1.8      maya        * exclude them from coverage statistics.
   6767   1.8      maya        *
   6768   1.8      maya        * LCOV_EXCL_START
   6769   1.8      maya        */
   6770   1.8      maya       eventPP = &(parser->m_openInternalEntities->internalEventPtr);
   6771   1.8      maya       eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
   6772   1.8      maya       /* LCOV_EXCL_STOP */
   6773   1.1      tron     }
   6774   1.1      tron     do {
   6775   1.8      maya       ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
   6776   1.8      maya       convert_res
   6777   1.8      maya           = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
   6778   1.1      tron       *eventEndPP = s;
   6779   1.8      maya       parser->m_defaultHandler(parser->m_handlerArg, parser->m_dataBuf,
   6780   1.8      maya                                (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
   6781   1.1      tron       *eventPP = s;
   6782   1.8      maya     } while ((convert_res != XML_CONVERT_COMPLETED)
   6783   1.8      maya              && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
   6784   1.8      maya   } else
   6785  1.10       wiz     parser->m_defaultHandler(
   6786  1.10       wiz         parser->m_handlerArg, (const XML_Char *)s,
   6787  1.10       wiz         (int)((const XML_Char *)end - (const XML_Char *)s));
   6788   1.1      tron }
   6789   1.1      tron 
   6790   1.1      tron static int
   6791   1.1      tron defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
   6792   1.8      maya                 XML_Bool isId, const XML_Char *value, XML_Parser parser) {
   6793   1.1      tron   DEFAULT_ATTRIBUTE *att;
   6794   1.1      tron   if (value || isId) {
   6795   1.1      tron     /* The handling of default attributes gets messed up if we have
   6796   1.1      tron        a default which duplicates a non-default. */
   6797   1.1      tron     int i;
   6798   1.1      tron     for (i = 0; i < type->nDefaultAtts; i++)
   6799   1.1      tron       if (attId == type->defaultAtts[i].id)
   6800   1.1      tron         return 1;
   6801   1.8      maya     if (isId && ! type->idAtt && ! attId->xmlns)
   6802   1.1      tron       type->idAtt = attId;
   6803   1.1      tron   }
   6804   1.1      tron   if (type->nDefaultAtts == type->allocDefaultAtts) {
   6805   1.1      tron     if (type->allocDefaultAtts == 0) {
   6806   1.1      tron       type->allocDefaultAtts = 8;
   6807   1.8      maya       type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(
   6808   1.8      maya           parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
   6809   1.8      maya       if (! type->defaultAtts) {
   6810   1.8      maya         type->allocDefaultAtts = 0;
   6811   1.1      tron         return 0;
   6812   1.8      maya       }
   6813   1.8      maya     } else {
   6814   1.1      tron       DEFAULT_ATTRIBUTE *temp;
   6815   1.9  christos 
   6816   1.9  christos       /* Detect and prevent integer overflow */
   6817   1.9  christos       if (type->allocDefaultAtts > INT_MAX / 2) {
   6818   1.9  christos         return 0;
   6819   1.9  christos       }
   6820   1.9  christos 
   6821   1.1      tron       int count = type->allocDefaultAtts * 2;
   6822   1.9  christos 
   6823   1.9  christos       /* Detect and prevent integer overflow.
   6824   1.9  christos        * The preprocessor guard addresses the "always false" warning
   6825   1.9  christos        * from -Wtype-limits on platforms where
   6826   1.9  christos        * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   6827   1.9  christos #if UINT_MAX >= SIZE_MAX
   6828   1.9  christos       if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) {
   6829   1.9  christos         return 0;
   6830   1.9  christos       }
   6831   1.9  christos #endif
   6832   1.9  christos 
   6833   1.8      maya       temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
   6834   1.8      maya                                           (count * sizeof(DEFAULT_ATTRIBUTE)));
   6835   1.1      tron       if (temp == NULL)
   6836   1.1      tron         return 0;
   6837   1.1      tron       type->allocDefaultAtts = count;
   6838   1.1      tron       type->defaultAtts = temp;
   6839   1.1      tron     }
   6840   1.1      tron   }
   6841   1.1      tron   att = type->defaultAtts + type->nDefaultAtts;
   6842   1.1      tron   att->id = attId;
   6843   1.1      tron   att->value = value;
   6844   1.1      tron   att->isCdata = isCdata;
   6845   1.8      maya   if (! isCdata)
   6846   1.1      tron     attId->maybeTokenized = XML_TRUE;
   6847   1.1      tron   type->nDefaultAtts += 1;
   6848   1.1      tron   return 1;
   6849   1.1      tron }
   6850   1.1      tron 
   6851   1.1      tron static int
   6852   1.8      maya setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) {
   6853   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   6854   1.1      tron   const XML_Char *name;
   6855   1.1      tron   for (name = elementType->name; *name; name++) {
   6856   1.1      tron     if (*name == XML_T(ASCII_COLON)) {
   6857   1.1      tron       PREFIX *prefix;
   6858   1.1      tron       const XML_Char *s;
   6859   1.1      tron       for (s = elementType->name; s != name; s++) {
   6860   1.8      maya         if (! poolAppendChar(&dtd->pool, *s))
   6861   1.1      tron           return 0;
   6862   1.1      tron       }
   6863   1.8      maya       if (! poolAppendChar(&dtd->pool, XML_T('\0')))
   6864   1.1      tron         return 0;
   6865   1.3       spz       prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
   6866   1.1      tron                                 sizeof(PREFIX));
   6867   1.8      maya       if (! prefix)
   6868   1.1      tron         return 0;
   6869   1.1      tron       if (prefix->name == poolStart(&dtd->pool))
   6870   1.1      tron         poolFinish(&dtd->pool);
   6871   1.1      tron       else
   6872   1.1      tron         poolDiscard(&dtd->pool);
   6873   1.1      tron       elementType->prefix = prefix;
   6874   1.8      maya       break;
   6875   1.1      tron     }
   6876   1.1      tron   }
   6877   1.1      tron   return 1;
   6878   1.1      tron }
   6879   1.1      tron 
   6880   1.1      tron static ATTRIBUTE_ID *
   6881   1.8      maya getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
   6882   1.8      maya                const char *end) {
   6883   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   6884   1.1      tron   ATTRIBUTE_ID *id;
   6885   1.1      tron   const XML_Char *name;
   6886   1.8      maya   if (! poolAppendChar(&dtd->pool, XML_T('\0')))
   6887   1.1      tron     return NULL;
   6888   1.1      tron   name = poolStoreString(&dtd->pool, enc, start, end);
   6889   1.8      maya   if (! name)
   6890   1.1      tron     return NULL;
   6891  1.10       wiz   /* skip quotation mark - its storage will be reused (like in name[-1]) */
   6892   1.1      tron   ++name;
   6893   1.8      maya   id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name,
   6894   1.8      maya                               sizeof(ATTRIBUTE_ID));
   6895   1.8      maya   if (! id)
   6896   1.1      tron     return NULL;
   6897   1.1      tron   if (id->name != name)
   6898   1.1      tron     poolDiscard(&dtd->pool);
   6899   1.1      tron   else {
   6900   1.1      tron     poolFinish(&dtd->pool);
   6901   1.8      maya     if (! parser->m_ns)
   6902   1.1      tron       ;
   6903   1.8      maya     else if (name[0] == XML_T(ASCII_x) && name[1] == XML_T(ASCII_m)
   6904   1.8      maya              && name[2] == XML_T(ASCII_l) && name[3] == XML_T(ASCII_n)
   6905   1.8      maya              && name[4] == XML_T(ASCII_s)
   6906   1.8      maya              && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
   6907   1.1      tron       if (name[5] == XML_T('\0'))
   6908   1.1      tron         id->prefix = &dtd->defaultPrefix;
   6909   1.1      tron       else
   6910   1.8      maya         id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6,
   6911   1.8      maya                                       sizeof(PREFIX));
   6912   1.1      tron       id->xmlns = XML_TRUE;
   6913   1.8      maya     } else {
   6914   1.1      tron       int i;
   6915   1.1      tron       for (i = 0; name[i]; i++) {
   6916   1.1      tron         /* attributes without prefix are *not* in the default namespace */
   6917   1.1      tron         if (name[i] == XML_T(ASCII_COLON)) {
   6918   1.1      tron           int j;
   6919   1.1      tron           for (j = 0; j < i; j++) {
   6920   1.8      maya             if (! poolAppendChar(&dtd->pool, name[j]))
   6921   1.1      tron               return NULL;
   6922   1.1      tron           }
   6923   1.8      maya           if (! poolAppendChar(&dtd->pool, XML_T('\0')))
   6924   1.1      tron             return NULL;
   6925   1.8      maya           id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes,
   6926   1.8      maya                                         poolStart(&dtd->pool), sizeof(PREFIX));
   6927   1.8      maya           if (! id->prefix)
   6928   1.4       spz             return NULL;
   6929   1.1      tron           if (id->prefix->name == poolStart(&dtd->pool))
   6930   1.1      tron             poolFinish(&dtd->pool);
   6931   1.1      tron           else
   6932   1.1      tron             poolDiscard(&dtd->pool);
   6933   1.1      tron           break;
   6934   1.1      tron         }
   6935   1.1      tron       }
   6936   1.1      tron     }
   6937   1.1      tron   }
   6938   1.1      tron   return id;
   6939   1.1      tron }
   6940   1.1      tron 
   6941   1.1      tron #define CONTEXT_SEP XML_T(ASCII_FF)
   6942   1.1      tron 
   6943   1.1      tron static const XML_Char *
   6944   1.8      maya getContext(XML_Parser parser) {
   6945   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   6946   1.1      tron   HASH_TABLE_ITER iter;
   6947   1.1      tron   XML_Bool needSep = XML_FALSE;
   6948   1.1      tron 
   6949   1.1      tron   if (dtd->defaultPrefix.binding) {
   6950   1.1      tron     int i;
   6951   1.1      tron     int len;
   6952   1.8      maya     if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
   6953   1.1      tron       return NULL;
   6954   1.1      tron     len = dtd->defaultPrefix.binding->uriLen;
   6955   1.8      maya     if (parser->m_namespaceSeparator)
   6956   1.1      tron       len--;
   6957   1.8      maya     for (i = 0; i < len; i++) {
   6958   1.8      maya       if (! poolAppendChar(&parser->m_tempPool,
   6959   1.8      maya                            dtd->defaultPrefix.binding->uri[i])) {
   6960   1.8      maya         /* Because of memory caching, I don't believe this line can be
   6961   1.8      maya          * executed.
   6962   1.8      maya          *
   6963   1.8      maya          * This is part of a loop copying the default prefix binding
   6964   1.8      maya          * URI into the parser's temporary string pool.  Previously,
   6965   1.8      maya          * that URI was copied into the same string pool, with a
   6966   1.8      maya          * terminating NUL character, as part of setContext().  When
   6967   1.8      maya          * the pool was cleared, that leaves a block definitely big
   6968   1.8      maya          * enough to hold the URI on the free block list of the pool.
   6969   1.8      maya          * The URI copy in getContext() therefore cannot run out of
   6970   1.8      maya          * memory.
   6971   1.8      maya          *
   6972   1.8      maya          * If the pool is used between the setContext() and
   6973   1.8      maya          * getContext() calls, the worst it can do is leave a bigger
   6974   1.8      maya          * block on the front of the free list.  Given that this is
   6975   1.8      maya          * all somewhat inobvious and program logic can be changed, we
   6976   1.8      maya          * don't delete the line but we do exclude it from the test
   6977   1.8      maya          * coverage statistics.
   6978   1.8      maya          */
   6979   1.8      maya         return NULL; /* LCOV_EXCL_LINE */
   6980   1.8      maya       }
   6981   1.8      maya     }
   6982   1.1      tron     needSep = XML_TRUE;
   6983   1.1      tron   }
   6984   1.1      tron 
   6985   1.1      tron   hashTableIterInit(&iter, &(dtd->prefixes));
   6986   1.1      tron   for (;;) {
   6987   1.1      tron     int i;
   6988   1.1      tron     int len;
   6989   1.1      tron     const XML_Char *s;
   6990   1.1      tron     PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
   6991   1.8      maya     if (! prefix)
   6992   1.1      tron       break;
   6993   1.8      maya     if (! prefix->binding) {
   6994   1.8      maya       /* This test appears to be (justifiable) paranoia.  There does
   6995   1.8      maya        * not seem to be a way of injecting a prefix without a binding
   6996   1.8      maya        * that doesn't get errored long before this function is called.
   6997   1.8      maya        * The test should remain for safety's sake, so we instead
   6998   1.8      maya        * exclude the following line from the coverage statistics.
   6999   1.8      maya        */
   7000   1.8      maya       continue; /* LCOV_EXCL_LINE */
   7001   1.8      maya     }
   7002   1.8      maya     if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
   7003   1.1      tron       return NULL;
   7004   1.1      tron     for (s = prefix->name; *s; s++)
   7005   1.8      maya       if (! poolAppendChar(&parser->m_tempPool, *s))
   7006   1.1      tron         return NULL;
   7007   1.8      maya     if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
   7008   1.1      tron       return NULL;
   7009   1.1      tron     len = prefix->binding->uriLen;
   7010   1.8      maya     if (parser->m_namespaceSeparator)
   7011   1.1      tron       len--;
   7012   1.1      tron     for (i = 0; i < len; i++)
   7013   1.8      maya       if (! poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i]))
   7014   1.1      tron         return NULL;
   7015   1.1      tron     needSep = XML_TRUE;
   7016   1.1      tron   }
   7017   1.1      tron 
   7018   1.1      tron   hashTableIterInit(&iter, &(dtd->generalEntities));
   7019   1.1      tron   for (;;) {
   7020   1.1      tron     const XML_Char *s;
   7021   1.1      tron     ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
   7022   1.8      maya     if (! e)
   7023   1.1      tron       break;
   7024   1.8      maya     if (! e->open)
   7025   1.1      tron       continue;
   7026   1.8      maya     if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
   7027   1.1      tron       return NULL;
   7028   1.1      tron     for (s = e->name; *s; s++)
   7029   1.8      maya       if (! poolAppendChar(&parser->m_tempPool, *s))
   7030   1.1      tron         return 0;
   7031   1.1      tron     needSep = XML_TRUE;
   7032   1.1      tron   }
   7033   1.1      tron 
   7034   1.8      maya   if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
   7035   1.1      tron     return NULL;
   7036   1.8      maya   return parser->m_tempPool.start;
   7037   1.1      tron }
   7038   1.1      tron 
   7039   1.1      tron static XML_Bool
   7040   1.8      maya setContext(XML_Parser parser, const XML_Char *context) {
   7041  1.10       wiz   if (context == NULL) {
   7042  1.10       wiz     return XML_FALSE;
   7043  1.10       wiz   }
   7044  1.10       wiz 
   7045   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   7046   1.1      tron   const XML_Char *s = context;
   7047   1.1      tron 
   7048   1.1      tron   while (*context != XML_T('\0')) {
   7049   1.1      tron     if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
   7050   1.1      tron       ENTITY *e;
   7051   1.8      maya       if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
   7052   1.1      tron         return XML_FALSE;
   7053   1.8      maya       e = (ENTITY *)lookup(parser, &dtd->generalEntities,
   7054   1.8      maya                            poolStart(&parser->m_tempPool), 0);
   7055   1.1      tron       if (e)
   7056   1.1      tron         e->open = XML_TRUE;
   7057   1.1      tron       if (*s != XML_T('\0'))
   7058   1.1      tron         s++;
   7059   1.1      tron       context = s;
   7060   1.8      maya       poolDiscard(&parser->m_tempPool);
   7061   1.8      maya     } else if (*s == XML_T(ASCII_EQUALS)) {
   7062   1.1      tron       PREFIX *prefix;
   7063   1.8      maya       if (poolLength(&parser->m_tempPool) == 0)
   7064   1.1      tron         prefix = &dtd->defaultPrefix;
   7065   1.1      tron       else {
   7066   1.8      maya         if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
   7067   1.1      tron           return XML_FALSE;
   7068   1.8      maya         prefix
   7069   1.8      maya             = (PREFIX *)lookup(parser, &dtd->prefixes,
   7070   1.8      maya                                poolStart(&parser->m_tempPool), sizeof(PREFIX));
   7071   1.8      maya         if (! prefix)
   7072   1.1      tron           return XML_FALSE;
   7073   1.8      maya         if (prefix->name == poolStart(&parser->m_tempPool)) {
   7074   1.1      tron           prefix->name = poolCopyString(&dtd->pool, prefix->name);
   7075   1.8      maya           if (! prefix->name)
   7076   1.1      tron             return XML_FALSE;
   7077   1.1      tron         }
   7078   1.8      maya         poolDiscard(&parser->m_tempPool);
   7079   1.1      tron       }
   7080   1.8      maya       for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0');
   7081   1.1      tron            context++)
   7082   1.8      maya         if (! poolAppendChar(&parser->m_tempPool, *context))
   7083   1.1      tron           return XML_FALSE;
   7084   1.8      maya       if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
   7085   1.1      tron         return XML_FALSE;
   7086   1.8      maya       if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool),
   7087   1.8      maya                      &parser->m_inheritedBindings)
   7088   1.8      maya           != XML_ERROR_NONE)
   7089   1.1      tron         return XML_FALSE;
   7090   1.8      maya       poolDiscard(&parser->m_tempPool);
   7091   1.1      tron       if (*context != XML_T('\0'))
   7092   1.1      tron         ++context;
   7093   1.1      tron       s = context;
   7094   1.8      maya     } else {
   7095   1.8      maya       if (! poolAppendChar(&parser->m_tempPool, *s))
   7096   1.1      tron         return XML_FALSE;
   7097   1.1      tron       s++;
   7098   1.1      tron     }
   7099   1.1      tron   }
   7100   1.1      tron   return XML_TRUE;
   7101   1.1      tron }
   7102   1.1      tron 
   7103   1.1      tron static void FASTCALL
   7104   1.8      maya normalizePublicId(XML_Char *publicId) {
   7105   1.1      tron   XML_Char *p = publicId;
   7106   1.1      tron   XML_Char *s;
   7107   1.1      tron   for (s = publicId; *s; s++) {
   7108   1.1      tron     switch (*s) {
   7109   1.1      tron     case 0x20:
   7110   1.1      tron     case 0xD:
   7111   1.1      tron     case 0xA:
   7112   1.1      tron       if (p != publicId && p[-1] != 0x20)
   7113   1.1      tron         *p++ = 0x20;
   7114   1.1      tron       break;
   7115   1.1      tron     default:
   7116   1.1      tron       *p++ = *s;
   7117   1.1      tron     }
   7118   1.1      tron   }
   7119   1.1      tron   if (p != publicId && p[-1] == 0x20)
   7120   1.1      tron     --p;
   7121   1.1      tron   *p = XML_T('\0');
   7122   1.1      tron }
   7123   1.1      tron 
   7124   1.1      tron static DTD *
   7125   1.8      maya dtdCreate(const XML_Memory_Handling_Suite *ms) {
   7126   1.9  christos   DTD *p = ms->malloc_fcn(sizeof(DTD));
   7127   1.1      tron   if (p == NULL)
   7128   1.1      tron     return p;
   7129   1.1      tron   poolInit(&(p->pool), ms);
   7130   1.1      tron   poolInit(&(p->entityValuePool), ms);
   7131   1.1      tron   hashTableInit(&(p->generalEntities), ms);
   7132   1.1      tron   hashTableInit(&(p->elementTypes), ms);
   7133   1.1      tron   hashTableInit(&(p->attributeIds), ms);
   7134   1.1      tron   hashTableInit(&(p->prefixes), ms);
   7135   1.1      tron #ifdef XML_DTD
   7136   1.1      tron   p->paramEntityRead = XML_FALSE;
   7137   1.1      tron   hashTableInit(&(p->paramEntities), ms);
   7138   1.1      tron #endif /* XML_DTD */
   7139   1.1      tron   p->defaultPrefix.name = NULL;
   7140   1.1      tron   p->defaultPrefix.binding = NULL;
   7141   1.1      tron 
   7142   1.1      tron   p->in_eldecl = XML_FALSE;
   7143   1.1      tron   p->scaffIndex = NULL;
   7144   1.1      tron   p->scaffold = NULL;
   7145   1.1      tron   p->scaffLevel = 0;
   7146   1.1      tron   p->scaffSize = 0;
   7147   1.1      tron   p->scaffCount = 0;
   7148   1.1      tron   p->contentStringLen = 0;
   7149   1.1      tron 
   7150   1.1      tron   p->keepProcessing = XML_TRUE;
   7151   1.1      tron   p->hasParamEntityRefs = XML_FALSE;
   7152   1.1      tron   p->standalone = XML_FALSE;
   7153   1.1      tron   return p;
   7154   1.1      tron }
   7155   1.1      tron 
   7156   1.1      tron static void
   7157   1.8      maya dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {
   7158   1.1      tron   HASH_TABLE_ITER iter;
   7159   1.1      tron   hashTableIterInit(&iter, &(p->elementTypes));
   7160   1.1      tron   for (;;) {
   7161   1.1      tron     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
   7162   1.8      maya     if (! e)
   7163   1.1      tron       break;
   7164   1.1      tron     if (e->allocDefaultAtts != 0)
   7165   1.1      tron       ms->free_fcn(e->defaultAtts);
   7166   1.1      tron   }
   7167   1.1      tron   hashTableClear(&(p->generalEntities));
   7168   1.1      tron #ifdef XML_DTD
   7169   1.1      tron   p->paramEntityRead = XML_FALSE;
   7170   1.1      tron   hashTableClear(&(p->paramEntities));
   7171   1.1      tron #endif /* XML_DTD */
   7172   1.1      tron   hashTableClear(&(p->elementTypes));
   7173   1.1      tron   hashTableClear(&(p->attributeIds));
   7174   1.1      tron   hashTableClear(&(p->prefixes));
   7175   1.1      tron   poolClear(&(p->pool));
   7176   1.1      tron   poolClear(&(p->entityValuePool));
   7177   1.1      tron   p->defaultPrefix.name = NULL;
   7178   1.1      tron   p->defaultPrefix.binding = NULL;
   7179   1.1      tron 
   7180   1.1      tron   p->in_eldecl = XML_FALSE;
   7181   1.1      tron 
   7182   1.1      tron   ms->free_fcn(p->scaffIndex);
   7183   1.1      tron   p->scaffIndex = NULL;
   7184   1.1      tron   ms->free_fcn(p->scaffold);
   7185   1.1      tron   p->scaffold = NULL;
   7186   1.1      tron 
   7187   1.1      tron   p->scaffLevel = 0;
   7188   1.1      tron   p->scaffSize = 0;
   7189   1.1      tron   p->scaffCount = 0;
   7190   1.1      tron   p->contentStringLen = 0;
   7191   1.1      tron 
   7192   1.1      tron   p->keepProcessing = XML_TRUE;
   7193   1.1      tron   p->hasParamEntityRefs = XML_FALSE;
   7194   1.1      tron   p->standalone = XML_FALSE;
   7195   1.1      tron }
   7196   1.1      tron 
   7197   1.1      tron static void
   7198   1.8      maya dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
   7199   1.1      tron   HASH_TABLE_ITER iter;
   7200   1.1      tron   hashTableIterInit(&iter, &(p->elementTypes));
   7201   1.1      tron   for (;;) {
   7202   1.1      tron     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
   7203   1.8      maya     if (! e)
   7204   1.1      tron       break;
   7205   1.1      tron     if (e->allocDefaultAtts != 0)
   7206   1.1      tron       ms->free_fcn(e->defaultAtts);
   7207   1.1      tron   }
   7208   1.1      tron   hashTableDestroy(&(p->generalEntities));
   7209   1.1      tron #ifdef XML_DTD
   7210   1.1      tron   hashTableDestroy(&(p->paramEntities));
   7211   1.1      tron #endif /* XML_DTD */
   7212   1.1      tron   hashTableDestroy(&(p->elementTypes));
   7213   1.1      tron   hashTableDestroy(&(p->attributeIds));
   7214   1.1      tron   hashTableDestroy(&(p->prefixes));
   7215   1.1      tron   poolDestroy(&(p->pool));
   7216   1.1      tron   poolDestroy(&(p->entityValuePool));
   7217   1.1      tron   if (isDocEntity) {
   7218   1.1      tron     ms->free_fcn(p->scaffIndex);
   7219   1.1      tron     ms->free_fcn(p->scaffold);
   7220   1.1      tron   }
   7221   1.1      tron   ms->free_fcn(p);
   7222   1.1      tron }
   7223   1.1      tron 
   7224   1.1      tron /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
   7225   1.1      tron    The new DTD has already been initialized.
   7226   1.1      tron */
   7227   1.1      tron static int
   7228   1.8      maya dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
   7229   1.8      maya         const XML_Memory_Handling_Suite *ms) {
   7230   1.1      tron   HASH_TABLE_ITER iter;
   7231   1.1      tron 
   7232   1.1      tron   /* Copy the prefix table. */
   7233   1.1      tron 
   7234   1.1      tron   hashTableIterInit(&iter, &(oldDtd->prefixes));
   7235   1.1      tron   for (;;) {
   7236   1.1      tron     const XML_Char *name;
   7237   1.1      tron     const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
   7238   1.8      maya     if (! oldP)
   7239   1.1      tron       break;
   7240   1.1      tron     name = poolCopyString(&(newDtd->pool), oldP->name);
   7241   1.8      maya     if (! name)
   7242   1.1      tron       return 0;
   7243   1.8      maya     if (! lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
   7244   1.1      tron       return 0;
   7245   1.1      tron   }
   7246   1.1      tron 
   7247   1.1      tron   hashTableIterInit(&iter, &(oldDtd->attributeIds));
   7248   1.1      tron 
   7249   1.1      tron   /* Copy the attribute id table. */
   7250   1.1      tron 
   7251   1.1      tron   for (;;) {
   7252   1.1      tron     ATTRIBUTE_ID *newA;
   7253   1.1      tron     const XML_Char *name;
   7254   1.1      tron     const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
   7255   1.1      tron 
   7256   1.8      maya     if (! oldA)
   7257   1.1      tron       break;
   7258   1.1      tron     /* Remember to allocate the scratch byte before the name. */
   7259   1.8      maya     if (! poolAppendChar(&(newDtd->pool), XML_T('\0')))
   7260   1.1      tron       return 0;
   7261   1.1      tron     name = poolCopyString(&(newDtd->pool), oldA->name);
   7262   1.8      maya     if (! name)
   7263   1.1      tron       return 0;
   7264   1.1      tron     ++name;
   7265   1.3       spz     newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
   7266   1.1      tron                                   sizeof(ATTRIBUTE_ID));
   7267   1.8      maya     if (! newA)
   7268   1.1      tron       return 0;
   7269   1.1      tron     newA->maybeTokenized = oldA->maybeTokenized;
   7270   1.1      tron     if (oldA->prefix) {
   7271   1.1      tron       newA->xmlns = oldA->xmlns;
   7272   1.1      tron       if (oldA->prefix == &oldDtd->defaultPrefix)
   7273   1.1      tron         newA->prefix = &newDtd->defaultPrefix;
   7274   1.1      tron       else
   7275   1.3       spz         newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
   7276   1.1      tron                                         oldA->prefix->name, 0);
   7277   1.1      tron     }
   7278   1.1      tron   }
   7279   1.1      tron 
   7280   1.1      tron   /* Copy the element type table. */
   7281   1.1      tron 
   7282   1.1      tron   hashTableIterInit(&iter, &(oldDtd->elementTypes));
   7283   1.1      tron 
   7284   1.1      tron   for (;;) {
   7285   1.1      tron     int i;
   7286   1.1      tron     ELEMENT_TYPE *newE;
   7287   1.1      tron     const XML_Char *name;
   7288   1.1      tron     const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
   7289   1.8      maya     if (! oldE)
   7290   1.1      tron       break;
   7291   1.1      tron     name = poolCopyString(&(newDtd->pool), oldE->name);
   7292   1.8      maya     if (! name)
   7293   1.1      tron       return 0;
   7294   1.3       spz     newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
   7295   1.1      tron                                   sizeof(ELEMENT_TYPE));
   7296   1.8      maya     if (! newE)
   7297   1.1      tron       return 0;
   7298   1.1      tron     if (oldE->nDefaultAtts) {
   7299  1.10       wiz       /* Detect and prevent integer overflow.
   7300  1.10       wiz        * The preprocessor guard addresses the "always false" warning
   7301  1.10       wiz        * from -Wtype-limits on platforms where
   7302  1.10       wiz        * sizeof(int) < sizeof(size_t), e.g. on x86_64. */
   7303  1.10       wiz #if UINT_MAX >= SIZE_MAX
   7304  1.10       wiz       if ((size_t)oldE->nDefaultAtts
   7305  1.10       wiz           > ((size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE))) {
   7306  1.10       wiz         return 0;
   7307  1.10       wiz       }
   7308  1.10       wiz #endif
   7309   1.9  christos       newE->defaultAtts
   7310   1.9  christos           = ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
   7311   1.8      maya       if (! newE->defaultAtts) {
   7312   1.1      tron         return 0;
   7313   1.1      tron       }
   7314   1.1      tron     }
   7315   1.1      tron     if (oldE->idAtt)
   7316   1.8      maya       newE->idAtt = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds),
   7317   1.8      maya                                            oldE->idAtt->name, 0);
   7318   1.1      tron     newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
   7319   1.1      tron     if (oldE->prefix)
   7320   1.3       spz       newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
   7321   1.1      tron                                       oldE->prefix->name, 0);
   7322   1.1      tron     for (i = 0; i < newE->nDefaultAtts; i++) {
   7323   1.8      maya       newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(
   7324   1.8      maya           oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
   7325   1.1      tron       newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
   7326   1.1      tron       if (oldE->defaultAtts[i].value) {
   7327   1.1      tron         newE->defaultAtts[i].value
   7328   1.1      tron             = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
   7329   1.8      maya         if (! newE->defaultAtts[i].value)
   7330   1.1      tron           return 0;
   7331   1.8      maya       } else
   7332   1.1      tron         newE->defaultAtts[i].value = NULL;
   7333   1.1      tron     }
   7334   1.1      tron   }
   7335   1.1      tron 
   7336   1.1      tron   /* Copy the entity tables. */
   7337   1.8      maya   if (! copyEntityTable(oldParser, &(newDtd->generalEntities), &(newDtd->pool),
   7338   1.8      maya                         &(oldDtd->generalEntities)))
   7339   1.8      maya     return 0;
   7340   1.1      tron 
   7341   1.1      tron #ifdef XML_DTD
   7342   1.8      maya   if (! copyEntityTable(oldParser, &(newDtd->paramEntities), &(newDtd->pool),
   7343   1.8      maya                         &(oldDtd->paramEntities)))
   7344   1.8      maya     return 0;
   7345   1.1      tron   newDtd->paramEntityRead = oldDtd->paramEntityRead;
   7346   1.1      tron #endif /* XML_DTD */
   7347   1.1      tron 
   7348   1.1      tron   newDtd->keepProcessing = oldDtd->keepProcessing;
   7349   1.1      tron   newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
   7350   1.1      tron   newDtd->standalone = oldDtd->standalone;
   7351   1.1      tron 
   7352   1.1      tron   /* Don't want deep copying for scaffolding */
   7353   1.1      tron   newDtd->in_eldecl = oldDtd->in_eldecl;
   7354   1.1      tron   newDtd->scaffold = oldDtd->scaffold;
   7355   1.1      tron   newDtd->contentStringLen = oldDtd->contentStringLen;
   7356   1.1      tron   newDtd->scaffSize = oldDtd->scaffSize;
   7357   1.1      tron   newDtd->scaffLevel = oldDtd->scaffLevel;
   7358   1.1      tron   newDtd->scaffIndex = oldDtd->scaffIndex;
   7359   1.1      tron 
   7360   1.1      tron   return 1;
   7361   1.8      maya } /* End dtdCopy */
   7362   1.1      tron 
   7363   1.1      tron static int
   7364   1.8      maya copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
   7365   1.8      maya                 STRING_POOL *newPool, const HASH_TABLE *oldTable) {
   7366   1.1      tron   HASH_TABLE_ITER iter;
   7367   1.1      tron   const XML_Char *cachedOldBase = NULL;
   7368   1.1      tron   const XML_Char *cachedNewBase = NULL;
   7369   1.1      tron 
   7370   1.1      tron   hashTableIterInit(&iter, oldTable);
   7371   1.1      tron 
   7372   1.1      tron   for (;;) {
   7373   1.1      tron     ENTITY *newE;
   7374   1.1      tron     const XML_Char *name;
   7375   1.1      tron     const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
   7376   1.8      maya     if (! oldE)
   7377   1.1      tron       break;
   7378   1.1      tron     name = poolCopyString(newPool, oldE->name);
   7379   1.8      maya     if (! name)
   7380   1.1      tron       return 0;
   7381   1.3       spz     newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
   7382   1.8      maya     if (! newE)
   7383   1.1      tron       return 0;
   7384   1.1      tron     if (oldE->systemId) {
   7385   1.1      tron       const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
   7386   1.8      maya       if (! tem)
   7387   1.1      tron         return 0;
   7388   1.1      tron       newE->systemId = tem;
   7389   1.1      tron       if (oldE->base) {
   7390   1.1      tron         if (oldE->base == cachedOldBase)
   7391   1.1      tron           newE->base = cachedNewBase;
   7392   1.1      tron         else {
   7393   1.1      tron           cachedOldBase = oldE->base;
   7394   1.1      tron           tem = poolCopyString(newPool, cachedOldBase);
   7395   1.8      maya           if (! tem)
   7396   1.1      tron             return 0;
   7397   1.1      tron           cachedNewBase = newE->base = tem;
   7398   1.1      tron         }
   7399   1.1      tron       }
   7400   1.1      tron       if (oldE->publicId) {
   7401   1.1      tron         tem = poolCopyString(newPool, oldE->publicId);
   7402   1.8      maya         if (! tem)
   7403   1.1      tron           return 0;
   7404   1.1      tron         newE->publicId = tem;
   7405   1.1      tron       }
   7406   1.8      maya     } else {
   7407   1.8      maya       const XML_Char *tem
   7408   1.8      maya           = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
   7409   1.8      maya       if (! tem)
   7410   1.1      tron         return 0;
   7411   1.1      tron       newE->textPtr = tem;
   7412   1.1      tron       newE->textLen = oldE->textLen;
   7413   1.1      tron     }
   7414   1.1      tron     if (oldE->notation) {
   7415   1.1      tron       const XML_Char *tem = poolCopyString(newPool, oldE->notation);
   7416   1.8      maya       if (! tem)
   7417   1.1      tron         return 0;
   7418   1.1      tron       newE->notation = tem;
   7419   1.1      tron     }
   7420   1.1      tron     newE->is_param = oldE->is_param;
   7421   1.1      tron     newE->is_internal = oldE->is_internal;
   7422   1.1      tron   }
   7423   1.1      tron   return 1;
   7424   1.1      tron }
   7425   1.1      tron 
   7426   1.1      tron #define INIT_POWER 6
   7427   1.1      tron 
   7428   1.1      tron static XML_Bool FASTCALL
   7429   1.8      maya keyeq(KEY s1, KEY s2) {
   7430   1.1      tron   for (; *s1 == *s2; s1++, s2++)
   7431   1.1      tron     if (*s1 == 0)
   7432   1.1      tron       return XML_TRUE;
   7433   1.1      tron   return XML_FALSE;
   7434   1.1      tron }
   7435   1.1      tron 
   7436   1.7  christos static size_t
   7437   1.8      maya keylen(KEY s) {
   7438   1.7  christos   size_t len = 0;
   7439   1.8      maya   for (; *s; s++, len++)
   7440   1.8      maya     ;
   7441   1.7  christos   return len;
   7442   1.7  christos }
   7443   1.7  christos 
   7444   1.7  christos static void
   7445   1.8      maya copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
   7446   1.7  christos   key->k[0] = 0;
   7447   1.7  christos   key->k[1] = get_hash_secret_salt(parser);
   7448   1.7  christos }
   7449   1.7  christos 
   7450   1.1      tron static unsigned long FASTCALL
   7451   1.8      maya hash(XML_Parser parser, KEY s) {
   7452   1.7  christos   struct siphash state;
   7453   1.7  christos   struct sipkey key;
   7454   1.7  christos   (void)sip24_valid;
   7455   1.7  christos   copy_salt_to_sipkey(parser, &key);
   7456   1.7  christos   sip24_init(&state, &key);
   7457   1.7  christos   sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
   7458   1.7  christos   return (unsigned long)sip24_final(&state);
   7459   1.1      tron }
   7460   1.1      tron 
   7461   1.1      tron static NAMED *
   7462   1.8      maya lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
   7463   1.1      tron   size_t i;
   7464   1.1      tron   if (table->size == 0) {
   7465   1.1      tron     size_t tsize;
   7466   1.8      maya     if (! createSize)
   7467   1.1      tron       return NULL;
   7468   1.1      tron     table->power = INIT_POWER;
   7469   1.1      tron     /* table->size is a power of 2 */
   7470   1.1      tron     table->size = (size_t)1 << INIT_POWER;
   7471   1.1      tron     tsize = table->size * sizeof(NAMED *);
   7472   1.9  christos     table->v = table->mem->malloc_fcn(tsize);
   7473   1.8      maya     if (! table->v) {
   7474   1.1      tron       table->size = 0;
   7475   1.1      tron       return NULL;
   7476   1.1      tron     }
   7477   1.1      tron     memset(table->v, 0, tsize);
   7478   1.3       spz     i = hash(parser, name) & ((unsigned long)table->size - 1);
   7479   1.8      maya   } else {
   7480   1.3       spz     unsigned long h = hash(parser, name);
   7481   1.1      tron     unsigned long mask = (unsigned long)table->size - 1;
   7482   1.1      tron     unsigned char step = 0;
   7483   1.1      tron     i = h & mask;
   7484   1.1      tron     while (table->v[i]) {
   7485   1.1      tron       if (keyeq(name, table->v[i]->name))
   7486   1.1      tron         return table->v[i];
   7487   1.8      maya       if (! step)
   7488   1.1      tron         step = PROBE_STEP(h, mask, table->power);
   7489   1.1      tron       i < step ? (i += table->size - step) : (i -= step);
   7490   1.1      tron     }
   7491   1.8      maya     if (! createSize)
   7492   1.1      tron       return NULL;
   7493   1.1      tron 
   7494   1.1      tron     /* check for overflow (table is half full) */
   7495   1.1      tron     if (table->used >> (table->power - 1)) {
   7496   1.1      tron       unsigned char newPower = table->power + 1;
   7497   1.9  christos 
   7498   1.9  christos       /* Detect and prevent invalid shift */
   7499   1.9  christos       if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
   7500   1.9  christos         return NULL;
   7501   1.9  christos       }
   7502   1.9  christos 
   7503   1.1      tron       size_t newSize = (size_t)1 << newPower;
   7504   1.1      tron       unsigned long newMask = (unsigned long)newSize - 1;
   7505   1.9  christos 
   7506   1.9  christos       /* Detect and prevent integer overflow */
   7507   1.9  christos       if (newSize > (size_t)(-1) / sizeof(NAMED *)) {
   7508   1.9  christos         return NULL;
   7509   1.9  christos       }
   7510   1.9  christos 
   7511   1.1      tron       size_t tsize = newSize * sizeof(NAMED *);
   7512   1.9  christos       NAMED **newV = table->mem->malloc_fcn(tsize);
   7513   1.8      maya       if (! newV)
   7514   1.1      tron         return NULL;
   7515   1.1      tron       memset(newV, 0, tsize);
   7516   1.1      tron       for (i = 0; i < table->size; i++)
   7517   1.1      tron         if (table->v[i]) {
   7518   1.3       spz           unsigned long newHash = hash(parser, table->v[i]->name);
   7519   1.1      tron           size_t j = newHash & newMask;
   7520   1.1      tron           step = 0;
   7521   1.1      tron           while (newV[j]) {
   7522   1.8      maya             if (! step)
   7523   1.1      tron               step = PROBE_STEP(newHash, newMask, newPower);
   7524   1.1      tron             j < step ? (j += newSize - step) : (j -= step);
   7525   1.1      tron           }
   7526   1.1      tron           newV[j] = table->v[i];
   7527   1.1      tron         }
   7528   1.1      tron       table->mem->free_fcn(table->v);
   7529   1.1      tron       table->v = newV;
   7530   1.1      tron       table->power = newPower;
   7531   1.1      tron       table->size = newSize;
   7532   1.1      tron       i = h & newMask;
   7533   1.1      tron       step = 0;
   7534   1.1      tron       while (table->v[i]) {
   7535   1.8      maya         if (! step)
   7536   1.1      tron           step = PROBE_STEP(h, newMask, newPower);
   7537   1.1      tron         i < step ? (i += newSize - step) : (i -= step);
   7538   1.1      tron       }
   7539   1.1      tron     }
   7540   1.1      tron   }
   7541   1.9  christos   table->v[i] = table->mem->malloc_fcn(createSize);
   7542   1.8      maya   if (! table->v[i])
   7543   1.1      tron     return NULL;
   7544   1.1      tron   memset(table->v[i], 0, createSize);
   7545   1.1      tron   table->v[i]->name = name;
   7546   1.1      tron   (table->used)++;
   7547   1.1      tron   return table->v[i];
   7548   1.1      tron }
   7549   1.1      tron 
   7550   1.1      tron static void FASTCALL
   7551   1.8      maya hashTableClear(HASH_TABLE *table) {
   7552   1.1      tron   size_t i;
   7553   1.1      tron   for (i = 0; i < table->size; i++) {
   7554   1.1      tron     table->mem->free_fcn(table->v[i]);
   7555   1.1      tron     table->v[i] = NULL;
   7556   1.1      tron   }
   7557   1.1      tron   table->used = 0;
   7558   1.1      tron }
   7559   1.1      tron 
   7560   1.1      tron static void FASTCALL
   7561   1.8      maya hashTableDestroy(HASH_TABLE *table) {
   7562   1.1      tron   size_t i;
   7563   1.1      tron   for (i = 0; i < table->size; i++)
   7564   1.1      tron     table->mem->free_fcn(table->v[i]);
   7565   1.1      tron   table->mem->free_fcn(table->v);
   7566   1.1      tron }
   7567   1.1      tron 
   7568   1.1      tron static void FASTCALL
   7569   1.8      maya hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) {
   7570   1.1      tron   p->power = 0;
   7571   1.1      tron   p->size = 0;
   7572   1.1      tron   p->used = 0;
   7573   1.1      tron   p->v = NULL;
   7574   1.1      tron   p->mem = ms;
   7575   1.1      tron }
   7576   1.1      tron 
   7577   1.1      tron static void FASTCALL
   7578   1.8      maya hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
   7579   1.1      tron   iter->p = table->v;
   7580   1.9  christos   iter->end = iter->p ? iter->p + table->size : NULL;
   7581   1.1      tron }
   7582   1.1      tron 
   7583   1.8      maya static NAMED *FASTCALL
   7584   1.8      maya hashTableIterNext(HASH_TABLE_ITER *iter) {
   7585   1.1      tron   while (iter->p != iter->end) {
   7586   1.1      tron     NAMED *tem = *(iter->p)++;
   7587   1.1      tron     if (tem)
   7588   1.1      tron       return tem;
   7589   1.1      tron   }
   7590   1.1      tron   return NULL;
   7591   1.1      tron }
   7592   1.1      tron 
   7593   1.1      tron static void FASTCALL
   7594   1.8      maya poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) {
   7595   1.1      tron   pool->blocks = NULL;
   7596   1.1      tron   pool->freeBlocks = NULL;
   7597   1.1      tron   pool->start = NULL;
   7598   1.1      tron   pool->ptr = NULL;
   7599   1.1      tron   pool->end = NULL;
   7600   1.1      tron   pool->mem = ms;
   7601   1.1      tron }
   7602   1.1      tron 
   7603   1.1      tron static void FASTCALL
   7604   1.8      maya poolClear(STRING_POOL *pool) {
   7605   1.8      maya   if (! pool->freeBlocks)
   7606   1.1      tron     pool->freeBlocks = pool->blocks;
   7607   1.1      tron   else {
   7608   1.1      tron     BLOCK *p = pool->blocks;
   7609   1.1      tron     while (p) {
   7610   1.1      tron       BLOCK *tem = p->next;
   7611   1.1      tron       p->next = pool->freeBlocks;
   7612   1.1      tron       pool->freeBlocks = p;
   7613   1.1      tron       p = tem;
   7614   1.1      tron     }
   7615   1.1      tron   }
   7616   1.1      tron   pool->blocks = NULL;
   7617   1.1      tron   pool->start = NULL;
   7618   1.1      tron   pool->ptr = NULL;
   7619   1.1      tron   pool->end = NULL;
   7620   1.1      tron }
   7621   1.1      tron 
   7622   1.1      tron static void FASTCALL
   7623   1.8      maya poolDestroy(STRING_POOL *pool) {
   7624   1.1      tron   BLOCK *p = pool->blocks;
   7625   1.1      tron   while (p) {
   7626   1.1      tron     BLOCK *tem = p->next;
   7627   1.1      tron     pool->mem->free_fcn(p);
   7628   1.1      tron     p = tem;
   7629   1.1      tron   }
   7630   1.1      tron   p = pool->freeBlocks;
   7631   1.1      tron   while (p) {
   7632   1.1      tron     BLOCK *tem = p->next;
   7633   1.1      tron     pool->mem->free_fcn(p);
   7634   1.1      tron     p = tem;
   7635   1.1      tron   }
   7636   1.1      tron }
   7637   1.1      tron 
   7638   1.1      tron static XML_Char *
   7639   1.8      maya poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
   7640   1.8      maya            const char *end) {
   7641   1.8      maya   if (! pool->ptr && ! poolGrow(pool))
   7642   1.1      tron     return NULL;
   7643   1.1      tron   for (;;) {
   7644   1.8      maya     const enum XML_Convert_Result convert_res = XmlConvert(
   7645  1.10       wiz         enc, &ptr, end, (ICHAR **)&(pool->ptr), (const ICHAR *)pool->end);
   7646   1.8      maya     if ((convert_res == XML_CONVERT_COMPLETED)
   7647   1.8      maya         || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
   7648   1.1      tron       break;
   7649   1.8      maya     if (! poolGrow(pool))
   7650   1.1      tron       return NULL;
   7651   1.1      tron   }
   7652   1.1      tron   return pool->start;
   7653   1.1      tron }
   7654   1.1      tron 
   7655   1.8      maya static const XML_Char *FASTCALL
   7656   1.8      maya poolCopyString(STRING_POOL *pool, const XML_Char *s) {
   7657   1.1      tron   do {
   7658   1.8      maya     if (! poolAppendChar(pool, *s))
   7659   1.1      tron       return NULL;
   7660   1.1      tron   } while (*s++);
   7661   1.1      tron   s = pool->start;
   7662   1.1      tron   poolFinish(pool);
   7663   1.1      tron   return s;
   7664   1.1      tron }
   7665   1.1      tron 
   7666   1.1      tron static const XML_Char *
   7667   1.8      maya poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) {
   7668   1.8      maya   if (! pool->ptr && ! poolGrow(pool)) {
   7669   1.8      maya     /* The following line is unreachable given the current usage of
   7670   1.8      maya      * poolCopyStringN().  Currently it is called from exactly one
   7671   1.8      maya      * place to copy the text of a simple general entity.  By that
   7672   1.8      maya      * point, the name of the entity is already stored in the pool, so
   7673   1.8      maya      * pool->ptr cannot be NULL.
   7674   1.8      maya      *
   7675   1.8      maya      * If poolCopyStringN() is used elsewhere as it well might be,
   7676   1.8      maya      * this line may well become executable again.  Regardless, this
   7677   1.8      maya      * sort of check shouldn't be removed lightly, so we just exclude
   7678   1.8      maya      * it from the coverage statistics.
   7679   1.8      maya      */
   7680   1.8      maya     return NULL; /* LCOV_EXCL_LINE */
   7681   1.8      maya   }
   7682   1.1      tron   for (; n > 0; --n, s++) {
   7683   1.8      maya     if (! poolAppendChar(pool, *s))
   7684   1.1      tron       return NULL;
   7685   1.1      tron   }
   7686   1.1      tron   s = pool->start;
   7687   1.1      tron   poolFinish(pool);
   7688   1.1      tron   return s;
   7689   1.1      tron }
   7690   1.1      tron 
   7691   1.8      maya static const XML_Char *FASTCALL
   7692   1.8      maya poolAppendString(STRING_POOL *pool, const XML_Char *s) {
   7693   1.1      tron   while (*s) {
   7694   1.8      maya     if (! poolAppendChar(pool, *s))
   7695   1.1      tron       return NULL;
   7696   1.1      tron     s++;
   7697   1.1      tron   }
   7698   1.1      tron   return pool->start;
   7699   1.1      tron }
   7700   1.1      tron 
   7701   1.1      tron static XML_Char *
   7702   1.8      maya poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
   7703   1.8      maya                 const char *end) {
   7704   1.8      maya   if (! poolAppend(pool, enc, ptr, end))
   7705   1.1      tron     return NULL;
   7706   1.8      maya   if (pool->ptr == pool->end && ! poolGrow(pool))
   7707   1.1      tron     return NULL;
   7708   1.1      tron   *(pool->ptr)++ = 0;
   7709   1.1      tron   return pool->start;
   7710   1.1      tron }
   7711   1.1      tron 
   7712   1.7  christos static size_t
   7713   1.8      maya poolBytesToAllocateFor(int blockSize) {
   7714   1.7  christos   /* Unprotected math would be:
   7715   1.7  christos   ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
   7716   1.7  christos   **
   7717   1.7  christos   ** Detect overflow, avoiding _signed_ overflow undefined behavior
   7718   1.7  christos   ** For a + b * c we check b * c in isolation first, so that addition of a
   7719   1.7  christos   ** on top has no chance of making us accept a small non-negative number
   7720   1.7  christos   */
   7721   1.8      maya   const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
   7722   1.7  christos 
   7723   1.7  christos   if (blockSize <= 0)
   7724   1.7  christos     return 0;
   7725   1.7  christos 
   7726   1.7  christos   if (blockSize > (int)(INT_MAX / stretch))
   7727   1.7  christos     return 0;
   7728   1.7  christos 
   7729   1.7  christos   {
   7730   1.7  christos     const int stretchedBlockSize = blockSize * (int)stretch;
   7731   1.8      maya     const int bytesToAllocate
   7732   1.8      maya         = (int)(offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
   7733   1.7  christos     if (bytesToAllocate < 0)
   7734   1.7  christos       return 0;
   7735   1.7  christos 
   7736   1.7  christos     return (size_t)bytesToAllocate;
   7737   1.7  christos   }
   7738   1.7  christos }
   7739   1.7  christos 
   7740   1.1      tron static XML_Bool FASTCALL
   7741   1.8      maya poolGrow(STRING_POOL *pool) {
   7742   1.1      tron   if (pool->freeBlocks) {
   7743   1.1      tron     if (pool->start == 0) {
   7744   1.1      tron       pool->blocks = pool->freeBlocks;
   7745   1.1      tron       pool->freeBlocks = pool->freeBlocks->next;
   7746   1.1      tron       pool->blocks->next = NULL;
   7747   1.1      tron       pool->start = pool->blocks->s;
   7748   1.1      tron       pool->end = pool->start + pool->blocks->size;
   7749   1.1      tron       pool->ptr = pool->start;
   7750   1.1      tron       return XML_TRUE;
   7751   1.1      tron     }
   7752   1.1      tron     if (pool->end - pool->start < pool->freeBlocks->size) {
   7753   1.1      tron       BLOCK *tem = pool->freeBlocks->next;
   7754   1.1      tron       pool->freeBlocks->next = pool->blocks;
   7755   1.1      tron       pool->blocks = pool->freeBlocks;
   7756   1.1      tron       pool->freeBlocks = tem;
   7757   1.1      tron       memcpy(pool->blocks->s, pool->start,
   7758   1.1      tron              (pool->end - pool->start) * sizeof(XML_Char));
   7759   1.1      tron       pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
   7760   1.1      tron       pool->start = pool->blocks->s;
   7761   1.1      tron       pool->end = pool->start + pool->blocks->size;
   7762   1.1      tron       return XML_TRUE;
   7763   1.1      tron     }
   7764   1.1      tron   }
   7765   1.1      tron   if (pool->blocks && pool->start == pool->blocks->s) {
   7766   1.5       spz     BLOCK *temp;
   7767   1.8      maya     int blockSize = (int)((unsigned)(pool->end - pool->start) * 2U);
   7768   1.7  christos     size_t bytesToAllocate;
   7769   1.5       spz 
   7770   1.8      maya     /* NOTE: Needs to be calculated prior to calling `realloc`
   7771   1.8      maya              to avoid dangling pointers: */
   7772   1.8      maya     const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
   7773   1.8      maya 
   7774   1.8      maya     if (blockSize < 0) {
   7775   1.8      maya       /* This condition traps a situation where either more than
   7776   1.8      maya        * INT_MAX/2 bytes have already been allocated.  This isn't
   7777   1.8      maya        * readily testable, since it is unlikely that an average
   7778   1.8      maya        * machine will have that much memory, so we exclude it from the
   7779   1.8      maya        * coverage statistics.
   7780   1.8      maya        */
   7781   1.8      maya       return XML_FALSE; /* LCOV_EXCL_LINE */
   7782   1.8      maya     }
   7783   1.5       spz 
   7784   1.7  christos     bytesToAllocate = poolBytesToAllocateFor(blockSize);
   7785   1.7  christos     if (bytesToAllocate == 0)
   7786   1.7  christos       return XML_FALSE;
   7787   1.7  christos 
   7788   1.8      maya     temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks,
   7789   1.8      maya                                            (unsigned)bytesToAllocate);
   7790   1.3       spz     if (temp == NULL)
   7791   1.1      tron       return XML_FALSE;
   7792   1.3       spz     pool->blocks = temp;
   7793   1.1      tron     pool->blocks->size = blockSize;
   7794   1.8      maya     pool->ptr = pool->blocks->s + offsetInsideBlock;
   7795   1.1      tron     pool->start = pool->blocks->s;
   7796   1.1      tron     pool->end = pool->start + blockSize;
   7797   1.8      maya   } else {
   7798   1.1      tron     BLOCK *tem;
   7799   1.1      tron     int blockSize = (int)(pool->end - pool->start);
   7800   1.7  christos     size_t bytesToAllocate;
   7801   1.5       spz 
   7802   1.8      maya     if (blockSize < 0) {
   7803   1.8      maya       /* This condition traps a situation where either more than
   7804   1.8      maya        * INT_MAX bytes have already been allocated (which is prevented
   7805   1.8      maya        * by various pieces of program logic, not least this one, never
   7806   1.8      maya        * mind the unlikelihood of actually having that much memory) or
   7807   1.8      maya        * the pool control fields have been corrupted (which could
   7808   1.8      maya        * conceivably happen in an extremely buggy user handler
   7809   1.8      maya        * function).  Either way it isn't readily testable, so we
   7810   1.8      maya        * exclude it from the coverage statistics.
   7811   1.8      maya        */
   7812   1.8      maya       return XML_FALSE; /* LCOV_EXCL_LINE */
   7813   1.8      maya     }
   7814   1.5       spz 
   7815   1.1      tron     if (blockSize < INIT_BLOCK_SIZE)
   7816   1.1      tron       blockSize = INIT_BLOCK_SIZE;
   7817   1.7  christos     else {
   7818   1.7  christos       /* Detect overflow, avoiding _signed_ overflow undefined behavior */
   7819   1.7  christos       if ((int)((unsigned)blockSize * 2U) < 0) {
   7820   1.7  christos         return XML_FALSE;
   7821   1.7  christos       }
   7822   1.1      tron       blockSize *= 2;
   7823   1.7  christos     }
   7824   1.7  christos 
   7825   1.7  christos     bytesToAllocate = poolBytesToAllocateFor(blockSize);
   7826   1.7  christos     if (bytesToAllocate == 0)
   7827   1.7  christos       return XML_FALSE;
   7828   1.7  christos 
   7829   1.9  christos     tem = pool->mem->malloc_fcn(bytesToAllocate);
   7830   1.8      maya     if (! tem)
   7831   1.1      tron       return XML_FALSE;
   7832   1.1      tron     tem->size = blockSize;
   7833   1.1      tron     tem->next = pool->blocks;
   7834   1.1      tron     pool->blocks = tem;
   7835   1.1      tron     if (pool->ptr != pool->start)
   7836   1.8      maya       memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
   7837   1.1      tron     pool->ptr = tem->s + (pool->ptr - pool->start);
   7838   1.1      tron     pool->start = tem->s;
   7839   1.1      tron     pool->end = tem->s + blockSize;
   7840   1.1      tron   }
   7841   1.1      tron   return XML_TRUE;
   7842   1.1      tron }
   7843   1.1      tron 
   7844   1.1      tron static int FASTCALL
   7845   1.8      maya nextScaffoldPart(XML_Parser parser) {
   7846   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   7847   1.8      maya   CONTENT_SCAFFOLD *me;
   7848   1.1      tron   int next;
   7849   1.1      tron 
   7850   1.8      maya   if (! dtd->scaffIndex) {
   7851  1.10       wiz     /* Detect and prevent integer overflow.
   7852  1.10       wiz      * The preprocessor guard addresses the "always false" warning
   7853  1.10       wiz      * from -Wtype-limits on platforms where
   7854  1.10       wiz      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   7855  1.10       wiz #if UINT_MAX >= SIZE_MAX
   7856  1.10       wiz     if (parser->m_groupSize > ((size_t)(-1) / sizeof(int))) {
   7857  1.10       wiz       return -1;
   7858  1.10       wiz     }
   7859  1.10       wiz #endif
   7860   1.8      maya     dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
   7861   1.8      maya     if (! dtd->scaffIndex)
   7862   1.1      tron       return -1;
   7863   1.1      tron     dtd->scaffIndex[0] = 0;
   7864   1.1      tron   }
   7865   1.1      tron 
   7866   1.1      tron   if (dtd->scaffCount >= dtd->scaffSize) {
   7867   1.1      tron     CONTENT_SCAFFOLD *temp;
   7868   1.1      tron     if (dtd->scaffold) {
   7869   1.9  christos       /* Detect and prevent integer overflow */
   7870   1.9  christos       if (dtd->scaffSize > UINT_MAX / 2u) {
   7871   1.9  christos         return -1;
   7872   1.9  christos       }
   7873   1.9  christos       /* Detect and prevent integer overflow.
   7874   1.9  christos        * The preprocessor guard addresses the "always false" warning
   7875   1.9  christos        * from -Wtype-limits on platforms where
   7876   1.9  christos        * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   7877   1.9  christos #if UINT_MAX >= SIZE_MAX
   7878   1.9  christos       if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) {
   7879   1.9  christos         return -1;
   7880   1.9  christos       }
   7881   1.9  christos #endif
   7882   1.9  christos 
   7883   1.8      maya       temp = (CONTENT_SCAFFOLD *)REALLOC(
   7884   1.8      maya           parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
   7885   1.1      tron       if (temp == NULL)
   7886   1.1      tron         return -1;
   7887   1.1      tron       dtd->scaffSize *= 2;
   7888   1.8      maya     } else {
   7889   1.8      maya       temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS
   7890   1.8      maya                                                     * sizeof(CONTENT_SCAFFOLD));
   7891   1.1      tron       if (temp == NULL)
   7892   1.1      tron         return -1;
   7893   1.1      tron       dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
   7894   1.1      tron     }
   7895   1.1      tron     dtd->scaffold = temp;
   7896   1.1      tron   }
   7897   1.1      tron   next = dtd->scaffCount++;
   7898   1.1      tron   me = &dtd->scaffold[next];
   7899   1.1      tron   if (dtd->scaffLevel) {
   7900   1.8      maya     CONTENT_SCAFFOLD *parent
   7901   1.8      maya         = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]];
   7902   1.1      tron     if (parent->lastchild) {
   7903   1.1      tron       dtd->scaffold[parent->lastchild].nextsib = next;
   7904   1.1      tron     }
   7905   1.8      maya     if (! parent->childcnt)
   7906   1.1      tron       parent->firstchild = next;
   7907   1.1      tron     parent->lastchild = next;
   7908   1.1      tron     parent->childcnt++;
   7909   1.1      tron   }
   7910   1.1      tron   me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
   7911   1.1      tron   return next;
   7912   1.1      tron }
   7913   1.1      tron 
   7914   1.1      tron static XML_Content *
   7915   1.8      maya build_model(XML_Parser parser) {
   7916   1.9  christos   /* Function build_model transforms the existing parser->m_dtd->scaffold
   7917   1.9  christos    * array of CONTENT_SCAFFOLD tree nodes into a new array of
   7918   1.9  christos    * XML_Content tree nodes followed by a gapless list of zero-terminated
   7919   1.9  christos    * strings. */
   7920   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   7921   1.1      tron   XML_Content *ret;
   7922   1.9  christos   XML_Char *str; /* the current string writing location */
   7923   1.9  christos 
   7924   1.9  christos   /* Detect and prevent integer overflow.
   7925   1.9  christos    * The preprocessor guard addresses the "always false" warning
   7926   1.9  christos    * from -Wtype-limits on platforms where
   7927   1.9  christos    * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
   7928   1.9  christos #if UINT_MAX >= SIZE_MAX
   7929   1.9  christos   if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) {
   7930   1.9  christos     return NULL;
   7931   1.9  christos   }
   7932   1.9  christos   if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) {
   7933   1.9  christos     return NULL;
   7934   1.9  christos   }
   7935   1.9  christos #endif
   7936   1.9  christos   if (dtd->scaffCount * sizeof(XML_Content)
   7937   1.9  christos       > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) {
   7938   1.9  christos     return NULL;
   7939   1.9  christos   }
   7940   1.9  christos 
   7941   1.9  christos   const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
   7942   1.9  christos                             + (dtd->contentStringLen * sizeof(XML_Char)));
   7943   1.1      tron 
   7944   1.8      maya   ret = (XML_Content *)MALLOC(parser, allocsize);
   7945   1.8      maya   if (! ret)
   7946   1.1      tron     return NULL;
   7947   1.1      tron 
   7948   1.9  christos   /* What follows is an iterative implementation (of what was previously done
   7949   1.9  christos    * recursively in a dedicated function called "build_node".  The old recursive
   7950   1.9  christos    * build_node could be forced into stack exhaustion from input as small as a
   7951   1.9  christos    * few megabyte, and so that was a security issue.  Hence, a function call
   7952   1.9  christos    * stack is avoided now by resolving recursion.)
   7953   1.9  christos    *
   7954   1.9  christos    * The iterative approach works as follows:
   7955   1.9  christos    *
   7956   1.9  christos    * - We have two writing pointers, both walking up the result array; one does
   7957   1.9  christos    *   the work, the other creates "jobs" for its colleague to do, and leads
   7958   1.9  christos    *   the way:
   7959   1.9  christos    *
   7960   1.9  christos    *   - The faster one, pointer jobDest, always leads and writes "what job
   7961   1.9  christos    *     to do" by the other, once they reach that place in the
   7962   1.9  christos    *     array: leader "jobDest" stores the source node array index (relative
   7963   1.9  christos    *     to array dtd->scaffold) in field "numchildren".
   7964   1.9  christos    *
   7965   1.9  christos    *   - The slower one, pointer dest, looks at the value stored in the
   7966   1.9  christos    *     "numchildren" field (which actually holds a source node array index
   7967   1.9  christos    *     at that time) and puts the real data from dtd->scaffold in.
   7968   1.9  christos    *
   7969   1.9  christos    * - Before the loop starts, jobDest writes source array index 0
   7970   1.9  christos    *   (where the root node is located) so that dest will have something to do
   7971   1.9  christos    *   when it starts operation.
   7972   1.9  christos    *
   7973   1.9  christos    * - Whenever nodes with children are encountered, jobDest appends
   7974   1.9  christos    *   them as new jobs, in order.  As a result, tree node siblings are
   7975   1.9  christos    *   adjacent in the resulting array, for example:
   7976   1.9  christos    *
   7977   1.9  christos    *     [0] root, has two children
   7978   1.9  christos    *       [1] first child of 0, has three children
   7979   1.9  christos    *         [3] first child of 1, does not have children
   7980   1.9  christos    *         [4] second child of 1, does not have children
   7981   1.9  christos    *         [5] third child of 1, does not have children
   7982   1.9  christos    *       [2] second child of 0, does not have children
   7983   1.9  christos    *
   7984   1.9  christos    *   Or (the same data) presented in flat array view:
   7985   1.9  christos    *
   7986   1.9  christos    *     [0] root, has two children
   7987   1.9  christos    *
   7988   1.9  christos    *     [1] first child of 0, has three children
   7989   1.9  christos    *     [2] second child of 0, does not have children
   7990   1.9  christos    *
   7991   1.9  christos    *     [3] first child of 1, does not have children
   7992   1.9  christos    *     [4] second child of 1, does not have children
   7993   1.9  christos    *     [5] third child of 1, does not have children
   7994   1.9  christos    *
   7995   1.9  christos    * - The algorithm repeats until all target array indices have been processed.
   7996   1.9  christos    */
   7997   1.9  christos   XML_Content *dest = ret; /* tree node writing location, moves upwards */
   7998   1.9  christos   XML_Content *const destLimit = &ret[dtd->scaffCount];
   7999   1.9  christos   XML_Content *jobDest = ret; /* next free writing location in target array */
   8000   1.9  christos   str = (XML_Char *)&ret[dtd->scaffCount];
   8001   1.9  christos 
   8002   1.9  christos   /* Add the starting job, the root node (index 0) of the source tree  */
   8003   1.9  christos   (jobDest++)->numchildren = 0;
   8004   1.9  christos 
   8005   1.9  christos   for (; dest < destLimit; dest++) {
   8006   1.9  christos     /* Retrieve source tree array index from job storage */
   8007   1.9  christos     const int src_node = (int)dest->numchildren;
   8008   1.9  christos 
   8009   1.9  christos     /* Convert item */
   8010   1.9  christos     dest->type = dtd->scaffold[src_node].type;
   8011   1.9  christos     dest->quant = dtd->scaffold[src_node].quant;
   8012   1.9  christos     if (dest->type == XML_CTYPE_NAME) {
   8013   1.9  christos       const XML_Char *src;
   8014   1.9  christos       dest->name = str;
   8015   1.9  christos       src = dtd->scaffold[src_node].name;
   8016   1.9  christos       for (;;) {
   8017   1.9  christos         *str++ = *src;
   8018   1.9  christos         if (! *src)
   8019   1.9  christos           break;
   8020   1.9  christos         src++;
   8021   1.9  christos       }
   8022   1.9  christos       dest->numchildren = 0;
   8023   1.9  christos       dest->children = NULL;
   8024   1.9  christos     } else {
   8025   1.9  christos       unsigned int i;
   8026   1.9  christos       int cn;
   8027   1.9  christos       dest->name = NULL;
   8028   1.9  christos       dest->numchildren = dtd->scaffold[src_node].childcnt;
   8029   1.9  christos       dest->children = jobDest;
   8030   1.9  christos 
   8031   1.9  christos       /* Append scaffold indices of children to array */
   8032   1.9  christos       for (i = 0, cn = dtd->scaffold[src_node].firstchild;
   8033   1.9  christos            i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib)
   8034   1.9  christos         (jobDest++)->numchildren = (unsigned int)cn;
   8035   1.9  christos     }
   8036   1.9  christos   }
   8037   1.1      tron 
   8038   1.1      tron   return ret;
   8039   1.1      tron }
   8040   1.1      tron 
   8041   1.1      tron static ELEMENT_TYPE *
   8042   1.8      maya getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
   8043   1.8      maya                const char *end) {
   8044   1.8      maya   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
   8045   1.1      tron   const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
   8046   1.1      tron   ELEMENT_TYPE *ret;
   8047   1.1      tron 
   8048   1.8      maya   if (! name)
   8049   1.1      tron     return NULL;
   8050   1.8      maya   ret = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
   8051   1.8      maya                                sizeof(ELEMENT_TYPE));
   8052   1.8      maya   if (! ret)
   8053   1.1      tron     return NULL;
   8054   1.1      tron   if (ret->name != name)
   8055   1.1      tron     poolDiscard(&dtd->pool);
   8056   1.1      tron   else {
   8057   1.1      tron     poolFinish(&dtd->pool);
   8058   1.8      maya     if (! setElementTypePrefix(parser, ret))
   8059   1.1      tron       return NULL;
   8060   1.1      tron   }
   8061   1.1      tron   return ret;
   8062   1.1      tron }
   8063   1.8      maya 
   8064   1.8      maya static XML_Char *
   8065   1.8      maya copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
   8066   1.9  christos   size_t charsRequired = 0;
   8067   1.8      maya   XML_Char *result;
   8068   1.8      maya 
   8069   1.8      maya   /* First determine how long the string is */
   8070   1.8      maya   while (s[charsRequired] != 0) {
   8071   1.8      maya     charsRequired++;
   8072   1.8      maya   }
   8073   1.8      maya   /* Include the terminator */
   8074   1.8      maya   charsRequired++;
   8075   1.8      maya 
   8076   1.8      maya   /* Now allocate space for the copy */
   8077   1.8      maya   result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
   8078   1.8      maya   if (result == NULL)
   8079   1.8      maya     return NULL;
   8080   1.8      maya   /* Copy the original into place */
   8081   1.8      maya   memcpy(result, s, charsRequired * sizeof(XML_Char));
   8082   1.8      maya   return result;
   8083   1.8      maya }
   8084   1.9  christos 
   8085  1.10       wiz #if XML_GE == 1
   8086   1.9  christos 
   8087   1.9  christos static float
   8088   1.9  christos accountingGetCurrentAmplification(XML_Parser rootParser) {
   8089  1.10       wiz   //                                          1.........1.........12 => 22
   8090  1.10       wiz   const size_t lenOfShortestInclude = sizeof("<!ENTITY a SYSTEM 'b'>") - 1;
   8091   1.9  christos   const XmlBigCount countBytesOutput
   8092   1.9  christos       = rootParser->m_accounting.countBytesDirect
   8093   1.9  christos         + rootParser->m_accounting.countBytesIndirect;
   8094   1.9  christos   const float amplificationFactor
   8095   1.9  christos       = rootParser->m_accounting.countBytesDirect
   8096   1.9  christos             ? (countBytesOutput
   8097   1.9  christos                / (float)(rootParser->m_accounting.countBytesDirect))
   8098  1.10       wiz             : ((lenOfShortestInclude
   8099  1.10       wiz                 + rootParser->m_accounting.countBytesIndirect)
   8100  1.10       wiz                / (float)lenOfShortestInclude);
   8101   1.9  christos   assert(! rootParser->m_parentParser);
   8102   1.9  christos   return amplificationFactor;
   8103   1.9  christos }
   8104   1.9  christos 
   8105   1.9  christos static void
   8106   1.9  christos accountingReportStats(XML_Parser originParser, const char *epilog) {
   8107   1.9  christos   const XML_Parser rootParser = getRootParserOf(originParser, NULL);
   8108   1.9  christos   assert(! rootParser->m_parentParser);
   8109   1.9  christos 
   8110  1.10       wiz   if (rootParser->m_accounting.debugLevel == 0u) {
   8111   1.9  christos     return;
   8112   1.9  christos   }
   8113   1.9  christos 
   8114   1.9  christos   const float amplificationFactor
   8115   1.9  christos       = accountingGetCurrentAmplification(rootParser);
   8116   1.9  christos   fprintf(stderr,
   8117   1.9  christos           "expat: Accounting(%p): Direct " EXPAT_FMT_ULL(
   8118   1.9  christos               "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s",
   8119   1.9  christos           (void *)rootParser, rootParser->m_accounting.countBytesDirect,
   8120   1.9  christos           rootParser->m_accounting.countBytesIndirect,
   8121   1.9  christos           (double)amplificationFactor, epilog);
   8122   1.9  christos }
   8123   1.9  christos 
   8124   1.9  christos static void
   8125   1.9  christos accountingOnAbort(XML_Parser originParser) {
   8126   1.9  christos   accountingReportStats(originParser, " ABORTING\n");
   8127   1.9  christos }
   8128   1.9  christos 
   8129   1.9  christos static void
   8130   1.9  christos accountingReportDiff(XML_Parser rootParser,
   8131   1.9  christos                      unsigned int levelsAwayFromRootParser, const char *before,
   8132   1.9  christos                      const char *after, ptrdiff_t bytesMore, int source_line,
   8133   1.9  christos                      enum XML_Account account) {
   8134   1.9  christos   assert(! rootParser->m_parentParser);
   8135   1.9  christos 
   8136   1.9  christos   fprintf(stderr,
   8137  1.10       wiz           " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%u, xmlparse.c:%d) %*s\"",
   8138   1.9  christos           bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP",
   8139   1.9  christos           levelsAwayFromRootParser, source_line, 10, "");
   8140   1.9  christos 
   8141   1.9  christos   const char ellipis[] = "[..]";
   8142   1.9  christos   const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1;
   8143   1.9  christos   const unsigned int contextLength = 10;
   8144   1.9  christos 
   8145   1.9  christos   /* Note: Performance is of no concern here */
   8146   1.9  christos   const char *walker = before;
   8147  1.10       wiz   if ((rootParser->m_accounting.debugLevel >= 3u)
   8148   1.9  christos       || (after - before)
   8149   1.9  christos              <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) {
   8150   1.9  christos     for (; walker < after; walker++) {
   8151   1.9  christos       fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
   8152   1.9  christos     }
   8153   1.9  christos   } else {
   8154   1.9  christos     for (; walker < before + contextLength; walker++) {
   8155   1.9  christos       fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
   8156   1.9  christos     }
   8157   1.9  christos     fprintf(stderr, ellipis);
   8158   1.9  christos     walker = after - contextLength;
   8159   1.9  christos     for (; walker < after; walker++) {
   8160   1.9  christos       fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
   8161   1.9  christos     }
   8162   1.9  christos   }
   8163   1.9  christos   fprintf(stderr, "\"\n");
   8164   1.9  christos }
   8165   1.9  christos 
   8166   1.9  christos static XML_Bool
   8167   1.9  christos accountingDiffTolerated(XML_Parser originParser, int tok, const char *before,
   8168   1.9  christos                         const char *after, int source_line,
   8169   1.9  christos                         enum XML_Account account) {
   8170   1.9  christos   /* Note: We need to check the token type *first* to be sure that
   8171   1.9  christos    *       we can even access variable <after>, safely.
   8172   1.9  christos    *       E.g. for XML_TOK_NONE <after> may hold an invalid pointer. */
   8173   1.9  christos   switch (tok) {
   8174   1.9  christos   case XML_TOK_INVALID:
   8175   1.9  christos   case XML_TOK_PARTIAL:
   8176   1.9  christos   case XML_TOK_PARTIAL_CHAR:
   8177   1.9  christos   case XML_TOK_NONE:
   8178   1.9  christos     return XML_TRUE;
   8179   1.9  christos   }
   8180   1.9  christos 
   8181   1.9  christos   if (account == XML_ACCOUNT_NONE)
   8182   1.9  christos     return XML_TRUE; /* because these bytes have been accounted for, already */
   8183   1.9  christos 
   8184   1.9  christos   unsigned int levelsAwayFromRootParser;
   8185   1.9  christos   const XML_Parser rootParser
   8186   1.9  christos       = getRootParserOf(originParser, &levelsAwayFromRootParser);
   8187   1.9  christos   assert(! rootParser->m_parentParser);
   8188   1.9  christos 
   8189   1.9  christos   const int isDirect
   8190   1.9  christos       = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser);
   8191   1.9  christos   const ptrdiff_t bytesMore = after - before;
   8192   1.9  christos 
   8193   1.9  christos   XmlBigCount *const additionTarget
   8194   1.9  christos       = isDirect ? &rootParser->m_accounting.countBytesDirect
   8195   1.9  christos                  : &rootParser->m_accounting.countBytesIndirect;
   8196   1.9  christos 
   8197   1.9  christos   /* Detect and avoid integer overflow */
   8198   1.9  christos   if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore)
   8199   1.9  christos     return XML_FALSE;
   8200   1.9  christos   *additionTarget += bytesMore;
   8201   1.9  christos 
   8202   1.9  christos   const XmlBigCount countBytesOutput
   8203   1.9  christos       = rootParser->m_accounting.countBytesDirect
   8204   1.9  christos         + rootParser->m_accounting.countBytesIndirect;
   8205   1.9  christos   const float amplificationFactor
   8206   1.9  christos       = accountingGetCurrentAmplification(rootParser);
   8207   1.9  christos   const XML_Bool tolerated
   8208   1.9  christos       = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes)
   8209   1.9  christos         || (amplificationFactor
   8210   1.9  christos             <= rootParser->m_accounting.maximumAmplificationFactor);
   8211   1.9  christos 
   8212  1.10       wiz   if (rootParser->m_accounting.debugLevel >= 2u) {
   8213   1.9  christos     accountingReportStats(rootParser, "");
   8214   1.9  christos     accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after,
   8215   1.9  christos                          bytesMore, source_line, account);
   8216   1.9  christos   }
   8217   1.9  christos 
   8218   1.9  christos   return tolerated;
   8219   1.9  christos }
   8220   1.9  christos 
   8221   1.9  christos unsigned long long
   8222   1.9  christos testingAccountingGetCountBytesDirect(XML_Parser parser) {
   8223   1.9  christos   if (! parser)
   8224   1.9  christos     return 0;
   8225   1.9  christos   return parser->m_accounting.countBytesDirect;
   8226   1.9  christos }
   8227   1.9  christos 
   8228   1.9  christos unsigned long long
   8229   1.9  christos testingAccountingGetCountBytesIndirect(XML_Parser parser) {
   8230   1.9  christos   if (! parser)
   8231   1.9  christos     return 0;
   8232   1.9  christos   return parser->m_accounting.countBytesIndirect;
   8233   1.9  christos }
   8234   1.9  christos 
   8235   1.9  christos static void
   8236   1.9  christos entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
   8237   1.9  christos                           const char *action, int sourceLine) {
   8238   1.9  christos   assert(! rootParser->m_parentParser);
   8239  1.10       wiz   if (rootParser->m_entity_stats.debugLevel == 0u)
   8240   1.9  christos     return;
   8241   1.9  christos 
   8242   1.9  christos #  if defined(XML_UNICODE)
   8243   1.9  christos   const char *const entityName = "[..]";
   8244   1.9  christos #  else
   8245   1.9  christos   const char *const entityName = entity->name;
   8246   1.9  christos #  endif
   8247   1.9  christos 
   8248   1.9  christos   fprintf(
   8249   1.9  christos       stderr,
   8250  1.10       wiz       "expat: Entities(%p): Count %9u, depth %2u/%2u %*s%s%s; %s length %d (xmlparse.c:%d)\n",
   8251   1.9  christos       (void *)rootParser, rootParser->m_entity_stats.countEverOpened,
   8252   1.9  christos       rootParser->m_entity_stats.currentDepth,
   8253   1.9  christos       rootParser->m_entity_stats.maximumDepthSeen,
   8254  1.11       wiz       ((int)rootParser->m_entity_stats.currentDepth - 1) * 2, "",
   8255   1.9  christos       entity->is_param ? "%" : "&", entityName, action, entity->textLen,
   8256   1.9  christos       sourceLine);
   8257   1.9  christos }
   8258   1.9  christos 
   8259   1.9  christos static void
   8260   1.9  christos entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) {
   8261   1.9  christos   const XML_Parser rootParser = getRootParserOf(originParser, NULL);
   8262   1.9  christos   assert(! rootParser->m_parentParser);
   8263   1.9  christos 
   8264   1.9  christos   rootParser->m_entity_stats.countEverOpened++;
   8265   1.9  christos   rootParser->m_entity_stats.currentDepth++;
   8266   1.9  christos   if (rootParser->m_entity_stats.currentDepth
   8267   1.9  christos       > rootParser->m_entity_stats.maximumDepthSeen) {
   8268   1.9  christos     rootParser->m_entity_stats.maximumDepthSeen++;
   8269   1.9  christos   }
   8270   1.9  christos 
   8271   1.9  christos   entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine);
   8272   1.9  christos }
   8273   1.9  christos 
   8274   1.9  christos static void
   8275   1.9  christos entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) {
   8276   1.9  christos   const XML_Parser rootParser = getRootParserOf(originParser, NULL);
   8277   1.9  christos   assert(! rootParser->m_parentParser);
   8278   1.9  christos 
   8279   1.9  christos   entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine);
   8280   1.9  christos   rootParser->m_entity_stats.currentDepth--;
   8281   1.9  christos }
   8282   1.9  christos 
   8283   1.9  christos static XML_Parser
   8284   1.9  christos getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {
   8285   1.9  christos   XML_Parser rootParser = parser;
   8286   1.9  christos   unsigned int stepsTakenUpwards = 0;
   8287   1.9  christos   while (rootParser->m_parentParser) {
   8288   1.9  christos     rootParser = rootParser->m_parentParser;
   8289   1.9  christos     stepsTakenUpwards++;
   8290   1.9  christos   }
   8291   1.9  christos   assert(! rootParser->m_parentParser);
   8292   1.9  christos   if (outLevelDiff != NULL) {
   8293   1.9  christos     *outLevelDiff = stepsTakenUpwards;
   8294   1.9  christos   }
   8295   1.9  christos   return rootParser;
   8296   1.9  christos }
   8297   1.9  christos 
   8298   1.9  christos const char *
   8299   1.9  christos unsignedCharToPrintable(unsigned char c) {
   8300   1.9  christos   switch (c) {
   8301   1.9  christos   case 0:
   8302   1.9  christos     return "\\0";
   8303   1.9  christos   case 1:
   8304   1.9  christos     return "\\x1";
   8305   1.9  christos   case 2:
   8306   1.9  christos     return "\\x2";
   8307   1.9  christos   case 3:
   8308   1.9  christos     return "\\x3";
   8309   1.9  christos   case 4:
   8310   1.9  christos     return "\\x4";
   8311   1.9  christos   case 5:
   8312   1.9  christos     return "\\x5";
   8313   1.9  christos   case 6:
   8314   1.9  christos     return "\\x6";
   8315   1.9  christos   case 7:
   8316   1.9  christos     return "\\x7";
   8317   1.9  christos   case 8:
   8318   1.9  christos     return "\\x8";
   8319   1.9  christos   case 9:
   8320   1.9  christos     return "\\t";
   8321   1.9  christos   case 10:
   8322   1.9  christos     return "\\n";
   8323   1.9  christos   case 11:
   8324   1.9  christos     return "\\xB";
   8325   1.9  christos   case 12:
   8326   1.9  christos     return "\\xC";
   8327   1.9  christos   case 13:
   8328   1.9  christos     return "\\r";
   8329   1.9  christos   case 14:
   8330   1.9  christos     return "\\xE";
   8331   1.9  christos   case 15:
   8332   1.9  christos     return "\\xF";
   8333   1.9  christos   case 16:
   8334   1.9  christos     return "\\x10";
   8335   1.9  christos   case 17:
   8336   1.9  christos     return "\\x11";
   8337   1.9  christos   case 18:
   8338   1.9  christos     return "\\x12";
   8339   1.9  christos   case 19:
   8340   1.9  christos     return "\\x13";
   8341   1.9  christos   case 20:
   8342   1.9  christos     return "\\x14";
   8343   1.9  christos   case 21:
   8344   1.9  christos     return "\\x15";
   8345   1.9  christos   case 22:
   8346   1.9  christos     return "\\x16";
   8347   1.9  christos   case 23:
   8348   1.9  christos     return "\\x17";
   8349   1.9  christos   case 24:
   8350   1.9  christos     return "\\x18";
   8351   1.9  christos   case 25:
   8352   1.9  christos     return "\\x19";
   8353   1.9  christos   case 26:
   8354   1.9  christos     return "\\x1A";
   8355   1.9  christos   case 27:
   8356   1.9  christos     return "\\x1B";
   8357   1.9  christos   case 28:
   8358   1.9  christos     return "\\x1C";
   8359   1.9  christos   case 29:
   8360   1.9  christos     return "\\x1D";
   8361   1.9  christos   case 30:
   8362   1.9  christos     return "\\x1E";
   8363   1.9  christos   case 31:
   8364   1.9  christos     return "\\x1F";
   8365   1.9  christos   case 32:
   8366   1.9  christos     return " ";
   8367   1.9  christos   case 33:
   8368   1.9  christos     return "!";
   8369   1.9  christos   case 34:
   8370   1.9  christos     return "\\\"";
   8371   1.9  christos   case 35:
   8372   1.9  christos     return "#";
   8373   1.9  christos   case 36:
   8374   1.9  christos     return "$";
   8375   1.9  christos   case 37:
   8376   1.9  christos     return "%";
   8377   1.9  christos   case 38:
   8378   1.9  christos     return "&";
   8379   1.9  christos   case 39:
   8380   1.9  christos     return "'";
   8381   1.9  christos   case 40:
   8382   1.9  christos     return "(";
   8383   1.9  christos   case 41:
   8384   1.9  christos     return ")";
   8385   1.9  christos   case 42:
   8386   1.9  christos     return "*";
   8387   1.9  christos   case 43:
   8388   1.9  christos     return "+";
   8389   1.9  christos   case 44:
   8390   1.9  christos     return ",";
   8391   1.9  christos   case 45:
   8392   1.9  christos     return "-";
   8393   1.9  christos   case 46:
   8394   1.9  christos     return ".";
   8395   1.9  christos   case 47:
   8396   1.9  christos     return "/";
   8397   1.9  christos   case 48:
   8398   1.9  christos     return "0";
   8399   1.9  christos   case 49:
   8400   1.9  christos     return "1";
   8401   1.9  christos   case 50:
   8402   1.9  christos     return "2";
   8403   1.9  christos   case 51:
   8404   1.9  christos     return "3";
   8405   1.9  christos   case 52:
   8406   1.9  christos     return "4";
   8407   1.9  christos   case 53:
   8408   1.9  christos     return "5";
   8409   1.9  christos   case 54:
   8410   1.9  christos     return "6";
   8411   1.9  christos   case 55:
   8412   1.9  christos     return "7";
   8413   1.9  christos   case 56:
   8414   1.9  christos     return "8";
   8415   1.9  christos   case 57:
   8416   1.9  christos     return "9";
   8417   1.9  christos   case 58:
   8418   1.9  christos     return ":";
   8419   1.9  christos   case 59:
   8420   1.9  christos     return ";";
   8421   1.9  christos   case 60:
   8422   1.9  christos     return "<";
   8423   1.9  christos   case 61:
   8424   1.9  christos     return "=";
   8425   1.9  christos   case 62:
   8426   1.9  christos     return ">";
   8427   1.9  christos   case 63:
   8428   1.9  christos     return "?";
   8429   1.9  christos   case 64:
   8430   1.9  christos     return "@";
   8431   1.9  christos   case 65:
   8432   1.9  christos     return "A";
   8433   1.9  christos   case 66:
   8434   1.9  christos     return "B";
   8435   1.9  christos   case 67:
   8436   1.9  christos     return "C";
   8437   1.9  christos   case 68:
   8438   1.9  christos     return "D";
   8439   1.9  christos   case 69:
   8440   1.9  christos     return "E";
   8441   1.9  christos   case 70:
   8442   1.9  christos     return "F";
   8443   1.9  christos   case 71:
   8444   1.9  christos     return "G";
   8445   1.9  christos   case 72:
   8446   1.9  christos     return "H";
   8447   1.9  christos   case 73:
   8448   1.9  christos     return "I";
   8449   1.9  christos   case 74:
   8450   1.9  christos     return "J";
   8451   1.9  christos   case 75:
   8452   1.9  christos     return "K";
   8453   1.9  christos   case 76:
   8454   1.9  christos     return "L";
   8455   1.9  christos   case 77:
   8456   1.9  christos     return "M";
   8457   1.9  christos   case 78:
   8458   1.9  christos     return "N";
   8459   1.9  christos   case 79:
   8460   1.9  christos     return "O";
   8461   1.9  christos   case 80:
   8462   1.9  christos     return "P";
   8463   1.9  christos   case 81:
   8464   1.9  christos     return "Q";
   8465   1.9  christos   case 82:
   8466   1.9  christos     return "R";
   8467   1.9  christos   case 83:
   8468   1.9  christos     return "S";
   8469   1.9  christos   case 84:
   8470   1.9  christos     return "T";
   8471   1.9  christos   case 85:
   8472   1.9  christos     return "U";
   8473   1.9  christos   case 86:
   8474   1.9  christos     return "V";
   8475   1.9  christos   case 87:
   8476   1.9  christos     return "W";
   8477   1.9  christos   case 88:
   8478   1.9  christos     return "X";
   8479   1.9  christos   case 89:
   8480   1.9  christos     return "Y";
   8481   1.9  christos   case 90:
   8482   1.9  christos     return "Z";
   8483   1.9  christos   case 91:
   8484   1.9  christos     return "[";
   8485   1.9  christos   case 92:
   8486   1.9  christos     return "\\\\";
   8487   1.9  christos   case 93:
   8488   1.9  christos     return "]";
   8489   1.9  christos   case 94:
   8490   1.9  christos     return "^";
   8491   1.9  christos   case 95:
   8492   1.9  christos     return "_";
   8493   1.9  christos   case 96:
   8494   1.9  christos     return "`";
   8495   1.9  christos   case 97:
   8496   1.9  christos     return "a";
   8497   1.9  christos   case 98:
   8498   1.9  christos     return "b";
   8499   1.9  christos   case 99:
   8500   1.9  christos     return "c";
   8501   1.9  christos   case 100:
   8502   1.9  christos     return "d";
   8503   1.9  christos   case 101:
   8504   1.9  christos     return "e";
   8505   1.9  christos   case 102:
   8506   1.9  christos     return "f";
   8507   1.9  christos   case 103:
   8508   1.9  christos     return "g";
   8509   1.9  christos   case 104:
   8510   1.9  christos     return "h";
   8511   1.9  christos   case 105:
   8512   1.9  christos     return "i";
   8513   1.9  christos   case 106:
   8514   1.9  christos     return "j";
   8515   1.9  christos   case 107:
   8516   1.9  christos     return "k";
   8517   1.9  christos   case 108:
   8518   1.9  christos     return "l";
   8519   1.9  christos   case 109:
   8520   1.9  christos     return "m";
   8521   1.9  christos   case 110:
   8522   1.9  christos     return "n";
   8523   1.9  christos   case 111:
   8524   1.9  christos     return "o";
   8525   1.9  christos   case 112:
   8526   1.9  christos     return "p";
   8527   1.9  christos   case 113:
   8528   1.9  christos     return "q";
   8529   1.9  christos   case 114:
   8530   1.9  christos     return "r";
   8531   1.9  christos   case 115:
   8532   1.9  christos     return "s";
   8533   1.9  christos   case 116:
   8534   1.9  christos     return "t";
   8535   1.9  christos   case 117:
   8536   1.9  christos     return "u";
   8537   1.9  christos   case 118:
   8538   1.9  christos     return "v";
   8539   1.9  christos   case 119:
   8540   1.9  christos     return "w";
   8541   1.9  christos   case 120:
   8542   1.9  christos     return "x";
   8543   1.9  christos   case 121:
   8544   1.9  christos     return "y";
   8545   1.9  christos   case 122:
   8546   1.9  christos     return "z";
   8547   1.9  christos   case 123:
   8548   1.9  christos     return "{";
   8549   1.9  christos   case 124:
   8550   1.9  christos     return "|";
   8551   1.9  christos   case 125:
   8552   1.9  christos     return "}";
   8553   1.9  christos   case 126:
   8554   1.9  christos     return "~";
   8555   1.9  christos   case 127:
   8556   1.9  christos     return "\\x7F";
   8557   1.9  christos   case 128:
   8558   1.9  christos     return "\\x80";
   8559   1.9  christos   case 129:
   8560   1.9  christos     return "\\x81";
   8561   1.9  christos   case 130:
   8562   1.9  christos     return "\\x82";
   8563   1.9  christos   case 131:
   8564   1.9  christos     return "\\x83";
   8565   1.9  christos   case 132:
   8566   1.9  christos     return "\\x84";
   8567   1.9  christos   case 133:
   8568   1.9  christos     return "\\x85";
   8569   1.9  christos   case 134:
   8570   1.9  christos     return "\\x86";
   8571   1.9  christos   case 135:
   8572   1.9  christos     return "\\x87";
   8573   1.9  christos   case 136:
   8574   1.9  christos     return "\\x88";
   8575   1.9  christos   case 137:
   8576   1.9  christos     return "\\x89";
   8577   1.9  christos   case 138:
   8578   1.9  christos     return "\\x8A";
   8579   1.9  christos   case 139:
   8580   1.9  christos     return "\\x8B";
   8581   1.9  christos   case 140:
   8582   1.9  christos     return "\\x8C";
   8583   1.9  christos   case 141:
   8584   1.9  christos     return "\\x8D";
   8585   1.9  christos   case 142:
   8586   1.9  christos     return "\\x8E";
   8587   1.9  christos   case 143:
   8588   1.9  christos     return "\\x8F";
   8589   1.9  christos   case 144:
   8590   1.9  christos     return "\\x90";
   8591   1.9  christos   case 145:
   8592   1.9  christos     return "\\x91";
   8593   1.9  christos   case 146:
   8594   1.9  christos     return "\\x92";
   8595   1.9  christos   case 147:
   8596   1.9  christos     return "\\x93";
   8597   1.9  christos   case 148:
   8598   1.9  christos     return "\\x94";
   8599   1.9  christos   case 149:
   8600   1.9  christos     return "\\x95";
   8601   1.9  christos   case 150:
   8602   1.9  christos     return "\\x96";
   8603   1.9  christos   case 151:
   8604   1.9  christos     return "\\x97";
   8605   1.9  christos   case 152:
   8606   1.9  christos     return "\\x98";
   8607   1.9  christos   case 153:
   8608   1.9  christos     return "\\x99";
   8609   1.9  christos   case 154:
   8610   1.9  christos     return "\\x9A";
   8611   1.9  christos   case 155:
   8612   1.9  christos     return "\\x9B";
   8613   1.9  christos   case 156:
   8614   1.9  christos     return "\\x9C";
   8615   1.9  christos   case 157:
   8616   1.9  christos     return "\\x9D";
   8617   1.9  christos   case 158:
   8618   1.9  christos     return "\\x9E";
   8619   1.9  christos   case 159:
   8620   1.9  christos     return "\\x9F";
   8621   1.9  christos   case 160:
   8622   1.9  christos     return "\\xA0";
   8623   1.9  christos   case 161:
   8624   1.9  christos     return "\\xA1";
   8625   1.9  christos   case 162:
   8626   1.9  christos     return "\\xA2";
   8627   1.9  christos   case 163:
   8628   1.9  christos     return "\\xA3";
   8629   1.9  christos   case 164:
   8630   1.9  christos     return "\\xA4";
   8631   1.9  christos   case 165:
   8632   1.9  christos     return "\\xA5";
   8633   1.9  christos   case 166:
   8634   1.9  christos     return "\\xA6";
   8635   1.9  christos   case 167:
   8636   1.9  christos     return "\\xA7";
   8637   1.9  christos   case 168:
   8638   1.9  christos     return "\\xA8";
   8639   1.9  christos   case 169:
   8640   1.9  christos     return "\\xA9";
   8641   1.9  christos   case 170:
   8642   1.9  christos     return "\\xAA";
   8643   1.9  christos   case 171:
   8644   1.9  christos     return "\\xAB";
   8645   1.9  christos   case 172:
   8646   1.9  christos     return "\\xAC";
   8647   1.9  christos   case 173:
   8648   1.9  christos     return "\\xAD";
   8649   1.9  christos   case 174:
   8650   1.9  christos     return "\\xAE";
   8651   1.9  christos   case 175:
   8652   1.9  christos     return "\\xAF";
   8653   1.9  christos   case 176:
   8654   1.9  christos     return "\\xB0";
   8655   1.9  christos   case 177:
   8656   1.9  christos     return "\\xB1";
   8657   1.9  christos   case 178:
   8658   1.9  christos     return "\\xB2";
   8659   1.9  christos   case 179:
   8660   1.9  christos     return "\\xB3";
   8661   1.9  christos   case 180:
   8662   1.9  christos     return "\\xB4";
   8663   1.9  christos   case 181:
   8664   1.9  christos     return "\\xB5";
   8665   1.9  christos   case 182:
   8666   1.9  christos     return "\\xB6";
   8667   1.9  christos   case 183:
   8668   1.9  christos     return "\\xB7";
   8669   1.9  christos   case 184:
   8670   1.9  christos     return "\\xB8";
   8671   1.9  christos   case 185:
   8672   1.9  christos     return "\\xB9";
   8673   1.9  christos   case 186:
   8674   1.9  christos     return "\\xBA";
   8675   1.9  christos   case 187:
   8676   1.9  christos     return "\\xBB";
   8677   1.9  christos   case 188:
   8678   1.9  christos     return "\\xBC";
   8679   1.9  christos   case 189:
   8680   1.9  christos     return "\\xBD";
   8681   1.9  christos   case 190:
   8682   1.9  christos     return "\\xBE";
   8683   1.9  christos   case 191:
   8684   1.9  christos     return "\\xBF";
   8685   1.9  christos   case 192:
   8686   1.9  christos     return "\\xC0";
   8687   1.9  christos   case 193:
   8688   1.9  christos     return "\\xC1";
   8689   1.9  christos   case 194:
   8690   1.9  christos     return "\\xC2";
   8691   1.9  christos   case 195:
   8692   1.9  christos     return "\\xC3";
   8693   1.9  christos   case 196:
   8694   1.9  christos     return "\\xC4";
   8695   1.9  christos   case 197:
   8696   1.9  christos     return "\\xC5";
   8697   1.9  christos   case 198:
   8698   1.9  christos     return "\\xC6";
   8699   1.9  christos   case 199:
   8700   1.9  christos     return "\\xC7";
   8701   1.9  christos   case 200:
   8702   1.9  christos     return "\\xC8";
   8703   1.9  christos   case 201:
   8704   1.9  christos     return "\\xC9";
   8705   1.9  christos   case 202:
   8706   1.9  christos     return "\\xCA";
   8707   1.9  christos   case 203:
   8708   1.9  christos     return "\\xCB";
   8709   1.9  christos   case 204:
   8710   1.9  christos     return "\\xCC";
   8711   1.9  christos   case 205:
   8712   1.9  christos     return "\\xCD";
   8713   1.9  christos   case 206:
   8714   1.9  christos     return "\\xCE";
   8715   1.9  christos   case 207:
   8716   1.9  christos     return "\\xCF";
   8717   1.9  christos   case 208:
   8718   1.9  christos     return "\\xD0";
   8719   1.9  christos   case 209:
   8720   1.9  christos     return "\\xD1";
   8721   1.9  christos   case 210:
   8722   1.9  christos     return "\\xD2";
   8723   1.9  christos   case 211:
   8724   1.9  christos     return "\\xD3";
   8725   1.9  christos   case 212:
   8726   1.9  christos     return "\\xD4";
   8727   1.9  christos   case 213:
   8728   1.9  christos     return "\\xD5";
   8729   1.9  christos   case 214:
   8730   1.9  christos     return "\\xD6";
   8731   1.9  christos   case 215:
   8732   1.9  christos     return "\\xD7";
   8733   1.9  christos   case 216:
   8734   1.9  christos     return "\\xD8";
   8735   1.9  christos   case 217:
   8736   1.9  christos     return "\\xD9";
   8737   1.9  christos   case 218:
   8738   1.9  christos     return "\\xDA";
   8739   1.9  christos   case 219:
   8740   1.9  christos     return "\\xDB";
   8741   1.9  christos   case 220:
   8742   1.9  christos     return "\\xDC";
   8743   1.9  christos   case 221:
   8744   1.9  christos     return "\\xDD";
   8745   1.9  christos   case 222:
   8746   1.9  christos     return "\\xDE";
   8747   1.9  christos   case 223:
   8748   1.9  christos     return "\\xDF";
   8749   1.9  christos   case 224:
   8750   1.9  christos     return "\\xE0";
   8751   1.9  christos   case 225:
   8752   1.9  christos     return "\\xE1";
   8753   1.9  christos   case 226:
   8754   1.9  christos     return "\\xE2";
   8755   1.9  christos   case 227:
   8756   1.9  christos     return "\\xE3";
   8757   1.9  christos   case 228:
   8758   1.9  christos     return "\\xE4";
   8759   1.9  christos   case 229:
   8760   1.9  christos     return "\\xE5";
   8761   1.9  christos   case 230:
   8762   1.9  christos     return "\\xE6";
   8763   1.9  christos   case 231:
   8764   1.9  christos     return "\\xE7";
   8765   1.9  christos   case 232:
   8766   1.9  christos     return "\\xE8";
   8767   1.9  christos   case 233:
   8768   1.9  christos     return "\\xE9";
   8769   1.9  christos   case 234:
   8770   1.9  christos     return "\\xEA";
   8771   1.9  christos   case 235:
   8772   1.9  christos     return "\\xEB";
   8773   1.9  christos   case 236:
   8774   1.9  christos     return "\\xEC";
   8775   1.9  christos   case 237:
   8776   1.9  christos     return "\\xED";
   8777   1.9  christos   case 238:
   8778   1.9  christos     return "\\xEE";
   8779   1.9  christos   case 239:
   8780   1.9  christos     return "\\xEF";
   8781   1.9  christos   case 240:
   8782   1.9  christos     return "\\xF0";
   8783   1.9  christos   case 241:
   8784   1.9  christos     return "\\xF1";
   8785   1.9  christos   case 242:
   8786   1.9  christos     return "\\xF2";
   8787   1.9  christos   case 243:
   8788   1.9  christos     return "\\xF3";
   8789   1.9  christos   case 244:
   8790   1.9  christos     return "\\xF4";
   8791   1.9  christos   case 245:
   8792   1.9  christos     return "\\xF5";
   8793   1.9  christos   case 246:
   8794   1.9  christos     return "\\xF6";
   8795   1.9  christos   case 247:
   8796   1.9  christos     return "\\xF7";
   8797   1.9  christos   case 248:
   8798   1.9  christos     return "\\xF8";
   8799   1.9  christos   case 249:
   8800   1.9  christos     return "\\xF9";
   8801   1.9  christos   case 250:
   8802   1.9  christos     return "\\xFA";
   8803   1.9  christos   case 251:
   8804   1.9  christos     return "\\xFB";
   8805   1.9  christos   case 252:
   8806   1.9  christos     return "\\xFC";
   8807   1.9  christos   case 253:
   8808   1.9  christos     return "\\xFD";
   8809   1.9  christos   case 254:
   8810   1.9  christos     return "\\xFE";
   8811   1.9  christos   case 255:
   8812   1.9  christos     return "\\xFF";
   8813  1.10       wiz   // LCOV_EXCL_START
   8814   1.9  christos   default:
   8815   1.9  christos     assert(0); /* never gets here */
   8816   1.9  christos     return "dead code";
   8817   1.9  christos   }
   8818   1.9  christos   assert(0); /* never gets here */
   8819  1.10       wiz   // LCOV_EXCL_STOP
   8820   1.9  christos }
   8821   1.9  christos 
   8822  1.10       wiz #endif /* XML_GE == 1 */
   8823   1.9  christos 
   8824   1.9  christos static unsigned long
   8825   1.9  christos getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {
   8826   1.9  christos   const char *const valueOrNull = getenv(variableName);
   8827   1.9  christos   if (valueOrNull == NULL) {
   8828   1.9  christos     return defaultDebugLevel;
   8829   1.9  christos   }
   8830   1.9  christos   const char *const value = valueOrNull;
   8831   1.9  christos 
   8832   1.9  christos   errno = 0;
   8833  1.10       wiz   char *afterValue = NULL;
   8834   1.9  christos   unsigned long debugLevel = strtoul(value, &afterValue, 10);
   8835  1.10       wiz   if ((errno != 0) || (afterValue == value) || (afterValue[0] != '\0')) {
   8836   1.9  christos     errno = 0;
   8837   1.9  christos     return defaultDebugLevel;
   8838   1.9  christos   }
   8839   1.9  christos 
   8840   1.9  christos   return debugLevel;
   8841   1.9  christos }
   8842