xref: /aosp_15_r20/external/expat/lib/xmlparse.c (revision 6be67779651aebaf20f11e5663acd1ae59e93f66)
1*6be67779SAndroid Build Coastguard Worker /* ba4cdf9bdb534f355a9def4c9e25d20ee8e72f95b0a4d930be52e563f5080196 (2.6.3+)
2*6be67779SAndroid Build Coastguard Worker                             __  __            _
3*6be67779SAndroid Build Coastguard Worker                          ___\ \/ /_ __   __ _| |_
4*6be67779SAndroid Build Coastguard Worker                         / _ \\  /| '_ \ / _` | __|
5*6be67779SAndroid Build Coastguard Worker                        |  __//  \| |_) | (_| | |_
6*6be67779SAndroid Build Coastguard Worker                         \___/_/\_\ .__/ \__,_|\__|
7*6be67779SAndroid Build Coastguard Worker                                  |_| XML parser
8*6be67779SAndroid Build Coastguard Worker 
9*6be67779SAndroid Build Coastguard Worker    Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2000      Clark Cooper <[email protected]>
11*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2000-2006 Fred L. Drake, Jr. <[email protected]>
12*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2001-2002 Greg Stein <[email protected]>
13*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2002-2016 Karl Waclawek <[email protected]>
14*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2005-2009 Steven Solie <[email protected]>
15*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2016      Eric Rahm <[email protected]>
16*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2016-2024 Sebastian Pipping <[email protected]>
17*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2016      Gaurav <[email protected]>
18*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2016      Thomas Beutlich <[email protected]>
19*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2016      Gustavo Grieco <[email protected]>
20*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2016      Pascal Cuoq <[email protected]>
21*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2016      Ed Schouten <[email protected]>
22*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2017-2022 Rhodri James <[email protected]>
23*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2017      Václav Slavík <[email protected]>
24*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2017      Viktor Szakats <[email protected]>
25*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2017      Chanho Park <[email protected]>
26*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2017      Rolf Eike Beer <[email protected]>
27*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2017      Hans Wennborg <[email protected]>
28*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2018      Anton Maklakov <[email protected]>
29*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2018      Benjamin Peterson <[email protected]>
30*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2018      Marco Maggi <[email protected]>
31*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2018      Mariusz Zaborski <[email protected]>
32*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2019      David Loffredo <[email protected]>
33*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2019-2020 Ben Wagner <[email protected]>
34*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2019      Vadim Zeitlin <[email protected]>
35*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2021      Donghee Na <[email protected]>
36*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2022      Samanta Navarro <[email protected]>
37*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2022      Jeffrey Walton <[email protected]>
38*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2022      Jann Horn <[email protected]>
39*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2022      Sean McBride <[email protected]>
40*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2023      Owain Davies <[email protected]>
41*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <[email protected]>
42*6be67779SAndroid Build Coastguard Worker    Copyright (c) 2024      Berkay Eren Ürün <[email protected]>
43*6be67779SAndroid Build Coastguard Worker    Licensed under the MIT license:
44*6be67779SAndroid Build Coastguard Worker 
45*6be67779SAndroid Build Coastguard Worker    Permission is  hereby granted,  free of charge,  to any  person obtaining
46*6be67779SAndroid Build Coastguard Worker    a  copy  of  this  software   and  associated  documentation  files  (the
47*6be67779SAndroid Build Coastguard Worker    "Software"),  to  deal in  the  Software  without restriction,  including
48*6be67779SAndroid Build Coastguard Worker    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
49*6be67779SAndroid Build Coastguard Worker    distribute, sublicense, and/or sell copies of the Software, and to permit
50*6be67779SAndroid Build Coastguard Worker    persons  to whom  the Software  is  furnished to  do so,  subject to  the
51*6be67779SAndroid Build Coastguard Worker    following conditions:
52*6be67779SAndroid Build Coastguard Worker 
53*6be67779SAndroid Build Coastguard Worker    The above copyright  notice and this permission notice  shall be included
54*6be67779SAndroid Build Coastguard Worker    in all copies or substantial portions of the Software.
55*6be67779SAndroid Build Coastguard Worker 
56*6be67779SAndroid Build Coastguard Worker    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
57*6be67779SAndroid Build Coastguard Worker    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
58*6be67779SAndroid Build Coastguard Worker    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
59*6be67779SAndroid Build Coastguard Worker    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
60*6be67779SAndroid Build Coastguard Worker    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
61*6be67779SAndroid Build Coastguard Worker    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
62*6be67779SAndroid Build Coastguard Worker    USE OR OTHER DEALINGS IN THE SOFTWARE.
63*6be67779SAndroid Build Coastguard Worker */
64*6be67779SAndroid Build Coastguard Worker 
65*6be67779SAndroid Build Coastguard Worker #define XML_BUILDING_EXPAT 1
66*6be67779SAndroid Build Coastguard Worker 
67*6be67779SAndroid Build Coastguard Worker #include "expat_config.h"
68*6be67779SAndroid Build Coastguard Worker 
69*6be67779SAndroid Build Coastguard Worker #if ! defined(XML_GE) || (1 - XML_GE - 1 == 2) || (XML_GE < 0) || (XML_GE > 1)
70*6be67779SAndroid Build Coastguard Worker #  error XML_GE (for general entities) must be defined, non-empty, either 1 or 0 (0 to disable, 1 to enable; 1 is a common default)
71*6be67779SAndroid Build Coastguard Worker #endif
72*6be67779SAndroid Build Coastguard Worker 
73*6be67779SAndroid Build Coastguard Worker #if defined(XML_DTD) && XML_GE == 0
74*6be67779SAndroid Build Coastguard Worker #  error Either undefine XML_DTD or define XML_GE to 1.
75*6be67779SAndroid Build Coastguard Worker #endif
76*6be67779SAndroid Build Coastguard Worker 
77*6be67779SAndroid Build Coastguard Worker #if ! defined(XML_CONTEXT_BYTES) || (1 - XML_CONTEXT_BYTES - 1 == 2)           \
78*6be67779SAndroid Build Coastguard Worker     || (XML_CONTEXT_BYTES + 0 < 0)
79*6be67779SAndroid Build Coastguard Worker #  error XML_CONTEXT_BYTES must be defined, non-empty and >=0 (0 to disable, >=1 to enable; 1024 is a common default)
80*6be67779SAndroid Build Coastguard Worker #endif
81*6be67779SAndroid Build Coastguard Worker 
82*6be67779SAndroid Build Coastguard Worker #if defined(HAVE_SYSCALL_GETRANDOM)
83*6be67779SAndroid Build Coastguard Worker #  if ! defined(_GNU_SOURCE)
84*6be67779SAndroid Build Coastguard Worker #    define _GNU_SOURCE 1 /* syscall prototype */
85*6be67779SAndroid Build Coastguard Worker #  endif
86*6be67779SAndroid Build Coastguard Worker #endif
87*6be67779SAndroid Build Coastguard Worker 
88*6be67779SAndroid Build Coastguard Worker #ifdef _WIN32
89*6be67779SAndroid Build Coastguard Worker /* force stdlib to define rand_s() */
90*6be67779SAndroid Build Coastguard Worker #  if ! defined(_CRT_RAND_S)
91*6be67779SAndroid Build Coastguard Worker #    define _CRT_RAND_S
92*6be67779SAndroid Build Coastguard Worker #  endif
93*6be67779SAndroid Build Coastguard Worker #endif
94*6be67779SAndroid Build Coastguard Worker 
95*6be67779SAndroid Build Coastguard Worker #include <stdbool.h>
96*6be67779SAndroid Build Coastguard Worker #include <stddef.h>
97*6be67779SAndroid Build Coastguard Worker #include <string.h> /* memset(), memcpy() */
98*6be67779SAndroid Build Coastguard Worker #include <assert.h>
99*6be67779SAndroid Build Coastguard Worker #include <limits.h> /* UINT_MAX */
100*6be67779SAndroid Build Coastguard Worker #include <stdio.h>  /* fprintf */
101*6be67779SAndroid Build Coastguard Worker #include <stdlib.h> /* getenv, rand_s */
102*6be67779SAndroid Build Coastguard Worker #include <stdint.h> /* uintptr_t */
103*6be67779SAndroid Build Coastguard Worker #include <math.h>   /* isnan */
104*6be67779SAndroid Build Coastguard Worker 
105*6be67779SAndroid Build Coastguard Worker #ifdef _WIN32
106*6be67779SAndroid Build Coastguard Worker #  define getpid GetCurrentProcessId
107*6be67779SAndroid Build Coastguard Worker #else
108*6be67779SAndroid Build Coastguard Worker #  include <sys/time.h>  /* gettimeofday() */
109*6be67779SAndroid Build Coastguard Worker #  include <sys/types.h> /* getpid() */
110*6be67779SAndroid Build Coastguard Worker #  include <unistd.h>    /* getpid() */
111*6be67779SAndroid Build Coastguard Worker #  include <fcntl.h>     /* O_RDONLY */
112*6be67779SAndroid Build Coastguard Worker #  include <errno.h>
113*6be67779SAndroid Build Coastguard Worker #endif
114*6be67779SAndroid Build Coastguard Worker 
115*6be67779SAndroid Build Coastguard Worker #ifdef _WIN32
116*6be67779SAndroid Build Coastguard Worker #  include "winconfig.h"
117*6be67779SAndroid Build Coastguard Worker #endif
118*6be67779SAndroid Build Coastguard Worker 
119*6be67779SAndroid Build Coastguard Worker #include "ascii.h"
120*6be67779SAndroid Build Coastguard Worker #include "expat.h"
121*6be67779SAndroid Build Coastguard Worker #include "siphash.h"
122*6be67779SAndroid Build Coastguard Worker 
123*6be67779SAndroid Build Coastguard Worker #if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
124*6be67779SAndroid Build Coastguard Worker #  if defined(HAVE_GETRANDOM)
125*6be67779SAndroid Build Coastguard Worker #    include <sys/random.h> /* getrandom */
126*6be67779SAndroid Build Coastguard Worker #  else
127*6be67779SAndroid Build Coastguard Worker #    include <unistd.h>      /* syscall */
128*6be67779SAndroid Build Coastguard Worker #    include <sys/syscall.h> /* SYS_getrandom */
129*6be67779SAndroid Build Coastguard Worker #  endif
130*6be67779SAndroid Build Coastguard Worker #  if ! defined(GRND_NONBLOCK)
131*6be67779SAndroid Build Coastguard Worker #    define GRND_NONBLOCK 0x0001
132*6be67779SAndroid Build Coastguard Worker #  endif /* defined(GRND_NONBLOCK) */
133*6be67779SAndroid Build Coastguard Worker #endif   /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
134*6be67779SAndroid Build Coastguard Worker 
135*6be67779SAndroid Build Coastguard Worker #if defined(HAVE_LIBBSD)                                                       \
136*6be67779SAndroid Build Coastguard Worker     && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
137*6be67779SAndroid Build Coastguard Worker #  include <bsd/stdlib.h>
138*6be67779SAndroid Build Coastguard Worker #endif
139*6be67779SAndroid Build Coastguard Worker 
140*6be67779SAndroid Build Coastguard Worker #if defined(_WIN32) && ! defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
141*6be67779SAndroid Build Coastguard Worker #  define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
142*6be67779SAndroid Build Coastguard Worker #endif
143*6be67779SAndroid Build Coastguard Worker 
144*6be67779SAndroid Build Coastguard Worker #if ! defined(HAVE_GETRANDOM) && ! defined(HAVE_SYSCALL_GETRANDOM)             \
145*6be67779SAndroid Build Coastguard Worker     && ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)            \
146*6be67779SAndroid Build Coastguard Worker     && ! defined(XML_DEV_URANDOM) && ! defined(_WIN32)                         \
147*6be67779SAndroid Build Coastguard Worker     && ! defined(XML_POOR_ENTROPY)
148*6be67779SAndroid Build Coastguard Worker #  error You do not have support for any sources of high quality entropy \
149*6be67779SAndroid Build Coastguard Worker     enabled.  For end user security, that is probably not what you want. \
150*6be67779SAndroid Build Coastguard Worker     \
151*6be67779SAndroid Build Coastguard Worker     Your options include: \
152*6be67779SAndroid Build Coastguard Worker       * Linux >=3.17 + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \
153*6be67779SAndroid Build Coastguard Worker       * Linux >=3.17 + glibc (including <2.25) (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \
154*6be67779SAndroid Build Coastguard Worker       * BSD / macOS >=10.7 / glibc >=2.36 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \
155*6be67779SAndroid Build Coastguard Worker       * BSD / macOS (including <10.7) / glibc >=2.36 (arc4random): HAVE_ARC4RANDOM, \
156*6be67779SAndroid Build Coastguard Worker       * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
157*6be67779SAndroid Build Coastguard Worker       * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
158*6be67779SAndroid Build Coastguard Worker       * Linux (including <3.17) / BSD / macOS (including <10.7) / Solaris >=8 (/dev/urandom): XML_DEV_URANDOM, \
159*6be67779SAndroid Build Coastguard Worker       * Windows >=Vista (rand_s): _WIN32. \
160*6be67779SAndroid Build Coastguard Worker     \
161*6be67779SAndroid Build Coastguard Worker     If insist on not using any of these, bypass this error by defining \
162*6be67779SAndroid Build Coastguard Worker     XML_POOR_ENTROPY; you have been warned. \
163*6be67779SAndroid Build Coastguard Worker     \
164*6be67779SAndroid Build Coastguard Worker     If you have reasons to patch this detection code away or need changes \
165*6be67779SAndroid Build Coastguard Worker     to the build system, please open a bug.  Thank you!
166*6be67779SAndroid Build Coastguard Worker #endif
167*6be67779SAndroid Build Coastguard Worker 
168*6be67779SAndroid Build Coastguard Worker #ifdef XML_UNICODE
169*6be67779SAndroid Build Coastguard Worker #  define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
170*6be67779SAndroid Build Coastguard Worker #  define XmlConvert XmlUtf16Convert
171*6be67779SAndroid Build Coastguard Worker #  define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
172*6be67779SAndroid Build Coastguard Worker #  define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
173*6be67779SAndroid Build Coastguard Worker #  define XmlEncode XmlUtf16Encode
174*6be67779SAndroid Build Coastguard Worker #  define MUST_CONVERT(enc, s) (! (enc)->isUtf16 || (((uintptr_t)(s)) & 1))
175*6be67779SAndroid Build Coastguard Worker typedef unsigned short ICHAR;
176*6be67779SAndroid Build Coastguard Worker #else
177*6be67779SAndroid Build Coastguard Worker #  define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
178*6be67779SAndroid Build Coastguard Worker #  define XmlConvert XmlUtf8Convert
179*6be67779SAndroid Build Coastguard Worker #  define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
180*6be67779SAndroid Build Coastguard Worker #  define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
181*6be67779SAndroid Build Coastguard Worker #  define XmlEncode XmlUtf8Encode
182*6be67779SAndroid Build Coastguard Worker #  define MUST_CONVERT(enc, s) (! (enc)->isUtf8)
183*6be67779SAndroid Build Coastguard Worker typedef char ICHAR;
184*6be67779SAndroid Build Coastguard Worker #endif
185*6be67779SAndroid Build Coastguard Worker 
186*6be67779SAndroid Build Coastguard Worker #ifndef XML_NS
187*6be67779SAndroid Build Coastguard Worker 
188*6be67779SAndroid Build Coastguard Worker #  define XmlInitEncodingNS XmlInitEncoding
189*6be67779SAndroid Build Coastguard Worker #  define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
190*6be67779SAndroid Build Coastguard Worker #  undef XmlGetInternalEncodingNS
191*6be67779SAndroid Build Coastguard Worker #  define XmlGetInternalEncodingNS XmlGetInternalEncoding
192*6be67779SAndroid Build Coastguard Worker #  define XmlParseXmlDeclNS XmlParseXmlDecl
193*6be67779SAndroid Build Coastguard Worker 
194*6be67779SAndroid Build Coastguard Worker #endif
195*6be67779SAndroid Build Coastguard Worker 
196*6be67779SAndroid Build Coastguard Worker #ifdef XML_UNICODE
197*6be67779SAndroid Build Coastguard Worker 
198*6be67779SAndroid Build Coastguard Worker #  ifdef XML_UNICODE_WCHAR_T
199*6be67779SAndroid Build Coastguard Worker #    define XML_T(x) (const wchar_t) x
200*6be67779SAndroid Build Coastguard Worker #    define XML_L(x) L##x
201*6be67779SAndroid Build Coastguard Worker #  else
202*6be67779SAndroid Build Coastguard Worker #    define XML_T(x) (const unsigned short)x
203*6be67779SAndroid Build Coastguard Worker #    define XML_L(x) x
204*6be67779SAndroid Build Coastguard Worker #  endif
205*6be67779SAndroid Build Coastguard Worker 
206*6be67779SAndroid Build Coastguard Worker #else
207*6be67779SAndroid Build Coastguard Worker 
208*6be67779SAndroid Build Coastguard Worker #  define XML_T(x) x
209*6be67779SAndroid Build Coastguard Worker #  define XML_L(x) x
210*6be67779SAndroid Build Coastguard Worker 
211*6be67779SAndroid Build Coastguard Worker #endif
212*6be67779SAndroid Build Coastguard Worker 
213*6be67779SAndroid Build Coastguard Worker /* Round up n to be a multiple of sz, where sz is a power of 2. */
214*6be67779SAndroid Build Coastguard Worker #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
215*6be67779SAndroid Build Coastguard Worker 
216*6be67779SAndroid Build Coastguard Worker /* Do safe (NULL-aware) pointer arithmetic */
217*6be67779SAndroid Build Coastguard Worker #define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
218*6be67779SAndroid Build Coastguard Worker 
219*6be67779SAndroid Build Coastguard Worker #define EXPAT_MIN(a, b) (((a) < (b)) ? (a) : (b))
220*6be67779SAndroid Build Coastguard Worker 
221*6be67779SAndroid Build Coastguard Worker #include "internal.h"
222*6be67779SAndroid Build Coastguard Worker #include "xmltok.h"
223*6be67779SAndroid Build Coastguard Worker #include "xmlrole.h"
224*6be67779SAndroid Build Coastguard Worker 
225*6be67779SAndroid Build Coastguard Worker typedef const XML_Char *KEY;
226*6be67779SAndroid Build Coastguard Worker 
227*6be67779SAndroid Build Coastguard Worker typedef struct {
228*6be67779SAndroid Build Coastguard Worker   KEY name;
229*6be67779SAndroid Build Coastguard Worker } NAMED;
230*6be67779SAndroid Build Coastguard Worker 
231*6be67779SAndroid Build Coastguard Worker typedef struct {
232*6be67779SAndroid Build Coastguard Worker   NAMED **v;
233*6be67779SAndroid Build Coastguard Worker   unsigned char power;
234*6be67779SAndroid Build Coastguard Worker   size_t size;
235*6be67779SAndroid Build Coastguard Worker   size_t used;
236*6be67779SAndroid Build Coastguard Worker   const XML_Memory_Handling_Suite *mem;
237*6be67779SAndroid Build Coastguard Worker } HASH_TABLE;
238*6be67779SAndroid Build Coastguard Worker 
239*6be67779SAndroid Build Coastguard Worker static size_t keylen(KEY s);
240*6be67779SAndroid Build Coastguard Worker 
241*6be67779SAndroid Build Coastguard Worker static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key);
242*6be67779SAndroid Build Coastguard Worker 
243*6be67779SAndroid Build Coastguard Worker /* For probing (after a collision) we need a step size relative prime
244*6be67779SAndroid Build Coastguard Worker    to the hash table size, which is a power of 2. We use double-hashing,
245*6be67779SAndroid Build Coastguard Worker    since we can calculate a second hash value cheaply by taking those bits
246*6be67779SAndroid Build Coastguard Worker    of the first hash value that were discarded (masked out) when the table
247*6be67779SAndroid Build Coastguard Worker    index was calculated: index = hash & mask, where mask = table->size - 1.
248*6be67779SAndroid Build Coastguard Worker    We limit the maximum step size to table->size / 4 (mask >> 2) and make
249*6be67779SAndroid Build Coastguard Worker    it odd, since odd numbers are always relative prime to a power of 2.
250*6be67779SAndroid Build Coastguard Worker */
251*6be67779SAndroid Build Coastguard Worker #define SECOND_HASH(hash, mask, power)                                         \
252*6be67779SAndroid Build Coastguard Worker   ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
253*6be67779SAndroid Build Coastguard Worker #define PROBE_STEP(hash, mask, power)                                          \
254*6be67779SAndroid Build Coastguard Worker   ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
255*6be67779SAndroid Build Coastguard Worker 
256*6be67779SAndroid Build Coastguard Worker typedef struct {
257*6be67779SAndroid Build Coastguard Worker   NAMED **p;
258*6be67779SAndroid Build Coastguard Worker   NAMED **end;
259*6be67779SAndroid Build Coastguard Worker } HASH_TABLE_ITER;
260*6be67779SAndroid Build Coastguard Worker 
261*6be67779SAndroid Build Coastguard Worker #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
262*6be67779SAndroid Build Coastguard Worker #define INIT_DATA_BUF_SIZE 1024
263*6be67779SAndroid Build Coastguard Worker #define INIT_ATTS_SIZE 16
264*6be67779SAndroid Build Coastguard Worker #define INIT_ATTS_VERSION 0xFFFFFFFF
265*6be67779SAndroid Build Coastguard Worker #define INIT_BLOCK_SIZE 1024
266*6be67779SAndroid Build Coastguard Worker #define INIT_BUFFER_SIZE 1024
267*6be67779SAndroid Build Coastguard Worker 
268*6be67779SAndroid Build Coastguard Worker #define EXPAND_SPARE 24
269*6be67779SAndroid Build Coastguard Worker 
270*6be67779SAndroid Build Coastguard Worker typedef struct binding {
271*6be67779SAndroid Build Coastguard Worker   struct prefix *prefix;
272*6be67779SAndroid Build Coastguard Worker   struct binding *nextTagBinding;
273*6be67779SAndroid Build Coastguard Worker   struct binding *prevPrefixBinding;
274*6be67779SAndroid Build Coastguard Worker   const struct attribute_id *attId;
275*6be67779SAndroid Build Coastguard Worker   XML_Char *uri;
276*6be67779SAndroid Build Coastguard Worker   int uriLen;
277*6be67779SAndroid Build Coastguard Worker   int uriAlloc;
278*6be67779SAndroid Build Coastguard Worker } BINDING;
279*6be67779SAndroid Build Coastguard Worker 
280*6be67779SAndroid Build Coastguard Worker typedef struct prefix {
281*6be67779SAndroid Build Coastguard Worker   const XML_Char *name;
282*6be67779SAndroid Build Coastguard Worker   BINDING *binding;
283*6be67779SAndroid Build Coastguard Worker } PREFIX;
284*6be67779SAndroid Build Coastguard Worker 
285*6be67779SAndroid Build Coastguard Worker typedef struct {
286*6be67779SAndroid Build Coastguard Worker   const XML_Char *str;
287*6be67779SAndroid Build Coastguard Worker   const XML_Char *localPart;
288*6be67779SAndroid Build Coastguard Worker   const XML_Char *prefix;
289*6be67779SAndroid Build Coastguard Worker   int strLen;
290*6be67779SAndroid Build Coastguard Worker   int uriLen;
291*6be67779SAndroid Build Coastguard Worker   int prefixLen;
292*6be67779SAndroid Build Coastguard Worker } TAG_NAME;
293*6be67779SAndroid Build Coastguard Worker 
294*6be67779SAndroid Build Coastguard Worker /* TAG represents an open element.
295*6be67779SAndroid Build Coastguard Worker    The name of the element is stored in both the document and API
296*6be67779SAndroid Build Coastguard Worker    encodings.  The memory buffer 'buf' is a separately-allocated
297*6be67779SAndroid Build Coastguard Worker    memory area which stores the name.  During the XML_Parse()/
298*6be67779SAndroid Build Coastguard Worker    XML_ParseBuffer() when the element is open, the memory for the 'raw'
299*6be67779SAndroid Build Coastguard Worker    version of the name (in the document encoding) is shared with the
300*6be67779SAndroid Build Coastguard Worker    document buffer.  If the element is open across calls to
301*6be67779SAndroid Build Coastguard Worker    XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
302*6be67779SAndroid Build Coastguard Worker    contain the 'raw' name as well.
303*6be67779SAndroid Build Coastguard Worker 
304*6be67779SAndroid Build Coastguard Worker    A parser reuses these structures, maintaining a list of allocated
305*6be67779SAndroid Build Coastguard Worker    TAG objects in a free list.
306*6be67779SAndroid Build Coastguard Worker */
307*6be67779SAndroid Build Coastguard Worker typedef struct tag {
308*6be67779SAndroid Build Coastguard Worker   struct tag *parent;  /* parent of this element */
309*6be67779SAndroid Build Coastguard Worker   const char *rawName; /* tagName in the original encoding */
310*6be67779SAndroid Build Coastguard Worker   int rawNameLength;
311*6be67779SAndroid Build Coastguard Worker   TAG_NAME name; /* tagName in the API encoding */
312*6be67779SAndroid Build Coastguard Worker   char *buf;     /* buffer for name components */
313*6be67779SAndroid Build Coastguard Worker   char *bufEnd;  /* end of the buffer */
314*6be67779SAndroid Build Coastguard Worker   BINDING *bindings;
315*6be67779SAndroid Build Coastguard Worker } TAG;
316*6be67779SAndroid Build Coastguard Worker 
317*6be67779SAndroid Build Coastguard Worker typedef struct {
318*6be67779SAndroid Build Coastguard Worker   const XML_Char *name;
319*6be67779SAndroid Build Coastguard Worker   const XML_Char *textPtr;
320*6be67779SAndroid Build Coastguard Worker   int textLen;   /* length in XML_Chars */
321*6be67779SAndroid Build Coastguard Worker   int processed; /* # of processed bytes - when suspended */
322*6be67779SAndroid Build Coastguard Worker   const XML_Char *systemId;
323*6be67779SAndroid Build Coastguard Worker   const XML_Char *base;
324*6be67779SAndroid Build Coastguard Worker   const XML_Char *publicId;
325*6be67779SAndroid Build Coastguard Worker   const XML_Char *notation;
326*6be67779SAndroid Build Coastguard Worker   XML_Bool open;
327*6be67779SAndroid Build Coastguard Worker   XML_Bool is_param;
328*6be67779SAndroid Build Coastguard Worker   XML_Bool is_internal; /* true if declared in internal subset outside PE */
329*6be67779SAndroid Build Coastguard Worker } ENTITY;
330*6be67779SAndroid Build Coastguard Worker 
331*6be67779SAndroid Build Coastguard Worker typedef struct {
332*6be67779SAndroid Build Coastguard Worker   enum XML_Content_Type type;
333*6be67779SAndroid Build Coastguard Worker   enum XML_Content_Quant quant;
334*6be67779SAndroid Build Coastguard Worker   const XML_Char *name;
335*6be67779SAndroid Build Coastguard Worker   int firstchild;
336*6be67779SAndroid Build Coastguard Worker   int lastchild;
337*6be67779SAndroid Build Coastguard Worker   int childcnt;
338*6be67779SAndroid Build Coastguard Worker   int nextsib;
339*6be67779SAndroid Build Coastguard Worker } CONTENT_SCAFFOLD;
340*6be67779SAndroid Build Coastguard Worker 
341*6be67779SAndroid Build Coastguard Worker #define INIT_SCAFFOLD_ELEMENTS 32
342*6be67779SAndroid Build Coastguard Worker 
343*6be67779SAndroid Build Coastguard Worker typedef struct block {
344*6be67779SAndroid Build Coastguard Worker   struct block *next;
345*6be67779SAndroid Build Coastguard Worker   int size;
346*6be67779SAndroid Build Coastguard Worker   XML_Char s[1];
347*6be67779SAndroid Build Coastguard Worker } BLOCK;
348*6be67779SAndroid Build Coastguard Worker 
349*6be67779SAndroid Build Coastguard Worker typedef struct {
350*6be67779SAndroid Build Coastguard Worker   BLOCK *blocks;
351*6be67779SAndroid Build Coastguard Worker   BLOCK *freeBlocks;
352*6be67779SAndroid Build Coastguard Worker   const XML_Char *end;
353*6be67779SAndroid Build Coastguard Worker   XML_Char *ptr;
354*6be67779SAndroid Build Coastguard Worker   XML_Char *start;
355*6be67779SAndroid Build Coastguard Worker   const XML_Memory_Handling_Suite *mem;
356*6be67779SAndroid Build Coastguard Worker } STRING_POOL;
357*6be67779SAndroid Build Coastguard Worker 
358*6be67779SAndroid Build Coastguard Worker /* The XML_Char before the name is used to determine whether
359*6be67779SAndroid Build Coastguard Worker    an attribute has been specified. */
360*6be67779SAndroid Build Coastguard Worker typedef struct attribute_id {
361*6be67779SAndroid Build Coastguard Worker   XML_Char *name;
362*6be67779SAndroid Build Coastguard Worker   PREFIX *prefix;
363*6be67779SAndroid Build Coastguard Worker   XML_Bool maybeTokenized;
364*6be67779SAndroid Build Coastguard Worker   XML_Bool xmlns;
365*6be67779SAndroid Build Coastguard Worker } ATTRIBUTE_ID;
366*6be67779SAndroid Build Coastguard Worker 
367*6be67779SAndroid Build Coastguard Worker typedef struct {
368*6be67779SAndroid Build Coastguard Worker   const ATTRIBUTE_ID *id;
369*6be67779SAndroid Build Coastguard Worker   XML_Bool isCdata;
370*6be67779SAndroid Build Coastguard Worker   const XML_Char *value;
371*6be67779SAndroid Build Coastguard Worker } DEFAULT_ATTRIBUTE;
372*6be67779SAndroid Build Coastguard Worker 
373*6be67779SAndroid Build Coastguard Worker typedef struct {
374*6be67779SAndroid Build Coastguard Worker   unsigned long version;
375*6be67779SAndroid Build Coastguard Worker   unsigned long hash;
376*6be67779SAndroid Build Coastguard Worker   const XML_Char *uriName;
377*6be67779SAndroid Build Coastguard Worker } NS_ATT;
378*6be67779SAndroid Build Coastguard Worker 
379*6be67779SAndroid Build Coastguard Worker typedef struct {
380*6be67779SAndroid Build Coastguard Worker   const XML_Char *name;
381*6be67779SAndroid Build Coastguard Worker   PREFIX *prefix;
382*6be67779SAndroid Build Coastguard Worker   const ATTRIBUTE_ID *idAtt;
383*6be67779SAndroid Build Coastguard Worker   int nDefaultAtts;
384*6be67779SAndroid Build Coastguard Worker   int allocDefaultAtts;
385*6be67779SAndroid Build Coastguard Worker   DEFAULT_ATTRIBUTE *defaultAtts;
386*6be67779SAndroid Build Coastguard Worker } ELEMENT_TYPE;
387*6be67779SAndroid Build Coastguard Worker 
388*6be67779SAndroid Build Coastguard Worker typedef struct {
389*6be67779SAndroid Build Coastguard Worker   HASH_TABLE generalEntities;
390*6be67779SAndroid Build Coastguard Worker   HASH_TABLE elementTypes;
391*6be67779SAndroid Build Coastguard Worker   HASH_TABLE attributeIds;
392*6be67779SAndroid Build Coastguard Worker   HASH_TABLE prefixes;
393*6be67779SAndroid Build Coastguard Worker   STRING_POOL pool;
394*6be67779SAndroid Build Coastguard Worker   STRING_POOL entityValuePool;
395*6be67779SAndroid Build Coastguard Worker   /* false once a parameter entity reference has been skipped */
396*6be67779SAndroid Build Coastguard Worker   XML_Bool keepProcessing;
397*6be67779SAndroid Build Coastguard Worker   /* true once an internal or external PE reference has been encountered;
398*6be67779SAndroid Build Coastguard Worker      this includes the reference to an external subset */
399*6be67779SAndroid Build Coastguard Worker   XML_Bool hasParamEntityRefs;
400*6be67779SAndroid Build Coastguard Worker   XML_Bool standalone;
401*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
402*6be67779SAndroid Build Coastguard Worker   /* indicates if external PE has been read */
403*6be67779SAndroid Build Coastguard Worker   XML_Bool paramEntityRead;
404*6be67779SAndroid Build Coastguard Worker   HASH_TABLE paramEntities;
405*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
406*6be67779SAndroid Build Coastguard Worker   PREFIX defaultPrefix;
407*6be67779SAndroid Build Coastguard Worker   /* === scaffolding for building content model === */
408*6be67779SAndroid Build Coastguard Worker   XML_Bool in_eldecl;
409*6be67779SAndroid Build Coastguard Worker   CONTENT_SCAFFOLD *scaffold;
410*6be67779SAndroid Build Coastguard Worker   unsigned contentStringLen;
411*6be67779SAndroid Build Coastguard Worker   unsigned scaffSize;
412*6be67779SAndroid Build Coastguard Worker   unsigned scaffCount;
413*6be67779SAndroid Build Coastguard Worker   int scaffLevel;
414*6be67779SAndroid Build Coastguard Worker   int *scaffIndex;
415*6be67779SAndroid Build Coastguard Worker } DTD;
416*6be67779SAndroid Build Coastguard Worker 
417*6be67779SAndroid Build Coastguard Worker typedef struct open_internal_entity {
418*6be67779SAndroid Build Coastguard Worker   const char *internalEventPtr;
419*6be67779SAndroid Build Coastguard Worker   const char *internalEventEndPtr;
420*6be67779SAndroid Build Coastguard Worker   struct open_internal_entity *next;
421*6be67779SAndroid Build Coastguard Worker   ENTITY *entity;
422*6be67779SAndroid Build Coastguard Worker   int startTagLevel;
423*6be67779SAndroid Build Coastguard Worker   XML_Bool betweenDecl; /* WFC: PE Between Declarations */
424*6be67779SAndroid Build Coastguard Worker } OPEN_INTERNAL_ENTITY;
425*6be67779SAndroid Build Coastguard Worker 
426*6be67779SAndroid Build Coastguard Worker enum XML_Account {
427*6be67779SAndroid Build Coastguard Worker   XML_ACCOUNT_DIRECT,           /* bytes directly passed to the Expat parser */
428*6be67779SAndroid Build Coastguard Worker   XML_ACCOUNT_ENTITY_EXPANSION, /* intermediate bytes produced during entity
429*6be67779SAndroid Build Coastguard Worker                                    expansion */
430*6be67779SAndroid Build Coastguard Worker   XML_ACCOUNT_NONE              /* i.e. do not account, was accounted already */
431*6be67779SAndroid Build Coastguard Worker };
432*6be67779SAndroid Build Coastguard Worker 
433*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
434*6be67779SAndroid Build Coastguard Worker typedef unsigned long long XmlBigCount;
435*6be67779SAndroid Build Coastguard Worker typedef struct accounting {
436*6be67779SAndroid Build Coastguard Worker   XmlBigCount countBytesDirect;
437*6be67779SAndroid Build Coastguard Worker   XmlBigCount countBytesIndirect;
438*6be67779SAndroid Build Coastguard Worker   unsigned long debugLevel;
439*6be67779SAndroid Build Coastguard Worker   float maximumAmplificationFactor; // >=1.0
440*6be67779SAndroid Build Coastguard Worker   unsigned long long activationThresholdBytes;
441*6be67779SAndroid Build Coastguard Worker } ACCOUNTING;
442*6be67779SAndroid Build Coastguard Worker 
443*6be67779SAndroid Build Coastguard Worker typedef struct entity_stats {
444*6be67779SAndroid Build Coastguard Worker   unsigned int countEverOpened;
445*6be67779SAndroid Build Coastguard Worker   unsigned int currentDepth;
446*6be67779SAndroid Build Coastguard Worker   unsigned int maximumDepthSeen;
447*6be67779SAndroid Build Coastguard Worker   unsigned long debugLevel;
448*6be67779SAndroid Build Coastguard Worker } ENTITY_STATS;
449*6be67779SAndroid Build Coastguard Worker #endif /* XML_GE == 1 */
450*6be67779SAndroid Build Coastguard Worker 
451*6be67779SAndroid Build Coastguard Worker typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
452*6be67779SAndroid Build Coastguard Worker                                          const char *end, const char **endPtr);
453*6be67779SAndroid Build Coastguard Worker 
454*6be67779SAndroid Build Coastguard Worker static Processor prologProcessor;
455*6be67779SAndroid Build Coastguard Worker static Processor prologInitProcessor;
456*6be67779SAndroid Build Coastguard Worker static Processor contentProcessor;
457*6be67779SAndroid Build Coastguard Worker static Processor cdataSectionProcessor;
458*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
459*6be67779SAndroid Build Coastguard Worker static Processor ignoreSectionProcessor;
460*6be67779SAndroid Build Coastguard Worker static Processor externalParEntProcessor;
461*6be67779SAndroid Build Coastguard Worker static Processor externalParEntInitProcessor;
462*6be67779SAndroid Build Coastguard Worker static Processor entityValueProcessor;
463*6be67779SAndroid Build Coastguard Worker static Processor entityValueInitProcessor;
464*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
465*6be67779SAndroid Build Coastguard Worker static Processor epilogProcessor;
466*6be67779SAndroid Build Coastguard Worker static Processor errorProcessor;
467*6be67779SAndroid Build Coastguard Worker static Processor externalEntityInitProcessor;
468*6be67779SAndroid Build Coastguard Worker static Processor externalEntityInitProcessor2;
469*6be67779SAndroid Build Coastguard Worker static Processor externalEntityInitProcessor3;
470*6be67779SAndroid Build Coastguard Worker static Processor externalEntityContentProcessor;
471*6be67779SAndroid Build Coastguard Worker static Processor internalEntityProcessor;
472*6be67779SAndroid Build Coastguard Worker 
473*6be67779SAndroid Build Coastguard Worker static enum XML_Error handleUnknownEncoding(XML_Parser parser,
474*6be67779SAndroid Build Coastguard Worker                                             const XML_Char *encodingName);
475*6be67779SAndroid Build Coastguard Worker static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
476*6be67779SAndroid Build Coastguard Worker                                      const char *s, const char *next);
477*6be67779SAndroid Build Coastguard Worker static enum XML_Error initializeEncoding(XML_Parser parser);
478*6be67779SAndroid Build Coastguard Worker static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
479*6be67779SAndroid Build Coastguard Worker                                const char *s, const char *end, int tok,
480*6be67779SAndroid Build Coastguard Worker                                const char *next, const char **nextPtr,
481*6be67779SAndroid Build Coastguard Worker                                XML_Bool haveMore, XML_Bool allowClosingDoctype,
482*6be67779SAndroid Build Coastguard Worker                                enum XML_Account account);
483*6be67779SAndroid Build Coastguard Worker static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
484*6be67779SAndroid Build Coastguard Worker                                             XML_Bool betweenDecl);
485*6be67779SAndroid Build Coastguard Worker static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
486*6be67779SAndroid Build Coastguard Worker                                 const ENCODING *enc, const char *start,
487*6be67779SAndroid Build Coastguard Worker                                 const char *end, const char **endPtr,
488*6be67779SAndroid Build Coastguard Worker                                 XML_Bool haveMore, enum XML_Account account);
489*6be67779SAndroid Build Coastguard Worker static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *enc,
490*6be67779SAndroid Build Coastguard Worker                                      const char **startPtr, const char *end,
491*6be67779SAndroid Build Coastguard Worker                                      const char **nextPtr, XML_Bool haveMore,
492*6be67779SAndroid Build Coastguard Worker                                      enum XML_Account account);
493*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
494*6be67779SAndroid Build Coastguard Worker static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *enc,
495*6be67779SAndroid Build Coastguard Worker                                       const char **startPtr, const char *end,
496*6be67779SAndroid Build Coastguard Worker                                       const char **nextPtr, XML_Bool haveMore);
497*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
498*6be67779SAndroid Build Coastguard Worker 
499*6be67779SAndroid Build Coastguard Worker static void freeBindings(XML_Parser parser, BINDING *bindings);
500*6be67779SAndroid Build Coastguard Worker static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
501*6be67779SAndroid Build Coastguard Worker                                 const char *attStr, TAG_NAME *tagNamePtr,
502*6be67779SAndroid Build Coastguard Worker                                 BINDING **bindingsPtr,
503*6be67779SAndroid Build Coastguard Worker                                 enum XML_Account account);
504*6be67779SAndroid Build Coastguard Worker static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
505*6be67779SAndroid Build Coastguard Worker                                  const ATTRIBUTE_ID *attId, const XML_Char *uri,
506*6be67779SAndroid Build Coastguard Worker                                  BINDING **bindingsPtr);
507*6be67779SAndroid Build Coastguard Worker static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId,
508*6be67779SAndroid Build Coastguard Worker                            XML_Bool isCdata, XML_Bool isId,
509*6be67779SAndroid Build Coastguard Worker                            const XML_Char *value, XML_Parser parser);
510*6be67779SAndroid Build Coastguard Worker static enum XML_Error storeAttributeValue(XML_Parser parser,
511*6be67779SAndroid Build Coastguard Worker                                           const ENCODING *enc, XML_Bool isCdata,
512*6be67779SAndroid Build Coastguard Worker                                           const char *ptr, const char *end,
513*6be67779SAndroid Build Coastguard Worker                                           STRING_POOL *pool,
514*6be67779SAndroid Build Coastguard Worker                                           enum XML_Account account);
515*6be67779SAndroid Build Coastguard Worker static enum XML_Error appendAttributeValue(XML_Parser parser,
516*6be67779SAndroid Build Coastguard Worker                                            const ENCODING *enc,
517*6be67779SAndroid Build Coastguard Worker                                            XML_Bool isCdata, const char *ptr,
518*6be67779SAndroid Build Coastguard Worker                                            const char *end, STRING_POOL *pool,
519*6be67779SAndroid Build Coastguard Worker                                            enum XML_Account account);
520*6be67779SAndroid Build Coastguard Worker static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
521*6be67779SAndroid Build Coastguard Worker                                     const char *start, const char *end);
522*6be67779SAndroid Build Coastguard Worker static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType);
523*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
524*6be67779SAndroid Build Coastguard Worker static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
525*6be67779SAndroid Build Coastguard Worker                                        const char *start, const char *end,
526*6be67779SAndroid Build Coastguard Worker                                        enum XML_Account account);
527*6be67779SAndroid Build Coastguard Worker #else
528*6be67779SAndroid Build Coastguard Worker static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity);
529*6be67779SAndroid Build Coastguard Worker #endif
530*6be67779SAndroid Build Coastguard Worker static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
531*6be67779SAndroid Build Coastguard Worker                                        const char *start, const char *end);
532*6be67779SAndroid Build Coastguard Worker static int reportComment(XML_Parser parser, const ENCODING *enc,
533*6be67779SAndroid Build Coastguard Worker                          const char *start, const char *end);
534*6be67779SAndroid Build Coastguard Worker static void reportDefault(XML_Parser parser, const ENCODING *enc,
535*6be67779SAndroid Build Coastguard Worker                           const char *start, const char *end);
536*6be67779SAndroid Build Coastguard Worker 
537*6be67779SAndroid Build Coastguard Worker static const XML_Char *getContext(XML_Parser parser);
538*6be67779SAndroid Build Coastguard Worker static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
539*6be67779SAndroid Build Coastguard Worker 
540*6be67779SAndroid Build Coastguard Worker static void FASTCALL normalizePublicId(XML_Char *s);
541*6be67779SAndroid Build Coastguard Worker 
542*6be67779SAndroid Build Coastguard Worker static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms);
543*6be67779SAndroid Build Coastguard Worker /* do not call if m_parentParser != NULL */
544*6be67779SAndroid Build Coastguard Worker static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
545*6be67779SAndroid Build Coastguard Worker static void dtdDestroy(DTD *p, XML_Bool isDocEntity,
546*6be67779SAndroid Build Coastguard Worker                        const XML_Memory_Handling_Suite *ms);
547*6be67779SAndroid Build Coastguard Worker static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
548*6be67779SAndroid Build Coastguard Worker                    const XML_Memory_Handling_Suite *ms);
549*6be67779SAndroid Build Coastguard Worker static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
550*6be67779SAndroid Build Coastguard Worker                            STRING_POOL *newPool, const HASH_TABLE *oldTable);
551*6be67779SAndroid Build Coastguard Worker static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
552*6be67779SAndroid Build Coastguard Worker                      size_t createSize);
553*6be67779SAndroid Build Coastguard Worker static void FASTCALL hashTableInit(HASH_TABLE *table,
554*6be67779SAndroid Build Coastguard Worker                                    const XML_Memory_Handling_Suite *ms);
555*6be67779SAndroid Build Coastguard Worker static void FASTCALL hashTableClear(HASH_TABLE *table);
556*6be67779SAndroid Build Coastguard Worker static void FASTCALL hashTableDestroy(HASH_TABLE *table);
557*6be67779SAndroid Build Coastguard Worker static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter,
558*6be67779SAndroid Build Coastguard Worker                                        const HASH_TABLE *table);
559*6be67779SAndroid Build Coastguard Worker static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter);
560*6be67779SAndroid Build Coastguard Worker 
561*6be67779SAndroid Build Coastguard Worker static void FASTCALL poolInit(STRING_POOL *pool,
562*6be67779SAndroid Build Coastguard Worker                               const XML_Memory_Handling_Suite *ms);
563*6be67779SAndroid Build Coastguard Worker static void FASTCALL poolClear(STRING_POOL *pool);
564*6be67779SAndroid Build Coastguard Worker static void FASTCALL poolDestroy(STRING_POOL *pool);
565*6be67779SAndroid Build Coastguard Worker static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
566*6be67779SAndroid Build Coastguard Worker                             const char *ptr, const char *end);
567*6be67779SAndroid Build Coastguard Worker static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
568*6be67779SAndroid Build Coastguard Worker                                  const char *ptr, const char *end);
569*6be67779SAndroid Build Coastguard Worker static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
570*6be67779SAndroid Build Coastguard Worker static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
571*6be67779SAndroid Build Coastguard Worker                                                const XML_Char *s);
572*6be67779SAndroid Build Coastguard Worker static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
573*6be67779SAndroid Build Coastguard Worker                                        int n);
574*6be67779SAndroid Build Coastguard Worker static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
575*6be67779SAndroid Build Coastguard Worker                                                  const XML_Char *s);
576*6be67779SAndroid Build Coastguard Worker 
577*6be67779SAndroid Build Coastguard Worker static int FASTCALL nextScaffoldPart(XML_Parser parser);
578*6be67779SAndroid Build Coastguard Worker static XML_Content *build_model(XML_Parser parser);
579*6be67779SAndroid Build Coastguard Worker static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
580*6be67779SAndroid Build Coastguard Worker                                     const char *ptr, const char *end);
581*6be67779SAndroid Build Coastguard Worker 
582*6be67779SAndroid Build Coastguard Worker static XML_Char *copyString(const XML_Char *s,
583*6be67779SAndroid Build Coastguard Worker                             const XML_Memory_Handling_Suite *memsuite);
584*6be67779SAndroid Build Coastguard Worker 
585*6be67779SAndroid Build Coastguard Worker static unsigned long generate_hash_secret_salt(XML_Parser parser);
586*6be67779SAndroid Build Coastguard Worker static XML_Bool startParsing(XML_Parser parser);
587*6be67779SAndroid Build Coastguard Worker 
588*6be67779SAndroid Build Coastguard Worker static XML_Parser parserCreate(const XML_Char *encodingName,
589*6be67779SAndroid Build Coastguard Worker                                const XML_Memory_Handling_Suite *memsuite,
590*6be67779SAndroid Build Coastguard Worker                                const XML_Char *nameSep, DTD *dtd);
591*6be67779SAndroid Build Coastguard Worker 
592*6be67779SAndroid Build Coastguard Worker static void parserInit(XML_Parser parser, const XML_Char *encodingName);
593*6be67779SAndroid Build Coastguard Worker 
594*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
595*6be67779SAndroid Build Coastguard Worker static float accountingGetCurrentAmplification(XML_Parser rootParser);
596*6be67779SAndroid Build Coastguard Worker static void accountingReportStats(XML_Parser originParser, const char *epilog);
597*6be67779SAndroid Build Coastguard Worker static void accountingOnAbort(XML_Parser originParser);
598*6be67779SAndroid Build Coastguard Worker static void accountingReportDiff(XML_Parser rootParser,
599*6be67779SAndroid Build Coastguard Worker                                  unsigned int levelsAwayFromRootParser,
600*6be67779SAndroid Build Coastguard Worker                                  const char *before, const char *after,
601*6be67779SAndroid Build Coastguard Worker                                  ptrdiff_t bytesMore, int source_line,
602*6be67779SAndroid Build Coastguard Worker                                  enum XML_Account account);
603*6be67779SAndroid Build Coastguard Worker static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok,
604*6be67779SAndroid Build Coastguard Worker                                         const char *before, const char *after,
605*6be67779SAndroid Build Coastguard Worker                                         int source_line,
606*6be67779SAndroid Build Coastguard Worker                                         enum XML_Account account);
607*6be67779SAndroid Build Coastguard Worker 
608*6be67779SAndroid Build Coastguard Worker static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity,
609*6be67779SAndroid Build Coastguard Worker                                       const char *action, int sourceLine);
610*6be67779SAndroid Build Coastguard Worker static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity,
611*6be67779SAndroid Build Coastguard Worker                                  int sourceLine);
612*6be67779SAndroid Build Coastguard Worker static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity,
613*6be67779SAndroid Build Coastguard Worker                                   int sourceLine);
614*6be67779SAndroid Build Coastguard Worker 
615*6be67779SAndroid Build Coastguard Worker static XML_Parser getRootParserOf(XML_Parser parser,
616*6be67779SAndroid Build Coastguard Worker                                   unsigned int *outLevelDiff);
617*6be67779SAndroid Build Coastguard Worker #endif /* XML_GE == 1 */
618*6be67779SAndroid Build Coastguard Worker 
619*6be67779SAndroid Build Coastguard Worker static unsigned long getDebugLevel(const char *variableName,
620*6be67779SAndroid Build Coastguard Worker                                    unsigned long defaultDebugLevel);
621*6be67779SAndroid Build Coastguard Worker 
622*6be67779SAndroid Build Coastguard Worker #define poolStart(pool) ((pool)->start)
623*6be67779SAndroid Build Coastguard Worker #define poolLength(pool) ((pool)->ptr - (pool)->start)
624*6be67779SAndroid Build Coastguard Worker #define poolChop(pool) ((void)--(pool->ptr))
625*6be67779SAndroid Build Coastguard Worker #define poolLastChar(pool) (((pool)->ptr)[-1])
626*6be67779SAndroid Build Coastguard Worker #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
627*6be67779SAndroid Build Coastguard Worker #define poolFinish(pool) ((pool)->start = (pool)->ptr)
628*6be67779SAndroid Build Coastguard Worker #define poolAppendChar(pool, c)                                                \
629*6be67779SAndroid Build Coastguard Worker   (((pool)->ptr == (pool)->end && ! poolGrow(pool))                            \
630*6be67779SAndroid Build Coastguard Worker        ? 0                                                                     \
631*6be67779SAndroid Build Coastguard Worker        : ((*((pool)->ptr)++ = c), 1))
632*6be67779SAndroid Build Coastguard Worker 
633*6be67779SAndroid Build Coastguard Worker #if ! defined(XML_TESTING)
634*6be67779SAndroid Build Coastguard Worker const
635*6be67779SAndroid Build Coastguard Worker #endif
636*6be67779SAndroid Build Coastguard Worker     XML_Bool g_reparseDeferralEnabledDefault
637*6be67779SAndroid Build Coastguard Worker     = XML_TRUE; // write ONLY in runtests.c
638*6be67779SAndroid Build Coastguard Worker #if defined(XML_TESTING)
639*6be67779SAndroid Build Coastguard Worker unsigned int g_bytesScanned = 0; // used for testing only
640*6be67779SAndroid Build Coastguard Worker #endif
641*6be67779SAndroid Build Coastguard Worker 
642*6be67779SAndroid Build Coastguard Worker struct XML_ParserStruct {
643*6be67779SAndroid Build Coastguard Worker   /* The first member must be m_userData so that the XML_GetUserData
644*6be67779SAndroid Build Coastguard Worker      macro works. */
645*6be67779SAndroid Build Coastguard Worker   void *m_userData;
646*6be67779SAndroid Build Coastguard Worker   void *m_handlerArg;
647*6be67779SAndroid Build Coastguard Worker 
648*6be67779SAndroid Build Coastguard Worker   // How the four parse buffer pointers below relate in time and space:
649*6be67779SAndroid Build Coastguard Worker   //
650*6be67779SAndroid Build Coastguard Worker   //   m_buffer <= m_bufferPtr <= m_bufferEnd  <= m_bufferLim
651*6be67779SAndroid Build Coastguard Worker   //   |           |              |               |
652*6be67779SAndroid Build Coastguard Worker   //   <--parsed-->|              |               |
653*6be67779SAndroid Build Coastguard Worker   //               <---parsing--->|               |
654*6be67779SAndroid Build Coastguard Worker   //                              <--unoccupied-->|
655*6be67779SAndroid Build Coastguard Worker   //   <---------total-malloced/realloced-------->|
656*6be67779SAndroid Build Coastguard Worker 
657*6be67779SAndroid Build Coastguard Worker   char *m_buffer; // malloc/realloc base pointer of parse buffer
658*6be67779SAndroid Build Coastguard Worker   const XML_Memory_Handling_Suite m_mem;
659*6be67779SAndroid Build Coastguard Worker   const char *m_bufferPtr; // first character to be parsed
660*6be67779SAndroid Build Coastguard Worker   char *m_bufferEnd;       // past last character to be parsed
661*6be67779SAndroid Build Coastguard Worker   const char *m_bufferLim; // allocated end of m_buffer
662*6be67779SAndroid Build Coastguard Worker 
663*6be67779SAndroid Build Coastguard Worker   XML_Index m_parseEndByteIndex;
664*6be67779SAndroid Build Coastguard Worker   const char *m_parseEndPtr;
665*6be67779SAndroid Build Coastguard Worker   size_t m_partialTokenBytesBefore; /* used in heuristic to avoid O(n^2) */
666*6be67779SAndroid Build Coastguard Worker   XML_Bool m_reparseDeferralEnabled;
667*6be67779SAndroid Build Coastguard Worker   int m_lastBufferRequestSize;
668*6be67779SAndroid Build Coastguard Worker   XML_Char *m_dataBuf;
669*6be67779SAndroid Build Coastguard Worker   XML_Char *m_dataBufEnd;
670*6be67779SAndroid Build Coastguard Worker   XML_StartElementHandler m_startElementHandler;
671*6be67779SAndroid Build Coastguard Worker   XML_EndElementHandler m_endElementHandler;
672*6be67779SAndroid Build Coastguard Worker   XML_CharacterDataHandler m_characterDataHandler;
673*6be67779SAndroid Build Coastguard Worker   XML_ProcessingInstructionHandler m_processingInstructionHandler;
674*6be67779SAndroid Build Coastguard Worker   XML_CommentHandler m_commentHandler;
675*6be67779SAndroid Build Coastguard Worker   XML_StartCdataSectionHandler m_startCdataSectionHandler;
676*6be67779SAndroid Build Coastguard Worker   XML_EndCdataSectionHandler m_endCdataSectionHandler;
677*6be67779SAndroid Build Coastguard Worker   XML_DefaultHandler m_defaultHandler;
678*6be67779SAndroid Build Coastguard Worker   XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
679*6be67779SAndroid Build Coastguard Worker   XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
680*6be67779SAndroid Build Coastguard Worker   XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
681*6be67779SAndroid Build Coastguard Worker   XML_NotationDeclHandler m_notationDeclHandler;
682*6be67779SAndroid Build Coastguard Worker   XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
683*6be67779SAndroid Build Coastguard Worker   XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
684*6be67779SAndroid Build Coastguard Worker   XML_NotStandaloneHandler m_notStandaloneHandler;
685*6be67779SAndroid Build Coastguard Worker   XML_ExternalEntityRefHandler m_externalEntityRefHandler;
686*6be67779SAndroid Build Coastguard Worker   XML_Parser m_externalEntityRefHandlerArg;
687*6be67779SAndroid Build Coastguard Worker   XML_SkippedEntityHandler m_skippedEntityHandler;
688*6be67779SAndroid Build Coastguard Worker   XML_UnknownEncodingHandler m_unknownEncodingHandler;
689*6be67779SAndroid Build Coastguard Worker   XML_ElementDeclHandler m_elementDeclHandler;
690*6be67779SAndroid Build Coastguard Worker   XML_AttlistDeclHandler m_attlistDeclHandler;
691*6be67779SAndroid Build Coastguard Worker   XML_EntityDeclHandler m_entityDeclHandler;
692*6be67779SAndroid Build Coastguard Worker   XML_XmlDeclHandler m_xmlDeclHandler;
693*6be67779SAndroid Build Coastguard Worker   const ENCODING *m_encoding;
694*6be67779SAndroid Build Coastguard Worker   INIT_ENCODING m_initEncoding;
695*6be67779SAndroid Build Coastguard Worker   const ENCODING *m_internalEncoding;
696*6be67779SAndroid Build Coastguard Worker   const XML_Char *m_protocolEncodingName;
697*6be67779SAndroid Build Coastguard Worker   XML_Bool m_ns;
698*6be67779SAndroid Build Coastguard Worker   XML_Bool m_ns_triplets;
699*6be67779SAndroid Build Coastguard Worker   void *m_unknownEncodingMem;
700*6be67779SAndroid Build Coastguard Worker   void *m_unknownEncodingData;
701*6be67779SAndroid Build Coastguard Worker   void *m_unknownEncodingHandlerData;
702*6be67779SAndroid Build Coastguard Worker   void(XMLCALL *m_unknownEncodingRelease)(void *);
703*6be67779SAndroid Build Coastguard Worker   PROLOG_STATE m_prologState;
704*6be67779SAndroid Build Coastguard Worker   Processor *m_processor;
705*6be67779SAndroid Build Coastguard Worker   enum XML_Error m_errorCode;
706*6be67779SAndroid Build Coastguard Worker   const char *m_eventPtr;
707*6be67779SAndroid Build Coastguard Worker   const char *m_eventEndPtr;
708*6be67779SAndroid Build Coastguard Worker   const char *m_positionPtr;
709*6be67779SAndroid Build Coastguard Worker   OPEN_INTERNAL_ENTITY *m_openInternalEntities;
710*6be67779SAndroid Build Coastguard Worker   OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
711*6be67779SAndroid Build Coastguard Worker   XML_Bool m_defaultExpandInternalEntities;
712*6be67779SAndroid Build Coastguard Worker   int m_tagLevel;
713*6be67779SAndroid Build Coastguard Worker   ENTITY *m_declEntity;
714*6be67779SAndroid Build Coastguard Worker   const XML_Char *m_doctypeName;
715*6be67779SAndroid Build Coastguard Worker   const XML_Char *m_doctypeSysid;
716*6be67779SAndroid Build Coastguard Worker   const XML_Char *m_doctypePubid;
717*6be67779SAndroid Build Coastguard Worker   const XML_Char *m_declAttributeType;
718*6be67779SAndroid Build Coastguard Worker   const XML_Char *m_declNotationName;
719*6be67779SAndroid Build Coastguard Worker   const XML_Char *m_declNotationPublicId;
720*6be67779SAndroid Build Coastguard Worker   ELEMENT_TYPE *m_declElementType;
721*6be67779SAndroid Build Coastguard Worker   ATTRIBUTE_ID *m_declAttributeId;
722*6be67779SAndroid Build Coastguard Worker   XML_Bool m_declAttributeIsCdata;
723*6be67779SAndroid Build Coastguard Worker   XML_Bool m_declAttributeIsId;
724*6be67779SAndroid Build Coastguard Worker   DTD *m_dtd;
725*6be67779SAndroid Build Coastguard Worker   const XML_Char *m_curBase;
726*6be67779SAndroid Build Coastguard Worker   TAG *m_tagStack;
727*6be67779SAndroid Build Coastguard Worker   TAG *m_freeTagList;
728*6be67779SAndroid Build Coastguard Worker   BINDING *m_inheritedBindings;
729*6be67779SAndroid Build Coastguard Worker   BINDING *m_freeBindingList;
730*6be67779SAndroid Build Coastguard Worker   int m_attsSize;
731*6be67779SAndroid Build Coastguard Worker   int m_nSpecifiedAtts;
732*6be67779SAndroid Build Coastguard Worker   int m_idAttIndex;
733*6be67779SAndroid Build Coastguard Worker   ATTRIBUTE *m_atts;
734*6be67779SAndroid Build Coastguard Worker   NS_ATT *m_nsAtts;
735*6be67779SAndroid Build Coastguard Worker   unsigned long m_nsAttsVersion;
736*6be67779SAndroid Build Coastguard Worker   unsigned char m_nsAttsPower;
737*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
738*6be67779SAndroid Build Coastguard Worker   XML_AttrInfo *m_attInfo;
739*6be67779SAndroid Build Coastguard Worker #endif
740*6be67779SAndroid Build Coastguard Worker   POSITION m_position;
741*6be67779SAndroid Build Coastguard Worker   STRING_POOL m_tempPool;
742*6be67779SAndroid Build Coastguard Worker   STRING_POOL m_temp2Pool;
743*6be67779SAndroid Build Coastguard Worker   char *m_groupConnector;
744*6be67779SAndroid Build Coastguard Worker   unsigned int m_groupSize;
745*6be67779SAndroid Build Coastguard Worker   XML_Char m_namespaceSeparator;
746*6be67779SAndroid Build Coastguard Worker   XML_Parser m_parentParser;
747*6be67779SAndroid Build Coastguard Worker   XML_ParsingStatus m_parsingStatus;
748*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
749*6be67779SAndroid Build Coastguard Worker   XML_Bool m_isParamEntity;
750*6be67779SAndroid Build Coastguard Worker   XML_Bool m_useForeignDTD;
751*6be67779SAndroid Build Coastguard Worker   enum XML_ParamEntityParsing m_paramEntityParsing;
752*6be67779SAndroid Build Coastguard Worker #endif
753*6be67779SAndroid Build Coastguard Worker   unsigned long m_hash_secret_salt;
754*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
755*6be67779SAndroid Build Coastguard Worker   ACCOUNTING m_accounting;
756*6be67779SAndroid Build Coastguard Worker   ENTITY_STATS m_entity_stats;
757*6be67779SAndroid Build Coastguard Worker #endif
758*6be67779SAndroid Build Coastguard Worker };
759*6be67779SAndroid Build Coastguard Worker 
760*6be67779SAndroid Build Coastguard Worker #define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
761*6be67779SAndroid Build Coastguard Worker #define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
762*6be67779SAndroid Build Coastguard Worker #define FREE(parser, p) (parser->m_mem.free_fcn((p)))
763*6be67779SAndroid Build Coastguard Worker 
764*6be67779SAndroid Build Coastguard Worker XML_Parser XMLCALL
XML_ParserCreate(const XML_Char * encodingName)765*6be67779SAndroid Build Coastguard Worker XML_ParserCreate(const XML_Char *encodingName) {
766*6be67779SAndroid Build Coastguard Worker   return XML_ParserCreate_MM(encodingName, NULL, NULL);
767*6be67779SAndroid Build Coastguard Worker }
768*6be67779SAndroid Build Coastguard Worker 
769*6be67779SAndroid Build Coastguard Worker XML_Parser XMLCALL
XML_ParserCreateNS(const XML_Char * encodingName,XML_Char nsSep)770*6be67779SAndroid Build Coastguard Worker XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
771*6be67779SAndroid Build Coastguard Worker   XML_Char tmp[2] = {nsSep, 0};
772*6be67779SAndroid Build Coastguard Worker   return XML_ParserCreate_MM(encodingName, NULL, tmp);
773*6be67779SAndroid Build Coastguard Worker }
774*6be67779SAndroid Build Coastguard Worker 
775*6be67779SAndroid Build Coastguard Worker // "xml=http://www.w3.org/XML/1998/namespace"
776*6be67779SAndroid Build Coastguard Worker static const XML_Char implicitContext[]
777*6be67779SAndroid Build Coastguard Worker     = {ASCII_x,     ASCII_m,     ASCII_l,      ASCII_EQUALS, ASCII_h,
778*6be67779SAndroid Build Coastguard Worker        ASCII_t,     ASCII_t,     ASCII_p,      ASCII_COLON,  ASCII_SLASH,
779*6be67779SAndroid Build Coastguard Worker        ASCII_SLASH, ASCII_w,     ASCII_w,      ASCII_w,      ASCII_PERIOD,
780*6be67779SAndroid Build Coastguard Worker        ASCII_w,     ASCII_3,     ASCII_PERIOD, ASCII_o,      ASCII_r,
781*6be67779SAndroid Build Coastguard Worker        ASCII_g,     ASCII_SLASH, ASCII_X,      ASCII_M,      ASCII_L,
782*6be67779SAndroid Build Coastguard Worker        ASCII_SLASH, ASCII_1,     ASCII_9,      ASCII_9,      ASCII_8,
783*6be67779SAndroid Build Coastguard Worker        ASCII_SLASH, ASCII_n,     ASCII_a,      ASCII_m,      ASCII_e,
784*6be67779SAndroid Build Coastguard Worker        ASCII_s,     ASCII_p,     ASCII_a,      ASCII_c,      ASCII_e,
785*6be67779SAndroid Build Coastguard Worker        '\0'};
786*6be67779SAndroid Build Coastguard Worker 
787*6be67779SAndroid Build Coastguard Worker /* To avoid warnings about unused functions: */
788*6be67779SAndroid Build Coastguard Worker #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
789*6be67779SAndroid Build Coastguard Worker 
790*6be67779SAndroid Build Coastguard Worker #  if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
791*6be67779SAndroid Build Coastguard Worker 
792*6be67779SAndroid Build Coastguard Worker /* Obtain entropy on Linux 3.17+ */
793*6be67779SAndroid Build Coastguard Worker static int
writeRandomBytes_getrandom_nonblock(void * target,size_t count)794*6be67779SAndroid Build Coastguard Worker writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
795*6be67779SAndroid Build Coastguard Worker   int success = 0; /* full count bytes written? */
796*6be67779SAndroid Build Coastguard Worker   size_t bytesWrittenTotal = 0;
797*6be67779SAndroid Build Coastguard Worker   const unsigned int getrandomFlags = GRND_NONBLOCK;
798*6be67779SAndroid Build Coastguard Worker 
799*6be67779SAndroid Build Coastguard Worker   do {
800*6be67779SAndroid Build Coastguard Worker     void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
801*6be67779SAndroid Build Coastguard Worker     const size_t bytesToWrite = count - bytesWrittenTotal;
802*6be67779SAndroid Build Coastguard Worker 
803*6be67779SAndroid Build Coastguard Worker     const int bytesWrittenMore =
804*6be67779SAndroid Build Coastguard Worker #    if defined(HAVE_GETRANDOM)
805*6be67779SAndroid Build Coastguard Worker         getrandom(currentTarget, bytesToWrite, getrandomFlags);
806*6be67779SAndroid Build Coastguard Worker #    else
807*6be67779SAndroid Build Coastguard Worker         syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
808*6be67779SAndroid Build Coastguard Worker #    endif
809*6be67779SAndroid Build Coastguard Worker 
810*6be67779SAndroid Build Coastguard Worker     if (bytesWrittenMore > 0) {
811*6be67779SAndroid Build Coastguard Worker       bytesWrittenTotal += bytesWrittenMore;
812*6be67779SAndroid Build Coastguard Worker       if (bytesWrittenTotal >= count)
813*6be67779SAndroid Build Coastguard Worker         success = 1;
814*6be67779SAndroid Build Coastguard Worker     }
815*6be67779SAndroid Build Coastguard Worker   } while (! success && (errno == EINTR));
816*6be67779SAndroid Build Coastguard Worker 
817*6be67779SAndroid Build Coastguard Worker   return success;
818*6be67779SAndroid Build Coastguard Worker }
819*6be67779SAndroid Build Coastguard Worker 
820*6be67779SAndroid Build Coastguard Worker #  endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
821*6be67779SAndroid Build Coastguard Worker 
822*6be67779SAndroid Build Coastguard Worker #  if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
823*6be67779SAndroid Build Coastguard Worker 
824*6be67779SAndroid Build Coastguard Worker /* Extract entropy from /dev/urandom */
825*6be67779SAndroid Build Coastguard Worker static int
writeRandomBytes_dev_urandom(void * target,size_t count)826*6be67779SAndroid Build Coastguard Worker writeRandomBytes_dev_urandom(void *target, size_t count) {
827*6be67779SAndroid Build Coastguard Worker   int success = 0; /* full count bytes written? */
828*6be67779SAndroid Build Coastguard Worker   size_t bytesWrittenTotal = 0;
829*6be67779SAndroid Build Coastguard Worker 
830*6be67779SAndroid Build Coastguard Worker   const int fd = open("/dev/urandom", O_RDONLY);
831*6be67779SAndroid Build Coastguard Worker   if (fd < 0) {
832*6be67779SAndroid Build Coastguard Worker     return 0;
833*6be67779SAndroid Build Coastguard Worker   }
834*6be67779SAndroid Build Coastguard Worker 
835*6be67779SAndroid Build Coastguard Worker   do {
836*6be67779SAndroid Build Coastguard Worker     void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
837*6be67779SAndroid Build Coastguard Worker     const size_t bytesToWrite = count - bytesWrittenTotal;
838*6be67779SAndroid Build Coastguard Worker 
839*6be67779SAndroid Build Coastguard Worker     const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
840*6be67779SAndroid Build Coastguard Worker 
841*6be67779SAndroid Build Coastguard Worker     if (bytesWrittenMore > 0) {
842*6be67779SAndroid Build Coastguard Worker       bytesWrittenTotal += bytesWrittenMore;
843*6be67779SAndroid Build Coastguard Worker       if (bytesWrittenTotal >= count)
844*6be67779SAndroid Build Coastguard Worker         success = 1;
845*6be67779SAndroid Build Coastguard Worker     }
846*6be67779SAndroid Build Coastguard Worker   } while (! success && (errno == EINTR));
847*6be67779SAndroid Build Coastguard Worker 
848*6be67779SAndroid Build Coastguard Worker   close(fd);
849*6be67779SAndroid Build Coastguard Worker   return success;
850*6be67779SAndroid Build Coastguard Worker }
851*6be67779SAndroid Build Coastguard Worker 
852*6be67779SAndroid Build Coastguard Worker #  endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
853*6be67779SAndroid Build Coastguard Worker 
854*6be67779SAndroid Build Coastguard Worker #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
855*6be67779SAndroid Build Coastguard Worker 
856*6be67779SAndroid Build Coastguard Worker #if defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF)
857*6be67779SAndroid Build Coastguard Worker 
858*6be67779SAndroid Build Coastguard Worker static void
writeRandomBytes_arc4random(void * target,size_t count)859*6be67779SAndroid Build Coastguard Worker writeRandomBytes_arc4random(void *target, size_t count) {
860*6be67779SAndroid Build Coastguard Worker   size_t bytesWrittenTotal = 0;
861*6be67779SAndroid Build Coastguard Worker 
862*6be67779SAndroid Build Coastguard Worker   while (bytesWrittenTotal < count) {
863*6be67779SAndroid Build Coastguard Worker     const uint32_t random32 = arc4random();
864*6be67779SAndroid Build Coastguard Worker     size_t i = 0;
865*6be67779SAndroid Build Coastguard Worker 
866*6be67779SAndroid Build Coastguard Worker     for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
867*6be67779SAndroid Build Coastguard Worker          i++, bytesWrittenTotal++) {
868*6be67779SAndroid Build Coastguard Worker       const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
869*6be67779SAndroid Build Coastguard Worker       ((uint8_t *)target)[bytesWrittenTotal] = random8;
870*6be67779SAndroid Build Coastguard Worker     }
871*6be67779SAndroid Build Coastguard Worker   }
872*6be67779SAndroid Build Coastguard Worker }
873*6be67779SAndroid Build Coastguard Worker 
874*6be67779SAndroid Build Coastguard Worker #endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */
875*6be67779SAndroid Build Coastguard Worker 
876*6be67779SAndroid Build Coastguard Worker #ifdef _WIN32
877*6be67779SAndroid Build Coastguard Worker 
878*6be67779SAndroid Build Coastguard Worker /* Provide declaration of rand_s() for MinGW-32 (not 64, which has it),
879*6be67779SAndroid Build Coastguard Worker    as it didn't declare it in its header prior to version 5.3.0 of its
880*6be67779SAndroid Build Coastguard Worker    runtime package (mingwrt, containing stdlib.h).  The upstream fix
881*6be67779SAndroid Build Coastguard Worker    was introduced at https://osdn.net/projects/mingw/ticket/39658 . */
882*6be67779SAndroid Build Coastguard Worker #  if defined(__MINGW32__) && defined(__MINGW32_VERSION)                       \
883*6be67779SAndroid Build Coastguard Worker       && __MINGW32_VERSION < 5003000L && ! defined(__MINGW64_VERSION_MAJOR)
884*6be67779SAndroid Build Coastguard Worker __declspec(dllimport) int rand_s(unsigned int *);
885*6be67779SAndroid Build Coastguard Worker #  endif
886*6be67779SAndroid Build Coastguard Worker 
887*6be67779SAndroid Build Coastguard Worker /* Obtain entropy on Windows using the rand_s() function which
888*6be67779SAndroid Build Coastguard Worker  * generates cryptographically secure random numbers.  Internally it
889*6be67779SAndroid Build Coastguard Worker  * uses RtlGenRandom API which is present in Windows XP and later.
890*6be67779SAndroid Build Coastguard Worker  */
891*6be67779SAndroid Build Coastguard Worker static int
writeRandomBytes_rand_s(void * target,size_t count)892*6be67779SAndroid Build Coastguard Worker writeRandomBytes_rand_s(void *target, size_t count) {
893*6be67779SAndroid Build Coastguard Worker   size_t bytesWrittenTotal = 0;
894*6be67779SAndroid Build Coastguard Worker 
895*6be67779SAndroid Build Coastguard Worker   while (bytesWrittenTotal < count) {
896*6be67779SAndroid Build Coastguard Worker     unsigned int random32 = 0;
897*6be67779SAndroid Build Coastguard Worker     size_t i = 0;
898*6be67779SAndroid Build Coastguard Worker 
899*6be67779SAndroid Build Coastguard Worker     if (rand_s(&random32))
900*6be67779SAndroid Build Coastguard Worker       return 0; /* failure */
901*6be67779SAndroid Build Coastguard Worker 
902*6be67779SAndroid Build Coastguard Worker     for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
903*6be67779SAndroid Build Coastguard Worker          i++, bytesWrittenTotal++) {
904*6be67779SAndroid Build Coastguard Worker       const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
905*6be67779SAndroid Build Coastguard Worker       ((uint8_t *)target)[bytesWrittenTotal] = random8;
906*6be67779SAndroid Build Coastguard Worker     }
907*6be67779SAndroid Build Coastguard Worker   }
908*6be67779SAndroid Build Coastguard Worker   return 1; /* success */
909*6be67779SAndroid Build Coastguard Worker }
910*6be67779SAndroid Build Coastguard Worker 
911*6be67779SAndroid Build Coastguard Worker #endif /* _WIN32 */
912*6be67779SAndroid Build Coastguard Worker 
913*6be67779SAndroid Build Coastguard Worker #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
914*6be67779SAndroid Build Coastguard Worker 
915*6be67779SAndroid Build Coastguard Worker static unsigned long
gather_time_entropy(void)916*6be67779SAndroid Build Coastguard Worker gather_time_entropy(void) {
917*6be67779SAndroid Build Coastguard Worker #  ifdef _WIN32
918*6be67779SAndroid Build Coastguard Worker   FILETIME ft;
919*6be67779SAndroid Build Coastguard Worker   GetSystemTimeAsFileTime(&ft); /* never fails */
920*6be67779SAndroid Build Coastguard Worker   return ft.dwHighDateTime ^ ft.dwLowDateTime;
921*6be67779SAndroid Build Coastguard Worker #  else
922*6be67779SAndroid Build Coastguard Worker   struct timeval tv;
923*6be67779SAndroid Build Coastguard Worker   int gettimeofday_res;
924*6be67779SAndroid Build Coastguard Worker 
925*6be67779SAndroid Build Coastguard Worker   gettimeofday_res = gettimeofday(&tv, NULL);
926*6be67779SAndroid Build Coastguard Worker 
927*6be67779SAndroid Build Coastguard Worker #    if defined(NDEBUG)
928*6be67779SAndroid Build Coastguard Worker   (void)gettimeofday_res;
929*6be67779SAndroid Build Coastguard Worker #    else
930*6be67779SAndroid Build Coastguard Worker   assert(gettimeofday_res == 0);
931*6be67779SAndroid Build Coastguard Worker #    endif /* defined(NDEBUG) */
932*6be67779SAndroid Build Coastguard Worker 
933*6be67779SAndroid Build Coastguard Worker   /* Microseconds time is <20 bits entropy */
934*6be67779SAndroid Build Coastguard Worker   return tv.tv_usec;
935*6be67779SAndroid Build Coastguard Worker #  endif
936*6be67779SAndroid Build Coastguard Worker }
937*6be67779SAndroid Build Coastguard Worker 
938*6be67779SAndroid Build Coastguard Worker #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
939*6be67779SAndroid Build Coastguard Worker 
940*6be67779SAndroid Build Coastguard Worker static unsigned long
ENTROPY_DEBUG(const char * label,unsigned long entropy)941*6be67779SAndroid Build Coastguard Worker ENTROPY_DEBUG(const char *label, unsigned long entropy) {
942*6be67779SAndroid Build Coastguard Worker   if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) {
943*6be67779SAndroid Build Coastguard Worker     fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
944*6be67779SAndroid Build Coastguard Worker             (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
945*6be67779SAndroid Build Coastguard Worker   }
946*6be67779SAndroid Build Coastguard Worker   return entropy;
947*6be67779SAndroid Build Coastguard Worker }
948*6be67779SAndroid Build Coastguard Worker 
949*6be67779SAndroid Build Coastguard Worker static unsigned long
generate_hash_secret_salt(XML_Parser parser)950*6be67779SAndroid Build Coastguard Worker generate_hash_secret_salt(XML_Parser parser) {
951*6be67779SAndroid Build Coastguard Worker   unsigned long entropy;
952*6be67779SAndroid Build Coastguard Worker   (void)parser;
953*6be67779SAndroid Build Coastguard Worker 
954*6be67779SAndroid Build Coastguard Worker   /* "Failproof" high quality providers: */
955*6be67779SAndroid Build Coastguard Worker #if defined(HAVE_ARC4RANDOM_BUF)
956*6be67779SAndroid Build Coastguard Worker   arc4random_buf(&entropy, sizeof(entropy));
957*6be67779SAndroid Build Coastguard Worker   return ENTROPY_DEBUG("arc4random_buf", entropy);
958*6be67779SAndroid Build Coastguard Worker #elif defined(HAVE_ARC4RANDOM)
959*6be67779SAndroid Build Coastguard Worker   writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
960*6be67779SAndroid Build Coastguard Worker   return ENTROPY_DEBUG("arc4random", entropy);
961*6be67779SAndroid Build Coastguard Worker #else
962*6be67779SAndroid Build Coastguard Worker   /* Try high quality providers first .. */
963*6be67779SAndroid Build Coastguard Worker #  ifdef _WIN32
964*6be67779SAndroid Build Coastguard Worker   if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
965*6be67779SAndroid Build Coastguard Worker     return ENTROPY_DEBUG("rand_s", entropy);
966*6be67779SAndroid Build Coastguard Worker   }
967*6be67779SAndroid Build Coastguard Worker #  elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
968*6be67779SAndroid Build Coastguard Worker   if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
969*6be67779SAndroid Build Coastguard Worker     return ENTROPY_DEBUG("getrandom", entropy);
970*6be67779SAndroid Build Coastguard Worker   }
971*6be67779SAndroid Build Coastguard Worker #  endif
972*6be67779SAndroid Build Coastguard Worker #  if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
973*6be67779SAndroid Build Coastguard Worker   if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
974*6be67779SAndroid Build Coastguard Worker     return ENTROPY_DEBUG("/dev/urandom", entropy);
975*6be67779SAndroid Build Coastguard Worker   }
976*6be67779SAndroid Build Coastguard Worker #  endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
977*6be67779SAndroid Build Coastguard Worker   /* .. and self-made low quality for backup: */
978*6be67779SAndroid Build Coastguard Worker 
979*6be67779SAndroid Build Coastguard Worker   /* Process ID is 0 bits entropy if attacker has local access */
980*6be67779SAndroid Build Coastguard Worker   entropy = gather_time_entropy() ^ getpid();
981*6be67779SAndroid Build Coastguard Worker 
982*6be67779SAndroid Build Coastguard Worker   /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
983*6be67779SAndroid Build Coastguard Worker   if (sizeof(unsigned long) == 4) {
984*6be67779SAndroid Build Coastguard Worker     return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
985*6be67779SAndroid Build Coastguard Worker   } else {
986*6be67779SAndroid Build Coastguard Worker     return ENTROPY_DEBUG("fallback(8)",
987*6be67779SAndroid Build Coastguard Worker                          entropy * (unsigned long)2305843009213693951ULL);
988*6be67779SAndroid Build Coastguard Worker   }
989*6be67779SAndroid Build Coastguard Worker #endif
990*6be67779SAndroid Build Coastguard Worker }
991*6be67779SAndroid Build Coastguard Worker 
992*6be67779SAndroid Build Coastguard Worker static unsigned long
get_hash_secret_salt(XML_Parser parser)993*6be67779SAndroid Build Coastguard Worker get_hash_secret_salt(XML_Parser parser) {
994*6be67779SAndroid Build Coastguard Worker   if (parser->m_parentParser != NULL)
995*6be67779SAndroid Build Coastguard Worker     return get_hash_secret_salt(parser->m_parentParser);
996*6be67779SAndroid Build Coastguard Worker   return parser->m_hash_secret_salt;
997*6be67779SAndroid Build Coastguard Worker }
998*6be67779SAndroid Build Coastguard Worker 
999*6be67779SAndroid Build Coastguard Worker static enum XML_Error
callProcessor(XML_Parser parser,const char * start,const char * end,const char ** endPtr)1000*6be67779SAndroid Build Coastguard Worker callProcessor(XML_Parser parser, const char *start, const char *end,
1001*6be67779SAndroid Build Coastguard Worker               const char **endPtr) {
1002*6be67779SAndroid Build Coastguard Worker   const size_t have_now = EXPAT_SAFE_PTR_DIFF(end, start);
1003*6be67779SAndroid Build Coastguard Worker 
1004*6be67779SAndroid Build Coastguard Worker   if (parser->m_reparseDeferralEnabled
1005*6be67779SAndroid Build Coastguard Worker       && ! parser->m_parsingStatus.finalBuffer) {
1006*6be67779SAndroid Build Coastguard Worker     // Heuristic: don't try to parse a partial token again until the amount of
1007*6be67779SAndroid Build Coastguard Worker     // available data has increased significantly.
1008*6be67779SAndroid Build Coastguard Worker     const size_t had_before = parser->m_partialTokenBytesBefore;
1009*6be67779SAndroid Build Coastguard Worker     // ...but *do* try anyway if we're close to causing a reallocation.
1010*6be67779SAndroid Build Coastguard Worker     size_t available_buffer
1011*6be67779SAndroid Build Coastguard Worker         = EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
1012*6be67779SAndroid Build Coastguard Worker #if XML_CONTEXT_BYTES > 0
1013*6be67779SAndroid Build Coastguard Worker     available_buffer -= EXPAT_MIN(available_buffer, XML_CONTEXT_BYTES);
1014*6be67779SAndroid Build Coastguard Worker #endif
1015*6be67779SAndroid Build Coastguard Worker     available_buffer
1016*6be67779SAndroid Build Coastguard Worker         += EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd);
1017*6be67779SAndroid Build Coastguard Worker     // m_lastBufferRequestSize is never assigned a value < 0, so the cast is ok
1018*6be67779SAndroid Build Coastguard Worker     const bool enough
1019*6be67779SAndroid Build Coastguard Worker         = (have_now >= 2 * had_before)
1020*6be67779SAndroid Build Coastguard Worker           || ((size_t)parser->m_lastBufferRequestSize > available_buffer);
1021*6be67779SAndroid Build Coastguard Worker 
1022*6be67779SAndroid Build Coastguard Worker     if (! enough) {
1023*6be67779SAndroid Build Coastguard Worker       *endPtr = start; // callers may expect this to be set
1024*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
1025*6be67779SAndroid Build Coastguard Worker     }
1026*6be67779SAndroid Build Coastguard Worker   }
1027*6be67779SAndroid Build Coastguard Worker #if defined(XML_TESTING)
1028*6be67779SAndroid Build Coastguard Worker   g_bytesScanned += (unsigned)have_now;
1029*6be67779SAndroid Build Coastguard Worker #endif
1030*6be67779SAndroid Build Coastguard Worker   const enum XML_Error ret = parser->m_processor(parser, start, end, endPtr);
1031*6be67779SAndroid Build Coastguard Worker   if (ret == XML_ERROR_NONE) {
1032*6be67779SAndroid Build Coastguard Worker     // if we consumed nothing, remember what we had on this parse attempt.
1033*6be67779SAndroid Build Coastguard Worker     if (*endPtr == start) {
1034*6be67779SAndroid Build Coastguard Worker       parser->m_partialTokenBytesBefore = have_now;
1035*6be67779SAndroid Build Coastguard Worker     } else {
1036*6be67779SAndroid Build Coastguard Worker       parser->m_partialTokenBytesBefore = 0;
1037*6be67779SAndroid Build Coastguard Worker     }
1038*6be67779SAndroid Build Coastguard Worker   }
1039*6be67779SAndroid Build Coastguard Worker   return ret;
1040*6be67779SAndroid Build Coastguard Worker }
1041*6be67779SAndroid Build Coastguard Worker 
1042*6be67779SAndroid Build Coastguard Worker static XML_Bool /* only valid for root parser */
startParsing(XML_Parser parser)1043*6be67779SAndroid Build Coastguard Worker startParsing(XML_Parser parser) {
1044*6be67779SAndroid Build Coastguard Worker   /* hash functions must be initialized before setContext() is called */
1045*6be67779SAndroid Build Coastguard Worker   if (parser->m_hash_secret_salt == 0)
1046*6be67779SAndroid Build Coastguard Worker     parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
1047*6be67779SAndroid Build Coastguard Worker   if (parser->m_ns) {
1048*6be67779SAndroid Build Coastguard Worker     /* implicit context only set for root parser, since child
1049*6be67779SAndroid Build Coastguard Worker        parsers (i.e. external entity parsers) will inherit it
1050*6be67779SAndroid Build Coastguard Worker     */
1051*6be67779SAndroid Build Coastguard Worker     return setContext(parser, implicitContext);
1052*6be67779SAndroid Build Coastguard Worker   }
1053*6be67779SAndroid Build Coastguard Worker   return XML_TRUE;
1054*6be67779SAndroid Build Coastguard Worker }
1055*6be67779SAndroid Build Coastguard Worker 
1056*6be67779SAndroid Build Coastguard Worker XML_Parser XMLCALL
XML_ParserCreate_MM(const XML_Char * encodingName,const XML_Memory_Handling_Suite * memsuite,const XML_Char * nameSep)1057*6be67779SAndroid Build Coastguard Worker XML_ParserCreate_MM(const XML_Char *encodingName,
1058*6be67779SAndroid Build Coastguard Worker                     const XML_Memory_Handling_Suite *memsuite,
1059*6be67779SAndroid Build Coastguard Worker                     const XML_Char *nameSep) {
1060*6be67779SAndroid Build Coastguard Worker   return parserCreate(encodingName, memsuite, nameSep, NULL);
1061*6be67779SAndroid Build Coastguard Worker }
1062*6be67779SAndroid Build Coastguard Worker 
1063*6be67779SAndroid Build Coastguard Worker static XML_Parser
parserCreate(const XML_Char * encodingName,const XML_Memory_Handling_Suite * memsuite,const XML_Char * nameSep,DTD * dtd)1064*6be67779SAndroid Build Coastguard Worker parserCreate(const XML_Char *encodingName,
1065*6be67779SAndroid Build Coastguard Worker              const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep,
1066*6be67779SAndroid Build Coastguard Worker              DTD *dtd) {
1067*6be67779SAndroid Build Coastguard Worker   XML_Parser parser;
1068*6be67779SAndroid Build Coastguard Worker 
1069*6be67779SAndroid Build Coastguard Worker   if (memsuite) {
1070*6be67779SAndroid Build Coastguard Worker     XML_Memory_Handling_Suite *mtemp;
1071*6be67779SAndroid Build Coastguard Worker     parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
1072*6be67779SAndroid Build Coastguard Worker     if (parser != NULL) {
1073*6be67779SAndroid Build Coastguard Worker       mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
1074*6be67779SAndroid Build Coastguard Worker       mtemp->malloc_fcn = memsuite->malloc_fcn;
1075*6be67779SAndroid Build Coastguard Worker       mtemp->realloc_fcn = memsuite->realloc_fcn;
1076*6be67779SAndroid Build Coastguard Worker       mtemp->free_fcn = memsuite->free_fcn;
1077*6be67779SAndroid Build Coastguard Worker     }
1078*6be67779SAndroid Build Coastguard Worker   } else {
1079*6be67779SAndroid Build Coastguard Worker     XML_Memory_Handling_Suite *mtemp;
1080*6be67779SAndroid Build Coastguard Worker     parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
1081*6be67779SAndroid Build Coastguard Worker     if (parser != NULL) {
1082*6be67779SAndroid Build Coastguard Worker       mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
1083*6be67779SAndroid Build Coastguard Worker       mtemp->malloc_fcn = malloc;
1084*6be67779SAndroid Build Coastguard Worker       mtemp->realloc_fcn = realloc;
1085*6be67779SAndroid Build Coastguard Worker       mtemp->free_fcn = free;
1086*6be67779SAndroid Build Coastguard Worker     }
1087*6be67779SAndroid Build Coastguard Worker   }
1088*6be67779SAndroid Build Coastguard Worker 
1089*6be67779SAndroid Build Coastguard Worker   if (! parser)
1090*6be67779SAndroid Build Coastguard Worker     return parser;
1091*6be67779SAndroid Build Coastguard Worker 
1092*6be67779SAndroid Build Coastguard Worker   parser->m_buffer = NULL;
1093*6be67779SAndroid Build Coastguard Worker   parser->m_bufferLim = NULL;
1094*6be67779SAndroid Build Coastguard Worker 
1095*6be67779SAndroid Build Coastguard Worker   parser->m_attsSize = INIT_ATTS_SIZE;
1096*6be67779SAndroid Build Coastguard Worker   parser->m_atts
1097*6be67779SAndroid Build Coastguard Worker       = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
1098*6be67779SAndroid Build Coastguard Worker   if (parser->m_atts == NULL) {
1099*6be67779SAndroid Build Coastguard Worker     FREE(parser, parser);
1100*6be67779SAndroid Build Coastguard Worker     return NULL;
1101*6be67779SAndroid Build Coastguard Worker   }
1102*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
1103*6be67779SAndroid Build Coastguard Worker   parser->m_attInfo = (XML_AttrInfo *)MALLOC(
1104*6be67779SAndroid Build Coastguard Worker       parser, parser->m_attsSize * sizeof(XML_AttrInfo));
1105*6be67779SAndroid Build Coastguard Worker   if (parser->m_attInfo == NULL) {
1106*6be67779SAndroid Build Coastguard Worker     FREE(parser, parser->m_atts);
1107*6be67779SAndroid Build Coastguard Worker     FREE(parser, parser);
1108*6be67779SAndroid Build Coastguard Worker     return NULL;
1109*6be67779SAndroid Build Coastguard Worker   }
1110*6be67779SAndroid Build Coastguard Worker #endif
1111*6be67779SAndroid Build Coastguard Worker   parser->m_dataBuf
1112*6be67779SAndroid Build Coastguard Worker       = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
1113*6be67779SAndroid Build Coastguard Worker   if (parser->m_dataBuf == NULL) {
1114*6be67779SAndroid Build Coastguard Worker     FREE(parser, parser->m_atts);
1115*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
1116*6be67779SAndroid Build Coastguard Worker     FREE(parser, parser->m_attInfo);
1117*6be67779SAndroid Build Coastguard Worker #endif
1118*6be67779SAndroid Build Coastguard Worker     FREE(parser, parser);
1119*6be67779SAndroid Build Coastguard Worker     return NULL;
1120*6be67779SAndroid Build Coastguard Worker   }
1121*6be67779SAndroid Build Coastguard Worker   parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
1122*6be67779SAndroid Build Coastguard Worker 
1123*6be67779SAndroid Build Coastguard Worker   if (dtd)
1124*6be67779SAndroid Build Coastguard Worker     parser->m_dtd = dtd;
1125*6be67779SAndroid Build Coastguard Worker   else {
1126*6be67779SAndroid Build Coastguard Worker     parser->m_dtd = dtdCreate(&parser->m_mem);
1127*6be67779SAndroid Build Coastguard Worker     if (parser->m_dtd == NULL) {
1128*6be67779SAndroid Build Coastguard Worker       FREE(parser, parser->m_dataBuf);
1129*6be67779SAndroid Build Coastguard Worker       FREE(parser, parser->m_atts);
1130*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
1131*6be67779SAndroid Build Coastguard Worker       FREE(parser, parser->m_attInfo);
1132*6be67779SAndroid Build Coastguard Worker #endif
1133*6be67779SAndroid Build Coastguard Worker       FREE(parser, parser);
1134*6be67779SAndroid Build Coastguard Worker       return NULL;
1135*6be67779SAndroid Build Coastguard Worker     }
1136*6be67779SAndroid Build Coastguard Worker   }
1137*6be67779SAndroid Build Coastguard Worker 
1138*6be67779SAndroid Build Coastguard Worker   parser->m_freeBindingList = NULL;
1139*6be67779SAndroid Build Coastguard Worker   parser->m_freeTagList = NULL;
1140*6be67779SAndroid Build Coastguard Worker   parser->m_freeInternalEntities = NULL;
1141*6be67779SAndroid Build Coastguard Worker 
1142*6be67779SAndroid Build Coastguard Worker   parser->m_groupSize = 0;
1143*6be67779SAndroid Build Coastguard Worker   parser->m_groupConnector = NULL;
1144*6be67779SAndroid Build Coastguard Worker 
1145*6be67779SAndroid Build Coastguard Worker   parser->m_unknownEncodingHandler = NULL;
1146*6be67779SAndroid Build Coastguard Worker   parser->m_unknownEncodingHandlerData = NULL;
1147*6be67779SAndroid Build Coastguard Worker 
1148*6be67779SAndroid Build Coastguard Worker   parser->m_namespaceSeparator = ASCII_EXCL;
1149*6be67779SAndroid Build Coastguard Worker   parser->m_ns = XML_FALSE;
1150*6be67779SAndroid Build Coastguard Worker   parser->m_ns_triplets = XML_FALSE;
1151*6be67779SAndroid Build Coastguard Worker 
1152*6be67779SAndroid Build Coastguard Worker   parser->m_nsAtts = NULL;
1153*6be67779SAndroid Build Coastguard Worker   parser->m_nsAttsVersion = 0;
1154*6be67779SAndroid Build Coastguard Worker   parser->m_nsAttsPower = 0;
1155*6be67779SAndroid Build Coastguard Worker 
1156*6be67779SAndroid Build Coastguard Worker   parser->m_protocolEncodingName = NULL;
1157*6be67779SAndroid Build Coastguard Worker 
1158*6be67779SAndroid Build Coastguard Worker   poolInit(&parser->m_tempPool, &(parser->m_mem));
1159*6be67779SAndroid Build Coastguard Worker   poolInit(&parser->m_temp2Pool, &(parser->m_mem));
1160*6be67779SAndroid Build Coastguard Worker   parserInit(parser, encodingName);
1161*6be67779SAndroid Build Coastguard Worker 
1162*6be67779SAndroid Build Coastguard Worker   if (encodingName && ! parser->m_protocolEncodingName) {
1163*6be67779SAndroid Build Coastguard Worker     if (dtd) {
1164*6be67779SAndroid Build Coastguard Worker       // We need to stop the upcoming call to XML_ParserFree from happily
1165*6be67779SAndroid Build Coastguard Worker       // destroying parser->m_dtd because the DTD is shared with the parent
1166*6be67779SAndroid Build Coastguard Worker       // parser and the only guard that keeps XML_ParserFree from destroying
1167*6be67779SAndroid Build Coastguard Worker       // parser->m_dtd is parser->m_isParamEntity but it will be set to
1168*6be67779SAndroid Build Coastguard Worker       // XML_TRUE only later in XML_ExternalEntityParserCreate (or not at all).
1169*6be67779SAndroid Build Coastguard Worker       parser->m_dtd = NULL;
1170*6be67779SAndroid Build Coastguard Worker     }
1171*6be67779SAndroid Build Coastguard Worker     XML_ParserFree(parser);
1172*6be67779SAndroid Build Coastguard Worker     return NULL;
1173*6be67779SAndroid Build Coastguard Worker   }
1174*6be67779SAndroid Build Coastguard Worker 
1175*6be67779SAndroid Build Coastguard Worker   if (nameSep) {
1176*6be67779SAndroid Build Coastguard Worker     parser->m_ns = XML_TRUE;
1177*6be67779SAndroid Build Coastguard Worker     parser->m_internalEncoding = XmlGetInternalEncodingNS();
1178*6be67779SAndroid Build Coastguard Worker     parser->m_namespaceSeparator = *nameSep;
1179*6be67779SAndroid Build Coastguard Worker   } else {
1180*6be67779SAndroid Build Coastguard Worker     parser->m_internalEncoding = XmlGetInternalEncoding();
1181*6be67779SAndroid Build Coastguard Worker   }
1182*6be67779SAndroid Build Coastguard Worker 
1183*6be67779SAndroid Build Coastguard Worker   return parser;
1184*6be67779SAndroid Build Coastguard Worker }
1185*6be67779SAndroid Build Coastguard Worker 
1186*6be67779SAndroid Build Coastguard Worker static void
parserInit(XML_Parser parser,const XML_Char * encodingName)1187*6be67779SAndroid Build Coastguard Worker parserInit(XML_Parser parser, const XML_Char *encodingName) {
1188*6be67779SAndroid Build Coastguard Worker   parser->m_processor = prologInitProcessor;
1189*6be67779SAndroid Build Coastguard Worker   XmlPrologStateInit(&parser->m_prologState);
1190*6be67779SAndroid Build Coastguard Worker   if (encodingName != NULL) {
1191*6be67779SAndroid Build Coastguard Worker     parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1192*6be67779SAndroid Build Coastguard Worker   }
1193*6be67779SAndroid Build Coastguard Worker   parser->m_curBase = NULL;
1194*6be67779SAndroid Build Coastguard Worker   XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
1195*6be67779SAndroid Build Coastguard Worker   parser->m_userData = NULL;
1196*6be67779SAndroid Build Coastguard Worker   parser->m_handlerArg = NULL;
1197*6be67779SAndroid Build Coastguard Worker   parser->m_startElementHandler = NULL;
1198*6be67779SAndroid Build Coastguard Worker   parser->m_endElementHandler = NULL;
1199*6be67779SAndroid Build Coastguard Worker   parser->m_characterDataHandler = NULL;
1200*6be67779SAndroid Build Coastguard Worker   parser->m_processingInstructionHandler = NULL;
1201*6be67779SAndroid Build Coastguard Worker   parser->m_commentHandler = NULL;
1202*6be67779SAndroid Build Coastguard Worker   parser->m_startCdataSectionHandler = NULL;
1203*6be67779SAndroid Build Coastguard Worker   parser->m_endCdataSectionHandler = NULL;
1204*6be67779SAndroid Build Coastguard Worker   parser->m_defaultHandler = NULL;
1205*6be67779SAndroid Build Coastguard Worker   parser->m_startDoctypeDeclHandler = NULL;
1206*6be67779SAndroid Build Coastguard Worker   parser->m_endDoctypeDeclHandler = NULL;
1207*6be67779SAndroid Build Coastguard Worker   parser->m_unparsedEntityDeclHandler = NULL;
1208*6be67779SAndroid Build Coastguard Worker   parser->m_notationDeclHandler = NULL;
1209*6be67779SAndroid Build Coastguard Worker   parser->m_startNamespaceDeclHandler = NULL;
1210*6be67779SAndroid Build Coastguard Worker   parser->m_endNamespaceDeclHandler = NULL;
1211*6be67779SAndroid Build Coastguard Worker   parser->m_notStandaloneHandler = NULL;
1212*6be67779SAndroid Build Coastguard Worker   parser->m_externalEntityRefHandler = NULL;
1213*6be67779SAndroid Build Coastguard Worker   parser->m_externalEntityRefHandlerArg = parser;
1214*6be67779SAndroid Build Coastguard Worker   parser->m_skippedEntityHandler = NULL;
1215*6be67779SAndroid Build Coastguard Worker   parser->m_elementDeclHandler = NULL;
1216*6be67779SAndroid Build Coastguard Worker   parser->m_attlistDeclHandler = NULL;
1217*6be67779SAndroid Build Coastguard Worker   parser->m_entityDeclHandler = NULL;
1218*6be67779SAndroid Build Coastguard Worker   parser->m_xmlDeclHandler = NULL;
1219*6be67779SAndroid Build Coastguard Worker   parser->m_bufferPtr = parser->m_buffer;
1220*6be67779SAndroid Build Coastguard Worker   parser->m_bufferEnd = parser->m_buffer;
1221*6be67779SAndroid Build Coastguard Worker   parser->m_parseEndByteIndex = 0;
1222*6be67779SAndroid Build Coastguard Worker   parser->m_parseEndPtr = NULL;
1223*6be67779SAndroid Build Coastguard Worker   parser->m_partialTokenBytesBefore = 0;
1224*6be67779SAndroid Build Coastguard Worker   parser->m_reparseDeferralEnabled = g_reparseDeferralEnabledDefault;
1225*6be67779SAndroid Build Coastguard Worker   parser->m_lastBufferRequestSize = 0;
1226*6be67779SAndroid Build Coastguard Worker   parser->m_declElementType = NULL;
1227*6be67779SAndroid Build Coastguard Worker   parser->m_declAttributeId = NULL;
1228*6be67779SAndroid Build Coastguard Worker   parser->m_declEntity = NULL;
1229*6be67779SAndroid Build Coastguard Worker   parser->m_doctypeName = NULL;
1230*6be67779SAndroid Build Coastguard Worker   parser->m_doctypeSysid = NULL;
1231*6be67779SAndroid Build Coastguard Worker   parser->m_doctypePubid = NULL;
1232*6be67779SAndroid Build Coastguard Worker   parser->m_declAttributeType = NULL;
1233*6be67779SAndroid Build Coastguard Worker   parser->m_declNotationName = NULL;
1234*6be67779SAndroid Build Coastguard Worker   parser->m_declNotationPublicId = NULL;
1235*6be67779SAndroid Build Coastguard Worker   parser->m_declAttributeIsCdata = XML_FALSE;
1236*6be67779SAndroid Build Coastguard Worker   parser->m_declAttributeIsId = XML_FALSE;
1237*6be67779SAndroid Build Coastguard Worker   memset(&parser->m_position, 0, sizeof(POSITION));
1238*6be67779SAndroid Build Coastguard Worker   parser->m_errorCode = XML_ERROR_NONE;
1239*6be67779SAndroid Build Coastguard Worker   parser->m_eventPtr = NULL;
1240*6be67779SAndroid Build Coastguard Worker   parser->m_eventEndPtr = NULL;
1241*6be67779SAndroid Build Coastguard Worker   parser->m_positionPtr = NULL;
1242*6be67779SAndroid Build Coastguard Worker   parser->m_openInternalEntities = NULL;
1243*6be67779SAndroid Build Coastguard Worker   parser->m_defaultExpandInternalEntities = XML_TRUE;
1244*6be67779SAndroid Build Coastguard Worker   parser->m_tagLevel = 0;
1245*6be67779SAndroid Build Coastguard Worker   parser->m_tagStack = NULL;
1246*6be67779SAndroid Build Coastguard Worker   parser->m_inheritedBindings = NULL;
1247*6be67779SAndroid Build Coastguard Worker   parser->m_nSpecifiedAtts = 0;
1248*6be67779SAndroid Build Coastguard Worker   parser->m_unknownEncodingMem = NULL;
1249*6be67779SAndroid Build Coastguard Worker   parser->m_unknownEncodingRelease = NULL;
1250*6be67779SAndroid Build Coastguard Worker   parser->m_unknownEncodingData = NULL;
1251*6be67779SAndroid Build Coastguard Worker   parser->m_parentParser = NULL;
1252*6be67779SAndroid Build Coastguard Worker   parser->m_parsingStatus.parsing = XML_INITIALIZED;
1253*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
1254*6be67779SAndroid Build Coastguard Worker   parser->m_isParamEntity = XML_FALSE;
1255*6be67779SAndroid Build Coastguard Worker   parser->m_useForeignDTD = XML_FALSE;
1256*6be67779SAndroid Build Coastguard Worker   parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
1257*6be67779SAndroid Build Coastguard Worker #endif
1258*6be67779SAndroid Build Coastguard Worker   parser->m_hash_secret_salt = 0;
1259*6be67779SAndroid Build Coastguard Worker 
1260*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
1261*6be67779SAndroid Build Coastguard Worker   memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
1262*6be67779SAndroid Build Coastguard Worker   parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
1263*6be67779SAndroid Build Coastguard Worker   parser->m_accounting.maximumAmplificationFactor
1264*6be67779SAndroid Build Coastguard Worker       = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT;
1265*6be67779SAndroid Build Coastguard Worker   parser->m_accounting.activationThresholdBytes
1266*6be67779SAndroid Build Coastguard Worker       = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT;
1267*6be67779SAndroid Build Coastguard Worker 
1268*6be67779SAndroid Build Coastguard Worker   memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS));
1269*6be67779SAndroid Build Coastguard Worker   parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u);
1270*6be67779SAndroid Build Coastguard Worker #endif
1271*6be67779SAndroid Build Coastguard Worker }
1272*6be67779SAndroid Build Coastguard Worker 
1273*6be67779SAndroid Build Coastguard Worker /* moves list of bindings to m_freeBindingList */
1274*6be67779SAndroid Build Coastguard Worker static void FASTCALL
moveToFreeBindingList(XML_Parser parser,BINDING * bindings)1275*6be67779SAndroid Build Coastguard Worker moveToFreeBindingList(XML_Parser parser, BINDING *bindings) {
1276*6be67779SAndroid Build Coastguard Worker   while (bindings) {
1277*6be67779SAndroid Build Coastguard Worker     BINDING *b = bindings;
1278*6be67779SAndroid Build Coastguard Worker     bindings = bindings->nextTagBinding;
1279*6be67779SAndroid Build Coastguard Worker     b->nextTagBinding = parser->m_freeBindingList;
1280*6be67779SAndroid Build Coastguard Worker     parser->m_freeBindingList = b;
1281*6be67779SAndroid Build Coastguard Worker   }
1282*6be67779SAndroid Build Coastguard Worker }
1283*6be67779SAndroid Build Coastguard Worker 
1284*6be67779SAndroid Build Coastguard Worker XML_Bool XMLCALL
XML_ParserReset(XML_Parser parser,const XML_Char * encodingName)1285*6be67779SAndroid Build Coastguard Worker XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
1286*6be67779SAndroid Build Coastguard Worker   TAG *tStk;
1287*6be67779SAndroid Build Coastguard Worker   OPEN_INTERNAL_ENTITY *openEntityList;
1288*6be67779SAndroid Build Coastguard Worker 
1289*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1290*6be67779SAndroid Build Coastguard Worker     return XML_FALSE;
1291*6be67779SAndroid Build Coastguard Worker 
1292*6be67779SAndroid Build Coastguard Worker   if (parser->m_parentParser)
1293*6be67779SAndroid Build Coastguard Worker     return XML_FALSE;
1294*6be67779SAndroid Build Coastguard Worker   /* move m_tagStack to m_freeTagList */
1295*6be67779SAndroid Build Coastguard Worker   tStk = parser->m_tagStack;
1296*6be67779SAndroid Build Coastguard Worker   while (tStk) {
1297*6be67779SAndroid Build Coastguard Worker     TAG *tag = tStk;
1298*6be67779SAndroid Build Coastguard Worker     tStk = tStk->parent;
1299*6be67779SAndroid Build Coastguard Worker     tag->parent = parser->m_freeTagList;
1300*6be67779SAndroid Build Coastguard Worker     moveToFreeBindingList(parser, tag->bindings);
1301*6be67779SAndroid Build Coastguard Worker     tag->bindings = NULL;
1302*6be67779SAndroid Build Coastguard Worker     parser->m_freeTagList = tag;
1303*6be67779SAndroid Build Coastguard Worker   }
1304*6be67779SAndroid Build Coastguard Worker   /* move m_openInternalEntities to m_freeInternalEntities */
1305*6be67779SAndroid Build Coastguard Worker   openEntityList = parser->m_openInternalEntities;
1306*6be67779SAndroid Build Coastguard Worker   while (openEntityList) {
1307*6be67779SAndroid Build Coastguard Worker     OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
1308*6be67779SAndroid Build Coastguard Worker     openEntityList = openEntity->next;
1309*6be67779SAndroid Build Coastguard Worker     openEntity->next = parser->m_freeInternalEntities;
1310*6be67779SAndroid Build Coastguard Worker     parser->m_freeInternalEntities = openEntity;
1311*6be67779SAndroid Build Coastguard Worker   }
1312*6be67779SAndroid Build Coastguard Worker   moveToFreeBindingList(parser, parser->m_inheritedBindings);
1313*6be67779SAndroid Build Coastguard Worker   FREE(parser, parser->m_unknownEncodingMem);
1314*6be67779SAndroid Build Coastguard Worker   if (parser->m_unknownEncodingRelease)
1315*6be67779SAndroid Build Coastguard Worker     parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1316*6be67779SAndroid Build Coastguard Worker   poolClear(&parser->m_tempPool);
1317*6be67779SAndroid Build Coastguard Worker   poolClear(&parser->m_temp2Pool);
1318*6be67779SAndroid Build Coastguard Worker   FREE(parser, (void *)parser->m_protocolEncodingName);
1319*6be67779SAndroid Build Coastguard Worker   parser->m_protocolEncodingName = NULL;
1320*6be67779SAndroid Build Coastguard Worker   parserInit(parser, encodingName);
1321*6be67779SAndroid Build Coastguard Worker   dtdReset(parser->m_dtd, &parser->m_mem);
1322*6be67779SAndroid Build Coastguard Worker   return XML_TRUE;
1323*6be67779SAndroid Build Coastguard Worker }
1324*6be67779SAndroid Build Coastguard Worker 
1325*6be67779SAndroid Build Coastguard Worker enum XML_Status XMLCALL
XML_SetEncoding(XML_Parser parser,const XML_Char * encodingName)1326*6be67779SAndroid Build Coastguard Worker XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
1327*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1328*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
1329*6be67779SAndroid Build Coastguard Worker   /* Block after XML_Parse()/XML_ParseBuffer() has been called.
1330*6be67779SAndroid Build Coastguard Worker      XXX There's no way for the caller to determine which of the
1331*6be67779SAndroid Build Coastguard Worker      XXX possible error cases caused the XML_STATUS_ERROR return.
1332*6be67779SAndroid Build Coastguard Worker   */
1333*6be67779SAndroid Build Coastguard Worker   if (parser->m_parsingStatus.parsing == XML_PARSING
1334*6be67779SAndroid Build Coastguard Worker       || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1335*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
1336*6be67779SAndroid Build Coastguard Worker 
1337*6be67779SAndroid Build Coastguard Worker   /* Get rid of any previous encoding name */
1338*6be67779SAndroid Build Coastguard Worker   FREE(parser, (void *)parser->m_protocolEncodingName);
1339*6be67779SAndroid Build Coastguard Worker 
1340*6be67779SAndroid Build Coastguard Worker   if (encodingName == NULL)
1341*6be67779SAndroid Build Coastguard Worker     /* No new encoding name */
1342*6be67779SAndroid Build Coastguard Worker     parser->m_protocolEncodingName = NULL;
1343*6be67779SAndroid Build Coastguard Worker   else {
1344*6be67779SAndroid Build Coastguard Worker     /* Copy the new encoding name into allocated memory */
1345*6be67779SAndroid Build Coastguard Worker     parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1346*6be67779SAndroid Build Coastguard Worker     if (! parser->m_protocolEncodingName)
1347*6be67779SAndroid Build Coastguard Worker       return XML_STATUS_ERROR;
1348*6be67779SAndroid Build Coastguard Worker   }
1349*6be67779SAndroid Build Coastguard Worker   return XML_STATUS_OK;
1350*6be67779SAndroid Build Coastguard Worker }
1351*6be67779SAndroid Build Coastguard Worker 
1352*6be67779SAndroid Build Coastguard Worker XML_Parser XMLCALL
XML_ExternalEntityParserCreate(XML_Parser oldParser,const XML_Char * context,const XML_Char * encodingName)1353*6be67779SAndroid Build Coastguard Worker XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
1354*6be67779SAndroid Build Coastguard Worker                                const XML_Char *encodingName) {
1355*6be67779SAndroid Build Coastguard Worker   XML_Parser parser = oldParser;
1356*6be67779SAndroid Build Coastguard Worker   DTD *newDtd = NULL;
1357*6be67779SAndroid Build Coastguard Worker   DTD *oldDtd;
1358*6be67779SAndroid Build Coastguard Worker   XML_StartElementHandler oldStartElementHandler;
1359*6be67779SAndroid Build Coastguard Worker   XML_EndElementHandler oldEndElementHandler;
1360*6be67779SAndroid Build Coastguard Worker   XML_CharacterDataHandler oldCharacterDataHandler;
1361*6be67779SAndroid Build Coastguard Worker   XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
1362*6be67779SAndroid Build Coastguard Worker   XML_CommentHandler oldCommentHandler;
1363*6be67779SAndroid Build Coastguard Worker   XML_StartCdataSectionHandler oldStartCdataSectionHandler;
1364*6be67779SAndroid Build Coastguard Worker   XML_EndCdataSectionHandler oldEndCdataSectionHandler;
1365*6be67779SAndroid Build Coastguard Worker   XML_DefaultHandler oldDefaultHandler;
1366*6be67779SAndroid Build Coastguard Worker   XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
1367*6be67779SAndroid Build Coastguard Worker   XML_NotationDeclHandler oldNotationDeclHandler;
1368*6be67779SAndroid Build Coastguard Worker   XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
1369*6be67779SAndroid Build Coastguard Worker   XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
1370*6be67779SAndroid Build Coastguard Worker   XML_NotStandaloneHandler oldNotStandaloneHandler;
1371*6be67779SAndroid Build Coastguard Worker   XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
1372*6be67779SAndroid Build Coastguard Worker   XML_SkippedEntityHandler oldSkippedEntityHandler;
1373*6be67779SAndroid Build Coastguard Worker   XML_UnknownEncodingHandler oldUnknownEncodingHandler;
1374*6be67779SAndroid Build Coastguard Worker   XML_ElementDeclHandler oldElementDeclHandler;
1375*6be67779SAndroid Build Coastguard Worker   XML_AttlistDeclHandler oldAttlistDeclHandler;
1376*6be67779SAndroid Build Coastguard Worker   XML_EntityDeclHandler oldEntityDeclHandler;
1377*6be67779SAndroid Build Coastguard Worker   XML_XmlDeclHandler oldXmlDeclHandler;
1378*6be67779SAndroid Build Coastguard Worker   ELEMENT_TYPE *oldDeclElementType;
1379*6be67779SAndroid Build Coastguard Worker 
1380*6be67779SAndroid Build Coastguard Worker   void *oldUserData;
1381*6be67779SAndroid Build Coastguard Worker   void *oldHandlerArg;
1382*6be67779SAndroid Build Coastguard Worker   XML_Bool oldDefaultExpandInternalEntities;
1383*6be67779SAndroid Build Coastguard Worker   XML_Parser oldExternalEntityRefHandlerArg;
1384*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
1385*6be67779SAndroid Build Coastguard Worker   enum XML_ParamEntityParsing oldParamEntityParsing;
1386*6be67779SAndroid Build Coastguard Worker   int oldInEntityValue;
1387*6be67779SAndroid Build Coastguard Worker #endif
1388*6be67779SAndroid Build Coastguard Worker   XML_Bool oldns_triplets;
1389*6be67779SAndroid Build Coastguard Worker   /* Note that the new parser shares the same hash secret as the old
1390*6be67779SAndroid Build Coastguard Worker      parser, so that dtdCopy and copyEntityTable can lookup values
1391*6be67779SAndroid Build Coastguard Worker      from hash tables associated with either parser without us having
1392*6be67779SAndroid Build Coastguard Worker      to worry which hash secrets each table has.
1393*6be67779SAndroid Build Coastguard Worker   */
1394*6be67779SAndroid Build Coastguard Worker   unsigned long oldhash_secret_salt;
1395*6be67779SAndroid Build Coastguard Worker   XML_Bool oldReparseDeferralEnabled;
1396*6be67779SAndroid Build Coastguard Worker 
1397*6be67779SAndroid Build Coastguard Worker   /* Validate the oldParser parameter before we pull everything out of it */
1398*6be67779SAndroid Build Coastguard Worker   if (oldParser == NULL)
1399*6be67779SAndroid Build Coastguard Worker     return NULL;
1400*6be67779SAndroid Build Coastguard Worker 
1401*6be67779SAndroid Build Coastguard Worker   /* Stash the original parser contents on the stack */
1402*6be67779SAndroid Build Coastguard Worker   oldDtd = parser->m_dtd;
1403*6be67779SAndroid Build Coastguard Worker   oldStartElementHandler = parser->m_startElementHandler;
1404*6be67779SAndroid Build Coastguard Worker   oldEndElementHandler = parser->m_endElementHandler;
1405*6be67779SAndroid Build Coastguard Worker   oldCharacterDataHandler = parser->m_characterDataHandler;
1406*6be67779SAndroid Build Coastguard Worker   oldProcessingInstructionHandler = parser->m_processingInstructionHandler;
1407*6be67779SAndroid Build Coastguard Worker   oldCommentHandler = parser->m_commentHandler;
1408*6be67779SAndroid Build Coastguard Worker   oldStartCdataSectionHandler = parser->m_startCdataSectionHandler;
1409*6be67779SAndroid Build Coastguard Worker   oldEndCdataSectionHandler = parser->m_endCdataSectionHandler;
1410*6be67779SAndroid Build Coastguard Worker   oldDefaultHandler = parser->m_defaultHandler;
1411*6be67779SAndroid Build Coastguard Worker   oldUnparsedEntityDeclHandler = parser->m_unparsedEntityDeclHandler;
1412*6be67779SAndroid Build Coastguard Worker   oldNotationDeclHandler = parser->m_notationDeclHandler;
1413*6be67779SAndroid Build Coastguard Worker   oldStartNamespaceDeclHandler = parser->m_startNamespaceDeclHandler;
1414*6be67779SAndroid Build Coastguard Worker   oldEndNamespaceDeclHandler = parser->m_endNamespaceDeclHandler;
1415*6be67779SAndroid Build Coastguard Worker   oldNotStandaloneHandler = parser->m_notStandaloneHandler;
1416*6be67779SAndroid Build Coastguard Worker   oldExternalEntityRefHandler = parser->m_externalEntityRefHandler;
1417*6be67779SAndroid Build Coastguard Worker   oldSkippedEntityHandler = parser->m_skippedEntityHandler;
1418*6be67779SAndroid Build Coastguard Worker   oldUnknownEncodingHandler = parser->m_unknownEncodingHandler;
1419*6be67779SAndroid Build Coastguard Worker   oldElementDeclHandler = parser->m_elementDeclHandler;
1420*6be67779SAndroid Build Coastguard Worker   oldAttlistDeclHandler = parser->m_attlistDeclHandler;
1421*6be67779SAndroid Build Coastguard Worker   oldEntityDeclHandler = parser->m_entityDeclHandler;
1422*6be67779SAndroid Build Coastguard Worker   oldXmlDeclHandler = parser->m_xmlDeclHandler;
1423*6be67779SAndroid Build Coastguard Worker   oldDeclElementType = parser->m_declElementType;
1424*6be67779SAndroid Build Coastguard Worker 
1425*6be67779SAndroid Build Coastguard Worker   oldUserData = parser->m_userData;
1426*6be67779SAndroid Build Coastguard Worker   oldHandlerArg = parser->m_handlerArg;
1427*6be67779SAndroid Build Coastguard Worker   oldDefaultExpandInternalEntities = parser->m_defaultExpandInternalEntities;
1428*6be67779SAndroid Build Coastguard Worker   oldExternalEntityRefHandlerArg = parser->m_externalEntityRefHandlerArg;
1429*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
1430*6be67779SAndroid Build Coastguard Worker   oldParamEntityParsing = parser->m_paramEntityParsing;
1431*6be67779SAndroid Build Coastguard Worker   oldInEntityValue = parser->m_prologState.inEntityValue;
1432*6be67779SAndroid Build Coastguard Worker #endif
1433*6be67779SAndroid Build Coastguard Worker   oldns_triplets = parser->m_ns_triplets;
1434*6be67779SAndroid Build Coastguard Worker   /* Note that the new parser shares the same hash secret as the old
1435*6be67779SAndroid Build Coastguard Worker      parser, so that dtdCopy and copyEntityTable can lookup values
1436*6be67779SAndroid Build Coastguard Worker      from hash tables associated with either parser without us having
1437*6be67779SAndroid Build Coastguard Worker      to worry which hash secrets each table has.
1438*6be67779SAndroid Build Coastguard Worker   */
1439*6be67779SAndroid Build Coastguard Worker   oldhash_secret_salt = parser->m_hash_secret_salt;
1440*6be67779SAndroid Build Coastguard Worker   oldReparseDeferralEnabled = parser->m_reparseDeferralEnabled;
1441*6be67779SAndroid Build Coastguard Worker 
1442*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
1443*6be67779SAndroid Build Coastguard Worker   if (! context)
1444*6be67779SAndroid Build Coastguard Worker     newDtd = oldDtd;
1445*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
1446*6be67779SAndroid Build Coastguard Worker 
1447*6be67779SAndroid Build Coastguard Worker   /* Note that the magical uses of the pre-processor to make field
1448*6be67779SAndroid Build Coastguard Worker      access look more like C++ require that `parser' be overwritten
1449*6be67779SAndroid Build Coastguard Worker      here.  This makes this function more painful to follow than it
1450*6be67779SAndroid Build Coastguard Worker      would be otherwise.
1451*6be67779SAndroid Build Coastguard Worker   */
1452*6be67779SAndroid Build Coastguard Worker   if (parser->m_ns) {
1453*6be67779SAndroid Build Coastguard Worker     XML_Char tmp[2] = {parser->m_namespaceSeparator, 0};
1454*6be67779SAndroid Build Coastguard Worker     parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1455*6be67779SAndroid Build Coastguard Worker   } else {
1456*6be67779SAndroid Build Coastguard Worker     parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1457*6be67779SAndroid Build Coastguard Worker   }
1458*6be67779SAndroid Build Coastguard Worker 
1459*6be67779SAndroid Build Coastguard Worker   if (! parser)
1460*6be67779SAndroid Build Coastguard Worker     return NULL;
1461*6be67779SAndroid Build Coastguard Worker 
1462*6be67779SAndroid Build Coastguard Worker   parser->m_startElementHandler = oldStartElementHandler;
1463*6be67779SAndroid Build Coastguard Worker   parser->m_endElementHandler = oldEndElementHandler;
1464*6be67779SAndroid Build Coastguard Worker   parser->m_characterDataHandler = oldCharacterDataHandler;
1465*6be67779SAndroid Build Coastguard Worker   parser->m_processingInstructionHandler = oldProcessingInstructionHandler;
1466*6be67779SAndroid Build Coastguard Worker   parser->m_commentHandler = oldCommentHandler;
1467*6be67779SAndroid Build Coastguard Worker   parser->m_startCdataSectionHandler = oldStartCdataSectionHandler;
1468*6be67779SAndroid Build Coastguard Worker   parser->m_endCdataSectionHandler = oldEndCdataSectionHandler;
1469*6be67779SAndroid Build Coastguard Worker   parser->m_defaultHandler = oldDefaultHandler;
1470*6be67779SAndroid Build Coastguard Worker   parser->m_unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1471*6be67779SAndroid Build Coastguard Worker   parser->m_notationDeclHandler = oldNotationDeclHandler;
1472*6be67779SAndroid Build Coastguard Worker   parser->m_startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1473*6be67779SAndroid Build Coastguard Worker   parser->m_endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1474*6be67779SAndroid Build Coastguard Worker   parser->m_notStandaloneHandler = oldNotStandaloneHandler;
1475*6be67779SAndroid Build Coastguard Worker   parser->m_externalEntityRefHandler = oldExternalEntityRefHandler;
1476*6be67779SAndroid Build Coastguard Worker   parser->m_skippedEntityHandler = oldSkippedEntityHandler;
1477*6be67779SAndroid Build Coastguard Worker   parser->m_unknownEncodingHandler = oldUnknownEncodingHandler;
1478*6be67779SAndroid Build Coastguard Worker   parser->m_elementDeclHandler = oldElementDeclHandler;
1479*6be67779SAndroid Build Coastguard Worker   parser->m_attlistDeclHandler = oldAttlistDeclHandler;
1480*6be67779SAndroid Build Coastguard Worker   parser->m_entityDeclHandler = oldEntityDeclHandler;
1481*6be67779SAndroid Build Coastguard Worker   parser->m_xmlDeclHandler = oldXmlDeclHandler;
1482*6be67779SAndroid Build Coastguard Worker   parser->m_declElementType = oldDeclElementType;
1483*6be67779SAndroid Build Coastguard Worker   parser->m_userData = oldUserData;
1484*6be67779SAndroid Build Coastguard Worker   if (oldUserData == oldHandlerArg)
1485*6be67779SAndroid Build Coastguard Worker     parser->m_handlerArg = parser->m_userData;
1486*6be67779SAndroid Build Coastguard Worker   else
1487*6be67779SAndroid Build Coastguard Worker     parser->m_handlerArg = parser;
1488*6be67779SAndroid Build Coastguard Worker   if (oldExternalEntityRefHandlerArg != oldParser)
1489*6be67779SAndroid Build Coastguard Worker     parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1490*6be67779SAndroid Build Coastguard Worker   parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1491*6be67779SAndroid Build Coastguard Worker   parser->m_ns_triplets = oldns_triplets;
1492*6be67779SAndroid Build Coastguard Worker   parser->m_hash_secret_salt = oldhash_secret_salt;
1493*6be67779SAndroid Build Coastguard Worker   parser->m_reparseDeferralEnabled = oldReparseDeferralEnabled;
1494*6be67779SAndroid Build Coastguard Worker   parser->m_parentParser = oldParser;
1495*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
1496*6be67779SAndroid Build Coastguard Worker   parser->m_paramEntityParsing = oldParamEntityParsing;
1497*6be67779SAndroid Build Coastguard Worker   parser->m_prologState.inEntityValue = oldInEntityValue;
1498*6be67779SAndroid Build Coastguard Worker   if (context) {
1499*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
1500*6be67779SAndroid Build Coastguard Worker     if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
1501*6be67779SAndroid Build Coastguard Worker         || ! setContext(parser, context)) {
1502*6be67779SAndroid Build Coastguard Worker       XML_ParserFree(parser);
1503*6be67779SAndroid Build Coastguard Worker       return NULL;
1504*6be67779SAndroid Build Coastguard Worker     }
1505*6be67779SAndroid Build Coastguard Worker     parser->m_processor = externalEntityInitProcessor;
1506*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
1507*6be67779SAndroid Build Coastguard Worker   } else {
1508*6be67779SAndroid Build Coastguard Worker     /* The DTD instance referenced by parser->m_dtd is shared between the
1509*6be67779SAndroid Build Coastguard Worker        document's root parser and external PE parsers, therefore one does not
1510*6be67779SAndroid Build Coastguard Worker        need to call setContext. In addition, one also *must* not call
1511*6be67779SAndroid Build Coastguard Worker        setContext, because this would overwrite existing prefix->binding
1512*6be67779SAndroid Build Coastguard Worker        pointers in parser->m_dtd with ones that get destroyed with the external
1513*6be67779SAndroid Build Coastguard Worker        PE parser. This would leave those prefixes with dangling pointers.
1514*6be67779SAndroid Build Coastguard Worker     */
1515*6be67779SAndroid Build Coastguard Worker     parser->m_isParamEntity = XML_TRUE;
1516*6be67779SAndroid Build Coastguard Worker     XmlPrologStateInitExternalEntity(&parser->m_prologState);
1517*6be67779SAndroid Build Coastguard Worker     parser->m_processor = externalParEntInitProcessor;
1518*6be67779SAndroid Build Coastguard Worker   }
1519*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
1520*6be67779SAndroid Build Coastguard Worker   return parser;
1521*6be67779SAndroid Build Coastguard Worker }
1522*6be67779SAndroid Build Coastguard Worker 
1523*6be67779SAndroid Build Coastguard Worker static void FASTCALL
destroyBindings(BINDING * bindings,XML_Parser parser)1524*6be67779SAndroid Build Coastguard Worker destroyBindings(BINDING *bindings, XML_Parser parser) {
1525*6be67779SAndroid Build Coastguard Worker   for (;;) {
1526*6be67779SAndroid Build Coastguard Worker     BINDING *b = bindings;
1527*6be67779SAndroid Build Coastguard Worker     if (! b)
1528*6be67779SAndroid Build Coastguard Worker       break;
1529*6be67779SAndroid Build Coastguard Worker     bindings = b->nextTagBinding;
1530*6be67779SAndroid Build Coastguard Worker     FREE(parser, b->uri);
1531*6be67779SAndroid Build Coastguard Worker     FREE(parser, b);
1532*6be67779SAndroid Build Coastguard Worker   }
1533*6be67779SAndroid Build Coastguard Worker }
1534*6be67779SAndroid Build Coastguard Worker 
1535*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_ParserFree(XML_Parser parser)1536*6be67779SAndroid Build Coastguard Worker XML_ParserFree(XML_Parser parser) {
1537*6be67779SAndroid Build Coastguard Worker   TAG *tagList;
1538*6be67779SAndroid Build Coastguard Worker   OPEN_INTERNAL_ENTITY *entityList;
1539*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1540*6be67779SAndroid Build Coastguard Worker     return;
1541*6be67779SAndroid Build Coastguard Worker   /* free m_tagStack and m_freeTagList */
1542*6be67779SAndroid Build Coastguard Worker   tagList = parser->m_tagStack;
1543*6be67779SAndroid Build Coastguard Worker   for (;;) {
1544*6be67779SAndroid Build Coastguard Worker     TAG *p;
1545*6be67779SAndroid Build Coastguard Worker     if (tagList == NULL) {
1546*6be67779SAndroid Build Coastguard Worker       if (parser->m_freeTagList == NULL)
1547*6be67779SAndroid Build Coastguard Worker         break;
1548*6be67779SAndroid Build Coastguard Worker       tagList = parser->m_freeTagList;
1549*6be67779SAndroid Build Coastguard Worker       parser->m_freeTagList = NULL;
1550*6be67779SAndroid Build Coastguard Worker     }
1551*6be67779SAndroid Build Coastguard Worker     p = tagList;
1552*6be67779SAndroid Build Coastguard Worker     tagList = tagList->parent;
1553*6be67779SAndroid Build Coastguard Worker     FREE(parser, p->buf);
1554*6be67779SAndroid Build Coastguard Worker     destroyBindings(p->bindings, parser);
1555*6be67779SAndroid Build Coastguard Worker     FREE(parser, p);
1556*6be67779SAndroid Build Coastguard Worker   }
1557*6be67779SAndroid Build Coastguard Worker   /* free m_openInternalEntities and m_freeInternalEntities */
1558*6be67779SAndroid Build Coastguard Worker   entityList = parser->m_openInternalEntities;
1559*6be67779SAndroid Build Coastguard Worker   for (;;) {
1560*6be67779SAndroid Build Coastguard Worker     OPEN_INTERNAL_ENTITY *openEntity;
1561*6be67779SAndroid Build Coastguard Worker     if (entityList == NULL) {
1562*6be67779SAndroid Build Coastguard Worker       if (parser->m_freeInternalEntities == NULL)
1563*6be67779SAndroid Build Coastguard Worker         break;
1564*6be67779SAndroid Build Coastguard Worker       entityList = parser->m_freeInternalEntities;
1565*6be67779SAndroid Build Coastguard Worker       parser->m_freeInternalEntities = NULL;
1566*6be67779SAndroid Build Coastguard Worker     }
1567*6be67779SAndroid Build Coastguard Worker     openEntity = entityList;
1568*6be67779SAndroid Build Coastguard Worker     entityList = entityList->next;
1569*6be67779SAndroid Build Coastguard Worker     FREE(parser, openEntity);
1570*6be67779SAndroid Build Coastguard Worker   }
1571*6be67779SAndroid Build Coastguard Worker 
1572*6be67779SAndroid Build Coastguard Worker   destroyBindings(parser->m_freeBindingList, parser);
1573*6be67779SAndroid Build Coastguard Worker   destroyBindings(parser->m_inheritedBindings, parser);
1574*6be67779SAndroid Build Coastguard Worker   poolDestroy(&parser->m_tempPool);
1575*6be67779SAndroid Build Coastguard Worker   poolDestroy(&parser->m_temp2Pool);
1576*6be67779SAndroid Build Coastguard Worker   FREE(parser, (void *)parser->m_protocolEncodingName);
1577*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
1578*6be67779SAndroid Build Coastguard Worker   /* external parameter entity parsers share the DTD structure
1579*6be67779SAndroid Build Coastguard Worker      parser->m_dtd with the root parser, so we must not destroy it
1580*6be67779SAndroid Build Coastguard Worker   */
1581*6be67779SAndroid Build Coastguard Worker   if (! parser->m_isParamEntity && parser->m_dtd)
1582*6be67779SAndroid Build Coastguard Worker #else
1583*6be67779SAndroid Build Coastguard Worker   if (parser->m_dtd)
1584*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
1585*6be67779SAndroid Build Coastguard Worker     dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser,
1586*6be67779SAndroid Build Coastguard Worker                &parser->m_mem);
1587*6be67779SAndroid Build Coastguard Worker   FREE(parser, (void *)parser->m_atts);
1588*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
1589*6be67779SAndroid Build Coastguard Worker   FREE(parser, (void *)parser->m_attInfo);
1590*6be67779SAndroid Build Coastguard Worker #endif
1591*6be67779SAndroid Build Coastguard Worker   FREE(parser, parser->m_groupConnector);
1592*6be67779SAndroid Build Coastguard Worker   FREE(parser, parser->m_buffer);
1593*6be67779SAndroid Build Coastguard Worker   FREE(parser, parser->m_dataBuf);
1594*6be67779SAndroid Build Coastguard Worker   FREE(parser, parser->m_nsAtts);
1595*6be67779SAndroid Build Coastguard Worker   FREE(parser, parser->m_unknownEncodingMem);
1596*6be67779SAndroid Build Coastguard Worker   if (parser->m_unknownEncodingRelease)
1597*6be67779SAndroid Build Coastguard Worker     parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1598*6be67779SAndroid Build Coastguard Worker   FREE(parser, parser);
1599*6be67779SAndroid Build Coastguard Worker }
1600*6be67779SAndroid Build Coastguard Worker 
1601*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_UseParserAsHandlerArg(XML_Parser parser)1602*6be67779SAndroid Build Coastguard Worker XML_UseParserAsHandlerArg(XML_Parser parser) {
1603*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1604*6be67779SAndroid Build Coastguard Worker     parser->m_handlerArg = parser;
1605*6be67779SAndroid Build Coastguard Worker }
1606*6be67779SAndroid Build Coastguard Worker 
1607*6be67779SAndroid Build Coastguard Worker enum XML_Error XMLCALL
XML_UseForeignDTD(XML_Parser parser,XML_Bool useDTD)1608*6be67779SAndroid Build Coastguard Worker XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) {
1609*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1610*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_INVALID_ARGUMENT;
1611*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
1612*6be67779SAndroid Build Coastguard Worker   /* block after XML_Parse()/XML_ParseBuffer() has been called */
1613*6be67779SAndroid Build Coastguard Worker   if (parser->m_parsingStatus.parsing == XML_PARSING
1614*6be67779SAndroid Build Coastguard Worker       || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1615*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1616*6be67779SAndroid Build Coastguard Worker   parser->m_useForeignDTD = useDTD;
1617*6be67779SAndroid Build Coastguard Worker   return XML_ERROR_NONE;
1618*6be67779SAndroid Build Coastguard Worker #else
1619*6be67779SAndroid Build Coastguard Worker   UNUSED_P(useDTD);
1620*6be67779SAndroid Build Coastguard Worker   return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1621*6be67779SAndroid Build Coastguard Worker #endif
1622*6be67779SAndroid Build Coastguard Worker }
1623*6be67779SAndroid Build Coastguard Worker 
1624*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetReturnNSTriplet(XML_Parser parser,int do_nst)1625*6be67779SAndroid Build Coastguard Worker XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
1626*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1627*6be67779SAndroid Build Coastguard Worker     return;
1628*6be67779SAndroid Build Coastguard Worker   /* block after XML_Parse()/XML_ParseBuffer() has been called */
1629*6be67779SAndroid Build Coastguard Worker   if (parser->m_parsingStatus.parsing == XML_PARSING
1630*6be67779SAndroid Build Coastguard Worker       || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1631*6be67779SAndroid Build Coastguard Worker     return;
1632*6be67779SAndroid Build Coastguard Worker   parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1633*6be67779SAndroid Build Coastguard Worker }
1634*6be67779SAndroid Build Coastguard Worker 
1635*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetUserData(XML_Parser parser,void * p)1636*6be67779SAndroid Build Coastguard Worker XML_SetUserData(XML_Parser parser, void *p) {
1637*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1638*6be67779SAndroid Build Coastguard Worker     return;
1639*6be67779SAndroid Build Coastguard Worker   if (parser->m_handlerArg == parser->m_userData)
1640*6be67779SAndroid Build Coastguard Worker     parser->m_handlerArg = parser->m_userData = p;
1641*6be67779SAndroid Build Coastguard Worker   else
1642*6be67779SAndroid Build Coastguard Worker     parser->m_userData = p;
1643*6be67779SAndroid Build Coastguard Worker }
1644*6be67779SAndroid Build Coastguard Worker 
1645*6be67779SAndroid Build Coastguard Worker enum XML_Status XMLCALL
XML_SetBase(XML_Parser parser,const XML_Char * p)1646*6be67779SAndroid Build Coastguard Worker XML_SetBase(XML_Parser parser, const XML_Char *p) {
1647*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1648*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
1649*6be67779SAndroid Build Coastguard Worker   if (p) {
1650*6be67779SAndroid Build Coastguard Worker     p = poolCopyString(&parser->m_dtd->pool, p);
1651*6be67779SAndroid Build Coastguard Worker     if (! p)
1652*6be67779SAndroid Build Coastguard Worker       return XML_STATUS_ERROR;
1653*6be67779SAndroid Build Coastguard Worker     parser->m_curBase = p;
1654*6be67779SAndroid Build Coastguard Worker   } else
1655*6be67779SAndroid Build Coastguard Worker     parser->m_curBase = NULL;
1656*6be67779SAndroid Build Coastguard Worker   return XML_STATUS_OK;
1657*6be67779SAndroid Build Coastguard Worker }
1658*6be67779SAndroid Build Coastguard Worker 
1659*6be67779SAndroid Build Coastguard Worker const XML_Char *XMLCALL
XML_GetBase(XML_Parser parser)1660*6be67779SAndroid Build Coastguard Worker XML_GetBase(XML_Parser parser) {
1661*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1662*6be67779SAndroid Build Coastguard Worker     return NULL;
1663*6be67779SAndroid Build Coastguard Worker   return parser->m_curBase;
1664*6be67779SAndroid Build Coastguard Worker }
1665*6be67779SAndroid Build Coastguard Worker 
1666*6be67779SAndroid Build Coastguard Worker int XMLCALL
XML_GetSpecifiedAttributeCount(XML_Parser parser)1667*6be67779SAndroid Build Coastguard Worker XML_GetSpecifiedAttributeCount(XML_Parser parser) {
1668*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1669*6be67779SAndroid Build Coastguard Worker     return -1;
1670*6be67779SAndroid Build Coastguard Worker   return parser->m_nSpecifiedAtts;
1671*6be67779SAndroid Build Coastguard Worker }
1672*6be67779SAndroid Build Coastguard Worker 
1673*6be67779SAndroid Build Coastguard Worker int XMLCALL
XML_GetIdAttributeIndex(XML_Parser parser)1674*6be67779SAndroid Build Coastguard Worker XML_GetIdAttributeIndex(XML_Parser parser) {
1675*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1676*6be67779SAndroid Build Coastguard Worker     return -1;
1677*6be67779SAndroid Build Coastguard Worker   return parser->m_idAttIndex;
1678*6be67779SAndroid Build Coastguard Worker }
1679*6be67779SAndroid Build Coastguard Worker 
1680*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
1681*6be67779SAndroid Build Coastguard Worker const XML_AttrInfo *XMLCALL
XML_GetAttributeInfo(XML_Parser parser)1682*6be67779SAndroid Build Coastguard Worker XML_GetAttributeInfo(XML_Parser parser) {
1683*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1684*6be67779SAndroid Build Coastguard Worker     return NULL;
1685*6be67779SAndroid Build Coastguard Worker   return parser->m_attInfo;
1686*6be67779SAndroid Build Coastguard Worker }
1687*6be67779SAndroid Build Coastguard Worker #endif
1688*6be67779SAndroid Build Coastguard Worker 
1689*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetElementHandler(XML_Parser parser,XML_StartElementHandler start,XML_EndElementHandler end)1690*6be67779SAndroid Build Coastguard Worker XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start,
1691*6be67779SAndroid Build Coastguard Worker                       XML_EndElementHandler end) {
1692*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1693*6be67779SAndroid Build Coastguard Worker     return;
1694*6be67779SAndroid Build Coastguard Worker   parser->m_startElementHandler = start;
1695*6be67779SAndroid Build Coastguard Worker   parser->m_endElementHandler = end;
1696*6be67779SAndroid Build Coastguard Worker }
1697*6be67779SAndroid Build Coastguard Worker 
1698*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetStartElementHandler(XML_Parser parser,XML_StartElementHandler start)1699*6be67779SAndroid Build Coastguard Worker XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) {
1700*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1701*6be67779SAndroid Build Coastguard Worker     parser->m_startElementHandler = start;
1702*6be67779SAndroid Build Coastguard Worker }
1703*6be67779SAndroid Build Coastguard Worker 
1704*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetEndElementHandler(XML_Parser parser,XML_EndElementHandler end)1705*6be67779SAndroid Build Coastguard Worker XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) {
1706*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1707*6be67779SAndroid Build Coastguard Worker     parser->m_endElementHandler = end;
1708*6be67779SAndroid Build Coastguard Worker }
1709*6be67779SAndroid Build Coastguard Worker 
1710*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetCharacterDataHandler(XML_Parser parser,XML_CharacterDataHandler handler)1711*6be67779SAndroid Build Coastguard Worker XML_SetCharacterDataHandler(XML_Parser parser,
1712*6be67779SAndroid Build Coastguard Worker                             XML_CharacterDataHandler handler) {
1713*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1714*6be67779SAndroid Build Coastguard Worker     parser->m_characterDataHandler = handler;
1715*6be67779SAndroid Build Coastguard Worker }
1716*6be67779SAndroid Build Coastguard Worker 
1717*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetProcessingInstructionHandler(XML_Parser parser,XML_ProcessingInstructionHandler handler)1718*6be67779SAndroid Build Coastguard Worker XML_SetProcessingInstructionHandler(XML_Parser parser,
1719*6be67779SAndroid Build Coastguard Worker                                     XML_ProcessingInstructionHandler handler) {
1720*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1721*6be67779SAndroid Build Coastguard Worker     parser->m_processingInstructionHandler = handler;
1722*6be67779SAndroid Build Coastguard Worker }
1723*6be67779SAndroid Build Coastguard Worker 
1724*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetCommentHandler(XML_Parser parser,XML_CommentHandler handler)1725*6be67779SAndroid Build Coastguard Worker XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) {
1726*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1727*6be67779SAndroid Build Coastguard Worker     parser->m_commentHandler = handler;
1728*6be67779SAndroid Build Coastguard Worker }
1729*6be67779SAndroid Build Coastguard Worker 
1730*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetCdataSectionHandler(XML_Parser parser,XML_StartCdataSectionHandler start,XML_EndCdataSectionHandler end)1731*6be67779SAndroid Build Coastguard Worker XML_SetCdataSectionHandler(XML_Parser parser,
1732*6be67779SAndroid Build Coastguard Worker                            XML_StartCdataSectionHandler start,
1733*6be67779SAndroid Build Coastguard Worker                            XML_EndCdataSectionHandler end) {
1734*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1735*6be67779SAndroid Build Coastguard Worker     return;
1736*6be67779SAndroid Build Coastguard Worker   parser->m_startCdataSectionHandler = start;
1737*6be67779SAndroid Build Coastguard Worker   parser->m_endCdataSectionHandler = end;
1738*6be67779SAndroid Build Coastguard Worker }
1739*6be67779SAndroid Build Coastguard Worker 
1740*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetStartCdataSectionHandler(XML_Parser parser,XML_StartCdataSectionHandler start)1741*6be67779SAndroid Build Coastguard Worker XML_SetStartCdataSectionHandler(XML_Parser parser,
1742*6be67779SAndroid Build Coastguard Worker                                 XML_StartCdataSectionHandler start) {
1743*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1744*6be67779SAndroid Build Coastguard Worker     parser->m_startCdataSectionHandler = start;
1745*6be67779SAndroid Build Coastguard Worker }
1746*6be67779SAndroid Build Coastguard Worker 
1747*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetEndCdataSectionHandler(XML_Parser parser,XML_EndCdataSectionHandler end)1748*6be67779SAndroid Build Coastguard Worker XML_SetEndCdataSectionHandler(XML_Parser parser,
1749*6be67779SAndroid Build Coastguard Worker                               XML_EndCdataSectionHandler end) {
1750*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1751*6be67779SAndroid Build Coastguard Worker     parser->m_endCdataSectionHandler = end;
1752*6be67779SAndroid Build Coastguard Worker }
1753*6be67779SAndroid Build Coastguard Worker 
1754*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetDefaultHandler(XML_Parser parser,XML_DefaultHandler handler)1755*6be67779SAndroid Build Coastguard Worker XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) {
1756*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1757*6be67779SAndroid Build Coastguard Worker     return;
1758*6be67779SAndroid Build Coastguard Worker   parser->m_defaultHandler = handler;
1759*6be67779SAndroid Build Coastguard Worker   parser->m_defaultExpandInternalEntities = XML_FALSE;
1760*6be67779SAndroid Build Coastguard Worker }
1761*6be67779SAndroid Build Coastguard Worker 
1762*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetDefaultHandlerExpand(XML_Parser parser,XML_DefaultHandler handler)1763*6be67779SAndroid Build Coastguard Worker XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) {
1764*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1765*6be67779SAndroid Build Coastguard Worker     return;
1766*6be67779SAndroid Build Coastguard Worker   parser->m_defaultHandler = handler;
1767*6be67779SAndroid Build Coastguard Worker   parser->m_defaultExpandInternalEntities = XML_TRUE;
1768*6be67779SAndroid Build Coastguard Worker }
1769*6be67779SAndroid Build Coastguard Worker 
1770*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetDoctypeDeclHandler(XML_Parser parser,XML_StartDoctypeDeclHandler start,XML_EndDoctypeDeclHandler end)1771*6be67779SAndroid Build Coastguard Worker XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start,
1772*6be67779SAndroid Build Coastguard Worker                           XML_EndDoctypeDeclHandler end) {
1773*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1774*6be67779SAndroid Build Coastguard Worker     return;
1775*6be67779SAndroid Build Coastguard Worker   parser->m_startDoctypeDeclHandler = start;
1776*6be67779SAndroid Build Coastguard Worker   parser->m_endDoctypeDeclHandler = end;
1777*6be67779SAndroid Build Coastguard Worker }
1778*6be67779SAndroid Build Coastguard Worker 
1779*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetStartDoctypeDeclHandler(XML_Parser parser,XML_StartDoctypeDeclHandler start)1780*6be67779SAndroid Build Coastguard Worker XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1781*6be67779SAndroid Build Coastguard Worker                                XML_StartDoctypeDeclHandler start) {
1782*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1783*6be67779SAndroid Build Coastguard Worker     parser->m_startDoctypeDeclHandler = start;
1784*6be67779SAndroid Build Coastguard Worker }
1785*6be67779SAndroid Build Coastguard Worker 
1786*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetEndDoctypeDeclHandler(XML_Parser parser,XML_EndDoctypeDeclHandler end)1787*6be67779SAndroid Build Coastguard Worker XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) {
1788*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1789*6be67779SAndroid Build Coastguard Worker     parser->m_endDoctypeDeclHandler = end;
1790*6be67779SAndroid Build Coastguard Worker }
1791*6be67779SAndroid Build Coastguard Worker 
1792*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetUnparsedEntityDeclHandler(XML_Parser parser,XML_UnparsedEntityDeclHandler handler)1793*6be67779SAndroid Build Coastguard Worker XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1794*6be67779SAndroid Build Coastguard Worker                                  XML_UnparsedEntityDeclHandler handler) {
1795*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1796*6be67779SAndroid Build Coastguard Worker     parser->m_unparsedEntityDeclHandler = handler;
1797*6be67779SAndroid Build Coastguard Worker }
1798*6be67779SAndroid Build Coastguard Worker 
1799*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetNotationDeclHandler(XML_Parser parser,XML_NotationDeclHandler handler)1800*6be67779SAndroid Build Coastguard Worker XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) {
1801*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1802*6be67779SAndroid Build Coastguard Worker     parser->m_notationDeclHandler = handler;
1803*6be67779SAndroid Build Coastguard Worker }
1804*6be67779SAndroid Build Coastguard Worker 
1805*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetNamespaceDeclHandler(XML_Parser parser,XML_StartNamespaceDeclHandler start,XML_EndNamespaceDeclHandler end)1806*6be67779SAndroid Build Coastguard Worker XML_SetNamespaceDeclHandler(XML_Parser parser,
1807*6be67779SAndroid Build Coastguard Worker                             XML_StartNamespaceDeclHandler start,
1808*6be67779SAndroid Build Coastguard Worker                             XML_EndNamespaceDeclHandler end) {
1809*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1810*6be67779SAndroid Build Coastguard Worker     return;
1811*6be67779SAndroid Build Coastguard Worker   parser->m_startNamespaceDeclHandler = start;
1812*6be67779SAndroid Build Coastguard Worker   parser->m_endNamespaceDeclHandler = end;
1813*6be67779SAndroid Build Coastguard Worker }
1814*6be67779SAndroid Build Coastguard Worker 
1815*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetStartNamespaceDeclHandler(XML_Parser parser,XML_StartNamespaceDeclHandler start)1816*6be67779SAndroid Build Coastguard Worker XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1817*6be67779SAndroid Build Coastguard Worker                                  XML_StartNamespaceDeclHandler start) {
1818*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1819*6be67779SAndroid Build Coastguard Worker     parser->m_startNamespaceDeclHandler = start;
1820*6be67779SAndroid Build Coastguard Worker }
1821*6be67779SAndroid Build Coastguard Worker 
1822*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetEndNamespaceDeclHandler(XML_Parser parser,XML_EndNamespaceDeclHandler end)1823*6be67779SAndroid Build Coastguard Worker XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1824*6be67779SAndroid Build Coastguard Worker                                XML_EndNamespaceDeclHandler end) {
1825*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1826*6be67779SAndroid Build Coastguard Worker     parser->m_endNamespaceDeclHandler = end;
1827*6be67779SAndroid Build Coastguard Worker }
1828*6be67779SAndroid Build Coastguard Worker 
1829*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetNotStandaloneHandler(XML_Parser parser,XML_NotStandaloneHandler handler)1830*6be67779SAndroid Build Coastguard Worker XML_SetNotStandaloneHandler(XML_Parser parser,
1831*6be67779SAndroid Build Coastguard Worker                             XML_NotStandaloneHandler handler) {
1832*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1833*6be67779SAndroid Build Coastguard Worker     parser->m_notStandaloneHandler = handler;
1834*6be67779SAndroid Build Coastguard Worker }
1835*6be67779SAndroid Build Coastguard Worker 
1836*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetExternalEntityRefHandler(XML_Parser parser,XML_ExternalEntityRefHandler handler)1837*6be67779SAndroid Build Coastguard Worker XML_SetExternalEntityRefHandler(XML_Parser parser,
1838*6be67779SAndroid Build Coastguard Worker                                 XML_ExternalEntityRefHandler handler) {
1839*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1840*6be67779SAndroid Build Coastguard Worker     parser->m_externalEntityRefHandler = handler;
1841*6be67779SAndroid Build Coastguard Worker }
1842*6be67779SAndroid Build Coastguard Worker 
1843*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetExternalEntityRefHandlerArg(XML_Parser parser,void * arg)1844*6be67779SAndroid Build Coastguard Worker XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) {
1845*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1846*6be67779SAndroid Build Coastguard Worker     return;
1847*6be67779SAndroid Build Coastguard Worker   if (arg)
1848*6be67779SAndroid Build Coastguard Worker     parser->m_externalEntityRefHandlerArg = (XML_Parser)arg;
1849*6be67779SAndroid Build Coastguard Worker   else
1850*6be67779SAndroid Build Coastguard Worker     parser->m_externalEntityRefHandlerArg = parser;
1851*6be67779SAndroid Build Coastguard Worker }
1852*6be67779SAndroid Build Coastguard Worker 
1853*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetSkippedEntityHandler(XML_Parser parser,XML_SkippedEntityHandler handler)1854*6be67779SAndroid Build Coastguard Worker XML_SetSkippedEntityHandler(XML_Parser parser,
1855*6be67779SAndroid Build Coastguard Worker                             XML_SkippedEntityHandler handler) {
1856*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1857*6be67779SAndroid Build Coastguard Worker     parser->m_skippedEntityHandler = handler;
1858*6be67779SAndroid Build Coastguard Worker }
1859*6be67779SAndroid Build Coastguard Worker 
1860*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetUnknownEncodingHandler(XML_Parser parser,XML_UnknownEncodingHandler handler,void * data)1861*6be67779SAndroid Build Coastguard Worker XML_SetUnknownEncodingHandler(XML_Parser parser,
1862*6be67779SAndroid Build Coastguard Worker                               XML_UnknownEncodingHandler handler, void *data) {
1863*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1864*6be67779SAndroid Build Coastguard Worker     return;
1865*6be67779SAndroid Build Coastguard Worker   parser->m_unknownEncodingHandler = handler;
1866*6be67779SAndroid Build Coastguard Worker   parser->m_unknownEncodingHandlerData = data;
1867*6be67779SAndroid Build Coastguard Worker }
1868*6be67779SAndroid Build Coastguard Worker 
1869*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetElementDeclHandler(XML_Parser parser,XML_ElementDeclHandler eldecl)1870*6be67779SAndroid Build Coastguard Worker XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) {
1871*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1872*6be67779SAndroid Build Coastguard Worker     parser->m_elementDeclHandler = eldecl;
1873*6be67779SAndroid Build Coastguard Worker }
1874*6be67779SAndroid Build Coastguard Worker 
1875*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetAttlistDeclHandler(XML_Parser parser,XML_AttlistDeclHandler attdecl)1876*6be67779SAndroid Build Coastguard Worker XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) {
1877*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1878*6be67779SAndroid Build Coastguard Worker     parser->m_attlistDeclHandler = attdecl;
1879*6be67779SAndroid Build Coastguard Worker }
1880*6be67779SAndroid Build Coastguard Worker 
1881*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetEntityDeclHandler(XML_Parser parser,XML_EntityDeclHandler handler)1882*6be67779SAndroid Build Coastguard Worker XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) {
1883*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1884*6be67779SAndroid Build Coastguard Worker     parser->m_entityDeclHandler = handler;
1885*6be67779SAndroid Build Coastguard Worker }
1886*6be67779SAndroid Build Coastguard Worker 
1887*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_SetXmlDeclHandler(XML_Parser parser,XML_XmlDeclHandler handler)1888*6be67779SAndroid Build Coastguard Worker XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) {
1889*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
1890*6be67779SAndroid Build Coastguard Worker     parser->m_xmlDeclHandler = handler;
1891*6be67779SAndroid Build Coastguard Worker }
1892*6be67779SAndroid Build Coastguard Worker 
1893*6be67779SAndroid Build Coastguard Worker int XMLCALL
XML_SetParamEntityParsing(XML_Parser parser,enum XML_ParamEntityParsing peParsing)1894*6be67779SAndroid Build Coastguard Worker XML_SetParamEntityParsing(XML_Parser parser,
1895*6be67779SAndroid Build Coastguard Worker                           enum XML_ParamEntityParsing peParsing) {
1896*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1897*6be67779SAndroid Build Coastguard Worker     return 0;
1898*6be67779SAndroid Build Coastguard Worker   /* block after XML_Parse()/XML_ParseBuffer() has been called */
1899*6be67779SAndroid Build Coastguard Worker   if (parser->m_parsingStatus.parsing == XML_PARSING
1900*6be67779SAndroid Build Coastguard Worker       || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1901*6be67779SAndroid Build Coastguard Worker     return 0;
1902*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
1903*6be67779SAndroid Build Coastguard Worker   parser->m_paramEntityParsing = peParsing;
1904*6be67779SAndroid Build Coastguard Worker   return 1;
1905*6be67779SAndroid Build Coastguard Worker #else
1906*6be67779SAndroid Build Coastguard Worker   return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1907*6be67779SAndroid Build Coastguard Worker #endif
1908*6be67779SAndroid Build Coastguard Worker }
1909*6be67779SAndroid Build Coastguard Worker 
1910*6be67779SAndroid Build Coastguard Worker int XMLCALL
XML_SetHashSalt(XML_Parser parser,unsigned long hash_salt)1911*6be67779SAndroid Build Coastguard Worker XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
1912*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
1913*6be67779SAndroid Build Coastguard Worker     return 0;
1914*6be67779SAndroid Build Coastguard Worker   if (parser->m_parentParser)
1915*6be67779SAndroid Build Coastguard Worker     return XML_SetHashSalt(parser->m_parentParser, hash_salt);
1916*6be67779SAndroid Build Coastguard Worker   /* block after XML_Parse()/XML_ParseBuffer() has been called */
1917*6be67779SAndroid Build Coastguard Worker   if (parser->m_parsingStatus.parsing == XML_PARSING
1918*6be67779SAndroid Build Coastguard Worker       || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1919*6be67779SAndroid Build Coastguard Worker     return 0;
1920*6be67779SAndroid Build Coastguard Worker   parser->m_hash_secret_salt = hash_salt;
1921*6be67779SAndroid Build Coastguard Worker   return 1;
1922*6be67779SAndroid Build Coastguard Worker }
1923*6be67779SAndroid Build Coastguard Worker 
1924*6be67779SAndroid Build Coastguard Worker enum XML_Status XMLCALL
XML_Parse(XML_Parser parser,const char * s,int len,int isFinal)1925*6be67779SAndroid Build Coastguard Worker XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
1926*6be67779SAndroid Build Coastguard Worker   if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
1927*6be67779SAndroid Build Coastguard Worker     if (parser != NULL)
1928*6be67779SAndroid Build Coastguard Worker       parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
1929*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
1930*6be67779SAndroid Build Coastguard Worker   }
1931*6be67779SAndroid Build Coastguard Worker   switch (parser->m_parsingStatus.parsing) {
1932*6be67779SAndroid Build Coastguard Worker   case XML_SUSPENDED:
1933*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_SUSPENDED;
1934*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
1935*6be67779SAndroid Build Coastguard Worker   case XML_FINISHED:
1936*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_FINISHED;
1937*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
1938*6be67779SAndroid Build Coastguard Worker   case XML_INITIALIZED:
1939*6be67779SAndroid Build Coastguard Worker     if (parser->m_parentParser == NULL && ! startParsing(parser)) {
1940*6be67779SAndroid Build Coastguard Worker       parser->m_errorCode = XML_ERROR_NO_MEMORY;
1941*6be67779SAndroid Build Coastguard Worker       return XML_STATUS_ERROR;
1942*6be67779SAndroid Build Coastguard Worker     }
1943*6be67779SAndroid Build Coastguard Worker     /* fall through */
1944*6be67779SAndroid Build Coastguard Worker   default:
1945*6be67779SAndroid Build Coastguard Worker     parser->m_parsingStatus.parsing = XML_PARSING;
1946*6be67779SAndroid Build Coastguard Worker   }
1947*6be67779SAndroid Build Coastguard Worker 
1948*6be67779SAndroid Build Coastguard Worker #if XML_CONTEXT_BYTES == 0
1949*6be67779SAndroid Build Coastguard Worker   if (parser->m_bufferPtr == parser->m_bufferEnd) {
1950*6be67779SAndroid Build Coastguard Worker     const char *end;
1951*6be67779SAndroid Build Coastguard Worker     int nLeftOver;
1952*6be67779SAndroid Build Coastguard Worker     enum XML_Status result;
1953*6be67779SAndroid Build Coastguard Worker     /* Detect overflow (a+b > MAX <==> b > MAX-a) */
1954*6be67779SAndroid Build Coastguard Worker     if ((XML_Size)len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) {
1955*6be67779SAndroid Build Coastguard Worker       parser->m_errorCode = XML_ERROR_NO_MEMORY;
1956*6be67779SAndroid Build Coastguard Worker       parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1957*6be67779SAndroid Build Coastguard Worker       parser->m_processor = errorProcessor;
1958*6be67779SAndroid Build Coastguard Worker       return XML_STATUS_ERROR;
1959*6be67779SAndroid Build Coastguard Worker     }
1960*6be67779SAndroid Build Coastguard Worker     // though this isn't a buffer request, we assume that `len` is the app's
1961*6be67779SAndroid Build Coastguard Worker     // preferred buffer fill size, and therefore save it here.
1962*6be67779SAndroid Build Coastguard Worker     parser->m_lastBufferRequestSize = len;
1963*6be67779SAndroid Build Coastguard Worker     parser->m_parseEndByteIndex += len;
1964*6be67779SAndroid Build Coastguard Worker     parser->m_positionPtr = s;
1965*6be67779SAndroid Build Coastguard Worker     parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
1966*6be67779SAndroid Build Coastguard Worker 
1967*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode
1968*6be67779SAndroid Build Coastguard Worker         = callProcessor(parser, s, parser->m_parseEndPtr = s + len, &end);
1969*6be67779SAndroid Build Coastguard Worker 
1970*6be67779SAndroid Build Coastguard Worker     if (parser->m_errorCode != XML_ERROR_NONE) {
1971*6be67779SAndroid Build Coastguard Worker       parser->m_eventEndPtr = parser->m_eventPtr;
1972*6be67779SAndroid Build Coastguard Worker       parser->m_processor = errorProcessor;
1973*6be67779SAndroid Build Coastguard Worker       return XML_STATUS_ERROR;
1974*6be67779SAndroid Build Coastguard Worker     } else {
1975*6be67779SAndroid Build Coastguard Worker       switch (parser->m_parsingStatus.parsing) {
1976*6be67779SAndroid Build Coastguard Worker       case XML_SUSPENDED:
1977*6be67779SAndroid Build Coastguard Worker         result = XML_STATUS_SUSPENDED;
1978*6be67779SAndroid Build Coastguard Worker         break;
1979*6be67779SAndroid Build Coastguard Worker       case XML_INITIALIZED:
1980*6be67779SAndroid Build Coastguard Worker       case XML_PARSING:
1981*6be67779SAndroid Build Coastguard Worker         if (isFinal) {
1982*6be67779SAndroid Build Coastguard Worker           parser->m_parsingStatus.parsing = XML_FINISHED;
1983*6be67779SAndroid Build Coastguard Worker           return XML_STATUS_OK;
1984*6be67779SAndroid Build Coastguard Worker         }
1985*6be67779SAndroid Build Coastguard Worker       /* fall through */
1986*6be67779SAndroid Build Coastguard Worker       default:
1987*6be67779SAndroid Build Coastguard Worker         result = XML_STATUS_OK;
1988*6be67779SAndroid Build Coastguard Worker       }
1989*6be67779SAndroid Build Coastguard Worker     }
1990*6be67779SAndroid Build Coastguard Worker 
1991*6be67779SAndroid Build Coastguard Worker     XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end,
1992*6be67779SAndroid Build Coastguard Worker                       &parser->m_position);
1993*6be67779SAndroid Build Coastguard Worker     nLeftOver = s + len - end;
1994*6be67779SAndroid Build Coastguard Worker     if (nLeftOver) {
1995*6be67779SAndroid Build Coastguard Worker       // Back up and restore the parsing status to avoid XML_ERROR_SUSPENDED
1996*6be67779SAndroid Build Coastguard Worker       // (and XML_ERROR_FINISHED) from XML_GetBuffer.
1997*6be67779SAndroid Build Coastguard Worker       const enum XML_Parsing originalStatus = parser->m_parsingStatus.parsing;
1998*6be67779SAndroid Build Coastguard Worker       parser->m_parsingStatus.parsing = XML_PARSING;
1999*6be67779SAndroid Build Coastguard Worker       void *const temp = XML_GetBuffer(parser, nLeftOver);
2000*6be67779SAndroid Build Coastguard Worker       parser->m_parsingStatus.parsing = originalStatus;
2001*6be67779SAndroid Build Coastguard Worker       // GetBuffer may have overwritten this, but we want to remember what the
2002*6be67779SAndroid Build Coastguard Worker       // app requested, not how many bytes were left over after parsing.
2003*6be67779SAndroid Build Coastguard Worker       parser->m_lastBufferRequestSize = len;
2004*6be67779SAndroid Build Coastguard Worker       if (temp == NULL) {
2005*6be67779SAndroid Build Coastguard Worker         // NOTE: parser->m_errorCode has already been set by XML_GetBuffer().
2006*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = parser->m_eventEndPtr = NULL;
2007*6be67779SAndroid Build Coastguard Worker         parser->m_processor = errorProcessor;
2008*6be67779SAndroid Build Coastguard Worker         return XML_STATUS_ERROR;
2009*6be67779SAndroid Build Coastguard Worker       }
2010*6be67779SAndroid Build Coastguard Worker       // Since we know that the buffer was empty and XML_CONTEXT_BYTES is 0, we
2011*6be67779SAndroid Build Coastguard Worker       // don't have any data to preserve, and can copy straight into the start
2012*6be67779SAndroid Build Coastguard Worker       // of the buffer rather than the GetBuffer return pointer (which may be
2013*6be67779SAndroid Build Coastguard Worker       // pointing further into the allocated buffer).
2014*6be67779SAndroid Build Coastguard Worker       memcpy(parser->m_buffer, end, nLeftOver);
2015*6be67779SAndroid Build Coastguard Worker     }
2016*6be67779SAndroid Build Coastguard Worker     parser->m_bufferPtr = parser->m_buffer;
2017*6be67779SAndroid Build Coastguard Worker     parser->m_bufferEnd = parser->m_buffer + nLeftOver;
2018*6be67779SAndroid Build Coastguard Worker     parser->m_positionPtr = parser->m_bufferPtr;
2019*6be67779SAndroid Build Coastguard Worker     parser->m_parseEndPtr = parser->m_bufferEnd;
2020*6be67779SAndroid Build Coastguard Worker     parser->m_eventPtr = parser->m_bufferPtr;
2021*6be67779SAndroid Build Coastguard Worker     parser->m_eventEndPtr = parser->m_bufferPtr;
2022*6be67779SAndroid Build Coastguard Worker     return result;
2023*6be67779SAndroid Build Coastguard Worker   }
2024*6be67779SAndroid Build Coastguard Worker #endif /* XML_CONTEXT_BYTES == 0 */
2025*6be67779SAndroid Build Coastguard Worker   void *buff = XML_GetBuffer(parser, len);
2026*6be67779SAndroid Build Coastguard Worker   if (buff == NULL)
2027*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2028*6be67779SAndroid Build Coastguard Worker   if (len > 0) {
2029*6be67779SAndroid Build Coastguard Worker     assert(s != NULL); // make sure s==NULL && len!=0 was rejected above
2030*6be67779SAndroid Build Coastguard Worker     memcpy(buff, s, len);
2031*6be67779SAndroid Build Coastguard Worker   }
2032*6be67779SAndroid Build Coastguard Worker   return XML_ParseBuffer(parser, len, isFinal);
2033*6be67779SAndroid Build Coastguard Worker }
2034*6be67779SAndroid Build Coastguard Worker 
2035*6be67779SAndroid Build Coastguard Worker enum XML_Status XMLCALL
XML_ParseBuffer(XML_Parser parser,int len,int isFinal)2036*6be67779SAndroid Build Coastguard Worker XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
2037*6be67779SAndroid Build Coastguard Worker   const char *start;
2038*6be67779SAndroid Build Coastguard Worker   enum XML_Status result = XML_STATUS_OK;
2039*6be67779SAndroid Build Coastguard Worker 
2040*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2041*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2042*6be67779SAndroid Build Coastguard Worker 
2043*6be67779SAndroid Build Coastguard Worker   if (len < 0) {
2044*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
2045*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2046*6be67779SAndroid Build Coastguard Worker   }
2047*6be67779SAndroid Build Coastguard Worker 
2048*6be67779SAndroid Build Coastguard Worker   switch (parser->m_parsingStatus.parsing) {
2049*6be67779SAndroid Build Coastguard Worker   case XML_SUSPENDED:
2050*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_SUSPENDED;
2051*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2052*6be67779SAndroid Build Coastguard Worker   case XML_FINISHED:
2053*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_FINISHED;
2054*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2055*6be67779SAndroid Build Coastguard Worker   case XML_INITIALIZED:
2056*6be67779SAndroid Build Coastguard Worker     /* Has someone called XML_GetBuffer successfully before? */
2057*6be67779SAndroid Build Coastguard Worker     if (! parser->m_bufferPtr) {
2058*6be67779SAndroid Build Coastguard Worker       parser->m_errorCode = XML_ERROR_NO_BUFFER;
2059*6be67779SAndroid Build Coastguard Worker       return XML_STATUS_ERROR;
2060*6be67779SAndroid Build Coastguard Worker     }
2061*6be67779SAndroid Build Coastguard Worker 
2062*6be67779SAndroid Build Coastguard Worker     if (parser->m_parentParser == NULL && ! startParsing(parser)) {
2063*6be67779SAndroid Build Coastguard Worker       parser->m_errorCode = XML_ERROR_NO_MEMORY;
2064*6be67779SAndroid Build Coastguard Worker       return XML_STATUS_ERROR;
2065*6be67779SAndroid Build Coastguard Worker     }
2066*6be67779SAndroid Build Coastguard Worker     /* fall through */
2067*6be67779SAndroid Build Coastguard Worker   default:
2068*6be67779SAndroid Build Coastguard Worker     parser->m_parsingStatus.parsing = XML_PARSING;
2069*6be67779SAndroid Build Coastguard Worker   }
2070*6be67779SAndroid Build Coastguard Worker 
2071*6be67779SAndroid Build Coastguard Worker   start = parser->m_bufferPtr;
2072*6be67779SAndroid Build Coastguard Worker   parser->m_positionPtr = start;
2073*6be67779SAndroid Build Coastguard Worker   parser->m_bufferEnd += len;
2074*6be67779SAndroid Build Coastguard Worker   parser->m_parseEndPtr = parser->m_bufferEnd;
2075*6be67779SAndroid Build Coastguard Worker   parser->m_parseEndByteIndex += len;
2076*6be67779SAndroid Build Coastguard Worker   parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
2077*6be67779SAndroid Build Coastguard Worker 
2078*6be67779SAndroid Build Coastguard Worker   parser->m_errorCode = callProcessor(parser, start, parser->m_parseEndPtr,
2079*6be67779SAndroid Build Coastguard Worker                                       &parser->m_bufferPtr);
2080*6be67779SAndroid Build Coastguard Worker 
2081*6be67779SAndroid Build Coastguard Worker   if (parser->m_errorCode != XML_ERROR_NONE) {
2082*6be67779SAndroid Build Coastguard Worker     parser->m_eventEndPtr = parser->m_eventPtr;
2083*6be67779SAndroid Build Coastguard Worker     parser->m_processor = errorProcessor;
2084*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2085*6be67779SAndroid Build Coastguard Worker   } else {
2086*6be67779SAndroid Build Coastguard Worker     switch (parser->m_parsingStatus.parsing) {
2087*6be67779SAndroid Build Coastguard Worker     case XML_SUSPENDED:
2088*6be67779SAndroid Build Coastguard Worker       result = XML_STATUS_SUSPENDED;
2089*6be67779SAndroid Build Coastguard Worker       break;
2090*6be67779SAndroid Build Coastguard Worker     case XML_INITIALIZED:
2091*6be67779SAndroid Build Coastguard Worker     case XML_PARSING:
2092*6be67779SAndroid Build Coastguard Worker       if (isFinal) {
2093*6be67779SAndroid Build Coastguard Worker         parser->m_parsingStatus.parsing = XML_FINISHED;
2094*6be67779SAndroid Build Coastguard Worker         return result;
2095*6be67779SAndroid Build Coastguard Worker       }
2096*6be67779SAndroid Build Coastguard Worker     default:; /* should not happen */
2097*6be67779SAndroid Build Coastguard Worker     }
2098*6be67779SAndroid Build Coastguard Worker   }
2099*6be67779SAndroid Build Coastguard Worker 
2100*6be67779SAndroid Build Coastguard Worker   XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2101*6be67779SAndroid Build Coastguard Worker                     parser->m_bufferPtr, &parser->m_position);
2102*6be67779SAndroid Build Coastguard Worker   parser->m_positionPtr = parser->m_bufferPtr;
2103*6be67779SAndroid Build Coastguard Worker   return result;
2104*6be67779SAndroid Build Coastguard Worker }
2105*6be67779SAndroid Build Coastguard Worker 
2106*6be67779SAndroid Build Coastguard Worker void *XMLCALL
XML_GetBuffer(XML_Parser parser,int len)2107*6be67779SAndroid Build Coastguard Worker XML_GetBuffer(XML_Parser parser, int len) {
2108*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2109*6be67779SAndroid Build Coastguard Worker     return NULL;
2110*6be67779SAndroid Build Coastguard Worker   if (len < 0) {
2111*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_NO_MEMORY;
2112*6be67779SAndroid Build Coastguard Worker     return NULL;
2113*6be67779SAndroid Build Coastguard Worker   }
2114*6be67779SAndroid Build Coastguard Worker   switch (parser->m_parsingStatus.parsing) {
2115*6be67779SAndroid Build Coastguard Worker   case XML_SUSPENDED:
2116*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_SUSPENDED;
2117*6be67779SAndroid Build Coastguard Worker     return NULL;
2118*6be67779SAndroid Build Coastguard Worker   case XML_FINISHED:
2119*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_FINISHED;
2120*6be67779SAndroid Build Coastguard Worker     return NULL;
2121*6be67779SAndroid Build Coastguard Worker   default:;
2122*6be67779SAndroid Build Coastguard Worker   }
2123*6be67779SAndroid Build Coastguard Worker 
2124*6be67779SAndroid Build Coastguard Worker   // whether or not the request succeeds, `len` seems to be the app's preferred
2125*6be67779SAndroid Build Coastguard Worker   // buffer fill size; remember it.
2126*6be67779SAndroid Build Coastguard Worker   parser->m_lastBufferRequestSize = len;
2127*6be67779SAndroid Build Coastguard Worker   if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)
2128*6be67779SAndroid Build Coastguard Worker       || parser->m_buffer == NULL) {
2129*6be67779SAndroid Build Coastguard Worker #if XML_CONTEXT_BYTES > 0
2130*6be67779SAndroid Build Coastguard Worker     int keep;
2131*6be67779SAndroid Build Coastguard Worker #endif /* XML_CONTEXT_BYTES > 0 */
2132*6be67779SAndroid Build Coastguard Worker     /* Do not invoke signed arithmetic overflow: */
2133*6be67779SAndroid Build Coastguard Worker     int neededSize = (int)((unsigned)len
2134*6be67779SAndroid Build Coastguard Worker                            + (unsigned)EXPAT_SAFE_PTR_DIFF(
2135*6be67779SAndroid Build Coastguard Worker                                parser->m_bufferEnd, parser->m_bufferPtr));
2136*6be67779SAndroid Build Coastguard Worker     if (neededSize < 0) {
2137*6be67779SAndroid Build Coastguard Worker       parser->m_errorCode = XML_ERROR_NO_MEMORY;
2138*6be67779SAndroid Build Coastguard Worker       return NULL;
2139*6be67779SAndroid Build Coastguard Worker     }
2140*6be67779SAndroid Build Coastguard Worker #if XML_CONTEXT_BYTES > 0
2141*6be67779SAndroid Build Coastguard Worker     keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
2142*6be67779SAndroid Build Coastguard Worker     if (keep > XML_CONTEXT_BYTES)
2143*6be67779SAndroid Build Coastguard Worker       keep = XML_CONTEXT_BYTES;
2144*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow */
2145*6be67779SAndroid Build Coastguard Worker     if (keep > INT_MAX - neededSize) {
2146*6be67779SAndroid Build Coastguard Worker       parser->m_errorCode = XML_ERROR_NO_MEMORY;
2147*6be67779SAndroid Build Coastguard Worker       return NULL;
2148*6be67779SAndroid Build Coastguard Worker     }
2149*6be67779SAndroid Build Coastguard Worker     neededSize += keep;
2150*6be67779SAndroid Build Coastguard Worker #endif /* XML_CONTEXT_BYTES > 0 */
2151*6be67779SAndroid Build Coastguard Worker     if (parser->m_buffer && parser->m_bufferPtr
2152*6be67779SAndroid Build Coastguard Worker         && neededSize
2153*6be67779SAndroid Build Coastguard Worker                <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) {
2154*6be67779SAndroid Build Coastguard Worker #if XML_CONTEXT_BYTES > 0
2155*6be67779SAndroid Build Coastguard Worker       if (keep < EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)) {
2156*6be67779SAndroid Build Coastguard Worker         int offset
2157*6be67779SAndroid Build Coastguard Worker             = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)
2158*6be67779SAndroid Build Coastguard Worker               - keep;
2159*6be67779SAndroid Build Coastguard Worker         /* The buffer pointers cannot be NULL here; we have at least some bytes
2160*6be67779SAndroid Build Coastguard Worker          * in the buffer */
2161*6be67779SAndroid Build Coastguard Worker         memmove(parser->m_buffer, &parser->m_buffer[offset],
2162*6be67779SAndroid Build Coastguard Worker                 parser->m_bufferEnd - parser->m_bufferPtr + keep);
2163*6be67779SAndroid Build Coastguard Worker         parser->m_bufferEnd -= offset;
2164*6be67779SAndroid Build Coastguard Worker         parser->m_bufferPtr -= offset;
2165*6be67779SAndroid Build Coastguard Worker       }
2166*6be67779SAndroid Build Coastguard Worker #else
2167*6be67779SAndroid Build Coastguard Worker       memmove(parser->m_buffer, parser->m_bufferPtr,
2168*6be67779SAndroid Build Coastguard Worker               EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
2169*6be67779SAndroid Build Coastguard Worker       parser->m_bufferEnd
2170*6be67779SAndroid Build Coastguard Worker           = parser->m_buffer
2171*6be67779SAndroid Build Coastguard Worker             + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
2172*6be67779SAndroid Build Coastguard Worker       parser->m_bufferPtr = parser->m_buffer;
2173*6be67779SAndroid Build Coastguard Worker #endif /* XML_CONTEXT_BYTES > 0 */
2174*6be67779SAndroid Build Coastguard Worker     } else {
2175*6be67779SAndroid Build Coastguard Worker       char *newBuf;
2176*6be67779SAndroid Build Coastguard Worker       int bufferSize
2177*6be67779SAndroid Build Coastguard Worker           = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer);
2178*6be67779SAndroid Build Coastguard Worker       if (bufferSize == 0)
2179*6be67779SAndroid Build Coastguard Worker         bufferSize = INIT_BUFFER_SIZE;
2180*6be67779SAndroid Build Coastguard Worker       do {
2181*6be67779SAndroid Build Coastguard Worker         /* Do not invoke signed arithmetic overflow: */
2182*6be67779SAndroid Build Coastguard Worker         bufferSize = (int)(2U * (unsigned)bufferSize);
2183*6be67779SAndroid Build Coastguard Worker       } while (bufferSize < neededSize && bufferSize > 0);
2184*6be67779SAndroid Build Coastguard Worker       if (bufferSize <= 0) {
2185*6be67779SAndroid Build Coastguard Worker         parser->m_errorCode = XML_ERROR_NO_MEMORY;
2186*6be67779SAndroid Build Coastguard Worker         return NULL;
2187*6be67779SAndroid Build Coastguard Worker       }
2188*6be67779SAndroid Build Coastguard Worker       newBuf = (char *)MALLOC(parser, bufferSize);
2189*6be67779SAndroid Build Coastguard Worker       if (newBuf == 0) {
2190*6be67779SAndroid Build Coastguard Worker         parser->m_errorCode = XML_ERROR_NO_MEMORY;
2191*6be67779SAndroid Build Coastguard Worker         return NULL;
2192*6be67779SAndroid Build Coastguard Worker       }
2193*6be67779SAndroid Build Coastguard Worker       parser->m_bufferLim = newBuf + bufferSize;
2194*6be67779SAndroid Build Coastguard Worker #if XML_CONTEXT_BYTES > 0
2195*6be67779SAndroid Build Coastguard Worker       if (parser->m_bufferPtr) {
2196*6be67779SAndroid Build Coastguard Worker         memcpy(newBuf, &parser->m_bufferPtr[-keep],
2197*6be67779SAndroid Build Coastguard Worker                EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
2198*6be67779SAndroid Build Coastguard Worker                    + keep);
2199*6be67779SAndroid Build Coastguard Worker         FREE(parser, parser->m_buffer);
2200*6be67779SAndroid Build Coastguard Worker         parser->m_buffer = newBuf;
2201*6be67779SAndroid Build Coastguard Worker         parser->m_bufferEnd
2202*6be67779SAndroid Build Coastguard Worker             = parser->m_buffer
2203*6be67779SAndroid Build Coastguard Worker               + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
2204*6be67779SAndroid Build Coastguard Worker               + keep;
2205*6be67779SAndroid Build Coastguard Worker         parser->m_bufferPtr = parser->m_buffer + keep;
2206*6be67779SAndroid Build Coastguard Worker       } else {
2207*6be67779SAndroid Build Coastguard Worker         /* This must be a brand new buffer with no data in it yet */
2208*6be67779SAndroid Build Coastguard Worker         parser->m_bufferEnd = newBuf;
2209*6be67779SAndroid Build Coastguard Worker         parser->m_bufferPtr = parser->m_buffer = newBuf;
2210*6be67779SAndroid Build Coastguard Worker       }
2211*6be67779SAndroid Build Coastguard Worker #else
2212*6be67779SAndroid Build Coastguard Worker       if (parser->m_bufferPtr) {
2213*6be67779SAndroid Build Coastguard Worker         memcpy(newBuf, parser->m_bufferPtr,
2214*6be67779SAndroid Build Coastguard Worker                EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
2215*6be67779SAndroid Build Coastguard Worker         FREE(parser, parser->m_buffer);
2216*6be67779SAndroid Build Coastguard Worker         parser->m_bufferEnd
2217*6be67779SAndroid Build Coastguard Worker             = newBuf
2218*6be67779SAndroid Build Coastguard Worker               + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
2219*6be67779SAndroid Build Coastguard Worker       } else {
2220*6be67779SAndroid Build Coastguard Worker         /* This must be a brand new buffer with no data in it yet */
2221*6be67779SAndroid Build Coastguard Worker         parser->m_bufferEnd = newBuf;
2222*6be67779SAndroid Build Coastguard Worker       }
2223*6be67779SAndroid Build Coastguard Worker       parser->m_bufferPtr = parser->m_buffer = newBuf;
2224*6be67779SAndroid Build Coastguard Worker #endif /* XML_CONTEXT_BYTES > 0 */
2225*6be67779SAndroid Build Coastguard Worker     }
2226*6be67779SAndroid Build Coastguard Worker     parser->m_eventPtr = parser->m_eventEndPtr = NULL;
2227*6be67779SAndroid Build Coastguard Worker     parser->m_positionPtr = NULL;
2228*6be67779SAndroid Build Coastguard Worker   }
2229*6be67779SAndroid Build Coastguard Worker   return parser->m_bufferEnd;
2230*6be67779SAndroid Build Coastguard Worker }
2231*6be67779SAndroid Build Coastguard Worker 
2232*6be67779SAndroid Build Coastguard Worker enum XML_Status XMLCALL
XML_StopParser(XML_Parser parser,XML_Bool resumable)2233*6be67779SAndroid Build Coastguard Worker XML_StopParser(XML_Parser parser, XML_Bool resumable) {
2234*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2235*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2236*6be67779SAndroid Build Coastguard Worker   switch (parser->m_parsingStatus.parsing) {
2237*6be67779SAndroid Build Coastguard Worker   case XML_SUSPENDED:
2238*6be67779SAndroid Build Coastguard Worker     if (resumable) {
2239*6be67779SAndroid Build Coastguard Worker       parser->m_errorCode = XML_ERROR_SUSPENDED;
2240*6be67779SAndroid Build Coastguard Worker       return XML_STATUS_ERROR;
2241*6be67779SAndroid Build Coastguard Worker     }
2242*6be67779SAndroid Build Coastguard Worker     parser->m_parsingStatus.parsing = XML_FINISHED;
2243*6be67779SAndroid Build Coastguard Worker     break;
2244*6be67779SAndroid Build Coastguard Worker   case XML_FINISHED:
2245*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_FINISHED;
2246*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2247*6be67779SAndroid Build Coastguard Worker   default:
2248*6be67779SAndroid Build Coastguard Worker     if (resumable) {
2249*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
2250*6be67779SAndroid Build Coastguard Worker       if (parser->m_isParamEntity) {
2251*6be67779SAndroid Build Coastguard Worker         parser->m_errorCode = XML_ERROR_SUSPEND_PE;
2252*6be67779SAndroid Build Coastguard Worker         return XML_STATUS_ERROR;
2253*6be67779SAndroid Build Coastguard Worker       }
2254*6be67779SAndroid Build Coastguard Worker #endif
2255*6be67779SAndroid Build Coastguard Worker       parser->m_parsingStatus.parsing = XML_SUSPENDED;
2256*6be67779SAndroid Build Coastguard Worker     } else
2257*6be67779SAndroid Build Coastguard Worker       parser->m_parsingStatus.parsing = XML_FINISHED;
2258*6be67779SAndroid Build Coastguard Worker   }
2259*6be67779SAndroid Build Coastguard Worker   return XML_STATUS_OK;
2260*6be67779SAndroid Build Coastguard Worker }
2261*6be67779SAndroid Build Coastguard Worker 
2262*6be67779SAndroid Build Coastguard Worker enum XML_Status XMLCALL
XML_ResumeParser(XML_Parser parser)2263*6be67779SAndroid Build Coastguard Worker XML_ResumeParser(XML_Parser parser) {
2264*6be67779SAndroid Build Coastguard Worker   enum XML_Status result = XML_STATUS_OK;
2265*6be67779SAndroid Build Coastguard Worker 
2266*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2267*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2268*6be67779SAndroid Build Coastguard Worker   if (parser->m_parsingStatus.parsing != XML_SUSPENDED) {
2269*6be67779SAndroid Build Coastguard Worker     parser->m_errorCode = XML_ERROR_NOT_SUSPENDED;
2270*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2271*6be67779SAndroid Build Coastguard Worker   }
2272*6be67779SAndroid Build Coastguard Worker   parser->m_parsingStatus.parsing = XML_PARSING;
2273*6be67779SAndroid Build Coastguard Worker 
2274*6be67779SAndroid Build Coastguard Worker   parser->m_errorCode = callProcessor(
2275*6be67779SAndroid Build Coastguard Worker       parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr);
2276*6be67779SAndroid Build Coastguard Worker 
2277*6be67779SAndroid Build Coastguard Worker   if (parser->m_errorCode != XML_ERROR_NONE) {
2278*6be67779SAndroid Build Coastguard Worker     parser->m_eventEndPtr = parser->m_eventPtr;
2279*6be67779SAndroid Build Coastguard Worker     parser->m_processor = errorProcessor;
2280*6be67779SAndroid Build Coastguard Worker     return XML_STATUS_ERROR;
2281*6be67779SAndroid Build Coastguard Worker   } else {
2282*6be67779SAndroid Build Coastguard Worker     switch (parser->m_parsingStatus.parsing) {
2283*6be67779SAndroid Build Coastguard Worker     case XML_SUSPENDED:
2284*6be67779SAndroid Build Coastguard Worker       result = XML_STATUS_SUSPENDED;
2285*6be67779SAndroid Build Coastguard Worker       break;
2286*6be67779SAndroid Build Coastguard Worker     case XML_INITIALIZED:
2287*6be67779SAndroid Build Coastguard Worker     case XML_PARSING:
2288*6be67779SAndroid Build Coastguard Worker       if (parser->m_parsingStatus.finalBuffer) {
2289*6be67779SAndroid Build Coastguard Worker         parser->m_parsingStatus.parsing = XML_FINISHED;
2290*6be67779SAndroid Build Coastguard Worker         return result;
2291*6be67779SAndroid Build Coastguard Worker       }
2292*6be67779SAndroid Build Coastguard Worker     default:;
2293*6be67779SAndroid Build Coastguard Worker     }
2294*6be67779SAndroid Build Coastguard Worker   }
2295*6be67779SAndroid Build Coastguard Worker 
2296*6be67779SAndroid Build Coastguard Worker   XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2297*6be67779SAndroid Build Coastguard Worker                     parser->m_bufferPtr, &parser->m_position);
2298*6be67779SAndroid Build Coastguard Worker   parser->m_positionPtr = parser->m_bufferPtr;
2299*6be67779SAndroid Build Coastguard Worker   return result;
2300*6be67779SAndroid Build Coastguard Worker }
2301*6be67779SAndroid Build Coastguard Worker 
2302*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_GetParsingStatus(XML_Parser parser,XML_ParsingStatus * status)2303*6be67779SAndroid Build Coastguard Worker XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) {
2304*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2305*6be67779SAndroid Build Coastguard Worker     return;
2306*6be67779SAndroid Build Coastguard Worker   assert(status != NULL);
2307*6be67779SAndroid Build Coastguard Worker   *status = parser->m_parsingStatus;
2308*6be67779SAndroid Build Coastguard Worker }
2309*6be67779SAndroid Build Coastguard Worker 
2310*6be67779SAndroid Build Coastguard Worker enum XML_Error XMLCALL
XML_GetErrorCode(XML_Parser parser)2311*6be67779SAndroid Build Coastguard Worker XML_GetErrorCode(XML_Parser parser) {
2312*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2313*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_INVALID_ARGUMENT;
2314*6be67779SAndroid Build Coastguard Worker   return parser->m_errorCode;
2315*6be67779SAndroid Build Coastguard Worker }
2316*6be67779SAndroid Build Coastguard Worker 
2317*6be67779SAndroid Build Coastguard Worker XML_Index XMLCALL
XML_GetCurrentByteIndex(XML_Parser parser)2318*6be67779SAndroid Build Coastguard Worker XML_GetCurrentByteIndex(XML_Parser parser) {
2319*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2320*6be67779SAndroid Build Coastguard Worker     return -1;
2321*6be67779SAndroid Build Coastguard Worker   if (parser->m_eventPtr)
2322*6be67779SAndroid Build Coastguard Worker     return (XML_Index)(parser->m_parseEndByteIndex
2323*6be67779SAndroid Build Coastguard Worker                        - (parser->m_parseEndPtr - parser->m_eventPtr));
2324*6be67779SAndroid Build Coastguard Worker   return -1;
2325*6be67779SAndroid Build Coastguard Worker }
2326*6be67779SAndroid Build Coastguard Worker 
2327*6be67779SAndroid Build Coastguard Worker int XMLCALL
XML_GetCurrentByteCount(XML_Parser parser)2328*6be67779SAndroid Build Coastguard Worker XML_GetCurrentByteCount(XML_Parser parser) {
2329*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2330*6be67779SAndroid Build Coastguard Worker     return 0;
2331*6be67779SAndroid Build Coastguard Worker   if (parser->m_eventEndPtr && parser->m_eventPtr)
2332*6be67779SAndroid Build Coastguard Worker     return (int)(parser->m_eventEndPtr - parser->m_eventPtr);
2333*6be67779SAndroid Build Coastguard Worker   return 0;
2334*6be67779SAndroid Build Coastguard Worker }
2335*6be67779SAndroid Build Coastguard Worker 
2336*6be67779SAndroid Build Coastguard Worker const char *XMLCALL
XML_GetInputContext(XML_Parser parser,int * offset,int * size)2337*6be67779SAndroid Build Coastguard Worker XML_GetInputContext(XML_Parser parser, int *offset, int *size) {
2338*6be67779SAndroid Build Coastguard Worker #if XML_CONTEXT_BYTES > 0
2339*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2340*6be67779SAndroid Build Coastguard Worker     return NULL;
2341*6be67779SAndroid Build Coastguard Worker   if (parser->m_eventPtr && parser->m_buffer) {
2342*6be67779SAndroid Build Coastguard Worker     if (offset != NULL)
2343*6be67779SAndroid Build Coastguard Worker       *offset = (int)(parser->m_eventPtr - parser->m_buffer);
2344*6be67779SAndroid Build Coastguard Worker     if (size != NULL)
2345*6be67779SAndroid Build Coastguard Worker       *size = (int)(parser->m_bufferEnd - parser->m_buffer);
2346*6be67779SAndroid Build Coastguard Worker     return parser->m_buffer;
2347*6be67779SAndroid Build Coastguard Worker   }
2348*6be67779SAndroid Build Coastguard Worker #else
2349*6be67779SAndroid Build Coastguard Worker   (void)parser;
2350*6be67779SAndroid Build Coastguard Worker   (void)offset;
2351*6be67779SAndroid Build Coastguard Worker   (void)size;
2352*6be67779SAndroid Build Coastguard Worker #endif /* XML_CONTEXT_BYTES > 0 */
2353*6be67779SAndroid Build Coastguard Worker   return (const char *)0;
2354*6be67779SAndroid Build Coastguard Worker }
2355*6be67779SAndroid Build Coastguard Worker 
2356*6be67779SAndroid Build Coastguard Worker XML_Size XMLCALL
XML_GetCurrentLineNumber(XML_Parser parser)2357*6be67779SAndroid Build Coastguard Worker XML_GetCurrentLineNumber(XML_Parser parser) {
2358*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2359*6be67779SAndroid Build Coastguard Worker     return 0;
2360*6be67779SAndroid Build Coastguard Worker   if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2361*6be67779SAndroid Build Coastguard Worker     XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2362*6be67779SAndroid Build Coastguard Worker                       parser->m_eventPtr, &parser->m_position);
2363*6be67779SAndroid Build Coastguard Worker     parser->m_positionPtr = parser->m_eventPtr;
2364*6be67779SAndroid Build Coastguard Worker   }
2365*6be67779SAndroid Build Coastguard Worker   return parser->m_position.lineNumber + 1;
2366*6be67779SAndroid Build Coastguard Worker }
2367*6be67779SAndroid Build Coastguard Worker 
2368*6be67779SAndroid Build Coastguard Worker XML_Size XMLCALL
XML_GetCurrentColumnNumber(XML_Parser parser)2369*6be67779SAndroid Build Coastguard Worker XML_GetCurrentColumnNumber(XML_Parser parser) {
2370*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2371*6be67779SAndroid Build Coastguard Worker     return 0;
2372*6be67779SAndroid Build Coastguard Worker   if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2373*6be67779SAndroid Build Coastguard Worker     XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2374*6be67779SAndroid Build Coastguard Worker                       parser->m_eventPtr, &parser->m_position);
2375*6be67779SAndroid Build Coastguard Worker     parser->m_positionPtr = parser->m_eventPtr;
2376*6be67779SAndroid Build Coastguard Worker   }
2377*6be67779SAndroid Build Coastguard Worker   return parser->m_position.columnNumber;
2378*6be67779SAndroid Build Coastguard Worker }
2379*6be67779SAndroid Build Coastguard Worker 
2380*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_FreeContentModel(XML_Parser parser,XML_Content * model)2381*6be67779SAndroid Build Coastguard Worker XML_FreeContentModel(XML_Parser parser, XML_Content *model) {
2382*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
2383*6be67779SAndroid Build Coastguard Worker     FREE(parser, model);
2384*6be67779SAndroid Build Coastguard Worker }
2385*6be67779SAndroid Build Coastguard Worker 
2386*6be67779SAndroid Build Coastguard Worker void *XMLCALL
XML_MemMalloc(XML_Parser parser,size_t size)2387*6be67779SAndroid Build Coastguard Worker XML_MemMalloc(XML_Parser parser, size_t size) {
2388*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2389*6be67779SAndroid Build Coastguard Worker     return NULL;
2390*6be67779SAndroid Build Coastguard Worker   return MALLOC(parser, size);
2391*6be67779SAndroid Build Coastguard Worker }
2392*6be67779SAndroid Build Coastguard Worker 
2393*6be67779SAndroid Build Coastguard Worker void *XMLCALL
XML_MemRealloc(XML_Parser parser,void * ptr,size_t size)2394*6be67779SAndroid Build Coastguard Worker XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) {
2395*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2396*6be67779SAndroid Build Coastguard Worker     return NULL;
2397*6be67779SAndroid Build Coastguard Worker   return REALLOC(parser, ptr, size);
2398*6be67779SAndroid Build Coastguard Worker }
2399*6be67779SAndroid Build Coastguard Worker 
2400*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_MemFree(XML_Parser parser,void * ptr)2401*6be67779SAndroid Build Coastguard Worker XML_MemFree(XML_Parser parser, void *ptr) {
2402*6be67779SAndroid Build Coastguard Worker   if (parser != NULL)
2403*6be67779SAndroid Build Coastguard Worker     FREE(parser, ptr);
2404*6be67779SAndroid Build Coastguard Worker }
2405*6be67779SAndroid Build Coastguard Worker 
2406*6be67779SAndroid Build Coastguard Worker void XMLCALL
XML_DefaultCurrent(XML_Parser parser)2407*6be67779SAndroid Build Coastguard Worker XML_DefaultCurrent(XML_Parser parser) {
2408*6be67779SAndroid Build Coastguard Worker   if (parser == NULL)
2409*6be67779SAndroid Build Coastguard Worker     return;
2410*6be67779SAndroid Build Coastguard Worker   if (parser->m_defaultHandler) {
2411*6be67779SAndroid Build Coastguard Worker     if (parser->m_openInternalEntities)
2412*6be67779SAndroid Build Coastguard Worker       reportDefault(parser, parser->m_internalEncoding,
2413*6be67779SAndroid Build Coastguard Worker                     parser->m_openInternalEntities->internalEventPtr,
2414*6be67779SAndroid Build Coastguard Worker                     parser->m_openInternalEntities->internalEventEndPtr);
2415*6be67779SAndroid Build Coastguard Worker     else
2416*6be67779SAndroid Build Coastguard Worker       reportDefault(parser, parser->m_encoding, parser->m_eventPtr,
2417*6be67779SAndroid Build Coastguard Worker                     parser->m_eventEndPtr);
2418*6be67779SAndroid Build Coastguard Worker   }
2419*6be67779SAndroid Build Coastguard Worker }
2420*6be67779SAndroid Build Coastguard Worker 
2421*6be67779SAndroid Build Coastguard Worker const XML_LChar *XMLCALL
XML_ErrorString(enum XML_Error code)2422*6be67779SAndroid Build Coastguard Worker XML_ErrorString(enum XML_Error code) {
2423*6be67779SAndroid Build Coastguard Worker   switch (code) {
2424*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_NONE:
2425*6be67779SAndroid Build Coastguard Worker     return NULL;
2426*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_NO_MEMORY:
2427*6be67779SAndroid Build Coastguard Worker     return XML_L("out of memory");
2428*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_SYNTAX:
2429*6be67779SAndroid Build Coastguard Worker     return XML_L("syntax error");
2430*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_NO_ELEMENTS:
2431*6be67779SAndroid Build Coastguard Worker     return XML_L("no element found");
2432*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_INVALID_TOKEN:
2433*6be67779SAndroid Build Coastguard Worker     return XML_L("not well-formed (invalid token)");
2434*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_UNCLOSED_TOKEN:
2435*6be67779SAndroid Build Coastguard Worker     return XML_L("unclosed token");
2436*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_PARTIAL_CHAR:
2437*6be67779SAndroid Build Coastguard Worker     return XML_L("partial character");
2438*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_TAG_MISMATCH:
2439*6be67779SAndroid Build Coastguard Worker     return XML_L("mismatched tag");
2440*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_DUPLICATE_ATTRIBUTE:
2441*6be67779SAndroid Build Coastguard Worker     return XML_L("duplicate attribute");
2442*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
2443*6be67779SAndroid Build Coastguard Worker     return XML_L("junk after document element");
2444*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_PARAM_ENTITY_REF:
2445*6be67779SAndroid Build Coastguard Worker     return XML_L("illegal parameter entity reference");
2446*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_UNDEFINED_ENTITY:
2447*6be67779SAndroid Build Coastguard Worker     return XML_L("undefined entity");
2448*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_RECURSIVE_ENTITY_REF:
2449*6be67779SAndroid Build Coastguard Worker     return XML_L("recursive entity reference");
2450*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_ASYNC_ENTITY:
2451*6be67779SAndroid Build Coastguard Worker     return XML_L("asynchronous entity");
2452*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_BAD_CHAR_REF:
2453*6be67779SAndroid Build Coastguard Worker     return XML_L("reference to invalid character number");
2454*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_BINARY_ENTITY_REF:
2455*6be67779SAndroid Build Coastguard Worker     return XML_L("reference to binary entity");
2456*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
2457*6be67779SAndroid Build Coastguard Worker     return XML_L("reference to external entity in attribute");
2458*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_MISPLACED_XML_PI:
2459*6be67779SAndroid Build Coastguard Worker     return XML_L("XML or text declaration not at start of entity");
2460*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_UNKNOWN_ENCODING:
2461*6be67779SAndroid Build Coastguard Worker     return XML_L("unknown encoding");
2462*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_INCORRECT_ENCODING:
2463*6be67779SAndroid Build Coastguard Worker     return XML_L("encoding specified in XML declaration is incorrect");
2464*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_UNCLOSED_CDATA_SECTION:
2465*6be67779SAndroid Build Coastguard Worker     return XML_L("unclosed CDATA section");
2466*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_EXTERNAL_ENTITY_HANDLING:
2467*6be67779SAndroid Build Coastguard Worker     return XML_L("error in processing external entity reference");
2468*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_NOT_STANDALONE:
2469*6be67779SAndroid Build Coastguard Worker     return XML_L("document is not standalone");
2470*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_UNEXPECTED_STATE:
2471*6be67779SAndroid Build Coastguard Worker     return XML_L("unexpected parser state - please send a bug report");
2472*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_ENTITY_DECLARED_IN_PE:
2473*6be67779SAndroid Build Coastguard Worker     return XML_L("entity declared in parameter entity");
2474*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_FEATURE_REQUIRES_XML_DTD:
2475*6be67779SAndroid Build Coastguard Worker     return XML_L("requested feature requires XML_DTD support in Expat");
2476*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:
2477*6be67779SAndroid Build Coastguard Worker     return XML_L("cannot change setting once parsing has begun");
2478*6be67779SAndroid Build Coastguard Worker   /* Added in 1.95.7. */
2479*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_UNBOUND_PREFIX:
2480*6be67779SAndroid Build Coastguard Worker     return XML_L("unbound prefix");
2481*6be67779SAndroid Build Coastguard Worker   /* Added in 1.95.8. */
2482*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_UNDECLARING_PREFIX:
2483*6be67779SAndroid Build Coastguard Worker     return XML_L("must not undeclare prefix");
2484*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_INCOMPLETE_PE:
2485*6be67779SAndroid Build Coastguard Worker     return XML_L("incomplete markup in parameter entity");
2486*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_XML_DECL:
2487*6be67779SAndroid Build Coastguard Worker     return XML_L("XML declaration not well-formed");
2488*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_TEXT_DECL:
2489*6be67779SAndroid Build Coastguard Worker     return XML_L("text declaration not well-formed");
2490*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_PUBLICID:
2491*6be67779SAndroid Build Coastguard Worker     return XML_L("illegal character(s) in public id");
2492*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_SUSPENDED:
2493*6be67779SAndroid Build Coastguard Worker     return XML_L("parser suspended");
2494*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_NOT_SUSPENDED:
2495*6be67779SAndroid Build Coastguard Worker     return XML_L("parser not suspended");
2496*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_ABORTED:
2497*6be67779SAndroid Build Coastguard Worker     return XML_L("parsing aborted");
2498*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_FINISHED:
2499*6be67779SAndroid Build Coastguard Worker     return XML_L("parsing finished");
2500*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_SUSPEND_PE:
2501*6be67779SAndroid Build Coastguard Worker     return XML_L("cannot suspend in external parameter entity");
2502*6be67779SAndroid Build Coastguard Worker   /* Added in 2.0.0. */
2503*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_RESERVED_PREFIX_XML:
2504*6be67779SAndroid Build Coastguard Worker     return XML_L(
2505*6be67779SAndroid Build Coastguard Worker         "reserved prefix (xml) must not be undeclared or bound to another namespace name");
2506*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_RESERVED_PREFIX_XMLNS:
2507*6be67779SAndroid Build Coastguard Worker     return XML_L("reserved prefix (xmlns) must not be declared or undeclared");
2508*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_RESERVED_NAMESPACE_URI:
2509*6be67779SAndroid Build Coastguard Worker     return XML_L(
2510*6be67779SAndroid Build Coastguard Worker         "prefix must not be bound to one of the reserved namespace names");
2511*6be67779SAndroid Build Coastguard Worker   /* Added in 2.2.5. */
2512*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
2513*6be67779SAndroid Build Coastguard Worker     return XML_L("invalid argument");
2514*6be67779SAndroid Build Coastguard Worker     /* Added in 2.3.0. */
2515*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_NO_BUFFER:
2516*6be67779SAndroid Build Coastguard Worker     return XML_L(
2517*6be67779SAndroid Build Coastguard Worker         "a successful prior call to function XML_GetBuffer is required");
2518*6be67779SAndroid Build Coastguard Worker   /* Added in 2.4.0. */
2519*6be67779SAndroid Build Coastguard Worker   case XML_ERROR_AMPLIFICATION_LIMIT_BREACH:
2520*6be67779SAndroid Build Coastguard Worker     return XML_L(
2521*6be67779SAndroid Build Coastguard Worker         "limit on input amplification factor (from DTD and entities) breached");
2522*6be67779SAndroid Build Coastguard Worker   }
2523*6be67779SAndroid Build Coastguard Worker   return NULL;
2524*6be67779SAndroid Build Coastguard Worker }
2525*6be67779SAndroid Build Coastguard Worker 
2526*6be67779SAndroid Build Coastguard Worker const XML_LChar *XMLCALL
XML_ExpatVersion(void)2527*6be67779SAndroid Build Coastguard Worker XML_ExpatVersion(void) {
2528*6be67779SAndroid Build Coastguard Worker   /* V1 is used to string-ize the version number. However, it would
2529*6be67779SAndroid Build Coastguard Worker      string-ize the actual version macro *names* unless we get them
2530*6be67779SAndroid Build Coastguard Worker      substituted before being passed to V1. CPP is defined to expand
2531*6be67779SAndroid Build Coastguard Worker      a macro, then rescan for more expansions. Thus, we use V2 to expand
2532*6be67779SAndroid Build Coastguard Worker      the version macros, then CPP will expand the resulting V1() macro
2533*6be67779SAndroid Build Coastguard Worker      with the correct numerals. */
2534*6be67779SAndroid Build Coastguard Worker   /* ### I'm assuming cpp is portable in this respect... */
2535*6be67779SAndroid Build Coastguard Worker 
2536*6be67779SAndroid Build Coastguard Worker #define V1(a, b, c) XML_L(#a) XML_L(".") XML_L(#b) XML_L(".") XML_L(#c)
2537*6be67779SAndroid Build Coastguard Worker #define V2(a, b, c) XML_L("expat_") V1(a, b, c)
2538*6be67779SAndroid Build Coastguard Worker 
2539*6be67779SAndroid Build Coastguard Worker   return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
2540*6be67779SAndroid Build Coastguard Worker 
2541*6be67779SAndroid Build Coastguard Worker #undef V1
2542*6be67779SAndroid Build Coastguard Worker #undef V2
2543*6be67779SAndroid Build Coastguard Worker }
2544*6be67779SAndroid Build Coastguard Worker 
2545*6be67779SAndroid Build Coastguard Worker XML_Expat_Version XMLCALL
XML_ExpatVersionInfo(void)2546*6be67779SAndroid Build Coastguard Worker XML_ExpatVersionInfo(void) {
2547*6be67779SAndroid Build Coastguard Worker   XML_Expat_Version version;
2548*6be67779SAndroid Build Coastguard Worker 
2549*6be67779SAndroid Build Coastguard Worker   version.major = XML_MAJOR_VERSION;
2550*6be67779SAndroid Build Coastguard Worker   version.minor = XML_MINOR_VERSION;
2551*6be67779SAndroid Build Coastguard Worker   version.micro = XML_MICRO_VERSION;
2552*6be67779SAndroid Build Coastguard Worker 
2553*6be67779SAndroid Build Coastguard Worker   return version;
2554*6be67779SAndroid Build Coastguard Worker }
2555*6be67779SAndroid Build Coastguard Worker 
2556*6be67779SAndroid Build Coastguard Worker const XML_Feature *XMLCALL
XML_GetFeatureList(void)2557*6be67779SAndroid Build Coastguard Worker XML_GetFeatureList(void) {
2558*6be67779SAndroid Build Coastguard Worker   static const XML_Feature features[] = {
2559*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2560*6be67779SAndroid Build Coastguard Worker        sizeof(XML_Char)},
2561*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2562*6be67779SAndroid Build Coastguard Worker        sizeof(XML_LChar)},
2563*6be67779SAndroid Build Coastguard Worker #ifdef XML_UNICODE
2564*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2565*6be67779SAndroid Build Coastguard Worker #endif
2566*6be67779SAndroid Build Coastguard Worker #ifdef XML_UNICODE_WCHAR_T
2567*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2568*6be67779SAndroid Build Coastguard Worker #endif
2569*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
2570*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2571*6be67779SAndroid Build Coastguard Worker #endif
2572*6be67779SAndroid Build Coastguard Worker #if XML_CONTEXT_BYTES > 0
2573*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2574*6be67779SAndroid Build Coastguard Worker        XML_CONTEXT_BYTES},
2575*6be67779SAndroid Build Coastguard Worker #endif
2576*6be67779SAndroid Build Coastguard Worker #ifdef XML_MIN_SIZE
2577*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2578*6be67779SAndroid Build Coastguard Worker #endif
2579*6be67779SAndroid Build Coastguard Worker #ifdef XML_NS
2580*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2581*6be67779SAndroid Build Coastguard Worker #endif
2582*6be67779SAndroid Build Coastguard Worker #ifdef XML_LARGE_SIZE
2583*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
2584*6be67779SAndroid Build Coastguard Worker #endif
2585*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
2586*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2587*6be67779SAndroid Build Coastguard Worker #endif
2588*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
2589*6be67779SAndroid Build Coastguard Worker       /* Added in Expat 2.4.0 for XML_DTD defined and
2590*6be67779SAndroid Build Coastguard Worker        * added in Expat 2.6.0 for XML_GE == 1. */
2591*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
2592*6be67779SAndroid Build Coastguard Worker        XML_L("XML_BLAP_MAX_AMP"),
2593*6be67779SAndroid Build Coastguard Worker        (long int)
2594*6be67779SAndroid Build Coastguard Worker            EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT},
2595*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
2596*6be67779SAndroid Build Coastguard Worker        XML_L("XML_BLAP_ACT_THRES"),
2597*6be67779SAndroid Build Coastguard Worker        EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT},
2598*6be67779SAndroid Build Coastguard Worker       /* Added in Expat 2.6.0. */
2599*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_GE, XML_L("XML_GE"), 0},
2600*6be67779SAndroid Build Coastguard Worker #endif
2601*6be67779SAndroid Build Coastguard Worker       {XML_FEATURE_END, NULL, 0}};
2602*6be67779SAndroid Build Coastguard Worker 
2603*6be67779SAndroid Build Coastguard Worker   return features;
2604*6be67779SAndroid Build Coastguard Worker }
2605*6be67779SAndroid Build Coastguard Worker 
2606*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
2607*6be67779SAndroid Build Coastguard Worker XML_Bool XMLCALL
XML_SetBillionLaughsAttackProtectionMaximumAmplification(XML_Parser parser,float maximumAmplificationFactor)2608*6be67779SAndroid Build Coastguard Worker XML_SetBillionLaughsAttackProtectionMaximumAmplification(
2609*6be67779SAndroid Build Coastguard Worker     XML_Parser parser, float maximumAmplificationFactor) {
2610*6be67779SAndroid Build Coastguard Worker   if ((parser == NULL) || (parser->m_parentParser != NULL)
2611*6be67779SAndroid Build Coastguard Worker       || isnan(maximumAmplificationFactor)
2612*6be67779SAndroid Build Coastguard Worker       || (maximumAmplificationFactor < 1.0f)) {
2613*6be67779SAndroid Build Coastguard Worker     return XML_FALSE;
2614*6be67779SAndroid Build Coastguard Worker   }
2615*6be67779SAndroid Build Coastguard Worker   parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor;
2616*6be67779SAndroid Build Coastguard Worker   return XML_TRUE;
2617*6be67779SAndroid Build Coastguard Worker }
2618*6be67779SAndroid Build Coastguard Worker 
2619*6be67779SAndroid Build Coastguard Worker XML_Bool XMLCALL
XML_SetBillionLaughsAttackProtectionActivationThreshold(XML_Parser parser,unsigned long long activationThresholdBytes)2620*6be67779SAndroid Build Coastguard Worker XML_SetBillionLaughsAttackProtectionActivationThreshold(
2621*6be67779SAndroid Build Coastguard Worker     XML_Parser parser, unsigned long long activationThresholdBytes) {
2622*6be67779SAndroid Build Coastguard Worker   if ((parser == NULL) || (parser->m_parentParser != NULL)) {
2623*6be67779SAndroid Build Coastguard Worker     return XML_FALSE;
2624*6be67779SAndroid Build Coastguard Worker   }
2625*6be67779SAndroid Build Coastguard Worker   parser->m_accounting.activationThresholdBytes = activationThresholdBytes;
2626*6be67779SAndroid Build Coastguard Worker   return XML_TRUE;
2627*6be67779SAndroid Build Coastguard Worker }
2628*6be67779SAndroid Build Coastguard Worker #endif /* XML_GE == 1 */
2629*6be67779SAndroid Build Coastguard Worker 
2630*6be67779SAndroid Build Coastguard Worker XML_Bool XMLCALL
XML_SetReparseDeferralEnabled(XML_Parser parser,XML_Bool enabled)2631*6be67779SAndroid Build Coastguard Worker XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled) {
2632*6be67779SAndroid Build Coastguard Worker   if (parser != NULL && (enabled == XML_TRUE || enabled == XML_FALSE)) {
2633*6be67779SAndroid Build Coastguard Worker     parser->m_reparseDeferralEnabled = enabled;
2634*6be67779SAndroid Build Coastguard Worker     return XML_TRUE;
2635*6be67779SAndroid Build Coastguard Worker   }
2636*6be67779SAndroid Build Coastguard Worker   return XML_FALSE;
2637*6be67779SAndroid Build Coastguard Worker }
2638*6be67779SAndroid Build Coastguard Worker 
2639*6be67779SAndroid Build Coastguard Worker /* Initially tag->rawName always points into the parse buffer;
2640*6be67779SAndroid Build Coastguard Worker    for those TAG instances opened while the current parse buffer was
2641*6be67779SAndroid Build Coastguard Worker    processed, and not yet closed, we need to store tag->rawName in a more
2642*6be67779SAndroid Build Coastguard Worker    permanent location, since the parse buffer is about to be discarded.
2643*6be67779SAndroid Build Coastguard Worker */
2644*6be67779SAndroid Build Coastguard Worker static XML_Bool
storeRawNames(XML_Parser parser)2645*6be67779SAndroid Build Coastguard Worker storeRawNames(XML_Parser parser) {
2646*6be67779SAndroid Build Coastguard Worker   TAG *tag = parser->m_tagStack;
2647*6be67779SAndroid Build Coastguard Worker   while (tag) {
2648*6be67779SAndroid Build Coastguard Worker     int bufSize;
2649*6be67779SAndroid Build Coastguard Worker     int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2650*6be67779SAndroid Build Coastguard Worker     size_t rawNameLen;
2651*6be67779SAndroid Build Coastguard Worker     char *rawNameBuf = tag->buf + nameLen;
2652*6be67779SAndroid Build Coastguard Worker     /* Stop if already stored.  Since m_tagStack is a stack, we can stop
2653*6be67779SAndroid Build Coastguard Worker        at the first entry that has already been copied; everything
2654*6be67779SAndroid Build Coastguard Worker        below it in the stack is already been accounted for in a
2655*6be67779SAndroid Build Coastguard Worker        previous call to this function.
2656*6be67779SAndroid Build Coastguard Worker     */
2657*6be67779SAndroid Build Coastguard Worker     if (tag->rawName == rawNameBuf)
2658*6be67779SAndroid Build Coastguard Worker       break;
2659*6be67779SAndroid Build Coastguard Worker     /* For reuse purposes we need to ensure that the
2660*6be67779SAndroid Build Coastguard Worker        size of tag->buf is a multiple of sizeof(XML_Char).
2661*6be67779SAndroid Build Coastguard Worker     */
2662*6be67779SAndroid Build Coastguard Worker     rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2663*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow. */
2664*6be67779SAndroid Build Coastguard Worker     if (rawNameLen > (size_t)INT_MAX - nameLen)
2665*6be67779SAndroid Build Coastguard Worker       return XML_FALSE;
2666*6be67779SAndroid Build Coastguard Worker     bufSize = nameLen + (int)rawNameLen;
2667*6be67779SAndroid Build Coastguard Worker     if (bufSize > tag->bufEnd - tag->buf) {
2668*6be67779SAndroid Build Coastguard Worker       char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
2669*6be67779SAndroid Build Coastguard Worker       if (temp == NULL)
2670*6be67779SAndroid Build Coastguard Worker         return XML_FALSE;
2671*6be67779SAndroid Build Coastguard Worker       /* if tag->name.str points to tag->buf (only when namespace
2672*6be67779SAndroid Build Coastguard Worker          processing is off) then we have to update it
2673*6be67779SAndroid Build Coastguard Worker       */
2674*6be67779SAndroid Build Coastguard Worker       if (tag->name.str == (XML_Char *)tag->buf)
2675*6be67779SAndroid Build Coastguard Worker         tag->name.str = (XML_Char *)temp;
2676*6be67779SAndroid Build Coastguard Worker       /* if tag->name.localPart is set (when namespace processing is on)
2677*6be67779SAndroid Build Coastguard Worker          then update it as well, since it will always point into tag->buf
2678*6be67779SAndroid Build Coastguard Worker       */
2679*6be67779SAndroid Build Coastguard Worker       if (tag->name.localPart)
2680*6be67779SAndroid Build Coastguard Worker         tag->name.localPart
2681*6be67779SAndroid Build Coastguard Worker             = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf);
2682*6be67779SAndroid Build Coastguard Worker       tag->buf = temp;
2683*6be67779SAndroid Build Coastguard Worker       tag->bufEnd = temp + bufSize;
2684*6be67779SAndroid Build Coastguard Worker       rawNameBuf = temp + nameLen;
2685*6be67779SAndroid Build Coastguard Worker     }
2686*6be67779SAndroid Build Coastguard Worker     memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2687*6be67779SAndroid Build Coastguard Worker     tag->rawName = rawNameBuf;
2688*6be67779SAndroid Build Coastguard Worker     tag = tag->parent;
2689*6be67779SAndroid Build Coastguard Worker   }
2690*6be67779SAndroid Build Coastguard Worker   return XML_TRUE;
2691*6be67779SAndroid Build Coastguard Worker }
2692*6be67779SAndroid Build Coastguard Worker 
2693*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
contentProcessor(XML_Parser parser,const char * start,const char * end,const char ** endPtr)2694*6be67779SAndroid Build Coastguard Worker contentProcessor(XML_Parser parser, const char *start, const char *end,
2695*6be67779SAndroid Build Coastguard Worker                  const char **endPtr) {
2696*6be67779SAndroid Build Coastguard Worker   enum XML_Error result = doContent(
2697*6be67779SAndroid Build Coastguard Worker       parser, 0, parser->m_encoding, start, end, endPtr,
2698*6be67779SAndroid Build Coastguard Worker       (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
2699*6be67779SAndroid Build Coastguard Worker   if (result == XML_ERROR_NONE) {
2700*6be67779SAndroid Build Coastguard Worker     if (! storeRawNames(parser))
2701*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
2702*6be67779SAndroid Build Coastguard Worker   }
2703*6be67779SAndroid Build Coastguard Worker   return result;
2704*6be67779SAndroid Build Coastguard Worker }
2705*6be67779SAndroid Build Coastguard Worker 
2706*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
externalEntityInitProcessor(XML_Parser parser,const char * start,const char * end,const char ** endPtr)2707*6be67779SAndroid Build Coastguard Worker externalEntityInitProcessor(XML_Parser parser, const char *start,
2708*6be67779SAndroid Build Coastguard Worker                             const char *end, const char **endPtr) {
2709*6be67779SAndroid Build Coastguard Worker   enum XML_Error result = initializeEncoding(parser);
2710*6be67779SAndroid Build Coastguard Worker   if (result != XML_ERROR_NONE)
2711*6be67779SAndroid Build Coastguard Worker     return result;
2712*6be67779SAndroid Build Coastguard Worker   parser->m_processor = externalEntityInitProcessor2;
2713*6be67779SAndroid Build Coastguard Worker   return externalEntityInitProcessor2(parser, start, end, endPtr);
2714*6be67779SAndroid Build Coastguard Worker }
2715*6be67779SAndroid Build Coastguard Worker 
2716*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
externalEntityInitProcessor2(XML_Parser parser,const char * start,const char * end,const char ** endPtr)2717*6be67779SAndroid Build Coastguard Worker externalEntityInitProcessor2(XML_Parser parser, const char *start,
2718*6be67779SAndroid Build Coastguard Worker                              const char *end, const char **endPtr) {
2719*6be67779SAndroid Build Coastguard Worker   const char *next = start; /* XmlContentTok doesn't always set the last arg */
2720*6be67779SAndroid Build Coastguard Worker   int tok = XmlContentTok(parser->m_encoding, start, end, &next);
2721*6be67779SAndroid Build Coastguard Worker   switch (tok) {
2722*6be67779SAndroid Build Coastguard Worker   case XML_TOK_BOM:
2723*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
2724*6be67779SAndroid Build Coastguard Worker     if (! accountingDiffTolerated(parser, tok, start, next, __LINE__,
2725*6be67779SAndroid Build Coastguard Worker                                   XML_ACCOUNT_DIRECT)) {
2726*6be67779SAndroid Build Coastguard Worker       accountingOnAbort(parser);
2727*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
2728*6be67779SAndroid Build Coastguard Worker     }
2729*6be67779SAndroid Build Coastguard Worker #endif /* XML_GE == 1 */
2730*6be67779SAndroid Build Coastguard Worker 
2731*6be67779SAndroid Build Coastguard Worker     /* If we are at the end of the buffer, this would cause the next stage,
2732*6be67779SAndroid Build Coastguard Worker        i.e. externalEntityInitProcessor3, to pass control directly to
2733*6be67779SAndroid Build Coastguard Worker        doContent (by detecting XML_TOK_NONE) without processing any xml text
2734*6be67779SAndroid Build Coastguard Worker        declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2735*6be67779SAndroid Build Coastguard Worker     */
2736*6be67779SAndroid Build Coastguard Worker     if (next == end && ! parser->m_parsingStatus.finalBuffer) {
2737*6be67779SAndroid Build Coastguard Worker       *endPtr = next;
2738*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
2739*6be67779SAndroid Build Coastguard Worker     }
2740*6be67779SAndroid Build Coastguard Worker     start = next;
2741*6be67779SAndroid Build Coastguard Worker     break;
2742*6be67779SAndroid Build Coastguard Worker   case XML_TOK_PARTIAL:
2743*6be67779SAndroid Build Coastguard Worker     if (! parser->m_parsingStatus.finalBuffer) {
2744*6be67779SAndroid Build Coastguard Worker       *endPtr = start;
2745*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
2746*6be67779SAndroid Build Coastguard Worker     }
2747*6be67779SAndroid Build Coastguard Worker     parser->m_eventPtr = start;
2748*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_UNCLOSED_TOKEN;
2749*6be67779SAndroid Build Coastguard Worker   case XML_TOK_PARTIAL_CHAR:
2750*6be67779SAndroid Build Coastguard Worker     if (! parser->m_parsingStatus.finalBuffer) {
2751*6be67779SAndroid Build Coastguard Worker       *endPtr = start;
2752*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
2753*6be67779SAndroid Build Coastguard Worker     }
2754*6be67779SAndroid Build Coastguard Worker     parser->m_eventPtr = start;
2755*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_PARTIAL_CHAR;
2756*6be67779SAndroid Build Coastguard Worker   }
2757*6be67779SAndroid Build Coastguard Worker   parser->m_processor = externalEntityInitProcessor3;
2758*6be67779SAndroid Build Coastguard Worker   return externalEntityInitProcessor3(parser, start, end, endPtr);
2759*6be67779SAndroid Build Coastguard Worker }
2760*6be67779SAndroid Build Coastguard Worker 
2761*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
externalEntityInitProcessor3(XML_Parser parser,const char * start,const char * end,const char ** endPtr)2762*6be67779SAndroid Build Coastguard Worker externalEntityInitProcessor3(XML_Parser parser, const char *start,
2763*6be67779SAndroid Build Coastguard Worker                              const char *end, const char **endPtr) {
2764*6be67779SAndroid Build Coastguard Worker   int tok;
2765*6be67779SAndroid Build Coastguard Worker   const char *next = start; /* XmlContentTok doesn't always set the last arg */
2766*6be67779SAndroid Build Coastguard Worker   parser->m_eventPtr = start;
2767*6be67779SAndroid Build Coastguard Worker   tok = XmlContentTok(parser->m_encoding, start, end, &next);
2768*6be67779SAndroid Build Coastguard Worker   /* Note: These bytes are accounted later in:
2769*6be67779SAndroid Build Coastguard Worker            - processXmlDecl
2770*6be67779SAndroid Build Coastguard Worker            - externalEntityContentProcessor
2771*6be67779SAndroid Build Coastguard Worker   */
2772*6be67779SAndroid Build Coastguard Worker   parser->m_eventEndPtr = next;
2773*6be67779SAndroid Build Coastguard Worker 
2774*6be67779SAndroid Build Coastguard Worker   switch (tok) {
2775*6be67779SAndroid Build Coastguard Worker   case XML_TOK_XML_DECL: {
2776*6be67779SAndroid Build Coastguard Worker     enum XML_Error result;
2777*6be67779SAndroid Build Coastguard Worker     result = processXmlDecl(parser, 1, start, next);
2778*6be67779SAndroid Build Coastguard Worker     if (result != XML_ERROR_NONE)
2779*6be67779SAndroid Build Coastguard Worker       return result;
2780*6be67779SAndroid Build Coastguard Worker     switch (parser->m_parsingStatus.parsing) {
2781*6be67779SAndroid Build Coastguard Worker     case XML_SUSPENDED:
2782*6be67779SAndroid Build Coastguard Worker       *endPtr = next;
2783*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
2784*6be67779SAndroid Build Coastguard Worker     case XML_FINISHED:
2785*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_ABORTED;
2786*6be67779SAndroid Build Coastguard Worker     default:
2787*6be67779SAndroid Build Coastguard Worker       start = next;
2788*6be67779SAndroid Build Coastguard Worker     }
2789*6be67779SAndroid Build Coastguard Worker   } break;
2790*6be67779SAndroid Build Coastguard Worker   case XML_TOK_PARTIAL:
2791*6be67779SAndroid Build Coastguard Worker     if (! parser->m_parsingStatus.finalBuffer) {
2792*6be67779SAndroid Build Coastguard Worker       *endPtr = start;
2793*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
2794*6be67779SAndroid Build Coastguard Worker     }
2795*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_UNCLOSED_TOKEN;
2796*6be67779SAndroid Build Coastguard Worker   case XML_TOK_PARTIAL_CHAR:
2797*6be67779SAndroid Build Coastguard Worker     if (! parser->m_parsingStatus.finalBuffer) {
2798*6be67779SAndroid Build Coastguard Worker       *endPtr = start;
2799*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
2800*6be67779SAndroid Build Coastguard Worker     }
2801*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_PARTIAL_CHAR;
2802*6be67779SAndroid Build Coastguard Worker   }
2803*6be67779SAndroid Build Coastguard Worker   parser->m_processor = externalEntityContentProcessor;
2804*6be67779SAndroid Build Coastguard Worker   parser->m_tagLevel = 1;
2805*6be67779SAndroid Build Coastguard Worker   return externalEntityContentProcessor(parser, start, end, endPtr);
2806*6be67779SAndroid Build Coastguard Worker }
2807*6be67779SAndroid Build Coastguard Worker 
2808*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
externalEntityContentProcessor(XML_Parser parser,const char * start,const char * end,const char ** endPtr)2809*6be67779SAndroid Build Coastguard Worker externalEntityContentProcessor(XML_Parser parser, const char *start,
2810*6be67779SAndroid Build Coastguard Worker                                const char *end, const char **endPtr) {
2811*6be67779SAndroid Build Coastguard Worker   enum XML_Error result
2812*6be67779SAndroid Build Coastguard Worker       = doContent(parser, 1, parser->m_encoding, start, end, endPtr,
2813*6be67779SAndroid Build Coastguard Worker                   (XML_Bool)! parser->m_parsingStatus.finalBuffer,
2814*6be67779SAndroid Build Coastguard Worker                   XML_ACCOUNT_ENTITY_EXPANSION);
2815*6be67779SAndroid Build Coastguard Worker   if (result == XML_ERROR_NONE) {
2816*6be67779SAndroid Build Coastguard Worker     if (! storeRawNames(parser))
2817*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
2818*6be67779SAndroid Build Coastguard Worker   }
2819*6be67779SAndroid Build Coastguard Worker   return result;
2820*6be67779SAndroid Build Coastguard Worker }
2821*6be67779SAndroid Build Coastguard Worker 
2822*6be67779SAndroid Build Coastguard Worker 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)2823*6be67779SAndroid Build Coastguard Worker doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
2824*6be67779SAndroid Build Coastguard Worker           const char *s, const char *end, const char **nextPtr,
2825*6be67779SAndroid Build Coastguard Worker           XML_Bool haveMore, enum XML_Account account) {
2826*6be67779SAndroid Build Coastguard Worker   /* save one level of indirection */
2827*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd;
2828*6be67779SAndroid Build Coastguard Worker 
2829*6be67779SAndroid Build Coastguard Worker   const char **eventPP;
2830*6be67779SAndroid Build Coastguard Worker   const char **eventEndPP;
2831*6be67779SAndroid Build Coastguard Worker   if (enc == parser->m_encoding) {
2832*6be67779SAndroid Build Coastguard Worker     eventPP = &parser->m_eventPtr;
2833*6be67779SAndroid Build Coastguard Worker     eventEndPP = &parser->m_eventEndPtr;
2834*6be67779SAndroid Build Coastguard Worker   } else {
2835*6be67779SAndroid Build Coastguard Worker     eventPP = &(parser->m_openInternalEntities->internalEventPtr);
2836*6be67779SAndroid Build Coastguard Worker     eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
2837*6be67779SAndroid Build Coastguard Worker   }
2838*6be67779SAndroid Build Coastguard Worker   *eventPP = s;
2839*6be67779SAndroid Build Coastguard Worker 
2840*6be67779SAndroid Build Coastguard Worker   for (;;) {
2841*6be67779SAndroid Build Coastguard Worker     const char *next = s; /* XmlContentTok doesn't always set the last arg */
2842*6be67779SAndroid Build Coastguard Worker     int tok = XmlContentTok(enc, s, end, &next);
2843*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
2844*6be67779SAndroid Build Coastguard Worker     const char *accountAfter
2845*6be67779SAndroid Build Coastguard Worker         = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR))
2846*6be67779SAndroid Build Coastguard Worker               ? (haveMore ? s /* i.e. 0 bytes */ : end)
2847*6be67779SAndroid Build Coastguard Worker               : next;
2848*6be67779SAndroid Build Coastguard Worker     if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__,
2849*6be67779SAndroid Build Coastguard Worker                                   account)) {
2850*6be67779SAndroid Build Coastguard Worker       accountingOnAbort(parser);
2851*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
2852*6be67779SAndroid Build Coastguard Worker     }
2853*6be67779SAndroid Build Coastguard Worker #endif
2854*6be67779SAndroid Build Coastguard Worker     *eventEndPP = next;
2855*6be67779SAndroid Build Coastguard Worker     switch (tok) {
2856*6be67779SAndroid Build Coastguard Worker     case XML_TOK_TRAILING_CR:
2857*6be67779SAndroid Build Coastguard Worker       if (haveMore) {
2858*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
2859*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
2860*6be67779SAndroid Build Coastguard Worker       }
2861*6be67779SAndroid Build Coastguard Worker       *eventEndPP = end;
2862*6be67779SAndroid Build Coastguard Worker       if (parser->m_characterDataHandler) {
2863*6be67779SAndroid Build Coastguard Worker         XML_Char c = 0xA;
2864*6be67779SAndroid Build Coastguard Worker         parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
2865*6be67779SAndroid Build Coastguard Worker       } else if (parser->m_defaultHandler)
2866*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, end);
2867*6be67779SAndroid Build Coastguard Worker       /* We are at the end of the final buffer, should we check for
2868*6be67779SAndroid Build Coastguard Worker          XML_SUSPENDED, XML_FINISHED?
2869*6be67779SAndroid Build Coastguard Worker       */
2870*6be67779SAndroid Build Coastguard Worker       if (startTagLevel == 0)
2871*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_ELEMENTS;
2872*6be67779SAndroid Build Coastguard Worker       if (parser->m_tagLevel != startTagLevel)
2873*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_ASYNC_ENTITY;
2874*6be67779SAndroid Build Coastguard Worker       *nextPtr = end;
2875*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
2876*6be67779SAndroid Build Coastguard Worker     case XML_TOK_NONE:
2877*6be67779SAndroid Build Coastguard Worker       if (haveMore) {
2878*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
2879*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
2880*6be67779SAndroid Build Coastguard Worker       }
2881*6be67779SAndroid Build Coastguard Worker       if (startTagLevel > 0) {
2882*6be67779SAndroid Build Coastguard Worker         if (parser->m_tagLevel != startTagLevel)
2883*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_ASYNC_ENTITY;
2884*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
2885*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
2886*6be67779SAndroid Build Coastguard Worker       }
2887*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_ELEMENTS;
2888*6be67779SAndroid Build Coastguard Worker     case XML_TOK_INVALID:
2889*6be67779SAndroid Build Coastguard Worker       *eventPP = next;
2890*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_INVALID_TOKEN;
2891*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL:
2892*6be67779SAndroid Build Coastguard Worker       if (haveMore) {
2893*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
2894*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
2895*6be67779SAndroid Build Coastguard Worker       }
2896*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_UNCLOSED_TOKEN;
2897*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL_CHAR:
2898*6be67779SAndroid Build Coastguard Worker       if (haveMore) {
2899*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
2900*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
2901*6be67779SAndroid Build Coastguard Worker       }
2902*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_PARTIAL_CHAR;
2903*6be67779SAndroid Build Coastguard Worker     case XML_TOK_ENTITY_REF: {
2904*6be67779SAndroid Build Coastguard Worker       const XML_Char *name;
2905*6be67779SAndroid Build Coastguard Worker       ENTITY *entity;
2906*6be67779SAndroid Build Coastguard Worker       XML_Char ch = (XML_Char)XmlPredefinedEntityName(
2907*6be67779SAndroid Build Coastguard Worker           enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
2908*6be67779SAndroid Build Coastguard Worker       if (ch) {
2909*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
2910*6be67779SAndroid Build Coastguard Worker         /* NOTE: We are replacing 4-6 characters original input for 1 character
2911*6be67779SAndroid Build Coastguard Worker          *       so there is no amplification and hence recording without
2912*6be67779SAndroid Build Coastguard Worker          *       protection. */
2913*6be67779SAndroid Build Coastguard Worker         accountingDiffTolerated(parser, tok, (char *)&ch,
2914*6be67779SAndroid Build Coastguard Worker                                 ((char *)&ch) + sizeof(XML_Char), __LINE__,
2915*6be67779SAndroid Build Coastguard Worker                                 XML_ACCOUNT_ENTITY_EXPANSION);
2916*6be67779SAndroid Build Coastguard Worker #endif /* XML_GE == 1 */
2917*6be67779SAndroid Build Coastguard Worker         if (parser->m_characterDataHandler)
2918*6be67779SAndroid Build Coastguard Worker           parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
2919*6be67779SAndroid Build Coastguard Worker         else if (parser->m_defaultHandler)
2920*6be67779SAndroid Build Coastguard Worker           reportDefault(parser, enc, s, next);
2921*6be67779SAndroid Build Coastguard Worker         break;
2922*6be67779SAndroid Build Coastguard Worker       }
2923*6be67779SAndroid Build Coastguard Worker       name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
2924*6be67779SAndroid Build Coastguard Worker                              next - enc->minBytesPerChar);
2925*6be67779SAndroid Build Coastguard Worker       if (! name)
2926*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
2927*6be67779SAndroid Build Coastguard Worker       entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
2928*6be67779SAndroid Build Coastguard Worker       poolDiscard(&dtd->pool);
2929*6be67779SAndroid Build Coastguard Worker       /* First, determine if a check for an existing declaration is needed;
2930*6be67779SAndroid Build Coastguard Worker          if yes, check that the entity exists, and that it is internal,
2931*6be67779SAndroid Build Coastguard Worker          otherwise call the skipped entity or default handler.
2932*6be67779SAndroid Build Coastguard Worker       */
2933*6be67779SAndroid Build Coastguard Worker       if (! dtd->hasParamEntityRefs || dtd->standalone) {
2934*6be67779SAndroid Build Coastguard Worker         if (! entity)
2935*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_UNDEFINED_ENTITY;
2936*6be67779SAndroid Build Coastguard Worker         else if (! entity->is_internal)
2937*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_ENTITY_DECLARED_IN_PE;
2938*6be67779SAndroid Build Coastguard Worker       } else if (! entity) {
2939*6be67779SAndroid Build Coastguard Worker         if (parser->m_skippedEntityHandler)
2940*6be67779SAndroid Build Coastguard Worker           parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
2941*6be67779SAndroid Build Coastguard Worker         else if (parser->m_defaultHandler)
2942*6be67779SAndroid Build Coastguard Worker           reportDefault(parser, enc, s, next);
2943*6be67779SAndroid Build Coastguard Worker         break;
2944*6be67779SAndroid Build Coastguard Worker       }
2945*6be67779SAndroid Build Coastguard Worker       if (entity->open)
2946*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_RECURSIVE_ENTITY_REF;
2947*6be67779SAndroid Build Coastguard Worker       if (entity->notation)
2948*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_BINARY_ENTITY_REF;
2949*6be67779SAndroid Build Coastguard Worker       if (entity->textPtr) {
2950*6be67779SAndroid Build Coastguard Worker         enum XML_Error result;
2951*6be67779SAndroid Build Coastguard Worker         if (! parser->m_defaultExpandInternalEntities) {
2952*6be67779SAndroid Build Coastguard Worker           if (parser->m_skippedEntityHandler)
2953*6be67779SAndroid Build Coastguard Worker             parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name,
2954*6be67779SAndroid Build Coastguard Worker                                            0);
2955*6be67779SAndroid Build Coastguard Worker           else if (parser->m_defaultHandler)
2956*6be67779SAndroid Build Coastguard Worker             reportDefault(parser, enc, s, next);
2957*6be67779SAndroid Build Coastguard Worker           break;
2958*6be67779SAndroid Build Coastguard Worker         }
2959*6be67779SAndroid Build Coastguard Worker         result = processInternalEntity(parser, entity, XML_FALSE);
2960*6be67779SAndroid Build Coastguard Worker         if (result != XML_ERROR_NONE)
2961*6be67779SAndroid Build Coastguard Worker           return result;
2962*6be67779SAndroid Build Coastguard Worker       } else if (parser->m_externalEntityRefHandler) {
2963*6be67779SAndroid Build Coastguard Worker         const XML_Char *context;
2964*6be67779SAndroid Build Coastguard Worker         entity->open = XML_TRUE;
2965*6be67779SAndroid Build Coastguard Worker         context = getContext(parser);
2966*6be67779SAndroid Build Coastguard Worker         entity->open = XML_FALSE;
2967*6be67779SAndroid Build Coastguard Worker         if (! context)
2968*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
2969*6be67779SAndroid Build Coastguard Worker         if (! parser->m_externalEntityRefHandler(
2970*6be67779SAndroid Build Coastguard Worker                 parser->m_externalEntityRefHandlerArg, context, entity->base,
2971*6be67779SAndroid Build Coastguard Worker                 entity->systemId, entity->publicId))
2972*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2973*6be67779SAndroid Build Coastguard Worker         poolDiscard(&parser->m_tempPool);
2974*6be67779SAndroid Build Coastguard Worker       } else if (parser->m_defaultHandler)
2975*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
2976*6be67779SAndroid Build Coastguard Worker       break;
2977*6be67779SAndroid Build Coastguard Worker     }
2978*6be67779SAndroid Build Coastguard Worker     case XML_TOK_START_TAG_NO_ATTS:
2979*6be67779SAndroid Build Coastguard Worker       /* fall through */
2980*6be67779SAndroid Build Coastguard Worker     case XML_TOK_START_TAG_WITH_ATTS: {
2981*6be67779SAndroid Build Coastguard Worker       TAG *tag;
2982*6be67779SAndroid Build Coastguard Worker       enum XML_Error result;
2983*6be67779SAndroid Build Coastguard Worker       XML_Char *toPtr;
2984*6be67779SAndroid Build Coastguard Worker       if (parser->m_freeTagList) {
2985*6be67779SAndroid Build Coastguard Worker         tag = parser->m_freeTagList;
2986*6be67779SAndroid Build Coastguard Worker         parser->m_freeTagList = parser->m_freeTagList->parent;
2987*6be67779SAndroid Build Coastguard Worker       } else {
2988*6be67779SAndroid Build Coastguard Worker         tag = (TAG *)MALLOC(parser, sizeof(TAG));
2989*6be67779SAndroid Build Coastguard Worker         if (! tag)
2990*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
2991*6be67779SAndroid Build Coastguard Worker         tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
2992*6be67779SAndroid Build Coastguard Worker         if (! tag->buf) {
2993*6be67779SAndroid Build Coastguard Worker           FREE(parser, tag);
2994*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
2995*6be67779SAndroid Build Coastguard Worker         }
2996*6be67779SAndroid Build Coastguard Worker         tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2997*6be67779SAndroid Build Coastguard Worker       }
2998*6be67779SAndroid Build Coastguard Worker       tag->bindings = NULL;
2999*6be67779SAndroid Build Coastguard Worker       tag->parent = parser->m_tagStack;
3000*6be67779SAndroid Build Coastguard Worker       parser->m_tagStack = tag;
3001*6be67779SAndroid Build Coastguard Worker       tag->name.localPart = NULL;
3002*6be67779SAndroid Build Coastguard Worker       tag->name.prefix = NULL;
3003*6be67779SAndroid Build Coastguard Worker       tag->rawName = s + enc->minBytesPerChar;
3004*6be67779SAndroid Build Coastguard Worker       tag->rawNameLength = XmlNameLength(enc, tag->rawName);
3005*6be67779SAndroid Build Coastguard Worker       ++parser->m_tagLevel;
3006*6be67779SAndroid Build Coastguard Worker       {
3007*6be67779SAndroid Build Coastguard Worker         const char *rawNameEnd = tag->rawName + tag->rawNameLength;
3008*6be67779SAndroid Build Coastguard Worker         const char *fromPtr = tag->rawName;
3009*6be67779SAndroid Build Coastguard Worker         toPtr = (XML_Char *)tag->buf;
3010*6be67779SAndroid Build Coastguard Worker         for (;;) {
3011*6be67779SAndroid Build Coastguard Worker           int bufSize;
3012*6be67779SAndroid Build Coastguard Worker           int convLen;
3013*6be67779SAndroid Build Coastguard Worker           const enum XML_Convert_Result convert_res
3014*6be67779SAndroid Build Coastguard Worker               = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr,
3015*6be67779SAndroid Build Coastguard Worker                            (ICHAR *)tag->bufEnd - 1);
3016*6be67779SAndroid Build Coastguard Worker           convLen = (int)(toPtr - (XML_Char *)tag->buf);
3017*6be67779SAndroid Build Coastguard Worker           if ((fromPtr >= rawNameEnd)
3018*6be67779SAndroid Build Coastguard Worker               || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
3019*6be67779SAndroid Build Coastguard Worker             tag->name.strLen = convLen;
3020*6be67779SAndroid Build Coastguard Worker             break;
3021*6be67779SAndroid Build Coastguard Worker           }
3022*6be67779SAndroid Build Coastguard Worker           bufSize = (int)(tag->bufEnd - tag->buf) << 1;
3023*6be67779SAndroid Build Coastguard Worker           {
3024*6be67779SAndroid Build Coastguard Worker             char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
3025*6be67779SAndroid Build Coastguard Worker             if (temp == NULL)
3026*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NO_MEMORY;
3027*6be67779SAndroid Build Coastguard Worker             tag->buf = temp;
3028*6be67779SAndroid Build Coastguard Worker             tag->bufEnd = temp + bufSize;
3029*6be67779SAndroid Build Coastguard Worker             toPtr = (XML_Char *)temp + convLen;
3030*6be67779SAndroid Build Coastguard Worker           }
3031*6be67779SAndroid Build Coastguard Worker         }
3032*6be67779SAndroid Build Coastguard Worker       }
3033*6be67779SAndroid Build Coastguard Worker       tag->name.str = (XML_Char *)tag->buf;
3034*6be67779SAndroid Build Coastguard Worker       *toPtr = XML_T('\0');
3035*6be67779SAndroid Build Coastguard Worker       result
3036*6be67779SAndroid Build Coastguard Worker           = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account);
3037*6be67779SAndroid Build Coastguard Worker       if (result)
3038*6be67779SAndroid Build Coastguard Worker         return result;
3039*6be67779SAndroid Build Coastguard Worker       if (parser->m_startElementHandler)
3040*6be67779SAndroid Build Coastguard Worker         parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
3041*6be67779SAndroid Build Coastguard Worker                                       (const XML_Char **)parser->m_atts);
3042*6be67779SAndroid Build Coastguard Worker       else if (parser->m_defaultHandler)
3043*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
3044*6be67779SAndroid Build Coastguard Worker       poolClear(&parser->m_tempPool);
3045*6be67779SAndroid Build Coastguard Worker       break;
3046*6be67779SAndroid Build Coastguard Worker     }
3047*6be67779SAndroid Build Coastguard Worker     case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
3048*6be67779SAndroid Build Coastguard Worker       /* fall through */
3049*6be67779SAndroid Build Coastguard Worker     case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: {
3050*6be67779SAndroid Build Coastguard Worker       const char *rawName = s + enc->minBytesPerChar;
3051*6be67779SAndroid Build Coastguard Worker       enum XML_Error result;
3052*6be67779SAndroid Build Coastguard Worker       BINDING *bindings = NULL;
3053*6be67779SAndroid Build Coastguard Worker       XML_Bool noElmHandlers = XML_TRUE;
3054*6be67779SAndroid Build Coastguard Worker       TAG_NAME name;
3055*6be67779SAndroid Build Coastguard Worker       name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
3056*6be67779SAndroid Build Coastguard Worker                                  rawName + XmlNameLength(enc, rawName));
3057*6be67779SAndroid Build Coastguard Worker       if (! name.str)
3058*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
3059*6be67779SAndroid Build Coastguard Worker       poolFinish(&parser->m_tempPool);
3060*6be67779SAndroid Build Coastguard Worker       result = storeAtts(parser, enc, s, &name, &bindings,
3061*6be67779SAndroid Build Coastguard Worker                          XML_ACCOUNT_NONE /* token spans whole start tag */);
3062*6be67779SAndroid Build Coastguard Worker       if (result != XML_ERROR_NONE) {
3063*6be67779SAndroid Build Coastguard Worker         freeBindings(parser, bindings);
3064*6be67779SAndroid Build Coastguard Worker         return result;
3065*6be67779SAndroid Build Coastguard Worker       }
3066*6be67779SAndroid Build Coastguard Worker       poolFinish(&parser->m_tempPool);
3067*6be67779SAndroid Build Coastguard Worker       if (parser->m_startElementHandler) {
3068*6be67779SAndroid Build Coastguard Worker         parser->m_startElementHandler(parser->m_handlerArg, name.str,
3069*6be67779SAndroid Build Coastguard Worker                                       (const XML_Char **)parser->m_atts);
3070*6be67779SAndroid Build Coastguard Worker         noElmHandlers = XML_FALSE;
3071*6be67779SAndroid Build Coastguard Worker       }
3072*6be67779SAndroid Build Coastguard Worker       if (parser->m_endElementHandler) {
3073*6be67779SAndroid Build Coastguard Worker         if (parser->m_startElementHandler)
3074*6be67779SAndroid Build Coastguard Worker           *eventPP = *eventEndPP;
3075*6be67779SAndroid Build Coastguard Worker         parser->m_endElementHandler(parser->m_handlerArg, name.str);
3076*6be67779SAndroid Build Coastguard Worker         noElmHandlers = XML_FALSE;
3077*6be67779SAndroid Build Coastguard Worker       }
3078*6be67779SAndroid Build Coastguard Worker       if (noElmHandlers && parser->m_defaultHandler)
3079*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
3080*6be67779SAndroid Build Coastguard Worker       poolClear(&parser->m_tempPool);
3081*6be67779SAndroid Build Coastguard Worker       freeBindings(parser, bindings);
3082*6be67779SAndroid Build Coastguard Worker     }
3083*6be67779SAndroid Build Coastguard Worker       if ((parser->m_tagLevel == 0)
3084*6be67779SAndroid Build Coastguard Worker           && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
3085*6be67779SAndroid Build Coastguard Worker         if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
3086*6be67779SAndroid Build Coastguard Worker           parser->m_processor = epilogProcessor;
3087*6be67779SAndroid Build Coastguard Worker         else
3088*6be67779SAndroid Build Coastguard Worker           return epilogProcessor(parser, next, end, nextPtr);
3089*6be67779SAndroid Build Coastguard Worker       }
3090*6be67779SAndroid Build Coastguard Worker       break;
3091*6be67779SAndroid Build Coastguard Worker     case XML_TOK_END_TAG:
3092*6be67779SAndroid Build Coastguard Worker       if (parser->m_tagLevel == startTagLevel)
3093*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_ASYNC_ENTITY;
3094*6be67779SAndroid Build Coastguard Worker       else {
3095*6be67779SAndroid Build Coastguard Worker         int len;
3096*6be67779SAndroid Build Coastguard Worker         const char *rawName;
3097*6be67779SAndroid Build Coastguard Worker         TAG *tag = parser->m_tagStack;
3098*6be67779SAndroid Build Coastguard Worker         rawName = s + enc->minBytesPerChar * 2;
3099*6be67779SAndroid Build Coastguard Worker         len = XmlNameLength(enc, rawName);
3100*6be67779SAndroid Build Coastguard Worker         if (len != tag->rawNameLength
3101*6be67779SAndroid Build Coastguard Worker             || memcmp(tag->rawName, rawName, len) != 0) {
3102*6be67779SAndroid Build Coastguard Worker           *eventPP = rawName;
3103*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_TAG_MISMATCH;
3104*6be67779SAndroid Build Coastguard Worker         }
3105*6be67779SAndroid Build Coastguard Worker         parser->m_tagStack = tag->parent;
3106*6be67779SAndroid Build Coastguard Worker         tag->parent = parser->m_freeTagList;
3107*6be67779SAndroid Build Coastguard Worker         parser->m_freeTagList = tag;
3108*6be67779SAndroid Build Coastguard Worker         --parser->m_tagLevel;
3109*6be67779SAndroid Build Coastguard Worker         if (parser->m_endElementHandler) {
3110*6be67779SAndroid Build Coastguard Worker           const XML_Char *localPart;
3111*6be67779SAndroid Build Coastguard Worker           const XML_Char *prefix;
3112*6be67779SAndroid Build Coastguard Worker           XML_Char *uri;
3113*6be67779SAndroid Build Coastguard Worker           localPart = tag->name.localPart;
3114*6be67779SAndroid Build Coastguard Worker           if (parser->m_ns && localPart) {
3115*6be67779SAndroid Build Coastguard Worker             /* localPart and prefix may have been overwritten in
3116*6be67779SAndroid Build Coastguard Worker                tag->name.str, since this points to the binding->uri
3117*6be67779SAndroid Build Coastguard Worker                buffer which gets reused; so we have to add them again
3118*6be67779SAndroid Build Coastguard Worker             */
3119*6be67779SAndroid Build Coastguard Worker             uri = (XML_Char *)tag->name.str + tag->name.uriLen;
3120*6be67779SAndroid Build Coastguard Worker             /* don't need to check for space - already done in storeAtts() */
3121*6be67779SAndroid Build Coastguard Worker             while (*localPart)
3122*6be67779SAndroid Build Coastguard Worker               *uri++ = *localPart++;
3123*6be67779SAndroid Build Coastguard Worker             prefix = tag->name.prefix;
3124*6be67779SAndroid Build Coastguard Worker             if (parser->m_ns_triplets && prefix) {
3125*6be67779SAndroid Build Coastguard Worker               *uri++ = parser->m_namespaceSeparator;
3126*6be67779SAndroid Build Coastguard Worker               while (*prefix)
3127*6be67779SAndroid Build Coastguard Worker                 *uri++ = *prefix++;
3128*6be67779SAndroid Build Coastguard Worker             }
3129*6be67779SAndroid Build Coastguard Worker             *uri = XML_T('\0');
3130*6be67779SAndroid Build Coastguard Worker           }
3131*6be67779SAndroid Build Coastguard Worker           parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
3132*6be67779SAndroid Build Coastguard Worker         } else if (parser->m_defaultHandler)
3133*6be67779SAndroid Build Coastguard Worker           reportDefault(parser, enc, s, next);
3134*6be67779SAndroid Build Coastguard Worker         while (tag->bindings) {
3135*6be67779SAndroid Build Coastguard Worker           BINDING *b = tag->bindings;
3136*6be67779SAndroid Build Coastguard Worker           if (parser->m_endNamespaceDeclHandler)
3137*6be67779SAndroid Build Coastguard Worker             parser->m_endNamespaceDeclHandler(parser->m_handlerArg,
3138*6be67779SAndroid Build Coastguard Worker                                               b->prefix->name);
3139*6be67779SAndroid Build Coastguard Worker           tag->bindings = tag->bindings->nextTagBinding;
3140*6be67779SAndroid Build Coastguard Worker           b->nextTagBinding = parser->m_freeBindingList;
3141*6be67779SAndroid Build Coastguard Worker           parser->m_freeBindingList = b;
3142*6be67779SAndroid Build Coastguard Worker           b->prefix->binding = b->prevPrefixBinding;
3143*6be67779SAndroid Build Coastguard Worker         }
3144*6be67779SAndroid Build Coastguard Worker         if ((parser->m_tagLevel == 0)
3145*6be67779SAndroid Build Coastguard Worker             && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
3146*6be67779SAndroid Build Coastguard Worker           if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
3147*6be67779SAndroid Build Coastguard Worker             parser->m_processor = epilogProcessor;
3148*6be67779SAndroid Build Coastguard Worker           else
3149*6be67779SAndroid Build Coastguard Worker             return epilogProcessor(parser, next, end, nextPtr);
3150*6be67779SAndroid Build Coastguard Worker         }
3151*6be67779SAndroid Build Coastguard Worker       }
3152*6be67779SAndroid Build Coastguard Worker       break;
3153*6be67779SAndroid Build Coastguard Worker     case XML_TOK_CHAR_REF: {
3154*6be67779SAndroid Build Coastguard Worker       int n = XmlCharRefNumber(enc, s);
3155*6be67779SAndroid Build Coastguard Worker       if (n < 0)
3156*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_BAD_CHAR_REF;
3157*6be67779SAndroid Build Coastguard Worker       if (parser->m_characterDataHandler) {
3158*6be67779SAndroid Build Coastguard Worker         XML_Char buf[XML_ENCODE_MAX];
3159*6be67779SAndroid Build Coastguard Worker         parser->m_characterDataHandler(parser->m_handlerArg, buf,
3160*6be67779SAndroid Build Coastguard Worker                                        XmlEncode(n, (ICHAR *)buf));
3161*6be67779SAndroid Build Coastguard Worker       } else if (parser->m_defaultHandler)
3162*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
3163*6be67779SAndroid Build Coastguard Worker     } break;
3164*6be67779SAndroid Build Coastguard Worker     case XML_TOK_XML_DECL:
3165*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_MISPLACED_XML_PI;
3166*6be67779SAndroid Build Coastguard Worker     case XML_TOK_DATA_NEWLINE:
3167*6be67779SAndroid Build Coastguard Worker       if (parser->m_characterDataHandler) {
3168*6be67779SAndroid Build Coastguard Worker         XML_Char c = 0xA;
3169*6be67779SAndroid Build Coastguard Worker         parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
3170*6be67779SAndroid Build Coastguard Worker       } else if (parser->m_defaultHandler)
3171*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
3172*6be67779SAndroid Build Coastguard Worker       break;
3173*6be67779SAndroid Build Coastguard Worker     case XML_TOK_CDATA_SECT_OPEN: {
3174*6be67779SAndroid Build Coastguard Worker       enum XML_Error result;
3175*6be67779SAndroid Build Coastguard Worker       if (parser->m_startCdataSectionHandler)
3176*6be67779SAndroid Build Coastguard Worker         parser->m_startCdataSectionHandler(parser->m_handlerArg);
3177*6be67779SAndroid Build Coastguard Worker       /* BEGIN disabled code */
3178*6be67779SAndroid Build Coastguard Worker       /* Suppose you doing a transformation on a document that involves
3179*6be67779SAndroid Build Coastguard Worker          changing only the character data.  You set up a defaultHandler
3180*6be67779SAndroid Build Coastguard Worker          and a characterDataHandler.  The defaultHandler simply copies
3181*6be67779SAndroid Build Coastguard Worker          characters through.  The characterDataHandler does the
3182*6be67779SAndroid Build Coastguard Worker          transformation and writes the characters out escaping them as
3183*6be67779SAndroid Build Coastguard Worker          necessary.  This case will fail to work if we leave out the
3184*6be67779SAndroid Build Coastguard Worker          following two lines (because & and < inside CDATA sections will
3185*6be67779SAndroid Build Coastguard Worker          be incorrectly escaped).
3186*6be67779SAndroid Build Coastguard Worker 
3187*6be67779SAndroid Build Coastguard Worker          However, now we have a start/endCdataSectionHandler, so it seems
3188*6be67779SAndroid Build Coastguard Worker          easier to let the user deal with this.
3189*6be67779SAndroid Build Coastguard Worker       */
3190*6be67779SAndroid Build Coastguard Worker       else if ((0) && parser->m_characterDataHandler)
3191*6be67779SAndroid Build Coastguard Worker         parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3192*6be67779SAndroid Build Coastguard Worker                                        0);
3193*6be67779SAndroid Build Coastguard Worker       /* END disabled code */
3194*6be67779SAndroid Build Coastguard Worker       else if (parser->m_defaultHandler)
3195*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
3196*6be67779SAndroid Build Coastguard Worker       result
3197*6be67779SAndroid Build Coastguard Worker           = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account);
3198*6be67779SAndroid Build Coastguard Worker       if (result != XML_ERROR_NONE)
3199*6be67779SAndroid Build Coastguard Worker         return result;
3200*6be67779SAndroid Build Coastguard Worker       else if (! next) {
3201*6be67779SAndroid Build Coastguard Worker         parser->m_processor = cdataSectionProcessor;
3202*6be67779SAndroid Build Coastguard Worker         return result;
3203*6be67779SAndroid Build Coastguard Worker       }
3204*6be67779SAndroid Build Coastguard Worker     } break;
3205*6be67779SAndroid Build Coastguard Worker     case XML_TOK_TRAILING_RSQB:
3206*6be67779SAndroid Build Coastguard Worker       if (haveMore) {
3207*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
3208*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
3209*6be67779SAndroid Build Coastguard Worker       }
3210*6be67779SAndroid Build Coastguard Worker       if (parser->m_characterDataHandler) {
3211*6be67779SAndroid Build Coastguard Worker         if (MUST_CONVERT(enc, s)) {
3212*6be67779SAndroid Build Coastguard Worker           ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3213*6be67779SAndroid Build Coastguard Worker           XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3214*6be67779SAndroid Build Coastguard Worker           parser->m_characterDataHandler(
3215*6be67779SAndroid Build Coastguard Worker               parser->m_handlerArg, parser->m_dataBuf,
3216*6be67779SAndroid Build Coastguard Worker               (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
3217*6be67779SAndroid Build Coastguard Worker         } else
3218*6be67779SAndroid Build Coastguard Worker           parser->m_characterDataHandler(
3219*6be67779SAndroid Build Coastguard Worker               parser->m_handlerArg, (const XML_Char *)s,
3220*6be67779SAndroid Build Coastguard Worker               (int)((const XML_Char *)end - (const XML_Char *)s));
3221*6be67779SAndroid Build Coastguard Worker       } else if (parser->m_defaultHandler)
3222*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, end);
3223*6be67779SAndroid Build Coastguard Worker       /* We are at the end of the final buffer, should we check for
3224*6be67779SAndroid Build Coastguard Worker          XML_SUSPENDED, XML_FINISHED?
3225*6be67779SAndroid Build Coastguard Worker       */
3226*6be67779SAndroid Build Coastguard Worker       if (startTagLevel == 0) {
3227*6be67779SAndroid Build Coastguard Worker         *eventPP = end;
3228*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_ELEMENTS;
3229*6be67779SAndroid Build Coastguard Worker       }
3230*6be67779SAndroid Build Coastguard Worker       if (parser->m_tagLevel != startTagLevel) {
3231*6be67779SAndroid Build Coastguard Worker         *eventPP = end;
3232*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_ASYNC_ENTITY;
3233*6be67779SAndroid Build Coastguard Worker       }
3234*6be67779SAndroid Build Coastguard Worker       *nextPtr = end;
3235*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
3236*6be67779SAndroid Build Coastguard Worker     case XML_TOK_DATA_CHARS: {
3237*6be67779SAndroid Build Coastguard Worker       XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
3238*6be67779SAndroid Build Coastguard Worker       if (charDataHandler) {
3239*6be67779SAndroid Build Coastguard Worker         if (MUST_CONVERT(enc, s)) {
3240*6be67779SAndroid Build Coastguard Worker           for (;;) {
3241*6be67779SAndroid Build Coastguard Worker             ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3242*6be67779SAndroid Build Coastguard Worker             const enum XML_Convert_Result convert_res = XmlConvert(
3243*6be67779SAndroid Build Coastguard Worker                 enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3244*6be67779SAndroid Build Coastguard Worker             *eventEndPP = s;
3245*6be67779SAndroid Build Coastguard Worker             charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3246*6be67779SAndroid Build Coastguard Worker                             (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
3247*6be67779SAndroid Build Coastguard Worker             if ((convert_res == XML_CONVERT_COMPLETED)
3248*6be67779SAndroid Build Coastguard Worker                 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3249*6be67779SAndroid Build Coastguard Worker               break;
3250*6be67779SAndroid Build Coastguard Worker             *eventPP = s;
3251*6be67779SAndroid Build Coastguard Worker           }
3252*6be67779SAndroid Build Coastguard Worker         } else
3253*6be67779SAndroid Build Coastguard Worker           charDataHandler(parser->m_handlerArg, (const XML_Char *)s,
3254*6be67779SAndroid Build Coastguard Worker                           (int)((const XML_Char *)next - (const XML_Char *)s));
3255*6be67779SAndroid Build Coastguard Worker       } else if (parser->m_defaultHandler)
3256*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
3257*6be67779SAndroid Build Coastguard Worker     } break;
3258*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PI:
3259*6be67779SAndroid Build Coastguard Worker       if (! reportProcessingInstruction(parser, enc, s, next))
3260*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
3261*6be67779SAndroid Build Coastguard Worker       break;
3262*6be67779SAndroid Build Coastguard Worker     case XML_TOK_COMMENT:
3263*6be67779SAndroid Build Coastguard Worker       if (! reportComment(parser, enc, s, next))
3264*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
3265*6be67779SAndroid Build Coastguard Worker       break;
3266*6be67779SAndroid Build Coastguard Worker     default:
3267*6be67779SAndroid Build Coastguard Worker       /* All of the tokens produced by XmlContentTok() have their own
3268*6be67779SAndroid Build Coastguard Worker        * explicit cases, so this default is not strictly necessary.
3269*6be67779SAndroid Build Coastguard Worker        * However it is a useful safety net, so we retain the code and
3270*6be67779SAndroid Build Coastguard Worker        * simply exclude it from the coverage tests.
3271*6be67779SAndroid Build Coastguard Worker        *
3272*6be67779SAndroid Build Coastguard Worker        * LCOV_EXCL_START
3273*6be67779SAndroid Build Coastguard Worker        */
3274*6be67779SAndroid Build Coastguard Worker       if (parser->m_defaultHandler)
3275*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
3276*6be67779SAndroid Build Coastguard Worker       break;
3277*6be67779SAndroid Build Coastguard Worker       /* LCOV_EXCL_STOP */
3278*6be67779SAndroid Build Coastguard Worker     }
3279*6be67779SAndroid Build Coastguard Worker     *eventPP = s = next;
3280*6be67779SAndroid Build Coastguard Worker     switch (parser->m_parsingStatus.parsing) {
3281*6be67779SAndroid Build Coastguard Worker     case XML_SUSPENDED:
3282*6be67779SAndroid Build Coastguard Worker       *nextPtr = next;
3283*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
3284*6be67779SAndroid Build Coastguard Worker     case XML_FINISHED:
3285*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_ABORTED;
3286*6be67779SAndroid Build Coastguard Worker     default:;
3287*6be67779SAndroid Build Coastguard Worker     }
3288*6be67779SAndroid Build Coastguard Worker   }
3289*6be67779SAndroid Build Coastguard Worker   /* not reached */
3290*6be67779SAndroid Build Coastguard Worker }
3291*6be67779SAndroid Build Coastguard Worker 
3292*6be67779SAndroid Build Coastguard Worker /* This function does not call free() on the allocated memory, merely
3293*6be67779SAndroid Build Coastguard Worker  * moving it to the parser's m_freeBindingList where it can be freed or
3294*6be67779SAndroid Build Coastguard Worker  * reused as appropriate.
3295*6be67779SAndroid Build Coastguard Worker  */
3296*6be67779SAndroid Build Coastguard Worker static void
freeBindings(XML_Parser parser,BINDING * bindings)3297*6be67779SAndroid Build Coastguard Worker freeBindings(XML_Parser parser, BINDING *bindings) {
3298*6be67779SAndroid Build Coastguard Worker   while (bindings) {
3299*6be67779SAndroid Build Coastguard Worker     BINDING *b = bindings;
3300*6be67779SAndroid Build Coastguard Worker 
3301*6be67779SAndroid Build Coastguard Worker     /* m_startNamespaceDeclHandler will have been called for this
3302*6be67779SAndroid Build Coastguard Worker      * binding in addBindings(), so call the end handler now.
3303*6be67779SAndroid Build Coastguard Worker      */
3304*6be67779SAndroid Build Coastguard Worker     if (parser->m_endNamespaceDeclHandler)
3305*6be67779SAndroid Build Coastguard Worker       parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
3306*6be67779SAndroid Build Coastguard Worker 
3307*6be67779SAndroid Build Coastguard Worker     bindings = bindings->nextTagBinding;
3308*6be67779SAndroid Build Coastguard Worker     b->nextTagBinding = parser->m_freeBindingList;
3309*6be67779SAndroid Build Coastguard Worker     parser->m_freeBindingList = b;
3310*6be67779SAndroid Build Coastguard Worker     b->prefix->binding = b->prevPrefixBinding;
3311*6be67779SAndroid Build Coastguard Worker   }
3312*6be67779SAndroid Build Coastguard Worker }
3313*6be67779SAndroid Build Coastguard Worker 
3314*6be67779SAndroid Build Coastguard Worker /* Precondition: all arguments must be non-NULL;
3315*6be67779SAndroid Build Coastguard Worker    Purpose:
3316*6be67779SAndroid Build Coastguard Worker    - normalize attributes
3317*6be67779SAndroid Build Coastguard Worker    - check attributes for well-formedness
3318*6be67779SAndroid Build Coastguard Worker    - generate namespace aware attribute names (URI, prefix)
3319*6be67779SAndroid Build Coastguard Worker    - build list of attributes for startElementHandler
3320*6be67779SAndroid Build Coastguard Worker    - default attributes
3321*6be67779SAndroid Build Coastguard Worker    - process namespace declarations (check and report them)
3322*6be67779SAndroid Build Coastguard Worker    - generate namespace aware element name (URI, prefix)
3323*6be67779SAndroid Build Coastguard Worker */
3324*6be67779SAndroid Build Coastguard Worker static enum XML_Error
storeAtts(XML_Parser parser,const ENCODING * enc,const char * attStr,TAG_NAME * tagNamePtr,BINDING ** bindingsPtr,enum XML_Account account)3325*6be67779SAndroid Build Coastguard Worker storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
3326*6be67779SAndroid Build Coastguard Worker           TAG_NAME *tagNamePtr, BINDING **bindingsPtr,
3327*6be67779SAndroid Build Coastguard Worker           enum XML_Account account) {
3328*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
3329*6be67779SAndroid Build Coastguard Worker   ELEMENT_TYPE *elementType;
3330*6be67779SAndroid Build Coastguard Worker   int nDefaultAtts;
3331*6be67779SAndroid Build Coastguard Worker   const XML_Char **appAtts; /* the attribute list for the application */
3332*6be67779SAndroid Build Coastguard Worker   int attIndex = 0;
3333*6be67779SAndroid Build Coastguard Worker   int prefixLen;
3334*6be67779SAndroid Build Coastguard Worker   int i;
3335*6be67779SAndroid Build Coastguard Worker   int n;
3336*6be67779SAndroid Build Coastguard Worker   XML_Char *uri;
3337*6be67779SAndroid Build Coastguard Worker   int nPrefixes = 0;
3338*6be67779SAndroid Build Coastguard Worker   BINDING *binding;
3339*6be67779SAndroid Build Coastguard Worker   const XML_Char *localPart;
3340*6be67779SAndroid Build Coastguard Worker 
3341*6be67779SAndroid Build Coastguard Worker   /* lookup the element type name */
3342*6be67779SAndroid Build Coastguard Worker   elementType
3343*6be67779SAndroid Build Coastguard Worker       = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str, 0);
3344*6be67779SAndroid Build Coastguard Worker   if (! elementType) {
3345*6be67779SAndroid Build Coastguard Worker     const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
3346*6be67779SAndroid Build Coastguard Worker     if (! name)
3347*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3348*6be67779SAndroid Build Coastguard Worker     elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
3349*6be67779SAndroid Build Coastguard Worker                                          sizeof(ELEMENT_TYPE));
3350*6be67779SAndroid Build Coastguard Worker     if (! elementType)
3351*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3352*6be67779SAndroid Build Coastguard Worker     if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
3353*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3354*6be67779SAndroid Build Coastguard Worker   }
3355*6be67779SAndroid Build Coastguard Worker   nDefaultAtts = elementType->nDefaultAtts;
3356*6be67779SAndroid Build Coastguard Worker 
3357*6be67779SAndroid Build Coastguard Worker   /* get the attributes from the tokenizer */
3358*6be67779SAndroid Build Coastguard Worker   n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
3359*6be67779SAndroid Build Coastguard Worker 
3360*6be67779SAndroid Build Coastguard Worker   /* Detect and prevent integer overflow */
3361*6be67779SAndroid Build Coastguard Worker   if (n > INT_MAX - nDefaultAtts) {
3362*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_NO_MEMORY;
3363*6be67779SAndroid Build Coastguard Worker   }
3364*6be67779SAndroid Build Coastguard Worker 
3365*6be67779SAndroid Build Coastguard Worker   if (n + nDefaultAtts > parser->m_attsSize) {
3366*6be67779SAndroid Build Coastguard Worker     int oldAttsSize = parser->m_attsSize;
3367*6be67779SAndroid Build Coastguard Worker     ATTRIBUTE *temp;
3368*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
3369*6be67779SAndroid Build Coastguard Worker     XML_AttrInfo *temp2;
3370*6be67779SAndroid Build Coastguard Worker #endif
3371*6be67779SAndroid Build Coastguard Worker 
3372*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow */
3373*6be67779SAndroid Build Coastguard Worker     if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE)
3374*6be67779SAndroid Build Coastguard Worker         || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
3375*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3376*6be67779SAndroid Build Coastguard Worker     }
3377*6be67779SAndroid Build Coastguard Worker 
3378*6be67779SAndroid Build Coastguard Worker     parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
3379*6be67779SAndroid Build Coastguard Worker 
3380*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow.
3381*6be67779SAndroid Build Coastguard Worker      * The preprocessor guard addresses the "always false" warning
3382*6be67779SAndroid Build Coastguard Worker      * from -Wtype-limits on platforms where
3383*6be67779SAndroid Build Coastguard Worker      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3384*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
3385*6be67779SAndroid Build Coastguard Worker     if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) {
3386*6be67779SAndroid Build Coastguard Worker       parser->m_attsSize = oldAttsSize;
3387*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3388*6be67779SAndroid Build Coastguard Worker     }
3389*6be67779SAndroid Build Coastguard Worker #endif
3390*6be67779SAndroid Build Coastguard Worker 
3391*6be67779SAndroid Build Coastguard Worker     temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
3392*6be67779SAndroid Build Coastguard Worker                                 parser->m_attsSize * sizeof(ATTRIBUTE));
3393*6be67779SAndroid Build Coastguard Worker     if (temp == NULL) {
3394*6be67779SAndroid Build Coastguard Worker       parser->m_attsSize = oldAttsSize;
3395*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3396*6be67779SAndroid Build Coastguard Worker     }
3397*6be67779SAndroid Build Coastguard Worker     parser->m_atts = temp;
3398*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
3399*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow.
3400*6be67779SAndroid Build Coastguard Worker      * The preprocessor guard addresses the "always false" warning
3401*6be67779SAndroid Build Coastguard Worker      * from -Wtype-limits on platforms where
3402*6be67779SAndroid Build Coastguard Worker      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3403*6be67779SAndroid Build Coastguard Worker #  if UINT_MAX >= SIZE_MAX
3404*6be67779SAndroid Build Coastguard Worker     if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) {
3405*6be67779SAndroid Build Coastguard Worker       parser->m_attsSize = oldAttsSize;
3406*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3407*6be67779SAndroid Build Coastguard Worker     }
3408*6be67779SAndroid Build Coastguard Worker #  endif
3409*6be67779SAndroid Build Coastguard Worker 
3410*6be67779SAndroid Build Coastguard Worker     temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
3411*6be67779SAndroid Build Coastguard Worker                                     parser->m_attsSize * sizeof(XML_AttrInfo));
3412*6be67779SAndroid Build Coastguard Worker     if (temp2 == NULL) {
3413*6be67779SAndroid Build Coastguard Worker       parser->m_attsSize = oldAttsSize;
3414*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3415*6be67779SAndroid Build Coastguard Worker     }
3416*6be67779SAndroid Build Coastguard Worker     parser->m_attInfo = temp2;
3417*6be67779SAndroid Build Coastguard Worker #endif
3418*6be67779SAndroid Build Coastguard Worker     if (n > oldAttsSize)
3419*6be67779SAndroid Build Coastguard Worker       XmlGetAttributes(enc, attStr, n, parser->m_atts);
3420*6be67779SAndroid Build Coastguard Worker   }
3421*6be67779SAndroid Build Coastguard Worker 
3422*6be67779SAndroid Build Coastguard Worker   appAtts = (const XML_Char **)parser->m_atts;
3423*6be67779SAndroid Build Coastguard Worker   for (i = 0; i < n; i++) {
3424*6be67779SAndroid Build Coastguard Worker     ATTRIBUTE *currAtt = &parser->m_atts[i];
3425*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
3426*6be67779SAndroid Build Coastguard Worker     XML_AttrInfo *currAttInfo = &parser->m_attInfo[i];
3427*6be67779SAndroid Build Coastguard Worker #endif
3428*6be67779SAndroid Build Coastguard Worker     /* add the name and value to the attribute list */
3429*6be67779SAndroid Build Coastguard Worker     ATTRIBUTE_ID *attId
3430*6be67779SAndroid Build Coastguard Worker         = getAttributeId(parser, enc, currAtt->name,
3431*6be67779SAndroid Build Coastguard Worker                          currAtt->name + XmlNameLength(enc, currAtt->name));
3432*6be67779SAndroid Build Coastguard Worker     if (! attId)
3433*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3434*6be67779SAndroid Build Coastguard Worker #ifdef XML_ATTR_INFO
3435*6be67779SAndroid Build Coastguard Worker     currAttInfo->nameStart
3436*6be67779SAndroid Build Coastguard Worker         = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name);
3437*6be67779SAndroid Build Coastguard Worker     currAttInfo->nameEnd
3438*6be67779SAndroid Build Coastguard Worker         = currAttInfo->nameStart + XmlNameLength(enc, currAtt->name);
3439*6be67779SAndroid Build Coastguard Worker     currAttInfo->valueStart = parser->m_parseEndByteIndex
3440*6be67779SAndroid Build Coastguard Worker                               - (parser->m_parseEndPtr - currAtt->valuePtr);
3441*6be67779SAndroid Build Coastguard Worker     currAttInfo->valueEnd = parser->m_parseEndByteIndex
3442*6be67779SAndroid Build Coastguard Worker                             - (parser->m_parseEndPtr - currAtt->valueEnd);
3443*6be67779SAndroid Build Coastguard Worker #endif
3444*6be67779SAndroid Build Coastguard Worker     /* Detect duplicate attributes by their QNames. This does not work when
3445*6be67779SAndroid Build Coastguard Worker        namespace processing is turned on and different prefixes for the same
3446*6be67779SAndroid Build Coastguard Worker        namespace are used. For this case we have a check further down.
3447*6be67779SAndroid Build Coastguard Worker     */
3448*6be67779SAndroid Build Coastguard Worker     if ((attId->name)[-1]) {
3449*6be67779SAndroid Build Coastguard Worker       if (enc == parser->m_encoding)
3450*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = parser->m_atts[i].name;
3451*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_DUPLICATE_ATTRIBUTE;
3452*6be67779SAndroid Build Coastguard Worker     }
3453*6be67779SAndroid Build Coastguard Worker     (attId->name)[-1] = 1;
3454*6be67779SAndroid Build Coastguard Worker     appAtts[attIndex++] = attId->name;
3455*6be67779SAndroid Build Coastguard Worker     if (! parser->m_atts[i].normalized) {
3456*6be67779SAndroid Build Coastguard Worker       enum XML_Error result;
3457*6be67779SAndroid Build Coastguard Worker       XML_Bool isCdata = XML_TRUE;
3458*6be67779SAndroid Build Coastguard Worker 
3459*6be67779SAndroid Build Coastguard Worker       /* figure out whether declared as other than CDATA */
3460*6be67779SAndroid Build Coastguard Worker       if (attId->maybeTokenized) {
3461*6be67779SAndroid Build Coastguard Worker         int j;
3462*6be67779SAndroid Build Coastguard Worker         for (j = 0; j < nDefaultAtts; j++) {
3463*6be67779SAndroid Build Coastguard Worker           if (attId == elementType->defaultAtts[j].id) {
3464*6be67779SAndroid Build Coastguard Worker             isCdata = elementType->defaultAtts[j].isCdata;
3465*6be67779SAndroid Build Coastguard Worker             break;
3466*6be67779SAndroid Build Coastguard Worker           }
3467*6be67779SAndroid Build Coastguard Worker         }
3468*6be67779SAndroid Build Coastguard Worker       }
3469*6be67779SAndroid Build Coastguard Worker 
3470*6be67779SAndroid Build Coastguard Worker       /* normalize the attribute value */
3471*6be67779SAndroid Build Coastguard Worker       result = storeAttributeValue(
3472*6be67779SAndroid Build Coastguard Worker           parser, enc, isCdata, parser->m_atts[i].valuePtr,
3473*6be67779SAndroid Build Coastguard Worker           parser->m_atts[i].valueEnd, &parser->m_tempPool, account);
3474*6be67779SAndroid Build Coastguard Worker       if (result)
3475*6be67779SAndroid Build Coastguard Worker         return result;
3476*6be67779SAndroid Build Coastguard Worker       appAtts[attIndex] = poolStart(&parser->m_tempPool);
3477*6be67779SAndroid Build Coastguard Worker       poolFinish(&parser->m_tempPool);
3478*6be67779SAndroid Build Coastguard Worker     } else {
3479*6be67779SAndroid Build Coastguard Worker       /* the value did not need normalizing */
3480*6be67779SAndroid Build Coastguard Worker       appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc,
3481*6be67779SAndroid Build Coastguard Worker                                           parser->m_atts[i].valuePtr,
3482*6be67779SAndroid Build Coastguard Worker                                           parser->m_atts[i].valueEnd);
3483*6be67779SAndroid Build Coastguard Worker       if (appAtts[attIndex] == 0)
3484*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
3485*6be67779SAndroid Build Coastguard Worker       poolFinish(&parser->m_tempPool);
3486*6be67779SAndroid Build Coastguard Worker     }
3487*6be67779SAndroid Build Coastguard Worker     /* handle prefixed attribute names */
3488*6be67779SAndroid Build Coastguard Worker     if (attId->prefix) {
3489*6be67779SAndroid Build Coastguard Worker       if (attId->xmlns) {
3490*6be67779SAndroid Build Coastguard Worker         /* deal with namespace declarations here */
3491*6be67779SAndroid Build Coastguard Worker         enum XML_Error result = addBinding(parser, attId->prefix, attId,
3492*6be67779SAndroid Build Coastguard Worker                                            appAtts[attIndex], bindingsPtr);
3493*6be67779SAndroid Build Coastguard Worker         if (result)
3494*6be67779SAndroid Build Coastguard Worker           return result;
3495*6be67779SAndroid Build Coastguard Worker         --attIndex;
3496*6be67779SAndroid Build Coastguard Worker       } else {
3497*6be67779SAndroid Build Coastguard Worker         /* deal with other prefixed names later */
3498*6be67779SAndroid Build Coastguard Worker         attIndex++;
3499*6be67779SAndroid Build Coastguard Worker         nPrefixes++;
3500*6be67779SAndroid Build Coastguard Worker         (attId->name)[-1] = 2;
3501*6be67779SAndroid Build Coastguard Worker       }
3502*6be67779SAndroid Build Coastguard Worker     } else
3503*6be67779SAndroid Build Coastguard Worker       attIndex++;
3504*6be67779SAndroid Build Coastguard Worker   }
3505*6be67779SAndroid Build Coastguard Worker 
3506*6be67779SAndroid Build Coastguard Worker   /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
3507*6be67779SAndroid Build Coastguard Worker   parser->m_nSpecifiedAtts = attIndex;
3508*6be67779SAndroid Build Coastguard Worker   if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
3509*6be67779SAndroid Build Coastguard Worker     for (i = 0; i < attIndex; i += 2)
3510*6be67779SAndroid Build Coastguard Worker       if (appAtts[i] == elementType->idAtt->name) {
3511*6be67779SAndroid Build Coastguard Worker         parser->m_idAttIndex = i;
3512*6be67779SAndroid Build Coastguard Worker         break;
3513*6be67779SAndroid Build Coastguard Worker       }
3514*6be67779SAndroid Build Coastguard Worker   } else
3515*6be67779SAndroid Build Coastguard Worker     parser->m_idAttIndex = -1;
3516*6be67779SAndroid Build Coastguard Worker 
3517*6be67779SAndroid Build Coastguard Worker   /* do attribute defaulting */
3518*6be67779SAndroid Build Coastguard Worker   for (i = 0; i < nDefaultAtts; i++) {
3519*6be67779SAndroid Build Coastguard Worker     const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
3520*6be67779SAndroid Build Coastguard Worker     if (! (da->id->name)[-1] && da->value) {
3521*6be67779SAndroid Build Coastguard Worker       if (da->id->prefix) {
3522*6be67779SAndroid Build Coastguard Worker         if (da->id->xmlns) {
3523*6be67779SAndroid Build Coastguard Worker           enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
3524*6be67779SAndroid Build Coastguard Worker                                              da->value, bindingsPtr);
3525*6be67779SAndroid Build Coastguard Worker           if (result)
3526*6be67779SAndroid Build Coastguard Worker             return result;
3527*6be67779SAndroid Build Coastguard Worker         } else {
3528*6be67779SAndroid Build Coastguard Worker           (da->id->name)[-1] = 2;
3529*6be67779SAndroid Build Coastguard Worker           nPrefixes++;
3530*6be67779SAndroid Build Coastguard Worker           appAtts[attIndex++] = da->id->name;
3531*6be67779SAndroid Build Coastguard Worker           appAtts[attIndex++] = da->value;
3532*6be67779SAndroid Build Coastguard Worker         }
3533*6be67779SAndroid Build Coastguard Worker       } else {
3534*6be67779SAndroid Build Coastguard Worker         (da->id->name)[-1] = 1;
3535*6be67779SAndroid Build Coastguard Worker         appAtts[attIndex++] = da->id->name;
3536*6be67779SAndroid Build Coastguard Worker         appAtts[attIndex++] = da->value;
3537*6be67779SAndroid Build Coastguard Worker       }
3538*6be67779SAndroid Build Coastguard Worker     }
3539*6be67779SAndroid Build Coastguard Worker   }
3540*6be67779SAndroid Build Coastguard Worker   appAtts[attIndex] = 0;
3541*6be67779SAndroid Build Coastguard Worker 
3542*6be67779SAndroid Build Coastguard Worker   /* expand prefixed attribute names, check for duplicates,
3543*6be67779SAndroid Build Coastguard Worker      and clear flags that say whether attributes were specified */
3544*6be67779SAndroid Build Coastguard Worker   i = 0;
3545*6be67779SAndroid Build Coastguard Worker   if (nPrefixes) {
3546*6be67779SAndroid Build Coastguard Worker     int j; /* hash table index */
3547*6be67779SAndroid Build Coastguard Worker     unsigned long version = parser->m_nsAttsVersion;
3548*6be67779SAndroid Build Coastguard Worker 
3549*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent invalid shift */
3550*6be67779SAndroid Build Coastguard Worker     if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
3551*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3552*6be67779SAndroid Build Coastguard Worker     }
3553*6be67779SAndroid Build Coastguard Worker 
3554*6be67779SAndroid Build Coastguard Worker     unsigned int nsAttsSize = 1u << parser->m_nsAttsPower;
3555*6be67779SAndroid Build Coastguard Worker     unsigned char oldNsAttsPower = parser->m_nsAttsPower;
3556*6be67779SAndroid Build Coastguard Worker     /* size of hash table must be at least 2 * (# of prefixed attributes) */
3557*6be67779SAndroid Build Coastguard Worker     if ((nPrefixes << 1)
3558*6be67779SAndroid Build Coastguard Worker         >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
3559*6be67779SAndroid Build Coastguard Worker       NS_ATT *temp;
3560*6be67779SAndroid Build Coastguard Worker       /* hash table size must also be a power of 2 and >= 8 */
3561*6be67779SAndroid Build Coastguard Worker       while (nPrefixes >> parser->m_nsAttsPower++)
3562*6be67779SAndroid Build Coastguard Worker         ;
3563*6be67779SAndroid Build Coastguard Worker       if (parser->m_nsAttsPower < 3)
3564*6be67779SAndroid Build Coastguard Worker         parser->m_nsAttsPower = 3;
3565*6be67779SAndroid Build Coastguard Worker 
3566*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent invalid shift */
3567*6be67779SAndroid Build Coastguard Worker       if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) {
3568*6be67779SAndroid Build Coastguard Worker         /* Restore actual size of memory in m_nsAtts */
3569*6be67779SAndroid Build Coastguard Worker         parser->m_nsAttsPower = oldNsAttsPower;
3570*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
3571*6be67779SAndroid Build Coastguard Worker       }
3572*6be67779SAndroid Build Coastguard Worker 
3573*6be67779SAndroid Build Coastguard Worker       nsAttsSize = 1u << parser->m_nsAttsPower;
3574*6be67779SAndroid Build Coastguard Worker 
3575*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent integer overflow.
3576*6be67779SAndroid Build Coastguard Worker        * The preprocessor guard addresses the "always false" warning
3577*6be67779SAndroid Build Coastguard Worker        * from -Wtype-limits on platforms where
3578*6be67779SAndroid Build Coastguard Worker        * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3579*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
3580*6be67779SAndroid Build Coastguard Worker       if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) {
3581*6be67779SAndroid Build Coastguard Worker         /* Restore actual size of memory in m_nsAtts */
3582*6be67779SAndroid Build Coastguard Worker         parser->m_nsAttsPower = oldNsAttsPower;
3583*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
3584*6be67779SAndroid Build Coastguard Worker       }
3585*6be67779SAndroid Build Coastguard Worker #endif
3586*6be67779SAndroid Build Coastguard Worker 
3587*6be67779SAndroid Build Coastguard Worker       temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
3588*6be67779SAndroid Build Coastguard Worker                                nsAttsSize * sizeof(NS_ATT));
3589*6be67779SAndroid Build Coastguard Worker       if (! temp) {
3590*6be67779SAndroid Build Coastguard Worker         /* Restore actual size of memory in m_nsAtts */
3591*6be67779SAndroid Build Coastguard Worker         parser->m_nsAttsPower = oldNsAttsPower;
3592*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
3593*6be67779SAndroid Build Coastguard Worker       }
3594*6be67779SAndroid Build Coastguard Worker       parser->m_nsAtts = temp;
3595*6be67779SAndroid Build Coastguard Worker       version = 0; /* force re-initialization of m_nsAtts hash table */
3596*6be67779SAndroid Build Coastguard Worker     }
3597*6be67779SAndroid Build Coastguard Worker     /* using a version flag saves us from initializing m_nsAtts every time */
3598*6be67779SAndroid Build Coastguard Worker     if (! version) { /* initialize version flags when version wraps around */
3599*6be67779SAndroid Build Coastguard Worker       version = INIT_ATTS_VERSION;
3600*6be67779SAndroid Build Coastguard Worker       for (j = nsAttsSize; j != 0;)
3601*6be67779SAndroid Build Coastguard Worker         parser->m_nsAtts[--j].version = version;
3602*6be67779SAndroid Build Coastguard Worker     }
3603*6be67779SAndroid Build Coastguard Worker     parser->m_nsAttsVersion = --version;
3604*6be67779SAndroid Build Coastguard Worker 
3605*6be67779SAndroid Build Coastguard Worker     /* expand prefixed names and check for duplicates */
3606*6be67779SAndroid Build Coastguard Worker     for (; i < attIndex; i += 2) {
3607*6be67779SAndroid Build Coastguard Worker       const XML_Char *s = appAtts[i];
3608*6be67779SAndroid Build Coastguard Worker       if (s[-1] == 2) { /* prefixed */
3609*6be67779SAndroid Build Coastguard Worker         ATTRIBUTE_ID *id;
3610*6be67779SAndroid Build Coastguard Worker         const BINDING *b;
3611*6be67779SAndroid Build Coastguard Worker         unsigned long uriHash;
3612*6be67779SAndroid Build Coastguard Worker         struct siphash sip_state;
3613*6be67779SAndroid Build Coastguard Worker         struct sipkey sip_key;
3614*6be67779SAndroid Build Coastguard Worker 
3615*6be67779SAndroid Build Coastguard Worker         copy_salt_to_sipkey(parser, &sip_key);
3616*6be67779SAndroid Build Coastguard Worker         sip24_init(&sip_state, &sip_key);
3617*6be67779SAndroid Build Coastguard Worker 
3618*6be67779SAndroid Build Coastguard Worker         ((XML_Char *)s)[-1] = 0; /* clear flag */
3619*6be67779SAndroid Build Coastguard Worker         id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
3620*6be67779SAndroid Build Coastguard Worker         if (! id || ! id->prefix) {
3621*6be67779SAndroid Build Coastguard Worker           /* This code is walking through the appAtts array, dealing
3622*6be67779SAndroid Build Coastguard Worker            * with (in this case) a prefixed attribute name.  To be in
3623*6be67779SAndroid Build Coastguard Worker            * the array, the attribute must have already been bound, so
3624*6be67779SAndroid Build Coastguard Worker            * has to have passed through the hash table lookup once
3625*6be67779SAndroid Build Coastguard Worker            * already.  That implies that an entry for it already
3626*6be67779SAndroid Build Coastguard Worker            * exists, so the lookup above will return a pointer to
3627*6be67779SAndroid Build Coastguard Worker            * already allocated memory.  There is no opportunaity for
3628*6be67779SAndroid Build Coastguard Worker            * the allocator to fail, so the condition above cannot be
3629*6be67779SAndroid Build Coastguard Worker            * fulfilled.
3630*6be67779SAndroid Build Coastguard Worker            *
3631*6be67779SAndroid Build Coastguard Worker            * Since it is difficult to be certain that the above
3632*6be67779SAndroid Build Coastguard Worker            * analysis is complete, we retain the test and merely
3633*6be67779SAndroid Build Coastguard Worker            * remove the code from coverage tests.
3634*6be67779SAndroid Build Coastguard Worker            */
3635*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
3636*6be67779SAndroid Build Coastguard Worker         }
3637*6be67779SAndroid Build Coastguard Worker         b = id->prefix->binding;
3638*6be67779SAndroid Build Coastguard Worker         if (! b)
3639*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_UNBOUND_PREFIX;
3640*6be67779SAndroid Build Coastguard Worker 
3641*6be67779SAndroid Build Coastguard Worker         for (j = 0; j < b->uriLen; j++) {
3642*6be67779SAndroid Build Coastguard Worker           const XML_Char c = b->uri[j];
3643*6be67779SAndroid Build Coastguard Worker           if (! poolAppendChar(&parser->m_tempPool, c))
3644*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_NO_MEMORY;
3645*6be67779SAndroid Build Coastguard Worker         }
3646*6be67779SAndroid Build Coastguard Worker 
3647*6be67779SAndroid Build Coastguard Worker         sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
3648*6be67779SAndroid Build Coastguard Worker 
3649*6be67779SAndroid Build Coastguard Worker         while (*s++ != XML_T(ASCII_COLON))
3650*6be67779SAndroid Build Coastguard Worker           ;
3651*6be67779SAndroid Build Coastguard Worker 
3652*6be67779SAndroid Build Coastguard Worker         sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
3653*6be67779SAndroid Build Coastguard Worker 
3654*6be67779SAndroid Build Coastguard Worker         do { /* copies null terminator */
3655*6be67779SAndroid Build Coastguard Worker           if (! poolAppendChar(&parser->m_tempPool, *s))
3656*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_NO_MEMORY;
3657*6be67779SAndroid Build Coastguard Worker         } while (*s++);
3658*6be67779SAndroid Build Coastguard Worker 
3659*6be67779SAndroid Build Coastguard Worker         uriHash = (unsigned long)sip24_final(&sip_state);
3660*6be67779SAndroid Build Coastguard Worker 
3661*6be67779SAndroid Build Coastguard Worker         { /* Check hash table for duplicate of expanded name (uriName).
3662*6be67779SAndroid Build Coastguard Worker              Derived from code in lookup(parser, HASH_TABLE *table, ...).
3663*6be67779SAndroid Build Coastguard Worker           */
3664*6be67779SAndroid Build Coastguard Worker           unsigned char step = 0;
3665*6be67779SAndroid Build Coastguard Worker           unsigned long mask = nsAttsSize - 1;
3666*6be67779SAndroid Build Coastguard Worker           j = uriHash & mask; /* index into hash table */
3667*6be67779SAndroid Build Coastguard Worker           while (parser->m_nsAtts[j].version == version) {
3668*6be67779SAndroid Build Coastguard Worker             /* for speed we compare stored hash values first */
3669*6be67779SAndroid Build Coastguard Worker             if (uriHash == parser->m_nsAtts[j].hash) {
3670*6be67779SAndroid Build Coastguard Worker               const XML_Char *s1 = poolStart(&parser->m_tempPool);
3671*6be67779SAndroid Build Coastguard Worker               const XML_Char *s2 = parser->m_nsAtts[j].uriName;
3672*6be67779SAndroid Build Coastguard Worker               /* s1 is null terminated, but not s2 */
3673*6be67779SAndroid Build Coastguard Worker               for (; *s1 == *s2 && *s1 != 0; s1++, s2++)
3674*6be67779SAndroid Build Coastguard Worker                 ;
3675*6be67779SAndroid Build Coastguard Worker               if (*s1 == 0)
3676*6be67779SAndroid Build Coastguard Worker                 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3677*6be67779SAndroid Build Coastguard Worker             }
3678*6be67779SAndroid Build Coastguard Worker             if (! step)
3679*6be67779SAndroid Build Coastguard Worker               step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower);
3680*6be67779SAndroid Build Coastguard Worker             j < step ? (j += nsAttsSize - step) : (j -= step);
3681*6be67779SAndroid Build Coastguard Worker           }
3682*6be67779SAndroid Build Coastguard Worker         }
3683*6be67779SAndroid Build Coastguard Worker 
3684*6be67779SAndroid Build Coastguard Worker         if (parser->m_ns_triplets) { /* append namespace separator and prefix */
3685*6be67779SAndroid Build Coastguard Worker           parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator;
3686*6be67779SAndroid Build Coastguard Worker           s = b->prefix->name;
3687*6be67779SAndroid Build Coastguard Worker           do {
3688*6be67779SAndroid Build Coastguard Worker             if (! poolAppendChar(&parser->m_tempPool, *s))
3689*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NO_MEMORY;
3690*6be67779SAndroid Build Coastguard Worker           } while (*s++);
3691*6be67779SAndroid Build Coastguard Worker         }
3692*6be67779SAndroid Build Coastguard Worker 
3693*6be67779SAndroid Build Coastguard Worker         /* store expanded name in attribute list */
3694*6be67779SAndroid Build Coastguard Worker         s = poolStart(&parser->m_tempPool);
3695*6be67779SAndroid Build Coastguard Worker         poolFinish(&parser->m_tempPool);
3696*6be67779SAndroid Build Coastguard Worker         appAtts[i] = s;
3697*6be67779SAndroid Build Coastguard Worker 
3698*6be67779SAndroid Build Coastguard Worker         /* fill empty slot with new version, uriName and hash value */
3699*6be67779SAndroid Build Coastguard Worker         parser->m_nsAtts[j].version = version;
3700*6be67779SAndroid Build Coastguard Worker         parser->m_nsAtts[j].hash = uriHash;
3701*6be67779SAndroid Build Coastguard Worker         parser->m_nsAtts[j].uriName = s;
3702*6be67779SAndroid Build Coastguard Worker 
3703*6be67779SAndroid Build Coastguard Worker         if (! --nPrefixes) {
3704*6be67779SAndroid Build Coastguard Worker           i += 2;
3705*6be67779SAndroid Build Coastguard Worker           break;
3706*6be67779SAndroid Build Coastguard Worker         }
3707*6be67779SAndroid Build Coastguard Worker       } else                     /* not prefixed */
3708*6be67779SAndroid Build Coastguard Worker         ((XML_Char *)s)[-1] = 0; /* clear flag */
3709*6be67779SAndroid Build Coastguard Worker     }
3710*6be67779SAndroid Build Coastguard Worker   }
3711*6be67779SAndroid Build Coastguard Worker   /* clear flags for the remaining attributes */
3712*6be67779SAndroid Build Coastguard Worker   for (; i < attIndex; i += 2)
3713*6be67779SAndroid Build Coastguard Worker     ((XML_Char *)(appAtts[i]))[-1] = 0;
3714*6be67779SAndroid Build Coastguard Worker   for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3715*6be67779SAndroid Build Coastguard Worker     binding->attId->name[-1] = 0;
3716*6be67779SAndroid Build Coastguard Worker 
3717*6be67779SAndroid Build Coastguard Worker   if (! parser->m_ns)
3718*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_NONE;
3719*6be67779SAndroid Build Coastguard Worker 
3720*6be67779SAndroid Build Coastguard Worker   /* expand the element type name */
3721*6be67779SAndroid Build Coastguard Worker   if (elementType->prefix) {
3722*6be67779SAndroid Build Coastguard Worker     binding = elementType->prefix->binding;
3723*6be67779SAndroid Build Coastguard Worker     if (! binding)
3724*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_UNBOUND_PREFIX;
3725*6be67779SAndroid Build Coastguard Worker     localPart = tagNamePtr->str;
3726*6be67779SAndroid Build Coastguard Worker     while (*localPart++ != XML_T(ASCII_COLON))
3727*6be67779SAndroid Build Coastguard Worker       ;
3728*6be67779SAndroid Build Coastguard Worker   } else if (dtd->defaultPrefix.binding) {
3729*6be67779SAndroid Build Coastguard Worker     binding = dtd->defaultPrefix.binding;
3730*6be67779SAndroid Build Coastguard Worker     localPart = tagNamePtr->str;
3731*6be67779SAndroid Build Coastguard Worker   } else
3732*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_NONE;
3733*6be67779SAndroid Build Coastguard Worker   prefixLen = 0;
3734*6be67779SAndroid Build Coastguard Worker   if (parser->m_ns_triplets && binding->prefix->name) {
3735*6be67779SAndroid Build Coastguard Worker     for (; binding->prefix->name[prefixLen++];)
3736*6be67779SAndroid Build Coastguard Worker       ; /* prefixLen includes null terminator */
3737*6be67779SAndroid Build Coastguard Worker   }
3738*6be67779SAndroid Build Coastguard Worker   tagNamePtr->localPart = localPart;
3739*6be67779SAndroid Build Coastguard Worker   tagNamePtr->uriLen = binding->uriLen;
3740*6be67779SAndroid Build Coastguard Worker   tagNamePtr->prefix = binding->prefix->name;
3741*6be67779SAndroid Build Coastguard Worker   tagNamePtr->prefixLen = prefixLen;
3742*6be67779SAndroid Build Coastguard Worker   for (i = 0; localPart[i++];)
3743*6be67779SAndroid Build Coastguard Worker     ; /* i includes null terminator */
3744*6be67779SAndroid Build Coastguard Worker 
3745*6be67779SAndroid Build Coastguard Worker   /* Detect and prevent integer overflow */
3746*6be67779SAndroid Build Coastguard Worker   if (binding->uriLen > INT_MAX - prefixLen
3747*6be67779SAndroid Build Coastguard Worker       || i > INT_MAX - (binding->uriLen + prefixLen)) {
3748*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_NO_MEMORY;
3749*6be67779SAndroid Build Coastguard Worker   }
3750*6be67779SAndroid Build Coastguard Worker 
3751*6be67779SAndroid Build Coastguard Worker   n = i + binding->uriLen + prefixLen;
3752*6be67779SAndroid Build Coastguard Worker   if (n > binding->uriAlloc) {
3753*6be67779SAndroid Build Coastguard Worker     TAG *p;
3754*6be67779SAndroid Build Coastguard Worker 
3755*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow */
3756*6be67779SAndroid Build Coastguard Worker     if (n > INT_MAX - EXPAND_SPARE) {
3757*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3758*6be67779SAndroid Build Coastguard Worker     }
3759*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow.
3760*6be67779SAndroid Build Coastguard Worker      * The preprocessor guard addresses the "always false" warning
3761*6be67779SAndroid Build Coastguard Worker      * from -Wtype-limits on platforms where
3762*6be67779SAndroid Build Coastguard Worker      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3763*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
3764*6be67779SAndroid Build Coastguard Worker     if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
3765*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3766*6be67779SAndroid Build Coastguard Worker     }
3767*6be67779SAndroid Build Coastguard Worker #endif
3768*6be67779SAndroid Build Coastguard Worker 
3769*6be67779SAndroid Build Coastguard Worker     uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
3770*6be67779SAndroid Build Coastguard Worker     if (! uri)
3771*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
3772*6be67779SAndroid Build Coastguard Worker     binding->uriAlloc = n + EXPAND_SPARE;
3773*6be67779SAndroid Build Coastguard Worker     memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
3774*6be67779SAndroid Build Coastguard Worker     for (p = parser->m_tagStack; p; p = p->parent)
3775*6be67779SAndroid Build Coastguard Worker       if (p->name.str == binding->uri)
3776*6be67779SAndroid Build Coastguard Worker         p->name.str = uri;
3777*6be67779SAndroid Build Coastguard Worker     FREE(parser, binding->uri);
3778*6be67779SAndroid Build Coastguard Worker     binding->uri = uri;
3779*6be67779SAndroid Build Coastguard Worker   }
3780*6be67779SAndroid Build Coastguard Worker   /* if m_namespaceSeparator != '\0' then uri includes it already */
3781*6be67779SAndroid Build Coastguard Worker   uri = binding->uri + binding->uriLen;
3782*6be67779SAndroid Build Coastguard Worker   memcpy(uri, localPart, i * sizeof(XML_Char));
3783*6be67779SAndroid Build Coastguard Worker   /* we always have a namespace separator between localPart and prefix */
3784*6be67779SAndroid Build Coastguard Worker   if (prefixLen) {
3785*6be67779SAndroid Build Coastguard Worker     uri += i - 1;
3786*6be67779SAndroid Build Coastguard Worker     *uri = parser->m_namespaceSeparator; /* replace null terminator */
3787*6be67779SAndroid Build Coastguard Worker     memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3788*6be67779SAndroid Build Coastguard Worker   }
3789*6be67779SAndroid Build Coastguard Worker   tagNamePtr->str = binding->uri;
3790*6be67779SAndroid Build Coastguard Worker   return XML_ERROR_NONE;
3791*6be67779SAndroid Build Coastguard Worker }
3792*6be67779SAndroid Build Coastguard Worker 
3793*6be67779SAndroid Build Coastguard Worker static XML_Bool
is_rfc3986_uri_char(XML_Char candidate)3794*6be67779SAndroid Build Coastguard Worker is_rfc3986_uri_char(XML_Char candidate) {
3795*6be67779SAndroid Build Coastguard Worker   // For the RFC 3986 ANBF grammar see
3796*6be67779SAndroid Build Coastguard Worker   // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A
3797*6be67779SAndroid Build Coastguard Worker 
3798*6be67779SAndroid Build Coastguard Worker   switch (candidate) {
3799*6be67779SAndroid Build Coastguard Worker   // From rule "ALPHA" (uppercase half)
3800*6be67779SAndroid Build Coastguard Worker   case 'A':
3801*6be67779SAndroid Build Coastguard Worker   case 'B':
3802*6be67779SAndroid Build Coastguard Worker   case 'C':
3803*6be67779SAndroid Build Coastguard Worker   case 'D':
3804*6be67779SAndroid Build Coastguard Worker   case 'E':
3805*6be67779SAndroid Build Coastguard Worker   case 'F':
3806*6be67779SAndroid Build Coastguard Worker   case 'G':
3807*6be67779SAndroid Build Coastguard Worker   case 'H':
3808*6be67779SAndroid Build Coastguard Worker   case 'I':
3809*6be67779SAndroid Build Coastguard Worker   case 'J':
3810*6be67779SAndroid Build Coastguard Worker   case 'K':
3811*6be67779SAndroid Build Coastguard Worker   case 'L':
3812*6be67779SAndroid Build Coastguard Worker   case 'M':
3813*6be67779SAndroid Build Coastguard Worker   case 'N':
3814*6be67779SAndroid Build Coastguard Worker   case 'O':
3815*6be67779SAndroid Build Coastguard Worker   case 'P':
3816*6be67779SAndroid Build Coastguard Worker   case 'Q':
3817*6be67779SAndroid Build Coastguard Worker   case 'R':
3818*6be67779SAndroid Build Coastguard Worker   case 'S':
3819*6be67779SAndroid Build Coastguard Worker   case 'T':
3820*6be67779SAndroid Build Coastguard Worker   case 'U':
3821*6be67779SAndroid Build Coastguard Worker   case 'V':
3822*6be67779SAndroid Build Coastguard Worker   case 'W':
3823*6be67779SAndroid Build Coastguard Worker   case 'X':
3824*6be67779SAndroid Build Coastguard Worker   case 'Y':
3825*6be67779SAndroid Build Coastguard Worker   case 'Z':
3826*6be67779SAndroid Build Coastguard Worker 
3827*6be67779SAndroid Build Coastguard Worker   // From rule "ALPHA" (lowercase half)
3828*6be67779SAndroid Build Coastguard Worker   case 'a':
3829*6be67779SAndroid Build Coastguard Worker   case 'b':
3830*6be67779SAndroid Build Coastguard Worker   case 'c':
3831*6be67779SAndroid Build Coastguard Worker   case 'd':
3832*6be67779SAndroid Build Coastguard Worker   case 'e':
3833*6be67779SAndroid Build Coastguard Worker   case 'f':
3834*6be67779SAndroid Build Coastguard Worker   case 'g':
3835*6be67779SAndroid Build Coastguard Worker   case 'h':
3836*6be67779SAndroid Build Coastguard Worker   case 'i':
3837*6be67779SAndroid Build Coastguard Worker   case 'j':
3838*6be67779SAndroid Build Coastguard Worker   case 'k':
3839*6be67779SAndroid Build Coastguard Worker   case 'l':
3840*6be67779SAndroid Build Coastguard Worker   case 'm':
3841*6be67779SAndroid Build Coastguard Worker   case 'n':
3842*6be67779SAndroid Build Coastguard Worker   case 'o':
3843*6be67779SAndroid Build Coastguard Worker   case 'p':
3844*6be67779SAndroid Build Coastguard Worker   case 'q':
3845*6be67779SAndroid Build Coastguard Worker   case 'r':
3846*6be67779SAndroid Build Coastguard Worker   case 's':
3847*6be67779SAndroid Build Coastguard Worker   case 't':
3848*6be67779SAndroid Build Coastguard Worker   case 'u':
3849*6be67779SAndroid Build Coastguard Worker   case 'v':
3850*6be67779SAndroid Build Coastguard Worker   case 'w':
3851*6be67779SAndroid Build Coastguard Worker   case 'x':
3852*6be67779SAndroid Build Coastguard Worker   case 'y':
3853*6be67779SAndroid Build Coastguard Worker   case 'z':
3854*6be67779SAndroid Build Coastguard Worker 
3855*6be67779SAndroid Build Coastguard Worker   // From rule "DIGIT"
3856*6be67779SAndroid Build Coastguard Worker   case '0':
3857*6be67779SAndroid Build Coastguard Worker   case '1':
3858*6be67779SAndroid Build Coastguard Worker   case '2':
3859*6be67779SAndroid Build Coastguard Worker   case '3':
3860*6be67779SAndroid Build Coastguard Worker   case '4':
3861*6be67779SAndroid Build Coastguard Worker   case '5':
3862*6be67779SAndroid Build Coastguard Worker   case '6':
3863*6be67779SAndroid Build Coastguard Worker   case '7':
3864*6be67779SAndroid Build Coastguard Worker   case '8':
3865*6be67779SAndroid Build Coastguard Worker   case '9':
3866*6be67779SAndroid Build Coastguard Worker 
3867*6be67779SAndroid Build Coastguard Worker   // From rule "pct-encoded"
3868*6be67779SAndroid Build Coastguard Worker   case '%':
3869*6be67779SAndroid Build Coastguard Worker 
3870*6be67779SAndroid Build Coastguard Worker   // From rule "unreserved"
3871*6be67779SAndroid Build Coastguard Worker   case '-':
3872*6be67779SAndroid Build Coastguard Worker   case '.':
3873*6be67779SAndroid Build Coastguard Worker   case '_':
3874*6be67779SAndroid Build Coastguard Worker   case '~':
3875*6be67779SAndroid Build Coastguard Worker 
3876*6be67779SAndroid Build Coastguard Worker   // From rule "gen-delims"
3877*6be67779SAndroid Build Coastguard Worker   case ':':
3878*6be67779SAndroid Build Coastguard Worker   case '/':
3879*6be67779SAndroid Build Coastguard Worker   case '?':
3880*6be67779SAndroid Build Coastguard Worker   case '#':
3881*6be67779SAndroid Build Coastguard Worker   case '[':
3882*6be67779SAndroid Build Coastguard Worker   case ']':
3883*6be67779SAndroid Build Coastguard Worker   case '@':
3884*6be67779SAndroid Build Coastguard Worker 
3885*6be67779SAndroid Build Coastguard Worker   // From rule "sub-delims"
3886*6be67779SAndroid Build Coastguard Worker   case '!':
3887*6be67779SAndroid Build Coastguard Worker   case '$':
3888*6be67779SAndroid Build Coastguard Worker   case '&':
3889*6be67779SAndroid Build Coastguard Worker   case '\'':
3890*6be67779SAndroid Build Coastguard Worker   case '(':
3891*6be67779SAndroid Build Coastguard Worker   case ')':
3892*6be67779SAndroid Build Coastguard Worker   case '*':
3893*6be67779SAndroid Build Coastguard Worker   case '+':
3894*6be67779SAndroid Build Coastguard Worker   case ',':
3895*6be67779SAndroid Build Coastguard Worker   case ';':
3896*6be67779SAndroid Build Coastguard Worker   case '=':
3897*6be67779SAndroid Build Coastguard Worker     return XML_TRUE;
3898*6be67779SAndroid Build Coastguard Worker 
3899*6be67779SAndroid Build Coastguard Worker   default:
3900*6be67779SAndroid Build Coastguard Worker     return XML_FALSE;
3901*6be67779SAndroid Build Coastguard Worker   }
3902*6be67779SAndroid Build Coastguard Worker }
3903*6be67779SAndroid Build Coastguard Worker 
3904*6be67779SAndroid Build Coastguard Worker /* addBinding() overwrites the value of prefix->binding without checking.
3905*6be67779SAndroid Build Coastguard Worker    Therefore one must keep track of the old value outside of addBinding().
3906*6be67779SAndroid Build Coastguard Worker */
3907*6be67779SAndroid Build Coastguard Worker static enum XML_Error
addBinding(XML_Parser parser,PREFIX * prefix,const ATTRIBUTE_ID * attId,const XML_Char * uri,BINDING ** bindingsPtr)3908*6be67779SAndroid Build Coastguard Worker addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3909*6be67779SAndroid Build Coastguard Worker            const XML_Char *uri, BINDING **bindingsPtr) {
3910*6be67779SAndroid Build Coastguard Worker   // "http://www.w3.org/XML/1998/namespace"
3911*6be67779SAndroid Build Coastguard Worker   static const XML_Char xmlNamespace[]
3912*6be67779SAndroid Build Coastguard Worker       = {ASCII_h,      ASCII_t,     ASCII_t,     ASCII_p,      ASCII_COLON,
3913*6be67779SAndroid Build Coastguard Worker          ASCII_SLASH,  ASCII_SLASH, ASCII_w,     ASCII_w,      ASCII_w,
3914*6be67779SAndroid Build Coastguard Worker          ASCII_PERIOD, ASCII_w,     ASCII_3,     ASCII_PERIOD, ASCII_o,
3915*6be67779SAndroid Build Coastguard Worker          ASCII_r,      ASCII_g,     ASCII_SLASH, ASCII_X,      ASCII_M,
3916*6be67779SAndroid Build Coastguard Worker          ASCII_L,      ASCII_SLASH, ASCII_1,     ASCII_9,      ASCII_9,
3917*6be67779SAndroid Build Coastguard Worker          ASCII_8,      ASCII_SLASH, ASCII_n,     ASCII_a,      ASCII_m,
3918*6be67779SAndroid Build Coastguard Worker          ASCII_e,      ASCII_s,     ASCII_p,     ASCII_a,      ASCII_c,
3919*6be67779SAndroid Build Coastguard Worker          ASCII_e,      '\0'};
3920*6be67779SAndroid Build Coastguard Worker   static const int xmlLen = (int)sizeof(xmlNamespace) / sizeof(XML_Char) - 1;
3921*6be67779SAndroid Build Coastguard Worker   // "http://www.w3.org/2000/xmlns/"
3922*6be67779SAndroid Build Coastguard Worker   static const XML_Char xmlnsNamespace[]
3923*6be67779SAndroid Build Coastguard Worker       = {ASCII_h,     ASCII_t,      ASCII_t, ASCII_p, ASCII_COLON,  ASCII_SLASH,
3924*6be67779SAndroid Build Coastguard Worker          ASCII_SLASH, ASCII_w,      ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w,
3925*6be67779SAndroid Build Coastguard Worker          ASCII_3,     ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,      ASCII_SLASH,
3926*6be67779SAndroid Build Coastguard Worker          ASCII_2,     ASCII_0,      ASCII_0, ASCII_0, ASCII_SLASH,  ASCII_x,
3927*6be67779SAndroid Build Coastguard Worker          ASCII_m,     ASCII_l,      ASCII_n, ASCII_s, ASCII_SLASH,  '\0'};
3928*6be67779SAndroid Build Coastguard Worker   static const int xmlnsLen
3929*6be67779SAndroid Build Coastguard Worker       = (int)sizeof(xmlnsNamespace) / sizeof(XML_Char) - 1;
3930*6be67779SAndroid Build Coastguard Worker 
3931*6be67779SAndroid Build Coastguard Worker   XML_Bool mustBeXML = XML_FALSE;
3932*6be67779SAndroid Build Coastguard Worker   XML_Bool isXML = XML_TRUE;
3933*6be67779SAndroid Build Coastguard Worker   XML_Bool isXMLNS = XML_TRUE;
3934*6be67779SAndroid Build Coastguard Worker 
3935*6be67779SAndroid Build Coastguard Worker   BINDING *b;
3936*6be67779SAndroid Build Coastguard Worker   int len;
3937*6be67779SAndroid Build Coastguard Worker 
3938*6be67779SAndroid Build Coastguard Worker   /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3939*6be67779SAndroid Build Coastguard Worker   if (*uri == XML_T('\0') && prefix->name)
3940*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_UNDECLARING_PREFIX;
3941*6be67779SAndroid Build Coastguard Worker 
3942*6be67779SAndroid Build Coastguard Worker   if (prefix->name && prefix->name[0] == XML_T(ASCII_x)
3943*6be67779SAndroid Build Coastguard Worker       && prefix->name[1] == XML_T(ASCII_m)
3944*6be67779SAndroid Build Coastguard Worker       && prefix->name[2] == XML_T(ASCII_l)) {
3945*6be67779SAndroid Build Coastguard Worker     /* Not allowed to bind xmlns */
3946*6be67779SAndroid Build Coastguard Worker     if (prefix->name[3] == XML_T(ASCII_n) && prefix->name[4] == XML_T(ASCII_s)
3947*6be67779SAndroid Build Coastguard Worker         && prefix->name[5] == XML_T('\0'))
3948*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_RESERVED_PREFIX_XMLNS;
3949*6be67779SAndroid Build Coastguard Worker 
3950*6be67779SAndroid Build Coastguard Worker     if (prefix->name[3] == XML_T('\0'))
3951*6be67779SAndroid Build Coastguard Worker       mustBeXML = XML_TRUE;
3952*6be67779SAndroid Build Coastguard Worker   }
3953*6be67779SAndroid Build Coastguard Worker 
3954*6be67779SAndroid Build Coastguard Worker   for (len = 0; uri[len]; len++) {
3955*6be67779SAndroid Build Coastguard Worker     if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3956*6be67779SAndroid Build Coastguard Worker       isXML = XML_FALSE;
3957*6be67779SAndroid Build Coastguard Worker 
3958*6be67779SAndroid Build Coastguard Worker     if (! mustBeXML && isXMLNS
3959*6be67779SAndroid Build Coastguard Worker         && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3960*6be67779SAndroid Build Coastguard Worker       isXMLNS = XML_FALSE;
3961*6be67779SAndroid Build Coastguard Worker 
3962*6be67779SAndroid Build Coastguard Worker     // NOTE: While Expat does not validate namespace URIs against RFC 3986
3963*6be67779SAndroid Build Coastguard Worker     //       today (and is not REQUIRED to do so with regard to the XML 1.0
3964*6be67779SAndroid Build Coastguard Worker     //       namespaces specification) we have to at least make sure, that
3965*6be67779SAndroid Build Coastguard Worker     //       the application on top of Expat (that is likely splitting expanded
3966*6be67779SAndroid Build Coastguard Worker     //       element names ("qualified names") of form
3967*6be67779SAndroid Build Coastguard Worker     //       "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces
3968*6be67779SAndroid Build Coastguard Worker     //       in its element handler code) cannot be confused by an attacker
3969*6be67779SAndroid Build Coastguard Worker     //       putting additional namespace separator characters into namespace
3970*6be67779SAndroid Build Coastguard Worker     //       declarations.  That would be ambiguous and not to be expected.
3971*6be67779SAndroid Build Coastguard Worker     //
3972*6be67779SAndroid Build Coastguard Worker     //       While the HTML API docs of function XML_ParserCreateNS have been
3973*6be67779SAndroid Build Coastguard Worker     //       advising against use of a namespace separator character that can
3974*6be67779SAndroid Build Coastguard Worker     //       appear in a URI for >20 years now, some widespread applications
3975*6be67779SAndroid Build Coastguard Worker     //       are using URI characters (':' (colon) in particular) for a
3976*6be67779SAndroid Build Coastguard Worker     //       namespace separator, in practice.  To keep these applications
3977*6be67779SAndroid Build Coastguard Worker     //       functional, we only reject namespaces URIs containing the
3978*6be67779SAndroid Build Coastguard Worker     //       application-chosen namespace separator if the chosen separator
3979*6be67779SAndroid Build Coastguard Worker     //       is a non-URI character with regard to RFC 3986.
3980*6be67779SAndroid Build Coastguard Worker     if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)
3981*6be67779SAndroid Build Coastguard Worker         && ! is_rfc3986_uri_char(uri[len])) {
3982*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_SYNTAX;
3983*6be67779SAndroid Build Coastguard Worker     }
3984*6be67779SAndroid Build Coastguard Worker   }
3985*6be67779SAndroid Build Coastguard Worker   isXML = isXML && len == xmlLen;
3986*6be67779SAndroid Build Coastguard Worker   isXMLNS = isXMLNS && len == xmlnsLen;
3987*6be67779SAndroid Build Coastguard Worker 
3988*6be67779SAndroid Build Coastguard Worker   if (mustBeXML != isXML)
3989*6be67779SAndroid Build Coastguard Worker     return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3990*6be67779SAndroid Build Coastguard Worker                      : XML_ERROR_RESERVED_NAMESPACE_URI;
3991*6be67779SAndroid Build Coastguard Worker 
3992*6be67779SAndroid Build Coastguard Worker   if (isXMLNS)
3993*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_RESERVED_NAMESPACE_URI;
3994*6be67779SAndroid Build Coastguard Worker 
3995*6be67779SAndroid Build Coastguard Worker   if (parser->m_namespaceSeparator)
3996*6be67779SAndroid Build Coastguard Worker     len++;
3997*6be67779SAndroid Build Coastguard Worker   if (parser->m_freeBindingList) {
3998*6be67779SAndroid Build Coastguard Worker     b = parser->m_freeBindingList;
3999*6be67779SAndroid Build Coastguard Worker     if (len > b->uriAlloc) {
4000*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent integer overflow */
4001*6be67779SAndroid Build Coastguard Worker       if (len > INT_MAX - EXPAND_SPARE) {
4002*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
4003*6be67779SAndroid Build Coastguard Worker       }
4004*6be67779SAndroid Build Coastguard Worker 
4005*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent integer overflow.
4006*6be67779SAndroid Build Coastguard Worker        * The preprocessor guard addresses the "always false" warning
4007*6be67779SAndroid Build Coastguard Worker        * from -Wtype-limits on platforms where
4008*6be67779SAndroid Build Coastguard Worker        * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
4009*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
4010*6be67779SAndroid Build Coastguard Worker       if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
4011*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
4012*6be67779SAndroid Build Coastguard Worker       }
4013*6be67779SAndroid Build Coastguard Worker #endif
4014*6be67779SAndroid Build Coastguard Worker 
4015*6be67779SAndroid Build Coastguard Worker       XML_Char *temp = (XML_Char *)REALLOC(
4016*6be67779SAndroid Build Coastguard Worker           parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
4017*6be67779SAndroid Build Coastguard Worker       if (temp == NULL)
4018*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
4019*6be67779SAndroid Build Coastguard Worker       b->uri = temp;
4020*6be67779SAndroid Build Coastguard Worker       b->uriAlloc = len + EXPAND_SPARE;
4021*6be67779SAndroid Build Coastguard Worker     }
4022*6be67779SAndroid Build Coastguard Worker     parser->m_freeBindingList = b->nextTagBinding;
4023*6be67779SAndroid Build Coastguard Worker   } else {
4024*6be67779SAndroid Build Coastguard Worker     b = (BINDING *)MALLOC(parser, sizeof(BINDING));
4025*6be67779SAndroid Build Coastguard Worker     if (! b)
4026*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
4027*6be67779SAndroid Build Coastguard Worker 
4028*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow */
4029*6be67779SAndroid Build Coastguard Worker     if (len > INT_MAX - EXPAND_SPARE) {
4030*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
4031*6be67779SAndroid Build Coastguard Worker     }
4032*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow.
4033*6be67779SAndroid Build Coastguard Worker      * The preprocessor guard addresses the "always false" warning
4034*6be67779SAndroid Build Coastguard Worker      * from -Wtype-limits on platforms where
4035*6be67779SAndroid Build Coastguard Worker      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
4036*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
4037*6be67779SAndroid Build Coastguard Worker     if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
4038*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
4039*6be67779SAndroid Build Coastguard Worker     }
4040*6be67779SAndroid Build Coastguard Worker #endif
4041*6be67779SAndroid Build Coastguard Worker 
4042*6be67779SAndroid Build Coastguard Worker     b->uri
4043*6be67779SAndroid Build Coastguard Worker         = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
4044*6be67779SAndroid Build Coastguard Worker     if (! b->uri) {
4045*6be67779SAndroid Build Coastguard Worker       FREE(parser, b);
4046*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
4047*6be67779SAndroid Build Coastguard Worker     }
4048*6be67779SAndroid Build Coastguard Worker     b->uriAlloc = len + EXPAND_SPARE;
4049*6be67779SAndroid Build Coastguard Worker   }
4050*6be67779SAndroid Build Coastguard Worker   b->uriLen = len;
4051*6be67779SAndroid Build Coastguard Worker   memcpy(b->uri, uri, len * sizeof(XML_Char));
4052*6be67779SAndroid Build Coastguard Worker   if (parser->m_namespaceSeparator)
4053*6be67779SAndroid Build Coastguard Worker     b->uri[len - 1] = parser->m_namespaceSeparator;
4054*6be67779SAndroid Build Coastguard Worker   b->prefix = prefix;
4055*6be67779SAndroid Build Coastguard Worker   b->attId = attId;
4056*6be67779SAndroid Build Coastguard Worker   b->prevPrefixBinding = prefix->binding;
4057*6be67779SAndroid Build Coastguard Worker   /* NULL binding when default namespace undeclared */
4058*6be67779SAndroid Build Coastguard Worker   if (*uri == XML_T('\0') && prefix == &parser->m_dtd->defaultPrefix)
4059*6be67779SAndroid Build Coastguard Worker     prefix->binding = NULL;
4060*6be67779SAndroid Build Coastguard Worker   else
4061*6be67779SAndroid Build Coastguard Worker     prefix->binding = b;
4062*6be67779SAndroid Build Coastguard Worker   b->nextTagBinding = *bindingsPtr;
4063*6be67779SAndroid Build Coastguard Worker   *bindingsPtr = b;
4064*6be67779SAndroid Build Coastguard Worker   /* if attId == NULL then we are not starting a namespace scope */
4065*6be67779SAndroid Build Coastguard Worker   if (attId && parser->m_startNamespaceDeclHandler)
4066*6be67779SAndroid Build Coastguard Worker     parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name,
4067*6be67779SAndroid Build Coastguard Worker                                         prefix->binding ? uri : 0);
4068*6be67779SAndroid Build Coastguard Worker   return XML_ERROR_NONE;
4069*6be67779SAndroid Build Coastguard Worker }
4070*6be67779SAndroid Build Coastguard Worker 
4071*6be67779SAndroid Build Coastguard Worker /* The idea here is to avoid using stack for each CDATA section when
4072*6be67779SAndroid Build Coastguard Worker    the whole file is parsed with one call.
4073*6be67779SAndroid Build Coastguard Worker */
4074*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
cdataSectionProcessor(XML_Parser parser,const char * start,const char * end,const char ** endPtr)4075*6be67779SAndroid Build Coastguard Worker cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
4076*6be67779SAndroid Build Coastguard Worker                       const char **endPtr) {
4077*6be67779SAndroid Build Coastguard Worker   enum XML_Error result = doCdataSection(
4078*6be67779SAndroid Build Coastguard Worker       parser, parser->m_encoding, &start, end, endPtr,
4079*6be67779SAndroid Build Coastguard Worker       (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
4080*6be67779SAndroid Build Coastguard Worker   if (result != XML_ERROR_NONE)
4081*6be67779SAndroid Build Coastguard Worker     return result;
4082*6be67779SAndroid Build Coastguard Worker   if (start) {
4083*6be67779SAndroid Build Coastguard Worker     if (parser->m_parentParser) { /* we are parsing an external entity */
4084*6be67779SAndroid Build Coastguard Worker       parser->m_processor = externalEntityContentProcessor;
4085*6be67779SAndroid Build Coastguard Worker       return externalEntityContentProcessor(parser, start, end, endPtr);
4086*6be67779SAndroid Build Coastguard Worker     } else {
4087*6be67779SAndroid Build Coastguard Worker       parser->m_processor = contentProcessor;
4088*6be67779SAndroid Build Coastguard Worker       return contentProcessor(parser, start, end, endPtr);
4089*6be67779SAndroid Build Coastguard Worker     }
4090*6be67779SAndroid Build Coastguard Worker   }
4091*6be67779SAndroid Build Coastguard Worker   return result;
4092*6be67779SAndroid Build Coastguard Worker }
4093*6be67779SAndroid Build Coastguard Worker 
4094*6be67779SAndroid Build Coastguard Worker /* startPtr gets set to non-null if the section is closed, and to null if
4095*6be67779SAndroid Build Coastguard Worker    the section is not yet closed.
4096*6be67779SAndroid Build Coastguard Worker */
4097*6be67779SAndroid Build Coastguard Worker 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)4098*6be67779SAndroid Build Coastguard Worker doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
4099*6be67779SAndroid Build Coastguard Worker                const char *end, const char **nextPtr, XML_Bool haveMore,
4100*6be67779SAndroid Build Coastguard Worker                enum XML_Account account) {
4101*6be67779SAndroid Build Coastguard Worker   const char *s = *startPtr;
4102*6be67779SAndroid Build Coastguard Worker   const char **eventPP;
4103*6be67779SAndroid Build Coastguard Worker   const char **eventEndPP;
4104*6be67779SAndroid Build Coastguard Worker   if (enc == parser->m_encoding) {
4105*6be67779SAndroid Build Coastguard Worker     eventPP = &parser->m_eventPtr;
4106*6be67779SAndroid Build Coastguard Worker     *eventPP = s;
4107*6be67779SAndroid Build Coastguard Worker     eventEndPP = &parser->m_eventEndPtr;
4108*6be67779SAndroid Build Coastguard Worker   } else {
4109*6be67779SAndroid Build Coastguard Worker     eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4110*6be67779SAndroid Build Coastguard Worker     eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
4111*6be67779SAndroid Build Coastguard Worker   }
4112*6be67779SAndroid Build Coastguard Worker   *eventPP = s;
4113*6be67779SAndroid Build Coastguard Worker   *startPtr = NULL;
4114*6be67779SAndroid Build Coastguard Worker 
4115*6be67779SAndroid Build Coastguard Worker   for (;;) {
4116*6be67779SAndroid Build Coastguard Worker     const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
4117*6be67779SAndroid Build Coastguard Worker     int tok = XmlCdataSectionTok(enc, s, end, &next);
4118*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
4119*6be67779SAndroid Build Coastguard Worker     if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
4120*6be67779SAndroid Build Coastguard Worker       accountingOnAbort(parser);
4121*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
4122*6be67779SAndroid Build Coastguard Worker     }
4123*6be67779SAndroid Build Coastguard Worker #else
4124*6be67779SAndroid Build Coastguard Worker     UNUSED_P(account);
4125*6be67779SAndroid Build Coastguard Worker #endif
4126*6be67779SAndroid Build Coastguard Worker     *eventEndPP = next;
4127*6be67779SAndroid Build Coastguard Worker     switch (tok) {
4128*6be67779SAndroid Build Coastguard Worker     case XML_TOK_CDATA_SECT_CLOSE:
4129*6be67779SAndroid Build Coastguard Worker       if (parser->m_endCdataSectionHandler)
4130*6be67779SAndroid Build Coastguard Worker         parser->m_endCdataSectionHandler(parser->m_handlerArg);
4131*6be67779SAndroid Build Coastguard Worker       /* BEGIN disabled code */
4132*6be67779SAndroid Build Coastguard Worker       /* see comment under XML_TOK_CDATA_SECT_OPEN */
4133*6be67779SAndroid Build Coastguard Worker       else if ((0) && parser->m_characterDataHandler)
4134*6be67779SAndroid Build Coastguard Worker         parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
4135*6be67779SAndroid Build Coastguard Worker                                        0);
4136*6be67779SAndroid Build Coastguard Worker       /* END disabled code */
4137*6be67779SAndroid Build Coastguard Worker       else if (parser->m_defaultHandler)
4138*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
4139*6be67779SAndroid Build Coastguard Worker       *startPtr = next;
4140*6be67779SAndroid Build Coastguard Worker       *nextPtr = next;
4141*6be67779SAndroid Build Coastguard Worker       if (parser->m_parsingStatus.parsing == XML_FINISHED)
4142*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_ABORTED;
4143*6be67779SAndroid Build Coastguard Worker       else
4144*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
4145*6be67779SAndroid Build Coastguard Worker     case XML_TOK_DATA_NEWLINE:
4146*6be67779SAndroid Build Coastguard Worker       if (parser->m_characterDataHandler) {
4147*6be67779SAndroid Build Coastguard Worker         XML_Char c = 0xA;
4148*6be67779SAndroid Build Coastguard Worker         parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
4149*6be67779SAndroid Build Coastguard Worker       } else if (parser->m_defaultHandler)
4150*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
4151*6be67779SAndroid Build Coastguard Worker       break;
4152*6be67779SAndroid Build Coastguard Worker     case XML_TOK_DATA_CHARS: {
4153*6be67779SAndroid Build Coastguard Worker       XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
4154*6be67779SAndroid Build Coastguard Worker       if (charDataHandler) {
4155*6be67779SAndroid Build Coastguard Worker         if (MUST_CONVERT(enc, s)) {
4156*6be67779SAndroid Build Coastguard Worker           for (;;) {
4157*6be67779SAndroid Build Coastguard Worker             ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
4158*6be67779SAndroid Build Coastguard Worker             const enum XML_Convert_Result convert_res = XmlConvert(
4159*6be67779SAndroid Build Coastguard Worker                 enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
4160*6be67779SAndroid Build Coastguard Worker             *eventEndPP = next;
4161*6be67779SAndroid Build Coastguard Worker             charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
4162*6be67779SAndroid Build Coastguard Worker                             (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
4163*6be67779SAndroid Build Coastguard Worker             if ((convert_res == XML_CONVERT_COMPLETED)
4164*6be67779SAndroid Build Coastguard Worker                 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
4165*6be67779SAndroid Build Coastguard Worker               break;
4166*6be67779SAndroid Build Coastguard Worker             *eventPP = s;
4167*6be67779SAndroid Build Coastguard Worker           }
4168*6be67779SAndroid Build Coastguard Worker         } else
4169*6be67779SAndroid Build Coastguard Worker           charDataHandler(parser->m_handlerArg, (const XML_Char *)s,
4170*6be67779SAndroid Build Coastguard Worker                           (int)((const XML_Char *)next - (const XML_Char *)s));
4171*6be67779SAndroid Build Coastguard Worker       } else if (parser->m_defaultHandler)
4172*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
4173*6be67779SAndroid Build Coastguard Worker     } break;
4174*6be67779SAndroid Build Coastguard Worker     case XML_TOK_INVALID:
4175*6be67779SAndroid Build Coastguard Worker       *eventPP = next;
4176*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_INVALID_TOKEN;
4177*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL_CHAR:
4178*6be67779SAndroid Build Coastguard Worker       if (haveMore) {
4179*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
4180*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
4181*6be67779SAndroid Build Coastguard Worker       }
4182*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_PARTIAL_CHAR;
4183*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL:
4184*6be67779SAndroid Build Coastguard Worker     case XML_TOK_NONE:
4185*6be67779SAndroid Build Coastguard Worker       if (haveMore) {
4186*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
4187*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
4188*6be67779SAndroid Build Coastguard Worker       }
4189*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_UNCLOSED_CDATA_SECTION;
4190*6be67779SAndroid Build Coastguard Worker     default:
4191*6be67779SAndroid Build Coastguard Worker       /* Every token returned by XmlCdataSectionTok() has its own
4192*6be67779SAndroid Build Coastguard Worker        * explicit case, so this default case will never be executed.
4193*6be67779SAndroid Build Coastguard Worker        * We retain it as a safety net and exclude it from the coverage
4194*6be67779SAndroid Build Coastguard Worker        * statistics.
4195*6be67779SAndroid Build Coastguard Worker        *
4196*6be67779SAndroid Build Coastguard Worker        * LCOV_EXCL_START
4197*6be67779SAndroid Build Coastguard Worker        */
4198*6be67779SAndroid Build Coastguard Worker       *eventPP = next;
4199*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_UNEXPECTED_STATE;
4200*6be67779SAndroid Build Coastguard Worker       /* LCOV_EXCL_STOP */
4201*6be67779SAndroid Build Coastguard Worker     }
4202*6be67779SAndroid Build Coastguard Worker 
4203*6be67779SAndroid Build Coastguard Worker     *eventPP = s = next;
4204*6be67779SAndroid Build Coastguard Worker     switch (parser->m_parsingStatus.parsing) {
4205*6be67779SAndroid Build Coastguard Worker     case XML_SUSPENDED:
4206*6be67779SAndroid Build Coastguard Worker       *nextPtr = next;
4207*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
4208*6be67779SAndroid Build Coastguard Worker     case XML_FINISHED:
4209*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_ABORTED;
4210*6be67779SAndroid Build Coastguard Worker     default:;
4211*6be67779SAndroid Build Coastguard Worker     }
4212*6be67779SAndroid Build Coastguard Worker   }
4213*6be67779SAndroid Build Coastguard Worker   /* not reached */
4214*6be67779SAndroid Build Coastguard Worker }
4215*6be67779SAndroid Build Coastguard Worker 
4216*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
4217*6be67779SAndroid Build Coastguard Worker 
4218*6be67779SAndroid Build Coastguard Worker /* The idea here is to avoid using stack for each IGNORE section when
4219*6be67779SAndroid Build Coastguard Worker    the whole file is parsed with one call.
4220*6be67779SAndroid Build Coastguard Worker */
4221*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
ignoreSectionProcessor(XML_Parser parser,const char * start,const char * end,const char ** endPtr)4222*6be67779SAndroid Build Coastguard Worker ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end,
4223*6be67779SAndroid Build Coastguard Worker                        const char **endPtr) {
4224*6be67779SAndroid Build Coastguard Worker   enum XML_Error result
4225*6be67779SAndroid Build Coastguard Worker       = doIgnoreSection(parser, parser->m_encoding, &start, end, endPtr,
4226*6be67779SAndroid Build Coastguard Worker                         (XML_Bool)! parser->m_parsingStatus.finalBuffer);
4227*6be67779SAndroid Build Coastguard Worker   if (result != XML_ERROR_NONE)
4228*6be67779SAndroid Build Coastguard Worker     return result;
4229*6be67779SAndroid Build Coastguard Worker   if (start) {
4230*6be67779SAndroid Build Coastguard Worker     parser->m_processor = prologProcessor;
4231*6be67779SAndroid Build Coastguard Worker     return prologProcessor(parser, start, end, endPtr);
4232*6be67779SAndroid Build Coastguard Worker   }
4233*6be67779SAndroid Build Coastguard Worker   return result;
4234*6be67779SAndroid Build Coastguard Worker }
4235*6be67779SAndroid Build Coastguard Worker 
4236*6be67779SAndroid Build Coastguard Worker /* startPtr gets set to non-null is the section is closed, and to null
4237*6be67779SAndroid Build Coastguard Worker    if the section is not yet closed.
4238*6be67779SAndroid Build Coastguard Worker */
4239*6be67779SAndroid Build Coastguard Worker static enum XML_Error
doIgnoreSection(XML_Parser parser,const ENCODING * enc,const char ** startPtr,const char * end,const char ** nextPtr,XML_Bool haveMore)4240*6be67779SAndroid Build Coastguard Worker doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
4241*6be67779SAndroid Build Coastguard Worker                 const char *end, const char **nextPtr, XML_Bool haveMore) {
4242*6be67779SAndroid Build Coastguard Worker   const char *next = *startPtr; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
4243*6be67779SAndroid Build Coastguard Worker   int tok;
4244*6be67779SAndroid Build Coastguard Worker   const char *s = *startPtr;
4245*6be67779SAndroid Build Coastguard Worker   const char **eventPP;
4246*6be67779SAndroid Build Coastguard Worker   const char **eventEndPP;
4247*6be67779SAndroid Build Coastguard Worker   if (enc == parser->m_encoding) {
4248*6be67779SAndroid Build Coastguard Worker     eventPP = &parser->m_eventPtr;
4249*6be67779SAndroid Build Coastguard Worker     *eventPP = s;
4250*6be67779SAndroid Build Coastguard Worker     eventEndPP = &parser->m_eventEndPtr;
4251*6be67779SAndroid Build Coastguard Worker   } else {
4252*6be67779SAndroid Build Coastguard Worker     /* It's not entirely clear, but it seems the following two lines
4253*6be67779SAndroid Build Coastguard Worker      * of code cannot be executed.  The only occasions on which 'enc'
4254*6be67779SAndroid Build Coastguard Worker      * is not 'encoding' are when this function is called
4255*6be67779SAndroid Build Coastguard Worker      * from the internal entity processing, and IGNORE sections are an
4256*6be67779SAndroid Build Coastguard Worker      * error in internal entities.
4257*6be67779SAndroid Build Coastguard Worker      *
4258*6be67779SAndroid Build Coastguard Worker      * Since it really isn't clear that this is true, we keep the code
4259*6be67779SAndroid Build Coastguard Worker      * and just remove it from our coverage tests.
4260*6be67779SAndroid Build Coastguard Worker      *
4261*6be67779SAndroid Build Coastguard Worker      * LCOV_EXCL_START
4262*6be67779SAndroid Build Coastguard Worker      */
4263*6be67779SAndroid Build Coastguard Worker     eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4264*6be67779SAndroid Build Coastguard Worker     eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
4265*6be67779SAndroid Build Coastguard Worker     /* LCOV_EXCL_STOP */
4266*6be67779SAndroid Build Coastguard Worker   }
4267*6be67779SAndroid Build Coastguard Worker   *eventPP = s;
4268*6be67779SAndroid Build Coastguard Worker   *startPtr = NULL;
4269*6be67779SAndroid Build Coastguard Worker   tok = XmlIgnoreSectionTok(enc, s, end, &next);
4270*6be67779SAndroid Build Coastguard Worker #  if XML_GE == 1
4271*6be67779SAndroid Build Coastguard Worker   if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
4272*6be67779SAndroid Build Coastguard Worker                                 XML_ACCOUNT_DIRECT)) {
4273*6be67779SAndroid Build Coastguard Worker     accountingOnAbort(parser);
4274*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
4275*6be67779SAndroid Build Coastguard Worker   }
4276*6be67779SAndroid Build Coastguard Worker #  endif
4277*6be67779SAndroid Build Coastguard Worker   *eventEndPP = next;
4278*6be67779SAndroid Build Coastguard Worker   switch (tok) {
4279*6be67779SAndroid Build Coastguard Worker   case XML_TOK_IGNORE_SECT:
4280*6be67779SAndroid Build Coastguard Worker     if (parser->m_defaultHandler)
4281*6be67779SAndroid Build Coastguard Worker       reportDefault(parser, enc, s, next);
4282*6be67779SAndroid Build Coastguard Worker     *startPtr = next;
4283*6be67779SAndroid Build Coastguard Worker     *nextPtr = next;
4284*6be67779SAndroid Build Coastguard Worker     if (parser->m_parsingStatus.parsing == XML_FINISHED)
4285*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_ABORTED;
4286*6be67779SAndroid Build Coastguard Worker     else
4287*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
4288*6be67779SAndroid Build Coastguard Worker   case XML_TOK_INVALID:
4289*6be67779SAndroid Build Coastguard Worker     *eventPP = next;
4290*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_INVALID_TOKEN;
4291*6be67779SAndroid Build Coastguard Worker   case XML_TOK_PARTIAL_CHAR:
4292*6be67779SAndroid Build Coastguard Worker     if (haveMore) {
4293*6be67779SAndroid Build Coastguard Worker       *nextPtr = s;
4294*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
4295*6be67779SAndroid Build Coastguard Worker     }
4296*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_PARTIAL_CHAR;
4297*6be67779SAndroid Build Coastguard Worker   case XML_TOK_PARTIAL:
4298*6be67779SAndroid Build Coastguard Worker   case XML_TOK_NONE:
4299*6be67779SAndroid Build Coastguard Worker     if (haveMore) {
4300*6be67779SAndroid Build Coastguard Worker       *nextPtr = s;
4301*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
4302*6be67779SAndroid Build Coastguard Worker     }
4303*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
4304*6be67779SAndroid Build Coastguard Worker   default:
4305*6be67779SAndroid Build Coastguard Worker     /* All of the tokens that XmlIgnoreSectionTok() returns have
4306*6be67779SAndroid Build Coastguard Worker      * explicit cases to handle them, so this default case is never
4307*6be67779SAndroid Build Coastguard Worker      * executed.  We keep it as a safety net anyway, and remove it
4308*6be67779SAndroid Build Coastguard Worker      * from our test coverage statistics.
4309*6be67779SAndroid Build Coastguard Worker      *
4310*6be67779SAndroid Build Coastguard Worker      * LCOV_EXCL_START
4311*6be67779SAndroid Build Coastguard Worker      */
4312*6be67779SAndroid Build Coastguard Worker     *eventPP = next;
4313*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_UNEXPECTED_STATE;
4314*6be67779SAndroid Build Coastguard Worker     /* LCOV_EXCL_STOP */
4315*6be67779SAndroid Build Coastguard Worker   }
4316*6be67779SAndroid Build Coastguard Worker   /* not reached */
4317*6be67779SAndroid Build Coastguard Worker }
4318*6be67779SAndroid Build Coastguard Worker 
4319*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
4320*6be67779SAndroid Build Coastguard Worker 
4321*6be67779SAndroid Build Coastguard Worker static enum XML_Error
initializeEncoding(XML_Parser parser)4322*6be67779SAndroid Build Coastguard Worker initializeEncoding(XML_Parser parser) {
4323*6be67779SAndroid Build Coastguard Worker   const char *s;
4324*6be67779SAndroid Build Coastguard Worker #ifdef XML_UNICODE
4325*6be67779SAndroid Build Coastguard Worker   char encodingBuf[128];
4326*6be67779SAndroid Build Coastguard Worker   /* See comments about `protocolEncodingName` in parserInit() */
4327*6be67779SAndroid Build Coastguard Worker   if (! parser->m_protocolEncodingName)
4328*6be67779SAndroid Build Coastguard Worker     s = NULL;
4329*6be67779SAndroid Build Coastguard Worker   else {
4330*6be67779SAndroid Build Coastguard Worker     int i;
4331*6be67779SAndroid Build Coastguard Worker     for (i = 0; parser->m_protocolEncodingName[i]; i++) {
4332*6be67779SAndroid Build Coastguard Worker       if (i == sizeof(encodingBuf) - 1
4333*6be67779SAndroid Build Coastguard Worker           || (parser->m_protocolEncodingName[i] & ~0x7f) != 0) {
4334*6be67779SAndroid Build Coastguard Worker         encodingBuf[0] = '\0';
4335*6be67779SAndroid Build Coastguard Worker         break;
4336*6be67779SAndroid Build Coastguard Worker       }
4337*6be67779SAndroid Build Coastguard Worker       encodingBuf[i] = (char)parser->m_protocolEncodingName[i];
4338*6be67779SAndroid Build Coastguard Worker     }
4339*6be67779SAndroid Build Coastguard Worker     encodingBuf[i] = '\0';
4340*6be67779SAndroid Build Coastguard Worker     s = encodingBuf;
4341*6be67779SAndroid Build Coastguard Worker   }
4342*6be67779SAndroid Build Coastguard Worker #else
4343*6be67779SAndroid Build Coastguard Worker   s = parser->m_protocolEncodingName;
4344*6be67779SAndroid Build Coastguard Worker #endif
4345*6be67779SAndroid Build Coastguard Worker   if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(
4346*6be67779SAndroid Build Coastguard Worker           &parser->m_initEncoding, &parser->m_encoding, s))
4347*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_NONE;
4348*6be67779SAndroid Build Coastguard Worker   return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
4349*6be67779SAndroid Build Coastguard Worker }
4350*6be67779SAndroid Build Coastguard Worker 
4351*6be67779SAndroid Build Coastguard Worker static enum XML_Error
processXmlDecl(XML_Parser parser,int isGeneralTextEntity,const char * s,const char * next)4352*6be67779SAndroid Build Coastguard Worker processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
4353*6be67779SAndroid Build Coastguard Worker                const char *next) {
4354*6be67779SAndroid Build Coastguard Worker   const char *encodingName = NULL;
4355*6be67779SAndroid Build Coastguard Worker   const XML_Char *storedEncName = NULL;
4356*6be67779SAndroid Build Coastguard Worker   const ENCODING *newEncoding = NULL;
4357*6be67779SAndroid Build Coastguard Worker   const char *version = NULL;
4358*6be67779SAndroid Build Coastguard Worker   const char *versionend = NULL;
4359*6be67779SAndroid Build Coastguard Worker   const XML_Char *storedversion = NULL;
4360*6be67779SAndroid Build Coastguard Worker   int standalone = -1;
4361*6be67779SAndroid Build Coastguard Worker 
4362*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
4363*6be67779SAndroid Build Coastguard Worker   if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__,
4364*6be67779SAndroid Build Coastguard Worker                                 XML_ACCOUNT_DIRECT)) {
4365*6be67779SAndroid Build Coastguard Worker     accountingOnAbort(parser);
4366*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
4367*6be67779SAndroid Build Coastguard Worker   }
4368*6be67779SAndroid Build Coastguard Worker #endif
4369*6be67779SAndroid Build Coastguard Worker 
4370*6be67779SAndroid Build Coastguard Worker   if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
4371*6be67779SAndroid Build Coastguard Worker           isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
4372*6be67779SAndroid Build Coastguard Worker           &version, &versionend, &encodingName, &newEncoding, &standalone)) {
4373*6be67779SAndroid Build Coastguard Worker     if (isGeneralTextEntity)
4374*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_TEXT_DECL;
4375*6be67779SAndroid Build Coastguard Worker     else
4376*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_XML_DECL;
4377*6be67779SAndroid Build Coastguard Worker   }
4378*6be67779SAndroid Build Coastguard Worker   if (! isGeneralTextEntity && standalone == 1) {
4379*6be67779SAndroid Build Coastguard Worker     parser->m_dtd->standalone = XML_TRUE;
4380*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
4381*6be67779SAndroid Build Coastguard Worker     if (parser->m_paramEntityParsing
4382*6be67779SAndroid Build Coastguard Worker         == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
4383*6be67779SAndroid Build Coastguard Worker       parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
4384*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
4385*6be67779SAndroid Build Coastguard Worker   }
4386*6be67779SAndroid Build Coastguard Worker   if (parser->m_xmlDeclHandler) {
4387*6be67779SAndroid Build Coastguard Worker     if (encodingName != NULL) {
4388*6be67779SAndroid Build Coastguard Worker       storedEncName = poolStoreString(
4389*6be67779SAndroid Build Coastguard Worker           &parser->m_temp2Pool, parser->m_encoding, encodingName,
4390*6be67779SAndroid Build Coastguard Worker           encodingName + XmlNameLength(parser->m_encoding, encodingName));
4391*6be67779SAndroid Build Coastguard Worker       if (! storedEncName)
4392*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
4393*6be67779SAndroid Build Coastguard Worker       poolFinish(&parser->m_temp2Pool);
4394*6be67779SAndroid Build Coastguard Worker     }
4395*6be67779SAndroid Build Coastguard Worker     if (version) {
4396*6be67779SAndroid Build Coastguard Worker       storedversion
4397*6be67779SAndroid Build Coastguard Worker           = poolStoreString(&parser->m_temp2Pool, parser->m_encoding, version,
4398*6be67779SAndroid Build Coastguard Worker                             versionend - parser->m_encoding->minBytesPerChar);
4399*6be67779SAndroid Build Coastguard Worker       if (! storedversion)
4400*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
4401*6be67779SAndroid Build Coastguard Worker     }
4402*6be67779SAndroid Build Coastguard Worker     parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName,
4403*6be67779SAndroid Build Coastguard Worker                              standalone);
4404*6be67779SAndroid Build Coastguard Worker   } else if (parser->m_defaultHandler)
4405*6be67779SAndroid Build Coastguard Worker     reportDefault(parser, parser->m_encoding, s, next);
4406*6be67779SAndroid Build Coastguard Worker   if (parser->m_protocolEncodingName == NULL) {
4407*6be67779SAndroid Build Coastguard Worker     if (newEncoding) {
4408*6be67779SAndroid Build Coastguard Worker       /* Check that the specified encoding does not conflict with what
4409*6be67779SAndroid Build Coastguard Worker        * the parser has already deduced.  Do we have the same number
4410*6be67779SAndroid Build Coastguard Worker        * of bytes in the smallest representation of a character?  If
4411*6be67779SAndroid Build Coastguard Worker        * this is UTF-16, is it the same endianness?
4412*6be67779SAndroid Build Coastguard Worker        */
4413*6be67779SAndroid Build Coastguard Worker       if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
4414*6be67779SAndroid Build Coastguard Worker           || (newEncoding->minBytesPerChar == 2
4415*6be67779SAndroid Build Coastguard Worker               && newEncoding != parser->m_encoding)) {
4416*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = encodingName;
4417*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_INCORRECT_ENCODING;
4418*6be67779SAndroid Build Coastguard Worker       }
4419*6be67779SAndroid Build Coastguard Worker       parser->m_encoding = newEncoding;
4420*6be67779SAndroid Build Coastguard Worker     } else if (encodingName) {
4421*6be67779SAndroid Build Coastguard Worker       enum XML_Error result;
4422*6be67779SAndroid Build Coastguard Worker       if (! storedEncName) {
4423*6be67779SAndroid Build Coastguard Worker         storedEncName = poolStoreString(
4424*6be67779SAndroid Build Coastguard Worker             &parser->m_temp2Pool, parser->m_encoding, encodingName,
4425*6be67779SAndroid Build Coastguard Worker             encodingName + XmlNameLength(parser->m_encoding, encodingName));
4426*6be67779SAndroid Build Coastguard Worker         if (! storedEncName)
4427*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
4428*6be67779SAndroid Build Coastguard Worker       }
4429*6be67779SAndroid Build Coastguard Worker       result = handleUnknownEncoding(parser, storedEncName);
4430*6be67779SAndroid Build Coastguard Worker       poolClear(&parser->m_temp2Pool);
4431*6be67779SAndroid Build Coastguard Worker       if (result == XML_ERROR_UNKNOWN_ENCODING)
4432*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = encodingName;
4433*6be67779SAndroid Build Coastguard Worker       return result;
4434*6be67779SAndroid Build Coastguard Worker     }
4435*6be67779SAndroid Build Coastguard Worker   }
4436*6be67779SAndroid Build Coastguard Worker 
4437*6be67779SAndroid Build Coastguard Worker   if (storedEncName || storedversion)
4438*6be67779SAndroid Build Coastguard Worker     poolClear(&parser->m_temp2Pool);
4439*6be67779SAndroid Build Coastguard Worker 
4440*6be67779SAndroid Build Coastguard Worker   return XML_ERROR_NONE;
4441*6be67779SAndroid Build Coastguard Worker }
4442*6be67779SAndroid Build Coastguard Worker 
4443*6be67779SAndroid Build Coastguard Worker static enum XML_Error
handleUnknownEncoding(XML_Parser parser,const XML_Char * encodingName)4444*6be67779SAndroid Build Coastguard Worker handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) {
4445*6be67779SAndroid Build Coastguard Worker   if (parser->m_unknownEncodingHandler) {
4446*6be67779SAndroid Build Coastguard Worker     XML_Encoding info;
4447*6be67779SAndroid Build Coastguard Worker     int i;
4448*6be67779SAndroid Build Coastguard Worker     for (i = 0; i < 256; i++)
4449*6be67779SAndroid Build Coastguard Worker       info.map[i] = -1;
4450*6be67779SAndroid Build Coastguard Worker     info.convert = NULL;
4451*6be67779SAndroid Build Coastguard Worker     info.data = NULL;
4452*6be67779SAndroid Build Coastguard Worker     info.release = NULL;
4453*6be67779SAndroid Build Coastguard Worker     if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData,
4454*6be67779SAndroid Build Coastguard Worker                                          encodingName, &info)) {
4455*6be67779SAndroid Build Coastguard Worker       ENCODING *enc;
4456*6be67779SAndroid Build Coastguard Worker       parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding());
4457*6be67779SAndroid Build Coastguard Worker       if (! parser->m_unknownEncodingMem) {
4458*6be67779SAndroid Build Coastguard Worker         if (info.release)
4459*6be67779SAndroid Build Coastguard Worker           info.release(info.data);
4460*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
4461*6be67779SAndroid Build Coastguard Worker       }
4462*6be67779SAndroid Build Coastguard Worker       enc = (parser->m_ns ? XmlInitUnknownEncodingNS : XmlInitUnknownEncoding)(
4463*6be67779SAndroid Build Coastguard Worker           parser->m_unknownEncodingMem, info.map, info.convert, info.data);
4464*6be67779SAndroid Build Coastguard Worker       if (enc) {
4465*6be67779SAndroid Build Coastguard Worker         parser->m_unknownEncodingData = info.data;
4466*6be67779SAndroid Build Coastguard Worker         parser->m_unknownEncodingRelease = info.release;
4467*6be67779SAndroid Build Coastguard Worker         parser->m_encoding = enc;
4468*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
4469*6be67779SAndroid Build Coastguard Worker       }
4470*6be67779SAndroid Build Coastguard Worker     }
4471*6be67779SAndroid Build Coastguard Worker     if (info.release != NULL)
4472*6be67779SAndroid Build Coastguard Worker       info.release(info.data);
4473*6be67779SAndroid Build Coastguard Worker   }
4474*6be67779SAndroid Build Coastguard Worker   return XML_ERROR_UNKNOWN_ENCODING;
4475*6be67779SAndroid Build Coastguard Worker }
4476*6be67779SAndroid Build Coastguard Worker 
4477*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
prologInitProcessor(XML_Parser parser,const char * s,const char * end,const char ** nextPtr)4478*6be67779SAndroid Build Coastguard Worker prologInitProcessor(XML_Parser parser, const char *s, const char *end,
4479*6be67779SAndroid Build Coastguard Worker                     const char **nextPtr) {
4480*6be67779SAndroid Build Coastguard Worker   enum XML_Error result = initializeEncoding(parser);
4481*6be67779SAndroid Build Coastguard Worker   if (result != XML_ERROR_NONE)
4482*6be67779SAndroid Build Coastguard Worker     return result;
4483*6be67779SAndroid Build Coastguard Worker   parser->m_processor = prologProcessor;
4484*6be67779SAndroid Build Coastguard Worker   return prologProcessor(parser, s, end, nextPtr);
4485*6be67779SAndroid Build Coastguard Worker }
4486*6be67779SAndroid Build Coastguard Worker 
4487*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
4488*6be67779SAndroid Build Coastguard Worker 
4489*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
externalParEntInitProcessor(XML_Parser parser,const char * s,const char * end,const char ** nextPtr)4490*6be67779SAndroid Build Coastguard Worker externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
4491*6be67779SAndroid Build Coastguard Worker                             const char **nextPtr) {
4492*6be67779SAndroid Build Coastguard Worker   enum XML_Error result = initializeEncoding(parser);
4493*6be67779SAndroid Build Coastguard Worker   if (result != XML_ERROR_NONE)
4494*6be67779SAndroid Build Coastguard Worker     return result;
4495*6be67779SAndroid Build Coastguard Worker 
4496*6be67779SAndroid Build Coastguard Worker   /* we know now that XML_Parse(Buffer) has been called,
4497*6be67779SAndroid Build Coastguard Worker      so we consider the external parameter entity read */
4498*6be67779SAndroid Build Coastguard Worker   parser->m_dtd->paramEntityRead = XML_TRUE;
4499*6be67779SAndroid Build Coastguard Worker 
4500*6be67779SAndroid Build Coastguard Worker   if (parser->m_prologState.inEntityValue) {
4501*6be67779SAndroid Build Coastguard Worker     parser->m_processor = entityValueInitProcessor;
4502*6be67779SAndroid Build Coastguard Worker     return entityValueInitProcessor(parser, s, end, nextPtr);
4503*6be67779SAndroid Build Coastguard Worker   } else {
4504*6be67779SAndroid Build Coastguard Worker     parser->m_processor = externalParEntProcessor;
4505*6be67779SAndroid Build Coastguard Worker     return externalParEntProcessor(parser, s, end, nextPtr);
4506*6be67779SAndroid Build Coastguard Worker   }
4507*6be67779SAndroid Build Coastguard Worker }
4508*6be67779SAndroid Build Coastguard Worker 
4509*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
entityValueInitProcessor(XML_Parser parser,const char * s,const char * end,const char ** nextPtr)4510*6be67779SAndroid Build Coastguard Worker entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
4511*6be67779SAndroid Build Coastguard Worker                          const char **nextPtr) {
4512*6be67779SAndroid Build Coastguard Worker   int tok;
4513*6be67779SAndroid Build Coastguard Worker   const char *start = s;
4514*6be67779SAndroid Build Coastguard Worker   const char *next = start;
4515*6be67779SAndroid Build Coastguard Worker   parser->m_eventPtr = start;
4516*6be67779SAndroid Build Coastguard Worker 
4517*6be67779SAndroid Build Coastguard Worker   for (;;) {
4518*6be67779SAndroid Build Coastguard Worker     tok = XmlPrologTok(parser->m_encoding, start, end, &next);
4519*6be67779SAndroid Build Coastguard Worker     /* Note: Except for XML_TOK_BOM below, these bytes are accounted later in:
4520*6be67779SAndroid Build Coastguard Worker              - storeEntityValue
4521*6be67779SAndroid Build Coastguard Worker              - processXmlDecl
4522*6be67779SAndroid Build Coastguard Worker     */
4523*6be67779SAndroid Build Coastguard Worker     parser->m_eventEndPtr = next;
4524*6be67779SAndroid Build Coastguard Worker     if (tok <= 0) {
4525*6be67779SAndroid Build Coastguard Worker       if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
4526*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
4527*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
4528*6be67779SAndroid Build Coastguard Worker       }
4529*6be67779SAndroid Build Coastguard Worker       switch (tok) {
4530*6be67779SAndroid Build Coastguard Worker       case XML_TOK_INVALID:
4531*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_INVALID_TOKEN;
4532*6be67779SAndroid Build Coastguard Worker       case XML_TOK_PARTIAL:
4533*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_UNCLOSED_TOKEN;
4534*6be67779SAndroid Build Coastguard Worker       case XML_TOK_PARTIAL_CHAR:
4535*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_PARTIAL_CHAR;
4536*6be67779SAndroid Build Coastguard Worker       case XML_TOK_NONE: /* start == end */
4537*6be67779SAndroid Build Coastguard Worker       default:
4538*6be67779SAndroid Build Coastguard Worker         break;
4539*6be67779SAndroid Build Coastguard Worker       }
4540*6be67779SAndroid Build Coastguard Worker       /* found end of entity value - can store it now */
4541*6be67779SAndroid Build Coastguard Worker       return storeEntityValue(parser, parser->m_encoding, s, end,
4542*6be67779SAndroid Build Coastguard Worker                               XML_ACCOUNT_DIRECT);
4543*6be67779SAndroid Build Coastguard Worker     } else if (tok == XML_TOK_XML_DECL) {
4544*6be67779SAndroid Build Coastguard Worker       enum XML_Error result;
4545*6be67779SAndroid Build Coastguard Worker       result = processXmlDecl(parser, 0, start, next);
4546*6be67779SAndroid Build Coastguard Worker       if (result != XML_ERROR_NONE)
4547*6be67779SAndroid Build Coastguard Worker         return result;
4548*6be67779SAndroid Build Coastguard Worker       /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED.  For
4549*6be67779SAndroid Build Coastguard Worker        * that to happen, a parameter entity parsing handler must have attempted
4550*6be67779SAndroid Build Coastguard Worker        * to suspend the parser, which fails and raises an error.  The parser can
4551*6be67779SAndroid Build Coastguard Worker        * be aborted, but can't be suspended.
4552*6be67779SAndroid Build Coastguard Worker        */
4553*6be67779SAndroid Build Coastguard Worker       if (parser->m_parsingStatus.parsing == XML_FINISHED)
4554*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_ABORTED;
4555*6be67779SAndroid Build Coastguard Worker       *nextPtr = next;
4556*6be67779SAndroid Build Coastguard Worker       /* stop scanning for text declaration - we found one */
4557*6be67779SAndroid Build Coastguard Worker       parser->m_processor = entityValueProcessor;
4558*6be67779SAndroid Build Coastguard Worker       return entityValueProcessor(parser, next, end, nextPtr);
4559*6be67779SAndroid Build Coastguard Worker     }
4560*6be67779SAndroid Build Coastguard Worker     /* XmlPrologTok has now set the encoding based on the BOM it found, and we
4561*6be67779SAndroid Build Coastguard Worker        must move s and nextPtr forward to consume the BOM.
4562*6be67779SAndroid Build Coastguard Worker 
4563*6be67779SAndroid Build Coastguard Worker        If we didn't, and got XML_TOK_NONE from the next XmlPrologTok call, we
4564*6be67779SAndroid Build Coastguard Worker        would leave the BOM in the buffer and return. On the next call to this
4565*6be67779SAndroid Build Coastguard Worker        function, our XmlPrologTok call would return XML_TOK_INVALID, since it
4566*6be67779SAndroid Build Coastguard Worker        is not valid to have multiple BOMs.
4567*6be67779SAndroid Build Coastguard Worker     */
4568*6be67779SAndroid Build Coastguard Worker     else if (tok == XML_TOK_BOM) {
4569*6be67779SAndroid Build Coastguard Worker #  if XML_GE == 1
4570*6be67779SAndroid Build Coastguard Worker       if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
4571*6be67779SAndroid Build Coastguard Worker                                     XML_ACCOUNT_DIRECT)) {
4572*6be67779SAndroid Build Coastguard Worker         accountingOnAbort(parser);
4573*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
4574*6be67779SAndroid Build Coastguard Worker       }
4575*6be67779SAndroid Build Coastguard Worker #  endif
4576*6be67779SAndroid Build Coastguard Worker 
4577*6be67779SAndroid Build Coastguard Worker       *nextPtr = next;
4578*6be67779SAndroid Build Coastguard Worker       s = next;
4579*6be67779SAndroid Build Coastguard Worker     }
4580*6be67779SAndroid Build Coastguard Worker     /* If we get this token, we have the start of what might be a
4581*6be67779SAndroid Build Coastguard Worker        normal tag, but not a declaration (i.e. it doesn't begin with
4582*6be67779SAndroid Build Coastguard Worker        "<!").  In a DTD context, that isn't legal.
4583*6be67779SAndroid Build Coastguard Worker     */
4584*6be67779SAndroid Build Coastguard Worker     else if (tok == XML_TOK_INSTANCE_START) {
4585*6be67779SAndroid Build Coastguard Worker       *nextPtr = next;
4586*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_SYNTAX;
4587*6be67779SAndroid Build Coastguard Worker     }
4588*6be67779SAndroid Build Coastguard Worker     start = next;
4589*6be67779SAndroid Build Coastguard Worker     parser->m_eventPtr = start;
4590*6be67779SAndroid Build Coastguard Worker   }
4591*6be67779SAndroid Build Coastguard Worker }
4592*6be67779SAndroid Build Coastguard Worker 
4593*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
externalParEntProcessor(XML_Parser parser,const char * s,const char * end,const char ** nextPtr)4594*6be67779SAndroid Build Coastguard Worker externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
4595*6be67779SAndroid Build Coastguard Worker                         const char **nextPtr) {
4596*6be67779SAndroid Build Coastguard Worker   const char *next = s;
4597*6be67779SAndroid Build Coastguard Worker   int tok;
4598*6be67779SAndroid Build Coastguard Worker 
4599*6be67779SAndroid Build Coastguard Worker   tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4600*6be67779SAndroid Build Coastguard Worker   if (tok <= 0) {
4601*6be67779SAndroid Build Coastguard Worker     if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
4602*6be67779SAndroid Build Coastguard Worker       *nextPtr = s;
4603*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
4604*6be67779SAndroid Build Coastguard Worker     }
4605*6be67779SAndroid Build Coastguard Worker     switch (tok) {
4606*6be67779SAndroid Build Coastguard Worker     case XML_TOK_INVALID:
4607*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_INVALID_TOKEN;
4608*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL:
4609*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_UNCLOSED_TOKEN;
4610*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL_CHAR:
4611*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_PARTIAL_CHAR;
4612*6be67779SAndroid Build Coastguard Worker     case XML_TOK_NONE: /* start == end */
4613*6be67779SAndroid Build Coastguard Worker     default:
4614*6be67779SAndroid Build Coastguard Worker       break;
4615*6be67779SAndroid Build Coastguard Worker     }
4616*6be67779SAndroid Build Coastguard Worker   }
4617*6be67779SAndroid Build Coastguard Worker   /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
4618*6be67779SAndroid Build Coastguard Worker      However, when parsing an external subset, doProlog will not accept a BOM
4619*6be67779SAndroid Build Coastguard Worker      as valid, and report a syntax error, so we have to skip the BOM, and
4620*6be67779SAndroid Build Coastguard Worker      account for the BOM bytes.
4621*6be67779SAndroid Build Coastguard Worker   */
4622*6be67779SAndroid Build Coastguard Worker   else if (tok == XML_TOK_BOM) {
4623*6be67779SAndroid Build Coastguard Worker     if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
4624*6be67779SAndroid Build Coastguard Worker                                   XML_ACCOUNT_DIRECT)) {
4625*6be67779SAndroid Build Coastguard Worker       accountingOnAbort(parser);
4626*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
4627*6be67779SAndroid Build Coastguard Worker     }
4628*6be67779SAndroid Build Coastguard Worker 
4629*6be67779SAndroid Build Coastguard Worker     s = next;
4630*6be67779SAndroid Build Coastguard Worker     tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4631*6be67779SAndroid Build Coastguard Worker   }
4632*6be67779SAndroid Build Coastguard Worker 
4633*6be67779SAndroid Build Coastguard Worker   parser->m_processor = prologProcessor;
4634*6be67779SAndroid Build Coastguard Worker   return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
4635*6be67779SAndroid Build Coastguard Worker                   (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
4636*6be67779SAndroid Build Coastguard Worker                   XML_ACCOUNT_DIRECT);
4637*6be67779SAndroid Build Coastguard Worker }
4638*6be67779SAndroid Build Coastguard Worker 
4639*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
entityValueProcessor(XML_Parser parser,const char * s,const char * end,const char ** nextPtr)4640*6be67779SAndroid Build Coastguard Worker entityValueProcessor(XML_Parser parser, const char *s, const char *end,
4641*6be67779SAndroid Build Coastguard Worker                      const char **nextPtr) {
4642*6be67779SAndroid Build Coastguard Worker   const char *start = s;
4643*6be67779SAndroid Build Coastguard Worker   const char *next = s;
4644*6be67779SAndroid Build Coastguard Worker   const ENCODING *enc = parser->m_encoding;
4645*6be67779SAndroid Build Coastguard Worker   int tok;
4646*6be67779SAndroid Build Coastguard Worker 
4647*6be67779SAndroid Build Coastguard Worker   for (;;) {
4648*6be67779SAndroid Build Coastguard Worker     tok = XmlPrologTok(enc, start, end, &next);
4649*6be67779SAndroid Build Coastguard Worker     /* Note: These bytes are accounted later in:
4650*6be67779SAndroid Build Coastguard Worker              - storeEntityValue
4651*6be67779SAndroid Build Coastguard Worker     */
4652*6be67779SAndroid Build Coastguard Worker     if (tok <= 0) {
4653*6be67779SAndroid Build Coastguard Worker       if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
4654*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
4655*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
4656*6be67779SAndroid Build Coastguard Worker       }
4657*6be67779SAndroid Build Coastguard Worker       switch (tok) {
4658*6be67779SAndroid Build Coastguard Worker       case XML_TOK_INVALID:
4659*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_INVALID_TOKEN;
4660*6be67779SAndroid Build Coastguard Worker       case XML_TOK_PARTIAL:
4661*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_UNCLOSED_TOKEN;
4662*6be67779SAndroid Build Coastguard Worker       case XML_TOK_PARTIAL_CHAR:
4663*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_PARTIAL_CHAR;
4664*6be67779SAndroid Build Coastguard Worker       case XML_TOK_NONE: /* start == end */
4665*6be67779SAndroid Build Coastguard Worker       default:
4666*6be67779SAndroid Build Coastguard Worker         break;
4667*6be67779SAndroid Build Coastguard Worker       }
4668*6be67779SAndroid Build Coastguard Worker       /* found end of entity value - can store it now */
4669*6be67779SAndroid Build Coastguard Worker       return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT);
4670*6be67779SAndroid Build Coastguard Worker     }
4671*6be67779SAndroid Build Coastguard Worker     start = next;
4672*6be67779SAndroid Build Coastguard Worker   }
4673*6be67779SAndroid Build Coastguard Worker }
4674*6be67779SAndroid Build Coastguard Worker 
4675*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
4676*6be67779SAndroid Build Coastguard Worker 
4677*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
prologProcessor(XML_Parser parser,const char * s,const char * end,const char ** nextPtr)4678*6be67779SAndroid Build Coastguard Worker prologProcessor(XML_Parser parser, const char *s, const char *end,
4679*6be67779SAndroid Build Coastguard Worker                 const char **nextPtr) {
4680*6be67779SAndroid Build Coastguard Worker   const char *next = s;
4681*6be67779SAndroid Build Coastguard Worker   int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4682*6be67779SAndroid Build Coastguard Worker   return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
4683*6be67779SAndroid Build Coastguard Worker                   (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
4684*6be67779SAndroid Build Coastguard Worker                   XML_ACCOUNT_DIRECT);
4685*6be67779SAndroid Build Coastguard Worker }
4686*6be67779SAndroid Build Coastguard Worker 
4687*6be67779SAndroid Build Coastguard Worker 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)4688*6be67779SAndroid Build Coastguard Worker doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
4689*6be67779SAndroid Build Coastguard Worker          int tok, const char *next, const char **nextPtr, XML_Bool haveMore,
4690*6be67779SAndroid Build Coastguard Worker          XML_Bool allowClosingDoctype, enum XML_Account account) {
4691*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
4692*6be67779SAndroid Build Coastguard Worker   static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
4693*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
4694*6be67779SAndroid Build Coastguard Worker   static const XML_Char atypeCDATA[]
4695*6be67779SAndroid Build Coastguard Worker       = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
4696*6be67779SAndroid Build Coastguard Worker   static const XML_Char atypeID[] = {ASCII_I, ASCII_D, '\0'};
4697*6be67779SAndroid Build Coastguard Worker   static const XML_Char atypeIDREF[]
4698*6be67779SAndroid Build Coastguard Worker       = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'};
4699*6be67779SAndroid Build Coastguard Worker   static const XML_Char atypeIDREFS[]
4700*6be67779SAndroid Build Coastguard Worker       = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0'};
4701*6be67779SAndroid Build Coastguard Worker   static const XML_Char atypeENTITY[]
4702*6be67779SAndroid Build Coastguard Worker       = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0'};
4703*6be67779SAndroid Build Coastguard Worker   static const XML_Char atypeENTITIES[]
4704*6be67779SAndroid Build Coastguard Worker       = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T,
4705*6be67779SAndroid Build Coastguard Worker          ASCII_I, ASCII_E, ASCII_S, '\0'};
4706*6be67779SAndroid Build Coastguard Worker   static const XML_Char atypeNMTOKEN[]
4707*6be67779SAndroid Build Coastguard Worker       = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0'};
4708*6be67779SAndroid Build Coastguard Worker   static const XML_Char atypeNMTOKENS[]
4709*6be67779SAndroid Build Coastguard Worker       = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K,
4710*6be67779SAndroid Build Coastguard Worker          ASCII_E, ASCII_N, ASCII_S, '\0'};
4711*6be67779SAndroid Build Coastguard Worker   static const XML_Char notationPrefix[]
4712*6be67779SAndroid Build Coastguard Worker       = {ASCII_N, ASCII_O, ASCII_T, ASCII_A,      ASCII_T,
4713*6be67779SAndroid Build Coastguard Worker          ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0'};
4714*6be67779SAndroid Build Coastguard Worker   static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
4715*6be67779SAndroid Build Coastguard Worker   static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
4716*6be67779SAndroid Build Coastguard Worker 
4717*6be67779SAndroid Build Coastguard Worker #ifndef XML_DTD
4718*6be67779SAndroid Build Coastguard Worker   UNUSED_P(account);
4719*6be67779SAndroid Build Coastguard Worker #endif
4720*6be67779SAndroid Build Coastguard Worker 
4721*6be67779SAndroid Build Coastguard Worker   /* save one level of indirection */
4722*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd;
4723*6be67779SAndroid Build Coastguard Worker 
4724*6be67779SAndroid Build Coastguard Worker   const char **eventPP;
4725*6be67779SAndroid Build Coastguard Worker   const char **eventEndPP;
4726*6be67779SAndroid Build Coastguard Worker   enum XML_Content_Quant quant;
4727*6be67779SAndroid Build Coastguard Worker 
4728*6be67779SAndroid Build Coastguard Worker   if (enc == parser->m_encoding) {
4729*6be67779SAndroid Build Coastguard Worker     eventPP = &parser->m_eventPtr;
4730*6be67779SAndroid Build Coastguard Worker     eventEndPP = &parser->m_eventEndPtr;
4731*6be67779SAndroid Build Coastguard Worker   } else {
4732*6be67779SAndroid Build Coastguard Worker     eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4733*6be67779SAndroid Build Coastguard Worker     eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
4734*6be67779SAndroid Build Coastguard Worker   }
4735*6be67779SAndroid Build Coastguard Worker 
4736*6be67779SAndroid Build Coastguard Worker   for (;;) {
4737*6be67779SAndroid Build Coastguard Worker     int role;
4738*6be67779SAndroid Build Coastguard Worker     XML_Bool handleDefault = XML_TRUE;
4739*6be67779SAndroid Build Coastguard Worker     *eventPP = s;
4740*6be67779SAndroid Build Coastguard Worker     *eventEndPP = next;
4741*6be67779SAndroid Build Coastguard Worker     if (tok <= 0) {
4742*6be67779SAndroid Build Coastguard Worker       if (haveMore && tok != XML_TOK_INVALID) {
4743*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
4744*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
4745*6be67779SAndroid Build Coastguard Worker       }
4746*6be67779SAndroid Build Coastguard Worker       switch (tok) {
4747*6be67779SAndroid Build Coastguard Worker       case XML_TOK_INVALID:
4748*6be67779SAndroid Build Coastguard Worker         *eventPP = next;
4749*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_INVALID_TOKEN;
4750*6be67779SAndroid Build Coastguard Worker       case XML_TOK_PARTIAL:
4751*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_UNCLOSED_TOKEN;
4752*6be67779SAndroid Build Coastguard Worker       case XML_TOK_PARTIAL_CHAR:
4753*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_PARTIAL_CHAR;
4754*6be67779SAndroid Build Coastguard Worker       case -XML_TOK_PROLOG_S:
4755*6be67779SAndroid Build Coastguard Worker         tok = -tok;
4756*6be67779SAndroid Build Coastguard Worker         break;
4757*6be67779SAndroid Build Coastguard Worker       case XML_TOK_NONE:
4758*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
4759*6be67779SAndroid Build Coastguard Worker         /* for internal PE NOT referenced between declarations */
4760*6be67779SAndroid Build Coastguard Worker         if (enc != parser->m_encoding
4761*6be67779SAndroid Build Coastguard Worker             && ! parser->m_openInternalEntities->betweenDecl) {
4762*6be67779SAndroid Build Coastguard Worker           *nextPtr = s;
4763*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NONE;
4764*6be67779SAndroid Build Coastguard Worker         }
4765*6be67779SAndroid Build Coastguard Worker         /* WFC: PE Between Declarations - must check that PE contains
4766*6be67779SAndroid Build Coastguard Worker            complete markup, not only for external PEs, but also for
4767*6be67779SAndroid Build Coastguard Worker            internal PEs if the reference occurs between declarations.
4768*6be67779SAndroid Build Coastguard Worker         */
4769*6be67779SAndroid Build Coastguard Worker         if (parser->m_isParamEntity || enc != parser->m_encoding) {
4770*6be67779SAndroid Build Coastguard Worker           if (XmlTokenRole(&parser->m_prologState, XML_TOK_NONE, end, end, enc)
4771*6be67779SAndroid Build Coastguard Worker               == XML_ROLE_ERROR)
4772*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_INCOMPLETE_PE;
4773*6be67779SAndroid Build Coastguard Worker           *nextPtr = s;
4774*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NONE;
4775*6be67779SAndroid Build Coastguard Worker         }
4776*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
4777*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_ELEMENTS;
4778*6be67779SAndroid Build Coastguard Worker       default:
4779*6be67779SAndroid Build Coastguard Worker         tok = -tok;
4780*6be67779SAndroid Build Coastguard Worker         next = end;
4781*6be67779SAndroid Build Coastguard Worker         break;
4782*6be67779SAndroid Build Coastguard Worker       }
4783*6be67779SAndroid Build Coastguard Worker     }
4784*6be67779SAndroid Build Coastguard Worker     role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
4785*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
4786*6be67779SAndroid Build Coastguard Worker     switch (role) {
4787*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor
4788*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_XML_DECL:       // bytes accounted in processXmlDecl
4789*6be67779SAndroid Build Coastguard Worker #  ifdef XML_DTD
4790*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl
4791*6be67779SAndroid Build Coastguard Worker #  endif
4792*6be67779SAndroid Build Coastguard Worker       break;
4793*6be67779SAndroid Build Coastguard Worker     default:
4794*6be67779SAndroid Build Coastguard Worker       if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
4795*6be67779SAndroid Build Coastguard Worker         accountingOnAbort(parser);
4796*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
4797*6be67779SAndroid Build Coastguard Worker       }
4798*6be67779SAndroid Build Coastguard Worker     }
4799*6be67779SAndroid Build Coastguard Worker #endif
4800*6be67779SAndroid Build Coastguard Worker     switch (role) {
4801*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_XML_DECL: {
4802*6be67779SAndroid Build Coastguard Worker       enum XML_Error result = processXmlDecl(parser, 0, s, next);
4803*6be67779SAndroid Build Coastguard Worker       if (result != XML_ERROR_NONE)
4804*6be67779SAndroid Build Coastguard Worker         return result;
4805*6be67779SAndroid Build Coastguard Worker       enc = parser->m_encoding;
4806*6be67779SAndroid Build Coastguard Worker       handleDefault = XML_FALSE;
4807*6be67779SAndroid Build Coastguard Worker     } break;
4808*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_DOCTYPE_NAME:
4809*6be67779SAndroid Build Coastguard Worker       if (parser->m_startDoctypeDeclHandler) {
4810*6be67779SAndroid Build Coastguard Worker         parser->m_doctypeName
4811*6be67779SAndroid Build Coastguard Worker             = poolStoreString(&parser->m_tempPool, enc, s, next);
4812*6be67779SAndroid Build Coastguard Worker         if (! parser->m_doctypeName)
4813*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
4814*6be67779SAndroid Build Coastguard Worker         poolFinish(&parser->m_tempPool);
4815*6be67779SAndroid Build Coastguard Worker         parser->m_doctypePubid = NULL;
4816*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
4817*6be67779SAndroid Build Coastguard Worker       }
4818*6be67779SAndroid Build Coastguard Worker       parser->m_doctypeSysid = NULL; /* always initialize to NULL */
4819*6be67779SAndroid Build Coastguard Worker       break;
4820*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
4821*6be67779SAndroid Build Coastguard Worker       if (parser->m_startDoctypeDeclHandler) {
4822*6be67779SAndroid Build Coastguard Worker         parser->m_startDoctypeDeclHandler(
4823*6be67779SAndroid Build Coastguard Worker             parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
4824*6be67779SAndroid Build Coastguard Worker             parser->m_doctypePubid, 1);
4825*6be67779SAndroid Build Coastguard Worker         parser->m_doctypeName = NULL;
4826*6be67779SAndroid Build Coastguard Worker         poolClear(&parser->m_tempPool);
4827*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
4828*6be67779SAndroid Build Coastguard Worker       }
4829*6be67779SAndroid Build Coastguard Worker       break;
4830*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
4831*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_TEXT_DECL: {
4832*6be67779SAndroid Build Coastguard Worker       enum XML_Error result = processXmlDecl(parser, 1, s, next);
4833*6be67779SAndroid Build Coastguard Worker       if (result != XML_ERROR_NONE)
4834*6be67779SAndroid Build Coastguard Worker         return result;
4835*6be67779SAndroid Build Coastguard Worker       enc = parser->m_encoding;
4836*6be67779SAndroid Build Coastguard Worker       handleDefault = XML_FALSE;
4837*6be67779SAndroid Build Coastguard Worker     } break;
4838*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
4839*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_DOCTYPE_PUBLIC_ID:
4840*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
4841*6be67779SAndroid Build Coastguard Worker       parser->m_useForeignDTD = XML_FALSE;
4842*6be67779SAndroid Build Coastguard Worker       parser->m_declEntity = (ENTITY *)lookup(
4843*6be67779SAndroid Build Coastguard Worker           parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
4844*6be67779SAndroid Build Coastguard Worker       if (! parser->m_declEntity)
4845*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
4846*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
4847*6be67779SAndroid Build Coastguard Worker       dtd->hasParamEntityRefs = XML_TRUE;
4848*6be67779SAndroid Build Coastguard Worker       if (parser->m_startDoctypeDeclHandler) {
4849*6be67779SAndroid Build Coastguard Worker         XML_Char *pubId;
4850*6be67779SAndroid Build Coastguard Worker         if (! XmlIsPublicId(enc, s, next, eventPP))
4851*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_PUBLICID;
4852*6be67779SAndroid Build Coastguard Worker         pubId = poolStoreString(&parser->m_tempPool, enc,
4853*6be67779SAndroid Build Coastguard Worker                                 s + enc->minBytesPerChar,
4854*6be67779SAndroid Build Coastguard Worker                                 next - enc->minBytesPerChar);
4855*6be67779SAndroid Build Coastguard Worker         if (! pubId)
4856*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
4857*6be67779SAndroid Build Coastguard Worker         normalizePublicId(pubId);
4858*6be67779SAndroid Build Coastguard Worker         poolFinish(&parser->m_tempPool);
4859*6be67779SAndroid Build Coastguard Worker         parser->m_doctypePubid = pubId;
4860*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
4861*6be67779SAndroid Build Coastguard Worker         goto alreadyChecked;
4862*6be67779SAndroid Build Coastguard Worker       }
4863*6be67779SAndroid Build Coastguard Worker       /* fall through */
4864*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ENTITY_PUBLIC_ID:
4865*6be67779SAndroid Build Coastguard Worker       if (! XmlIsPublicId(enc, s, next, eventPP))
4866*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_PUBLICID;
4867*6be67779SAndroid Build Coastguard Worker     alreadyChecked:
4868*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing && parser->m_declEntity) {
4869*6be67779SAndroid Build Coastguard Worker         XML_Char *tem
4870*6be67779SAndroid Build Coastguard Worker             = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
4871*6be67779SAndroid Build Coastguard Worker                               next - enc->minBytesPerChar);
4872*6be67779SAndroid Build Coastguard Worker         if (! tem)
4873*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
4874*6be67779SAndroid Build Coastguard Worker         normalizePublicId(tem);
4875*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity->publicId = tem;
4876*6be67779SAndroid Build Coastguard Worker         poolFinish(&dtd->pool);
4877*6be67779SAndroid Build Coastguard Worker         /* Don't suppress the default handler if we fell through from
4878*6be67779SAndroid Build Coastguard Worker          * the XML_ROLE_DOCTYPE_PUBLIC_ID case.
4879*6be67779SAndroid Build Coastguard Worker          */
4880*6be67779SAndroid Build Coastguard Worker         if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID)
4881*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
4882*6be67779SAndroid Build Coastguard Worker       }
4883*6be67779SAndroid Build Coastguard Worker       break;
4884*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_DOCTYPE_CLOSE:
4885*6be67779SAndroid Build Coastguard Worker       if (allowClosingDoctype != XML_TRUE) {
4886*6be67779SAndroid Build Coastguard Worker         /* Must not close doctype from within expanded parameter entities */
4887*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_INVALID_TOKEN;
4888*6be67779SAndroid Build Coastguard Worker       }
4889*6be67779SAndroid Build Coastguard Worker 
4890*6be67779SAndroid Build Coastguard Worker       if (parser->m_doctypeName) {
4891*6be67779SAndroid Build Coastguard Worker         parser->m_startDoctypeDeclHandler(
4892*6be67779SAndroid Build Coastguard Worker             parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
4893*6be67779SAndroid Build Coastguard Worker             parser->m_doctypePubid, 0);
4894*6be67779SAndroid Build Coastguard Worker         poolClear(&parser->m_tempPool);
4895*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
4896*6be67779SAndroid Build Coastguard Worker       }
4897*6be67779SAndroid Build Coastguard Worker       /* parser->m_doctypeSysid will be non-NULL in the case of a previous
4898*6be67779SAndroid Build Coastguard Worker          XML_ROLE_DOCTYPE_SYSTEM_ID, even if parser->m_startDoctypeDeclHandler
4899*6be67779SAndroid Build Coastguard Worker          was not set, indicating an external subset
4900*6be67779SAndroid Build Coastguard Worker       */
4901*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
4902*6be67779SAndroid Build Coastguard Worker       if (parser->m_doctypeSysid || parser->m_useForeignDTD) {
4903*6be67779SAndroid Build Coastguard Worker         XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4904*6be67779SAndroid Build Coastguard Worker         dtd->hasParamEntityRefs = XML_TRUE;
4905*6be67779SAndroid Build Coastguard Worker         if (parser->m_paramEntityParsing
4906*6be67779SAndroid Build Coastguard Worker             && parser->m_externalEntityRefHandler) {
4907*6be67779SAndroid Build Coastguard Worker           ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4908*6be67779SAndroid Build Coastguard Worker                                             externalSubsetName, sizeof(ENTITY));
4909*6be67779SAndroid Build Coastguard Worker           if (! entity) {
4910*6be67779SAndroid Build Coastguard Worker             /* The external subset name "#" will have already been
4911*6be67779SAndroid Build Coastguard Worker              * inserted into the hash table at the start of the
4912*6be67779SAndroid Build Coastguard Worker              * external entity parsing, so no allocation will happen
4913*6be67779SAndroid Build Coastguard Worker              * and lookup() cannot fail.
4914*6be67779SAndroid Build Coastguard Worker              */
4915*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
4916*6be67779SAndroid Build Coastguard Worker           }
4917*6be67779SAndroid Build Coastguard Worker           if (parser->m_useForeignDTD)
4918*6be67779SAndroid Build Coastguard Worker             entity->base = parser->m_curBase;
4919*6be67779SAndroid Build Coastguard Worker           dtd->paramEntityRead = XML_FALSE;
4920*6be67779SAndroid Build Coastguard Worker           if (! parser->m_externalEntityRefHandler(
4921*6be67779SAndroid Build Coastguard Worker                   parser->m_externalEntityRefHandlerArg, 0, entity->base,
4922*6be67779SAndroid Build Coastguard Worker                   entity->systemId, entity->publicId))
4923*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4924*6be67779SAndroid Build Coastguard Worker           if (dtd->paramEntityRead) {
4925*6be67779SAndroid Build Coastguard Worker             if (! dtd->standalone && parser->m_notStandaloneHandler
4926*6be67779SAndroid Build Coastguard Worker                 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
4927*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NOT_STANDALONE;
4928*6be67779SAndroid Build Coastguard Worker           }
4929*6be67779SAndroid Build Coastguard Worker           /* if we didn't read the foreign DTD then this means that there
4930*6be67779SAndroid Build Coastguard Worker              is no external subset and we must reset dtd->hasParamEntityRefs
4931*6be67779SAndroid Build Coastguard Worker           */
4932*6be67779SAndroid Build Coastguard Worker           else if (! parser->m_doctypeSysid)
4933*6be67779SAndroid Build Coastguard Worker             dtd->hasParamEntityRefs = hadParamEntityRefs;
4934*6be67779SAndroid Build Coastguard Worker           /* end of DTD - no need to update dtd->keepProcessing */
4935*6be67779SAndroid Build Coastguard Worker         }
4936*6be67779SAndroid Build Coastguard Worker         parser->m_useForeignDTD = XML_FALSE;
4937*6be67779SAndroid Build Coastguard Worker       }
4938*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
4939*6be67779SAndroid Build Coastguard Worker       if (parser->m_endDoctypeDeclHandler) {
4940*6be67779SAndroid Build Coastguard Worker         parser->m_endDoctypeDeclHandler(parser->m_handlerArg);
4941*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
4942*6be67779SAndroid Build Coastguard Worker       }
4943*6be67779SAndroid Build Coastguard Worker       break;
4944*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_INSTANCE_START:
4945*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
4946*6be67779SAndroid Build Coastguard Worker       /* if there is no DOCTYPE declaration then now is the
4947*6be67779SAndroid Build Coastguard Worker          last chance to read the foreign DTD
4948*6be67779SAndroid Build Coastguard Worker       */
4949*6be67779SAndroid Build Coastguard Worker       if (parser->m_useForeignDTD) {
4950*6be67779SAndroid Build Coastguard Worker         XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4951*6be67779SAndroid Build Coastguard Worker         dtd->hasParamEntityRefs = XML_TRUE;
4952*6be67779SAndroid Build Coastguard Worker         if (parser->m_paramEntityParsing
4953*6be67779SAndroid Build Coastguard Worker             && parser->m_externalEntityRefHandler) {
4954*6be67779SAndroid Build Coastguard Worker           ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4955*6be67779SAndroid Build Coastguard Worker                                             externalSubsetName, sizeof(ENTITY));
4956*6be67779SAndroid Build Coastguard Worker           if (! entity)
4957*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_NO_MEMORY;
4958*6be67779SAndroid Build Coastguard Worker           entity->base = parser->m_curBase;
4959*6be67779SAndroid Build Coastguard Worker           dtd->paramEntityRead = XML_FALSE;
4960*6be67779SAndroid Build Coastguard Worker           if (! parser->m_externalEntityRefHandler(
4961*6be67779SAndroid Build Coastguard Worker                   parser->m_externalEntityRefHandlerArg, 0, entity->base,
4962*6be67779SAndroid Build Coastguard Worker                   entity->systemId, entity->publicId))
4963*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4964*6be67779SAndroid Build Coastguard Worker           if (dtd->paramEntityRead) {
4965*6be67779SAndroid Build Coastguard Worker             if (! dtd->standalone && parser->m_notStandaloneHandler
4966*6be67779SAndroid Build Coastguard Worker                 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
4967*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NOT_STANDALONE;
4968*6be67779SAndroid Build Coastguard Worker           }
4969*6be67779SAndroid Build Coastguard Worker           /* if we didn't read the foreign DTD then this means that there
4970*6be67779SAndroid Build Coastguard Worker              is no external subset and we must reset dtd->hasParamEntityRefs
4971*6be67779SAndroid Build Coastguard Worker           */
4972*6be67779SAndroid Build Coastguard Worker           else
4973*6be67779SAndroid Build Coastguard Worker             dtd->hasParamEntityRefs = hadParamEntityRefs;
4974*6be67779SAndroid Build Coastguard Worker           /* end of DTD - no need to update dtd->keepProcessing */
4975*6be67779SAndroid Build Coastguard Worker         }
4976*6be67779SAndroid Build Coastguard Worker       }
4977*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
4978*6be67779SAndroid Build Coastguard Worker       parser->m_processor = contentProcessor;
4979*6be67779SAndroid Build Coastguard Worker       return contentProcessor(parser, s, end, nextPtr);
4980*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTLIST_ELEMENT_NAME:
4981*6be67779SAndroid Build Coastguard Worker       parser->m_declElementType = getElementType(parser, enc, s, next);
4982*6be67779SAndroid Build Coastguard Worker       if (! parser->m_declElementType)
4983*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
4984*6be67779SAndroid Build Coastguard Worker       goto checkAttListDeclHandler;
4985*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_NAME:
4986*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
4987*6be67779SAndroid Build Coastguard Worker       if (! parser->m_declAttributeId)
4988*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
4989*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeIsCdata = XML_FALSE;
4990*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeType = NULL;
4991*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeIsId = XML_FALSE;
4992*6be67779SAndroid Build Coastguard Worker       goto checkAttListDeclHandler;
4993*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
4994*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeIsCdata = XML_TRUE;
4995*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeType = atypeCDATA;
4996*6be67779SAndroid Build Coastguard Worker       goto checkAttListDeclHandler;
4997*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_TYPE_ID:
4998*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeIsId = XML_TRUE;
4999*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeType = atypeID;
5000*6be67779SAndroid Build Coastguard Worker       goto checkAttListDeclHandler;
5001*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
5002*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeType = atypeIDREF;
5003*6be67779SAndroid Build Coastguard Worker       goto checkAttListDeclHandler;
5004*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
5005*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeType = atypeIDREFS;
5006*6be67779SAndroid Build Coastguard Worker       goto checkAttListDeclHandler;
5007*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
5008*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeType = atypeENTITY;
5009*6be67779SAndroid Build Coastguard Worker       goto checkAttListDeclHandler;
5010*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
5011*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeType = atypeENTITIES;
5012*6be67779SAndroid Build Coastguard Worker       goto checkAttListDeclHandler;
5013*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
5014*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeType = atypeNMTOKEN;
5015*6be67779SAndroid Build Coastguard Worker       goto checkAttListDeclHandler;
5016*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
5017*6be67779SAndroid Build Coastguard Worker       parser->m_declAttributeType = atypeNMTOKENS;
5018*6be67779SAndroid Build Coastguard Worker     checkAttListDeclHandler:
5019*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing && parser->m_attlistDeclHandler)
5020*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5021*6be67779SAndroid Build Coastguard Worker       break;
5022*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
5023*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
5024*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing && parser->m_attlistDeclHandler) {
5025*6be67779SAndroid Build Coastguard Worker         const XML_Char *prefix;
5026*6be67779SAndroid Build Coastguard Worker         if (parser->m_declAttributeType) {
5027*6be67779SAndroid Build Coastguard Worker           prefix = enumValueSep;
5028*6be67779SAndroid Build Coastguard Worker         } else {
5029*6be67779SAndroid Build Coastguard Worker           prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE ? notationPrefix
5030*6be67779SAndroid Build Coastguard Worker                                                               : enumValueStart);
5031*6be67779SAndroid Build Coastguard Worker         }
5032*6be67779SAndroid Build Coastguard Worker         if (! poolAppendString(&parser->m_tempPool, prefix))
5033*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5034*6be67779SAndroid Build Coastguard Worker         if (! poolAppend(&parser->m_tempPool, enc, s, next))
5035*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5036*6be67779SAndroid Build Coastguard Worker         parser->m_declAttributeType = parser->m_tempPool.start;
5037*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5038*6be67779SAndroid Build Coastguard Worker       }
5039*6be67779SAndroid Build Coastguard Worker       break;
5040*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
5041*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
5042*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing) {
5043*6be67779SAndroid Build Coastguard Worker         if (! defineAttribute(parser->m_declElementType,
5044*6be67779SAndroid Build Coastguard Worker                               parser->m_declAttributeId,
5045*6be67779SAndroid Build Coastguard Worker                               parser->m_declAttributeIsCdata,
5046*6be67779SAndroid Build Coastguard Worker                               parser->m_declAttributeIsId, 0, parser))
5047*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5048*6be67779SAndroid Build Coastguard Worker         if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
5049*6be67779SAndroid Build Coastguard Worker           if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
5050*6be67779SAndroid Build Coastguard Worker               || (*parser->m_declAttributeType == XML_T(ASCII_N)
5051*6be67779SAndroid Build Coastguard Worker                   && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
5052*6be67779SAndroid Build Coastguard Worker             /* Enumerated or Notation type */
5053*6be67779SAndroid Build Coastguard Worker             if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
5054*6be67779SAndroid Build Coastguard Worker                 || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
5055*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NO_MEMORY;
5056*6be67779SAndroid Build Coastguard Worker             parser->m_declAttributeType = parser->m_tempPool.start;
5057*6be67779SAndroid Build Coastguard Worker             poolFinish(&parser->m_tempPool);
5058*6be67779SAndroid Build Coastguard Worker           }
5059*6be67779SAndroid Build Coastguard Worker           *eventEndPP = s;
5060*6be67779SAndroid Build Coastguard Worker           parser->m_attlistDeclHandler(
5061*6be67779SAndroid Build Coastguard Worker               parser->m_handlerArg, parser->m_declElementType->name,
5062*6be67779SAndroid Build Coastguard Worker               parser->m_declAttributeId->name, parser->m_declAttributeType, 0,
5063*6be67779SAndroid Build Coastguard Worker               role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
5064*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5065*6be67779SAndroid Build Coastguard Worker         }
5066*6be67779SAndroid Build Coastguard Worker       }
5067*6be67779SAndroid Build Coastguard Worker       poolClear(&parser->m_tempPool);
5068*6be67779SAndroid Build Coastguard Worker       break;
5069*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
5070*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
5071*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing) {
5072*6be67779SAndroid Build Coastguard Worker         const XML_Char *attVal;
5073*6be67779SAndroid Build Coastguard Worker         enum XML_Error result = storeAttributeValue(
5074*6be67779SAndroid Build Coastguard Worker             parser, enc, parser->m_declAttributeIsCdata,
5075*6be67779SAndroid Build Coastguard Worker             s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool,
5076*6be67779SAndroid Build Coastguard Worker             XML_ACCOUNT_NONE);
5077*6be67779SAndroid Build Coastguard Worker         if (result)
5078*6be67779SAndroid Build Coastguard Worker           return result;
5079*6be67779SAndroid Build Coastguard Worker         attVal = poolStart(&dtd->pool);
5080*6be67779SAndroid Build Coastguard Worker         poolFinish(&dtd->pool);
5081*6be67779SAndroid Build Coastguard Worker         /* ID attributes aren't allowed to have a default */
5082*6be67779SAndroid Build Coastguard Worker         if (! defineAttribute(
5083*6be67779SAndroid Build Coastguard Worker                 parser->m_declElementType, parser->m_declAttributeId,
5084*6be67779SAndroid Build Coastguard Worker                 parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
5085*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5086*6be67779SAndroid Build Coastguard Worker         if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
5087*6be67779SAndroid Build Coastguard Worker           if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
5088*6be67779SAndroid Build Coastguard Worker               || (*parser->m_declAttributeType == XML_T(ASCII_N)
5089*6be67779SAndroid Build Coastguard Worker                   && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
5090*6be67779SAndroid Build Coastguard Worker             /* Enumerated or Notation type */
5091*6be67779SAndroid Build Coastguard Worker             if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
5092*6be67779SAndroid Build Coastguard Worker                 || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
5093*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NO_MEMORY;
5094*6be67779SAndroid Build Coastguard Worker             parser->m_declAttributeType = parser->m_tempPool.start;
5095*6be67779SAndroid Build Coastguard Worker             poolFinish(&parser->m_tempPool);
5096*6be67779SAndroid Build Coastguard Worker           }
5097*6be67779SAndroid Build Coastguard Worker           *eventEndPP = s;
5098*6be67779SAndroid Build Coastguard Worker           parser->m_attlistDeclHandler(
5099*6be67779SAndroid Build Coastguard Worker               parser->m_handlerArg, parser->m_declElementType->name,
5100*6be67779SAndroid Build Coastguard Worker               parser->m_declAttributeId->name, parser->m_declAttributeType,
5101*6be67779SAndroid Build Coastguard Worker               attVal, role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
5102*6be67779SAndroid Build Coastguard Worker           poolClear(&parser->m_tempPool);
5103*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5104*6be67779SAndroid Build Coastguard Worker         }
5105*6be67779SAndroid Build Coastguard Worker       }
5106*6be67779SAndroid Build Coastguard Worker       break;
5107*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ENTITY_VALUE:
5108*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing) {
5109*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
5110*6be67779SAndroid Build Coastguard Worker         // This will store the given replacement text in
5111*6be67779SAndroid Build Coastguard Worker         // parser->m_declEntity->textPtr.
5112*6be67779SAndroid Build Coastguard Worker         enum XML_Error result
5113*6be67779SAndroid Build Coastguard Worker             = storeEntityValue(parser, enc, s + enc->minBytesPerChar,
5114*6be67779SAndroid Build Coastguard Worker                                next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
5115*6be67779SAndroid Build Coastguard Worker         if (parser->m_declEntity) {
5116*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
5117*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity->textLen
5118*6be67779SAndroid Build Coastguard Worker               = (int)(poolLength(&dtd->entityValuePool));
5119*6be67779SAndroid Build Coastguard Worker           poolFinish(&dtd->entityValuePool);
5120*6be67779SAndroid Build Coastguard Worker           if (parser->m_entityDeclHandler) {
5121*6be67779SAndroid Build Coastguard Worker             *eventEndPP = s;
5122*6be67779SAndroid Build Coastguard Worker             parser->m_entityDeclHandler(
5123*6be67779SAndroid Build Coastguard Worker                 parser->m_handlerArg, parser->m_declEntity->name,
5124*6be67779SAndroid Build Coastguard Worker                 parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
5125*6be67779SAndroid Build Coastguard Worker                 parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
5126*6be67779SAndroid Build Coastguard Worker             handleDefault = XML_FALSE;
5127*6be67779SAndroid Build Coastguard Worker           }
5128*6be67779SAndroid Build Coastguard Worker         } else
5129*6be67779SAndroid Build Coastguard Worker           poolDiscard(&dtd->entityValuePool);
5130*6be67779SAndroid Build Coastguard Worker         if (result != XML_ERROR_NONE)
5131*6be67779SAndroid Build Coastguard Worker           return result;
5132*6be67779SAndroid Build Coastguard Worker #else
5133*6be67779SAndroid Build Coastguard Worker         // This will store "&amp;entity123;" in parser->m_declEntity->textPtr
5134*6be67779SAndroid Build Coastguard Worker         // to end up as "&entity123;" in the handler.
5135*6be67779SAndroid Build Coastguard Worker         if (parser->m_declEntity != NULL) {
5136*6be67779SAndroid Build Coastguard Worker           const enum XML_Error result
5137*6be67779SAndroid Build Coastguard Worker               = storeSelfEntityValue(parser, parser->m_declEntity);
5138*6be67779SAndroid Build Coastguard Worker           if (result != XML_ERROR_NONE)
5139*6be67779SAndroid Build Coastguard Worker             return result;
5140*6be67779SAndroid Build Coastguard Worker 
5141*6be67779SAndroid Build Coastguard Worker           if (parser->m_entityDeclHandler) {
5142*6be67779SAndroid Build Coastguard Worker             *eventEndPP = s;
5143*6be67779SAndroid Build Coastguard Worker             parser->m_entityDeclHandler(
5144*6be67779SAndroid Build Coastguard Worker                 parser->m_handlerArg, parser->m_declEntity->name,
5145*6be67779SAndroid Build Coastguard Worker                 parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
5146*6be67779SAndroid Build Coastguard Worker                 parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
5147*6be67779SAndroid Build Coastguard Worker             handleDefault = XML_FALSE;
5148*6be67779SAndroid Build Coastguard Worker           }
5149*6be67779SAndroid Build Coastguard Worker         }
5150*6be67779SAndroid Build Coastguard Worker #endif
5151*6be67779SAndroid Build Coastguard Worker       }
5152*6be67779SAndroid Build Coastguard Worker       break;
5153*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_DOCTYPE_SYSTEM_ID:
5154*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
5155*6be67779SAndroid Build Coastguard Worker       parser->m_useForeignDTD = XML_FALSE;
5156*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
5157*6be67779SAndroid Build Coastguard Worker       dtd->hasParamEntityRefs = XML_TRUE;
5158*6be67779SAndroid Build Coastguard Worker       if (parser->m_startDoctypeDeclHandler) {
5159*6be67779SAndroid Build Coastguard Worker         parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc,
5160*6be67779SAndroid Build Coastguard Worker                                                  s + enc->minBytesPerChar,
5161*6be67779SAndroid Build Coastguard Worker                                                  next - enc->minBytesPerChar);
5162*6be67779SAndroid Build Coastguard Worker         if (parser->m_doctypeSysid == NULL)
5163*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5164*6be67779SAndroid Build Coastguard Worker         poolFinish(&parser->m_tempPool);
5165*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5166*6be67779SAndroid Build Coastguard Worker       }
5167*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
5168*6be67779SAndroid Build Coastguard Worker       else
5169*6be67779SAndroid Build Coastguard Worker         /* use externalSubsetName to make parser->m_doctypeSysid non-NULL
5170*6be67779SAndroid Build Coastguard Worker            for the case where no parser->m_startDoctypeDeclHandler is set */
5171*6be67779SAndroid Build Coastguard Worker         parser->m_doctypeSysid = externalSubsetName;
5172*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
5173*6be67779SAndroid Build Coastguard Worker       if (! dtd->standalone
5174*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
5175*6be67779SAndroid Build Coastguard Worker           && ! parser->m_paramEntityParsing
5176*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
5177*6be67779SAndroid Build Coastguard Worker           && parser->m_notStandaloneHandler
5178*6be67779SAndroid Build Coastguard Worker           && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
5179*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NOT_STANDALONE;
5180*6be67779SAndroid Build Coastguard Worker #ifndef XML_DTD
5181*6be67779SAndroid Build Coastguard Worker       break;
5182*6be67779SAndroid Build Coastguard Worker #else  /* XML_DTD */
5183*6be67779SAndroid Build Coastguard Worker       if (! parser->m_declEntity) {
5184*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity = (ENTITY *)lookup(
5185*6be67779SAndroid Build Coastguard Worker             parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
5186*6be67779SAndroid Build Coastguard Worker         if (! parser->m_declEntity)
5187*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5188*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity->publicId = NULL;
5189*6be67779SAndroid Build Coastguard Worker       }
5190*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
5191*6be67779SAndroid Build Coastguard Worker       /* fall through */
5192*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ENTITY_SYSTEM_ID:
5193*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing && parser->m_declEntity) {
5194*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity->systemId
5195*6be67779SAndroid Build Coastguard Worker             = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
5196*6be67779SAndroid Build Coastguard Worker                               next - enc->minBytesPerChar);
5197*6be67779SAndroid Build Coastguard Worker         if (! parser->m_declEntity->systemId)
5198*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5199*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity->base = parser->m_curBase;
5200*6be67779SAndroid Build Coastguard Worker         poolFinish(&dtd->pool);
5201*6be67779SAndroid Build Coastguard Worker         /* Don't suppress the default handler if we fell through from
5202*6be67779SAndroid Build Coastguard Worker          * the XML_ROLE_DOCTYPE_SYSTEM_ID case.
5203*6be67779SAndroid Build Coastguard Worker          */
5204*6be67779SAndroid Build Coastguard Worker         if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID)
5205*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5206*6be67779SAndroid Build Coastguard Worker       }
5207*6be67779SAndroid Build Coastguard Worker       break;
5208*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ENTITY_COMPLETE:
5209*6be67779SAndroid Build Coastguard Worker #if XML_GE == 0
5210*6be67779SAndroid Build Coastguard Worker       // This will store "&amp;entity123;" in entity->textPtr
5211*6be67779SAndroid Build Coastguard Worker       // to end up as "&entity123;" in the handler.
5212*6be67779SAndroid Build Coastguard Worker       if (parser->m_declEntity != NULL) {
5213*6be67779SAndroid Build Coastguard Worker         const enum XML_Error result
5214*6be67779SAndroid Build Coastguard Worker             = storeSelfEntityValue(parser, parser->m_declEntity);
5215*6be67779SAndroid Build Coastguard Worker         if (result != XML_ERROR_NONE)
5216*6be67779SAndroid Build Coastguard Worker           return result;
5217*6be67779SAndroid Build Coastguard Worker       }
5218*6be67779SAndroid Build Coastguard Worker #endif
5219*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing && parser->m_declEntity
5220*6be67779SAndroid Build Coastguard Worker           && parser->m_entityDeclHandler) {
5221*6be67779SAndroid Build Coastguard Worker         *eventEndPP = s;
5222*6be67779SAndroid Build Coastguard Worker         parser->m_entityDeclHandler(
5223*6be67779SAndroid Build Coastguard Worker             parser->m_handlerArg, parser->m_declEntity->name,
5224*6be67779SAndroid Build Coastguard Worker             parser->m_declEntity->is_param, 0, 0, parser->m_declEntity->base,
5225*6be67779SAndroid Build Coastguard Worker             parser->m_declEntity->systemId, parser->m_declEntity->publicId, 0);
5226*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5227*6be67779SAndroid Build Coastguard Worker       }
5228*6be67779SAndroid Build Coastguard Worker       break;
5229*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ENTITY_NOTATION_NAME:
5230*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing && parser->m_declEntity) {
5231*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity->notation
5232*6be67779SAndroid Build Coastguard Worker             = poolStoreString(&dtd->pool, enc, s, next);
5233*6be67779SAndroid Build Coastguard Worker         if (! parser->m_declEntity->notation)
5234*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5235*6be67779SAndroid Build Coastguard Worker         poolFinish(&dtd->pool);
5236*6be67779SAndroid Build Coastguard Worker         if (parser->m_unparsedEntityDeclHandler) {
5237*6be67779SAndroid Build Coastguard Worker           *eventEndPP = s;
5238*6be67779SAndroid Build Coastguard Worker           parser->m_unparsedEntityDeclHandler(
5239*6be67779SAndroid Build Coastguard Worker               parser->m_handlerArg, parser->m_declEntity->name,
5240*6be67779SAndroid Build Coastguard Worker               parser->m_declEntity->base, parser->m_declEntity->systemId,
5241*6be67779SAndroid Build Coastguard Worker               parser->m_declEntity->publicId, parser->m_declEntity->notation);
5242*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5243*6be67779SAndroid Build Coastguard Worker         } else if (parser->m_entityDeclHandler) {
5244*6be67779SAndroid Build Coastguard Worker           *eventEndPP = s;
5245*6be67779SAndroid Build Coastguard Worker           parser->m_entityDeclHandler(
5246*6be67779SAndroid Build Coastguard Worker               parser->m_handlerArg, parser->m_declEntity->name, 0, 0, 0,
5247*6be67779SAndroid Build Coastguard Worker               parser->m_declEntity->base, parser->m_declEntity->systemId,
5248*6be67779SAndroid Build Coastguard Worker               parser->m_declEntity->publicId, parser->m_declEntity->notation);
5249*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5250*6be67779SAndroid Build Coastguard Worker         }
5251*6be67779SAndroid Build Coastguard Worker       }
5252*6be67779SAndroid Build Coastguard Worker       break;
5253*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_GENERAL_ENTITY_NAME: {
5254*6be67779SAndroid Build Coastguard Worker       if (XmlPredefinedEntityName(enc, s, next)) {
5255*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity = NULL;
5256*6be67779SAndroid Build Coastguard Worker         break;
5257*6be67779SAndroid Build Coastguard Worker       }
5258*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing) {
5259*6be67779SAndroid Build Coastguard Worker         const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
5260*6be67779SAndroid Build Coastguard Worker         if (! name)
5261*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5262*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities,
5263*6be67779SAndroid Build Coastguard Worker                                                 name, sizeof(ENTITY));
5264*6be67779SAndroid Build Coastguard Worker         if (! parser->m_declEntity)
5265*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5266*6be67779SAndroid Build Coastguard Worker         if (parser->m_declEntity->name != name) {
5267*6be67779SAndroid Build Coastguard Worker           poolDiscard(&dtd->pool);
5268*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity = NULL;
5269*6be67779SAndroid Build Coastguard Worker         } else {
5270*6be67779SAndroid Build Coastguard Worker           poolFinish(&dtd->pool);
5271*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity->publicId = NULL;
5272*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity->is_param = XML_FALSE;
5273*6be67779SAndroid Build Coastguard Worker           /* if we have a parent parser or are reading an internal parameter
5274*6be67779SAndroid Build Coastguard Worker              entity, then the entity declaration is not considered "internal"
5275*6be67779SAndroid Build Coastguard Worker           */
5276*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity->is_internal
5277*6be67779SAndroid Build Coastguard Worker               = ! (parser->m_parentParser || parser->m_openInternalEntities);
5278*6be67779SAndroid Build Coastguard Worker           if (parser->m_entityDeclHandler)
5279*6be67779SAndroid Build Coastguard Worker             handleDefault = XML_FALSE;
5280*6be67779SAndroid Build Coastguard Worker         }
5281*6be67779SAndroid Build Coastguard Worker       } else {
5282*6be67779SAndroid Build Coastguard Worker         poolDiscard(&dtd->pool);
5283*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity = NULL;
5284*6be67779SAndroid Build Coastguard Worker       }
5285*6be67779SAndroid Build Coastguard Worker     } break;
5286*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_PARAM_ENTITY_NAME:
5287*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
5288*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing) {
5289*6be67779SAndroid Build Coastguard Worker         const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
5290*6be67779SAndroid Build Coastguard Worker         if (! name)
5291*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5292*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
5293*6be67779SAndroid Build Coastguard Worker                                                 name, sizeof(ENTITY));
5294*6be67779SAndroid Build Coastguard Worker         if (! parser->m_declEntity)
5295*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5296*6be67779SAndroid Build Coastguard Worker         if (parser->m_declEntity->name != name) {
5297*6be67779SAndroid Build Coastguard Worker           poolDiscard(&dtd->pool);
5298*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity = NULL;
5299*6be67779SAndroid Build Coastguard Worker         } else {
5300*6be67779SAndroid Build Coastguard Worker           poolFinish(&dtd->pool);
5301*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity->publicId = NULL;
5302*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity->is_param = XML_TRUE;
5303*6be67779SAndroid Build Coastguard Worker           /* if we have a parent parser or are reading an internal parameter
5304*6be67779SAndroid Build Coastguard Worker              entity, then the entity declaration is not considered "internal"
5305*6be67779SAndroid Build Coastguard Worker           */
5306*6be67779SAndroid Build Coastguard Worker           parser->m_declEntity->is_internal
5307*6be67779SAndroid Build Coastguard Worker               = ! (parser->m_parentParser || parser->m_openInternalEntities);
5308*6be67779SAndroid Build Coastguard Worker           if (parser->m_entityDeclHandler)
5309*6be67779SAndroid Build Coastguard Worker             handleDefault = XML_FALSE;
5310*6be67779SAndroid Build Coastguard Worker         }
5311*6be67779SAndroid Build Coastguard Worker       } else {
5312*6be67779SAndroid Build Coastguard Worker         poolDiscard(&dtd->pool);
5313*6be67779SAndroid Build Coastguard Worker         parser->m_declEntity = NULL;
5314*6be67779SAndroid Build Coastguard Worker       }
5315*6be67779SAndroid Build Coastguard Worker #else  /* not XML_DTD */
5316*6be67779SAndroid Build Coastguard Worker       parser->m_declEntity = NULL;
5317*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
5318*6be67779SAndroid Build Coastguard Worker       break;
5319*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_NOTATION_NAME:
5320*6be67779SAndroid Build Coastguard Worker       parser->m_declNotationPublicId = NULL;
5321*6be67779SAndroid Build Coastguard Worker       parser->m_declNotationName = NULL;
5322*6be67779SAndroid Build Coastguard Worker       if (parser->m_notationDeclHandler) {
5323*6be67779SAndroid Build Coastguard Worker         parser->m_declNotationName
5324*6be67779SAndroid Build Coastguard Worker             = poolStoreString(&parser->m_tempPool, enc, s, next);
5325*6be67779SAndroid Build Coastguard Worker         if (! parser->m_declNotationName)
5326*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5327*6be67779SAndroid Build Coastguard Worker         poolFinish(&parser->m_tempPool);
5328*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5329*6be67779SAndroid Build Coastguard Worker       }
5330*6be67779SAndroid Build Coastguard Worker       break;
5331*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_NOTATION_PUBLIC_ID:
5332*6be67779SAndroid Build Coastguard Worker       if (! XmlIsPublicId(enc, s, next, eventPP))
5333*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_PUBLICID;
5334*6be67779SAndroid Build Coastguard Worker       if (parser
5335*6be67779SAndroid Build Coastguard Worker               ->m_declNotationName) { /* means m_notationDeclHandler != NULL */
5336*6be67779SAndroid Build Coastguard Worker         XML_Char *tem = poolStoreString(&parser->m_tempPool, enc,
5337*6be67779SAndroid Build Coastguard Worker                                         s + enc->minBytesPerChar,
5338*6be67779SAndroid Build Coastguard Worker                                         next - enc->minBytesPerChar);
5339*6be67779SAndroid Build Coastguard Worker         if (! tem)
5340*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5341*6be67779SAndroid Build Coastguard Worker         normalizePublicId(tem);
5342*6be67779SAndroid Build Coastguard Worker         parser->m_declNotationPublicId = tem;
5343*6be67779SAndroid Build Coastguard Worker         poolFinish(&parser->m_tempPool);
5344*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5345*6be67779SAndroid Build Coastguard Worker       }
5346*6be67779SAndroid Build Coastguard Worker       break;
5347*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_NOTATION_SYSTEM_ID:
5348*6be67779SAndroid Build Coastguard Worker       if (parser->m_declNotationName && parser->m_notationDeclHandler) {
5349*6be67779SAndroid Build Coastguard Worker         const XML_Char *systemId = poolStoreString(&parser->m_tempPool, enc,
5350*6be67779SAndroid Build Coastguard Worker                                                    s + enc->minBytesPerChar,
5351*6be67779SAndroid Build Coastguard Worker                                                    next - enc->minBytesPerChar);
5352*6be67779SAndroid Build Coastguard Worker         if (! systemId)
5353*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5354*6be67779SAndroid Build Coastguard Worker         *eventEndPP = s;
5355*6be67779SAndroid Build Coastguard Worker         parser->m_notationDeclHandler(
5356*6be67779SAndroid Build Coastguard Worker             parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
5357*6be67779SAndroid Build Coastguard Worker             systemId, parser->m_declNotationPublicId);
5358*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5359*6be67779SAndroid Build Coastguard Worker       }
5360*6be67779SAndroid Build Coastguard Worker       poolClear(&parser->m_tempPool);
5361*6be67779SAndroid Build Coastguard Worker       break;
5362*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_NOTATION_NO_SYSTEM_ID:
5363*6be67779SAndroid Build Coastguard Worker       if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) {
5364*6be67779SAndroid Build Coastguard Worker         *eventEndPP = s;
5365*6be67779SAndroid Build Coastguard Worker         parser->m_notationDeclHandler(
5366*6be67779SAndroid Build Coastguard Worker             parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
5367*6be67779SAndroid Build Coastguard Worker             0, parser->m_declNotationPublicId);
5368*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5369*6be67779SAndroid Build Coastguard Worker       }
5370*6be67779SAndroid Build Coastguard Worker       poolClear(&parser->m_tempPool);
5371*6be67779SAndroid Build Coastguard Worker       break;
5372*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ERROR:
5373*6be67779SAndroid Build Coastguard Worker       switch (tok) {
5374*6be67779SAndroid Build Coastguard Worker       case XML_TOK_PARAM_ENTITY_REF:
5375*6be67779SAndroid Build Coastguard Worker         /* PE references in internal subset are
5376*6be67779SAndroid Build Coastguard Worker            not allowed within declarations. */
5377*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_PARAM_ENTITY_REF;
5378*6be67779SAndroid Build Coastguard Worker       case XML_TOK_XML_DECL:
5379*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_MISPLACED_XML_PI;
5380*6be67779SAndroid Build Coastguard Worker       default:
5381*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_SYNTAX;
5382*6be67779SAndroid Build Coastguard Worker       }
5383*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
5384*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_IGNORE_SECT: {
5385*6be67779SAndroid Build Coastguard Worker       enum XML_Error result;
5386*6be67779SAndroid Build Coastguard Worker       if (parser->m_defaultHandler)
5387*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, enc, s, next);
5388*6be67779SAndroid Build Coastguard Worker       handleDefault = XML_FALSE;
5389*6be67779SAndroid Build Coastguard Worker       result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
5390*6be67779SAndroid Build Coastguard Worker       if (result != XML_ERROR_NONE)
5391*6be67779SAndroid Build Coastguard Worker         return result;
5392*6be67779SAndroid Build Coastguard Worker       else if (! next) {
5393*6be67779SAndroid Build Coastguard Worker         parser->m_processor = ignoreSectionProcessor;
5394*6be67779SAndroid Build Coastguard Worker         return result;
5395*6be67779SAndroid Build Coastguard Worker       }
5396*6be67779SAndroid Build Coastguard Worker     } break;
5397*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
5398*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_GROUP_OPEN:
5399*6be67779SAndroid Build Coastguard Worker       if (parser->m_prologState.level >= parser->m_groupSize) {
5400*6be67779SAndroid Build Coastguard Worker         if (parser->m_groupSize) {
5401*6be67779SAndroid Build Coastguard Worker           {
5402*6be67779SAndroid Build Coastguard Worker             /* Detect and prevent integer overflow */
5403*6be67779SAndroid Build Coastguard Worker             if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
5404*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NO_MEMORY;
5405*6be67779SAndroid Build Coastguard Worker             }
5406*6be67779SAndroid Build Coastguard Worker 
5407*6be67779SAndroid Build Coastguard Worker             char *const new_connector = (char *)REALLOC(
5408*6be67779SAndroid Build Coastguard Worker                 parser, parser->m_groupConnector, parser->m_groupSize *= 2);
5409*6be67779SAndroid Build Coastguard Worker             if (new_connector == NULL) {
5410*6be67779SAndroid Build Coastguard Worker               parser->m_groupSize /= 2;
5411*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NO_MEMORY;
5412*6be67779SAndroid Build Coastguard Worker             }
5413*6be67779SAndroid Build Coastguard Worker             parser->m_groupConnector = new_connector;
5414*6be67779SAndroid Build Coastguard Worker           }
5415*6be67779SAndroid Build Coastguard Worker 
5416*6be67779SAndroid Build Coastguard Worker           if (dtd->scaffIndex) {
5417*6be67779SAndroid Build Coastguard Worker             /* Detect and prevent integer overflow.
5418*6be67779SAndroid Build Coastguard Worker              * The preprocessor guard addresses the "always false" warning
5419*6be67779SAndroid Build Coastguard Worker              * from -Wtype-limits on platforms where
5420*6be67779SAndroid Build Coastguard Worker              * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
5421*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
5422*6be67779SAndroid Build Coastguard Worker             if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) {
5423*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NO_MEMORY;
5424*6be67779SAndroid Build Coastguard Worker             }
5425*6be67779SAndroid Build Coastguard Worker #endif
5426*6be67779SAndroid Build Coastguard Worker 
5427*6be67779SAndroid Build Coastguard Worker             int *const new_scaff_index = (int *)REALLOC(
5428*6be67779SAndroid Build Coastguard Worker                 parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
5429*6be67779SAndroid Build Coastguard Worker             if (new_scaff_index == NULL)
5430*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NO_MEMORY;
5431*6be67779SAndroid Build Coastguard Worker             dtd->scaffIndex = new_scaff_index;
5432*6be67779SAndroid Build Coastguard Worker           }
5433*6be67779SAndroid Build Coastguard Worker         } else {
5434*6be67779SAndroid Build Coastguard Worker           parser->m_groupConnector
5435*6be67779SAndroid Build Coastguard Worker               = (char *)MALLOC(parser, parser->m_groupSize = 32);
5436*6be67779SAndroid Build Coastguard Worker           if (! parser->m_groupConnector) {
5437*6be67779SAndroid Build Coastguard Worker             parser->m_groupSize = 0;
5438*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_NO_MEMORY;
5439*6be67779SAndroid Build Coastguard Worker           }
5440*6be67779SAndroid Build Coastguard Worker         }
5441*6be67779SAndroid Build Coastguard Worker       }
5442*6be67779SAndroid Build Coastguard Worker       parser->m_groupConnector[parser->m_prologState.level] = 0;
5443*6be67779SAndroid Build Coastguard Worker       if (dtd->in_eldecl) {
5444*6be67779SAndroid Build Coastguard Worker         int myindex = nextScaffoldPart(parser);
5445*6be67779SAndroid Build Coastguard Worker         if (myindex < 0)
5446*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5447*6be67779SAndroid Build Coastguard Worker         assert(dtd->scaffIndex != NULL);
5448*6be67779SAndroid Build Coastguard Worker         dtd->scaffIndex[dtd->scaffLevel] = myindex;
5449*6be67779SAndroid Build Coastguard Worker         dtd->scaffLevel++;
5450*6be67779SAndroid Build Coastguard Worker         dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
5451*6be67779SAndroid Build Coastguard Worker         if (parser->m_elementDeclHandler)
5452*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5453*6be67779SAndroid Build Coastguard Worker       }
5454*6be67779SAndroid Build Coastguard Worker       break;
5455*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_GROUP_SEQUENCE:
5456*6be67779SAndroid Build Coastguard Worker       if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE)
5457*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_SYNTAX;
5458*6be67779SAndroid Build Coastguard Worker       parser->m_groupConnector[parser->m_prologState.level] = ASCII_COMMA;
5459*6be67779SAndroid Build Coastguard Worker       if (dtd->in_eldecl && parser->m_elementDeclHandler)
5460*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5461*6be67779SAndroid Build Coastguard Worker       break;
5462*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_GROUP_CHOICE:
5463*6be67779SAndroid Build Coastguard Worker       if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
5464*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_SYNTAX;
5465*6be67779SAndroid Build Coastguard Worker       if (dtd->in_eldecl
5466*6be67779SAndroid Build Coastguard Worker           && ! parser->m_groupConnector[parser->m_prologState.level]
5467*6be67779SAndroid Build Coastguard Worker           && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5468*6be67779SAndroid Build Coastguard Worker               != XML_CTYPE_MIXED)) {
5469*6be67779SAndroid Build Coastguard Worker         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5470*6be67779SAndroid Build Coastguard Worker             = XML_CTYPE_CHOICE;
5471*6be67779SAndroid Build Coastguard Worker         if (parser->m_elementDeclHandler)
5472*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5473*6be67779SAndroid Build Coastguard Worker       }
5474*6be67779SAndroid Build Coastguard Worker       parser->m_groupConnector[parser->m_prologState.level] = ASCII_PIPE;
5475*6be67779SAndroid Build Coastguard Worker       break;
5476*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_PARAM_ENTITY_REF:
5477*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
5478*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_INNER_PARAM_ENTITY_REF:
5479*6be67779SAndroid Build Coastguard Worker       dtd->hasParamEntityRefs = XML_TRUE;
5480*6be67779SAndroid Build Coastguard Worker       if (! parser->m_paramEntityParsing)
5481*6be67779SAndroid Build Coastguard Worker         dtd->keepProcessing = dtd->standalone;
5482*6be67779SAndroid Build Coastguard Worker       else {
5483*6be67779SAndroid Build Coastguard Worker         const XML_Char *name;
5484*6be67779SAndroid Build Coastguard Worker         ENTITY *entity;
5485*6be67779SAndroid Build Coastguard Worker         name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
5486*6be67779SAndroid Build Coastguard Worker                                next - enc->minBytesPerChar);
5487*6be67779SAndroid Build Coastguard Worker         if (! name)
5488*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5489*6be67779SAndroid Build Coastguard Worker         entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5490*6be67779SAndroid Build Coastguard Worker         poolDiscard(&dtd->pool);
5491*6be67779SAndroid Build Coastguard Worker         /* first, determine if a check for an existing declaration is needed;
5492*6be67779SAndroid Build Coastguard Worker            if yes, check that the entity exists, and that it is internal,
5493*6be67779SAndroid Build Coastguard Worker            otherwise call the skipped entity handler
5494*6be67779SAndroid Build Coastguard Worker         */
5495*6be67779SAndroid Build Coastguard Worker         if (parser->m_prologState.documentEntity
5496*6be67779SAndroid Build Coastguard Worker             && (dtd->standalone ? ! parser->m_openInternalEntities
5497*6be67779SAndroid Build Coastguard Worker                                 : ! dtd->hasParamEntityRefs)) {
5498*6be67779SAndroid Build Coastguard Worker           if (! entity)
5499*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_UNDEFINED_ENTITY;
5500*6be67779SAndroid Build Coastguard Worker           else if (! entity->is_internal) {
5501*6be67779SAndroid Build Coastguard Worker             /* It's hard to exhaustively search the code to be sure,
5502*6be67779SAndroid Build Coastguard Worker              * but there doesn't seem to be a way of executing the
5503*6be67779SAndroid Build Coastguard Worker              * following line.  There are two cases:
5504*6be67779SAndroid Build Coastguard Worker              *
5505*6be67779SAndroid Build Coastguard Worker              * If 'standalone' is false, the DTD must have no
5506*6be67779SAndroid Build Coastguard Worker              * parameter entities or we wouldn't have passed the outer
5507*6be67779SAndroid Build Coastguard Worker              * 'if' statement.  That means the only entity in the hash
5508*6be67779SAndroid Build Coastguard Worker              * table is the external subset name "#" which cannot be
5509*6be67779SAndroid Build Coastguard Worker              * given as a parameter entity name in XML syntax, so the
5510*6be67779SAndroid Build Coastguard Worker              * lookup must have returned NULL and we don't even reach
5511*6be67779SAndroid Build Coastguard Worker              * the test for an internal entity.
5512*6be67779SAndroid Build Coastguard Worker              *
5513*6be67779SAndroid Build Coastguard Worker              * If 'standalone' is true, it does not seem to be
5514*6be67779SAndroid Build Coastguard Worker              * possible to create entities taking this code path that
5515*6be67779SAndroid Build Coastguard Worker              * are not internal entities, so fail the test above.
5516*6be67779SAndroid Build Coastguard Worker              *
5517*6be67779SAndroid Build Coastguard Worker              * Because this analysis is very uncertain, the code is
5518*6be67779SAndroid Build Coastguard Worker              * being left in place and merely removed from the
5519*6be67779SAndroid Build Coastguard Worker              * coverage test statistics.
5520*6be67779SAndroid Build Coastguard Worker              */
5521*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
5522*6be67779SAndroid Build Coastguard Worker           }
5523*6be67779SAndroid Build Coastguard Worker         } else if (! entity) {
5524*6be67779SAndroid Build Coastguard Worker           dtd->keepProcessing = dtd->standalone;
5525*6be67779SAndroid Build Coastguard Worker           /* cannot report skipped entities in declarations */
5526*6be67779SAndroid Build Coastguard Worker           if ((role == XML_ROLE_PARAM_ENTITY_REF)
5527*6be67779SAndroid Build Coastguard Worker               && parser->m_skippedEntityHandler) {
5528*6be67779SAndroid Build Coastguard Worker             parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1);
5529*6be67779SAndroid Build Coastguard Worker             handleDefault = XML_FALSE;
5530*6be67779SAndroid Build Coastguard Worker           }
5531*6be67779SAndroid Build Coastguard Worker           break;
5532*6be67779SAndroid Build Coastguard Worker         }
5533*6be67779SAndroid Build Coastguard Worker         if (entity->open)
5534*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_RECURSIVE_ENTITY_REF;
5535*6be67779SAndroid Build Coastguard Worker         if (entity->textPtr) {
5536*6be67779SAndroid Build Coastguard Worker           enum XML_Error result;
5537*6be67779SAndroid Build Coastguard Worker           XML_Bool betweenDecl
5538*6be67779SAndroid Build Coastguard Worker               = (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
5539*6be67779SAndroid Build Coastguard Worker           result = processInternalEntity(parser, entity, betweenDecl);
5540*6be67779SAndroid Build Coastguard Worker           if (result != XML_ERROR_NONE)
5541*6be67779SAndroid Build Coastguard Worker             return result;
5542*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5543*6be67779SAndroid Build Coastguard Worker           break;
5544*6be67779SAndroid Build Coastguard Worker         }
5545*6be67779SAndroid Build Coastguard Worker         if (parser->m_externalEntityRefHandler) {
5546*6be67779SAndroid Build Coastguard Worker           dtd->paramEntityRead = XML_FALSE;
5547*6be67779SAndroid Build Coastguard Worker           entity->open = XML_TRUE;
5548*6be67779SAndroid Build Coastguard Worker           entityTrackingOnOpen(parser, entity, __LINE__);
5549*6be67779SAndroid Build Coastguard Worker           if (! parser->m_externalEntityRefHandler(
5550*6be67779SAndroid Build Coastguard Worker                   parser->m_externalEntityRefHandlerArg, 0, entity->base,
5551*6be67779SAndroid Build Coastguard Worker                   entity->systemId, entity->publicId)) {
5552*6be67779SAndroid Build Coastguard Worker             entityTrackingOnClose(parser, entity, __LINE__);
5553*6be67779SAndroid Build Coastguard Worker             entity->open = XML_FALSE;
5554*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5555*6be67779SAndroid Build Coastguard Worker           }
5556*6be67779SAndroid Build Coastguard Worker           entityTrackingOnClose(parser, entity, __LINE__);
5557*6be67779SAndroid Build Coastguard Worker           entity->open = XML_FALSE;
5558*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5559*6be67779SAndroid Build Coastguard Worker           if (! dtd->paramEntityRead) {
5560*6be67779SAndroid Build Coastguard Worker             dtd->keepProcessing = dtd->standalone;
5561*6be67779SAndroid Build Coastguard Worker             break;
5562*6be67779SAndroid Build Coastguard Worker           }
5563*6be67779SAndroid Build Coastguard Worker         } else {
5564*6be67779SAndroid Build Coastguard Worker           dtd->keepProcessing = dtd->standalone;
5565*6be67779SAndroid Build Coastguard Worker           break;
5566*6be67779SAndroid Build Coastguard Worker         }
5567*6be67779SAndroid Build Coastguard Worker       }
5568*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
5569*6be67779SAndroid Build Coastguard Worker       if (! dtd->standalone && parser->m_notStandaloneHandler
5570*6be67779SAndroid Build Coastguard Worker           && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
5571*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NOT_STANDALONE;
5572*6be67779SAndroid Build Coastguard Worker       break;
5573*6be67779SAndroid Build Coastguard Worker 
5574*6be67779SAndroid Build Coastguard Worker       /* Element declaration stuff */
5575*6be67779SAndroid Build Coastguard Worker 
5576*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ELEMENT_NAME:
5577*6be67779SAndroid Build Coastguard Worker       if (parser->m_elementDeclHandler) {
5578*6be67779SAndroid Build Coastguard Worker         parser->m_declElementType = getElementType(parser, enc, s, next);
5579*6be67779SAndroid Build Coastguard Worker         if (! parser->m_declElementType)
5580*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5581*6be67779SAndroid Build Coastguard Worker         dtd->scaffLevel = 0;
5582*6be67779SAndroid Build Coastguard Worker         dtd->scaffCount = 0;
5583*6be67779SAndroid Build Coastguard Worker         dtd->in_eldecl = XML_TRUE;
5584*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5585*6be67779SAndroid Build Coastguard Worker       }
5586*6be67779SAndroid Build Coastguard Worker       break;
5587*6be67779SAndroid Build Coastguard Worker 
5588*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_CONTENT_ANY:
5589*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_CONTENT_EMPTY:
5590*6be67779SAndroid Build Coastguard Worker       if (dtd->in_eldecl) {
5591*6be67779SAndroid Build Coastguard Worker         if (parser->m_elementDeclHandler) {
5592*6be67779SAndroid Build Coastguard Worker           XML_Content *content
5593*6be67779SAndroid Build Coastguard Worker               = (XML_Content *)MALLOC(parser, sizeof(XML_Content));
5594*6be67779SAndroid Build Coastguard Worker           if (! content)
5595*6be67779SAndroid Build Coastguard Worker             return XML_ERROR_NO_MEMORY;
5596*6be67779SAndroid Build Coastguard Worker           content->quant = XML_CQUANT_NONE;
5597*6be67779SAndroid Build Coastguard Worker           content->name = NULL;
5598*6be67779SAndroid Build Coastguard Worker           content->numchildren = 0;
5599*6be67779SAndroid Build Coastguard Worker           content->children = NULL;
5600*6be67779SAndroid Build Coastguard Worker           content->type = ((role == XML_ROLE_CONTENT_ANY) ? XML_CTYPE_ANY
5601*6be67779SAndroid Build Coastguard Worker                                                           : XML_CTYPE_EMPTY);
5602*6be67779SAndroid Build Coastguard Worker           *eventEndPP = s;
5603*6be67779SAndroid Build Coastguard Worker           parser->m_elementDeclHandler(
5604*6be67779SAndroid Build Coastguard Worker               parser->m_handlerArg, parser->m_declElementType->name, content);
5605*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5606*6be67779SAndroid Build Coastguard Worker         }
5607*6be67779SAndroid Build Coastguard Worker         dtd->in_eldecl = XML_FALSE;
5608*6be67779SAndroid Build Coastguard Worker       }
5609*6be67779SAndroid Build Coastguard Worker       break;
5610*6be67779SAndroid Build Coastguard Worker 
5611*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_CONTENT_PCDATA:
5612*6be67779SAndroid Build Coastguard Worker       if (dtd->in_eldecl) {
5613*6be67779SAndroid Build Coastguard Worker         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5614*6be67779SAndroid Build Coastguard Worker             = XML_CTYPE_MIXED;
5615*6be67779SAndroid Build Coastguard Worker         if (parser->m_elementDeclHandler)
5616*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5617*6be67779SAndroid Build Coastguard Worker       }
5618*6be67779SAndroid Build Coastguard Worker       break;
5619*6be67779SAndroid Build Coastguard Worker 
5620*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_CONTENT_ELEMENT:
5621*6be67779SAndroid Build Coastguard Worker       quant = XML_CQUANT_NONE;
5622*6be67779SAndroid Build Coastguard Worker       goto elementContent;
5623*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_CONTENT_ELEMENT_OPT:
5624*6be67779SAndroid Build Coastguard Worker       quant = XML_CQUANT_OPT;
5625*6be67779SAndroid Build Coastguard Worker       goto elementContent;
5626*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_CONTENT_ELEMENT_REP:
5627*6be67779SAndroid Build Coastguard Worker       quant = XML_CQUANT_REP;
5628*6be67779SAndroid Build Coastguard Worker       goto elementContent;
5629*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_CONTENT_ELEMENT_PLUS:
5630*6be67779SAndroid Build Coastguard Worker       quant = XML_CQUANT_PLUS;
5631*6be67779SAndroid Build Coastguard Worker     elementContent:
5632*6be67779SAndroid Build Coastguard Worker       if (dtd->in_eldecl) {
5633*6be67779SAndroid Build Coastguard Worker         ELEMENT_TYPE *el;
5634*6be67779SAndroid Build Coastguard Worker         const XML_Char *name;
5635*6be67779SAndroid Build Coastguard Worker         size_t nameLen;
5636*6be67779SAndroid Build Coastguard Worker         const char *nxt
5637*6be67779SAndroid Build Coastguard Worker             = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
5638*6be67779SAndroid Build Coastguard Worker         int myindex = nextScaffoldPart(parser);
5639*6be67779SAndroid Build Coastguard Worker         if (myindex < 0)
5640*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5641*6be67779SAndroid Build Coastguard Worker         dtd->scaffold[myindex].type = XML_CTYPE_NAME;
5642*6be67779SAndroid Build Coastguard Worker         dtd->scaffold[myindex].quant = quant;
5643*6be67779SAndroid Build Coastguard Worker         el = getElementType(parser, enc, s, nxt);
5644*6be67779SAndroid Build Coastguard Worker         if (! el)
5645*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5646*6be67779SAndroid Build Coastguard Worker         name = el->name;
5647*6be67779SAndroid Build Coastguard Worker         dtd->scaffold[myindex].name = name;
5648*6be67779SAndroid Build Coastguard Worker         nameLen = 0;
5649*6be67779SAndroid Build Coastguard Worker         for (; name[nameLen++];)
5650*6be67779SAndroid Build Coastguard Worker           ;
5651*6be67779SAndroid Build Coastguard Worker 
5652*6be67779SAndroid Build Coastguard Worker         /* Detect and prevent integer overflow */
5653*6be67779SAndroid Build Coastguard Worker         if (nameLen > UINT_MAX - dtd->contentStringLen) {
5654*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
5655*6be67779SAndroid Build Coastguard Worker         }
5656*6be67779SAndroid Build Coastguard Worker 
5657*6be67779SAndroid Build Coastguard Worker         dtd->contentStringLen += (unsigned)nameLen;
5658*6be67779SAndroid Build Coastguard Worker         if (parser->m_elementDeclHandler)
5659*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5660*6be67779SAndroid Build Coastguard Worker       }
5661*6be67779SAndroid Build Coastguard Worker       break;
5662*6be67779SAndroid Build Coastguard Worker 
5663*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_GROUP_CLOSE:
5664*6be67779SAndroid Build Coastguard Worker       quant = XML_CQUANT_NONE;
5665*6be67779SAndroid Build Coastguard Worker       goto closeGroup;
5666*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_GROUP_CLOSE_OPT:
5667*6be67779SAndroid Build Coastguard Worker       quant = XML_CQUANT_OPT;
5668*6be67779SAndroid Build Coastguard Worker       goto closeGroup;
5669*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_GROUP_CLOSE_REP:
5670*6be67779SAndroid Build Coastguard Worker       quant = XML_CQUANT_REP;
5671*6be67779SAndroid Build Coastguard Worker       goto closeGroup;
5672*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_GROUP_CLOSE_PLUS:
5673*6be67779SAndroid Build Coastguard Worker       quant = XML_CQUANT_PLUS;
5674*6be67779SAndroid Build Coastguard Worker     closeGroup:
5675*6be67779SAndroid Build Coastguard Worker       if (dtd->in_eldecl) {
5676*6be67779SAndroid Build Coastguard Worker         if (parser->m_elementDeclHandler)
5677*6be67779SAndroid Build Coastguard Worker           handleDefault = XML_FALSE;
5678*6be67779SAndroid Build Coastguard Worker         dtd->scaffLevel--;
5679*6be67779SAndroid Build Coastguard Worker         dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
5680*6be67779SAndroid Build Coastguard Worker         if (dtd->scaffLevel == 0) {
5681*6be67779SAndroid Build Coastguard Worker           if (! handleDefault) {
5682*6be67779SAndroid Build Coastguard Worker             XML_Content *model = build_model(parser);
5683*6be67779SAndroid Build Coastguard Worker             if (! model)
5684*6be67779SAndroid Build Coastguard Worker               return XML_ERROR_NO_MEMORY;
5685*6be67779SAndroid Build Coastguard Worker             *eventEndPP = s;
5686*6be67779SAndroid Build Coastguard Worker             parser->m_elementDeclHandler(
5687*6be67779SAndroid Build Coastguard Worker                 parser->m_handlerArg, parser->m_declElementType->name, model);
5688*6be67779SAndroid Build Coastguard Worker           }
5689*6be67779SAndroid Build Coastguard Worker           dtd->in_eldecl = XML_FALSE;
5690*6be67779SAndroid Build Coastguard Worker           dtd->contentStringLen = 0;
5691*6be67779SAndroid Build Coastguard Worker         }
5692*6be67779SAndroid Build Coastguard Worker       }
5693*6be67779SAndroid Build Coastguard Worker       break;
5694*6be67779SAndroid Build Coastguard Worker       /* End element declaration stuff */
5695*6be67779SAndroid Build Coastguard Worker 
5696*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_PI:
5697*6be67779SAndroid Build Coastguard Worker       if (! reportProcessingInstruction(parser, enc, s, next))
5698*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
5699*6be67779SAndroid Build Coastguard Worker       handleDefault = XML_FALSE;
5700*6be67779SAndroid Build Coastguard Worker       break;
5701*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_COMMENT:
5702*6be67779SAndroid Build Coastguard Worker       if (! reportComment(parser, enc, s, next))
5703*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
5704*6be67779SAndroid Build Coastguard Worker       handleDefault = XML_FALSE;
5705*6be67779SAndroid Build Coastguard Worker       break;
5706*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_NONE:
5707*6be67779SAndroid Build Coastguard Worker       switch (tok) {
5708*6be67779SAndroid Build Coastguard Worker       case XML_TOK_BOM:
5709*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5710*6be67779SAndroid Build Coastguard Worker         break;
5711*6be67779SAndroid Build Coastguard Worker       }
5712*6be67779SAndroid Build Coastguard Worker       break;
5713*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_DOCTYPE_NONE:
5714*6be67779SAndroid Build Coastguard Worker       if (parser->m_startDoctypeDeclHandler)
5715*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5716*6be67779SAndroid Build Coastguard Worker       break;
5717*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ENTITY_NONE:
5718*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing && parser->m_entityDeclHandler)
5719*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5720*6be67779SAndroid Build Coastguard Worker       break;
5721*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_NOTATION_NONE:
5722*6be67779SAndroid Build Coastguard Worker       if (parser->m_notationDeclHandler)
5723*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5724*6be67779SAndroid Build Coastguard Worker       break;
5725*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ATTLIST_NONE:
5726*6be67779SAndroid Build Coastguard Worker       if (dtd->keepProcessing && parser->m_attlistDeclHandler)
5727*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5728*6be67779SAndroid Build Coastguard Worker       break;
5729*6be67779SAndroid Build Coastguard Worker     case XML_ROLE_ELEMENT_NONE:
5730*6be67779SAndroid Build Coastguard Worker       if (parser->m_elementDeclHandler)
5731*6be67779SAndroid Build Coastguard Worker         handleDefault = XML_FALSE;
5732*6be67779SAndroid Build Coastguard Worker       break;
5733*6be67779SAndroid Build Coastguard Worker     } /* end of big switch */
5734*6be67779SAndroid Build Coastguard Worker 
5735*6be67779SAndroid Build Coastguard Worker     if (handleDefault && parser->m_defaultHandler)
5736*6be67779SAndroid Build Coastguard Worker       reportDefault(parser, enc, s, next);
5737*6be67779SAndroid Build Coastguard Worker 
5738*6be67779SAndroid Build Coastguard Worker     switch (parser->m_parsingStatus.parsing) {
5739*6be67779SAndroid Build Coastguard Worker     case XML_SUSPENDED:
5740*6be67779SAndroid Build Coastguard Worker       *nextPtr = next;
5741*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
5742*6be67779SAndroid Build Coastguard Worker     case XML_FINISHED:
5743*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_ABORTED;
5744*6be67779SAndroid Build Coastguard Worker     default:
5745*6be67779SAndroid Build Coastguard Worker       s = next;
5746*6be67779SAndroid Build Coastguard Worker       tok = XmlPrologTok(enc, s, end, &next);
5747*6be67779SAndroid Build Coastguard Worker     }
5748*6be67779SAndroid Build Coastguard Worker   }
5749*6be67779SAndroid Build Coastguard Worker   /* not reached */
5750*6be67779SAndroid Build Coastguard Worker }
5751*6be67779SAndroid Build Coastguard Worker 
5752*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
epilogProcessor(XML_Parser parser,const char * s,const char * end,const char ** nextPtr)5753*6be67779SAndroid Build Coastguard Worker epilogProcessor(XML_Parser parser, const char *s, const char *end,
5754*6be67779SAndroid Build Coastguard Worker                 const char **nextPtr) {
5755*6be67779SAndroid Build Coastguard Worker   parser->m_processor = epilogProcessor;
5756*6be67779SAndroid Build Coastguard Worker   parser->m_eventPtr = s;
5757*6be67779SAndroid Build Coastguard Worker   for (;;) {
5758*6be67779SAndroid Build Coastguard Worker     const char *next = NULL;
5759*6be67779SAndroid Build Coastguard Worker     int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5760*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
5761*6be67779SAndroid Build Coastguard Worker     if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
5762*6be67779SAndroid Build Coastguard Worker                                   XML_ACCOUNT_DIRECT)) {
5763*6be67779SAndroid Build Coastguard Worker       accountingOnAbort(parser);
5764*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
5765*6be67779SAndroid Build Coastguard Worker     }
5766*6be67779SAndroid Build Coastguard Worker #endif
5767*6be67779SAndroid Build Coastguard Worker     parser->m_eventEndPtr = next;
5768*6be67779SAndroid Build Coastguard Worker     switch (tok) {
5769*6be67779SAndroid Build Coastguard Worker     /* report partial linebreak - it might be the last token */
5770*6be67779SAndroid Build Coastguard Worker     case -XML_TOK_PROLOG_S:
5771*6be67779SAndroid Build Coastguard Worker       if (parser->m_defaultHandler) {
5772*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, parser->m_encoding, s, next);
5773*6be67779SAndroid Build Coastguard Worker         if (parser->m_parsingStatus.parsing == XML_FINISHED)
5774*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_ABORTED;
5775*6be67779SAndroid Build Coastguard Worker       }
5776*6be67779SAndroid Build Coastguard Worker       *nextPtr = next;
5777*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
5778*6be67779SAndroid Build Coastguard Worker     case XML_TOK_NONE:
5779*6be67779SAndroid Build Coastguard Worker       *nextPtr = s;
5780*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
5781*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PROLOG_S:
5782*6be67779SAndroid Build Coastguard Worker       if (parser->m_defaultHandler)
5783*6be67779SAndroid Build Coastguard Worker         reportDefault(parser, parser->m_encoding, s, next);
5784*6be67779SAndroid Build Coastguard Worker       break;
5785*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PI:
5786*6be67779SAndroid Build Coastguard Worker       if (! reportProcessingInstruction(parser, parser->m_encoding, s, next))
5787*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
5788*6be67779SAndroid Build Coastguard Worker       break;
5789*6be67779SAndroid Build Coastguard Worker     case XML_TOK_COMMENT:
5790*6be67779SAndroid Build Coastguard Worker       if (! reportComment(parser, parser->m_encoding, s, next))
5791*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
5792*6be67779SAndroid Build Coastguard Worker       break;
5793*6be67779SAndroid Build Coastguard Worker     case XML_TOK_INVALID:
5794*6be67779SAndroid Build Coastguard Worker       parser->m_eventPtr = next;
5795*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_INVALID_TOKEN;
5796*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL:
5797*6be67779SAndroid Build Coastguard Worker       if (! parser->m_parsingStatus.finalBuffer) {
5798*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
5799*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
5800*6be67779SAndroid Build Coastguard Worker       }
5801*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_UNCLOSED_TOKEN;
5802*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL_CHAR:
5803*6be67779SAndroid Build Coastguard Worker       if (! parser->m_parsingStatus.finalBuffer) {
5804*6be67779SAndroid Build Coastguard Worker         *nextPtr = s;
5805*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NONE;
5806*6be67779SAndroid Build Coastguard Worker       }
5807*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_PARTIAL_CHAR;
5808*6be67779SAndroid Build Coastguard Worker     default:
5809*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
5810*6be67779SAndroid Build Coastguard Worker     }
5811*6be67779SAndroid Build Coastguard Worker     parser->m_eventPtr = s = next;
5812*6be67779SAndroid Build Coastguard Worker     switch (parser->m_parsingStatus.parsing) {
5813*6be67779SAndroid Build Coastguard Worker     case XML_SUSPENDED:
5814*6be67779SAndroid Build Coastguard Worker       *nextPtr = next;
5815*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
5816*6be67779SAndroid Build Coastguard Worker     case XML_FINISHED:
5817*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_ABORTED;
5818*6be67779SAndroid Build Coastguard Worker     default:;
5819*6be67779SAndroid Build Coastguard Worker     }
5820*6be67779SAndroid Build Coastguard Worker   }
5821*6be67779SAndroid Build Coastguard Worker }
5822*6be67779SAndroid Build Coastguard Worker 
5823*6be67779SAndroid Build Coastguard Worker static enum XML_Error
processInternalEntity(XML_Parser parser,ENTITY * entity,XML_Bool betweenDecl)5824*6be67779SAndroid Build Coastguard Worker processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
5825*6be67779SAndroid Build Coastguard Worker   const char *textStart, *textEnd;
5826*6be67779SAndroid Build Coastguard Worker   const char *next;
5827*6be67779SAndroid Build Coastguard Worker   enum XML_Error result;
5828*6be67779SAndroid Build Coastguard Worker   OPEN_INTERNAL_ENTITY *openEntity;
5829*6be67779SAndroid Build Coastguard Worker 
5830*6be67779SAndroid Build Coastguard Worker   if (parser->m_freeInternalEntities) {
5831*6be67779SAndroid Build Coastguard Worker     openEntity = parser->m_freeInternalEntities;
5832*6be67779SAndroid Build Coastguard Worker     parser->m_freeInternalEntities = openEntity->next;
5833*6be67779SAndroid Build Coastguard Worker   } else {
5834*6be67779SAndroid Build Coastguard Worker     openEntity
5835*6be67779SAndroid Build Coastguard Worker         = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
5836*6be67779SAndroid Build Coastguard Worker     if (! openEntity)
5837*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
5838*6be67779SAndroid Build Coastguard Worker   }
5839*6be67779SAndroid Build Coastguard Worker   entity->open = XML_TRUE;
5840*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
5841*6be67779SAndroid Build Coastguard Worker   entityTrackingOnOpen(parser, entity, __LINE__);
5842*6be67779SAndroid Build Coastguard Worker #endif
5843*6be67779SAndroid Build Coastguard Worker   entity->processed = 0;
5844*6be67779SAndroid Build Coastguard Worker   openEntity->next = parser->m_openInternalEntities;
5845*6be67779SAndroid Build Coastguard Worker   parser->m_openInternalEntities = openEntity;
5846*6be67779SAndroid Build Coastguard Worker   openEntity->entity = entity;
5847*6be67779SAndroid Build Coastguard Worker   openEntity->startTagLevel = parser->m_tagLevel;
5848*6be67779SAndroid Build Coastguard Worker   openEntity->betweenDecl = betweenDecl;
5849*6be67779SAndroid Build Coastguard Worker   openEntity->internalEventPtr = NULL;
5850*6be67779SAndroid Build Coastguard Worker   openEntity->internalEventEndPtr = NULL;
5851*6be67779SAndroid Build Coastguard Worker   textStart = (const char *)entity->textPtr;
5852*6be67779SAndroid Build Coastguard Worker   textEnd = (const char *)(entity->textPtr + entity->textLen);
5853*6be67779SAndroid Build Coastguard Worker   /* Set a safe default value in case 'next' does not get set */
5854*6be67779SAndroid Build Coastguard Worker   next = textStart;
5855*6be67779SAndroid Build Coastguard Worker 
5856*6be67779SAndroid Build Coastguard Worker   if (entity->is_param) {
5857*6be67779SAndroid Build Coastguard Worker     int tok
5858*6be67779SAndroid Build Coastguard Worker         = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5859*6be67779SAndroid Build Coastguard Worker     result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
5860*6be67779SAndroid Build Coastguard Worker                       tok, next, &next, XML_FALSE, XML_FALSE,
5861*6be67779SAndroid Build Coastguard Worker                       XML_ACCOUNT_ENTITY_EXPANSION);
5862*6be67779SAndroid Build Coastguard Worker   } else {
5863*6be67779SAndroid Build Coastguard Worker     result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
5864*6be67779SAndroid Build Coastguard Worker                        textStart, textEnd, &next, XML_FALSE,
5865*6be67779SAndroid Build Coastguard Worker                        XML_ACCOUNT_ENTITY_EXPANSION);
5866*6be67779SAndroid Build Coastguard Worker   }
5867*6be67779SAndroid Build Coastguard Worker 
5868*6be67779SAndroid Build Coastguard Worker   if (result == XML_ERROR_NONE) {
5869*6be67779SAndroid Build Coastguard Worker     if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
5870*6be67779SAndroid Build Coastguard Worker       entity->processed = (int)(next - textStart);
5871*6be67779SAndroid Build Coastguard Worker       parser->m_processor = internalEntityProcessor;
5872*6be67779SAndroid Build Coastguard Worker     } else if (parser->m_openInternalEntities->entity == entity) {
5873*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
5874*6be67779SAndroid Build Coastguard Worker       entityTrackingOnClose(parser, entity, __LINE__);
5875*6be67779SAndroid Build Coastguard Worker #endif /* XML_GE == 1 */
5876*6be67779SAndroid Build Coastguard Worker       entity->open = XML_FALSE;
5877*6be67779SAndroid Build Coastguard Worker       parser->m_openInternalEntities = openEntity->next;
5878*6be67779SAndroid Build Coastguard Worker       /* put openEntity back in list of free instances */
5879*6be67779SAndroid Build Coastguard Worker       openEntity->next = parser->m_freeInternalEntities;
5880*6be67779SAndroid Build Coastguard Worker       parser->m_freeInternalEntities = openEntity;
5881*6be67779SAndroid Build Coastguard Worker     }
5882*6be67779SAndroid Build Coastguard Worker   }
5883*6be67779SAndroid Build Coastguard Worker   return result;
5884*6be67779SAndroid Build Coastguard Worker }
5885*6be67779SAndroid Build Coastguard Worker 
5886*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
internalEntityProcessor(XML_Parser parser,const char * s,const char * end,const char ** nextPtr)5887*6be67779SAndroid Build Coastguard Worker internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
5888*6be67779SAndroid Build Coastguard Worker                         const char **nextPtr) {
5889*6be67779SAndroid Build Coastguard Worker   ENTITY *entity;
5890*6be67779SAndroid Build Coastguard Worker   const char *textStart, *textEnd;
5891*6be67779SAndroid Build Coastguard Worker   const char *next;
5892*6be67779SAndroid Build Coastguard Worker   enum XML_Error result;
5893*6be67779SAndroid Build Coastguard Worker   OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
5894*6be67779SAndroid Build Coastguard Worker   if (! openEntity)
5895*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_UNEXPECTED_STATE;
5896*6be67779SAndroid Build Coastguard Worker 
5897*6be67779SAndroid Build Coastguard Worker   entity = openEntity->entity;
5898*6be67779SAndroid Build Coastguard Worker   textStart = ((const char *)entity->textPtr) + entity->processed;
5899*6be67779SAndroid Build Coastguard Worker   textEnd = (const char *)(entity->textPtr + entity->textLen);
5900*6be67779SAndroid Build Coastguard Worker   /* Set a safe default value in case 'next' does not get set */
5901*6be67779SAndroid Build Coastguard Worker   next = textStart;
5902*6be67779SAndroid Build Coastguard Worker 
5903*6be67779SAndroid Build Coastguard Worker   if (entity->is_param) {
5904*6be67779SAndroid Build Coastguard Worker     int tok
5905*6be67779SAndroid Build Coastguard Worker         = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5906*6be67779SAndroid Build Coastguard Worker     result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
5907*6be67779SAndroid Build Coastguard Worker                       tok, next, &next, XML_FALSE, XML_TRUE,
5908*6be67779SAndroid Build Coastguard Worker                       XML_ACCOUNT_ENTITY_EXPANSION);
5909*6be67779SAndroid Build Coastguard Worker   } else {
5910*6be67779SAndroid Build Coastguard Worker     result = doContent(parser, openEntity->startTagLevel,
5911*6be67779SAndroid Build Coastguard Worker                        parser->m_internalEncoding, textStart, textEnd, &next,
5912*6be67779SAndroid Build Coastguard Worker                        XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
5913*6be67779SAndroid Build Coastguard Worker   }
5914*6be67779SAndroid Build Coastguard Worker 
5915*6be67779SAndroid Build Coastguard Worker   if (result != XML_ERROR_NONE)
5916*6be67779SAndroid Build Coastguard Worker     return result;
5917*6be67779SAndroid Build Coastguard Worker 
5918*6be67779SAndroid Build Coastguard Worker   if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
5919*6be67779SAndroid Build Coastguard Worker     entity->processed = (int)(next - (const char *)entity->textPtr);
5920*6be67779SAndroid Build Coastguard Worker     return result;
5921*6be67779SAndroid Build Coastguard Worker   }
5922*6be67779SAndroid Build Coastguard Worker 
5923*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
5924*6be67779SAndroid Build Coastguard Worker   entityTrackingOnClose(parser, entity, __LINE__);
5925*6be67779SAndroid Build Coastguard Worker #endif
5926*6be67779SAndroid Build Coastguard Worker   entity->open = XML_FALSE;
5927*6be67779SAndroid Build Coastguard Worker   parser->m_openInternalEntities = openEntity->next;
5928*6be67779SAndroid Build Coastguard Worker   /* put openEntity back in list of free instances */
5929*6be67779SAndroid Build Coastguard Worker   openEntity->next = parser->m_freeInternalEntities;
5930*6be67779SAndroid Build Coastguard Worker   parser->m_freeInternalEntities = openEntity;
5931*6be67779SAndroid Build Coastguard Worker 
5932*6be67779SAndroid Build Coastguard Worker   // If there are more open entities we want to stop right here and have the
5933*6be67779SAndroid Build Coastguard Worker   // upcoming call to XML_ResumeParser continue with entity content, or it would
5934*6be67779SAndroid Build Coastguard Worker   // be ignored altogether.
5935*6be67779SAndroid Build Coastguard Worker   if (parser->m_openInternalEntities != NULL
5936*6be67779SAndroid Build Coastguard Worker       && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
5937*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_NONE;
5938*6be67779SAndroid Build Coastguard Worker   }
5939*6be67779SAndroid Build Coastguard Worker 
5940*6be67779SAndroid Build Coastguard Worker   if (entity->is_param) {
5941*6be67779SAndroid Build Coastguard Worker     int tok;
5942*6be67779SAndroid Build Coastguard Worker     parser->m_processor = prologProcessor;
5943*6be67779SAndroid Build Coastguard Worker     tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5944*6be67779SAndroid Build Coastguard Worker     return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
5945*6be67779SAndroid Build Coastguard Worker                     (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
5946*6be67779SAndroid Build Coastguard Worker                     XML_ACCOUNT_DIRECT);
5947*6be67779SAndroid Build Coastguard Worker   } else {
5948*6be67779SAndroid Build Coastguard Worker     parser->m_processor = contentProcessor;
5949*6be67779SAndroid Build Coastguard Worker     /* see externalEntityContentProcessor vs contentProcessor */
5950*6be67779SAndroid Build Coastguard Worker     result = doContent(parser, parser->m_parentParser ? 1 : 0,
5951*6be67779SAndroid Build Coastguard Worker                        parser->m_encoding, s, end, nextPtr,
5952*6be67779SAndroid Build Coastguard Worker                        (XML_Bool)! parser->m_parsingStatus.finalBuffer,
5953*6be67779SAndroid Build Coastguard Worker                        XML_ACCOUNT_DIRECT);
5954*6be67779SAndroid Build Coastguard Worker     if (result == XML_ERROR_NONE) {
5955*6be67779SAndroid Build Coastguard Worker       if (! storeRawNames(parser))
5956*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
5957*6be67779SAndroid Build Coastguard Worker     }
5958*6be67779SAndroid Build Coastguard Worker     return result;
5959*6be67779SAndroid Build Coastguard Worker   }
5960*6be67779SAndroid Build Coastguard Worker }
5961*6be67779SAndroid Build Coastguard Worker 
5962*6be67779SAndroid Build Coastguard Worker static enum XML_Error PTRCALL
errorProcessor(XML_Parser parser,const char * s,const char * end,const char ** nextPtr)5963*6be67779SAndroid Build Coastguard Worker errorProcessor(XML_Parser parser, const char *s, const char *end,
5964*6be67779SAndroid Build Coastguard Worker                const char **nextPtr) {
5965*6be67779SAndroid Build Coastguard Worker   UNUSED_P(s);
5966*6be67779SAndroid Build Coastguard Worker   UNUSED_P(end);
5967*6be67779SAndroid Build Coastguard Worker   UNUSED_P(nextPtr);
5968*6be67779SAndroid Build Coastguard Worker   return parser->m_errorCode;
5969*6be67779SAndroid Build Coastguard Worker }
5970*6be67779SAndroid Build Coastguard Worker 
5971*6be67779SAndroid Build Coastguard Worker 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)5972*6be67779SAndroid Build Coastguard Worker storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5973*6be67779SAndroid Build Coastguard Worker                     const char *ptr, const char *end, STRING_POOL *pool,
5974*6be67779SAndroid Build Coastguard Worker                     enum XML_Account account) {
5975*6be67779SAndroid Build Coastguard Worker   enum XML_Error result
5976*6be67779SAndroid Build Coastguard Worker       = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
5977*6be67779SAndroid Build Coastguard Worker   if (result)
5978*6be67779SAndroid Build Coastguard Worker     return result;
5979*6be67779SAndroid Build Coastguard Worker   if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
5980*6be67779SAndroid Build Coastguard Worker     poolChop(pool);
5981*6be67779SAndroid Build Coastguard Worker   if (! poolAppendChar(pool, XML_T('\0')))
5982*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_NO_MEMORY;
5983*6be67779SAndroid Build Coastguard Worker   return XML_ERROR_NONE;
5984*6be67779SAndroid Build Coastguard Worker }
5985*6be67779SAndroid Build Coastguard Worker 
5986*6be67779SAndroid Build Coastguard Worker 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)5987*6be67779SAndroid Build Coastguard Worker appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5988*6be67779SAndroid Build Coastguard Worker                      const char *ptr, const char *end, STRING_POOL *pool,
5989*6be67779SAndroid Build Coastguard Worker                      enum XML_Account account) {
5990*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5991*6be67779SAndroid Build Coastguard Worker #ifndef XML_DTD
5992*6be67779SAndroid Build Coastguard Worker   UNUSED_P(account);
5993*6be67779SAndroid Build Coastguard Worker #endif
5994*6be67779SAndroid Build Coastguard Worker 
5995*6be67779SAndroid Build Coastguard Worker   for (;;) {
5996*6be67779SAndroid Build Coastguard Worker     const char *next
5997*6be67779SAndroid Build Coastguard Worker         = ptr; /* XmlAttributeValueTok doesn't always set the last arg */
5998*6be67779SAndroid Build Coastguard Worker     int tok = XmlAttributeValueTok(enc, ptr, end, &next);
5999*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
6000*6be67779SAndroid Build Coastguard Worker     if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) {
6001*6be67779SAndroid Build Coastguard Worker       accountingOnAbort(parser);
6002*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
6003*6be67779SAndroid Build Coastguard Worker     }
6004*6be67779SAndroid Build Coastguard Worker #endif
6005*6be67779SAndroid Build Coastguard Worker     switch (tok) {
6006*6be67779SAndroid Build Coastguard Worker     case XML_TOK_NONE:
6007*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NONE;
6008*6be67779SAndroid Build Coastguard Worker     case XML_TOK_INVALID:
6009*6be67779SAndroid Build Coastguard Worker       if (enc == parser->m_encoding)
6010*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = next;
6011*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_INVALID_TOKEN;
6012*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL:
6013*6be67779SAndroid Build Coastguard Worker       if (enc == parser->m_encoding)
6014*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = ptr;
6015*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_INVALID_TOKEN;
6016*6be67779SAndroid Build Coastguard Worker     case XML_TOK_CHAR_REF: {
6017*6be67779SAndroid Build Coastguard Worker       XML_Char buf[XML_ENCODE_MAX];
6018*6be67779SAndroid Build Coastguard Worker       int i;
6019*6be67779SAndroid Build Coastguard Worker       int n = XmlCharRefNumber(enc, ptr);
6020*6be67779SAndroid Build Coastguard Worker       if (n < 0) {
6021*6be67779SAndroid Build Coastguard Worker         if (enc == parser->m_encoding)
6022*6be67779SAndroid Build Coastguard Worker           parser->m_eventPtr = ptr;
6023*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_BAD_CHAR_REF;
6024*6be67779SAndroid Build Coastguard Worker       }
6025*6be67779SAndroid Build Coastguard Worker       if (! isCdata && n == 0x20 /* space */
6026*6be67779SAndroid Build Coastguard Worker           && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
6027*6be67779SAndroid Build Coastguard Worker         break;
6028*6be67779SAndroid Build Coastguard Worker       n = XmlEncode(n, (ICHAR *)buf);
6029*6be67779SAndroid Build Coastguard Worker       /* The XmlEncode() functions can never return 0 here.  That
6030*6be67779SAndroid Build Coastguard Worker        * error return happens if the code point passed in is either
6031*6be67779SAndroid Build Coastguard Worker        * negative or greater than or equal to 0x110000.  The
6032*6be67779SAndroid Build Coastguard Worker        * XmlCharRefNumber() functions will all return a number
6033*6be67779SAndroid Build Coastguard Worker        * strictly less than 0x110000 or a negative value if an error
6034*6be67779SAndroid Build Coastguard Worker        * occurred.  The negative value is intercepted above, so
6035*6be67779SAndroid Build Coastguard Worker        * XmlEncode() is never passed a value it might return an
6036*6be67779SAndroid Build Coastguard Worker        * error for.
6037*6be67779SAndroid Build Coastguard Worker        */
6038*6be67779SAndroid Build Coastguard Worker       for (i = 0; i < n; i++) {
6039*6be67779SAndroid Build Coastguard Worker         if (! poolAppendChar(pool, buf[i]))
6040*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
6041*6be67779SAndroid Build Coastguard Worker       }
6042*6be67779SAndroid Build Coastguard Worker     } break;
6043*6be67779SAndroid Build Coastguard Worker     case XML_TOK_DATA_CHARS:
6044*6be67779SAndroid Build Coastguard Worker       if (! poolAppend(pool, enc, ptr, next))
6045*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
6046*6be67779SAndroid Build Coastguard Worker       break;
6047*6be67779SAndroid Build Coastguard Worker     case XML_TOK_TRAILING_CR:
6048*6be67779SAndroid Build Coastguard Worker       next = ptr + enc->minBytesPerChar;
6049*6be67779SAndroid Build Coastguard Worker       /* fall through */
6050*6be67779SAndroid Build Coastguard Worker     case XML_TOK_ATTRIBUTE_VALUE_S:
6051*6be67779SAndroid Build Coastguard Worker     case XML_TOK_DATA_NEWLINE:
6052*6be67779SAndroid Build Coastguard Worker       if (! isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
6053*6be67779SAndroid Build Coastguard Worker         break;
6054*6be67779SAndroid Build Coastguard Worker       if (! poolAppendChar(pool, 0x20))
6055*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
6056*6be67779SAndroid Build Coastguard Worker       break;
6057*6be67779SAndroid Build Coastguard Worker     case XML_TOK_ENTITY_REF: {
6058*6be67779SAndroid Build Coastguard Worker       const XML_Char *name;
6059*6be67779SAndroid Build Coastguard Worker       ENTITY *entity;
6060*6be67779SAndroid Build Coastguard Worker       char checkEntityDecl;
6061*6be67779SAndroid Build Coastguard Worker       XML_Char ch = (XML_Char)XmlPredefinedEntityName(
6062*6be67779SAndroid Build Coastguard Worker           enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
6063*6be67779SAndroid Build Coastguard Worker       if (ch) {
6064*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
6065*6be67779SAndroid Build Coastguard Worker         /* NOTE: We are replacing 4-6 characters original input for 1 character
6066*6be67779SAndroid Build Coastguard Worker          *       so there is no amplification and hence recording without
6067*6be67779SAndroid Build Coastguard Worker          *       protection. */
6068*6be67779SAndroid Build Coastguard Worker         accountingDiffTolerated(parser, tok, (char *)&ch,
6069*6be67779SAndroid Build Coastguard Worker                                 ((char *)&ch) + sizeof(XML_Char), __LINE__,
6070*6be67779SAndroid Build Coastguard Worker                                 XML_ACCOUNT_ENTITY_EXPANSION);
6071*6be67779SAndroid Build Coastguard Worker #endif /* XML_GE == 1 */
6072*6be67779SAndroid Build Coastguard Worker         if (! poolAppendChar(pool, ch))
6073*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_NO_MEMORY;
6074*6be67779SAndroid Build Coastguard Worker         break;
6075*6be67779SAndroid Build Coastguard Worker       }
6076*6be67779SAndroid Build Coastguard Worker       name = poolStoreString(&parser->m_temp2Pool, enc,
6077*6be67779SAndroid Build Coastguard Worker                              ptr + enc->minBytesPerChar,
6078*6be67779SAndroid Build Coastguard Worker                              next - enc->minBytesPerChar);
6079*6be67779SAndroid Build Coastguard Worker       if (! name)
6080*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_NO_MEMORY;
6081*6be67779SAndroid Build Coastguard Worker       entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
6082*6be67779SAndroid Build Coastguard Worker       poolDiscard(&parser->m_temp2Pool);
6083*6be67779SAndroid Build Coastguard Worker       /* First, determine if a check for an existing declaration is needed;
6084*6be67779SAndroid Build Coastguard Worker          if yes, check that the entity exists, and that it is internal.
6085*6be67779SAndroid Build Coastguard Worker       */
6086*6be67779SAndroid Build Coastguard Worker       if (pool == &dtd->pool) /* are we called from prolog? */
6087*6be67779SAndroid Build Coastguard Worker         checkEntityDecl =
6088*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
6089*6be67779SAndroid Build Coastguard Worker             parser->m_prologState.documentEntity &&
6090*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
6091*6be67779SAndroid Build Coastguard Worker             (dtd->standalone ? ! parser->m_openInternalEntities
6092*6be67779SAndroid Build Coastguard Worker                              : ! dtd->hasParamEntityRefs);
6093*6be67779SAndroid Build Coastguard Worker       else /* if (pool == &parser->m_tempPool): we are called from content */
6094*6be67779SAndroid Build Coastguard Worker         checkEntityDecl = ! dtd->hasParamEntityRefs || dtd->standalone;
6095*6be67779SAndroid Build Coastguard Worker       if (checkEntityDecl) {
6096*6be67779SAndroid Build Coastguard Worker         if (! entity)
6097*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_UNDEFINED_ENTITY;
6098*6be67779SAndroid Build Coastguard Worker         else if (! entity->is_internal)
6099*6be67779SAndroid Build Coastguard Worker           return XML_ERROR_ENTITY_DECLARED_IN_PE;
6100*6be67779SAndroid Build Coastguard Worker       } else if (! entity) {
6101*6be67779SAndroid Build Coastguard Worker         /* Cannot report skipped entity here - see comments on
6102*6be67779SAndroid Build Coastguard Worker            parser->m_skippedEntityHandler.
6103*6be67779SAndroid Build Coastguard Worker         if (parser->m_skippedEntityHandler)
6104*6be67779SAndroid Build Coastguard Worker           parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
6105*6be67779SAndroid Build Coastguard Worker         */
6106*6be67779SAndroid Build Coastguard Worker         /* Cannot call the default handler because this would be
6107*6be67779SAndroid Build Coastguard Worker            out of sync with the call to the startElementHandler.
6108*6be67779SAndroid Build Coastguard Worker         if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
6109*6be67779SAndroid Build Coastguard Worker           reportDefault(parser, enc, ptr, next);
6110*6be67779SAndroid Build Coastguard Worker         */
6111*6be67779SAndroid Build Coastguard Worker         break;
6112*6be67779SAndroid Build Coastguard Worker       }
6113*6be67779SAndroid Build Coastguard Worker       if (entity->open) {
6114*6be67779SAndroid Build Coastguard Worker         if (enc == parser->m_encoding) {
6115*6be67779SAndroid Build Coastguard Worker           /* It does not appear that this line can be executed.
6116*6be67779SAndroid Build Coastguard Worker            *
6117*6be67779SAndroid Build Coastguard Worker            * The "if (entity->open)" check catches recursive entity
6118*6be67779SAndroid Build Coastguard Worker            * definitions.  In order to be called with an open
6119*6be67779SAndroid Build Coastguard Worker            * entity, it must have gone through this code before and
6120*6be67779SAndroid Build Coastguard Worker            * been through the recursive call to
6121*6be67779SAndroid Build Coastguard Worker            * appendAttributeValue() some lines below.  That call
6122*6be67779SAndroid Build Coastguard Worker            * sets the local encoding ("enc") to the parser's
6123*6be67779SAndroid Build Coastguard Worker            * internal encoding (internal_utf8 or internal_utf16),
6124*6be67779SAndroid Build Coastguard Worker            * which can never be the same as the principle encoding.
6125*6be67779SAndroid Build Coastguard Worker            * It doesn't appear there is another code path that gets
6126*6be67779SAndroid Build Coastguard Worker            * here with entity->open being TRUE.
6127*6be67779SAndroid Build Coastguard Worker            *
6128*6be67779SAndroid Build Coastguard Worker            * Since it is not certain that this logic is watertight,
6129*6be67779SAndroid Build Coastguard Worker            * we keep the line and merely exclude it from coverage
6130*6be67779SAndroid Build Coastguard Worker            * tests.
6131*6be67779SAndroid Build Coastguard Worker            */
6132*6be67779SAndroid Build Coastguard Worker           parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
6133*6be67779SAndroid Build Coastguard Worker         }
6134*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_RECURSIVE_ENTITY_REF;
6135*6be67779SAndroid Build Coastguard Worker       }
6136*6be67779SAndroid Build Coastguard Worker       if (entity->notation) {
6137*6be67779SAndroid Build Coastguard Worker         if (enc == parser->m_encoding)
6138*6be67779SAndroid Build Coastguard Worker           parser->m_eventPtr = ptr;
6139*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_BINARY_ENTITY_REF;
6140*6be67779SAndroid Build Coastguard Worker       }
6141*6be67779SAndroid Build Coastguard Worker       if (! entity->textPtr) {
6142*6be67779SAndroid Build Coastguard Worker         if (enc == parser->m_encoding)
6143*6be67779SAndroid Build Coastguard Worker           parser->m_eventPtr = ptr;
6144*6be67779SAndroid Build Coastguard Worker         return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
6145*6be67779SAndroid Build Coastguard Worker       } else {
6146*6be67779SAndroid Build Coastguard Worker         enum XML_Error result;
6147*6be67779SAndroid Build Coastguard Worker         const XML_Char *textEnd = entity->textPtr + entity->textLen;
6148*6be67779SAndroid Build Coastguard Worker         entity->open = XML_TRUE;
6149*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
6150*6be67779SAndroid Build Coastguard Worker         entityTrackingOnOpen(parser, entity, __LINE__);
6151*6be67779SAndroid Build Coastguard Worker #endif
6152*6be67779SAndroid Build Coastguard Worker         result = appendAttributeValue(parser, parser->m_internalEncoding,
6153*6be67779SAndroid Build Coastguard Worker                                       isCdata, (const char *)entity->textPtr,
6154*6be67779SAndroid Build Coastguard Worker                                       (const char *)textEnd, pool,
6155*6be67779SAndroid Build Coastguard Worker                                       XML_ACCOUNT_ENTITY_EXPANSION);
6156*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
6157*6be67779SAndroid Build Coastguard Worker         entityTrackingOnClose(parser, entity, __LINE__);
6158*6be67779SAndroid Build Coastguard Worker #endif
6159*6be67779SAndroid Build Coastguard Worker         entity->open = XML_FALSE;
6160*6be67779SAndroid Build Coastguard Worker         if (result)
6161*6be67779SAndroid Build Coastguard Worker           return result;
6162*6be67779SAndroid Build Coastguard Worker       }
6163*6be67779SAndroid Build Coastguard Worker     } break;
6164*6be67779SAndroid Build Coastguard Worker     default:
6165*6be67779SAndroid Build Coastguard Worker       /* The only token returned by XmlAttributeValueTok() that does
6166*6be67779SAndroid Build Coastguard Worker        * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
6167*6be67779SAndroid Build Coastguard Worker        * Getting that would require an entity name to contain an
6168*6be67779SAndroid Build Coastguard Worker        * incomplete XML character (e.g. \xE2\x82); however previous
6169*6be67779SAndroid Build Coastguard Worker        * tokenisers will have already recognised and rejected such
6170*6be67779SAndroid Build Coastguard Worker        * names before XmlAttributeValueTok() gets a look-in.  This
6171*6be67779SAndroid Build Coastguard Worker        * default case should be retained as a safety net, but the code
6172*6be67779SAndroid Build Coastguard Worker        * excluded from coverage tests.
6173*6be67779SAndroid Build Coastguard Worker        *
6174*6be67779SAndroid Build Coastguard Worker        * LCOV_EXCL_START
6175*6be67779SAndroid Build Coastguard Worker        */
6176*6be67779SAndroid Build Coastguard Worker       if (enc == parser->m_encoding)
6177*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = ptr;
6178*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_UNEXPECTED_STATE;
6179*6be67779SAndroid Build Coastguard Worker       /* LCOV_EXCL_STOP */
6180*6be67779SAndroid Build Coastguard Worker     }
6181*6be67779SAndroid Build Coastguard Worker     ptr = next;
6182*6be67779SAndroid Build Coastguard Worker   }
6183*6be67779SAndroid Build Coastguard Worker   /* not reached */
6184*6be67779SAndroid Build Coastguard Worker }
6185*6be67779SAndroid Build Coastguard Worker 
6186*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
6187*6be67779SAndroid Build Coastguard Worker static enum XML_Error
storeEntityValue(XML_Parser parser,const ENCODING * enc,const char * entityTextPtr,const char * entityTextEnd,enum XML_Account account)6188*6be67779SAndroid Build Coastguard Worker storeEntityValue(XML_Parser parser, const ENCODING *enc,
6189*6be67779SAndroid Build Coastguard Worker                  const char *entityTextPtr, const char *entityTextEnd,
6190*6be67779SAndroid Build Coastguard Worker                  enum XML_Account account) {
6191*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6192*6be67779SAndroid Build Coastguard Worker   STRING_POOL *pool = &(dtd->entityValuePool);
6193*6be67779SAndroid Build Coastguard Worker   enum XML_Error result = XML_ERROR_NONE;
6194*6be67779SAndroid Build Coastguard Worker #  ifdef XML_DTD
6195*6be67779SAndroid Build Coastguard Worker   int oldInEntityValue = parser->m_prologState.inEntityValue;
6196*6be67779SAndroid Build Coastguard Worker   parser->m_prologState.inEntityValue = 1;
6197*6be67779SAndroid Build Coastguard Worker #  else
6198*6be67779SAndroid Build Coastguard Worker   UNUSED_P(account);
6199*6be67779SAndroid Build Coastguard Worker #  endif /* XML_DTD */
6200*6be67779SAndroid Build Coastguard Worker   /* never return Null for the value argument in EntityDeclHandler,
6201*6be67779SAndroid Build Coastguard Worker      since this would indicate an external entity; therefore we
6202*6be67779SAndroid Build Coastguard Worker      have to make sure that entityValuePool.start is not null */
6203*6be67779SAndroid Build Coastguard Worker   if (! pool->blocks) {
6204*6be67779SAndroid Build Coastguard Worker     if (! poolGrow(pool))
6205*6be67779SAndroid Build Coastguard Worker       return XML_ERROR_NO_MEMORY;
6206*6be67779SAndroid Build Coastguard Worker   }
6207*6be67779SAndroid Build Coastguard Worker 
6208*6be67779SAndroid Build Coastguard Worker   for (;;) {
6209*6be67779SAndroid Build Coastguard Worker     const char *next
6210*6be67779SAndroid Build Coastguard Worker         = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
6211*6be67779SAndroid Build Coastguard Worker     int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
6212*6be67779SAndroid Build Coastguard Worker 
6213*6be67779SAndroid Build Coastguard Worker     if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__,
6214*6be67779SAndroid Build Coastguard Worker                                   account)) {
6215*6be67779SAndroid Build Coastguard Worker       accountingOnAbort(parser);
6216*6be67779SAndroid Build Coastguard Worker       result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
6217*6be67779SAndroid Build Coastguard Worker       goto endEntityValue;
6218*6be67779SAndroid Build Coastguard Worker     }
6219*6be67779SAndroid Build Coastguard Worker 
6220*6be67779SAndroid Build Coastguard Worker     switch (tok) {
6221*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARAM_ENTITY_REF:
6222*6be67779SAndroid Build Coastguard Worker #  ifdef XML_DTD
6223*6be67779SAndroid Build Coastguard Worker       if (parser->m_isParamEntity || enc != parser->m_encoding) {
6224*6be67779SAndroid Build Coastguard Worker         const XML_Char *name;
6225*6be67779SAndroid Build Coastguard Worker         ENTITY *entity;
6226*6be67779SAndroid Build Coastguard Worker         name = poolStoreString(&parser->m_tempPool, enc,
6227*6be67779SAndroid Build Coastguard Worker                                entityTextPtr + enc->minBytesPerChar,
6228*6be67779SAndroid Build Coastguard Worker                                next - enc->minBytesPerChar);
6229*6be67779SAndroid Build Coastguard Worker         if (! name) {
6230*6be67779SAndroid Build Coastguard Worker           result = XML_ERROR_NO_MEMORY;
6231*6be67779SAndroid Build Coastguard Worker           goto endEntityValue;
6232*6be67779SAndroid Build Coastguard Worker         }
6233*6be67779SAndroid Build Coastguard Worker         entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
6234*6be67779SAndroid Build Coastguard Worker         poolDiscard(&parser->m_tempPool);
6235*6be67779SAndroid Build Coastguard Worker         if (! entity) {
6236*6be67779SAndroid Build Coastguard Worker           /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
6237*6be67779SAndroid Build Coastguard Worker           /* cannot report skipped entity here - see comments on
6238*6be67779SAndroid Build Coastguard Worker              parser->m_skippedEntityHandler
6239*6be67779SAndroid Build Coastguard Worker           if (parser->m_skippedEntityHandler)
6240*6be67779SAndroid Build Coastguard Worker             parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
6241*6be67779SAndroid Build Coastguard Worker           */
6242*6be67779SAndroid Build Coastguard Worker           dtd->keepProcessing = dtd->standalone;
6243*6be67779SAndroid Build Coastguard Worker           goto endEntityValue;
6244*6be67779SAndroid Build Coastguard Worker         }
6245*6be67779SAndroid Build Coastguard Worker         if (entity->open || (entity == parser->m_declEntity)) {
6246*6be67779SAndroid Build Coastguard Worker           if (enc == parser->m_encoding)
6247*6be67779SAndroid Build Coastguard Worker             parser->m_eventPtr = entityTextPtr;
6248*6be67779SAndroid Build Coastguard Worker           result = XML_ERROR_RECURSIVE_ENTITY_REF;
6249*6be67779SAndroid Build Coastguard Worker           goto endEntityValue;
6250*6be67779SAndroid Build Coastguard Worker         }
6251*6be67779SAndroid Build Coastguard Worker         if (entity->systemId) {
6252*6be67779SAndroid Build Coastguard Worker           if (parser->m_externalEntityRefHandler) {
6253*6be67779SAndroid Build Coastguard Worker             dtd->paramEntityRead = XML_FALSE;
6254*6be67779SAndroid Build Coastguard Worker             entity->open = XML_TRUE;
6255*6be67779SAndroid Build Coastguard Worker             entityTrackingOnOpen(parser, entity, __LINE__);
6256*6be67779SAndroid Build Coastguard Worker             if (! parser->m_externalEntityRefHandler(
6257*6be67779SAndroid Build Coastguard Worker                     parser->m_externalEntityRefHandlerArg, 0, entity->base,
6258*6be67779SAndroid Build Coastguard Worker                     entity->systemId, entity->publicId)) {
6259*6be67779SAndroid Build Coastguard Worker               entityTrackingOnClose(parser, entity, __LINE__);
6260*6be67779SAndroid Build Coastguard Worker               entity->open = XML_FALSE;
6261*6be67779SAndroid Build Coastguard Worker               result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
6262*6be67779SAndroid Build Coastguard Worker               goto endEntityValue;
6263*6be67779SAndroid Build Coastguard Worker             }
6264*6be67779SAndroid Build Coastguard Worker             entityTrackingOnClose(parser, entity, __LINE__);
6265*6be67779SAndroid Build Coastguard Worker             entity->open = XML_FALSE;
6266*6be67779SAndroid Build Coastguard Worker             if (! dtd->paramEntityRead)
6267*6be67779SAndroid Build Coastguard Worker               dtd->keepProcessing = dtd->standalone;
6268*6be67779SAndroid Build Coastguard Worker           } else
6269*6be67779SAndroid Build Coastguard Worker             dtd->keepProcessing = dtd->standalone;
6270*6be67779SAndroid Build Coastguard Worker         } else {
6271*6be67779SAndroid Build Coastguard Worker           entity->open = XML_TRUE;
6272*6be67779SAndroid Build Coastguard Worker           entityTrackingOnOpen(parser, entity, __LINE__);
6273*6be67779SAndroid Build Coastguard Worker           result = storeEntityValue(
6274*6be67779SAndroid Build Coastguard Worker               parser, parser->m_internalEncoding, (const char *)entity->textPtr,
6275*6be67779SAndroid Build Coastguard Worker               (const char *)(entity->textPtr + entity->textLen),
6276*6be67779SAndroid Build Coastguard Worker               XML_ACCOUNT_ENTITY_EXPANSION);
6277*6be67779SAndroid Build Coastguard Worker           entityTrackingOnClose(parser, entity, __LINE__);
6278*6be67779SAndroid Build Coastguard Worker           entity->open = XML_FALSE;
6279*6be67779SAndroid Build Coastguard Worker           if (result)
6280*6be67779SAndroid Build Coastguard Worker             goto endEntityValue;
6281*6be67779SAndroid Build Coastguard Worker         }
6282*6be67779SAndroid Build Coastguard Worker         break;
6283*6be67779SAndroid Build Coastguard Worker       }
6284*6be67779SAndroid Build Coastguard Worker #  endif /* XML_DTD */
6285*6be67779SAndroid Build Coastguard Worker       /* In the internal subset, PE references are not legal
6286*6be67779SAndroid Build Coastguard Worker          within markup declarations, e.g entity values in this case. */
6287*6be67779SAndroid Build Coastguard Worker       parser->m_eventPtr = entityTextPtr;
6288*6be67779SAndroid Build Coastguard Worker       result = XML_ERROR_PARAM_ENTITY_REF;
6289*6be67779SAndroid Build Coastguard Worker       goto endEntityValue;
6290*6be67779SAndroid Build Coastguard Worker     case XML_TOK_NONE:
6291*6be67779SAndroid Build Coastguard Worker       result = XML_ERROR_NONE;
6292*6be67779SAndroid Build Coastguard Worker       goto endEntityValue;
6293*6be67779SAndroid Build Coastguard Worker     case XML_TOK_ENTITY_REF:
6294*6be67779SAndroid Build Coastguard Worker     case XML_TOK_DATA_CHARS:
6295*6be67779SAndroid Build Coastguard Worker       if (! poolAppend(pool, enc, entityTextPtr, next)) {
6296*6be67779SAndroid Build Coastguard Worker         result = XML_ERROR_NO_MEMORY;
6297*6be67779SAndroid Build Coastguard Worker         goto endEntityValue;
6298*6be67779SAndroid Build Coastguard Worker       }
6299*6be67779SAndroid Build Coastguard Worker       break;
6300*6be67779SAndroid Build Coastguard Worker     case XML_TOK_TRAILING_CR:
6301*6be67779SAndroid Build Coastguard Worker       next = entityTextPtr + enc->minBytesPerChar;
6302*6be67779SAndroid Build Coastguard Worker       /* fall through */
6303*6be67779SAndroid Build Coastguard Worker     case XML_TOK_DATA_NEWLINE:
6304*6be67779SAndroid Build Coastguard Worker       if (pool->end == pool->ptr && ! poolGrow(pool)) {
6305*6be67779SAndroid Build Coastguard Worker         result = XML_ERROR_NO_MEMORY;
6306*6be67779SAndroid Build Coastguard Worker         goto endEntityValue;
6307*6be67779SAndroid Build Coastguard Worker       }
6308*6be67779SAndroid Build Coastguard Worker       *(pool->ptr)++ = 0xA;
6309*6be67779SAndroid Build Coastguard Worker       break;
6310*6be67779SAndroid Build Coastguard Worker     case XML_TOK_CHAR_REF: {
6311*6be67779SAndroid Build Coastguard Worker       XML_Char buf[XML_ENCODE_MAX];
6312*6be67779SAndroid Build Coastguard Worker       int i;
6313*6be67779SAndroid Build Coastguard Worker       int n = XmlCharRefNumber(enc, entityTextPtr);
6314*6be67779SAndroid Build Coastguard Worker       if (n < 0) {
6315*6be67779SAndroid Build Coastguard Worker         if (enc == parser->m_encoding)
6316*6be67779SAndroid Build Coastguard Worker           parser->m_eventPtr = entityTextPtr;
6317*6be67779SAndroid Build Coastguard Worker         result = XML_ERROR_BAD_CHAR_REF;
6318*6be67779SAndroid Build Coastguard Worker         goto endEntityValue;
6319*6be67779SAndroid Build Coastguard Worker       }
6320*6be67779SAndroid Build Coastguard Worker       n = XmlEncode(n, (ICHAR *)buf);
6321*6be67779SAndroid Build Coastguard Worker       /* The XmlEncode() functions can never return 0 here.  That
6322*6be67779SAndroid Build Coastguard Worker        * error return happens if the code point passed in is either
6323*6be67779SAndroid Build Coastguard Worker        * negative or greater than or equal to 0x110000.  The
6324*6be67779SAndroid Build Coastguard Worker        * XmlCharRefNumber() functions will all return a number
6325*6be67779SAndroid Build Coastguard Worker        * strictly less than 0x110000 or a negative value if an error
6326*6be67779SAndroid Build Coastguard Worker        * occurred.  The negative value is intercepted above, so
6327*6be67779SAndroid Build Coastguard Worker        * XmlEncode() is never passed a value it might return an
6328*6be67779SAndroid Build Coastguard Worker        * error for.
6329*6be67779SAndroid Build Coastguard Worker        */
6330*6be67779SAndroid Build Coastguard Worker       for (i = 0; i < n; i++) {
6331*6be67779SAndroid Build Coastguard Worker         if (pool->end == pool->ptr && ! poolGrow(pool)) {
6332*6be67779SAndroid Build Coastguard Worker           result = XML_ERROR_NO_MEMORY;
6333*6be67779SAndroid Build Coastguard Worker           goto endEntityValue;
6334*6be67779SAndroid Build Coastguard Worker         }
6335*6be67779SAndroid Build Coastguard Worker         *(pool->ptr)++ = buf[i];
6336*6be67779SAndroid Build Coastguard Worker       }
6337*6be67779SAndroid Build Coastguard Worker     } break;
6338*6be67779SAndroid Build Coastguard Worker     case XML_TOK_PARTIAL:
6339*6be67779SAndroid Build Coastguard Worker       if (enc == parser->m_encoding)
6340*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = entityTextPtr;
6341*6be67779SAndroid Build Coastguard Worker       result = XML_ERROR_INVALID_TOKEN;
6342*6be67779SAndroid Build Coastguard Worker       goto endEntityValue;
6343*6be67779SAndroid Build Coastguard Worker     case XML_TOK_INVALID:
6344*6be67779SAndroid Build Coastguard Worker       if (enc == parser->m_encoding)
6345*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = next;
6346*6be67779SAndroid Build Coastguard Worker       result = XML_ERROR_INVALID_TOKEN;
6347*6be67779SAndroid Build Coastguard Worker       goto endEntityValue;
6348*6be67779SAndroid Build Coastguard Worker     default:
6349*6be67779SAndroid Build Coastguard Worker       /* This default case should be unnecessary -- all the tokens
6350*6be67779SAndroid Build Coastguard Worker        * that XmlEntityValueTok() can return have their own explicit
6351*6be67779SAndroid Build Coastguard Worker        * cases -- but should be retained for safety.  We do however
6352*6be67779SAndroid Build Coastguard Worker        * exclude it from the coverage statistics.
6353*6be67779SAndroid Build Coastguard Worker        *
6354*6be67779SAndroid Build Coastguard Worker        * LCOV_EXCL_START
6355*6be67779SAndroid Build Coastguard Worker        */
6356*6be67779SAndroid Build Coastguard Worker       if (enc == parser->m_encoding)
6357*6be67779SAndroid Build Coastguard Worker         parser->m_eventPtr = entityTextPtr;
6358*6be67779SAndroid Build Coastguard Worker       result = XML_ERROR_UNEXPECTED_STATE;
6359*6be67779SAndroid Build Coastguard Worker       goto endEntityValue;
6360*6be67779SAndroid Build Coastguard Worker       /* LCOV_EXCL_STOP */
6361*6be67779SAndroid Build Coastguard Worker     }
6362*6be67779SAndroid Build Coastguard Worker     entityTextPtr = next;
6363*6be67779SAndroid Build Coastguard Worker   }
6364*6be67779SAndroid Build Coastguard Worker endEntityValue:
6365*6be67779SAndroid Build Coastguard Worker #  ifdef XML_DTD
6366*6be67779SAndroid Build Coastguard Worker   parser->m_prologState.inEntityValue = oldInEntityValue;
6367*6be67779SAndroid Build Coastguard Worker #  endif /* XML_DTD */
6368*6be67779SAndroid Build Coastguard Worker   return result;
6369*6be67779SAndroid Build Coastguard Worker }
6370*6be67779SAndroid Build Coastguard Worker 
6371*6be67779SAndroid Build Coastguard Worker #else /* XML_GE == 0 */
6372*6be67779SAndroid Build Coastguard Worker 
6373*6be67779SAndroid Build Coastguard Worker static enum XML_Error
storeSelfEntityValue(XML_Parser parser,ENTITY * entity)6374*6be67779SAndroid Build Coastguard Worker storeSelfEntityValue(XML_Parser parser, ENTITY *entity) {
6375*6be67779SAndroid Build Coastguard Worker   // This will store "&amp;entity123;" in entity->textPtr
6376*6be67779SAndroid Build Coastguard Worker   // to end up as "&entity123;" in the handler.
6377*6be67779SAndroid Build Coastguard Worker   const char *const entity_start = "&amp;";
6378*6be67779SAndroid Build Coastguard Worker   const char *const entity_end = ";";
6379*6be67779SAndroid Build Coastguard Worker 
6380*6be67779SAndroid Build Coastguard Worker   STRING_POOL *const pool = &(parser->m_dtd->entityValuePool);
6381*6be67779SAndroid Build Coastguard Worker   if (! poolAppendString(pool, entity_start)
6382*6be67779SAndroid Build Coastguard Worker       || ! poolAppendString(pool, entity->name)
6383*6be67779SAndroid Build Coastguard Worker       || ! poolAppendString(pool, entity_end)) {
6384*6be67779SAndroid Build Coastguard Worker     poolDiscard(pool);
6385*6be67779SAndroid Build Coastguard Worker     return XML_ERROR_NO_MEMORY;
6386*6be67779SAndroid Build Coastguard Worker   }
6387*6be67779SAndroid Build Coastguard Worker 
6388*6be67779SAndroid Build Coastguard Worker   entity->textPtr = poolStart(pool);
6389*6be67779SAndroid Build Coastguard Worker   entity->textLen = (int)(poolLength(pool));
6390*6be67779SAndroid Build Coastguard Worker   poolFinish(pool);
6391*6be67779SAndroid Build Coastguard Worker 
6392*6be67779SAndroid Build Coastguard Worker   return XML_ERROR_NONE;
6393*6be67779SAndroid Build Coastguard Worker }
6394*6be67779SAndroid Build Coastguard Worker 
6395*6be67779SAndroid Build Coastguard Worker #endif /* XML_GE == 0 */
6396*6be67779SAndroid Build Coastguard Worker 
6397*6be67779SAndroid Build Coastguard Worker static void FASTCALL
normalizeLines(XML_Char * s)6398*6be67779SAndroid Build Coastguard Worker normalizeLines(XML_Char *s) {
6399*6be67779SAndroid Build Coastguard Worker   XML_Char *p;
6400*6be67779SAndroid Build Coastguard Worker   for (;; s++) {
6401*6be67779SAndroid Build Coastguard Worker     if (*s == XML_T('\0'))
6402*6be67779SAndroid Build Coastguard Worker       return;
6403*6be67779SAndroid Build Coastguard Worker     if (*s == 0xD)
6404*6be67779SAndroid Build Coastguard Worker       break;
6405*6be67779SAndroid Build Coastguard Worker   }
6406*6be67779SAndroid Build Coastguard Worker   p = s;
6407*6be67779SAndroid Build Coastguard Worker   do {
6408*6be67779SAndroid Build Coastguard Worker     if (*s == 0xD) {
6409*6be67779SAndroid Build Coastguard Worker       *p++ = 0xA;
6410*6be67779SAndroid Build Coastguard Worker       if (*++s == 0xA)
6411*6be67779SAndroid Build Coastguard Worker         s++;
6412*6be67779SAndroid Build Coastguard Worker     } else
6413*6be67779SAndroid Build Coastguard Worker       *p++ = *s++;
6414*6be67779SAndroid Build Coastguard Worker   } while (*s);
6415*6be67779SAndroid Build Coastguard Worker   *p = XML_T('\0');
6416*6be67779SAndroid Build Coastguard Worker }
6417*6be67779SAndroid Build Coastguard Worker 
6418*6be67779SAndroid Build Coastguard Worker static int
reportProcessingInstruction(XML_Parser parser,const ENCODING * enc,const char * start,const char * end)6419*6be67779SAndroid Build Coastguard Worker reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
6420*6be67779SAndroid Build Coastguard Worker                             const char *start, const char *end) {
6421*6be67779SAndroid Build Coastguard Worker   const XML_Char *target;
6422*6be67779SAndroid Build Coastguard Worker   XML_Char *data;
6423*6be67779SAndroid Build Coastguard Worker   const char *tem;
6424*6be67779SAndroid Build Coastguard Worker   if (! parser->m_processingInstructionHandler) {
6425*6be67779SAndroid Build Coastguard Worker     if (parser->m_defaultHandler)
6426*6be67779SAndroid Build Coastguard Worker       reportDefault(parser, enc, start, end);
6427*6be67779SAndroid Build Coastguard Worker     return 1;
6428*6be67779SAndroid Build Coastguard Worker   }
6429*6be67779SAndroid Build Coastguard Worker   start += enc->minBytesPerChar * 2;
6430*6be67779SAndroid Build Coastguard Worker   tem = start + XmlNameLength(enc, start);
6431*6be67779SAndroid Build Coastguard Worker   target = poolStoreString(&parser->m_tempPool, enc, start, tem);
6432*6be67779SAndroid Build Coastguard Worker   if (! target)
6433*6be67779SAndroid Build Coastguard Worker     return 0;
6434*6be67779SAndroid Build Coastguard Worker   poolFinish(&parser->m_tempPool);
6435*6be67779SAndroid Build Coastguard Worker   data = poolStoreString(&parser->m_tempPool, enc, XmlSkipS(enc, tem),
6436*6be67779SAndroid Build Coastguard Worker                          end - enc->minBytesPerChar * 2);
6437*6be67779SAndroid Build Coastguard Worker   if (! data)
6438*6be67779SAndroid Build Coastguard Worker     return 0;
6439*6be67779SAndroid Build Coastguard Worker   normalizeLines(data);
6440*6be67779SAndroid Build Coastguard Worker   parser->m_processingInstructionHandler(parser->m_handlerArg, target, data);
6441*6be67779SAndroid Build Coastguard Worker   poolClear(&parser->m_tempPool);
6442*6be67779SAndroid Build Coastguard Worker   return 1;
6443*6be67779SAndroid Build Coastguard Worker }
6444*6be67779SAndroid Build Coastguard Worker 
6445*6be67779SAndroid Build Coastguard Worker static int
reportComment(XML_Parser parser,const ENCODING * enc,const char * start,const char * end)6446*6be67779SAndroid Build Coastguard Worker reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
6447*6be67779SAndroid Build Coastguard Worker               const char *end) {
6448*6be67779SAndroid Build Coastguard Worker   XML_Char *data;
6449*6be67779SAndroid Build Coastguard Worker   if (! parser->m_commentHandler) {
6450*6be67779SAndroid Build Coastguard Worker     if (parser->m_defaultHandler)
6451*6be67779SAndroid Build Coastguard Worker       reportDefault(parser, enc, start, end);
6452*6be67779SAndroid Build Coastguard Worker     return 1;
6453*6be67779SAndroid Build Coastguard Worker   }
6454*6be67779SAndroid Build Coastguard Worker   data = poolStoreString(&parser->m_tempPool, enc,
6455*6be67779SAndroid Build Coastguard Worker                          start + enc->minBytesPerChar * 4,
6456*6be67779SAndroid Build Coastguard Worker                          end - enc->minBytesPerChar * 3);
6457*6be67779SAndroid Build Coastguard Worker   if (! data)
6458*6be67779SAndroid Build Coastguard Worker     return 0;
6459*6be67779SAndroid Build Coastguard Worker   normalizeLines(data);
6460*6be67779SAndroid Build Coastguard Worker   parser->m_commentHandler(parser->m_handlerArg, data);
6461*6be67779SAndroid Build Coastguard Worker   poolClear(&parser->m_tempPool);
6462*6be67779SAndroid Build Coastguard Worker   return 1;
6463*6be67779SAndroid Build Coastguard Worker }
6464*6be67779SAndroid Build Coastguard Worker 
6465*6be67779SAndroid Build Coastguard Worker static void
reportDefault(XML_Parser parser,const ENCODING * enc,const char * s,const char * end)6466*6be67779SAndroid Build Coastguard Worker reportDefault(XML_Parser parser, const ENCODING *enc, const char *s,
6467*6be67779SAndroid Build Coastguard Worker               const char *end) {
6468*6be67779SAndroid Build Coastguard Worker   if (MUST_CONVERT(enc, s)) {
6469*6be67779SAndroid Build Coastguard Worker     enum XML_Convert_Result convert_res;
6470*6be67779SAndroid Build Coastguard Worker     const char **eventPP;
6471*6be67779SAndroid Build Coastguard Worker     const char **eventEndPP;
6472*6be67779SAndroid Build Coastguard Worker     if (enc == parser->m_encoding) {
6473*6be67779SAndroid Build Coastguard Worker       eventPP = &parser->m_eventPtr;
6474*6be67779SAndroid Build Coastguard Worker       eventEndPP = &parser->m_eventEndPtr;
6475*6be67779SAndroid Build Coastguard Worker     } else {
6476*6be67779SAndroid Build Coastguard Worker       /* To get here, two things must be true; the parser must be
6477*6be67779SAndroid Build Coastguard Worker        * using a character encoding that is not the same as the
6478*6be67779SAndroid Build Coastguard Worker        * encoding passed in, and the encoding passed in must need
6479*6be67779SAndroid Build Coastguard Worker        * conversion to the internal format (UTF-8 unless XML_UNICODE
6480*6be67779SAndroid Build Coastguard Worker        * is defined).  The only occasions on which the encoding passed
6481*6be67779SAndroid Build Coastguard Worker        * in is not the same as the parser's encoding are when it is
6482*6be67779SAndroid Build Coastguard Worker        * the internal encoding (e.g. a previously defined parameter
6483*6be67779SAndroid Build Coastguard Worker        * entity, already converted to internal format).  This by
6484*6be67779SAndroid Build Coastguard Worker        * definition doesn't need conversion, so the whole branch never
6485*6be67779SAndroid Build Coastguard Worker        * gets executed.
6486*6be67779SAndroid Build Coastguard Worker        *
6487*6be67779SAndroid Build Coastguard Worker        * For safety's sake we don't delete these lines and merely
6488*6be67779SAndroid Build Coastguard Worker        * exclude them from coverage statistics.
6489*6be67779SAndroid Build Coastguard Worker        *
6490*6be67779SAndroid Build Coastguard Worker        * LCOV_EXCL_START
6491*6be67779SAndroid Build Coastguard Worker        */
6492*6be67779SAndroid Build Coastguard Worker       eventPP = &(parser->m_openInternalEntities->internalEventPtr);
6493*6be67779SAndroid Build Coastguard Worker       eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
6494*6be67779SAndroid Build Coastguard Worker       /* LCOV_EXCL_STOP */
6495*6be67779SAndroid Build Coastguard Worker     }
6496*6be67779SAndroid Build Coastguard Worker     do {
6497*6be67779SAndroid Build Coastguard Worker       ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
6498*6be67779SAndroid Build Coastguard Worker       convert_res
6499*6be67779SAndroid Build Coastguard Worker           = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
6500*6be67779SAndroid Build Coastguard Worker       *eventEndPP = s;
6501*6be67779SAndroid Build Coastguard Worker       parser->m_defaultHandler(parser->m_handlerArg, parser->m_dataBuf,
6502*6be67779SAndroid Build Coastguard Worker                                (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
6503*6be67779SAndroid Build Coastguard Worker       *eventPP = s;
6504*6be67779SAndroid Build Coastguard Worker     } while ((convert_res != XML_CONVERT_COMPLETED)
6505*6be67779SAndroid Build Coastguard Worker              && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
6506*6be67779SAndroid Build Coastguard Worker   } else
6507*6be67779SAndroid Build Coastguard Worker     parser->m_defaultHandler(
6508*6be67779SAndroid Build Coastguard Worker         parser->m_handlerArg, (const XML_Char *)s,
6509*6be67779SAndroid Build Coastguard Worker         (int)((const XML_Char *)end - (const XML_Char *)s));
6510*6be67779SAndroid Build Coastguard Worker }
6511*6be67779SAndroid Build Coastguard Worker 
6512*6be67779SAndroid Build Coastguard Worker static int
defineAttribute(ELEMENT_TYPE * type,ATTRIBUTE_ID * attId,XML_Bool isCdata,XML_Bool isId,const XML_Char * value,XML_Parser parser)6513*6be67779SAndroid Build Coastguard Worker defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
6514*6be67779SAndroid Build Coastguard Worker                 XML_Bool isId, const XML_Char *value, XML_Parser parser) {
6515*6be67779SAndroid Build Coastguard Worker   DEFAULT_ATTRIBUTE *att;
6516*6be67779SAndroid Build Coastguard Worker   if (value || isId) {
6517*6be67779SAndroid Build Coastguard Worker     /* The handling of default attributes gets messed up if we have
6518*6be67779SAndroid Build Coastguard Worker        a default which duplicates a non-default. */
6519*6be67779SAndroid Build Coastguard Worker     int i;
6520*6be67779SAndroid Build Coastguard Worker     for (i = 0; i < type->nDefaultAtts; i++)
6521*6be67779SAndroid Build Coastguard Worker       if (attId == type->defaultAtts[i].id)
6522*6be67779SAndroid Build Coastguard Worker         return 1;
6523*6be67779SAndroid Build Coastguard Worker     if (isId && ! type->idAtt && ! attId->xmlns)
6524*6be67779SAndroid Build Coastguard Worker       type->idAtt = attId;
6525*6be67779SAndroid Build Coastguard Worker   }
6526*6be67779SAndroid Build Coastguard Worker   if (type->nDefaultAtts == type->allocDefaultAtts) {
6527*6be67779SAndroid Build Coastguard Worker     if (type->allocDefaultAtts == 0) {
6528*6be67779SAndroid Build Coastguard Worker       type->allocDefaultAtts = 8;
6529*6be67779SAndroid Build Coastguard Worker       type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(
6530*6be67779SAndroid Build Coastguard Worker           parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6531*6be67779SAndroid Build Coastguard Worker       if (! type->defaultAtts) {
6532*6be67779SAndroid Build Coastguard Worker         type->allocDefaultAtts = 0;
6533*6be67779SAndroid Build Coastguard Worker         return 0;
6534*6be67779SAndroid Build Coastguard Worker       }
6535*6be67779SAndroid Build Coastguard Worker     } else {
6536*6be67779SAndroid Build Coastguard Worker       DEFAULT_ATTRIBUTE *temp;
6537*6be67779SAndroid Build Coastguard Worker 
6538*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent integer overflow */
6539*6be67779SAndroid Build Coastguard Worker       if (type->allocDefaultAtts > INT_MAX / 2) {
6540*6be67779SAndroid Build Coastguard Worker         return 0;
6541*6be67779SAndroid Build Coastguard Worker       }
6542*6be67779SAndroid Build Coastguard Worker 
6543*6be67779SAndroid Build Coastguard Worker       int count = type->allocDefaultAtts * 2;
6544*6be67779SAndroid Build Coastguard Worker 
6545*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent integer overflow.
6546*6be67779SAndroid Build Coastguard Worker        * The preprocessor guard addresses the "always false" warning
6547*6be67779SAndroid Build Coastguard Worker        * from -Wtype-limits on platforms where
6548*6be67779SAndroid Build Coastguard Worker        * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
6549*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
6550*6be67779SAndroid Build Coastguard Worker       if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) {
6551*6be67779SAndroid Build Coastguard Worker         return 0;
6552*6be67779SAndroid Build Coastguard Worker       }
6553*6be67779SAndroid Build Coastguard Worker #endif
6554*6be67779SAndroid Build Coastguard Worker 
6555*6be67779SAndroid Build Coastguard Worker       temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
6556*6be67779SAndroid Build Coastguard Worker                                           (count * sizeof(DEFAULT_ATTRIBUTE)));
6557*6be67779SAndroid Build Coastguard Worker       if (temp == NULL)
6558*6be67779SAndroid Build Coastguard Worker         return 0;
6559*6be67779SAndroid Build Coastguard Worker       type->allocDefaultAtts = count;
6560*6be67779SAndroid Build Coastguard Worker       type->defaultAtts = temp;
6561*6be67779SAndroid Build Coastguard Worker     }
6562*6be67779SAndroid Build Coastguard Worker   }
6563*6be67779SAndroid Build Coastguard Worker   att = type->defaultAtts + type->nDefaultAtts;
6564*6be67779SAndroid Build Coastguard Worker   att->id = attId;
6565*6be67779SAndroid Build Coastguard Worker   att->value = value;
6566*6be67779SAndroid Build Coastguard Worker   att->isCdata = isCdata;
6567*6be67779SAndroid Build Coastguard Worker   if (! isCdata)
6568*6be67779SAndroid Build Coastguard Worker     attId->maybeTokenized = XML_TRUE;
6569*6be67779SAndroid Build Coastguard Worker   type->nDefaultAtts += 1;
6570*6be67779SAndroid Build Coastguard Worker   return 1;
6571*6be67779SAndroid Build Coastguard Worker }
6572*6be67779SAndroid Build Coastguard Worker 
6573*6be67779SAndroid Build Coastguard Worker static int
setElementTypePrefix(XML_Parser parser,ELEMENT_TYPE * elementType)6574*6be67779SAndroid Build Coastguard Worker setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) {
6575*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6576*6be67779SAndroid Build Coastguard Worker   const XML_Char *name;
6577*6be67779SAndroid Build Coastguard Worker   for (name = elementType->name; *name; name++) {
6578*6be67779SAndroid Build Coastguard Worker     if (*name == XML_T(ASCII_COLON)) {
6579*6be67779SAndroid Build Coastguard Worker       PREFIX *prefix;
6580*6be67779SAndroid Build Coastguard Worker       const XML_Char *s;
6581*6be67779SAndroid Build Coastguard Worker       for (s = elementType->name; s != name; s++) {
6582*6be67779SAndroid Build Coastguard Worker         if (! poolAppendChar(&dtd->pool, *s))
6583*6be67779SAndroid Build Coastguard Worker           return 0;
6584*6be67779SAndroid Build Coastguard Worker       }
6585*6be67779SAndroid Build Coastguard Worker       if (! poolAppendChar(&dtd->pool, XML_T('\0')))
6586*6be67779SAndroid Build Coastguard Worker         return 0;
6587*6be67779SAndroid Build Coastguard Worker       prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
6588*6be67779SAndroid Build Coastguard Worker                                 sizeof(PREFIX));
6589*6be67779SAndroid Build Coastguard Worker       if (! prefix)
6590*6be67779SAndroid Build Coastguard Worker         return 0;
6591*6be67779SAndroid Build Coastguard Worker       if (prefix->name == poolStart(&dtd->pool))
6592*6be67779SAndroid Build Coastguard Worker         poolFinish(&dtd->pool);
6593*6be67779SAndroid Build Coastguard Worker       else
6594*6be67779SAndroid Build Coastguard Worker         poolDiscard(&dtd->pool);
6595*6be67779SAndroid Build Coastguard Worker       elementType->prefix = prefix;
6596*6be67779SAndroid Build Coastguard Worker       break;
6597*6be67779SAndroid Build Coastguard Worker     }
6598*6be67779SAndroid Build Coastguard Worker   }
6599*6be67779SAndroid Build Coastguard Worker   return 1;
6600*6be67779SAndroid Build Coastguard Worker }
6601*6be67779SAndroid Build Coastguard Worker 
6602*6be67779SAndroid Build Coastguard Worker static ATTRIBUTE_ID *
getAttributeId(XML_Parser parser,const ENCODING * enc,const char * start,const char * end)6603*6be67779SAndroid Build Coastguard Worker getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
6604*6be67779SAndroid Build Coastguard Worker                const char *end) {
6605*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6606*6be67779SAndroid Build Coastguard Worker   ATTRIBUTE_ID *id;
6607*6be67779SAndroid Build Coastguard Worker   const XML_Char *name;
6608*6be67779SAndroid Build Coastguard Worker   if (! poolAppendChar(&dtd->pool, XML_T('\0')))
6609*6be67779SAndroid Build Coastguard Worker     return NULL;
6610*6be67779SAndroid Build Coastguard Worker   name = poolStoreString(&dtd->pool, enc, start, end);
6611*6be67779SAndroid Build Coastguard Worker   if (! name)
6612*6be67779SAndroid Build Coastguard Worker     return NULL;
6613*6be67779SAndroid Build Coastguard Worker   /* skip quotation mark - its storage will be reused (like in name[-1]) */
6614*6be67779SAndroid Build Coastguard Worker   ++name;
6615*6be67779SAndroid Build Coastguard Worker   id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name,
6616*6be67779SAndroid Build Coastguard Worker                               sizeof(ATTRIBUTE_ID));
6617*6be67779SAndroid Build Coastguard Worker   if (! id)
6618*6be67779SAndroid Build Coastguard Worker     return NULL;
6619*6be67779SAndroid Build Coastguard Worker   if (id->name != name)
6620*6be67779SAndroid Build Coastguard Worker     poolDiscard(&dtd->pool);
6621*6be67779SAndroid Build Coastguard Worker   else {
6622*6be67779SAndroid Build Coastguard Worker     poolFinish(&dtd->pool);
6623*6be67779SAndroid Build Coastguard Worker     if (! parser->m_ns)
6624*6be67779SAndroid Build Coastguard Worker       ;
6625*6be67779SAndroid Build Coastguard Worker     else if (name[0] == XML_T(ASCII_x) && name[1] == XML_T(ASCII_m)
6626*6be67779SAndroid Build Coastguard Worker              && name[2] == XML_T(ASCII_l) && name[3] == XML_T(ASCII_n)
6627*6be67779SAndroid Build Coastguard Worker              && name[4] == XML_T(ASCII_s)
6628*6be67779SAndroid Build Coastguard Worker              && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
6629*6be67779SAndroid Build Coastguard Worker       if (name[5] == XML_T('\0'))
6630*6be67779SAndroid Build Coastguard Worker         id->prefix = &dtd->defaultPrefix;
6631*6be67779SAndroid Build Coastguard Worker       else
6632*6be67779SAndroid Build Coastguard Worker         id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6,
6633*6be67779SAndroid Build Coastguard Worker                                       sizeof(PREFIX));
6634*6be67779SAndroid Build Coastguard Worker       id->xmlns = XML_TRUE;
6635*6be67779SAndroid Build Coastguard Worker     } else {
6636*6be67779SAndroid Build Coastguard Worker       int i;
6637*6be67779SAndroid Build Coastguard Worker       for (i = 0; name[i]; i++) {
6638*6be67779SAndroid Build Coastguard Worker         /* attributes without prefix are *not* in the default namespace */
6639*6be67779SAndroid Build Coastguard Worker         if (name[i] == XML_T(ASCII_COLON)) {
6640*6be67779SAndroid Build Coastguard Worker           int j;
6641*6be67779SAndroid Build Coastguard Worker           for (j = 0; j < i; j++) {
6642*6be67779SAndroid Build Coastguard Worker             if (! poolAppendChar(&dtd->pool, name[j]))
6643*6be67779SAndroid Build Coastguard Worker               return NULL;
6644*6be67779SAndroid Build Coastguard Worker           }
6645*6be67779SAndroid Build Coastguard Worker           if (! poolAppendChar(&dtd->pool, XML_T('\0')))
6646*6be67779SAndroid Build Coastguard Worker             return NULL;
6647*6be67779SAndroid Build Coastguard Worker           id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes,
6648*6be67779SAndroid Build Coastguard Worker                                         poolStart(&dtd->pool), sizeof(PREFIX));
6649*6be67779SAndroid Build Coastguard Worker           if (! id->prefix)
6650*6be67779SAndroid Build Coastguard Worker             return NULL;
6651*6be67779SAndroid Build Coastguard Worker           if (id->prefix->name == poolStart(&dtd->pool))
6652*6be67779SAndroid Build Coastguard Worker             poolFinish(&dtd->pool);
6653*6be67779SAndroid Build Coastguard Worker           else
6654*6be67779SAndroid Build Coastguard Worker             poolDiscard(&dtd->pool);
6655*6be67779SAndroid Build Coastguard Worker           break;
6656*6be67779SAndroid Build Coastguard Worker         }
6657*6be67779SAndroid Build Coastguard Worker       }
6658*6be67779SAndroid Build Coastguard Worker     }
6659*6be67779SAndroid Build Coastguard Worker   }
6660*6be67779SAndroid Build Coastguard Worker   return id;
6661*6be67779SAndroid Build Coastguard Worker }
6662*6be67779SAndroid Build Coastguard Worker 
6663*6be67779SAndroid Build Coastguard Worker #define CONTEXT_SEP XML_T(ASCII_FF)
6664*6be67779SAndroid Build Coastguard Worker 
6665*6be67779SAndroid Build Coastguard Worker static const XML_Char *
getContext(XML_Parser parser)6666*6be67779SAndroid Build Coastguard Worker getContext(XML_Parser parser) {
6667*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6668*6be67779SAndroid Build Coastguard Worker   HASH_TABLE_ITER iter;
6669*6be67779SAndroid Build Coastguard Worker   XML_Bool needSep = XML_FALSE;
6670*6be67779SAndroid Build Coastguard Worker 
6671*6be67779SAndroid Build Coastguard Worker   if (dtd->defaultPrefix.binding) {
6672*6be67779SAndroid Build Coastguard Worker     int i;
6673*6be67779SAndroid Build Coastguard Worker     int len;
6674*6be67779SAndroid Build Coastguard Worker     if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
6675*6be67779SAndroid Build Coastguard Worker       return NULL;
6676*6be67779SAndroid Build Coastguard Worker     len = dtd->defaultPrefix.binding->uriLen;
6677*6be67779SAndroid Build Coastguard Worker     if (parser->m_namespaceSeparator)
6678*6be67779SAndroid Build Coastguard Worker       len--;
6679*6be67779SAndroid Build Coastguard Worker     for (i = 0; i < len; i++) {
6680*6be67779SAndroid Build Coastguard Worker       if (! poolAppendChar(&parser->m_tempPool,
6681*6be67779SAndroid Build Coastguard Worker                            dtd->defaultPrefix.binding->uri[i])) {
6682*6be67779SAndroid Build Coastguard Worker         /* Because of memory caching, I don't believe this line can be
6683*6be67779SAndroid Build Coastguard Worker          * executed.
6684*6be67779SAndroid Build Coastguard Worker          *
6685*6be67779SAndroid Build Coastguard Worker          * This is part of a loop copying the default prefix binding
6686*6be67779SAndroid Build Coastguard Worker          * URI into the parser's temporary string pool.  Previously,
6687*6be67779SAndroid Build Coastguard Worker          * that URI was copied into the same string pool, with a
6688*6be67779SAndroid Build Coastguard Worker          * terminating NUL character, as part of setContext().  When
6689*6be67779SAndroid Build Coastguard Worker          * the pool was cleared, that leaves a block definitely big
6690*6be67779SAndroid Build Coastguard Worker          * enough to hold the URI on the free block list of the pool.
6691*6be67779SAndroid Build Coastguard Worker          * The URI copy in getContext() therefore cannot run out of
6692*6be67779SAndroid Build Coastguard Worker          * memory.
6693*6be67779SAndroid Build Coastguard Worker          *
6694*6be67779SAndroid Build Coastguard Worker          * If the pool is used between the setContext() and
6695*6be67779SAndroid Build Coastguard Worker          * getContext() calls, the worst it can do is leave a bigger
6696*6be67779SAndroid Build Coastguard Worker          * block on the front of the free list.  Given that this is
6697*6be67779SAndroid Build Coastguard Worker          * all somewhat inobvious and program logic can be changed, we
6698*6be67779SAndroid Build Coastguard Worker          * don't delete the line but we do exclude it from the test
6699*6be67779SAndroid Build Coastguard Worker          * coverage statistics.
6700*6be67779SAndroid Build Coastguard Worker          */
6701*6be67779SAndroid Build Coastguard Worker         return NULL; /* LCOV_EXCL_LINE */
6702*6be67779SAndroid Build Coastguard Worker       }
6703*6be67779SAndroid Build Coastguard Worker     }
6704*6be67779SAndroid Build Coastguard Worker     needSep = XML_TRUE;
6705*6be67779SAndroid Build Coastguard Worker   }
6706*6be67779SAndroid Build Coastguard Worker 
6707*6be67779SAndroid Build Coastguard Worker   hashTableIterInit(&iter, &(dtd->prefixes));
6708*6be67779SAndroid Build Coastguard Worker   for (;;) {
6709*6be67779SAndroid Build Coastguard Worker     int i;
6710*6be67779SAndroid Build Coastguard Worker     int len;
6711*6be67779SAndroid Build Coastguard Worker     const XML_Char *s;
6712*6be67779SAndroid Build Coastguard Worker     PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
6713*6be67779SAndroid Build Coastguard Worker     if (! prefix)
6714*6be67779SAndroid Build Coastguard Worker       break;
6715*6be67779SAndroid Build Coastguard Worker     if (! prefix->binding) {
6716*6be67779SAndroid Build Coastguard Worker       /* This test appears to be (justifiable) paranoia.  There does
6717*6be67779SAndroid Build Coastguard Worker        * not seem to be a way of injecting a prefix without a binding
6718*6be67779SAndroid Build Coastguard Worker        * that doesn't get errored long before this function is called.
6719*6be67779SAndroid Build Coastguard Worker        * The test should remain for safety's sake, so we instead
6720*6be67779SAndroid Build Coastguard Worker        * exclude the following line from the coverage statistics.
6721*6be67779SAndroid Build Coastguard Worker        */
6722*6be67779SAndroid Build Coastguard Worker       continue; /* LCOV_EXCL_LINE */
6723*6be67779SAndroid Build Coastguard Worker     }
6724*6be67779SAndroid Build Coastguard Worker     if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
6725*6be67779SAndroid Build Coastguard Worker       return NULL;
6726*6be67779SAndroid Build Coastguard Worker     for (s = prefix->name; *s; s++)
6727*6be67779SAndroid Build Coastguard Worker       if (! poolAppendChar(&parser->m_tempPool, *s))
6728*6be67779SAndroid Build Coastguard Worker         return NULL;
6729*6be67779SAndroid Build Coastguard Worker     if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
6730*6be67779SAndroid Build Coastguard Worker       return NULL;
6731*6be67779SAndroid Build Coastguard Worker     len = prefix->binding->uriLen;
6732*6be67779SAndroid Build Coastguard Worker     if (parser->m_namespaceSeparator)
6733*6be67779SAndroid Build Coastguard Worker       len--;
6734*6be67779SAndroid Build Coastguard Worker     for (i = 0; i < len; i++)
6735*6be67779SAndroid Build Coastguard Worker       if (! poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i]))
6736*6be67779SAndroid Build Coastguard Worker         return NULL;
6737*6be67779SAndroid Build Coastguard Worker     needSep = XML_TRUE;
6738*6be67779SAndroid Build Coastguard Worker   }
6739*6be67779SAndroid Build Coastguard Worker 
6740*6be67779SAndroid Build Coastguard Worker   hashTableIterInit(&iter, &(dtd->generalEntities));
6741*6be67779SAndroid Build Coastguard Worker   for (;;) {
6742*6be67779SAndroid Build Coastguard Worker     const XML_Char *s;
6743*6be67779SAndroid Build Coastguard Worker     ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
6744*6be67779SAndroid Build Coastguard Worker     if (! e)
6745*6be67779SAndroid Build Coastguard Worker       break;
6746*6be67779SAndroid Build Coastguard Worker     if (! e->open)
6747*6be67779SAndroid Build Coastguard Worker       continue;
6748*6be67779SAndroid Build Coastguard Worker     if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
6749*6be67779SAndroid Build Coastguard Worker       return NULL;
6750*6be67779SAndroid Build Coastguard Worker     for (s = e->name; *s; s++)
6751*6be67779SAndroid Build Coastguard Worker       if (! poolAppendChar(&parser->m_tempPool, *s))
6752*6be67779SAndroid Build Coastguard Worker         return 0;
6753*6be67779SAndroid Build Coastguard Worker     needSep = XML_TRUE;
6754*6be67779SAndroid Build Coastguard Worker   }
6755*6be67779SAndroid Build Coastguard Worker 
6756*6be67779SAndroid Build Coastguard Worker   if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6757*6be67779SAndroid Build Coastguard Worker     return NULL;
6758*6be67779SAndroid Build Coastguard Worker   return parser->m_tempPool.start;
6759*6be67779SAndroid Build Coastguard Worker }
6760*6be67779SAndroid Build Coastguard Worker 
6761*6be67779SAndroid Build Coastguard Worker static XML_Bool
setContext(XML_Parser parser,const XML_Char * context)6762*6be67779SAndroid Build Coastguard Worker setContext(XML_Parser parser, const XML_Char *context) {
6763*6be67779SAndroid Build Coastguard Worker   if (context == NULL) {
6764*6be67779SAndroid Build Coastguard Worker     return XML_FALSE;
6765*6be67779SAndroid Build Coastguard Worker   }
6766*6be67779SAndroid Build Coastguard Worker 
6767*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6768*6be67779SAndroid Build Coastguard Worker   const XML_Char *s = context;
6769*6be67779SAndroid Build Coastguard Worker 
6770*6be67779SAndroid Build Coastguard Worker   while (*context != XML_T('\0')) {
6771*6be67779SAndroid Build Coastguard Worker     if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
6772*6be67779SAndroid Build Coastguard Worker       ENTITY *e;
6773*6be67779SAndroid Build Coastguard Worker       if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6774*6be67779SAndroid Build Coastguard Worker         return XML_FALSE;
6775*6be67779SAndroid Build Coastguard Worker       e = (ENTITY *)lookup(parser, &dtd->generalEntities,
6776*6be67779SAndroid Build Coastguard Worker                            poolStart(&parser->m_tempPool), 0);
6777*6be67779SAndroid Build Coastguard Worker       if (e)
6778*6be67779SAndroid Build Coastguard Worker         e->open = XML_TRUE;
6779*6be67779SAndroid Build Coastguard Worker       if (*s != XML_T('\0'))
6780*6be67779SAndroid Build Coastguard Worker         s++;
6781*6be67779SAndroid Build Coastguard Worker       context = s;
6782*6be67779SAndroid Build Coastguard Worker       poolDiscard(&parser->m_tempPool);
6783*6be67779SAndroid Build Coastguard Worker     } else if (*s == XML_T(ASCII_EQUALS)) {
6784*6be67779SAndroid Build Coastguard Worker       PREFIX *prefix;
6785*6be67779SAndroid Build Coastguard Worker       if (poolLength(&parser->m_tempPool) == 0)
6786*6be67779SAndroid Build Coastguard Worker         prefix = &dtd->defaultPrefix;
6787*6be67779SAndroid Build Coastguard Worker       else {
6788*6be67779SAndroid Build Coastguard Worker         if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6789*6be67779SAndroid Build Coastguard Worker           return XML_FALSE;
6790*6be67779SAndroid Build Coastguard Worker         prefix
6791*6be67779SAndroid Build Coastguard Worker             = (PREFIX *)lookup(parser, &dtd->prefixes,
6792*6be67779SAndroid Build Coastguard Worker                                poolStart(&parser->m_tempPool), sizeof(PREFIX));
6793*6be67779SAndroid Build Coastguard Worker         if (! prefix)
6794*6be67779SAndroid Build Coastguard Worker           return XML_FALSE;
6795*6be67779SAndroid Build Coastguard Worker         if (prefix->name == poolStart(&parser->m_tempPool)) {
6796*6be67779SAndroid Build Coastguard Worker           prefix->name = poolCopyString(&dtd->pool, prefix->name);
6797*6be67779SAndroid Build Coastguard Worker           if (! prefix->name)
6798*6be67779SAndroid Build Coastguard Worker             return XML_FALSE;
6799*6be67779SAndroid Build Coastguard Worker         }
6800*6be67779SAndroid Build Coastguard Worker         poolDiscard(&parser->m_tempPool);
6801*6be67779SAndroid Build Coastguard Worker       }
6802*6be67779SAndroid Build Coastguard Worker       for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0');
6803*6be67779SAndroid Build Coastguard Worker            context++)
6804*6be67779SAndroid Build Coastguard Worker         if (! poolAppendChar(&parser->m_tempPool, *context))
6805*6be67779SAndroid Build Coastguard Worker           return XML_FALSE;
6806*6be67779SAndroid Build Coastguard Worker       if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6807*6be67779SAndroid Build Coastguard Worker         return XML_FALSE;
6808*6be67779SAndroid Build Coastguard Worker       if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool),
6809*6be67779SAndroid Build Coastguard Worker                      &parser->m_inheritedBindings)
6810*6be67779SAndroid Build Coastguard Worker           != XML_ERROR_NONE)
6811*6be67779SAndroid Build Coastguard Worker         return XML_FALSE;
6812*6be67779SAndroid Build Coastguard Worker       poolDiscard(&parser->m_tempPool);
6813*6be67779SAndroid Build Coastguard Worker       if (*context != XML_T('\0'))
6814*6be67779SAndroid Build Coastguard Worker         ++context;
6815*6be67779SAndroid Build Coastguard Worker       s = context;
6816*6be67779SAndroid Build Coastguard Worker     } else {
6817*6be67779SAndroid Build Coastguard Worker       if (! poolAppendChar(&parser->m_tempPool, *s))
6818*6be67779SAndroid Build Coastguard Worker         return XML_FALSE;
6819*6be67779SAndroid Build Coastguard Worker       s++;
6820*6be67779SAndroid Build Coastguard Worker     }
6821*6be67779SAndroid Build Coastguard Worker   }
6822*6be67779SAndroid Build Coastguard Worker   return XML_TRUE;
6823*6be67779SAndroid Build Coastguard Worker }
6824*6be67779SAndroid Build Coastguard Worker 
6825*6be67779SAndroid Build Coastguard Worker static void FASTCALL
normalizePublicId(XML_Char * publicId)6826*6be67779SAndroid Build Coastguard Worker normalizePublicId(XML_Char *publicId) {
6827*6be67779SAndroid Build Coastguard Worker   XML_Char *p = publicId;
6828*6be67779SAndroid Build Coastguard Worker   XML_Char *s;
6829*6be67779SAndroid Build Coastguard Worker   for (s = publicId; *s; s++) {
6830*6be67779SAndroid Build Coastguard Worker     switch (*s) {
6831*6be67779SAndroid Build Coastguard Worker     case 0x20:
6832*6be67779SAndroid Build Coastguard Worker     case 0xD:
6833*6be67779SAndroid Build Coastguard Worker     case 0xA:
6834*6be67779SAndroid Build Coastguard Worker       if (p != publicId && p[-1] != 0x20)
6835*6be67779SAndroid Build Coastguard Worker         *p++ = 0x20;
6836*6be67779SAndroid Build Coastguard Worker       break;
6837*6be67779SAndroid Build Coastguard Worker     default:
6838*6be67779SAndroid Build Coastguard Worker       *p++ = *s;
6839*6be67779SAndroid Build Coastguard Worker     }
6840*6be67779SAndroid Build Coastguard Worker   }
6841*6be67779SAndroid Build Coastguard Worker   if (p != publicId && p[-1] == 0x20)
6842*6be67779SAndroid Build Coastguard Worker     --p;
6843*6be67779SAndroid Build Coastguard Worker   *p = XML_T('\0');
6844*6be67779SAndroid Build Coastguard Worker }
6845*6be67779SAndroid Build Coastguard Worker 
6846*6be67779SAndroid Build Coastguard Worker static DTD *
dtdCreate(const XML_Memory_Handling_Suite * ms)6847*6be67779SAndroid Build Coastguard Worker dtdCreate(const XML_Memory_Handling_Suite *ms) {
6848*6be67779SAndroid Build Coastguard Worker   DTD *p = ms->malloc_fcn(sizeof(DTD));
6849*6be67779SAndroid Build Coastguard Worker   if (p == NULL)
6850*6be67779SAndroid Build Coastguard Worker     return p;
6851*6be67779SAndroid Build Coastguard Worker   poolInit(&(p->pool), ms);
6852*6be67779SAndroid Build Coastguard Worker   poolInit(&(p->entityValuePool), ms);
6853*6be67779SAndroid Build Coastguard Worker   hashTableInit(&(p->generalEntities), ms);
6854*6be67779SAndroid Build Coastguard Worker   hashTableInit(&(p->elementTypes), ms);
6855*6be67779SAndroid Build Coastguard Worker   hashTableInit(&(p->attributeIds), ms);
6856*6be67779SAndroid Build Coastguard Worker   hashTableInit(&(p->prefixes), ms);
6857*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
6858*6be67779SAndroid Build Coastguard Worker   p->paramEntityRead = XML_FALSE;
6859*6be67779SAndroid Build Coastguard Worker   hashTableInit(&(p->paramEntities), ms);
6860*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
6861*6be67779SAndroid Build Coastguard Worker   p->defaultPrefix.name = NULL;
6862*6be67779SAndroid Build Coastguard Worker   p->defaultPrefix.binding = NULL;
6863*6be67779SAndroid Build Coastguard Worker 
6864*6be67779SAndroid Build Coastguard Worker   p->in_eldecl = XML_FALSE;
6865*6be67779SAndroid Build Coastguard Worker   p->scaffIndex = NULL;
6866*6be67779SAndroid Build Coastguard Worker   p->scaffold = NULL;
6867*6be67779SAndroid Build Coastguard Worker   p->scaffLevel = 0;
6868*6be67779SAndroid Build Coastguard Worker   p->scaffSize = 0;
6869*6be67779SAndroid Build Coastguard Worker   p->scaffCount = 0;
6870*6be67779SAndroid Build Coastguard Worker   p->contentStringLen = 0;
6871*6be67779SAndroid Build Coastguard Worker 
6872*6be67779SAndroid Build Coastguard Worker   p->keepProcessing = XML_TRUE;
6873*6be67779SAndroid Build Coastguard Worker   p->hasParamEntityRefs = XML_FALSE;
6874*6be67779SAndroid Build Coastguard Worker   p->standalone = XML_FALSE;
6875*6be67779SAndroid Build Coastguard Worker   return p;
6876*6be67779SAndroid Build Coastguard Worker }
6877*6be67779SAndroid Build Coastguard Worker 
6878*6be67779SAndroid Build Coastguard Worker static void
dtdReset(DTD * p,const XML_Memory_Handling_Suite * ms)6879*6be67779SAndroid Build Coastguard Worker dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {
6880*6be67779SAndroid Build Coastguard Worker   HASH_TABLE_ITER iter;
6881*6be67779SAndroid Build Coastguard Worker   hashTableIterInit(&iter, &(p->elementTypes));
6882*6be67779SAndroid Build Coastguard Worker   for (;;) {
6883*6be67779SAndroid Build Coastguard Worker     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6884*6be67779SAndroid Build Coastguard Worker     if (! e)
6885*6be67779SAndroid Build Coastguard Worker       break;
6886*6be67779SAndroid Build Coastguard Worker     if (e->allocDefaultAtts != 0)
6887*6be67779SAndroid Build Coastguard Worker       ms->free_fcn(e->defaultAtts);
6888*6be67779SAndroid Build Coastguard Worker   }
6889*6be67779SAndroid Build Coastguard Worker   hashTableClear(&(p->generalEntities));
6890*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
6891*6be67779SAndroid Build Coastguard Worker   p->paramEntityRead = XML_FALSE;
6892*6be67779SAndroid Build Coastguard Worker   hashTableClear(&(p->paramEntities));
6893*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
6894*6be67779SAndroid Build Coastguard Worker   hashTableClear(&(p->elementTypes));
6895*6be67779SAndroid Build Coastguard Worker   hashTableClear(&(p->attributeIds));
6896*6be67779SAndroid Build Coastguard Worker   hashTableClear(&(p->prefixes));
6897*6be67779SAndroid Build Coastguard Worker   poolClear(&(p->pool));
6898*6be67779SAndroid Build Coastguard Worker   poolClear(&(p->entityValuePool));
6899*6be67779SAndroid Build Coastguard Worker   p->defaultPrefix.name = NULL;
6900*6be67779SAndroid Build Coastguard Worker   p->defaultPrefix.binding = NULL;
6901*6be67779SAndroid Build Coastguard Worker 
6902*6be67779SAndroid Build Coastguard Worker   p->in_eldecl = XML_FALSE;
6903*6be67779SAndroid Build Coastguard Worker 
6904*6be67779SAndroid Build Coastguard Worker   ms->free_fcn(p->scaffIndex);
6905*6be67779SAndroid Build Coastguard Worker   p->scaffIndex = NULL;
6906*6be67779SAndroid Build Coastguard Worker   ms->free_fcn(p->scaffold);
6907*6be67779SAndroid Build Coastguard Worker   p->scaffold = NULL;
6908*6be67779SAndroid Build Coastguard Worker 
6909*6be67779SAndroid Build Coastguard Worker   p->scaffLevel = 0;
6910*6be67779SAndroid Build Coastguard Worker   p->scaffSize = 0;
6911*6be67779SAndroid Build Coastguard Worker   p->scaffCount = 0;
6912*6be67779SAndroid Build Coastguard Worker   p->contentStringLen = 0;
6913*6be67779SAndroid Build Coastguard Worker 
6914*6be67779SAndroid Build Coastguard Worker   p->keepProcessing = XML_TRUE;
6915*6be67779SAndroid Build Coastguard Worker   p->hasParamEntityRefs = XML_FALSE;
6916*6be67779SAndroid Build Coastguard Worker   p->standalone = XML_FALSE;
6917*6be67779SAndroid Build Coastguard Worker }
6918*6be67779SAndroid Build Coastguard Worker 
6919*6be67779SAndroid Build Coastguard Worker static void
dtdDestroy(DTD * p,XML_Bool isDocEntity,const XML_Memory_Handling_Suite * ms)6920*6be67779SAndroid Build Coastguard Worker dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
6921*6be67779SAndroid Build Coastguard Worker   HASH_TABLE_ITER iter;
6922*6be67779SAndroid Build Coastguard Worker   hashTableIterInit(&iter, &(p->elementTypes));
6923*6be67779SAndroid Build Coastguard Worker   for (;;) {
6924*6be67779SAndroid Build Coastguard Worker     ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6925*6be67779SAndroid Build Coastguard Worker     if (! e)
6926*6be67779SAndroid Build Coastguard Worker       break;
6927*6be67779SAndroid Build Coastguard Worker     if (e->allocDefaultAtts != 0)
6928*6be67779SAndroid Build Coastguard Worker       ms->free_fcn(e->defaultAtts);
6929*6be67779SAndroid Build Coastguard Worker   }
6930*6be67779SAndroid Build Coastguard Worker   hashTableDestroy(&(p->generalEntities));
6931*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
6932*6be67779SAndroid Build Coastguard Worker   hashTableDestroy(&(p->paramEntities));
6933*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
6934*6be67779SAndroid Build Coastguard Worker   hashTableDestroy(&(p->elementTypes));
6935*6be67779SAndroid Build Coastguard Worker   hashTableDestroy(&(p->attributeIds));
6936*6be67779SAndroid Build Coastguard Worker   hashTableDestroy(&(p->prefixes));
6937*6be67779SAndroid Build Coastguard Worker   poolDestroy(&(p->pool));
6938*6be67779SAndroid Build Coastguard Worker   poolDestroy(&(p->entityValuePool));
6939*6be67779SAndroid Build Coastguard Worker   if (isDocEntity) {
6940*6be67779SAndroid Build Coastguard Worker     ms->free_fcn(p->scaffIndex);
6941*6be67779SAndroid Build Coastguard Worker     ms->free_fcn(p->scaffold);
6942*6be67779SAndroid Build Coastguard Worker   }
6943*6be67779SAndroid Build Coastguard Worker   ms->free_fcn(p);
6944*6be67779SAndroid Build Coastguard Worker }
6945*6be67779SAndroid Build Coastguard Worker 
6946*6be67779SAndroid Build Coastguard Worker /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
6947*6be67779SAndroid Build Coastguard Worker    The new DTD has already been initialized.
6948*6be67779SAndroid Build Coastguard Worker */
6949*6be67779SAndroid Build Coastguard Worker static int
dtdCopy(XML_Parser oldParser,DTD * newDtd,const DTD * oldDtd,const XML_Memory_Handling_Suite * ms)6950*6be67779SAndroid Build Coastguard Worker dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
6951*6be67779SAndroid Build Coastguard Worker         const XML_Memory_Handling_Suite *ms) {
6952*6be67779SAndroid Build Coastguard Worker   HASH_TABLE_ITER iter;
6953*6be67779SAndroid Build Coastguard Worker 
6954*6be67779SAndroid Build Coastguard Worker   /* Copy the prefix table. */
6955*6be67779SAndroid Build Coastguard Worker 
6956*6be67779SAndroid Build Coastguard Worker   hashTableIterInit(&iter, &(oldDtd->prefixes));
6957*6be67779SAndroid Build Coastguard Worker   for (;;) {
6958*6be67779SAndroid Build Coastguard Worker     const XML_Char *name;
6959*6be67779SAndroid Build Coastguard Worker     const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
6960*6be67779SAndroid Build Coastguard Worker     if (! oldP)
6961*6be67779SAndroid Build Coastguard Worker       break;
6962*6be67779SAndroid Build Coastguard Worker     name = poolCopyString(&(newDtd->pool), oldP->name);
6963*6be67779SAndroid Build Coastguard Worker     if (! name)
6964*6be67779SAndroid Build Coastguard Worker       return 0;
6965*6be67779SAndroid Build Coastguard Worker     if (! lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
6966*6be67779SAndroid Build Coastguard Worker       return 0;
6967*6be67779SAndroid Build Coastguard Worker   }
6968*6be67779SAndroid Build Coastguard Worker 
6969*6be67779SAndroid Build Coastguard Worker   hashTableIterInit(&iter, &(oldDtd->attributeIds));
6970*6be67779SAndroid Build Coastguard Worker 
6971*6be67779SAndroid Build Coastguard Worker   /* Copy the attribute id table. */
6972*6be67779SAndroid Build Coastguard Worker 
6973*6be67779SAndroid Build Coastguard Worker   for (;;) {
6974*6be67779SAndroid Build Coastguard Worker     ATTRIBUTE_ID *newA;
6975*6be67779SAndroid Build Coastguard Worker     const XML_Char *name;
6976*6be67779SAndroid Build Coastguard Worker     const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
6977*6be67779SAndroid Build Coastguard Worker 
6978*6be67779SAndroid Build Coastguard Worker     if (! oldA)
6979*6be67779SAndroid Build Coastguard Worker       break;
6980*6be67779SAndroid Build Coastguard Worker     /* Remember to allocate the scratch byte before the name. */
6981*6be67779SAndroid Build Coastguard Worker     if (! poolAppendChar(&(newDtd->pool), XML_T('\0')))
6982*6be67779SAndroid Build Coastguard Worker       return 0;
6983*6be67779SAndroid Build Coastguard Worker     name = poolCopyString(&(newDtd->pool), oldA->name);
6984*6be67779SAndroid Build Coastguard Worker     if (! name)
6985*6be67779SAndroid Build Coastguard Worker       return 0;
6986*6be67779SAndroid Build Coastguard Worker     ++name;
6987*6be67779SAndroid Build Coastguard Worker     newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
6988*6be67779SAndroid Build Coastguard Worker                                   sizeof(ATTRIBUTE_ID));
6989*6be67779SAndroid Build Coastguard Worker     if (! newA)
6990*6be67779SAndroid Build Coastguard Worker       return 0;
6991*6be67779SAndroid Build Coastguard Worker     newA->maybeTokenized = oldA->maybeTokenized;
6992*6be67779SAndroid Build Coastguard Worker     if (oldA->prefix) {
6993*6be67779SAndroid Build Coastguard Worker       newA->xmlns = oldA->xmlns;
6994*6be67779SAndroid Build Coastguard Worker       if (oldA->prefix == &oldDtd->defaultPrefix)
6995*6be67779SAndroid Build Coastguard Worker         newA->prefix = &newDtd->defaultPrefix;
6996*6be67779SAndroid Build Coastguard Worker       else
6997*6be67779SAndroid Build Coastguard Worker         newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
6998*6be67779SAndroid Build Coastguard Worker                                         oldA->prefix->name, 0);
6999*6be67779SAndroid Build Coastguard Worker     }
7000*6be67779SAndroid Build Coastguard Worker   }
7001*6be67779SAndroid Build Coastguard Worker 
7002*6be67779SAndroid Build Coastguard Worker   /* Copy the element type table. */
7003*6be67779SAndroid Build Coastguard Worker 
7004*6be67779SAndroid Build Coastguard Worker   hashTableIterInit(&iter, &(oldDtd->elementTypes));
7005*6be67779SAndroid Build Coastguard Worker 
7006*6be67779SAndroid Build Coastguard Worker   for (;;) {
7007*6be67779SAndroid Build Coastguard Worker     int i;
7008*6be67779SAndroid Build Coastguard Worker     ELEMENT_TYPE *newE;
7009*6be67779SAndroid Build Coastguard Worker     const XML_Char *name;
7010*6be67779SAndroid Build Coastguard Worker     const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
7011*6be67779SAndroid Build Coastguard Worker     if (! oldE)
7012*6be67779SAndroid Build Coastguard Worker       break;
7013*6be67779SAndroid Build Coastguard Worker     name = poolCopyString(&(newDtd->pool), oldE->name);
7014*6be67779SAndroid Build Coastguard Worker     if (! name)
7015*6be67779SAndroid Build Coastguard Worker       return 0;
7016*6be67779SAndroid Build Coastguard Worker     newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
7017*6be67779SAndroid Build Coastguard Worker                                   sizeof(ELEMENT_TYPE));
7018*6be67779SAndroid Build Coastguard Worker     if (! newE)
7019*6be67779SAndroid Build Coastguard Worker       return 0;
7020*6be67779SAndroid Build Coastguard Worker     if (oldE->nDefaultAtts) {
7021*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent integer overflow.
7022*6be67779SAndroid Build Coastguard Worker        * The preprocessor guard addresses the "always false" warning
7023*6be67779SAndroid Build Coastguard Worker        * from -Wtype-limits on platforms where
7024*6be67779SAndroid Build Coastguard Worker        * sizeof(int) < sizeof(size_t), e.g. on x86_64. */
7025*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
7026*6be67779SAndroid Build Coastguard Worker       if ((size_t)oldE->nDefaultAtts
7027*6be67779SAndroid Build Coastguard Worker           > ((size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE))) {
7028*6be67779SAndroid Build Coastguard Worker         return 0;
7029*6be67779SAndroid Build Coastguard Worker       }
7030*6be67779SAndroid Build Coastguard Worker #endif
7031*6be67779SAndroid Build Coastguard Worker       newE->defaultAtts
7032*6be67779SAndroid Build Coastguard Worker           = ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
7033*6be67779SAndroid Build Coastguard Worker       if (! newE->defaultAtts) {
7034*6be67779SAndroid Build Coastguard Worker         return 0;
7035*6be67779SAndroid Build Coastguard Worker       }
7036*6be67779SAndroid Build Coastguard Worker     }
7037*6be67779SAndroid Build Coastguard Worker     if (oldE->idAtt)
7038*6be67779SAndroid Build Coastguard Worker       newE->idAtt = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds),
7039*6be67779SAndroid Build Coastguard Worker                                            oldE->idAtt->name, 0);
7040*6be67779SAndroid Build Coastguard Worker     newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
7041*6be67779SAndroid Build Coastguard Worker     if (oldE->prefix)
7042*6be67779SAndroid Build Coastguard Worker       newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
7043*6be67779SAndroid Build Coastguard Worker                                       oldE->prefix->name, 0);
7044*6be67779SAndroid Build Coastguard Worker     for (i = 0; i < newE->nDefaultAtts; i++) {
7045*6be67779SAndroid Build Coastguard Worker       newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(
7046*6be67779SAndroid Build Coastguard Worker           oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
7047*6be67779SAndroid Build Coastguard Worker       newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
7048*6be67779SAndroid Build Coastguard Worker       if (oldE->defaultAtts[i].value) {
7049*6be67779SAndroid Build Coastguard Worker         newE->defaultAtts[i].value
7050*6be67779SAndroid Build Coastguard Worker             = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
7051*6be67779SAndroid Build Coastguard Worker         if (! newE->defaultAtts[i].value)
7052*6be67779SAndroid Build Coastguard Worker           return 0;
7053*6be67779SAndroid Build Coastguard Worker       } else
7054*6be67779SAndroid Build Coastguard Worker         newE->defaultAtts[i].value = NULL;
7055*6be67779SAndroid Build Coastguard Worker     }
7056*6be67779SAndroid Build Coastguard Worker   }
7057*6be67779SAndroid Build Coastguard Worker 
7058*6be67779SAndroid Build Coastguard Worker   /* Copy the entity tables. */
7059*6be67779SAndroid Build Coastguard Worker   if (! copyEntityTable(oldParser, &(newDtd->generalEntities), &(newDtd->pool),
7060*6be67779SAndroid Build Coastguard Worker                         &(oldDtd->generalEntities)))
7061*6be67779SAndroid Build Coastguard Worker     return 0;
7062*6be67779SAndroid Build Coastguard Worker 
7063*6be67779SAndroid Build Coastguard Worker #ifdef XML_DTD
7064*6be67779SAndroid Build Coastguard Worker   if (! copyEntityTable(oldParser, &(newDtd->paramEntities), &(newDtd->pool),
7065*6be67779SAndroid Build Coastguard Worker                         &(oldDtd->paramEntities)))
7066*6be67779SAndroid Build Coastguard Worker     return 0;
7067*6be67779SAndroid Build Coastguard Worker   newDtd->paramEntityRead = oldDtd->paramEntityRead;
7068*6be67779SAndroid Build Coastguard Worker #endif /* XML_DTD */
7069*6be67779SAndroid Build Coastguard Worker 
7070*6be67779SAndroid Build Coastguard Worker   newDtd->keepProcessing = oldDtd->keepProcessing;
7071*6be67779SAndroid Build Coastguard Worker   newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
7072*6be67779SAndroid Build Coastguard Worker   newDtd->standalone = oldDtd->standalone;
7073*6be67779SAndroid Build Coastguard Worker 
7074*6be67779SAndroid Build Coastguard Worker   /* Don't want deep copying for scaffolding */
7075*6be67779SAndroid Build Coastguard Worker   newDtd->in_eldecl = oldDtd->in_eldecl;
7076*6be67779SAndroid Build Coastguard Worker   newDtd->scaffold = oldDtd->scaffold;
7077*6be67779SAndroid Build Coastguard Worker   newDtd->contentStringLen = oldDtd->contentStringLen;
7078*6be67779SAndroid Build Coastguard Worker   newDtd->scaffSize = oldDtd->scaffSize;
7079*6be67779SAndroid Build Coastguard Worker   newDtd->scaffLevel = oldDtd->scaffLevel;
7080*6be67779SAndroid Build Coastguard Worker   newDtd->scaffIndex = oldDtd->scaffIndex;
7081*6be67779SAndroid Build Coastguard Worker 
7082*6be67779SAndroid Build Coastguard Worker   return 1;
7083*6be67779SAndroid Build Coastguard Worker } /* End dtdCopy */
7084*6be67779SAndroid Build Coastguard Worker 
7085*6be67779SAndroid Build Coastguard Worker static int
copyEntityTable(XML_Parser oldParser,HASH_TABLE * newTable,STRING_POOL * newPool,const HASH_TABLE * oldTable)7086*6be67779SAndroid Build Coastguard Worker copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
7087*6be67779SAndroid Build Coastguard Worker                 STRING_POOL *newPool, const HASH_TABLE *oldTable) {
7088*6be67779SAndroid Build Coastguard Worker   HASH_TABLE_ITER iter;
7089*6be67779SAndroid Build Coastguard Worker   const XML_Char *cachedOldBase = NULL;
7090*6be67779SAndroid Build Coastguard Worker   const XML_Char *cachedNewBase = NULL;
7091*6be67779SAndroid Build Coastguard Worker 
7092*6be67779SAndroid Build Coastguard Worker   hashTableIterInit(&iter, oldTable);
7093*6be67779SAndroid Build Coastguard Worker 
7094*6be67779SAndroid Build Coastguard Worker   for (;;) {
7095*6be67779SAndroid Build Coastguard Worker     ENTITY *newE;
7096*6be67779SAndroid Build Coastguard Worker     const XML_Char *name;
7097*6be67779SAndroid Build Coastguard Worker     const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
7098*6be67779SAndroid Build Coastguard Worker     if (! oldE)
7099*6be67779SAndroid Build Coastguard Worker       break;
7100*6be67779SAndroid Build Coastguard Worker     name = poolCopyString(newPool, oldE->name);
7101*6be67779SAndroid Build Coastguard Worker     if (! name)
7102*6be67779SAndroid Build Coastguard Worker       return 0;
7103*6be67779SAndroid Build Coastguard Worker     newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
7104*6be67779SAndroid Build Coastguard Worker     if (! newE)
7105*6be67779SAndroid Build Coastguard Worker       return 0;
7106*6be67779SAndroid Build Coastguard Worker     if (oldE->systemId) {
7107*6be67779SAndroid Build Coastguard Worker       const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
7108*6be67779SAndroid Build Coastguard Worker       if (! tem)
7109*6be67779SAndroid Build Coastguard Worker         return 0;
7110*6be67779SAndroid Build Coastguard Worker       newE->systemId = tem;
7111*6be67779SAndroid Build Coastguard Worker       if (oldE->base) {
7112*6be67779SAndroid Build Coastguard Worker         if (oldE->base == cachedOldBase)
7113*6be67779SAndroid Build Coastguard Worker           newE->base = cachedNewBase;
7114*6be67779SAndroid Build Coastguard Worker         else {
7115*6be67779SAndroid Build Coastguard Worker           cachedOldBase = oldE->base;
7116*6be67779SAndroid Build Coastguard Worker           tem = poolCopyString(newPool, cachedOldBase);
7117*6be67779SAndroid Build Coastguard Worker           if (! tem)
7118*6be67779SAndroid Build Coastguard Worker             return 0;
7119*6be67779SAndroid Build Coastguard Worker           cachedNewBase = newE->base = tem;
7120*6be67779SAndroid Build Coastguard Worker         }
7121*6be67779SAndroid Build Coastguard Worker       }
7122*6be67779SAndroid Build Coastguard Worker       if (oldE->publicId) {
7123*6be67779SAndroid Build Coastguard Worker         tem = poolCopyString(newPool, oldE->publicId);
7124*6be67779SAndroid Build Coastguard Worker         if (! tem)
7125*6be67779SAndroid Build Coastguard Worker           return 0;
7126*6be67779SAndroid Build Coastguard Worker         newE->publicId = tem;
7127*6be67779SAndroid Build Coastguard Worker       }
7128*6be67779SAndroid Build Coastguard Worker     } else {
7129*6be67779SAndroid Build Coastguard Worker       const XML_Char *tem
7130*6be67779SAndroid Build Coastguard Worker           = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
7131*6be67779SAndroid Build Coastguard Worker       if (! tem)
7132*6be67779SAndroid Build Coastguard Worker         return 0;
7133*6be67779SAndroid Build Coastguard Worker       newE->textPtr = tem;
7134*6be67779SAndroid Build Coastguard Worker       newE->textLen = oldE->textLen;
7135*6be67779SAndroid Build Coastguard Worker     }
7136*6be67779SAndroid Build Coastguard Worker     if (oldE->notation) {
7137*6be67779SAndroid Build Coastguard Worker       const XML_Char *tem = poolCopyString(newPool, oldE->notation);
7138*6be67779SAndroid Build Coastguard Worker       if (! tem)
7139*6be67779SAndroid Build Coastguard Worker         return 0;
7140*6be67779SAndroid Build Coastguard Worker       newE->notation = tem;
7141*6be67779SAndroid Build Coastguard Worker     }
7142*6be67779SAndroid Build Coastguard Worker     newE->is_param = oldE->is_param;
7143*6be67779SAndroid Build Coastguard Worker     newE->is_internal = oldE->is_internal;
7144*6be67779SAndroid Build Coastguard Worker   }
7145*6be67779SAndroid Build Coastguard Worker   return 1;
7146*6be67779SAndroid Build Coastguard Worker }
7147*6be67779SAndroid Build Coastguard Worker 
7148*6be67779SAndroid Build Coastguard Worker #define INIT_POWER 6
7149*6be67779SAndroid Build Coastguard Worker 
7150*6be67779SAndroid Build Coastguard Worker static XML_Bool FASTCALL
keyeq(KEY s1,KEY s2)7151*6be67779SAndroid Build Coastguard Worker keyeq(KEY s1, KEY s2) {
7152*6be67779SAndroid Build Coastguard Worker   for (; *s1 == *s2; s1++, s2++)
7153*6be67779SAndroid Build Coastguard Worker     if (*s1 == 0)
7154*6be67779SAndroid Build Coastguard Worker       return XML_TRUE;
7155*6be67779SAndroid Build Coastguard Worker   return XML_FALSE;
7156*6be67779SAndroid Build Coastguard Worker }
7157*6be67779SAndroid Build Coastguard Worker 
7158*6be67779SAndroid Build Coastguard Worker static size_t
keylen(KEY s)7159*6be67779SAndroid Build Coastguard Worker keylen(KEY s) {
7160*6be67779SAndroid Build Coastguard Worker   size_t len = 0;
7161*6be67779SAndroid Build Coastguard Worker   for (; *s; s++, len++)
7162*6be67779SAndroid Build Coastguard Worker     ;
7163*6be67779SAndroid Build Coastguard Worker   return len;
7164*6be67779SAndroid Build Coastguard Worker }
7165*6be67779SAndroid Build Coastguard Worker 
7166*6be67779SAndroid Build Coastguard Worker static void
copy_salt_to_sipkey(XML_Parser parser,struct sipkey * key)7167*6be67779SAndroid Build Coastguard Worker copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
7168*6be67779SAndroid Build Coastguard Worker   key->k[0] = 0;
7169*6be67779SAndroid Build Coastguard Worker   key->k[1] = get_hash_secret_salt(parser);
7170*6be67779SAndroid Build Coastguard Worker }
7171*6be67779SAndroid Build Coastguard Worker 
7172*6be67779SAndroid Build Coastguard Worker static unsigned long FASTCALL
hash(XML_Parser parser,KEY s)7173*6be67779SAndroid Build Coastguard Worker hash(XML_Parser parser, KEY s) {
7174*6be67779SAndroid Build Coastguard Worker   struct siphash state;
7175*6be67779SAndroid Build Coastguard Worker   struct sipkey key;
7176*6be67779SAndroid Build Coastguard Worker   (void)sip24_valid;
7177*6be67779SAndroid Build Coastguard Worker   copy_salt_to_sipkey(parser, &key);
7178*6be67779SAndroid Build Coastguard Worker   sip24_init(&state, &key);
7179*6be67779SAndroid Build Coastguard Worker   sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
7180*6be67779SAndroid Build Coastguard Worker   return (unsigned long)sip24_final(&state);
7181*6be67779SAndroid Build Coastguard Worker }
7182*6be67779SAndroid Build Coastguard Worker 
7183*6be67779SAndroid Build Coastguard Worker static NAMED *
lookup(XML_Parser parser,HASH_TABLE * table,KEY name,size_t createSize)7184*6be67779SAndroid Build Coastguard Worker lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
7185*6be67779SAndroid Build Coastguard Worker   size_t i;
7186*6be67779SAndroid Build Coastguard Worker   if (table->size == 0) {
7187*6be67779SAndroid Build Coastguard Worker     size_t tsize;
7188*6be67779SAndroid Build Coastguard Worker     if (! createSize)
7189*6be67779SAndroid Build Coastguard Worker       return NULL;
7190*6be67779SAndroid Build Coastguard Worker     table->power = INIT_POWER;
7191*6be67779SAndroid Build Coastguard Worker     /* table->size is a power of 2 */
7192*6be67779SAndroid Build Coastguard Worker     table->size = (size_t)1 << INIT_POWER;
7193*6be67779SAndroid Build Coastguard Worker     tsize = table->size * sizeof(NAMED *);
7194*6be67779SAndroid Build Coastguard Worker     table->v = table->mem->malloc_fcn(tsize);
7195*6be67779SAndroid Build Coastguard Worker     if (! table->v) {
7196*6be67779SAndroid Build Coastguard Worker       table->size = 0;
7197*6be67779SAndroid Build Coastguard Worker       return NULL;
7198*6be67779SAndroid Build Coastguard Worker     }
7199*6be67779SAndroid Build Coastguard Worker     memset(table->v, 0, tsize);
7200*6be67779SAndroid Build Coastguard Worker     i = hash(parser, name) & ((unsigned long)table->size - 1);
7201*6be67779SAndroid Build Coastguard Worker   } else {
7202*6be67779SAndroid Build Coastguard Worker     unsigned long h = hash(parser, name);
7203*6be67779SAndroid Build Coastguard Worker     unsigned long mask = (unsigned long)table->size - 1;
7204*6be67779SAndroid Build Coastguard Worker     unsigned char step = 0;
7205*6be67779SAndroid Build Coastguard Worker     i = h & mask;
7206*6be67779SAndroid Build Coastguard Worker     while (table->v[i]) {
7207*6be67779SAndroid Build Coastguard Worker       if (keyeq(name, table->v[i]->name))
7208*6be67779SAndroid Build Coastguard Worker         return table->v[i];
7209*6be67779SAndroid Build Coastguard Worker       if (! step)
7210*6be67779SAndroid Build Coastguard Worker         step = PROBE_STEP(h, mask, table->power);
7211*6be67779SAndroid Build Coastguard Worker       i < step ? (i += table->size - step) : (i -= step);
7212*6be67779SAndroid Build Coastguard Worker     }
7213*6be67779SAndroid Build Coastguard Worker     if (! createSize)
7214*6be67779SAndroid Build Coastguard Worker       return NULL;
7215*6be67779SAndroid Build Coastguard Worker 
7216*6be67779SAndroid Build Coastguard Worker     /* check for overflow (table is half full) */
7217*6be67779SAndroid Build Coastguard Worker     if (table->used >> (table->power - 1)) {
7218*6be67779SAndroid Build Coastguard Worker       unsigned char newPower = table->power + 1;
7219*6be67779SAndroid Build Coastguard Worker 
7220*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent invalid shift */
7221*6be67779SAndroid Build Coastguard Worker       if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
7222*6be67779SAndroid Build Coastguard Worker         return NULL;
7223*6be67779SAndroid Build Coastguard Worker       }
7224*6be67779SAndroid Build Coastguard Worker 
7225*6be67779SAndroid Build Coastguard Worker       size_t newSize = (size_t)1 << newPower;
7226*6be67779SAndroid Build Coastguard Worker       unsigned long newMask = (unsigned long)newSize - 1;
7227*6be67779SAndroid Build Coastguard Worker 
7228*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent integer overflow */
7229*6be67779SAndroid Build Coastguard Worker       if (newSize > (size_t)(-1) / sizeof(NAMED *)) {
7230*6be67779SAndroid Build Coastguard Worker         return NULL;
7231*6be67779SAndroid Build Coastguard Worker       }
7232*6be67779SAndroid Build Coastguard Worker 
7233*6be67779SAndroid Build Coastguard Worker       size_t tsize = newSize * sizeof(NAMED *);
7234*6be67779SAndroid Build Coastguard Worker       NAMED **newV = table->mem->malloc_fcn(tsize);
7235*6be67779SAndroid Build Coastguard Worker       if (! newV)
7236*6be67779SAndroid Build Coastguard Worker         return NULL;
7237*6be67779SAndroid Build Coastguard Worker       memset(newV, 0, tsize);
7238*6be67779SAndroid Build Coastguard Worker       for (i = 0; i < table->size; i++)
7239*6be67779SAndroid Build Coastguard Worker         if (table->v[i]) {
7240*6be67779SAndroid Build Coastguard Worker           unsigned long newHash = hash(parser, table->v[i]->name);
7241*6be67779SAndroid Build Coastguard Worker           size_t j = newHash & newMask;
7242*6be67779SAndroid Build Coastguard Worker           step = 0;
7243*6be67779SAndroid Build Coastguard Worker           while (newV[j]) {
7244*6be67779SAndroid Build Coastguard Worker             if (! step)
7245*6be67779SAndroid Build Coastguard Worker               step = PROBE_STEP(newHash, newMask, newPower);
7246*6be67779SAndroid Build Coastguard Worker             j < step ? (j += newSize - step) : (j -= step);
7247*6be67779SAndroid Build Coastguard Worker           }
7248*6be67779SAndroid Build Coastguard Worker           newV[j] = table->v[i];
7249*6be67779SAndroid Build Coastguard Worker         }
7250*6be67779SAndroid Build Coastguard Worker       table->mem->free_fcn(table->v);
7251*6be67779SAndroid Build Coastguard Worker       table->v = newV;
7252*6be67779SAndroid Build Coastguard Worker       table->power = newPower;
7253*6be67779SAndroid Build Coastguard Worker       table->size = newSize;
7254*6be67779SAndroid Build Coastguard Worker       i = h & newMask;
7255*6be67779SAndroid Build Coastguard Worker       step = 0;
7256*6be67779SAndroid Build Coastguard Worker       while (table->v[i]) {
7257*6be67779SAndroid Build Coastguard Worker         if (! step)
7258*6be67779SAndroid Build Coastguard Worker           step = PROBE_STEP(h, newMask, newPower);
7259*6be67779SAndroid Build Coastguard Worker         i < step ? (i += newSize - step) : (i -= step);
7260*6be67779SAndroid Build Coastguard Worker       }
7261*6be67779SAndroid Build Coastguard Worker     }
7262*6be67779SAndroid Build Coastguard Worker   }
7263*6be67779SAndroid Build Coastguard Worker   table->v[i] = table->mem->malloc_fcn(createSize);
7264*6be67779SAndroid Build Coastguard Worker   if (! table->v[i])
7265*6be67779SAndroid Build Coastguard Worker     return NULL;
7266*6be67779SAndroid Build Coastguard Worker   memset(table->v[i], 0, createSize);
7267*6be67779SAndroid Build Coastguard Worker   table->v[i]->name = name;
7268*6be67779SAndroid Build Coastguard Worker   (table->used)++;
7269*6be67779SAndroid Build Coastguard Worker   return table->v[i];
7270*6be67779SAndroid Build Coastguard Worker }
7271*6be67779SAndroid Build Coastguard Worker 
7272*6be67779SAndroid Build Coastguard Worker static void FASTCALL
hashTableClear(HASH_TABLE * table)7273*6be67779SAndroid Build Coastguard Worker hashTableClear(HASH_TABLE *table) {
7274*6be67779SAndroid Build Coastguard Worker   size_t i;
7275*6be67779SAndroid Build Coastguard Worker   for (i = 0; i < table->size; i++) {
7276*6be67779SAndroid Build Coastguard Worker     table->mem->free_fcn(table->v[i]);
7277*6be67779SAndroid Build Coastguard Worker     table->v[i] = NULL;
7278*6be67779SAndroid Build Coastguard Worker   }
7279*6be67779SAndroid Build Coastguard Worker   table->used = 0;
7280*6be67779SAndroid Build Coastguard Worker }
7281*6be67779SAndroid Build Coastguard Worker 
7282*6be67779SAndroid Build Coastguard Worker static void FASTCALL
hashTableDestroy(HASH_TABLE * table)7283*6be67779SAndroid Build Coastguard Worker hashTableDestroy(HASH_TABLE *table) {
7284*6be67779SAndroid Build Coastguard Worker   size_t i;
7285*6be67779SAndroid Build Coastguard Worker   for (i = 0; i < table->size; i++)
7286*6be67779SAndroid Build Coastguard Worker     table->mem->free_fcn(table->v[i]);
7287*6be67779SAndroid Build Coastguard Worker   table->mem->free_fcn(table->v);
7288*6be67779SAndroid Build Coastguard Worker }
7289*6be67779SAndroid Build Coastguard Worker 
7290*6be67779SAndroid Build Coastguard Worker static void FASTCALL
hashTableInit(HASH_TABLE * p,const XML_Memory_Handling_Suite * ms)7291*6be67779SAndroid Build Coastguard Worker hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) {
7292*6be67779SAndroid Build Coastguard Worker   p->power = 0;
7293*6be67779SAndroid Build Coastguard Worker   p->size = 0;
7294*6be67779SAndroid Build Coastguard Worker   p->used = 0;
7295*6be67779SAndroid Build Coastguard Worker   p->v = NULL;
7296*6be67779SAndroid Build Coastguard Worker   p->mem = ms;
7297*6be67779SAndroid Build Coastguard Worker }
7298*6be67779SAndroid Build Coastguard Worker 
7299*6be67779SAndroid Build Coastguard Worker static void FASTCALL
hashTableIterInit(HASH_TABLE_ITER * iter,const HASH_TABLE * table)7300*6be67779SAndroid Build Coastguard Worker hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
7301*6be67779SAndroid Build Coastguard Worker   iter->p = table->v;
7302*6be67779SAndroid Build Coastguard Worker   iter->end = iter->p ? iter->p + table->size : NULL;
7303*6be67779SAndroid Build Coastguard Worker }
7304*6be67779SAndroid Build Coastguard Worker 
7305*6be67779SAndroid Build Coastguard Worker static NAMED *FASTCALL
hashTableIterNext(HASH_TABLE_ITER * iter)7306*6be67779SAndroid Build Coastguard Worker hashTableIterNext(HASH_TABLE_ITER *iter) {
7307*6be67779SAndroid Build Coastguard Worker   while (iter->p != iter->end) {
7308*6be67779SAndroid Build Coastguard Worker     NAMED *tem = *(iter->p)++;
7309*6be67779SAndroid Build Coastguard Worker     if (tem)
7310*6be67779SAndroid Build Coastguard Worker       return tem;
7311*6be67779SAndroid Build Coastguard Worker   }
7312*6be67779SAndroid Build Coastguard Worker   return NULL;
7313*6be67779SAndroid Build Coastguard Worker }
7314*6be67779SAndroid Build Coastguard Worker 
7315*6be67779SAndroid Build Coastguard Worker static void FASTCALL
poolInit(STRING_POOL * pool,const XML_Memory_Handling_Suite * ms)7316*6be67779SAndroid Build Coastguard Worker poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) {
7317*6be67779SAndroid Build Coastguard Worker   pool->blocks = NULL;
7318*6be67779SAndroid Build Coastguard Worker   pool->freeBlocks = NULL;
7319*6be67779SAndroid Build Coastguard Worker   pool->start = NULL;
7320*6be67779SAndroid Build Coastguard Worker   pool->ptr = NULL;
7321*6be67779SAndroid Build Coastguard Worker   pool->end = NULL;
7322*6be67779SAndroid Build Coastguard Worker   pool->mem = ms;
7323*6be67779SAndroid Build Coastguard Worker }
7324*6be67779SAndroid Build Coastguard Worker 
7325*6be67779SAndroid Build Coastguard Worker static void FASTCALL
poolClear(STRING_POOL * pool)7326*6be67779SAndroid Build Coastguard Worker poolClear(STRING_POOL *pool) {
7327*6be67779SAndroid Build Coastguard Worker   if (! pool->freeBlocks)
7328*6be67779SAndroid Build Coastguard Worker     pool->freeBlocks = pool->blocks;
7329*6be67779SAndroid Build Coastguard Worker   else {
7330*6be67779SAndroid Build Coastguard Worker     BLOCK *p = pool->blocks;
7331*6be67779SAndroid Build Coastguard Worker     while (p) {
7332*6be67779SAndroid Build Coastguard Worker       BLOCK *tem = p->next;
7333*6be67779SAndroid Build Coastguard Worker       p->next = pool->freeBlocks;
7334*6be67779SAndroid Build Coastguard Worker       pool->freeBlocks = p;
7335*6be67779SAndroid Build Coastguard Worker       p = tem;
7336*6be67779SAndroid Build Coastguard Worker     }
7337*6be67779SAndroid Build Coastguard Worker   }
7338*6be67779SAndroid Build Coastguard Worker   pool->blocks = NULL;
7339*6be67779SAndroid Build Coastguard Worker   pool->start = NULL;
7340*6be67779SAndroid Build Coastguard Worker   pool->ptr = NULL;
7341*6be67779SAndroid Build Coastguard Worker   pool->end = NULL;
7342*6be67779SAndroid Build Coastguard Worker }
7343*6be67779SAndroid Build Coastguard Worker 
7344*6be67779SAndroid Build Coastguard Worker static void FASTCALL
poolDestroy(STRING_POOL * pool)7345*6be67779SAndroid Build Coastguard Worker poolDestroy(STRING_POOL *pool) {
7346*6be67779SAndroid Build Coastguard Worker   BLOCK *p = pool->blocks;
7347*6be67779SAndroid Build Coastguard Worker   while (p) {
7348*6be67779SAndroid Build Coastguard Worker     BLOCK *tem = p->next;
7349*6be67779SAndroid Build Coastguard Worker     pool->mem->free_fcn(p);
7350*6be67779SAndroid Build Coastguard Worker     p = tem;
7351*6be67779SAndroid Build Coastguard Worker   }
7352*6be67779SAndroid Build Coastguard Worker   p = pool->freeBlocks;
7353*6be67779SAndroid Build Coastguard Worker   while (p) {
7354*6be67779SAndroid Build Coastguard Worker     BLOCK *tem = p->next;
7355*6be67779SAndroid Build Coastguard Worker     pool->mem->free_fcn(p);
7356*6be67779SAndroid Build Coastguard Worker     p = tem;
7357*6be67779SAndroid Build Coastguard Worker   }
7358*6be67779SAndroid Build Coastguard Worker }
7359*6be67779SAndroid Build Coastguard Worker 
7360*6be67779SAndroid Build Coastguard Worker static XML_Char *
poolAppend(STRING_POOL * pool,const ENCODING * enc,const char * ptr,const char * end)7361*6be67779SAndroid Build Coastguard Worker poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
7362*6be67779SAndroid Build Coastguard Worker            const char *end) {
7363*6be67779SAndroid Build Coastguard Worker   if (! pool->ptr && ! poolGrow(pool))
7364*6be67779SAndroid Build Coastguard Worker     return NULL;
7365*6be67779SAndroid Build Coastguard Worker   for (;;) {
7366*6be67779SAndroid Build Coastguard Worker     const enum XML_Convert_Result convert_res = XmlConvert(
7367*6be67779SAndroid Build Coastguard Worker         enc, &ptr, end, (ICHAR **)&(pool->ptr), (const ICHAR *)pool->end);
7368*6be67779SAndroid Build Coastguard Worker     if ((convert_res == XML_CONVERT_COMPLETED)
7369*6be67779SAndroid Build Coastguard Worker         || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
7370*6be67779SAndroid Build Coastguard Worker       break;
7371*6be67779SAndroid Build Coastguard Worker     if (! poolGrow(pool))
7372*6be67779SAndroid Build Coastguard Worker       return NULL;
7373*6be67779SAndroid Build Coastguard Worker   }
7374*6be67779SAndroid Build Coastguard Worker   return pool->start;
7375*6be67779SAndroid Build Coastguard Worker }
7376*6be67779SAndroid Build Coastguard Worker 
7377*6be67779SAndroid Build Coastguard Worker static const XML_Char *FASTCALL
poolCopyString(STRING_POOL * pool,const XML_Char * s)7378*6be67779SAndroid Build Coastguard Worker poolCopyString(STRING_POOL *pool, const XML_Char *s) {
7379*6be67779SAndroid Build Coastguard Worker   do {
7380*6be67779SAndroid Build Coastguard Worker     if (! poolAppendChar(pool, *s))
7381*6be67779SAndroid Build Coastguard Worker       return NULL;
7382*6be67779SAndroid Build Coastguard Worker   } while (*s++);
7383*6be67779SAndroid Build Coastguard Worker   s = pool->start;
7384*6be67779SAndroid Build Coastguard Worker   poolFinish(pool);
7385*6be67779SAndroid Build Coastguard Worker   return s;
7386*6be67779SAndroid Build Coastguard Worker }
7387*6be67779SAndroid Build Coastguard Worker 
7388*6be67779SAndroid Build Coastguard Worker static const XML_Char *
poolCopyStringN(STRING_POOL * pool,const XML_Char * s,int n)7389*6be67779SAndroid Build Coastguard Worker poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) {
7390*6be67779SAndroid Build Coastguard Worker   if (! pool->ptr && ! poolGrow(pool)) {
7391*6be67779SAndroid Build Coastguard Worker     /* The following line is unreachable given the current usage of
7392*6be67779SAndroid Build Coastguard Worker      * poolCopyStringN().  Currently it is called from exactly one
7393*6be67779SAndroid Build Coastguard Worker      * place to copy the text of a simple general entity.  By that
7394*6be67779SAndroid Build Coastguard Worker      * point, the name of the entity is already stored in the pool, so
7395*6be67779SAndroid Build Coastguard Worker      * pool->ptr cannot be NULL.
7396*6be67779SAndroid Build Coastguard Worker      *
7397*6be67779SAndroid Build Coastguard Worker      * If poolCopyStringN() is used elsewhere as it well might be,
7398*6be67779SAndroid Build Coastguard Worker      * this line may well become executable again.  Regardless, this
7399*6be67779SAndroid Build Coastguard Worker      * sort of check shouldn't be removed lightly, so we just exclude
7400*6be67779SAndroid Build Coastguard Worker      * it from the coverage statistics.
7401*6be67779SAndroid Build Coastguard Worker      */
7402*6be67779SAndroid Build Coastguard Worker     return NULL; /* LCOV_EXCL_LINE */
7403*6be67779SAndroid Build Coastguard Worker   }
7404*6be67779SAndroid Build Coastguard Worker   for (; n > 0; --n, s++) {
7405*6be67779SAndroid Build Coastguard Worker     if (! poolAppendChar(pool, *s))
7406*6be67779SAndroid Build Coastguard Worker       return NULL;
7407*6be67779SAndroid Build Coastguard Worker   }
7408*6be67779SAndroid Build Coastguard Worker   s = pool->start;
7409*6be67779SAndroid Build Coastguard Worker   poolFinish(pool);
7410*6be67779SAndroid Build Coastguard Worker   return s;
7411*6be67779SAndroid Build Coastguard Worker }
7412*6be67779SAndroid Build Coastguard Worker 
7413*6be67779SAndroid Build Coastguard Worker static const XML_Char *FASTCALL
poolAppendString(STRING_POOL * pool,const XML_Char * s)7414*6be67779SAndroid Build Coastguard Worker poolAppendString(STRING_POOL *pool, const XML_Char *s) {
7415*6be67779SAndroid Build Coastguard Worker   while (*s) {
7416*6be67779SAndroid Build Coastguard Worker     if (! poolAppendChar(pool, *s))
7417*6be67779SAndroid Build Coastguard Worker       return NULL;
7418*6be67779SAndroid Build Coastguard Worker     s++;
7419*6be67779SAndroid Build Coastguard Worker   }
7420*6be67779SAndroid Build Coastguard Worker   return pool->start;
7421*6be67779SAndroid Build Coastguard Worker }
7422*6be67779SAndroid Build Coastguard Worker 
7423*6be67779SAndroid Build Coastguard Worker static XML_Char *
poolStoreString(STRING_POOL * pool,const ENCODING * enc,const char * ptr,const char * end)7424*6be67779SAndroid Build Coastguard Worker poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
7425*6be67779SAndroid Build Coastguard Worker                 const char *end) {
7426*6be67779SAndroid Build Coastguard Worker   if (! poolAppend(pool, enc, ptr, end))
7427*6be67779SAndroid Build Coastguard Worker     return NULL;
7428*6be67779SAndroid Build Coastguard Worker   if (pool->ptr == pool->end && ! poolGrow(pool))
7429*6be67779SAndroid Build Coastguard Worker     return NULL;
7430*6be67779SAndroid Build Coastguard Worker   *(pool->ptr)++ = 0;
7431*6be67779SAndroid Build Coastguard Worker   return pool->start;
7432*6be67779SAndroid Build Coastguard Worker }
7433*6be67779SAndroid Build Coastguard Worker 
7434*6be67779SAndroid Build Coastguard Worker static size_t
poolBytesToAllocateFor(int blockSize)7435*6be67779SAndroid Build Coastguard Worker poolBytesToAllocateFor(int blockSize) {
7436*6be67779SAndroid Build Coastguard Worker   /* Unprotected math would be:
7437*6be67779SAndroid Build Coastguard Worker   ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
7438*6be67779SAndroid Build Coastguard Worker   **
7439*6be67779SAndroid Build Coastguard Worker   ** Detect overflow, avoiding _signed_ overflow undefined behavior
7440*6be67779SAndroid Build Coastguard Worker   ** For a + b * c we check b * c in isolation first, so that addition of a
7441*6be67779SAndroid Build Coastguard Worker   ** on top has no chance of making us accept a small non-negative number
7442*6be67779SAndroid Build Coastguard Worker   */
7443*6be67779SAndroid Build Coastguard Worker   const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
7444*6be67779SAndroid Build Coastguard Worker 
7445*6be67779SAndroid Build Coastguard Worker   if (blockSize <= 0)
7446*6be67779SAndroid Build Coastguard Worker     return 0;
7447*6be67779SAndroid Build Coastguard Worker 
7448*6be67779SAndroid Build Coastguard Worker   if (blockSize > (int)(INT_MAX / stretch))
7449*6be67779SAndroid Build Coastguard Worker     return 0;
7450*6be67779SAndroid Build Coastguard Worker 
7451*6be67779SAndroid Build Coastguard Worker   {
7452*6be67779SAndroid Build Coastguard Worker     const int stretchedBlockSize = blockSize * (int)stretch;
7453*6be67779SAndroid Build Coastguard Worker     const int bytesToAllocate
7454*6be67779SAndroid Build Coastguard Worker         = (int)(offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
7455*6be67779SAndroid Build Coastguard Worker     if (bytesToAllocate < 0)
7456*6be67779SAndroid Build Coastguard Worker       return 0;
7457*6be67779SAndroid Build Coastguard Worker 
7458*6be67779SAndroid Build Coastguard Worker     return (size_t)bytesToAllocate;
7459*6be67779SAndroid Build Coastguard Worker   }
7460*6be67779SAndroid Build Coastguard Worker }
7461*6be67779SAndroid Build Coastguard Worker 
7462*6be67779SAndroid Build Coastguard Worker static XML_Bool FASTCALL
poolGrow(STRING_POOL * pool)7463*6be67779SAndroid Build Coastguard Worker poolGrow(STRING_POOL *pool) {
7464*6be67779SAndroid Build Coastguard Worker   if (pool->freeBlocks) {
7465*6be67779SAndroid Build Coastguard Worker     if (pool->start == 0) {
7466*6be67779SAndroid Build Coastguard Worker       pool->blocks = pool->freeBlocks;
7467*6be67779SAndroid Build Coastguard Worker       pool->freeBlocks = pool->freeBlocks->next;
7468*6be67779SAndroid Build Coastguard Worker       pool->blocks->next = NULL;
7469*6be67779SAndroid Build Coastguard Worker       pool->start = pool->blocks->s;
7470*6be67779SAndroid Build Coastguard Worker       pool->end = pool->start + pool->blocks->size;
7471*6be67779SAndroid Build Coastguard Worker       pool->ptr = pool->start;
7472*6be67779SAndroid Build Coastguard Worker       return XML_TRUE;
7473*6be67779SAndroid Build Coastguard Worker     }
7474*6be67779SAndroid Build Coastguard Worker     if (pool->end - pool->start < pool->freeBlocks->size) {
7475*6be67779SAndroid Build Coastguard Worker       BLOCK *tem = pool->freeBlocks->next;
7476*6be67779SAndroid Build Coastguard Worker       pool->freeBlocks->next = pool->blocks;
7477*6be67779SAndroid Build Coastguard Worker       pool->blocks = pool->freeBlocks;
7478*6be67779SAndroid Build Coastguard Worker       pool->freeBlocks = tem;
7479*6be67779SAndroid Build Coastguard Worker       memcpy(pool->blocks->s, pool->start,
7480*6be67779SAndroid Build Coastguard Worker              (pool->end - pool->start) * sizeof(XML_Char));
7481*6be67779SAndroid Build Coastguard Worker       pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
7482*6be67779SAndroid Build Coastguard Worker       pool->start = pool->blocks->s;
7483*6be67779SAndroid Build Coastguard Worker       pool->end = pool->start + pool->blocks->size;
7484*6be67779SAndroid Build Coastguard Worker       return XML_TRUE;
7485*6be67779SAndroid Build Coastguard Worker     }
7486*6be67779SAndroid Build Coastguard Worker   }
7487*6be67779SAndroid Build Coastguard Worker   if (pool->blocks && pool->start == pool->blocks->s) {
7488*6be67779SAndroid Build Coastguard Worker     BLOCK *temp;
7489*6be67779SAndroid Build Coastguard Worker     int blockSize = (int)((unsigned)(pool->end - pool->start) * 2U);
7490*6be67779SAndroid Build Coastguard Worker     size_t bytesToAllocate;
7491*6be67779SAndroid Build Coastguard Worker 
7492*6be67779SAndroid Build Coastguard Worker     /* NOTE: Needs to be calculated prior to calling `realloc`
7493*6be67779SAndroid Build Coastguard Worker              to avoid dangling pointers: */
7494*6be67779SAndroid Build Coastguard Worker     const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
7495*6be67779SAndroid Build Coastguard Worker 
7496*6be67779SAndroid Build Coastguard Worker     if (blockSize < 0) {
7497*6be67779SAndroid Build Coastguard Worker       /* This condition traps a situation where either more than
7498*6be67779SAndroid Build Coastguard Worker        * INT_MAX/2 bytes have already been allocated.  This isn't
7499*6be67779SAndroid Build Coastguard Worker        * readily testable, since it is unlikely that an average
7500*6be67779SAndroid Build Coastguard Worker        * machine will have that much memory, so we exclude it from the
7501*6be67779SAndroid Build Coastguard Worker        * coverage statistics.
7502*6be67779SAndroid Build Coastguard Worker        */
7503*6be67779SAndroid Build Coastguard Worker       return XML_FALSE; /* LCOV_EXCL_LINE */
7504*6be67779SAndroid Build Coastguard Worker     }
7505*6be67779SAndroid Build Coastguard Worker 
7506*6be67779SAndroid Build Coastguard Worker     bytesToAllocate = poolBytesToAllocateFor(blockSize);
7507*6be67779SAndroid Build Coastguard Worker     if (bytesToAllocate == 0)
7508*6be67779SAndroid Build Coastguard Worker       return XML_FALSE;
7509*6be67779SAndroid Build Coastguard Worker 
7510*6be67779SAndroid Build Coastguard Worker     temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks,
7511*6be67779SAndroid Build Coastguard Worker                                            (unsigned)bytesToAllocate);
7512*6be67779SAndroid Build Coastguard Worker     if (temp == NULL)
7513*6be67779SAndroid Build Coastguard Worker       return XML_FALSE;
7514*6be67779SAndroid Build Coastguard Worker     pool->blocks = temp;
7515*6be67779SAndroid Build Coastguard Worker     pool->blocks->size = blockSize;
7516*6be67779SAndroid Build Coastguard Worker     pool->ptr = pool->blocks->s + offsetInsideBlock;
7517*6be67779SAndroid Build Coastguard Worker     pool->start = pool->blocks->s;
7518*6be67779SAndroid Build Coastguard Worker     pool->end = pool->start + blockSize;
7519*6be67779SAndroid Build Coastguard Worker   } else {
7520*6be67779SAndroid Build Coastguard Worker     BLOCK *tem;
7521*6be67779SAndroid Build Coastguard Worker     int blockSize = (int)(pool->end - pool->start);
7522*6be67779SAndroid Build Coastguard Worker     size_t bytesToAllocate;
7523*6be67779SAndroid Build Coastguard Worker 
7524*6be67779SAndroid Build Coastguard Worker     if (blockSize < 0) {
7525*6be67779SAndroid Build Coastguard Worker       /* This condition traps a situation where either more than
7526*6be67779SAndroid Build Coastguard Worker        * INT_MAX bytes have already been allocated (which is prevented
7527*6be67779SAndroid Build Coastguard Worker        * by various pieces of program logic, not least this one, never
7528*6be67779SAndroid Build Coastguard Worker        * mind the unlikelihood of actually having that much memory) or
7529*6be67779SAndroid Build Coastguard Worker        * the pool control fields have been corrupted (which could
7530*6be67779SAndroid Build Coastguard Worker        * conceivably happen in an extremely buggy user handler
7531*6be67779SAndroid Build Coastguard Worker        * function).  Either way it isn't readily testable, so we
7532*6be67779SAndroid Build Coastguard Worker        * exclude it from the coverage statistics.
7533*6be67779SAndroid Build Coastguard Worker        */
7534*6be67779SAndroid Build Coastguard Worker       return XML_FALSE; /* LCOV_EXCL_LINE */
7535*6be67779SAndroid Build Coastguard Worker     }
7536*6be67779SAndroid Build Coastguard Worker 
7537*6be67779SAndroid Build Coastguard Worker     if (blockSize < INIT_BLOCK_SIZE)
7538*6be67779SAndroid Build Coastguard Worker       blockSize = INIT_BLOCK_SIZE;
7539*6be67779SAndroid Build Coastguard Worker     else {
7540*6be67779SAndroid Build Coastguard Worker       /* Detect overflow, avoiding _signed_ overflow undefined behavior */
7541*6be67779SAndroid Build Coastguard Worker       if ((int)((unsigned)blockSize * 2U) < 0) {
7542*6be67779SAndroid Build Coastguard Worker         return XML_FALSE;
7543*6be67779SAndroid Build Coastguard Worker       }
7544*6be67779SAndroid Build Coastguard Worker       blockSize *= 2;
7545*6be67779SAndroid Build Coastguard Worker     }
7546*6be67779SAndroid Build Coastguard Worker 
7547*6be67779SAndroid Build Coastguard Worker     bytesToAllocate = poolBytesToAllocateFor(blockSize);
7548*6be67779SAndroid Build Coastguard Worker     if (bytesToAllocate == 0)
7549*6be67779SAndroid Build Coastguard Worker       return XML_FALSE;
7550*6be67779SAndroid Build Coastguard Worker 
7551*6be67779SAndroid Build Coastguard Worker     tem = pool->mem->malloc_fcn(bytesToAllocate);
7552*6be67779SAndroid Build Coastguard Worker     if (! tem)
7553*6be67779SAndroid Build Coastguard Worker       return XML_FALSE;
7554*6be67779SAndroid Build Coastguard Worker     tem->size = blockSize;
7555*6be67779SAndroid Build Coastguard Worker     tem->next = pool->blocks;
7556*6be67779SAndroid Build Coastguard Worker     pool->blocks = tem;
7557*6be67779SAndroid Build Coastguard Worker     if (pool->ptr != pool->start)
7558*6be67779SAndroid Build Coastguard Worker       memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
7559*6be67779SAndroid Build Coastguard Worker     pool->ptr = tem->s + (pool->ptr - pool->start);
7560*6be67779SAndroid Build Coastguard Worker     pool->start = tem->s;
7561*6be67779SAndroid Build Coastguard Worker     pool->end = tem->s + blockSize;
7562*6be67779SAndroid Build Coastguard Worker   }
7563*6be67779SAndroid Build Coastguard Worker   return XML_TRUE;
7564*6be67779SAndroid Build Coastguard Worker }
7565*6be67779SAndroid Build Coastguard Worker 
7566*6be67779SAndroid Build Coastguard Worker static int FASTCALL
nextScaffoldPart(XML_Parser parser)7567*6be67779SAndroid Build Coastguard Worker nextScaffoldPart(XML_Parser parser) {
7568*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7569*6be67779SAndroid Build Coastguard Worker   CONTENT_SCAFFOLD *me;
7570*6be67779SAndroid Build Coastguard Worker   int next;
7571*6be67779SAndroid Build Coastguard Worker 
7572*6be67779SAndroid Build Coastguard Worker   if (! dtd->scaffIndex) {
7573*6be67779SAndroid Build Coastguard Worker     /* Detect and prevent integer overflow.
7574*6be67779SAndroid Build Coastguard Worker      * The preprocessor guard addresses the "always false" warning
7575*6be67779SAndroid Build Coastguard Worker      * from -Wtype-limits on platforms where
7576*6be67779SAndroid Build Coastguard Worker      * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
7577*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
7578*6be67779SAndroid Build Coastguard Worker     if (parser->m_groupSize > ((size_t)(-1) / sizeof(int))) {
7579*6be67779SAndroid Build Coastguard Worker       return -1;
7580*6be67779SAndroid Build Coastguard Worker     }
7581*6be67779SAndroid Build Coastguard Worker #endif
7582*6be67779SAndroid Build Coastguard Worker     dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
7583*6be67779SAndroid Build Coastguard Worker     if (! dtd->scaffIndex)
7584*6be67779SAndroid Build Coastguard Worker       return -1;
7585*6be67779SAndroid Build Coastguard Worker     dtd->scaffIndex[0] = 0;
7586*6be67779SAndroid Build Coastguard Worker   }
7587*6be67779SAndroid Build Coastguard Worker 
7588*6be67779SAndroid Build Coastguard Worker   if (dtd->scaffCount >= dtd->scaffSize) {
7589*6be67779SAndroid Build Coastguard Worker     CONTENT_SCAFFOLD *temp;
7590*6be67779SAndroid Build Coastguard Worker     if (dtd->scaffold) {
7591*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent integer overflow */
7592*6be67779SAndroid Build Coastguard Worker       if (dtd->scaffSize > UINT_MAX / 2u) {
7593*6be67779SAndroid Build Coastguard Worker         return -1;
7594*6be67779SAndroid Build Coastguard Worker       }
7595*6be67779SAndroid Build Coastguard Worker       /* Detect and prevent integer overflow.
7596*6be67779SAndroid Build Coastguard Worker        * The preprocessor guard addresses the "always false" warning
7597*6be67779SAndroid Build Coastguard Worker        * from -Wtype-limits on platforms where
7598*6be67779SAndroid Build Coastguard Worker        * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
7599*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
7600*6be67779SAndroid Build Coastguard Worker       if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) {
7601*6be67779SAndroid Build Coastguard Worker         return -1;
7602*6be67779SAndroid Build Coastguard Worker       }
7603*6be67779SAndroid Build Coastguard Worker #endif
7604*6be67779SAndroid Build Coastguard Worker 
7605*6be67779SAndroid Build Coastguard Worker       temp = (CONTENT_SCAFFOLD *)REALLOC(
7606*6be67779SAndroid Build Coastguard Worker           parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
7607*6be67779SAndroid Build Coastguard Worker       if (temp == NULL)
7608*6be67779SAndroid Build Coastguard Worker         return -1;
7609*6be67779SAndroid Build Coastguard Worker       dtd->scaffSize *= 2;
7610*6be67779SAndroid Build Coastguard Worker     } else {
7611*6be67779SAndroid Build Coastguard Worker       temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS
7612*6be67779SAndroid Build Coastguard Worker                                                     * sizeof(CONTENT_SCAFFOLD));
7613*6be67779SAndroid Build Coastguard Worker       if (temp == NULL)
7614*6be67779SAndroid Build Coastguard Worker         return -1;
7615*6be67779SAndroid Build Coastguard Worker       dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
7616*6be67779SAndroid Build Coastguard Worker     }
7617*6be67779SAndroid Build Coastguard Worker     dtd->scaffold = temp;
7618*6be67779SAndroid Build Coastguard Worker   }
7619*6be67779SAndroid Build Coastguard Worker   next = dtd->scaffCount++;
7620*6be67779SAndroid Build Coastguard Worker   me = &dtd->scaffold[next];
7621*6be67779SAndroid Build Coastguard Worker   if (dtd->scaffLevel) {
7622*6be67779SAndroid Build Coastguard Worker     CONTENT_SCAFFOLD *parent
7623*6be67779SAndroid Build Coastguard Worker         = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]];
7624*6be67779SAndroid Build Coastguard Worker     if (parent->lastchild) {
7625*6be67779SAndroid Build Coastguard Worker       dtd->scaffold[parent->lastchild].nextsib = next;
7626*6be67779SAndroid Build Coastguard Worker     }
7627*6be67779SAndroid Build Coastguard Worker     if (! parent->childcnt)
7628*6be67779SAndroid Build Coastguard Worker       parent->firstchild = next;
7629*6be67779SAndroid Build Coastguard Worker     parent->lastchild = next;
7630*6be67779SAndroid Build Coastguard Worker     parent->childcnt++;
7631*6be67779SAndroid Build Coastguard Worker   }
7632*6be67779SAndroid Build Coastguard Worker   me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
7633*6be67779SAndroid Build Coastguard Worker   return next;
7634*6be67779SAndroid Build Coastguard Worker }
7635*6be67779SAndroid Build Coastguard Worker 
7636*6be67779SAndroid Build Coastguard Worker static XML_Content *
build_model(XML_Parser parser)7637*6be67779SAndroid Build Coastguard Worker build_model(XML_Parser parser) {
7638*6be67779SAndroid Build Coastguard Worker   /* Function build_model transforms the existing parser->m_dtd->scaffold
7639*6be67779SAndroid Build Coastguard Worker    * array of CONTENT_SCAFFOLD tree nodes into a new array of
7640*6be67779SAndroid Build Coastguard Worker    * XML_Content tree nodes followed by a gapless list of zero-terminated
7641*6be67779SAndroid Build Coastguard Worker    * strings. */
7642*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7643*6be67779SAndroid Build Coastguard Worker   XML_Content *ret;
7644*6be67779SAndroid Build Coastguard Worker   XML_Char *str; /* the current string writing location */
7645*6be67779SAndroid Build Coastguard Worker 
7646*6be67779SAndroid Build Coastguard Worker   /* Detect and prevent integer overflow.
7647*6be67779SAndroid Build Coastguard Worker    * The preprocessor guard addresses the "always false" warning
7648*6be67779SAndroid Build Coastguard Worker    * from -Wtype-limits on platforms where
7649*6be67779SAndroid Build Coastguard Worker    * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
7650*6be67779SAndroid Build Coastguard Worker #if UINT_MAX >= SIZE_MAX
7651*6be67779SAndroid Build Coastguard Worker   if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) {
7652*6be67779SAndroid Build Coastguard Worker     return NULL;
7653*6be67779SAndroid Build Coastguard Worker   }
7654*6be67779SAndroid Build Coastguard Worker   if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) {
7655*6be67779SAndroid Build Coastguard Worker     return NULL;
7656*6be67779SAndroid Build Coastguard Worker   }
7657*6be67779SAndroid Build Coastguard Worker #endif
7658*6be67779SAndroid Build Coastguard Worker   if (dtd->scaffCount * sizeof(XML_Content)
7659*6be67779SAndroid Build Coastguard Worker       > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) {
7660*6be67779SAndroid Build Coastguard Worker     return NULL;
7661*6be67779SAndroid Build Coastguard Worker   }
7662*6be67779SAndroid Build Coastguard Worker 
7663*6be67779SAndroid Build Coastguard Worker   const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
7664*6be67779SAndroid Build Coastguard Worker                             + (dtd->contentStringLen * sizeof(XML_Char)));
7665*6be67779SAndroid Build Coastguard Worker 
7666*6be67779SAndroid Build Coastguard Worker   ret = (XML_Content *)MALLOC(parser, allocsize);
7667*6be67779SAndroid Build Coastguard Worker   if (! ret)
7668*6be67779SAndroid Build Coastguard Worker     return NULL;
7669*6be67779SAndroid Build Coastguard Worker 
7670*6be67779SAndroid Build Coastguard Worker   /* What follows is an iterative implementation (of what was previously done
7671*6be67779SAndroid Build Coastguard Worker    * recursively in a dedicated function called "build_node".  The old recursive
7672*6be67779SAndroid Build Coastguard Worker    * build_node could be forced into stack exhaustion from input as small as a
7673*6be67779SAndroid Build Coastguard Worker    * few megabyte, and so that was a security issue.  Hence, a function call
7674*6be67779SAndroid Build Coastguard Worker    * stack is avoided now by resolving recursion.)
7675*6be67779SAndroid Build Coastguard Worker    *
7676*6be67779SAndroid Build Coastguard Worker    * The iterative approach works as follows:
7677*6be67779SAndroid Build Coastguard Worker    *
7678*6be67779SAndroid Build Coastguard Worker    * - We have two writing pointers, both walking up the result array; one does
7679*6be67779SAndroid Build Coastguard Worker    *   the work, the other creates "jobs" for its colleague to do, and leads
7680*6be67779SAndroid Build Coastguard Worker    *   the way:
7681*6be67779SAndroid Build Coastguard Worker    *
7682*6be67779SAndroid Build Coastguard Worker    *   - The faster one, pointer jobDest, always leads and writes "what job
7683*6be67779SAndroid Build Coastguard Worker    *     to do" by the other, once they reach that place in the
7684*6be67779SAndroid Build Coastguard Worker    *     array: leader "jobDest" stores the source node array index (relative
7685*6be67779SAndroid Build Coastguard Worker    *     to array dtd->scaffold) in field "numchildren".
7686*6be67779SAndroid Build Coastguard Worker    *
7687*6be67779SAndroid Build Coastguard Worker    *   - The slower one, pointer dest, looks at the value stored in the
7688*6be67779SAndroid Build Coastguard Worker    *     "numchildren" field (which actually holds a source node array index
7689*6be67779SAndroid Build Coastguard Worker    *     at that time) and puts the real data from dtd->scaffold in.
7690*6be67779SAndroid Build Coastguard Worker    *
7691*6be67779SAndroid Build Coastguard Worker    * - Before the loop starts, jobDest writes source array index 0
7692*6be67779SAndroid Build Coastguard Worker    *   (where the root node is located) so that dest will have something to do
7693*6be67779SAndroid Build Coastguard Worker    *   when it starts operation.
7694*6be67779SAndroid Build Coastguard Worker    *
7695*6be67779SAndroid Build Coastguard Worker    * - Whenever nodes with children are encountered, jobDest appends
7696*6be67779SAndroid Build Coastguard Worker    *   them as new jobs, in order.  As a result, tree node siblings are
7697*6be67779SAndroid Build Coastguard Worker    *   adjacent in the resulting array, for example:
7698*6be67779SAndroid Build Coastguard Worker    *
7699*6be67779SAndroid Build Coastguard Worker    *     [0] root, has two children
7700*6be67779SAndroid Build Coastguard Worker    *       [1] first child of 0, has three children
7701*6be67779SAndroid Build Coastguard Worker    *         [3] first child of 1, does not have children
7702*6be67779SAndroid Build Coastguard Worker    *         [4] second child of 1, does not have children
7703*6be67779SAndroid Build Coastguard Worker    *         [5] third child of 1, does not have children
7704*6be67779SAndroid Build Coastguard Worker    *       [2] second child of 0, does not have children
7705*6be67779SAndroid Build Coastguard Worker    *
7706*6be67779SAndroid Build Coastguard Worker    *   Or (the same data) presented in flat array view:
7707*6be67779SAndroid Build Coastguard Worker    *
7708*6be67779SAndroid Build Coastguard Worker    *     [0] root, has two children
7709*6be67779SAndroid Build Coastguard Worker    *
7710*6be67779SAndroid Build Coastguard Worker    *     [1] first child of 0, has three children
7711*6be67779SAndroid Build Coastguard Worker    *     [2] second child of 0, does not have children
7712*6be67779SAndroid Build Coastguard Worker    *
7713*6be67779SAndroid Build Coastguard Worker    *     [3] first child of 1, does not have children
7714*6be67779SAndroid Build Coastguard Worker    *     [4] second child of 1, does not have children
7715*6be67779SAndroid Build Coastguard Worker    *     [5] third child of 1, does not have children
7716*6be67779SAndroid Build Coastguard Worker    *
7717*6be67779SAndroid Build Coastguard Worker    * - The algorithm repeats until all target array indices have been processed.
7718*6be67779SAndroid Build Coastguard Worker    */
7719*6be67779SAndroid Build Coastguard Worker   XML_Content *dest = ret; /* tree node writing location, moves upwards */
7720*6be67779SAndroid Build Coastguard Worker   XML_Content *const destLimit = &ret[dtd->scaffCount];
7721*6be67779SAndroid Build Coastguard Worker   XML_Content *jobDest = ret; /* next free writing location in target array */
7722*6be67779SAndroid Build Coastguard Worker   str = (XML_Char *)&ret[dtd->scaffCount];
7723*6be67779SAndroid Build Coastguard Worker 
7724*6be67779SAndroid Build Coastguard Worker   /* Add the starting job, the root node (index 0) of the source tree  */
7725*6be67779SAndroid Build Coastguard Worker   (jobDest++)->numchildren = 0;
7726*6be67779SAndroid Build Coastguard Worker 
7727*6be67779SAndroid Build Coastguard Worker   for (; dest < destLimit; dest++) {
7728*6be67779SAndroid Build Coastguard Worker     /* Retrieve source tree array index from job storage */
7729*6be67779SAndroid Build Coastguard Worker     const int src_node = (int)dest->numchildren;
7730*6be67779SAndroid Build Coastguard Worker 
7731*6be67779SAndroid Build Coastguard Worker     /* Convert item */
7732*6be67779SAndroid Build Coastguard Worker     dest->type = dtd->scaffold[src_node].type;
7733*6be67779SAndroid Build Coastguard Worker     dest->quant = dtd->scaffold[src_node].quant;
7734*6be67779SAndroid Build Coastguard Worker     if (dest->type == XML_CTYPE_NAME) {
7735*6be67779SAndroid Build Coastguard Worker       const XML_Char *src;
7736*6be67779SAndroid Build Coastguard Worker       dest->name = str;
7737*6be67779SAndroid Build Coastguard Worker       src = dtd->scaffold[src_node].name;
7738*6be67779SAndroid Build Coastguard Worker       for (;;) {
7739*6be67779SAndroid Build Coastguard Worker         *str++ = *src;
7740*6be67779SAndroid Build Coastguard Worker         if (! *src)
7741*6be67779SAndroid Build Coastguard Worker           break;
7742*6be67779SAndroid Build Coastguard Worker         src++;
7743*6be67779SAndroid Build Coastguard Worker       }
7744*6be67779SAndroid Build Coastguard Worker       dest->numchildren = 0;
7745*6be67779SAndroid Build Coastguard Worker       dest->children = NULL;
7746*6be67779SAndroid Build Coastguard Worker     } else {
7747*6be67779SAndroid Build Coastguard Worker       unsigned int i;
7748*6be67779SAndroid Build Coastguard Worker       int cn;
7749*6be67779SAndroid Build Coastguard Worker       dest->name = NULL;
7750*6be67779SAndroid Build Coastguard Worker       dest->numchildren = dtd->scaffold[src_node].childcnt;
7751*6be67779SAndroid Build Coastguard Worker       dest->children = jobDest;
7752*6be67779SAndroid Build Coastguard Worker 
7753*6be67779SAndroid Build Coastguard Worker       /* Append scaffold indices of children to array */
7754*6be67779SAndroid Build Coastguard Worker       for (i = 0, cn = dtd->scaffold[src_node].firstchild;
7755*6be67779SAndroid Build Coastguard Worker            i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib)
7756*6be67779SAndroid Build Coastguard Worker         (jobDest++)->numchildren = (unsigned int)cn;
7757*6be67779SAndroid Build Coastguard Worker     }
7758*6be67779SAndroid Build Coastguard Worker   }
7759*6be67779SAndroid Build Coastguard Worker 
7760*6be67779SAndroid Build Coastguard Worker   return ret;
7761*6be67779SAndroid Build Coastguard Worker }
7762*6be67779SAndroid Build Coastguard Worker 
7763*6be67779SAndroid Build Coastguard Worker static ELEMENT_TYPE *
getElementType(XML_Parser parser,const ENCODING * enc,const char * ptr,const char * end)7764*6be67779SAndroid Build Coastguard Worker getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
7765*6be67779SAndroid Build Coastguard Worker                const char *end) {
7766*6be67779SAndroid Build Coastguard Worker   DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7767*6be67779SAndroid Build Coastguard Worker   const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
7768*6be67779SAndroid Build Coastguard Worker   ELEMENT_TYPE *ret;
7769*6be67779SAndroid Build Coastguard Worker 
7770*6be67779SAndroid Build Coastguard Worker   if (! name)
7771*6be67779SAndroid Build Coastguard Worker     return NULL;
7772*6be67779SAndroid Build Coastguard Worker   ret = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
7773*6be67779SAndroid Build Coastguard Worker                                sizeof(ELEMENT_TYPE));
7774*6be67779SAndroid Build Coastguard Worker   if (! ret)
7775*6be67779SAndroid Build Coastguard Worker     return NULL;
7776*6be67779SAndroid Build Coastguard Worker   if (ret->name != name)
7777*6be67779SAndroid Build Coastguard Worker     poolDiscard(&dtd->pool);
7778*6be67779SAndroid Build Coastguard Worker   else {
7779*6be67779SAndroid Build Coastguard Worker     poolFinish(&dtd->pool);
7780*6be67779SAndroid Build Coastguard Worker     if (! setElementTypePrefix(parser, ret))
7781*6be67779SAndroid Build Coastguard Worker       return NULL;
7782*6be67779SAndroid Build Coastguard Worker   }
7783*6be67779SAndroid Build Coastguard Worker   return ret;
7784*6be67779SAndroid Build Coastguard Worker }
7785*6be67779SAndroid Build Coastguard Worker 
7786*6be67779SAndroid Build Coastguard Worker static XML_Char *
copyString(const XML_Char * s,const XML_Memory_Handling_Suite * memsuite)7787*6be67779SAndroid Build Coastguard Worker copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
7788*6be67779SAndroid Build Coastguard Worker   size_t charsRequired = 0;
7789*6be67779SAndroid Build Coastguard Worker   XML_Char *result;
7790*6be67779SAndroid Build Coastguard Worker 
7791*6be67779SAndroid Build Coastguard Worker   /* First determine how long the string is */
7792*6be67779SAndroid Build Coastguard Worker   while (s[charsRequired] != 0) {
7793*6be67779SAndroid Build Coastguard Worker     charsRequired++;
7794*6be67779SAndroid Build Coastguard Worker   }
7795*6be67779SAndroid Build Coastguard Worker   /* Include the terminator */
7796*6be67779SAndroid Build Coastguard Worker   charsRequired++;
7797*6be67779SAndroid Build Coastguard Worker 
7798*6be67779SAndroid Build Coastguard Worker   /* Now allocate space for the copy */
7799*6be67779SAndroid Build Coastguard Worker   result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
7800*6be67779SAndroid Build Coastguard Worker   if (result == NULL)
7801*6be67779SAndroid Build Coastguard Worker     return NULL;
7802*6be67779SAndroid Build Coastguard Worker   /* Copy the original into place */
7803*6be67779SAndroid Build Coastguard Worker   memcpy(result, s, charsRequired * sizeof(XML_Char));
7804*6be67779SAndroid Build Coastguard Worker   return result;
7805*6be67779SAndroid Build Coastguard Worker }
7806*6be67779SAndroid Build Coastguard Worker 
7807*6be67779SAndroid Build Coastguard Worker #if XML_GE == 1
7808*6be67779SAndroid Build Coastguard Worker 
7809*6be67779SAndroid Build Coastguard Worker static float
accountingGetCurrentAmplification(XML_Parser rootParser)7810*6be67779SAndroid Build Coastguard Worker accountingGetCurrentAmplification(XML_Parser rootParser) {
7811*6be67779SAndroid Build Coastguard Worker   //                                          1.........1.........12 => 22
7812*6be67779SAndroid Build Coastguard Worker   const size_t lenOfShortestInclude = sizeof("<!ENTITY a SYSTEM 'b'>") - 1;
7813*6be67779SAndroid Build Coastguard Worker   const XmlBigCount countBytesOutput
7814*6be67779SAndroid Build Coastguard Worker       = rootParser->m_accounting.countBytesDirect
7815*6be67779SAndroid Build Coastguard Worker         + rootParser->m_accounting.countBytesIndirect;
7816*6be67779SAndroid Build Coastguard Worker   const float amplificationFactor
7817*6be67779SAndroid Build Coastguard Worker       = rootParser->m_accounting.countBytesDirect
7818*6be67779SAndroid Build Coastguard Worker             ? (countBytesOutput
7819*6be67779SAndroid Build Coastguard Worker                / (float)(rootParser->m_accounting.countBytesDirect))
7820*6be67779SAndroid Build Coastguard Worker             : ((lenOfShortestInclude
7821*6be67779SAndroid Build Coastguard Worker                 + rootParser->m_accounting.countBytesIndirect)
7822*6be67779SAndroid Build Coastguard Worker                / (float)lenOfShortestInclude);
7823*6be67779SAndroid Build Coastguard Worker   assert(! rootParser->m_parentParser);
7824*6be67779SAndroid Build Coastguard Worker   return amplificationFactor;
7825*6be67779SAndroid Build Coastguard Worker }
7826*6be67779SAndroid Build Coastguard Worker 
7827*6be67779SAndroid Build Coastguard Worker static void
accountingReportStats(XML_Parser originParser,const char * epilog)7828*6be67779SAndroid Build Coastguard Worker accountingReportStats(XML_Parser originParser, const char *epilog) {
7829*6be67779SAndroid Build Coastguard Worker   const XML_Parser rootParser = getRootParserOf(originParser, NULL);
7830*6be67779SAndroid Build Coastguard Worker   assert(! rootParser->m_parentParser);
7831*6be67779SAndroid Build Coastguard Worker 
7832*6be67779SAndroid Build Coastguard Worker   if (rootParser->m_accounting.debugLevel == 0u) {
7833*6be67779SAndroid Build Coastguard Worker     return;
7834*6be67779SAndroid Build Coastguard Worker   }
7835*6be67779SAndroid Build Coastguard Worker 
7836*6be67779SAndroid Build Coastguard Worker   const float amplificationFactor
7837*6be67779SAndroid Build Coastguard Worker       = accountingGetCurrentAmplification(rootParser);
7838*6be67779SAndroid Build Coastguard Worker   fprintf(stderr,
7839*6be67779SAndroid Build Coastguard Worker           "expat: Accounting(%p): Direct " EXPAT_FMT_ULL(
7840*6be67779SAndroid Build Coastguard Worker               "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s",
7841*6be67779SAndroid Build Coastguard Worker           (void *)rootParser, rootParser->m_accounting.countBytesDirect,
7842*6be67779SAndroid Build Coastguard Worker           rootParser->m_accounting.countBytesIndirect,
7843*6be67779SAndroid Build Coastguard Worker           (double)amplificationFactor, epilog);
7844*6be67779SAndroid Build Coastguard Worker }
7845*6be67779SAndroid Build Coastguard Worker 
7846*6be67779SAndroid Build Coastguard Worker static void
accountingOnAbort(XML_Parser originParser)7847*6be67779SAndroid Build Coastguard Worker accountingOnAbort(XML_Parser originParser) {
7848*6be67779SAndroid Build Coastguard Worker   accountingReportStats(originParser, " ABORTING\n");
7849*6be67779SAndroid Build Coastguard Worker }
7850*6be67779SAndroid Build Coastguard Worker 
7851*6be67779SAndroid Build Coastguard Worker 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)7852*6be67779SAndroid Build Coastguard Worker accountingReportDiff(XML_Parser rootParser,
7853*6be67779SAndroid Build Coastguard Worker                      unsigned int levelsAwayFromRootParser, const char *before,
7854*6be67779SAndroid Build Coastguard Worker                      const char *after, ptrdiff_t bytesMore, int source_line,
7855*6be67779SAndroid Build Coastguard Worker                      enum XML_Account account) {
7856*6be67779SAndroid Build Coastguard Worker   assert(! rootParser->m_parentParser);
7857*6be67779SAndroid Build Coastguard Worker 
7858*6be67779SAndroid Build Coastguard Worker   fprintf(stderr,
7859*6be67779SAndroid Build Coastguard Worker           " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"",
7860*6be67779SAndroid Build Coastguard Worker           bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP",
7861*6be67779SAndroid Build Coastguard Worker           levelsAwayFromRootParser, source_line, 10, "");
7862*6be67779SAndroid Build Coastguard Worker 
7863*6be67779SAndroid Build Coastguard Worker   const char ellipis[] = "[..]";
7864*6be67779SAndroid Build Coastguard Worker   const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1;
7865*6be67779SAndroid Build Coastguard Worker   const unsigned int contextLength = 10;
7866*6be67779SAndroid Build Coastguard Worker 
7867*6be67779SAndroid Build Coastguard Worker   /* Note: Performance is of no concern here */
7868*6be67779SAndroid Build Coastguard Worker   const char *walker = before;
7869*6be67779SAndroid Build Coastguard Worker   if ((rootParser->m_accounting.debugLevel >= 3u)
7870*6be67779SAndroid Build Coastguard Worker       || (after - before)
7871*6be67779SAndroid Build Coastguard Worker              <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) {
7872*6be67779SAndroid Build Coastguard Worker     for (; walker < after; walker++) {
7873*6be67779SAndroid Build Coastguard Worker       fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
7874*6be67779SAndroid Build Coastguard Worker     }
7875*6be67779SAndroid Build Coastguard Worker   } else {
7876*6be67779SAndroid Build Coastguard Worker     for (; walker < before + contextLength; walker++) {
7877*6be67779SAndroid Build Coastguard Worker       fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
7878*6be67779SAndroid Build Coastguard Worker     }
7879*6be67779SAndroid Build Coastguard Worker     fprintf(stderr, ellipis);
7880*6be67779SAndroid Build Coastguard Worker     walker = after - contextLength;
7881*6be67779SAndroid Build Coastguard Worker     for (; walker < after; walker++) {
7882*6be67779SAndroid Build Coastguard Worker       fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
7883*6be67779SAndroid Build Coastguard Worker     }
7884*6be67779SAndroid Build Coastguard Worker   }
7885*6be67779SAndroid Build Coastguard Worker   fprintf(stderr, "\"\n");
7886*6be67779SAndroid Build Coastguard Worker }
7887*6be67779SAndroid Build Coastguard Worker 
7888*6be67779SAndroid Build Coastguard Worker static XML_Bool
accountingDiffTolerated(XML_Parser originParser,int tok,const char * before,const char * after,int source_line,enum XML_Account account)7889*6be67779SAndroid Build Coastguard Worker accountingDiffTolerated(XML_Parser originParser, int tok, const char *before,
7890*6be67779SAndroid Build Coastguard Worker                         const char *after, int source_line,
7891*6be67779SAndroid Build Coastguard Worker                         enum XML_Account account) {
7892*6be67779SAndroid Build Coastguard Worker   /* Note: We need to check the token type *first* to be sure that
7893*6be67779SAndroid Build Coastguard Worker    *       we can even access variable <after>, safely.
7894*6be67779SAndroid Build Coastguard Worker    *       E.g. for XML_TOK_NONE <after> may hold an invalid pointer. */
7895*6be67779SAndroid Build Coastguard Worker   switch (tok) {
7896*6be67779SAndroid Build Coastguard Worker   case XML_TOK_INVALID:
7897*6be67779SAndroid Build Coastguard Worker   case XML_TOK_PARTIAL:
7898*6be67779SAndroid Build Coastguard Worker   case XML_TOK_PARTIAL_CHAR:
7899*6be67779SAndroid Build Coastguard Worker   case XML_TOK_NONE:
7900*6be67779SAndroid Build Coastguard Worker     return XML_TRUE;
7901*6be67779SAndroid Build Coastguard Worker   }
7902*6be67779SAndroid Build Coastguard Worker 
7903*6be67779SAndroid Build Coastguard Worker   if (account == XML_ACCOUNT_NONE)
7904*6be67779SAndroid Build Coastguard Worker     return XML_TRUE; /* because these bytes have been accounted for, already */
7905*6be67779SAndroid Build Coastguard Worker 
7906*6be67779SAndroid Build Coastguard Worker   unsigned int levelsAwayFromRootParser;
7907*6be67779SAndroid Build Coastguard Worker   const XML_Parser rootParser
7908*6be67779SAndroid Build Coastguard Worker       = getRootParserOf(originParser, &levelsAwayFromRootParser);
7909*6be67779SAndroid Build Coastguard Worker   assert(! rootParser->m_parentParser);
7910*6be67779SAndroid Build Coastguard Worker 
7911*6be67779SAndroid Build Coastguard Worker   const int isDirect
7912*6be67779SAndroid Build Coastguard Worker       = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser);
7913*6be67779SAndroid Build Coastguard Worker   const ptrdiff_t bytesMore = after - before;
7914*6be67779SAndroid Build Coastguard Worker 
7915*6be67779SAndroid Build Coastguard Worker   XmlBigCount *const additionTarget
7916*6be67779SAndroid Build Coastguard Worker       = isDirect ? &rootParser->m_accounting.countBytesDirect
7917*6be67779SAndroid Build Coastguard Worker                  : &rootParser->m_accounting.countBytesIndirect;
7918*6be67779SAndroid Build Coastguard Worker 
7919*6be67779SAndroid Build Coastguard Worker   /* Detect and avoid integer overflow */
7920*6be67779SAndroid Build Coastguard Worker   if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore)
7921*6be67779SAndroid Build Coastguard Worker     return XML_FALSE;
7922*6be67779SAndroid Build Coastguard Worker   *additionTarget += bytesMore;
7923*6be67779SAndroid Build Coastguard Worker 
7924*6be67779SAndroid Build Coastguard Worker   const XmlBigCount countBytesOutput
7925*6be67779SAndroid Build Coastguard Worker       = rootParser->m_accounting.countBytesDirect
7926*6be67779SAndroid Build Coastguard Worker         + rootParser->m_accounting.countBytesIndirect;
7927*6be67779SAndroid Build Coastguard Worker   const float amplificationFactor
7928*6be67779SAndroid Build Coastguard Worker       = accountingGetCurrentAmplification(rootParser);
7929*6be67779SAndroid Build Coastguard Worker   const XML_Bool tolerated
7930*6be67779SAndroid Build Coastguard Worker       = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes)
7931*6be67779SAndroid Build Coastguard Worker         || (amplificationFactor
7932*6be67779SAndroid Build Coastguard Worker             <= rootParser->m_accounting.maximumAmplificationFactor);
7933*6be67779SAndroid Build Coastguard Worker 
7934*6be67779SAndroid Build Coastguard Worker   if (rootParser->m_accounting.debugLevel >= 2u) {
7935*6be67779SAndroid Build Coastguard Worker     accountingReportStats(rootParser, "");
7936*6be67779SAndroid Build Coastguard Worker     accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after,
7937*6be67779SAndroid Build Coastguard Worker                          bytesMore, source_line, account);
7938*6be67779SAndroid Build Coastguard Worker   }
7939*6be67779SAndroid Build Coastguard Worker 
7940*6be67779SAndroid Build Coastguard Worker   return tolerated;
7941*6be67779SAndroid Build Coastguard Worker }
7942*6be67779SAndroid Build Coastguard Worker 
7943*6be67779SAndroid Build Coastguard Worker unsigned long long
testingAccountingGetCountBytesDirect(XML_Parser parser)7944*6be67779SAndroid Build Coastguard Worker testingAccountingGetCountBytesDirect(XML_Parser parser) {
7945*6be67779SAndroid Build Coastguard Worker   if (! parser)
7946*6be67779SAndroid Build Coastguard Worker     return 0;
7947*6be67779SAndroid Build Coastguard Worker   return parser->m_accounting.countBytesDirect;
7948*6be67779SAndroid Build Coastguard Worker }
7949*6be67779SAndroid Build Coastguard Worker 
7950*6be67779SAndroid Build Coastguard Worker unsigned long long
testingAccountingGetCountBytesIndirect(XML_Parser parser)7951*6be67779SAndroid Build Coastguard Worker testingAccountingGetCountBytesIndirect(XML_Parser parser) {
7952*6be67779SAndroid Build Coastguard Worker   if (! parser)
7953*6be67779SAndroid Build Coastguard Worker     return 0;
7954*6be67779SAndroid Build Coastguard Worker   return parser->m_accounting.countBytesIndirect;
7955*6be67779SAndroid Build Coastguard Worker }
7956*6be67779SAndroid Build Coastguard Worker 
7957*6be67779SAndroid Build Coastguard Worker static void
entityTrackingReportStats(XML_Parser rootParser,ENTITY * entity,const char * action,int sourceLine)7958*6be67779SAndroid Build Coastguard Worker entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
7959*6be67779SAndroid Build Coastguard Worker                           const char *action, int sourceLine) {
7960*6be67779SAndroid Build Coastguard Worker   assert(! rootParser->m_parentParser);
7961*6be67779SAndroid Build Coastguard Worker   if (rootParser->m_entity_stats.debugLevel == 0u)
7962*6be67779SAndroid Build Coastguard Worker     return;
7963*6be67779SAndroid Build Coastguard Worker 
7964*6be67779SAndroid Build Coastguard Worker #  if defined(XML_UNICODE)
7965*6be67779SAndroid Build Coastguard Worker   const char *const entityName = "[..]";
7966*6be67779SAndroid Build Coastguard Worker #  else
7967*6be67779SAndroid Build Coastguard Worker   const char *const entityName = entity->name;
7968*6be67779SAndroid Build Coastguard Worker #  endif
7969*6be67779SAndroid Build Coastguard Worker 
7970*6be67779SAndroid Build Coastguard Worker   fprintf(
7971*6be67779SAndroid Build Coastguard Worker       stderr,
7972*6be67779SAndroid Build Coastguard Worker       "expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n",
7973*6be67779SAndroid Build Coastguard Worker       (void *)rootParser, rootParser->m_entity_stats.countEverOpened,
7974*6be67779SAndroid Build Coastguard Worker       rootParser->m_entity_stats.currentDepth,
7975*6be67779SAndroid Build Coastguard Worker       rootParser->m_entity_stats.maximumDepthSeen,
7976*6be67779SAndroid Build Coastguard Worker       (rootParser->m_entity_stats.currentDepth - 1) * 2, "",
7977*6be67779SAndroid Build Coastguard Worker       entity->is_param ? "%" : "&", entityName, action, entity->textLen,
7978*6be67779SAndroid Build Coastguard Worker       sourceLine);
7979*6be67779SAndroid Build Coastguard Worker }
7980*6be67779SAndroid Build Coastguard Worker 
7981*6be67779SAndroid Build Coastguard Worker static void
entityTrackingOnOpen(XML_Parser originParser,ENTITY * entity,int sourceLine)7982*6be67779SAndroid Build Coastguard Worker entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) {
7983*6be67779SAndroid Build Coastguard Worker   const XML_Parser rootParser = getRootParserOf(originParser, NULL);
7984*6be67779SAndroid Build Coastguard Worker   assert(! rootParser->m_parentParser);
7985*6be67779SAndroid Build Coastguard Worker 
7986*6be67779SAndroid Build Coastguard Worker   rootParser->m_entity_stats.countEverOpened++;
7987*6be67779SAndroid Build Coastguard Worker   rootParser->m_entity_stats.currentDepth++;
7988*6be67779SAndroid Build Coastguard Worker   if (rootParser->m_entity_stats.currentDepth
7989*6be67779SAndroid Build Coastguard Worker       > rootParser->m_entity_stats.maximumDepthSeen) {
7990*6be67779SAndroid Build Coastguard Worker     rootParser->m_entity_stats.maximumDepthSeen++;
7991*6be67779SAndroid Build Coastguard Worker   }
7992*6be67779SAndroid Build Coastguard Worker 
7993*6be67779SAndroid Build Coastguard Worker   entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine);
7994*6be67779SAndroid Build Coastguard Worker }
7995*6be67779SAndroid Build Coastguard Worker 
7996*6be67779SAndroid Build Coastguard Worker static void
entityTrackingOnClose(XML_Parser originParser,ENTITY * entity,int sourceLine)7997*6be67779SAndroid Build Coastguard Worker entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) {
7998*6be67779SAndroid Build Coastguard Worker   const XML_Parser rootParser = getRootParserOf(originParser, NULL);
7999*6be67779SAndroid Build Coastguard Worker   assert(! rootParser->m_parentParser);
8000*6be67779SAndroid Build Coastguard Worker 
8001*6be67779SAndroid Build Coastguard Worker   entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine);
8002*6be67779SAndroid Build Coastguard Worker   rootParser->m_entity_stats.currentDepth--;
8003*6be67779SAndroid Build Coastguard Worker }
8004*6be67779SAndroid Build Coastguard Worker 
8005*6be67779SAndroid Build Coastguard Worker static XML_Parser
getRootParserOf(XML_Parser parser,unsigned int * outLevelDiff)8006*6be67779SAndroid Build Coastguard Worker getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {
8007*6be67779SAndroid Build Coastguard Worker   XML_Parser rootParser = parser;
8008*6be67779SAndroid Build Coastguard Worker   unsigned int stepsTakenUpwards = 0;
8009*6be67779SAndroid Build Coastguard Worker   while (rootParser->m_parentParser) {
8010*6be67779SAndroid Build Coastguard Worker     rootParser = rootParser->m_parentParser;
8011*6be67779SAndroid Build Coastguard Worker     stepsTakenUpwards++;
8012*6be67779SAndroid Build Coastguard Worker   }
8013*6be67779SAndroid Build Coastguard Worker   assert(! rootParser->m_parentParser);
8014*6be67779SAndroid Build Coastguard Worker   if (outLevelDiff != NULL) {
8015*6be67779SAndroid Build Coastguard Worker     *outLevelDiff = stepsTakenUpwards;
8016*6be67779SAndroid Build Coastguard Worker   }
8017*6be67779SAndroid Build Coastguard Worker   return rootParser;
8018*6be67779SAndroid Build Coastguard Worker }
8019*6be67779SAndroid Build Coastguard Worker 
8020*6be67779SAndroid Build Coastguard Worker const char *
unsignedCharToPrintable(unsigned char c)8021*6be67779SAndroid Build Coastguard Worker unsignedCharToPrintable(unsigned char c) {
8022*6be67779SAndroid Build Coastguard Worker   switch (c) {
8023*6be67779SAndroid Build Coastguard Worker   case 0:
8024*6be67779SAndroid Build Coastguard Worker     return "\\0";
8025*6be67779SAndroid Build Coastguard Worker   case 1:
8026*6be67779SAndroid Build Coastguard Worker     return "\\x1";
8027*6be67779SAndroid Build Coastguard Worker   case 2:
8028*6be67779SAndroid Build Coastguard Worker     return "\\x2";
8029*6be67779SAndroid Build Coastguard Worker   case 3:
8030*6be67779SAndroid Build Coastguard Worker     return "\\x3";
8031*6be67779SAndroid Build Coastguard Worker   case 4:
8032*6be67779SAndroid Build Coastguard Worker     return "\\x4";
8033*6be67779SAndroid Build Coastguard Worker   case 5:
8034*6be67779SAndroid Build Coastguard Worker     return "\\x5";
8035*6be67779SAndroid Build Coastguard Worker   case 6:
8036*6be67779SAndroid Build Coastguard Worker     return "\\x6";
8037*6be67779SAndroid Build Coastguard Worker   case 7:
8038*6be67779SAndroid Build Coastguard Worker     return "\\x7";
8039*6be67779SAndroid Build Coastguard Worker   case 8:
8040*6be67779SAndroid Build Coastguard Worker     return "\\x8";
8041*6be67779SAndroid Build Coastguard Worker   case 9:
8042*6be67779SAndroid Build Coastguard Worker     return "\\t";
8043*6be67779SAndroid Build Coastguard Worker   case 10:
8044*6be67779SAndroid Build Coastguard Worker     return "\\n";
8045*6be67779SAndroid Build Coastguard Worker   case 11:
8046*6be67779SAndroid Build Coastguard Worker     return "\\xB";
8047*6be67779SAndroid Build Coastguard Worker   case 12:
8048*6be67779SAndroid Build Coastguard Worker     return "\\xC";
8049*6be67779SAndroid Build Coastguard Worker   case 13:
8050*6be67779SAndroid Build Coastguard Worker     return "\\r";
8051*6be67779SAndroid Build Coastguard Worker   case 14:
8052*6be67779SAndroid Build Coastguard Worker     return "\\xE";
8053*6be67779SAndroid Build Coastguard Worker   case 15:
8054*6be67779SAndroid Build Coastguard Worker     return "\\xF";
8055*6be67779SAndroid Build Coastguard Worker   case 16:
8056*6be67779SAndroid Build Coastguard Worker     return "\\x10";
8057*6be67779SAndroid Build Coastguard Worker   case 17:
8058*6be67779SAndroid Build Coastguard Worker     return "\\x11";
8059*6be67779SAndroid Build Coastguard Worker   case 18:
8060*6be67779SAndroid Build Coastguard Worker     return "\\x12";
8061*6be67779SAndroid Build Coastguard Worker   case 19:
8062*6be67779SAndroid Build Coastguard Worker     return "\\x13";
8063*6be67779SAndroid Build Coastguard Worker   case 20:
8064*6be67779SAndroid Build Coastguard Worker     return "\\x14";
8065*6be67779SAndroid Build Coastguard Worker   case 21:
8066*6be67779SAndroid Build Coastguard Worker     return "\\x15";
8067*6be67779SAndroid Build Coastguard Worker   case 22:
8068*6be67779SAndroid Build Coastguard Worker     return "\\x16";
8069*6be67779SAndroid Build Coastguard Worker   case 23:
8070*6be67779SAndroid Build Coastguard Worker     return "\\x17";
8071*6be67779SAndroid Build Coastguard Worker   case 24:
8072*6be67779SAndroid Build Coastguard Worker     return "\\x18";
8073*6be67779SAndroid Build Coastguard Worker   case 25:
8074*6be67779SAndroid Build Coastguard Worker     return "\\x19";
8075*6be67779SAndroid Build Coastguard Worker   case 26:
8076*6be67779SAndroid Build Coastguard Worker     return "\\x1A";
8077*6be67779SAndroid Build Coastguard Worker   case 27:
8078*6be67779SAndroid Build Coastguard Worker     return "\\x1B";
8079*6be67779SAndroid Build Coastguard Worker   case 28:
8080*6be67779SAndroid Build Coastguard Worker     return "\\x1C";
8081*6be67779SAndroid Build Coastguard Worker   case 29:
8082*6be67779SAndroid Build Coastguard Worker     return "\\x1D";
8083*6be67779SAndroid Build Coastguard Worker   case 30:
8084*6be67779SAndroid Build Coastguard Worker     return "\\x1E";
8085*6be67779SAndroid Build Coastguard Worker   case 31:
8086*6be67779SAndroid Build Coastguard Worker     return "\\x1F";
8087*6be67779SAndroid Build Coastguard Worker   case 32:
8088*6be67779SAndroid Build Coastguard Worker     return " ";
8089*6be67779SAndroid Build Coastguard Worker   case 33:
8090*6be67779SAndroid Build Coastguard Worker     return "!";
8091*6be67779SAndroid Build Coastguard Worker   case 34:
8092*6be67779SAndroid Build Coastguard Worker     return "\\\"";
8093*6be67779SAndroid Build Coastguard Worker   case 35:
8094*6be67779SAndroid Build Coastguard Worker     return "#";
8095*6be67779SAndroid Build Coastguard Worker   case 36:
8096*6be67779SAndroid Build Coastguard Worker     return "$";
8097*6be67779SAndroid Build Coastguard Worker   case 37:
8098*6be67779SAndroid Build Coastguard Worker     return "%";
8099*6be67779SAndroid Build Coastguard Worker   case 38:
8100*6be67779SAndroid Build Coastguard Worker     return "&";
8101*6be67779SAndroid Build Coastguard Worker   case 39:
8102*6be67779SAndroid Build Coastguard Worker     return "'";
8103*6be67779SAndroid Build Coastguard Worker   case 40:
8104*6be67779SAndroid Build Coastguard Worker     return "(";
8105*6be67779SAndroid Build Coastguard Worker   case 41:
8106*6be67779SAndroid Build Coastguard Worker     return ")";
8107*6be67779SAndroid Build Coastguard Worker   case 42:
8108*6be67779SAndroid Build Coastguard Worker     return "*";
8109*6be67779SAndroid Build Coastguard Worker   case 43:
8110*6be67779SAndroid Build Coastguard Worker     return "+";
8111*6be67779SAndroid Build Coastguard Worker   case 44:
8112*6be67779SAndroid Build Coastguard Worker     return ",";
8113*6be67779SAndroid Build Coastguard Worker   case 45:
8114*6be67779SAndroid Build Coastguard Worker     return "-";
8115*6be67779SAndroid Build Coastguard Worker   case 46:
8116*6be67779SAndroid Build Coastguard Worker     return ".";
8117*6be67779SAndroid Build Coastguard Worker   case 47:
8118*6be67779SAndroid Build Coastguard Worker     return "/";
8119*6be67779SAndroid Build Coastguard Worker   case 48:
8120*6be67779SAndroid Build Coastguard Worker     return "0";
8121*6be67779SAndroid Build Coastguard Worker   case 49:
8122*6be67779SAndroid Build Coastguard Worker     return "1";
8123*6be67779SAndroid Build Coastguard Worker   case 50:
8124*6be67779SAndroid Build Coastguard Worker     return "2";
8125*6be67779SAndroid Build Coastguard Worker   case 51:
8126*6be67779SAndroid Build Coastguard Worker     return "3";
8127*6be67779SAndroid Build Coastguard Worker   case 52:
8128*6be67779SAndroid Build Coastguard Worker     return "4";
8129*6be67779SAndroid Build Coastguard Worker   case 53:
8130*6be67779SAndroid Build Coastguard Worker     return "5";
8131*6be67779SAndroid Build Coastguard Worker   case 54:
8132*6be67779SAndroid Build Coastguard Worker     return "6";
8133*6be67779SAndroid Build Coastguard Worker   case 55:
8134*6be67779SAndroid Build Coastguard Worker     return "7";
8135*6be67779SAndroid Build Coastguard Worker   case 56:
8136*6be67779SAndroid Build Coastguard Worker     return "8";
8137*6be67779SAndroid Build Coastguard Worker   case 57:
8138*6be67779SAndroid Build Coastguard Worker     return "9";
8139*6be67779SAndroid Build Coastguard Worker   case 58:
8140*6be67779SAndroid Build Coastguard Worker     return ":";
8141*6be67779SAndroid Build Coastguard Worker   case 59:
8142*6be67779SAndroid Build Coastguard Worker     return ";";
8143*6be67779SAndroid Build Coastguard Worker   case 60:
8144*6be67779SAndroid Build Coastguard Worker     return "<";
8145*6be67779SAndroid Build Coastguard Worker   case 61:
8146*6be67779SAndroid Build Coastguard Worker     return "=";
8147*6be67779SAndroid Build Coastguard Worker   case 62:
8148*6be67779SAndroid Build Coastguard Worker     return ">";
8149*6be67779SAndroid Build Coastguard Worker   case 63:
8150*6be67779SAndroid Build Coastguard Worker     return "?";
8151*6be67779SAndroid Build Coastguard Worker   case 64:
8152*6be67779SAndroid Build Coastguard Worker     return "@";
8153*6be67779SAndroid Build Coastguard Worker   case 65:
8154*6be67779SAndroid Build Coastguard Worker     return "A";
8155*6be67779SAndroid Build Coastguard Worker   case 66:
8156*6be67779SAndroid Build Coastguard Worker     return "B";
8157*6be67779SAndroid Build Coastguard Worker   case 67:
8158*6be67779SAndroid Build Coastguard Worker     return "C";
8159*6be67779SAndroid Build Coastguard Worker   case 68:
8160*6be67779SAndroid Build Coastguard Worker     return "D";
8161*6be67779SAndroid Build Coastguard Worker   case 69:
8162*6be67779SAndroid Build Coastguard Worker     return "E";
8163*6be67779SAndroid Build Coastguard Worker   case 70:
8164*6be67779SAndroid Build Coastguard Worker     return "F";
8165*6be67779SAndroid Build Coastguard Worker   case 71:
8166*6be67779SAndroid Build Coastguard Worker     return "G";
8167*6be67779SAndroid Build Coastguard Worker   case 72:
8168*6be67779SAndroid Build Coastguard Worker     return "H";
8169*6be67779SAndroid Build Coastguard Worker   case 73:
8170*6be67779SAndroid Build Coastguard Worker     return "I";
8171*6be67779SAndroid Build Coastguard Worker   case 74:
8172*6be67779SAndroid Build Coastguard Worker     return "J";
8173*6be67779SAndroid Build Coastguard Worker   case 75:
8174*6be67779SAndroid Build Coastguard Worker     return "K";
8175*6be67779SAndroid Build Coastguard Worker   case 76:
8176*6be67779SAndroid Build Coastguard Worker     return "L";
8177*6be67779SAndroid Build Coastguard Worker   case 77:
8178*6be67779SAndroid Build Coastguard Worker     return "M";
8179*6be67779SAndroid Build Coastguard Worker   case 78:
8180*6be67779SAndroid Build Coastguard Worker     return "N";
8181*6be67779SAndroid Build Coastguard Worker   case 79:
8182*6be67779SAndroid Build Coastguard Worker     return "O";
8183*6be67779SAndroid Build Coastguard Worker   case 80:
8184*6be67779SAndroid Build Coastguard Worker     return "P";
8185*6be67779SAndroid Build Coastguard Worker   case 81:
8186*6be67779SAndroid Build Coastguard Worker     return "Q";
8187*6be67779SAndroid Build Coastguard Worker   case 82:
8188*6be67779SAndroid Build Coastguard Worker     return "R";
8189*6be67779SAndroid Build Coastguard Worker   case 83:
8190*6be67779SAndroid Build Coastguard Worker     return "S";
8191*6be67779SAndroid Build Coastguard Worker   case 84:
8192*6be67779SAndroid Build Coastguard Worker     return "T";
8193*6be67779SAndroid Build Coastguard Worker   case 85:
8194*6be67779SAndroid Build Coastguard Worker     return "U";
8195*6be67779SAndroid Build Coastguard Worker   case 86:
8196*6be67779SAndroid Build Coastguard Worker     return "V";
8197*6be67779SAndroid Build Coastguard Worker   case 87:
8198*6be67779SAndroid Build Coastguard Worker     return "W";
8199*6be67779SAndroid Build Coastguard Worker   case 88:
8200*6be67779SAndroid Build Coastguard Worker     return "X";
8201*6be67779SAndroid Build Coastguard Worker   case 89:
8202*6be67779SAndroid Build Coastguard Worker     return "Y";
8203*6be67779SAndroid Build Coastguard Worker   case 90:
8204*6be67779SAndroid Build Coastguard Worker     return "Z";
8205*6be67779SAndroid Build Coastguard Worker   case 91:
8206*6be67779SAndroid Build Coastguard Worker     return "[";
8207*6be67779SAndroid Build Coastguard Worker   case 92:
8208*6be67779SAndroid Build Coastguard Worker     return "\\\\";
8209*6be67779SAndroid Build Coastguard Worker   case 93:
8210*6be67779SAndroid Build Coastguard Worker     return "]";
8211*6be67779SAndroid Build Coastguard Worker   case 94:
8212*6be67779SAndroid Build Coastguard Worker     return "^";
8213*6be67779SAndroid Build Coastguard Worker   case 95:
8214*6be67779SAndroid Build Coastguard Worker     return "_";
8215*6be67779SAndroid Build Coastguard Worker   case 96:
8216*6be67779SAndroid Build Coastguard Worker     return "`";
8217*6be67779SAndroid Build Coastguard Worker   case 97:
8218*6be67779SAndroid Build Coastguard Worker     return "a";
8219*6be67779SAndroid Build Coastguard Worker   case 98:
8220*6be67779SAndroid Build Coastguard Worker     return "b";
8221*6be67779SAndroid Build Coastguard Worker   case 99:
8222*6be67779SAndroid Build Coastguard Worker     return "c";
8223*6be67779SAndroid Build Coastguard Worker   case 100:
8224*6be67779SAndroid Build Coastguard Worker     return "d";
8225*6be67779SAndroid Build Coastguard Worker   case 101:
8226*6be67779SAndroid Build Coastguard Worker     return "e";
8227*6be67779SAndroid Build Coastguard Worker   case 102:
8228*6be67779SAndroid Build Coastguard Worker     return "f";
8229*6be67779SAndroid Build Coastguard Worker   case 103:
8230*6be67779SAndroid Build Coastguard Worker     return "g";
8231*6be67779SAndroid Build Coastguard Worker   case 104:
8232*6be67779SAndroid Build Coastguard Worker     return "h";
8233*6be67779SAndroid Build Coastguard Worker   case 105:
8234*6be67779SAndroid Build Coastguard Worker     return "i";
8235*6be67779SAndroid Build Coastguard Worker   case 106:
8236*6be67779SAndroid Build Coastguard Worker     return "j";
8237*6be67779SAndroid Build Coastguard Worker   case 107:
8238*6be67779SAndroid Build Coastguard Worker     return "k";
8239*6be67779SAndroid Build Coastguard Worker   case 108:
8240*6be67779SAndroid Build Coastguard Worker     return "l";
8241*6be67779SAndroid Build Coastguard Worker   case 109:
8242*6be67779SAndroid Build Coastguard Worker     return "m";
8243*6be67779SAndroid Build Coastguard Worker   case 110:
8244*6be67779SAndroid Build Coastguard Worker     return "n";
8245*6be67779SAndroid Build Coastguard Worker   case 111:
8246*6be67779SAndroid Build Coastguard Worker     return "o";
8247*6be67779SAndroid Build Coastguard Worker   case 112:
8248*6be67779SAndroid Build Coastguard Worker     return "p";
8249*6be67779SAndroid Build Coastguard Worker   case 113:
8250*6be67779SAndroid Build Coastguard Worker     return "q";
8251*6be67779SAndroid Build Coastguard Worker   case 114:
8252*6be67779SAndroid Build Coastguard Worker     return "r";
8253*6be67779SAndroid Build Coastguard Worker   case 115:
8254*6be67779SAndroid Build Coastguard Worker     return "s";
8255*6be67779SAndroid Build Coastguard Worker   case 116:
8256*6be67779SAndroid Build Coastguard Worker     return "t";
8257*6be67779SAndroid Build Coastguard Worker   case 117:
8258*6be67779SAndroid Build Coastguard Worker     return "u";
8259*6be67779SAndroid Build Coastguard Worker   case 118:
8260*6be67779SAndroid Build Coastguard Worker     return "v";
8261*6be67779SAndroid Build Coastguard Worker   case 119:
8262*6be67779SAndroid Build Coastguard Worker     return "w";
8263*6be67779SAndroid Build Coastguard Worker   case 120:
8264*6be67779SAndroid Build Coastguard Worker     return "x";
8265*6be67779SAndroid Build Coastguard Worker   case 121:
8266*6be67779SAndroid Build Coastguard Worker     return "y";
8267*6be67779SAndroid Build Coastguard Worker   case 122:
8268*6be67779SAndroid Build Coastguard Worker     return "z";
8269*6be67779SAndroid Build Coastguard Worker   case 123:
8270*6be67779SAndroid Build Coastguard Worker     return "{";
8271*6be67779SAndroid Build Coastguard Worker   case 124:
8272*6be67779SAndroid Build Coastguard Worker     return "|";
8273*6be67779SAndroid Build Coastguard Worker   case 125:
8274*6be67779SAndroid Build Coastguard Worker     return "}";
8275*6be67779SAndroid Build Coastguard Worker   case 126:
8276*6be67779SAndroid Build Coastguard Worker     return "~";
8277*6be67779SAndroid Build Coastguard Worker   case 127:
8278*6be67779SAndroid Build Coastguard Worker     return "\\x7F";
8279*6be67779SAndroid Build Coastguard Worker   case 128:
8280*6be67779SAndroid Build Coastguard Worker     return "\\x80";
8281*6be67779SAndroid Build Coastguard Worker   case 129:
8282*6be67779SAndroid Build Coastguard Worker     return "\\x81";
8283*6be67779SAndroid Build Coastguard Worker   case 130:
8284*6be67779SAndroid Build Coastguard Worker     return "\\x82";
8285*6be67779SAndroid Build Coastguard Worker   case 131:
8286*6be67779SAndroid Build Coastguard Worker     return "\\x83";
8287*6be67779SAndroid Build Coastguard Worker   case 132:
8288*6be67779SAndroid Build Coastguard Worker     return "\\x84";
8289*6be67779SAndroid Build Coastguard Worker   case 133:
8290*6be67779SAndroid Build Coastguard Worker     return "\\x85";
8291*6be67779SAndroid Build Coastguard Worker   case 134:
8292*6be67779SAndroid Build Coastguard Worker     return "\\x86";
8293*6be67779SAndroid Build Coastguard Worker   case 135:
8294*6be67779SAndroid Build Coastguard Worker     return "\\x87";
8295*6be67779SAndroid Build Coastguard Worker   case 136:
8296*6be67779SAndroid Build Coastguard Worker     return "\\x88";
8297*6be67779SAndroid Build Coastguard Worker   case 137:
8298*6be67779SAndroid Build Coastguard Worker     return "\\x89";
8299*6be67779SAndroid Build Coastguard Worker   case 138:
8300*6be67779SAndroid Build Coastguard Worker     return "\\x8A";
8301*6be67779SAndroid Build Coastguard Worker   case 139:
8302*6be67779SAndroid Build Coastguard Worker     return "\\x8B";
8303*6be67779SAndroid Build Coastguard Worker   case 140:
8304*6be67779SAndroid Build Coastguard Worker     return "\\x8C";
8305*6be67779SAndroid Build Coastguard Worker   case 141:
8306*6be67779SAndroid Build Coastguard Worker     return "\\x8D";
8307*6be67779SAndroid Build Coastguard Worker   case 142:
8308*6be67779SAndroid Build Coastguard Worker     return "\\x8E";
8309*6be67779SAndroid Build Coastguard Worker   case 143:
8310*6be67779SAndroid Build Coastguard Worker     return "\\x8F";
8311*6be67779SAndroid Build Coastguard Worker   case 144:
8312*6be67779SAndroid Build Coastguard Worker     return "\\x90";
8313*6be67779SAndroid Build Coastguard Worker   case 145:
8314*6be67779SAndroid Build Coastguard Worker     return "\\x91";
8315*6be67779SAndroid Build Coastguard Worker   case 146:
8316*6be67779SAndroid Build Coastguard Worker     return "\\x92";
8317*6be67779SAndroid Build Coastguard Worker   case 147:
8318*6be67779SAndroid Build Coastguard Worker     return "\\x93";
8319*6be67779SAndroid Build Coastguard Worker   case 148:
8320*6be67779SAndroid Build Coastguard Worker     return "\\x94";
8321*6be67779SAndroid Build Coastguard Worker   case 149:
8322*6be67779SAndroid Build Coastguard Worker     return "\\x95";
8323*6be67779SAndroid Build Coastguard Worker   case 150:
8324*6be67779SAndroid Build Coastguard Worker     return "\\x96";
8325*6be67779SAndroid Build Coastguard Worker   case 151:
8326*6be67779SAndroid Build Coastguard Worker     return "\\x97";
8327*6be67779SAndroid Build Coastguard Worker   case 152:
8328*6be67779SAndroid Build Coastguard Worker     return "\\x98";
8329*6be67779SAndroid Build Coastguard Worker   case 153:
8330*6be67779SAndroid Build Coastguard Worker     return "\\x99";
8331*6be67779SAndroid Build Coastguard Worker   case 154:
8332*6be67779SAndroid Build Coastguard Worker     return "\\x9A";
8333*6be67779SAndroid Build Coastguard Worker   case 155:
8334*6be67779SAndroid Build Coastguard Worker     return "\\x9B";
8335*6be67779SAndroid Build Coastguard Worker   case 156:
8336*6be67779SAndroid Build Coastguard Worker     return "\\x9C";
8337*6be67779SAndroid Build Coastguard Worker   case 157:
8338*6be67779SAndroid Build Coastguard Worker     return "\\x9D";
8339*6be67779SAndroid Build Coastguard Worker   case 158:
8340*6be67779SAndroid Build Coastguard Worker     return "\\x9E";
8341*6be67779SAndroid Build Coastguard Worker   case 159:
8342*6be67779SAndroid Build Coastguard Worker     return "\\x9F";
8343*6be67779SAndroid Build Coastguard Worker   case 160:
8344*6be67779SAndroid Build Coastguard Worker     return "\\xA0";
8345*6be67779SAndroid Build Coastguard Worker   case 161:
8346*6be67779SAndroid Build Coastguard Worker     return "\\xA1";
8347*6be67779SAndroid Build Coastguard Worker   case 162:
8348*6be67779SAndroid Build Coastguard Worker     return "\\xA2";
8349*6be67779SAndroid Build Coastguard Worker   case 163:
8350*6be67779SAndroid Build Coastguard Worker     return "\\xA3";
8351*6be67779SAndroid Build Coastguard Worker   case 164:
8352*6be67779SAndroid Build Coastguard Worker     return "\\xA4";
8353*6be67779SAndroid Build Coastguard Worker   case 165:
8354*6be67779SAndroid Build Coastguard Worker     return "\\xA5";
8355*6be67779SAndroid Build Coastguard Worker   case 166:
8356*6be67779SAndroid Build Coastguard Worker     return "\\xA6";
8357*6be67779SAndroid Build Coastguard Worker   case 167:
8358*6be67779SAndroid Build Coastguard Worker     return "\\xA7";
8359*6be67779SAndroid Build Coastguard Worker   case 168:
8360*6be67779SAndroid Build Coastguard Worker     return "\\xA8";
8361*6be67779SAndroid Build Coastguard Worker   case 169:
8362*6be67779SAndroid Build Coastguard Worker     return "\\xA9";
8363*6be67779SAndroid Build Coastguard Worker   case 170:
8364*6be67779SAndroid Build Coastguard Worker     return "\\xAA";
8365*6be67779SAndroid Build Coastguard Worker   case 171:
8366*6be67779SAndroid Build Coastguard Worker     return "\\xAB";
8367*6be67779SAndroid Build Coastguard Worker   case 172:
8368*6be67779SAndroid Build Coastguard Worker     return "\\xAC";
8369*6be67779SAndroid Build Coastguard Worker   case 173:
8370*6be67779SAndroid Build Coastguard Worker     return "\\xAD";
8371*6be67779SAndroid Build Coastguard Worker   case 174:
8372*6be67779SAndroid Build Coastguard Worker     return "\\xAE";
8373*6be67779SAndroid Build Coastguard Worker   case 175:
8374*6be67779SAndroid Build Coastguard Worker     return "\\xAF";
8375*6be67779SAndroid Build Coastguard Worker   case 176:
8376*6be67779SAndroid Build Coastguard Worker     return "\\xB0";
8377*6be67779SAndroid Build Coastguard Worker   case 177:
8378*6be67779SAndroid Build Coastguard Worker     return "\\xB1";
8379*6be67779SAndroid Build Coastguard Worker   case 178:
8380*6be67779SAndroid Build Coastguard Worker     return "\\xB2";
8381*6be67779SAndroid Build Coastguard Worker   case 179:
8382*6be67779SAndroid Build Coastguard Worker     return "\\xB3";
8383*6be67779SAndroid Build Coastguard Worker   case 180:
8384*6be67779SAndroid Build Coastguard Worker     return "\\xB4";
8385*6be67779SAndroid Build Coastguard Worker   case 181:
8386*6be67779SAndroid Build Coastguard Worker     return "\\xB5";
8387*6be67779SAndroid Build Coastguard Worker   case 182:
8388*6be67779SAndroid Build Coastguard Worker     return "\\xB6";
8389*6be67779SAndroid Build Coastguard Worker   case 183:
8390*6be67779SAndroid Build Coastguard Worker     return "\\xB7";
8391*6be67779SAndroid Build Coastguard Worker   case 184:
8392*6be67779SAndroid Build Coastguard Worker     return "\\xB8";
8393*6be67779SAndroid Build Coastguard Worker   case 185:
8394*6be67779SAndroid Build Coastguard Worker     return "\\xB9";
8395*6be67779SAndroid Build Coastguard Worker   case 186:
8396*6be67779SAndroid Build Coastguard Worker     return "\\xBA";
8397*6be67779SAndroid Build Coastguard Worker   case 187:
8398*6be67779SAndroid Build Coastguard Worker     return "\\xBB";
8399*6be67779SAndroid Build Coastguard Worker   case 188:
8400*6be67779SAndroid Build Coastguard Worker     return "\\xBC";
8401*6be67779SAndroid Build Coastguard Worker   case 189:
8402*6be67779SAndroid Build Coastguard Worker     return "\\xBD";
8403*6be67779SAndroid Build Coastguard Worker   case 190:
8404*6be67779SAndroid Build Coastguard Worker     return "\\xBE";
8405*6be67779SAndroid Build Coastguard Worker   case 191:
8406*6be67779SAndroid Build Coastguard Worker     return "\\xBF";
8407*6be67779SAndroid Build Coastguard Worker   case 192:
8408*6be67779SAndroid Build Coastguard Worker     return "\\xC0";
8409*6be67779SAndroid Build Coastguard Worker   case 193:
8410*6be67779SAndroid Build Coastguard Worker     return "\\xC1";
8411*6be67779SAndroid Build Coastguard Worker   case 194:
8412*6be67779SAndroid Build Coastguard Worker     return "\\xC2";
8413*6be67779SAndroid Build Coastguard Worker   case 195:
8414*6be67779SAndroid Build Coastguard Worker     return "\\xC3";
8415*6be67779SAndroid Build Coastguard Worker   case 196:
8416*6be67779SAndroid Build Coastguard Worker     return "\\xC4";
8417*6be67779SAndroid Build Coastguard Worker   case 197:
8418*6be67779SAndroid Build Coastguard Worker     return "\\xC5";
8419*6be67779SAndroid Build Coastguard Worker   case 198:
8420*6be67779SAndroid Build Coastguard Worker     return "\\xC6";
8421*6be67779SAndroid Build Coastguard Worker   case 199:
8422*6be67779SAndroid Build Coastguard Worker     return "\\xC7";
8423*6be67779SAndroid Build Coastguard Worker   case 200:
8424*6be67779SAndroid Build Coastguard Worker     return "\\xC8";
8425*6be67779SAndroid Build Coastguard Worker   case 201:
8426*6be67779SAndroid Build Coastguard Worker     return "\\xC9";
8427*6be67779SAndroid Build Coastguard Worker   case 202:
8428*6be67779SAndroid Build Coastguard Worker     return "\\xCA";
8429*6be67779SAndroid Build Coastguard Worker   case 203:
8430*6be67779SAndroid Build Coastguard Worker     return "\\xCB";
8431*6be67779SAndroid Build Coastguard Worker   case 204:
8432*6be67779SAndroid Build Coastguard Worker     return "\\xCC";
8433*6be67779SAndroid Build Coastguard Worker   case 205:
8434*6be67779SAndroid Build Coastguard Worker     return "\\xCD";
8435*6be67779SAndroid Build Coastguard Worker   case 206:
8436*6be67779SAndroid Build Coastguard Worker     return "\\xCE";
8437*6be67779SAndroid Build Coastguard Worker   case 207:
8438*6be67779SAndroid Build Coastguard Worker     return "\\xCF";
8439*6be67779SAndroid Build Coastguard Worker   case 208:
8440*6be67779SAndroid Build Coastguard Worker     return "\\xD0";
8441*6be67779SAndroid Build Coastguard Worker   case 209:
8442*6be67779SAndroid Build Coastguard Worker     return "\\xD1";
8443*6be67779SAndroid Build Coastguard Worker   case 210:
8444*6be67779SAndroid Build Coastguard Worker     return "\\xD2";
8445*6be67779SAndroid Build Coastguard Worker   case 211:
8446*6be67779SAndroid Build Coastguard Worker     return "\\xD3";
8447*6be67779SAndroid Build Coastguard Worker   case 212:
8448*6be67779SAndroid Build Coastguard Worker     return "\\xD4";
8449*6be67779SAndroid Build Coastguard Worker   case 213:
8450*6be67779SAndroid Build Coastguard Worker     return "\\xD5";
8451*6be67779SAndroid Build Coastguard Worker   case 214:
8452*6be67779SAndroid Build Coastguard Worker     return "\\xD6";
8453*6be67779SAndroid Build Coastguard Worker   case 215:
8454*6be67779SAndroid Build Coastguard Worker     return "\\xD7";
8455*6be67779SAndroid Build Coastguard Worker   case 216:
8456*6be67779SAndroid Build Coastguard Worker     return "\\xD8";
8457*6be67779SAndroid Build Coastguard Worker   case 217:
8458*6be67779SAndroid Build Coastguard Worker     return "\\xD9";
8459*6be67779SAndroid Build Coastguard Worker   case 218:
8460*6be67779SAndroid Build Coastguard Worker     return "\\xDA";
8461*6be67779SAndroid Build Coastguard Worker   case 219:
8462*6be67779SAndroid Build Coastguard Worker     return "\\xDB";
8463*6be67779SAndroid Build Coastguard Worker   case 220:
8464*6be67779SAndroid Build Coastguard Worker     return "\\xDC";
8465*6be67779SAndroid Build Coastguard Worker   case 221:
8466*6be67779SAndroid Build Coastguard Worker     return "\\xDD";
8467*6be67779SAndroid Build Coastguard Worker   case 222:
8468*6be67779SAndroid Build Coastguard Worker     return "\\xDE";
8469*6be67779SAndroid Build Coastguard Worker   case 223:
8470*6be67779SAndroid Build Coastguard Worker     return "\\xDF";
8471*6be67779SAndroid Build Coastguard Worker   case 224:
8472*6be67779SAndroid Build Coastguard Worker     return "\\xE0";
8473*6be67779SAndroid Build Coastguard Worker   case 225:
8474*6be67779SAndroid Build Coastguard Worker     return "\\xE1";
8475*6be67779SAndroid Build Coastguard Worker   case 226:
8476*6be67779SAndroid Build Coastguard Worker     return "\\xE2";
8477*6be67779SAndroid Build Coastguard Worker   case 227:
8478*6be67779SAndroid Build Coastguard Worker     return "\\xE3";
8479*6be67779SAndroid Build Coastguard Worker   case 228:
8480*6be67779SAndroid Build Coastguard Worker     return "\\xE4";
8481*6be67779SAndroid Build Coastguard Worker   case 229:
8482*6be67779SAndroid Build Coastguard Worker     return "\\xE5";
8483*6be67779SAndroid Build Coastguard Worker   case 230:
8484*6be67779SAndroid Build Coastguard Worker     return "\\xE6";
8485*6be67779SAndroid Build Coastguard Worker   case 231:
8486*6be67779SAndroid Build Coastguard Worker     return "\\xE7";
8487*6be67779SAndroid Build Coastguard Worker   case 232:
8488*6be67779SAndroid Build Coastguard Worker     return "\\xE8";
8489*6be67779SAndroid Build Coastguard Worker   case 233:
8490*6be67779SAndroid Build Coastguard Worker     return "\\xE9";
8491*6be67779SAndroid Build Coastguard Worker   case 234:
8492*6be67779SAndroid Build Coastguard Worker     return "\\xEA";
8493*6be67779SAndroid Build Coastguard Worker   case 235:
8494*6be67779SAndroid Build Coastguard Worker     return "\\xEB";
8495*6be67779SAndroid Build Coastguard Worker   case 236:
8496*6be67779SAndroid Build Coastguard Worker     return "\\xEC";
8497*6be67779SAndroid Build Coastguard Worker   case 237:
8498*6be67779SAndroid Build Coastguard Worker     return "\\xED";
8499*6be67779SAndroid Build Coastguard Worker   case 238:
8500*6be67779SAndroid Build Coastguard Worker     return "\\xEE";
8501*6be67779SAndroid Build Coastguard Worker   case 239:
8502*6be67779SAndroid Build Coastguard Worker     return "\\xEF";
8503*6be67779SAndroid Build Coastguard Worker   case 240:
8504*6be67779SAndroid Build Coastguard Worker     return "\\xF0";
8505*6be67779SAndroid Build Coastguard Worker   case 241:
8506*6be67779SAndroid Build Coastguard Worker     return "\\xF1";
8507*6be67779SAndroid Build Coastguard Worker   case 242:
8508*6be67779SAndroid Build Coastguard Worker     return "\\xF2";
8509*6be67779SAndroid Build Coastguard Worker   case 243:
8510*6be67779SAndroid Build Coastguard Worker     return "\\xF3";
8511*6be67779SAndroid Build Coastguard Worker   case 244:
8512*6be67779SAndroid Build Coastguard Worker     return "\\xF4";
8513*6be67779SAndroid Build Coastguard Worker   case 245:
8514*6be67779SAndroid Build Coastguard Worker     return "\\xF5";
8515*6be67779SAndroid Build Coastguard Worker   case 246:
8516*6be67779SAndroid Build Coastguard Worker     return "\\xF6";
8517*6be67779SAndroid Build Coastguard Worker   case 247:
8518*6be67779SAndroid Build Coastguard Worker     return "\\xF7";
8519*6be67779SAndroid Build Coastguard Worker   case 248:
8520*6be67779SAndroid Build Coastguard Worker     return "\\xF8";
8521*6be67779SAndroid Build Coastguard Worker   case 249:
8522*6be67779SAndroid Build Coastguard Worker     return "\\xF9";
8523*6be67779SAndroid Build Coastguard Worker   case 250:
8524*6be67779SAndroid Build Coastguard Worker     return "\\xFA";
8525*6be67779SAndroid Build Coastguard Worker   case 251:
8526*6be67779SAndroid Build Coastguard Worker     return "\\xFB";
8527*6be67779SAndroid Build Coastguard Worker   case 252:
8528*6be67779SAndroid Build Coastguard Worker     return "\\xFC";
8529*6be67779SAndroid Build Coastguard Worker   case 253:
8530*6be67779SAndroid Build Coastguard Worker     return "\\xFD";
8531*6be67779SAndroid Build Coastguard Worker   case 254:
8532*6be67779SAndroid Build Coastguard Worker     return "\\xFE";
8533*6be67779SAndroid Build Coastguard Worker   case 255:
8534*6be67779SAndroid Build Coastguard Worker     return "\\xFF";
8535*6be67779SAndroid Build Coastguard Worker   default:
8536*6be67779SAndroid Build Coastguard Worker     assert(0); /* never gets here */
8537*6be67779SAndroid Build Coastguard Worker     return "dead code";
8538*6be67779SAndroid Build Coastguard Worker   }
8539*6be67779SAndroid Build Coastguard Worker   assert(0); /* never gets here */
8540*6be67779SAndroid Build Coastguard Worker }
8541*6be67779SAndroid Build Coastguard Worker 
8542*6be67779SAndroid Build Coastguard Worker #endif /* XML_GE == 1 */
8543*6be67779SAndroid Build Coastguard Worker 
8544*6be67779SAndroid Build Coastguard Worker static unsigned long
getDebugLevel(const char * variableName,unsigned long defaultDebugLevel)8545*6be67779SAndroid Build Coastguard Worker getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {
8546*6be67779SAndroid Build Coastguard Worker   const char *const valueOrNull = getenv(variableName);
8547*6be67779SAndroid Build Coastguard Worker   if (valueOrNull == NULL) {
8548*6be67779SAndroid Build Coastguard Worker     return defaultDebugLevel;
8549*6be67779SAndroid Build Coastguard Worker   }
8550*6be67779SAndroid Build Coastguard Worker   const char *const value = valueOrNull;
8551*6be67779SAndroid Build Coastguard Worker 
8552*6be67779SAndroid Build Coastguard Worker   errno = 0;
8553*6be67779SAndroid Build Coastguard Worker   char *afterValue = NULL;
8554*6be67779SAndroid Build Coastguard Worker   unsigned long debugLevel = strtoul(value, &afterValue, 10);
8555*6be67779SAndroid Build Coastguard Worker   if ((errno != 0) || (afterValue == value) || (afterValue[0] != '\0')) {
8556*6be67779SAndroid Build Coastguard Worker     errno = 0;
8557*6be67779SAndroid Build Coastguard Worker     return defaultDebugLevel;
8558*6be67779SAndroid Build Coastguard Worker   }
8559*6be67779SAndroid Build Coastguard Worker 
8560*6be67779SAndroid Build Coastguard Worker   return debugLevel;
8561*6be67779SAndroid Build Coastguard Worker }
8562