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