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