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