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