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))
127typedef 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)
135typedef 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
175typedef const XML_Char *KEY;
176
177typedef struct {
178  KEY name;
179} NAMED;
180
181typedef 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
189static size_t keylen(KEY s);
190
191static 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
206typedef 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
220typedef 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
230typedef struct prefix {
231  const XML_Char *name;
232  BINDING *binding;
233} PREFIX;
234
235typedef 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*/
257typedef 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
267typedef 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
281typedef 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
293typedef struct block {
294  struct block *next;
295  int size;
296  XML_Char s[1];
297} BLOCK;
298
299typedef 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. */
310typedef struct attribute_id {
311  XML_Char *name;
312  PREFIX *prefix;
313  XML_Bool maybeTokenized;
314  XML_Bool xmlns;
315} ATTRIBUTE_ID;
316
317typedef struct {
318  const ATTRIBUTE_ID *id;
319  XML_Bool isCdata;
320  const XML_Char *value;
321} DEFAULT_ATTRIBUTE;
322
323typedef struct {
324  unsigned long version;
325  unsigned long hash;
326  const XML_Char *uriName;
327} NS_ATT;
328
329typedef 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
338typedef 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
367typedef 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
376typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
377                                         const char *end, const char **endPtr);
378
379static Processor prologProcessor;
380static Processor prologInitProcessor;
381static Processor contentProcessor;
382static Processor cdataSectionProcessor;
383#ifdef XML_DTD
384static Processor ignoreSectionProcessor;
385static Processor externalParEntProcessor;
386static Processor externalParEntInitProcessor;
387static Processor entityValueProcessor;
388static Processor entityValueInitProcessor;
389#endif /* XML_DTD */
390static Processor epilogProcessor;
391static Processor errorProcessor;
392static Processor externalEntityInitProcessor;
393static Processor externalEntityInitProcessor2;
394static Processor externalEntityInitProcessor3;
395static Processor externalEntityContentProcessor;
396static Processor internalEntityProcessor;
397
398static enum XML_Error handleUnknownEncoding(XML_Parser parser,
399                                            const XML_Char *encodingName);
400static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
401                                     const char *s, const char *next);
402static enum XML_Error initializeEncoding(XML_Parser parser);
403static 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);
407static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
408                                            XML_Bool betweenDecl);
409static 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);
413static 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
417static 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
422static void freeBindings(XML_Parser parser, BINDING *bindings);
423static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *,
424                                const char *s, TAG_NAME *tagNamePtr,
425                                BINDING **bindingsPtr);
426static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
427                                 const ATTRIBUTE_ID *attId, const XML_Char *uri,
428                                 BINDING **bindingsPtr);
429static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
430                           XML_Bool isId, const XML_Char *dfltValue,
431                           XML_Parser parser);
432static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *,
433                                          XML_Bool isCdata, const char *,
434                                          const char *, STRING_POOL *);
435static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *,
436                                           XML_Bool isCdata, const char *,
437                                           const char *, STRING_POOL *);
438static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
439                                    const char *start, const char *end);
440static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
441static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
442                                       const char *start, const char *end);
443static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
444                                       const char *start, const char *end);
445static int reportComment(XML_Parser parser, const ENCODING *enc,
446                         const char *start, const char *end);
447static void reportDefault(XML_Parser parser, const ENCODING *enc,
448                          const char *start, const char *end);
449
450static const XML_Char *getContext(XML_Parser parser);
451static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
452
453static void FASTCALL normalizePublicId(XML_Char *s);
454
455static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms);
456/* do not call if m_parentParser != NULL */
457static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
458static void dtdDestroy(DTD *p, XML_Bool isDocEntity,
459                       const XML_Memory_Handling_Suite *ms);
460static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
461                   const XML_Memory_Handling_Suite *ms);
462static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *, STRING_POOL *,
463                           const HASH_TABLE *);
464static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
465                     size_t createSize);
466static void FASTCALL hashTableInit(HASH_TABLE *,
467                                   const XML_Memory_Handling_Suite *ms);
468static void FASTCALL hashTableClear(HASH_TABLE *);
469static void FASTCALL hashTableDestroy(HASH_TABLE *);
470static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
471static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
472
473static void FASTCALL poolInit(STRING_POOL *,
474                              const XML_Memory_Handling_Suite *ms);
475static void FASTCALL poolClear(STRING_POOL *);
476static void FASTCALL poolDestroy(STRING_POOL *);
477static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
478                            const char *ptr, const char *end);
479static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
480                                 const char *ptr, const char *end);
481static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
482static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
483                                               const XML_Char *s);
484static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
485                                       int n);
486static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
487                                                 const XML_Char *s);
488
489static int FASTCALL nextScaffoldPart(XML_Parser parser);
490static XML_Content *build_model(XML_Parser parser);
491static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
492                                    const char *ptr, const char *end);
493
494static XML_Char *copyString(const XML_Char *s,
495                            const XML_Memory_Handling_Suite *memsuite);
496
497static unsigned long generate_hash_secret_salt(XML_Parser parser);
498static XML_Bool startParsing(XML_Parser parser);
499
500static XML_Parser parserCreate(const XML_Char *encodingName,
501                               const XML_Memory_Handling_Suite *memsuite,
502                               const XML_Char *nameSep, DTD *dtd);
503
504static 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
518struct 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
625XML_Parser XMLCALL
626XML_ParserCreate(const XML_Char *encodingName) {
627  return XML_ParserCreate_MM(encodingName, NULL, NULL);
628}
629
630XML_Parser XMLCALL
631XML_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
637static 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+ */
654static int
655writeRandomBytes_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 */
686static int
687writeRandomBytes_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
719static void
720writeRandomBytes_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 */
743static int
744writeRandomBytes_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
767static unsigned long
768gather_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
792static unsigned long
793ENTROPY_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
802static unsigned long
803generate_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
845static unsigned long
846get_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
852static XML_Bool /* only valid for root parser */
853startParsing(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
866XML_Parser XMLCALL
867XML_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
873static XML_Parser
874parserCreate(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
988static void
989parserInit(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 */
1061static void FASTCALL
1062moveToFreeBindingList(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
1071XML_Bool XMLCALL
1072XML_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
1112enum XML_Status XMLCALL
1113XML_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
1139XML_Parser XMLCALL
1140XML_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
1308static void FASTCALL
1309destroyBindings(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
1320void XMLCALL
1321XML_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
1386void XMLCALL
1387XML_UseParserAsHandlerArg(XML_Parser parser) {
1388  if (parser != NULL)
1389    parser->m_handlerArg = parser;
1390}
1391
1392enum XML_Error XMLCALL
1393XML_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
1408void XMLCALL
1409XML_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
1419void XMLCALL
1420XML_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
1429enum XML_Status XMLCALL
1430XML_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
1443const XML_Char *XMLCALL
1444XML_GetBase(XML_Parser parser) {
1445  if (parser == NULL)
1446    return NULL;
1447  return parser->m_curBase;
1448}
1449
1450int XMLCALL
1451XML_GetSpecifiedAttributeCount(XML_Parser parser) {
1452  if (parser == NULL)
1453    return -1;
1454  return parser->m_nSpecifiedAtts;
1455}
1456
1457int XMLCALL
1458XML_GetIdAttributeIndex(XML_Parser parser) {
1459  if (parser == NULL)
1460    return -1;
1461  return parser->m_idAttIndex;
1462}
1463
1464#ifdef XML_ATTR_INFO
1465const XML_AttrInfo *XMLCALL
1466XML_GetAttributeInfo(XML_Parser parser) {
1467  if (parser == NULL)
1468    return NULL;
1469  return parser->m_attInfo;
1470}
1471#endif
1472
1473void XMLCALL
1474XML_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
1482void XMLCALL
1483XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) {
1484  if (parser != NULL)
1485    parser->m_startElementHandler = start;
1486}
1487
1488void XMLCALL
1489XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) {
1490  if (parser != NULL)
1491    parser->m_endElementHandler = end;
1492}
1493
1494void XMLCALL
1495XML_SetCharacterDataHandler(XML_Parser parser,
1496                            XML_CharacterDataHandler handler) {
1497  if (parser != NULL)
1498    parser->m_characterDataHandler = handler;
1499}
1500
1501void XMLCALL
1502XML_SetProcessingInstructionHandler(XML_Parser parser,
1503                                    XML_ProcessingInstructionHandler handler) {
1504  if (parser != NULL)
1505    parser->m_processingInstructionHandler = handler;
1506}
1507
1508void XMLCALL
1509XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) {
1510  if (parser != NULL)
1511    parser->m_commentHandler = handler;
1512}
1513
1514void XMLCALL
1515XML_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
1524void XMLCALL
1525XML_SetStartCdataSectionHandler(XML_Parser parser,
1526                                XML_StartCdataSectionHandler start) {
1527  if (parser != NULL)
1528    parser->m_startCdataSectionHandler = start;
1529}
1530
1531void XMLCALL
1532XML_SetEndCdataSectionHandler(XML_Parser parser,
1533                              XML_EndCdataSectionHandler end) {
1534  if (parser != NULL)
1535    parser->m_endCdataSectionHandler = end;
1536}
1537
1538void XMLCALL
1539XML_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
1546void XMLCALL
1547XML_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
1554void XMLCALL
1555XML_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
1563void XMLCALL
1564XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1565                               XML_StartDoctypeDeclHandler start) {
1566  if (parser != NULL)
1567    parser->m_startDoctypeDeclHandler = start;
1568}
1569
1570void XMLCALL
1571XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) {
1572  if (parser != NULL)
1573    parser->m_endDoctypeDeclHandler = end;
1574}
1575
1576void XMLCALL
1577XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1578                                 XML_UnparsedEntityDeclHandler handler) {
1579  if (parser != NULL)
1580    parser->m_unparsedEntityDeclHandler = handler;
1581}
1582
1583void XMLCALL
1584XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) {
1585  if (parser != NULL)
1586    parser->m_notationDeclHandler = handler;
1587}
1588
1589void XMLCALL
1590XML_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
1599void XMLCALL
1600XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1601                                 XML_StartNamespaceDeclHandler start) {
1602  if (parser != NULL)
1603    parser->m_startNamespaceDeclHandler = start;
1604}
1605
1606void XMLCALL
1607XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1608                               XML_EndNamespaceDeclHandler end) {
1609  if (parser != NULL)
1610    parser->m_endNamespaceDeclHandler = end;
1611}
1612
1613void XMLCALL
1614XML_SetNotStandaloneHandler(XML_Parser parser,
1615                            XML_NotStandaloneHandler handler) {
1616  if (parser != NULL)
1617    parser->m_notStandaloneHandler = handler;
1618}
1619
1620void XMLCALL
1621XML_SetExternalEntityRefHandler(XML_Parser parser,
1622                                XML_ExternalEntityRefHandler handler) {
1623  if (parser != NULL)
1624    parser->m_externalEntityRefHandler = handler;
1625}
1626
1627void XMLCALL
1628XML_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
1637void XMLCALL
1638XML_SetSkippedEntityHandler(XML_Parser parser,
1639                            XML_SkippedEntityHandler handler) {
1640  if (parser != NULL)
1641    parser->m_skippedEntityHandler = handler;
1642}
1643
1644void XMLCALL
1645XML_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
1653void XMLCALL
1654XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) {
1655  if (parser != NULL)
1656    parser->m_elementDeclHandler = eldecl;
1657}
1658
1659void XMLCALL
1660XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) {
1661  if (parser != NULL)
1662    parser->m_attlistDeclHandler = attdecl;
1663}
1664
1665void XMLCALL
1666XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) {
1667  if (parser != NULL)
1668    parser->m_entityDeclHandler = handler;
1669}
1670
1671void XMLCALL
1672XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) {
1673  if (parser != NULL)
1674    parser->m_xmlDeclHandler = handler;
1675}
1676
1677int XMLCALL
1678XML_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
1694int XMLCALL
1695XML_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
1708enum XML_Status XMLCALL
1709XML_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
1862enum XML_Status XMLCALL
1863XML_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
1921void *XMLCALL
1922XML_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
2039enum XML_Status XMLCALL
2040XML_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
2069enum XML_Status XMLCALL
2070XML_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
2109void XMLCALL
2110XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) {
2111  if (parser == NULL)
2112    return;
2113  assert(status != NULL);
2114  *status = parser->m_parsingStatus;
2115}
2116
2117enum XML_Error XMLCALL
2118XML_GetErrorCode(XML_Parser parser) {
2119  if (parser == NULL)
2120    return XML_ERROR_INVALID_ARGUMENT;
2121  return parser->m_errorCode;
2122}
2123
2124XML_Index XMLCALL
2125XML_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
2134int XMLCALL
2135XML_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
2143const char *XMLCALL
2144XML_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
2163XML_Size XMLCALL
2164XML_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
2175XML_Size XMLCALL
2176XML_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
2187void XMLCALL
2188XML_FreeContentModel(XML_Parser parser, XML_Content *model) {
2189  if (parser != NULL)
2190    FREE(parser, model);
2191}
2192
2193void *XMLCALL
2194XML_MemMalloc(XML_Parser parser, size_t size) {
2195  if (parser == NULL)
2196    return NULL;
2197  return MALLOC(parser, size);
2198}
2199
2200void *XMLCALL
2201XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) {
2202  if (parser == NULL)
2203    return NULL;
2204  return REALLOC(parser, ptr, size);
2205}
2206
2207void XMLCALL
2208XML_MemFree(XML_Parser parser, void *ptr) {
2209  if (parser != NULL)
2210    FREE(parser, ptr);
2211}
2212
2213void XMLCALL
2214XML_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
2228const XML_LChar *XMLCALL
2229XML_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
2325const XML_LChar *XMLCALL
2326XML_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
2344XML_Expat_Version XMLCALL
2345XML_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
2355const XML_Feature *XMLCALL
2356XML_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*/
2397static XML_Bool
2398storeRawNames(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
2441static enum XML_Error PTRCALL
2442contentProcessor(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
2454static enum XML_Error PTRCALL
2455externalEntityInitProcessor(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
2464static enum XML_Error PTRCALL
2465externalEntityInitProcessor2(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
2501static enum XML_Error PTRCALL
2502externalEntityInitProcessor3(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
2544static enum XML_Error PTRCALL
2545externalEntityContentProcessor(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
2557static enum XML_Error
2558doContent(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 */
3009static void
3010freeBindings(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*/
3037static enum XML_Error
3038storeAtts(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*/
3423static enum XML_Error
3424addBinding(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*/
3535static enum XML_Error PTRCALL
3536cdataSectionProcessor(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*/
3558static enum XML_Error
3559doCdataSection(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*/
3673static enum XML_Error PTRCALL
3674ignoreSectionProcessor(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*/
3691static enum XML_Error
3692doIgnoreSection(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
3766static enum XML_Error
3767initializeEncoding(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
3796static enum XML_Error
3797processXmlDecl(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
3879static enum XML_Error
3880handleUnknownEncoding(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
3913static enum XML_Error PTRCALL
3914prologInitProcessor(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
3925static enum XML_Error PTRCALL
3926externalParEntInitProcessor(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
3945static enum XML_Error PTRCALL
3946entityValueInitProcessor(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
4016static enum XML_Error PTRCALL
4017externalParEntProcessor(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
4054static enum XML_Error PTRCALL
4055entityValueProcessor(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
4089static enum XML_Error PTRCALL
4090prologProcessor(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
4098static enum XML_Error
4099doProlog(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
5086static enum XML_Error PTRCALL
5087epilogProcessor(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
5150static enum XML_Error
5151processInternalEntity(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
5206static enum XML_Error PTRCALL
5207internalEntityProcessor(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
5267static enum XML_Error PTRCALL
5268errorProcessor(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
5276static enum XML_Error
5277storeAttributeValue(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
5290static enum XML_Error
5291appendAttributeValue(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
5463static enum XML_Error
5464storeEntityValue(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  }
5622endEntityValue:
5623#ifdef XML_DTD
5624  parser->m_prologState.inEntityValue = oldInEntityValue;
5625#endif /* XML_DTD */
5626  return result;
5627}
5628
5629static void FASTCALL
5630normalizeLines(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
5650static int
5651reportProcessingInstruction(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
5677static int
5678reportComment(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
5697static void
5698reportDefault(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
5743static int
5744defineAttribute(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
5787static int
5788setElementTypePrefix(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
5816static ATTRIBUTE_ID *
5817getAttributeId(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
5879static const XML_Char *
5880getContext(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
5975static XML_Bool
5976setContext(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
6035static void FASTCALL
6036normalizePublicId(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
6056static DTD *
6057dtdCreate(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
6088static void
6089dtdReset(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
6129static void
6130dtdDestroy(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*/
6159static int
6160dtdCopy(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
6285static int
6286copyEntityTable(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
6350static XML_Bool FASTCALL
6351keyeq(KEY s1, KEY s2) {
6352  for (; *s1 == *s2; s1++, s2++)
6353    if (*s1 == 0)
6354      return XML_TRUE;
6355  return XML_FALSE;
6356}
6357
6358static size_t
6359keylen(KEY s) {
6360  size_t len = 0;
6361  for (; *s; s++, len++)
6362    ;
6363  return len;
6364}
6365
6366static void
6367copy_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
6372static unsigned long FASTCALL
6373hash(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
6383static NAMED *
6384lookup(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
6460static void FASTCALL
6461hashTableClear(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
6470static void FASTCALL
6471hashTableDestroy(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
6478static void FASTCALL
6479hashTableInit(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
6487static void FASTCALL
6488hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
6489  iter->p = table->v;
6490  iter->end = iter->p + table->size;
6491}
6492
6493static NAMED *FASTCALL
6494hashTableIterNext(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
6503static void FASTCALL
6504poolInit(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
6513static void FASTCALL
6514poolClear(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
6532static void FASTCALL
6533poolDestroy(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
6548static XML_Char *
6549poolAppend(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
6565static const XML_Char *FASTCALL
6566poolCopyString(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
6576static const XML_Char *
6577poolCopyStringN(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
6601static const XML_Char *FASTCALL
6602poolAppendString(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
6611static XML_Char *
6612poolStoreString(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
6622static size_t
6623poolBytesToAllocateFor(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
6650static XML_Bool FASTCALL
6651poolGrow(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
6754static int FASTCALL
6755nextScaffoldPart(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
6801static void
6802build_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
6833static XML_Content *
6834build_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
6853static ELEMENT_TYPE *
6854getElementType(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
6876static XML_Char *
6877copyString(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