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