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