1 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
2 See the file COPYING for copying permission.
4 101bfd65d1ff3d1511cf6671e6aae65f82cd97df6f4da137d46d510731830ad9 (2.2.3+)
7 #if !defined(_GNU_SOURCE)
8 # define _GNU_SOURCE 1 /* syscall prototype */
12 #include <string.h> /* memset(), memcpy() */
14 #include <limits.h> /* UINT_MAX */
15 #include <stdio.h> /* fprintf */
16 #include <stdlib.h> /* getenv */
19 #define getpid GetCurrentProcessId
21 #include <sys/time.h> /* gettimeofday() */
22 #include <sys/types.h> /* getpid() */
23 #include <unistd.h> /* getpid() */
24 #include <fcntl.h> /* O_RDONLY */
28 #define XML_BUILDING_EXPAT 1
31 #include "winconfig.h"
32 #elif defined(HAVE_EXPAT_CONFIG_H)
33 #include <expat_config.h>
34 #endif /* ndef _WIN32 */
40 #if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
41 # if defined(HAVE_GETRANDOM)
42 # include <sys/random.h> /* getrandom */
44 # include <unistd.h> /* syscall */
45 # include <sys/syscall.h> /* SYS_getrandom */
47 # if ! defined(GRND_NONBLOCK)
48 # define GRND_NONBLOCK 0x0001
49 # endif /* defined(GRND_NONBLOCK) */
50 #endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
52 #if defined(HAVE_LIBBSD) \
53 && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
54 # include <bsd/stdlib.h>
57 #if defined(_WIN32) && !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
58 # define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
61 #if !defined(HAVE_GETRANDOM) && !defined(HAVE_SYSCALL_GETRANDOM) \
62 && !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM) \
63 && !defined(XML_DEV_URANDOM) \
65 && !defined(XML_POOR_ENTROPY)
67 You do not have support for any sources of high quality entropy \
68 enabled. For end user security, that is probably not what you want. \
70 Your options include: \
71 * Linux + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \
72 * Linux + glibc <2.25 (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \
73 * BSD / macOS >=10.7 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \
74 * BSD / macOS <10.7 (arc4random): HAVE_ARC4RANDOM, \
75 * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
76 * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
77 * Linux / BSD / macOS (/dev/urandom): XML_DEV_URANDOM \
78 * Windows (RtlGenRandom): _WIN32. \
80 If insist on not using any of these, bypass this error by defining \
81 XML_POOR_ENTROPY; you have been warned. \
83 For CMake, one way to pass the define is: \
84 cmake -DCMAKE_C_FLAGS="-pipe -O2 -DHAVE_SYSCALL_GETRANDOM" . \
86 If you have reasons to patch this detection code away or need changes \
87 to the build system, please open a bug. Thank you!
92 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
93 #define XmlConvert XmlUtf16Convert
94 #define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
95 #define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
96 #define XmlEncode XmlUtf16Encode
97 /* Using pointer subtraction to convert to integer type. */
98 #define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
99 typedef unsigned short ICHAR;
101 #define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
102 #define XmlConvert XmlUtf8Convert
103 #define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
104 #define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
105 #define XmlEncode XmlUtf8Encode
106 #define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
113 #define XmlInitEncodingNS XmlInitEncoding
114 #define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
115 #undef XmlGetInternalEncodingNS
116 #define XmlGetInternalEncodingNS XmlGetInternalEncoding
117 #define XmlParseXmlDeclNS XmlParseXmlDecl
123 #ifdef XML_UNICODE_WCHAR_T
124 #define XML_T(x) (const wchar_t)x
125 #define XML_L(x) L ## x
127 #define XML_T(x) (const unsigned short)x
138 /* Round up n to be a multiple of sz, where sz is a power of 2. */
139 #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
141 /* Handle the case where memmove() doesn't exist. */
144 #define memmove(d,s,l) bcopy((s),(d),(l))
146 #error memmove does not exist on this platform, nor is a substitute available
147 #endif /* HAVE_BCOPY */
148 #endif /* HAVE_MEMMOVE */
150 #include "internal.h"
154 typedef const XML_Char *KEY;
165 const XML_Memory_Handling_Suite *mem;
172 copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key);
174 /* For probing (after a collision) we need a step size relative prime
175 to the hash table size, which is a power of 2. We use double-hashing,
176 since we can calculate a second hash value cheaply by taking those bits
177 of the first hash value that were discarded (masked out) when the table
178 index was calculated: index = hash & mask, where mask = table->size - 1.
179 We limit the maximum step size to table->size / 4 (mask >> 2) and make
180 it odd, since odd numbers are always relative prime to a power of 2.
182 #define SECOND_HASH(hash, mask, power) \
183 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
184 #define PROBE_STEP(hash, mask, power) \
185 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
192 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
193 #define INIT_DATA_BUF_SIZE 1024
194 #define INIT_ATTS_SIZE 16
195 #define INIT_ATTS_VERSION 0xFFFFFFFF
196 #define INIT_BLOCK_SIZE 1024
197 #define INIT_BUFFER_SIZE 1024
199 #define EXPAND_SPARE 24
201 typedef struct binding {
202 struct prefix *prefix;
203 struct binding *nextTagBinding;
204 struct binding *prevPrefixBinding;
205 const struct attribute_id *attId;
211 typedef struct prefix {
212 const XML_Char *name;
218 const XML_Char *localPart;
219 const XML_Char *prefix;
225 /* TAG represents an open element.
226 The name of the element is stored in both the document and API
227 encodings. The memory buffer 'buf' is a separately-allocated
228 memory area which stores the name. During the XML_Parse()/
229 XMLParseBuffer() when the element is open, the memory for the 'raw'
230 version of the name (in the document encoding) is shared with the
231 document buffer. If the element is open across calls to
232 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
233 contain the 'raw' name as well.
235 A parser re-uses these structures, maintaining a list of allocated
236 TAG objects in a free list.
239 struct tag *parent; /* parent of this element */
240 const char *rawName; /* tagName in the original encoding */
242 TAG_NAME name; /* tagName in the API encoding */
243 char *buf; /* buffer for name components */
244 char *bufEnd; /* end of the buffer */
249 const XML_Char *name;
250 const XML_Char *textPtr;
251 int textLen; /* length in XML_Chars */
252 int processed; /* # of processed bytes - when suspended */
253 const XML_Char *systemId;
254 const XML_Char *base;
255 const XML_Char *publicId;
256 const XML_Char *notation;
259 XML_Bool is_internal; /* true if declared in internal subset outside PE */
263 enum XML_Content_Type type;
264 enum XML_Content_Quant quant;
265 const XML_Char * name;
272 #define INIT_SCAFFOLD_ELEMENTS 32
274 typedef struct block {
286 const XML_Memory_Handling_Suite *mem;
289 /* The XML_Char before the name is used to determine whether
290 an attribute has been specified. */
291 typedef struct attribute_id {
294 XML_Bool maybeTokenized;
299 const ATTRIBUTE_ID *id;
301 const XML_Char *value;
305 unsigned long version;
307 const XML_Char *uriName;
311 const XML_Char *name;
313 const ATTRIBUTE_ID *idAtt;
315 int allocDefaultAtts;
316 DEFAULT_ATTRIBUTE *defaultAtts;
320 HASH_TABLE generalEntities;
321 HASH_TABLE elementTypes;
322 HASH_TABLE attributeIds;
325 STRING_POOL entityValuePool;
326 /* false once a parameter entity reference has been skipped */
327 XML_Bool keepProcessing;
328 /* true once an internal or external PE reference has been encountered;
329 this includes the reference to an external subset */
330 XML_Bool hasParamEntityRefs;
333 /* indicates if external PE has been read */
334 XML_Bool paramEntityRead;
335 HASH_TABLE paramEntities;
337 PREFIX defaultPrefix;
338 /* === scaffolding for building content model === */
340 CONTENT_SCAFFOLD *scaffold;
341 unsigned contentStringLen;
348 typedef struct open_internal_entity {
349 const char *internalEventPtr;
350 const char *internalEventEndPtr;
351 struct open_internal_entity *next;
354 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
355 } OPEN_INTERNAL_ENTITY;
357 typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
360 const char **endPtr);
362 static Processor prologProcessor;
363 static Processor prologInitProcessor;
364 static Processor contentProcessor;
365 static Processor cdataSectionProcessor;
367 static Processor ignoreSectionProcessor;
368 static Processor externalParEntProcessor;
369 static Processor externalParEntInitProcessor;
370 static Processor entityValueProcessor;
371 static Processor entityValueInitProcessor;
373 static Processor epilogProcessor;
374 static Processor errorProcessor;
375 static Processor externalEntityInitProcessor;
376 static Processor externalEntityInitProcessor2;
377 static Processor externalEntityInitProcessor3;
378 static Processor externalEntityContentProcessor;
379 static Processor internalEntityProcessor;
381 static enum XML_Error
382 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
383 static enum XML_Error
384 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
385 const char *s, const char *next);
386 static enum XML_Error
387 initializeEncoding(XML_Parser parser);
388 static enum XML_Error
389 doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
390 const char *end, int tok, const char *next, const char **nextPtr,
392 static enum XML_Error
393 processInternalEntity(XML_Parser parser, ENTITY *entity,
394 XML_Bool betweenDecl);
395 static enum XML_Error
396 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
397 const char *start, const char *end, const char **endPtr,
399 static enum XML_Error
400 doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
401 const char *end, const char **nextPtr, XML_Bool haveMore);
403 static enum XML_Error
404 doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
405 const char *end, const char **nextPtr, XML_Bool haveMore);
409 freeBindings(XML_Parser parser, BINDING *bindings);
410 static enum XML_Error
411 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
412 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
413 static enum XML_Error
414 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
415 const XML_Char *uri, BINDING **bindingsPtr);
417 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
418 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
419 static enum XML_Error
420 storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
421 const char *, const char *, STRING_POOL *);
422 static enum XML_Error
423 appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
424 const char *, const char *, STRING_POOL *);
425 static ATTRIBUTE_ID *
426 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
429 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
430 static enum XML_Error
431 storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
434 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
435 const char *start, const char *end);
437 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
440 reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
443 static const XML_Char * getContext(XML_Parser parser);
445 setContext(XML_Parser parser, const XML_Char *context);
447 static void FASTCALL normalizePublicId(XML_Char *s);
449 static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
450 /* do not call if parentParser != NULL */
451 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
453 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
455 dtdCopy(XML_Parser oldParser,
456 DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
458 copyEntityTable(XML_Parser oldParser,
459 HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
461 lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
463 hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
464 static void FASTCALL hashTableClear(HASH_TABLE *);
465 static void FASTCALL hashTableDestroy(HASH_TABLE *);
467 hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
468 static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
471 poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
472 static void FASTCALL poolClear(STRING_POOL *);
473 static void FASTCALL poolDestroy(STRING_POOL *);
475 poolAppend(STRING_POOL *pool, const ENCODING *enc,
476 const char *ptr, const char *end);
478 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
479 const char *ptr, const char *end);
480 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
481 static const XML_Char * FASTCALL
482 poolCopyString(STRING_POOL *pool, const XML_Char *s);
483 static const XML_Char *
484 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
485 static const XML_Char * FASTCALL
486 poolAppendString(STRING_POOL *pool, const XML_Char *s);
488 static int FASTCALL nextScaffoldPart(XML_Parser parser);
489 static XML_Content * build_model(XML_Parser parser);
490 static ELEMENT_TYPE *
491 getElementType(XML_Parser parser, const ENCODING *enc,
492 const char *ptr, const char *end);
494 static XML_Char *copyString(const XML_Char *s,
495 const XML_Memory_Handling_Suite *memsuite);
497 static unsigned long generate_hash_secret_salt(XML_Parser parser);
498 static XML_Bool startParsing(XML_Parser parser);
501 parserCreate(const XML_Char *encodingName,
502 const XML_Memory_Handling_Suite *memsuite,
503 const XML_Char *nameSep,
507 parserInit(XML_Parser parser, const XML_Char *encodingName);
509 #define poolStart(pool) ((pool)->start)
510 #define poolEnd(pool) ((pool)->ptr)
511 #define poolLength(pool) ((pool)->ptr - (pool)->start)
512 #define poolChop(pool) ((void)--(pool->ptr))
513 #define poolLastChar(pool) (((pool)->ptr)[-1])
514 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
515 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
516 #define poolAppendChar(pool, c) \
517 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
519 : ((*((pool)->ptr)++ = c), 1))
521 struct XML_ParserStruct {
522 /* The first member must be userData so that the XML_GetUserData
527 const XML_Memory_Handling_Suite m_mem;
528 /* first character to be parsed */
529 const char *m_bufferPtr;
530 /* past last character to be parsed */
532 /* allocated end of buffer */
533 const char *m_bufferLim;
534 XML_Index m_parseEndByteIndex;
535 const char *m_parseEndPtr;
537 XML_Char *m_dataBufEnd;
538 XML_StartElementHandler m_startElementHandler;
539 XML_EndElementHandler m_endElementHandler;
540 XML_CharacterDataHandler m_characterDataHandler;
541 XML_ProcessingInstructionHandler m_processingInstructionHandler;
542 XML_CommentHandler m_commentHandler;
543 XML_StartCdataSectionHandler m_startCdataSectionHandler;
544 XML_EndCdataSectionHandler m_endCdataSectionHandler;
545 XML_DefaultHandler m_defaultHandler;
546 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
547 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
548 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
549 XML_NotationDeclHandler m_notationDeclHandler;
550 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
551 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
552 XML_NotStandaloneHandler m_notStandaloneHandler;
553 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
554 XML_Parser m_externalEntityRefHandlerArg;
555 XML_SkippedEntityHandler m_skippedEntityHandler;
556 XML_UnknownEncodingHandler m_unknownEncodingHandler;
557 XML_ElementDeclHandler m_elementDeclHandler;
558 XML_AttlistDeclHandler m_attlistDeclHandler;
559 XML_EntityDeclHandler m_entityDeclHandler;
560 XML_XmlDeclHandler m_xmlDeclHandler;
561 const ENCODING *m_encoding;
562 INIT_ENCODING m_initEncoding;
563 const ENCODING *m_internalEncoding;
564 const XML_Char *m_protocolEncodingName;
566 XML_Bool m_ns_triplets;
567 void *m_unknownEncodingMem;
568 void *m_unknownEncodingData;
569 void *m_unknownEncodingHandlerData;
570 void (XMLCALL *m_unknownEncodingRelease)(void *);
571 PROLOG_STATE m_prologState;
572 Processor *m_processor;
573 enum XML_Error m_errorCode;
574 const char *m_eventPtr;
575 const char *m_eventEndPtr;
576 const char *m_positionPtr;
577 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
578 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
579 XML_Bool m_defaultExpandInternalEntities;
581 ENTITY *m_declEntity;
582 const XML_Char *m_doctypeName;
583 const XML_Char *m_doctypeSysid;
584 const XML_Char *m_doctypePubid;
585 const XML_Char *m_declAttributeType;
586 const XML_Char *m_declNotationName;
587 const XML_Char *m_declNotationPublicId;
588 ELEMENT_TYPE *m_declElementType;
589 ATTRIBUTE_ID *m_declAttributeId;
590 XML_Bool m_declAttributeIsCdata;
591 XML_Bool m_declAttributeIsId;
593 const XML_Char *m_curBase;
596 BINDING *m_inheritedBindings;
597 BINDING *m_freeBindingList;
599 int m_nSpecifiedAtts;
603 unsigned long m_nsAttsVersion;
604 unsigned char m_nsAttsPower;
606 XML_AttrInfo *m_attInfo;
609 STRING_POOL m_tempPool;
610 STRING_POOL m_temp2Pool;
611 char *m_groupConnector;
612 unsigned int m_groupSize;
613 XML_Char m_namespaceSeparator;
614 XML_Parser m_parentParser;
615 XML_ParsingStatus m_parsingStatus;
617 XML_Bool m_isParamEntity;
618 XML_Bool m_useForeignDTD;
619 enum XML_ParamEntityParsing m_paramEntityParsing;
621 unsigned long m_hash_secret_salt;
624 #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
625 #define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
626 #define FREE(p) (parser->m_mem.free_fcn((p)))
628 #define userData (parser->m_userData)
629 #define handlerArg (parser->m_handlerArg)
630 #define startElementHandler (parser->m_startElementHandler)
631 #define endElementHandler (parser->m_endElementHandler)
632 #define characterDataHandler (parser->m_characterDataHandler)
633 #define processingInstructionHandler \
634 (parser->m_processingInstructionHandler)
635 #define commentHandler (parser->m_commentHandler)
636 #define startCdataSectionHandler \
637 (parser->m_startCdataSectionHandler)
638 #define endCdataSectionHandler (parser->m_endCdataSectionHandler)
639 #define defaultHandler (parser->m_defaultHandler)
640 #define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
641 #define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
642 #define unparsedEntityDeclHandler \
643 (parser->m_unparsedEntityDeclHandler)
644 #define notationDeclHandler (parser->m_notationDeclHandler)
645 #define startNamespaceDeclHandler \
646 (parser->m_startNamespaceDeclHandler)
647 #define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
648 #define notStandaloneHandler (parser->m_notStandaloneHandler)
649 #define externalEntityRefHandler \
650 (parser->m_externalEntityRefHandler)
651 #define externalEntityRefHandlerArg \
652 (parser->m_externalEntityRefHandlerArg)
653 #define internalEntityRefHandler \
654 (parser->m_internalEntityRefHandler)
655 #define skippedEntityHandler (parser->m_skippedEntityHandler)
656 #define unknownEncodingHandler (parser->m_unknownEncodingHandler)
657 #define elementDeclHandler (parser->m_elementDeclHandler)
658 #define attlistDeclHandler (parser->m_attlistDeclHandler)
659 #define entityDeclHandler (parser->m_entityDeclHandler)
660 #define xmlDeclHandler (parser->m_xmlDeclHandler)
661 #define encoding (parser->m_encoding)
662 #define initEncoding (parser->m_initEncoding)
663 #define internalEncoding (parser->m_internalEncoding)
664 #define unknownEncodingMem (parser->m_unknownEncodingMem)
665 #define unknownEncodingData (parser->m_unknownEncodingData)
666 #define unknownEncodingHandlerData \
667 (parser->m_unknownEncodingHandlerData)
668 #define unknownEncodingRelease (parser->m_unknownEncodingRelease)
669 #define protocolEncodingName (parser->m_protocolEncodingName)
670 #define ns (parser->m_ns)
671 #define ns_triplets (parser->m_ns_triplets)
672 #define prologState (parser->m_prologState)
673 #define processor (parser->m_processor)
674 #define errorCode (parser->m_errorCode)
675 #define eventPtr (parser->m_eventPtr)
676 #define eventEndPtr (parser->m_eventEndPtr)
677 #define positionPtr (parser->m_positionPtr)
678 #define position (parser->m_position)
679 #define openInternalEntities (parser->m_openInternalEntities)
680 #define freeInternalEntities (parser->m_freeInternalEntities)
681 #define defaultExpandInternalEntities \
682 (parser->m_defaultExpandInternalEntities)
683 #define tagLevel (parser->m_tagLevel)
684 #define buffer (parser->m_buffer)
685 #define bufferPtr (parser->m_bufferPtr)
686 #define bufferEnd (parser->m_bufferEnd)
687 #define parseEndByteIndex (parser->m_parseEndByteIndex)
688 #define parseEndPtr (parser->m_parseEndPtr)
689 #define bufferLim (parser->m_bufferLim)
690 #define dataBuf (parser->m_dataBuf)
691 #define dataBufEnd (parser->m_dataBufEnd)
692 #define _dtd (parser->m_dtd)
693 #define curBase (parser->m_curBase)
694 #define declEntity (parser->m_declEntity)
695 #define doctypeName (parser->m_doctypeName)
696 #define doctypeSysid (parser->m_doctypeSysid)
697 #define doctypePubid (parser->m_doctypePubid)
698 #define declAttributeType (parser->m_declAttributeType)
699 #define declNotationName (parser->m_declNotationName)
700 #define declNotationPublicId (parser->m_declNotationPublicId)
701 #define declElementType (parser->m_declElementType)
702 #define declAttributeId (parser->m_declAttributeId)
703 #define declAttributeIsCdata (parser->m_declAttributeIsCdata)
704 #define declAttributeIsId (parser->m_declAttributeIsId)
705 #define freeTagList (parser->m_freeTagList)
706 #define freeBindingList (parser->m_freeBindingList)
707 #define inheritedBindings (parser->m_inheritedBindings)
708 #define tagStack (parser->m_tagStack)
709 #define atts (parser->m_atts)
710 #define attsSize (parser->m_attsSize)
711 #define nSpecifiedAtts (parser->m_nSpecifiedAtts)
712 #define idAttIndex (parser->m_idAttIndex)
713 #define nsAtts (parser->m_nsAtts)
714 #define nsAttsVersion (parser->m_nsAttsVersion)
715 #define nsAttsPower (parser->m_nsAttsPower)
716 #define attInfo (parser->m_attInfo)
717 #define tempPool (parser->m_tempPool)
718 #define temp2Pool (parser->m_temp2Pool)
719 #define groupConnector (parser->m_groupConnector)
720 #define groupSize (parser->m_groupSize)
721 #define namespaceSeparator (parser->m_namespaceSeparator)
722 #define parentParser (parser->m_parentParser)
723 #define ps_parsing (parser->m_parsingStatus.parsing)
724 #define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
726 #define isParamEntity (parser->m_isParamEntity)
727 #define useForeignDTD (parser->m_useForeignDTD)
728 #define paramEntityParsing (parser->m_paramEntityParsing)
730 #define hash_secret_salt (parser->m_hash_secret_salt)
733 XML_ParserCreate(const XML_Char *encodingName)
735 return XML_ParserCreate_MM(encodingName, NULL, NULL);
739 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
743 return XML_ParserCreate_MM(encodingName, NULL, tmp);
746 static const XML_Char implicitContext[] = {
747 ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
748 ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
749 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
750 ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
751 ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
752 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
756 #if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
758 /* Obtain entropy on Linux 3.17+ */
760 writeRandomBytes_getrandom_nonblock(void * target, size_t count) {
761 int success = 0; /* full count bytes written? */
762 size_t bytesWrittenTotal = 0;
763 const unsigned int getrandomFlags = GRND_NONBLOCK;
766 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
767 const size_t bytesToWrite = count - bytesWrittenTotal;
769 const int bytesWrittenMore =
770 #if defined(HAVE_GETRANDOM)
771 getrandom(currentTarget, bytesToWrite, getrandomFlags);
773 syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
776 if (bytesWrittenMore > 0) {
777 bytesWrittenTotal += bytesWrittenMore;
778 if (bytesWrittenTotal >= count)
781 } while (! success && (errno == EINTR));
786 #endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
789 #if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
791 /* Extract entropy from /dev/urandom */
793 writeRandomBytes_dev_urandom(void * target, size_t count) {
794 int success = 0; /* full count bytes written? */
795 size_t bytesWrittenTotal = 0;
797 const int fd = open("/dev/urandom", O_RDONLY);
803 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
804 const size_t bytesToWrite = count - bytesWrittenTotal;
806 const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
808 if (bytesWrittenMore > 0) {
809 bytesWrittenTotal += bytesWrittenMore;
810 if (bytesWrittenTotal >= count)
813 } while (! success && (errno == EINTR));
819 #endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
822 #if defined(HAVE_ARC4RANDOM)
825 writeRandomBytes_arc4random(void * target, size_t count) {
826 size_t bytesWrittenTotal = 0;
828 while (bytesWrittenTotal < count) {
829 const uint32_t random32 = arc4random();
832 for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
833 i++, bytesWrittenTotal++) {
834 const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
835 ((uint8_t *)target)[bytesWrittenTotal] = random8;
840 #endif /* defined(HAVE_ARC4RANDOM) */
845 typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
846 HMODULE _Expat_LoadLibrary(LPCTSTR filename); /* see loadlibrary.c */
848 /* Obtain entropy on Windows XP / Windows Server 2003 and later.
849 * Hint on RtlGenRandom and the following article from libsodium.
851 * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
852 * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
855 writeRandomBytes_RtlGenRandom(void * target, size_t count) {
856 int success = 0; /* full count bytes written? */
857 const HMODULE advapi32 = _Expat_LoadLibrary(TEXT("ADVAPI32.DLL"));
860 const RTLGENRANDOM_FUNC RtlGenRandom
861 = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
863 if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
867 FreeLibrary(advapi32);
876 #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
879 gather_time_entropy(void)
883 GetSystemTimeAsFileTime(&ft); /* never fails */
884 return ft.dwHighDateTime ^ ft.dwLowDateTime;
887 int gettimeofday_res;
889 gettimeofday_res = gettimeofday(&tv, NULL);
892 (void)gettimeofday_res;
894 assert (gettimeofday_res == 0);
895 #endif /* defined(NDEBUG) */
897 /* Microseconds time is <20 bits entropy */
902 #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
906 ENTROPY_DEBUG(const char * label, unsigned long entropy) {
907 const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
908 if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
909 fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
911 (int)sizeof(entropy) * 2, entropy,
912 (unsigned long)sizeof(entropy));
918 generate_hash_secret_salt(XML_Parser parser)
920 unsigned long entropy;
922 #if defined(HAVE_ARC4RANDOM_BUF)
923 arc4random_buf(&entropy, sizeof(entropy));
924 return ENTROPY_DEBUG("arc4random_buf", entropy);
925 #elif defined(HAVE_ARC4RANDOM)
926 writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
927 return ENTROPY_DEBUG("arc4random", entropy);
929 /* Try high quality providers first .. */
931 if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
932 return ENTROPY_DEBUG("RtlGenRandom", entropy);
934 #elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
935 if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
936 return ENTROPY_DEBUG("getrandom", entropy);
939 #if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
940 if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
941 return ENTROPY_DEBUG("/dev/urandom", entropy);
943 #endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
944 /* .. and self-made low quality for backup: */
946 /* Process ID is 0 bits entropy if attacker has local access */
947 entropy = gather_time_entropy() ^ getpid();
949 /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
950 if (sizeof(unsigned long) == 4) {
951 return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
953 return ENTROPY_DEBUG("fallback(8)",
954 entropy * (unsigned long)2305843009213693951ULL);
960 get_hash_secret_salt(XML_Parser parser) {
961 if (parser->m_parentParser != NULL)
962 return get_hash_secret_salt(parser->m_parentParser);
963 return parser->m_hash_secret_salt;
966 static XML_Bool /* only valid for root parser */
967 startParsing(XML_Parser parser)
969 /* hash functions must be initialized before setContext() is called */
970 if (hash_secret_salt == 0)
971 hash_secret_salt = generate_hash_secret_salt(parser);
973 /* implicit context only set for root parser, since child
974 parsers (i.e. external entity parsers) will inherit it
976 return setContext(parser, implicitContext);
982 XML_ParserCreate_MM(const XML_Char *encodingName,
983 const XML_Memory_Handling_Suite *memsuite,
984 const XML_Char *nameSep)
986 return parserCreate(encodingName, memsuite, nameSep, NULL);
990 parserCreate(const XML_Char *encodingName,
991 const XML_Memory_Handling_Suite *memsuite,
992 const XML_Char *nameSep,
998 XML_Memory_Handling_Suite *mtemp;
999 parser = (XML_Parser)
1000 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
1001 if (parser != NULL) {
1002 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
1003 mtemp->malloc_fcn = memsuite->malloc_fcn;
1004 mtemp->realloc_fcn = memsuite->realloc_fcn;
1005 mtemp->free_fcn = memsuite->free_fcn;
1009 XML_Memory_Handling_Suite *mtemp;
1010 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
1011 if (parser != NULL) {
1012 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
1013 mtemp->malloc_fcn = malloc;
1014 mtemp->realloc_fcn = realloc;
1015 mtemp->free_fcn = free;
1025 attsSize = INIT_ATTS_SIZE;
1026 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
1031 #ifdef XML_ATTR_INFO
1032 attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));
1033 if (attInfo == NULL) {
1039 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
1040 if (dataBuf == NULL) {
1042 #ifdef XML_ATTR_INFO
1048 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
1053 _dtd = dtdCreate(&parser->m_mem);
1057 #ifdef XML_ATTR_INFO
1065 freeBindingList = NULL;
1067 freeInternalEntities = NULL;
1070 groupConnector = NULL;
1072 unknownEncodingHandler = NULL;
1073 unknownEncodingHandlerData = NULL;
1075 namespaceSeparator = ASCII_EXCL;
1077 ns_triplets = XML_FALSE;
1083 protocolEncodingName = NULL;
1085 poolInit(&tempPool, &(parser->m_mem));
1086 poolInit(&temp2Pool, &(parser->m_mem));
1087 parserInit(parser, encodingName);
1089 if (encodingName && !protocolEncodingName) {
1090 XML_ParserFree(parser);
1096 internalEncoding = XmlGetInternalEncodingNS();
1097 namespaceSeparator = *nameSep;
1100 internalEncoding = XmlGetInternalEncoding();
1107 parserInit(XML_Parser parser, const XML_Char *encodingName)
1109 processor = prologInitProcessor;
1110 XmlPrologStateInit(&prologState);
1111 if (encodingName != NULL) {
1112 protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1115 XmlInitEncoding(&initEncoding, &encoding, 0);
1118 startElementHandler = NULL;
1119 endElementHandler = NULL;
1120 characterDataHandler = NULL;
1121 processingInstructionHandler = NULL;
1122 commentHandler = NULL;
1123 startCdataSectionHandler = NULL;
1124 endCdataSectionHandler = NULL;
1125 defaultHandler = NULL;
1126 startDoctypeDeclHandler = NULL;
1127 endDoctypeDeclHandler = NULL;
1128 unparsedEntityDeclHandler = NULL;
1129 notationDeclHandler = NULL;
1130 startNamespaceDeclHandler = NULL;
1131 endNamespaceDeclHandler = NULL;
1132 notStandaloneHandler = NULL;
1133 externalEntityRefHandler = NULL;
1134 externalEntityRefHandlerArg = parser;
1135 skippedEntityHandler = NULL;
1136 elementDeclHandler = NULL;
1137 attlistDeclHandler = NULL;
1138 entityDeclHandler = NULL;
1139 xmlDeclHandler = NULL;
1142 parseEndByteIndex = 0;
1144 declElementType = NULL;
1145 declAttributeId = NULL;
1148 doctypeSysid = NULL;
1149 doctypePubid = NULL;
1150 declAttributeType = NULL;
1151 declNotationName = NULL;
1152 declNotationPublicId = NULL;
1153 declAttributeIsCdata = XML_FALSE;
1154 declAttributeIsId = XML_FALSE;
1155 memset(&position, 0, sizeof(POSITION));
1156 errorCode = XML_ERROR_NONE;
1160 openInternalEntities = NULL;
1161 defaultExpandInternalEntities = XML_TRUE;
1164 inheritedBindings = NULL;
1166 unknownEncodingMem = NULL;
1167 unknownEncodingRelease = NULL;
1168 unknownEncodingData = NULL;
1169 parentParser = NULL;
1170 ps_parsing = XML_INITIALIZED;
1172 isParamEntity = XML_FALSE;
1173 useForeignDTD = XML_FALSE;
1174 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
1176 hash_secret_salt = 0;
1179 /* moves list of bindings to freeBindingList */
1180 static void FASTCALL
1181 moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
1184 BINDING *b = bindings;
1185 bindings = bindings->nextTagBinding;
1186 b->nextTagBinding = freeBindingList;
1187 freeBindingList = b;
1192 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
1195 OPEN_INTERNAL_ENTITY *openEntityList;
1202 /* move tagStack to freeTagList */
1206 tStk = tStk->parent;
1207 tag->parent = freeTagList;
1208 moveToFreeBindingList(parser, tag->bindings);
1209 tag->bindings = NULL;
1212 /* move openInternalEntities to freeInternalEntities */
1213 openEntityList = openInternalEntities;
1214 while (openEntityList) {
1215 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
1216 openEntityList = openEntity->next;
1217 openEntity->next = freeInternalEntities;
1218 freeInternalEntities = openEntity;
1220 moveToFreeBindingList(parser, inheritedBindings);
1221 FREE(unknownEncodingMem);
1222 if (unknownEncodingRelease)
1223 unknownEncodingRelease(unknownEncodingData);
1224 poolClear(&tempPool);
1225 poolClear(&temp2Pool);
1226 FREE((void *)protocolEncodingName);
1227 protocolEncodingName = NULL;
1228 parserInit(parser, encodingName);
1229 dtdReset(_dtd, &parser->m_mem);
1233 enum XML_Status XMLCALL
1234 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
1237 return XML_STATUS_ERROR;
1238 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
1239 XXX There's no way for the caller to determine which of the
1240 XXX possible error cases caused the XML_STATUS_ERROR return.
1242 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1243 return XML_STATUS_ERROR;
1245 /* Get rid of any previous encoding name */
1246 FREE((void *)protocolEncodingName);
1248 if (encodingName == NULL)
1249 /* No new encoding name */
1250 protocolEncodingName = NULL;
1252 /* Copy the new encoding name into allocated memory */
1253 protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1254 if (!protocolEncodingName)
1255 return XML_STATUS_ERROR;
1257 return XML_STATUS_OK;
1261 XML_ExternalEntityParserCreate(XML_Parser oldParser,
1262 const XML_Char *context,
1263 const XML_Char *encodingName)
1265 XML_Parser parser = oldParser;
1268 XML_StartElementHandler oldStartElementHandler;
1269 XML_EndElementHandler oldEndElementHandler;
1270 XML_CharacterDataHandler oldCharacterDataHandler;
1271 XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
1272 XML_CommentHandler oldCommentHandler;
1273 XML_StartCdataSectionHandler oldStartCdataSectionHandler;
1274 XML_EndCdataSectionHandler oldEndCdataSectionHandler;
1275 XML_DefaultHandler oldDefaultHandler;
1276 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
1277 XML_NotationDeclHandler oldNotationDeclHandler;
1278 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
1279 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
1280 XML_NotStandaloneHandler oldNotStandaloneHandler;
1281 XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
1282 XML_SkippedEntityHandler oldSkippedEntityHandler;
1283 XML_UnknownEncodingHandler oldUnknownEncodingHandler;
1284 XML_ElementDeclHandler oldElementDeclHandler;
1285 XML_AttlistDeclHandler oldAttlistDeclHandler;
1286 XML_EntityDeclHandler oldEntityDeclHandler;
1287 XML_XmlDeclHandler oldXmlDeclHandler;
1288 ELEMENT_TYPE * oldDeclElementType;
1291 void *oldHandlerArg;
1292 XML_Bool oldDefaultExpandInternalEntities;
1293 XML_Parser oldExternalEntityRefHandlerArg;
1295 enum XML_ParamEntityParsing oldParamEntityParsing;
1296 int oldInEntityValue;
1298 XML_Bool oldns_triplets;
1299 /* Note that the new parser shares the same hash secret as the old
1300 parser, so that dtdCopy and copyEntityTable can lookup values
1301 from hash tables associated with either parser without us having
1302 to worry which hash secrets each table has.
1304 unsigned long oldhash_secret_salt;
1306 /* Validate the oldParser parameter before we pull everything out of it */
1307 if (oldParser == NULL)
1310 /* Stash the original parser contents on the stack */
1312 oldStartElementHandler = startElementHandler;
1313 oldEndElementHandler = endElementHandler;
1314 oldCharacterDataHandler = characterDataHandler;
1315 oldProcessingInstructionHandler = processingInstructionHandler;
1316 oldCommentHandler = commentHandler;
1317 oldStartCdataSectionHandler = startCdataSectionHandler;
1318 oldEndCdataSectionHandler = endCdataSectionHandler;
1319 oldDefaultHandler = defaultHandler;
1320 oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
1321 oldNotationDeclHandler = notationDeclHandler;
1322 oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
1323 oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
1324 oldNotStandaloneHandler = notStandaloneHandler;
1325 oldExternalEntityRefHandler = externalEntityRefHandler;
1326 oldSkippedEntityHandler = skippedEntityHandler;
1327 oldUnknownEncodingHandler = unknownEncodingHandler;
1328 oldElementDeclHandler = elementDeclHandler;
1329 oldAttlistDeclHandler = attlistDeclHandler;
1330 oldEntityDeclHandler = entityDeclHandler;
1331 oldXmlDeclHandler = xmlDeclHandler;
1332 oldDeclElementType = declElementType;
1334 oldUserData = userData;
1335 oldHandlerArg = handlerArg;
1336 oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
1337 oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
1339 oldParamEntityParsing = paramEntityParsing;
1340 oldInEntityValue = prologState.inEntityValue;
1342 oldns_triplets = ns_triplets;
1343 /* Note that the new parser shares the same hash secret as the old
1344 parser, so that dtdCopy and copyEntityTable can lookup values
1345 from hash tables associated with either parser without us having
1346 to worry which hash secrets each table has.
1348 oldhash_secret_salt = hash_secret_salt;
1353 #endif /* XML_DTD */
1355 /* Note that the magical uses of the pre-processor to make field
1356 access look more like C++ require that `parser' be overwritten
1357 here. This makes this function more painful to follow than it
1362 *tmp = namespaceSeparator;
1363 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1366 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1372 startElementHandler = oldStartElementHandler;
1373 endElementHandler = oldEndElementHandler;
1374 characterDataHandler = oldCharacterDataHandler;
1375 processingInstructionHandler = oldProcessingInstructionHandler;
1376 commentHandler = oldCommentHandler;
1377 startCdataSectionHandler = oldStartCdataSectionHandler;
1378 endCdataSectionHandler = oldEndCdataSectionHandler;
1379 defaultHandler = oldDefaultHandler;
1380 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1381 notationDeclHandler = oldNotationDeclHandler;
1382 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1383 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1384 notStandaloneHandler = oldNotStandaloneHandler;
1385 externalEntityRefHandler = oldExternalEntityRefHandler;
1386 skippedEntityHandler = oldSkippedEntityHandler;
1387 unknownEncodingHandler = oldUnknownEncodingHandler;
1388 elementDeclHandler = oldElementDeclHandler;
1389 attlistDeclHandler = oldAttlistDeclHandler;
1390 entityDeclHandler = oldEntityDeclHandler;
1391 xmlDeclHandler = oldXmlDeclHandler;
1392 declElementType = oldDeclElementType;
1393 userData = oldUserData;
1394 if (oldUserData == oldHandlerArg)
1395 handlerArg = userData;
1397 handlerArg = parser;
1398 if (oldExternalEntityRefHandlerArg != oldParser)
1399 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1400 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1401 ns_triplets = oldns_triplets;
1402 hash_secret_salt = oldhash_secret_salt;
1403 parentParser = oldParser;
1405 paramEntityParsing = oldParamEntityParsing;
1406 prologState.inEntityValue = oldInEntityValue;
1408 #endif /* XML_DTD */
1409 if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
1410 || !setContext(parser, context)) {
1411 XML_ParserFree(parser);
1414 processor = externalEntityInitProcessor;
1418 /* The DTD instance referenced by _dtd is shared between the document's
1419 root parser and external PE parsers, therefore one does not need to
1420 call setContext. In addition, one also *must* not call setContext,
1421 because this would overwrite existing prefix->binding pointers in
1422 _dtd with ones that get destroyed with the external PE parser.
1423 This would leave those prefixes with dangling pointers.
1425 isParamEntity = XML_TRUE;
1426 XmlPrologStateInitExternalEntity(&prologState);
1427 processor = externalParEntInitProcessor;
1429 #endif /* XML_DTD */
1433 static void FASTCALL
1434 destroyBindings(BINDING *bindings, XML_Parser parser)
1437 BINDING *b = bindings;
1440 bindings = b->nextTagBinding;
1447 XML_ParserFree(XML_Parser parser)
1450 OPEN_INTERNAL_ENTITY *entityList;
1453 /* free tagStack and freeTagList */
1457 if (tagList == NULL) {
1458 if (freeTagList == NULL)
1460 tagList = freeTagList;
1464 tagList = tagList->parent;
1466 destroyBindings(p->bindings, parser);
1469 /* free openInternalEntities and freeInternalEntities */
1470 entityList = openInternalEntities;
1472 OPEN_INTERNAL_ENTITY *openEntity;
1473 if (entityList == NULL) {
1474 if (freeInternalEntities == NULL)
1476 entityList = freeInternalEntities;
1477 freeInternalEntities = NULL;
1479 openEntity = entityList;
1480 entityList = entityList->next;
1484 destroyBindings(freeBindingList, parser);
1485 destroyBindings(inheritedBindings, parser);
1486 poolDestroy(&tempPool);
1487 poolDestroy(&temp2Pool);
1488 FREE((void *)protocolEncodingName);
1490 /* external parameter entity parsers share the DTD structure
1491 parser->m_dtd with the root parser, so we must not destroy it
1493 if (!isParamEntity && _dtd)
1496 #endif /* XML_DTD */
1497 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
1499 #ifdef XML_ATTR_INFO
1500 FREE((void *)attInfo);
1502 FREE(groupConnector);
1506 FREE(unknownEncodingMem);
1507 if (unknownEncodingRelease)
1508 unknownEncodingRelease(unknownEncodingData);
1513 XML_UseParserAsHandlerArg(XML_Parser parser)
1516 handlerArg = parser;
1519 enum XML_Error XMLCALL
1520 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1523 return XML_ERROR_INVALID_ARGUMENT;
1525 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1526 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1527 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1528 useForeignDTD = useDTD;
1529 return XML_ERROR_NONE;
1531 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1536 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1540 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1541 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1543 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1547 XML_SetUserData(XML_Parser parser, void *p)
1551 if (handlerArg == userData)
1552 handlerArg = userData = p;
1557 enum XML_Status XMLCALL
1558 XML_SetBase(XML_Parser parser, const XML_Char *p)
1561 return XML_STATUS_ERROR;
1563 p = poolCopyString(&_dtd->pool, p);
1565 return XML_STATUS_ERROR;
1570 return XML_STATUS_OK;
1573 const XML_Char * XMLCALL
1574 XML_GetBase(XML_Parser parser)
1582 XML_GetSpecifiedAttributeCount(XML_Parser parser)
1586 return nSpecifiedAtts;
1590 XML_GetIdAttributeIndex(XML_Parser parser)
1597 #ifdef XML_ATTR_INFO
1598 const XML_AttrInfo * XMLCALL
1599 XML_GetAttributeInfo(XML_Parser parser)
1608 XML_SetElementHandler(XML_Parser parser,
1609 XML_StartElementHandler start,
1610 XML_EndElementHandler end)
1614 startElementHandler = start;
1615 endElementHandler = end;
1619 XML_SetStartElementHandler(XML_Parser parser,
1620 XML_StartElementHandler start) {
1622 startElementHandler = start;
1626 XML_SetEndElementHandler(XML_Parser parser,
1627 XML_EndElementHandler end) {
1629 endElementHandler = end;
1633 XML_SetCharacterDataHandler(XML_Parser parser,
1634 XML_CharacterDataHandler handler)
1637 characterDataHandler = handler;
1641 XML_SetProcessingInstructionHandler(XML_Parser parser,
1642 XML_ProcessingInstructionHandler handler)
1645 processingInstructionHandler = handler;
1649 XML_SetCommentHandler(XML_Parser parser,
1650 XML_CommentHandler handler)
1653 commentHandler = handler;
1657 XML_SetCdataSectionHandler(XML_Parser parser,
1658 XML_StartCdataSectionHandler start,
1659 XML_EndCdataSectionHandler end)
1663 startCdataSectionHandler = start;
1664 endCdataSectionHandler = end;
1668 XML_SetStartCdataSectionHandler(XML_Parser parser,
1669 XML_StartCdataSectionHandler start) {
1671 startCdataSectionHandler = start;
1675 XML_SetEndCdataSectionHandler(XML_Parser parser,
1676 XML_EndCdataSectionHandler end) {
1678 endCdataSectionHandler = end;
1682 XML_SetDefaultHandler(XML_Parser parser,
1683 XML_DefaultHandler handler)
1687 defaultHandler = handler;
1688 defaultExpandInternalEntities = XML_FALSE;
1692 XML_SetDefaultHandlerExpand(XML_Parser parser,
1693 XML_DefaultHandler handler)
1697 defaultHandler = handler;
1698 defaultExpandInternalEntities = XML_TRUE;
1702 XML_SetDoctypeDeclHandler(XML_Parser parser,
1703 XML_StartDoctypeDeclHandler start,
1704 XML_EndDoctypeDeclHandler end)
1708 startDoctypeDeclHandler = start;
1709 endDoctypeDeclHandler = end;
1713 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1714 XML_StartDoctypeDeclHandler start) {
1716 startDoctypeDeclHandler = start;
1720 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1721 XML_EndDoctypeDeclHandler end) {
1723 endDoctypeDeclHandler = end;
1727 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1728 XML_UnparsedEntityDeclHandler handler)
1731 unparsedEntityDeclHandler = handler;
1735 XML_SetNotationDeclHandler(XML_Parser parser,
1736 XML_NotationDeclHandler handler)
1739 notationDeclHandler = handler;
1743 XML_SetNamespaceDeclHandler(XML_Parser parser,
1744 XML_StartNamespaceDeclHandler start,
1745 XML_EndNamespaceDeclHandler end)
1749 startNamespaceDeclHandler = start;
1750 endNamespaceDeclHandler = end;
1754 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1755 XML_StartNamespaceDeclHandler start) {
1757 startNamespaceDeclHandler = start;
1761 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1762 XML_EndNamespaceDeclHandler end) {
1764 endNamespaceDeclHandler = end;
1768 XML_SetNotStandaloneHandler(XML_Parser parser,
1769 XML_NotStandaloneHandler handler)
1772 notStandaloneHandler = handler;
1776 XML_SetExternalEntityRefHandler(XML_Parser parser,
1777 XML_ExternalEntityRefHandler handler)
1780 externalEntityRefHandler = handler;
1784 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1789 externalEntityRefHandlerArg = (XML_Parser)arg;
1791 externalEntityRefHandlerArg = parser;
1795 XML_SetSkippedEntityHandler(XML_Parser parser,
1796 XML_SkippedEntityHandler handler)
1799 skippedEntityHandler = handler;
1803 XML_SetUnknownEncodingHandler(XML_Parser parser,
1804 XML_UnknownEncodingHandler handler,
1809 unknownEncodingHandler = handler;
1810 unknownEncodingHandlerData = data;
1814 XML_SetElementDeclHandler(XML_Parser parser,
1815 XML_ElementDeclHandler eldecl)
1818 elementDeclHandler = eldecl;
1822 XML_SetAttlistDeclHandler(XML_Parser parser,
1823 XML_AttlistDeclHandler attdecl)
1826 attlistDeclHandler = attdecl;
1830 XML_SetEntityDeclHandler(XML_Parser parser,
1831 XML_EntityDeclHandler handler)
1834 entityDeclHandler = handler;
1838 XML_SetXmlDeclHandler(XML_Parser parser,
1839 XML_XmlDeclHandler handler) {
1841 xmlDeclHandler = handler;
1845 XML_SetParamEntityParsing(XML_Parser parser,
1846 enum XML_ParamEntityParsing peParsing)
1850 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1851 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1854 paramEntityParsing = peParsing;
1857 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1862 XML_SetHashSalt(XML_Parser parser,
1863 unsigned long hash_salt)
1867 if (parser->m_parentParser)
1868 return XML_SetHashSalt(parser->m_parentParser, hash_salt);
1869 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1870 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1872 hash_secret_salt = hash_salt;
1876 enum XML_Status XMLCALL
1877 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1879 if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
1881 parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
1882 return XML_STATUS_ERROR;
1884 switch (ps_parsing) {
1886 errorCode = XML_ERROR_SUSPENDED;
1887 return XML_STATUS_ERROR;
1889 errorCode = XML_ERROR_FINISHED;
1890 return XML_STATUS_ERROR;
1891 case XML_INITIALIZED:
1892 if (parentParser == NULL && !startParsing(parser)) {
1893 errorCode = XML_ERROR_NO_MEMORY;
1894 return XML_STATUS_ERROR;
1897 ps_parsing = XML_PARSING;
1901 ps_finalBuffer = (XML_Bool)isFinal;
1903 return XML_STATUS_OK;
1904 positionPtr = bufferPtr;
1905 parseEndPtr = bufferEnd;
1907 /* If data are left over from last buffer, and we now know that these
1908 data are the final chunk of input, then we have to check them again
1909 to detect errors based on that fact.
1911 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1913 if (errorCode == XML_ERROR_NONE) {
1914 switch (ps_parsing) {
1916 /* It is hard to be certain, but it seems that this case
1917 * cannot occur. This code is cleaning up a previous parse
1918 * with no new data (since len == 0). Changing the parsing
1919 * state requires getting to execute a handler function, and
1920 * there doesn't seem to be an opportunity for that while in
1921 * this circumstance.
1923 * Given the uncertainty, we retain the code but exclude it
1924 * from coverage tests.
1928 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1929 positionPtr = bufferPtr;
1930 return XML_STATUS_SUSPENDED;
1931 /* LCOV_EXCL_STOP */
1932 case XML_INITIALIZED:
1934 ps_parsing = XML_FINISHED;
1937 return XML_STATUS_OK;
1940 eventEndPtr = eventPtr;
1941 processor = errorProcessor;
1942 return XML_STATUS_ERROR;
1944 #ifndef XML_CONTEXT_BYTES
1945 else if (bufferPtr == bufferEnd) {
1948 enum XML_Status result;
1949 /* Detect overflow (a+b > MAX <==> b > MAX-a) */
1950 if (len > ((XML_Size)-1) / 2 - parseEndByteIndex) {
1951 errorCode = XML_ERROR_NO_MEMORY;
1952 eventPtr = eventEndPtr = NULL;
1953 processor = errorProcessor;
1954 return XML_STATUS_ERROR;
1956 parseEndByteIndex += len;
1958 ps_finalBuffer = (XML_Bool)isFinal;
1960 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
1962 if (errorCode != XML_ERROR_NONE) {
1963 eventEndPtr = eventPtr;
1964 processor = errorProcessor;
1965 return XML_STATUS_ERROR;
1968 switch (ps_parsing) {
1970 result = XML_STATUS_SUSPENDED;
1972 case XML_INITIALIZED:
1975 ps_parsing = XML_FINISHED;
1976 return XML_STATUS_OK;
1980 result = XML_STATUS_OK;
1984 XmlUpdatePosition(encoding, positionPtr, end, &position);
1985 nLeftOver = s + len - end;
1987 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
1988 /* avoid _signed_ integer overflow */
1990 const int bytesToAllocate = (int)((unsigned)len * 2U);
1991 if (bytesToAllocate > 0) {
1992 temp = (buffer == NULL
1993 ? (char *)MALLOC(bytesToAllocate)
1994 : (char *)REALLOC(buffer, bytesToAllocate));
1997 errorCode = XML_ERROR_NO_MEMORY;
1998 eventPtr = eventEndPtr = NULL;
1999 processor = errorProcessor;
2000 return XML_STATUS_ERROR;
2003 bufferLim = buffer + bytesToAllocate;
2005 memcpy(buffer, end, nLeftOver);
2008 bufferEnd = buffer + nLeftOver;
2009 positionPtr = bufferPtr;
2010 parseEndPtr = bufferEnd;
2011 eventPtr = bufferPtr;
2012 eventEndPtr = bufferPtr;
2015 #endif /* not defined XML_CONTEXT_BYTES */
2017 void *buff = XML_GetBuffer(parser, len);
2019 return XML_STATUS_ERROR;
2021 memcpy(buff, s, len);
2022 return XML_ParseBuffer(parser, len, isFinal);
2027 enum XML_Status XMLCALL
2028 XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
2031 enum XML_Status result = XML_STATUS_OK;
2034 return XML_STATUS_ERROR;
2035 switch (ps_parsing) {
2037 errorCode = XML_ERROR_SUSPENDED;
2038 return XML_STATUS_ERROR;
2040 errorCode = XML_ERROR_FINISHED;
2041 return XML_STATUS_ERROR;
2042 case XML_INITIALIZED:
2043 if (parentParser == NULL && !startParsing(parser)) {
2044 errorCode = XML_ERROR_NO_MEMORY;
2045 return XML_STATUS_ERROR;
2048 ps_parsing = XML_PARSING;
2052 positionPtr = start;
2054 parseEndPtr = bufferEnd;
2055 parseEndByteIndex += len;
2056 ps_finalBuffer = (XML_Bool)isFinal;
2058 errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
2060 if (errorCode != XML_ERROR_NONE) {
2061 eventEndPtr = eventPtr;
2062 processor = errorProcessor;
2063 return XML_STATUS_ERROR;
2066 switch (ps_parsing) {
2068 result = XML_STATUS_SUSPENDED;
2070 case XML_INITIALIZED:
2073 ps_parsing = XML_FINISHED;
2076 default: ; /* should not happen */
2080 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
2081 positionPtr = bufferPtr;
2086 XML_GetBuffer(XML_Parser parser, int len)
2091 errorCode = XML_ERROR_NO_MEMORY;
2094 switch (ps_parsing) {
2096 errorCode = XML_ERROR_SUSPENDED;
2099 errorCode = XML_ERROR_FINISHED;
2104 if (len > bufferLim - bufferEnd) {
2105 #ifdef XML_CONTEXT_BYTES
2107 #endif /* defined XML_CONTEXT_BYTES */
2108 /* Do not invoke signed arithmetic overflow: */
2109 int neededSize = (int) ((unsigned)len + (unsigned)(bufferEnd - bufferPtr));
2110 if (neededSize < 0) {
2111 errorCode = XML_ERROR_NO_MEMORY;
2114 #ifdef XML_CONTEXT_BYTES
2115 keep = (int)(bufferPtr - buffer);
2116 if (keep > XML_CONTEXT_BYTES)
2117 keep = XML_CONTEXT_BYTES;
2119 #endif /* defined XML_CONTEXT_BYTES */
2120 if (neededSize <= bufferLim - buffer) {
2121 #ifdef XML_CONTEXT_BYTES
2122 if (keep < bufferPtr - buffer) {
2123 int offset = (int)(bufferPtr - buffer) - keep;
2124 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
2125 bufferEnd -= offset;
2126 bufferPtr -= offset;
2129 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
2130 bufferEnd = buffer + (bufferEnd - bufferPtr);
2132 #endif /* not defined XML_CONTEXT_BYTES */
2136 int bufferSize = (int)(bufferLim - bufferPtr);
2137 if (bufferSize == 0)
2138 bufferSize = INIT_BUFFER_SIZE;
2140 /* Do not invoke signed arithmetic overflow: */
2141 bufferSize = (int) (2U * (unsigned) bufferSize);
2142 } while (bufferSize < neededSize && bufferSize > 0);
2143 if (bufferSize <= 0) {
2144 errorCode = XML_ERROR_NO_MEMORY;
2147 newBuf = (char *)MALLOC(bufferSize);
2149 errorCode = XML_ERROR_NO_MEMORY;
2152 bufferLim = newBuf + bufferSize;
2153 #ifdef XML_CONTEXT_BYTES
2155 int keep = (int)(bufferPtr - buffer);
2156 if (keep > XML_CONTEXT_BYTES)
2157 keep = XML_CONTEXT_BYTES;
2158 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
2161 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
2162 bufferPtr = buffer + keep;
2165 bufferEnd = newBuf + (bufferEnd - bufferPtr);
2166 bufferPtr = buffer = newBuf;
2170 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
2173 bufferEnd = newBuf + (bufferEnd - bufferPtr);
2174 bufferPtr = buffer = newBuf;
2175 #endif /* not defined XML_CONTEXT_BYTES */
2177 eventPtr = eventEndPtr = NULL;
2183 enum XML_Status XMLCALL
2184 XML_StopParser(XML_Parser parser, XML_Bool resumable)
2187 return XML_STATUS_ERROR;
2188 switch (ps_parsing) {
2191 errorCode = XML_ERROR_SUSPENDED;
2192 return XML_STATUS_ERROR;
2194 ps_parsing = XML_FINISHED;
2197 errorCode = XML_ERROR_FINISHED;
2198 return XML_STATUS_ERROR;
2202 if (isParamEntity) {
2203 errorCode = XML_ERROR_SUSPEND_PE;
2204 return XML_STATUS_ERROR;
2207 ps_parsing = XML_SUSPENDED;
2210 ps_parsing = XML_FINISHED;
2212 return XML_STATUS_OK;
2215 enum XML_Status XMLCALL
2216 XML_ResumeParser(XML_Parser parser)
2218 enum XML_Status result = XML_STATUS_OK;
2221 return XML_STATUS_ERROR;
2222 if (ps_parsing != XML_SUSPENDED) {
2223 errorCode = XML_ERROR_NOT_SUSPENDED;
2224 return XML_STATUS_ERROR;
2226 ps_parsing = XML_PARSING;
2228 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
2230 if (errorCode != XML_ERROR_NONE) {
2231 eventEndPtr = eventPtr;
2232 processor = errorProcessor;
2233 return XML_STATUS_ERROR;
2236 switch (ps_parsing) {
2238 result = XML_STATUS_SUSPENDED;
2240 case XML_INITIALIZED:
2242 if (ps_finalBuffer) {
2243 ps_parsing = XML_FINISHED;
2250 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
2251 positionPtr = bufferPtr;
2256 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
2260 assert(status != NULL);
2261 *status = parser->m_parsingStatus;
2264 enum XML_Error XMLCALL
2265 XML_GetErrorCode(XML_Parser parser)
2268 return XML_ERROR_INVALID_ARGUMENT;
2273 XML_GetCurrentByteIndex(XML_Parser parser)
2278 return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr));
2283 XML_GetCurrentByteCount(XML_Parser parser)
2287 if (eventEndPtr && eventPtr)
2288 return (int)(eventEndPtr - eventPtr);
2292 const char * XMLCALL
2293 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
2295 #ifdef XML_CONTEXT_BYTES
2298 if (eventPtr && buffer) {
2300 *offset = (int)(eventPtr - buffer);
2302 *size = (int)(bufferEnd - buffer);
2309 #endif /* defined XML_CONTEXT_BYTES */
2314 XML_GetCurrentLineNumber(XML_Parser parser)
2318 if (eventPtr && eventPtr >= positionPtr) {
2319 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
2320 positionPtr = eventPtr;
2322 return position.lineNumber + 1;
2326 XML_GetCurrentColumnNumber(XML_Parser parser)
2330 if (eventPtr && eventPtr >= positionPtr) {
2331 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
2332 positionPtr = eventPtr;
2334 return position.columnNumber;
2338 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
2345 XML_MemMalloc(XML_Parser parser, size_t size)
2349 return MALLOC(size);
2353 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
2357 return REALLOC(ptr, size);
2361 XML_MemFree(XML_Parser parser, void *ptr)
2368 XML_DefaultCurrent(XML_Parser parser)
2372 if (defaultHandler) {
2373 if (openInternalEntities)
2374 reportDefault(parser,
2376 openInternalEntities->internalEventPtr,
2377 openInternalEntities->internalEventEndPtr);
2379 reportDefault(parser, encoding, eventPtr, eventEndPtr);
2383 const XML_LChar * XMLCALL
2384 XML_ErrorString(enum XML_Error code)
2386 static const XML_LChar* const message[] = {
2388 XML_L("out of memory"),
2389 XML_L("syntax error"),
2390 XML_L("no element found"),
2391 XML_L("not well-formed (invalid token)"),
2392 XML_L("unclosed token"),
2393 XML_L("partial character"),
2394 XML_L("mismatched tag"),
2395 XML_L("duplicate attribute"),
2396 XML_L("junk after document element"),
2397 XML_L("illegal parameter entity reference"),
2398 XML_L("undefined entity"),
2399 XML_L("recursive entity reference"),
2400 XML_L("asynchronous entity"),
2401 XML_L("reference to invalid character number"),
2402 XML_L("reference to binary entity"),
2403 XML_L("reference to external entity in attribute"),
2404 XML_L("XML or text declaration not at start of entity"),
2405 XML_L("unknown encoding"),
2406 XML_L("encoding specified in XML declaration is incorrect"),
2407 XML_L("unclosed CDATA section"),
2408 XML_L("error in processing external entity reference"),
2409 XML_L("document is not standalone"),
2410 XML_L("unexpected parser state - please send a bug report"),
2411 XML_L("entity declared in parameter entity"),
2412 XML_L("requested feature requires XML_DTD support in Expat"),
2413 XML_L("cannot change setting once parsing has begun"),
2414 XML_L("unbound prefix"),
2415 XML_L("must not undeclare prefix"),
2416 XML_L("incomplete markup in parameter entity"),
2417 XML_L("XML declaration not well-formed"),
2418 XML_L("text declaration not well-formed"),
2419 XML_L("illegal character(s) in public id"),
2420 XML_L("parser suspended"),
2421 XML_L("parser not suspended"),
2422 XML_L("parsing aborted"),
2423 XML_L("parsing finished"),
2424 XML_L("cannot suspend in external parameter entity"),
2425 XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
2426 XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
2427 XML_L("prefix must not be bound to one of the reserved namespace names")
2429 if (code > 0 && code < sizeof(message)/sizeof(message[0]))
2430 return message[code];
2434 const XML_LChar * XMLCALL
2435 XML_ExpatVersion(void) {
2437 /* V1 is used to string-ize the version number. However, it would
2438 string-ize the actual version macro *names* unless we get them
2439 substituted before being passed to V1. CPP is defined to expand
2440 a macro, then rescan for more expansions. Thus, we use V2 to expand
2441 the version macros, then CPP will expand the resulting V1() macro
2442 with the correct numerals. */
2443 /* ### I'm assuming cpp is portable in this respect... */
2445 #define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
2446 #define V2(a,b,c) XML_L("expat_")V1(a,b,c)
2448 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
2454 XML_Expat_Version XMLCALL
2455 XML_ExpatVersionInfo(void)
2457 XML_Expat_Version version;
2459 version.major = XML_MAJOR_VERSION;
2460 version.minor = XML_MINOR_VERSION;
2461 version.micro = XML_MICRO_VERSION;
2466 const XML_Feature * XMLCALL
2467 XML_GetFeatureList(void)
2469 static const XML_Feature features[] = {
2470 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2472 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2475 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2477 #ifdef XML_UNICODE_WCHAR_T
2478 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2481 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2483 #ifdef XML_CONTEXT_BYTES
2484 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2488 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2491 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2493 #ifdef XML_LARGE_SIZE
2494 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
2496 #ifdef XML_ATTR_INFO
2497 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2499 {XML_FEATURE_END, NULL, 0}
2505 /* Initially tag->rawName always points into the parse buffer;
2506 for those TAG instances opened while the current parse buffer was
2507 processed, and not yet closed, we need to store tag->rawName in a more
2508 permanent location, since the parse buffer is about to be discarded.
2511 storeRawNames(XML_Parser parser)
2513 TAG *tag = tagStack;
2516 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2517 char *rawNameBuf = tag->buf + nameLen;
2518 /* Stop if already stored. Since tagStack is a stack, we can stop
2519 at the first entry that has already been copied; everything
2520 below it in the stack is already been accounted for in a
2521 previous call to this function.
2523 if (tag->rawName == rawNameBuf)
2525 /* For re-use purposes we need to ensure that the
2526 size of tag->buf is a multiple of sizeof(XML_Char).
2528 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2529 if (bufSize > tag->bufEnd - tag->buf) {
2530 char *temp = (char *)REALLOC(tag->buf, bufSize);
2533 /* if tag->name.str points to tag->buf (only when namespace
2534 processing is off) then we have to update it
2536 if (tag->name.str == (XML_Char *)tag->buf)
2537 tag->name.str = (XML_Char *)temp;
2538 /* if tag->name.localPart is set (when namespace processing is on)
2539 then update it as well, since it will always point into tag->buf
2541 if (tag->name.localPart)
2542 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2543 (XML_Char *)tag->buf);
2545 tag->bufEnd = temp + bufSize;
2546 rawNameBuf = temp + nameLen;
2548 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2549 tag->rawName = rawNameBuf;
2555 static enum XML_Error PTRCALL
2556 contentProcessor(XML_Parser parser,
2559 const char **endPtr)
2561 enum XML_Error result = doContent(parser, 0, encoding, start, end,
2562 endPtr, (XML_Bool)!ps_finalBuffer);
2563 if (result == XML_ERROR_NONE) {
2564 if (!storeRawNames(parser))
2565 return XML_ERROR_NO_MEMORY;
2570 static enum XML_Error PTRCALL
2571 externalEntityInitProcessor(XML_Parser parser,
2574 const char **endPtr)
2576 enum XML_Error result = initializeEncoding(parser);
2577 if (result != XML_ERROR_NONE)
2579 processor = externalEntityInitProcessor2;
2580 return externalEntityInitProcessor2(parser, start, end, endPtr);
2583 static enum XML_Error PTRCALL
2584 externalEntityInitProcessor2(XML_Parser parser,
2587 const char **endPtr)
2589 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2590 int tok = XmlContentTok(encoding, start, end, &next);
2593 /* If we are at the end of the buffer, this would cause the next stage,
2594 i.e. externalEntityInitProcessor3, to pass control directly to
2595 doContent (by detecting XML_TOK_NONE) without processing any xml text
2596 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2598 if (next == end && !ps_finalBuffer) {
2600 return XML_ERROR_NONE;
2604 case XML_TOK_PARTIAL:
2605 if (!ps_finalBuffer) {
2607 return XML_ERROR_NONE;
2610 return XML_ERROR_UNCLOSED_TOKEN;
2611 case XML_TOK_PARTIAL_CHAR:
2612 if (!ps_finalBuffer) {
2614 return XML_ERROR_NONE;
2617 return XML_ERROR_PARTIAL_CHAR;
2619 processor = externalEntityInitProcessor3;
2620 return externalEntityInitProcessor3(parser, start, end, endPtr);
2623 static enum XML_Error PTRCALL
2624 externalEntityInitProcessor3(XML_Parser parser,
2627 const char **endPtr)
2630 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2632 tok = XmlContentTok(encoding, start, end, &next);
2636 case XML_TOK_XML_DECL:
2638 enum XML_Error result;
2639 result = processXmlDecl(parser, 1, start, next);
2640 if (result != XML_ERROR_NONE)
2642 switch (ps_parsing) {
2645 return XML_ERROR_NONE;
2647 return XML_ERROR_ABORTED;
2653 case XML_TOK_PARTIAL:
2654 if (!ps_finalBuffer) {
2656 return XML_ERROR_NONE;
2658 return XML_ERROR_UNCLOSED_TOKEN;
2659 case XML_TOK_PARTIAL_CHAR:
2660 if (!ps_finalBuffer) {
2662 return XML_ERROR_NONE;
2664 return XML_ERROR_PARTIAL_CHAR;
2666 processor = externalEntityContentProcessor;
2668 return externalEntityContentProcessor(parser, start, end, endPtr);
2671 static enum XML_Error PTRCALL
2672 externalEntityContentProcessor(XML_Parser parser,
2675 const char **endPtr)
2677 enum XML_Error result = doContent(parser, 1, encoding, start, end,
2678 endPtr, (XML_Bool)!ps_finalBuffer);
2679 if (result == XML_ERROR_NONE) {
2680 if (!storeRawNames(parser))
2681 return XML_ERROR_NO_MEMORY;
2686 static enum XML_Error
2687 doContent(XML_Parser parser,
2689 const ENCODING *enc,
2692 const char **nextPtr,
2695 /* save one level of indirection */
2696 DTD * const dtd = _dtd;
2698 const char **eventPP;
2699 const char **eventEndPP;
2700 if (enc == encoding) {
2701 eventPP = &eventPtr;
2702 eventEndPP = &eventEndPtr;
2705 eventPP = &(openInternalEntities->internalEventPtr);
2706 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2711 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2712 int tok = XmlContentTok(enc, s, end, &next);
2715 case XML_TOK_TRAILING_CR:
2718 return XML_ERROR_NONE;
2721 if (characterDataHandler) {
2723 characterDataHandler(handlerArg, &c, 1);
2725 else if (defaultHandler)
2726 reportDefault(parser, enc, s, end);
2727 /* We are at the end of the final buffer, should we check for
2728 XML_SUSPENDED, XML_FINISHED?
2730 if (startTagLevel == 0)
2731 return XML_ERROR_NO_ELEMENTS;
2732 if (tagLevel != startTagLevel)
2733 return XML_ERROR_ASYNC_ENTITY;
2735 return XML_ERROR_NONE;
2739 return XML_ERROR_NONE;
2741 if (startTagLevel > 0) {
2742 if (tagLevel != startTagLevel)
2743 return XML_ERROR_ASYNC_ENTITY;
2745 return XML_ERROR_NONE;
2747 return XML_ERROR_NO_ELEMENTS;
2748 case XML_TOK_INVALID:
2750 return XML_ERROR_INVALID_TOKEN;
2751 case XML_TOK_PARTIAL:
2754 return XML_ERROR_NONE;
2756 return XML_ERROR_UNCLOSED_TOKEN;
2757 case XML_TOK_PARTIAL_CHAR:
2760 return XML_ERROR_NONE;
2762 return XML_ERROR_PARTIAL_CHAR;
2763 case XML_TOK_ENTITY_REF:
2765 const XML_Char *name;
2767 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2768 s + enc->minBytesPerChar,
2769 next - enc->minBytesPerChar);
2771 if (characterDataHandler)
2772 characterDataHandler(handlerArg, &ch, 1);
2773 else if (defaultHandler)
2774 reportDefault(parser, enc, s, next);
2777 name = poolStoreString(&dtd->pool, enc,
2778 s + enc->minBytesPerChar,
2779 next - enc->minBytesPerChar);
2781 return XML_ERROR_NO_MEMORY;
2782 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
2783 poolDiscard(&dtd->pool);
2784 /* First, determine if a check for an existing declaration is needed;
2785 if yes, check that the entity exists, and that it is internal,
2786 otherwise call the skipped entity or default handler.
2788 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2790 return XML_ERROR_UNDEFINED_ENTITY;
2791 else if (!entity->is_internal)
2792 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2795 if (skippedEntityHandler)
2796 skippedEntityHandler(handlerArg, name, 0);
2797 else if (defaultHandler)
2798 reportDefault(parser, enc, s, next);
2802 return XML_ERROR_RECURSIVE_ENTITY_REF;
2803 if (entity->notation)
2804 return XML_ERROR_BINARY_ENTITY_REF;
2805 if (entity->textPtr) {
2806 enum XML_Error result;
2807 if (!defaultExpandInternalEntities) {
2808 if (skippedEntityHandler)
2809 skippedEntityHandler(handlerArg, entity->name, 0);
2810 else if (defaultHandler)
2811 reportDefault(parser, enc, s, next);
2814 result = processInternalEntity(parser, entity, XML_FALSE);
2815 if (result != XML_ERROR_NONE)
2818 else if (externalEntityRefHandler) {
2819 const XML_Char *context;
2820 entity->open = XML_TRUE;
2821 context = getContext(parser);
2822 entity->open = XML_FALSE;
2824 return XML_ERROR_NO_MEMORY;
2825 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
2830 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2831 poolDiscard(&tempPool);
2833 else if (defaultHandler)
2834 reportDefault(parser, enc, s, next);
2837 case XML_TOK_START_TAG_NO_ATTS:
2839 case XML_TOK_START_TAG_WITH_ATTS:
2842 enum XML_Error result;
2846 freeTagList = freeTagList->parent;
2849 tag = (TAG *)MALLOC(sizeof(TAG));
2851 return XML_ERROR_NO_MEMORY;
2852 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
2855 return XML_ERROR_NO_MEMORY;
2857 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2859 tag->bindings = NULL;
2860 tag->parent = tagStack;
2862 tag->name.localPart = NULL;
2863 tag->name.prefix = NULL;
2864 tag->rawName = s + enc->minBytesPerChar;
2865 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2868 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2869 const char *fromPtr = tag->rawName;
2870 toPtr = (XML_Char *)tag->buf;
2874 const enum XML_Convert_Result convert_res = XmlConvert(enc,
2875 &fromPtr, rawNameEnd,
2876 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2877 convLen = (int)(toPtr - (XML_Char *)tag->buf);
2878 if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
2879 tag->name.strLen = convLen;
2882 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2884 char *temp = (char *)REALLOC(tag->buf, bufSize);
2886 return XML_ERROR_NO_MEMORY;
2888 tag->bufEnd = temp + bufSize;
2889 toPtr = (XML_Char *)temp + convLen;
2893 tag->name.str = (XML_Char *)tag->buf;
2894 *toPtr = XML_T('\0');
2895 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2898 if (startElementHandler)
2899 startElementHandler(handlerArg, tag->name.str,
2900 (const XML_Char **)atts);
2901 else if (defaultHandler)
2902 reportDefault(parser, enc, s, next);
2903 poolClear(&tempPool);
2906 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2908 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2910 const char *rawName = s + enc->minBytesPerChar;
2911 enum XML_Error result;
2912 BINDING *bindings = NULL;
2913 XML_Bool noElmHandlers = XML_TRUE;
2915 name.str = poolStoreString(&tempPool, enc, rawName,
2916 rawName + XmlNameLength(enc, rawName));
2918 return XML_ERROR_NO_MEMORY;
2919 poolFinish(&tempPool);
2920 result = storeAtts(parser, enc, s, &name, &bindings);
2921 if (result != XML_ERROR_NONE) {
2922 freeBindings(parser, bindings);
2925 poolFinish(&tempPool);
2926 if (startElementHandler) {
2927 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
2928 noElmHandlers = XML_FALSE;
2930 if (endElementHandler) {
2931 if (startElementHandler)
2932 *eventPP = *eventEndPP;
2933 endElementHandler(handlerArg, name.str);
2934 noElmHandlers = XML_FALSE;
2936 if (noElmHandlers && defaultHandler)
2937 reportDefault(parser, enc, s, next);
2938 poolClear(&tempPool);
2939 freeBindings(parser, bindings);
2942 return epilogProcessor(parser, next, end, nextPtr);
2944 case XML_TOK_END_TAG:
2945 if (tagLevel == startTagLevel)
2946 return XML_ERROR_ASYNC_ENTITY;
2949 const char *rawName;
2950 TAG *tag = tagStack;
2951 tagStack = tag->parent;
2952 tag->parent = freeTagList;
2954 rawName = s + enc->minBytesPerChar*2;
2955 len = XmlNameLength(enc, rawName);
2956 if (len != tag->rawNameLength
2957 || memcmp(tag->rawName, rawName, len) != 0) {
2959 return XML_ERROR_TAG_MISMATCH;
2962 if (endElementHandler) {
2963 const XML_Char *localPart;
2964 const XML_Char *prefix;
2966 localPart = tag->name.localPart;
2967 if (ns && localPart) {
2968 /* localPart and prefix may have been overwritten in
2969 tag->name.str, since this points to the binding->uri
2970 buffer which gets re-used; so we have to add them again
2972 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2973 /* don't need to check for space - already done in storeAtts() */
2974 while (*localPart) *uri++ = *localPart++;
2975 prefix = (XML_Char *)tag->name.prefix;
2976 if (ns_triplets && prefix) {
2977 *uri++ = namespaceSeparator;
2978 while (*prefix) *uri++ = *prefix++;
2982 endElementHandler(handlerArg, tag->name.str);
2984 else if (defaultHandler)
2985 reportDefault(parser, enc, s, next);
2986 while (tag->bindings) {
2987 BINDING *b = tag->bindings;
2988 if (endNamespaceDeclHandler)
2989 endNamespaceDeclHandler(handlerArg, b->prefix->name);
2990 tag->bindings = tag->bindings->nextTagBinding;
2991 b->nextTagBinding = freeBindingList;
2992 freeBindingList = b;
2993 b->prefix->binding = b->prevPrefixBinding;
2996 return epilogProcessor(parser, next, end, nextPtr);
2999 case XML_TOK_CHAR_REF:
3001 int n = XmlCharRefNumber(enc, s);
3003 return XML_ERROR_BAD_CHAR_REF;
3004 if (characterDataHandler) {
3005 XML_Char buf[XML_ENCODE_MAX];
3006 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
3008 else if (defaultHandler)
3009 reportDefault(parser, enc, s, next);
3012 case XML_TOK_XML_DECL:
3013 return XML_ERROR_MISPLACED_XML_PI;
3014 case XML_TOK_DATA_NEWLINE:
3015 if (characterDataHandler) {
3017 characterDataHandler(handlerArg, &c, 1);
3019 else if (defaultHandler)
3020 reportDefault(parser, enc, s, next);
3022 case XML_TOK_CDATA_SECT_OPEN:
3024 enum XML_Error result;
3025 if (startCdataSectionHandler)
3026 startCdataSectionHandler(handlerArg);
3028 /* Suppose you doing a transformation on a document that involves
3029 changing only the character data. You set up a defaultHandler
3030 and a characterDataHandler. The defaultHandler simply copies
3031 characters through. The characterDataHandler does the
3032 transformation and writes the characters out escaping them as
3033 necessary. This case will fail to work if we leave out the
3034 following two lines (because & and < inside CDATA sections will
3035 be incorrectly escaped).
3037 However, now we have a start/endCdataSectionHandler, so it seems
3038 easier to let the user deal with this.
3040 else if (characterDataHandler)
3041 characterDataHandler(handlerArg, dataBuf, 0);
3043 else if (defaultHandler)
3044 reportDefault(parser, enc, s, next);
3045 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
3046 if (result != XML_ERROR_NONE)
3049 processor = cdataSectionProcessor;
3054 case XML_TOK_TRAILING_RSQB:
3057 return XML_ERROR_NONE;
3059 if (characterDataHandler) {
3060 if (MUST_CONVERT(enc, s)) {
3061 ICHAR *dataPtr = (ICHAR *)dataBuf;
3062 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
3063 characterDataHandler(handlerArg, dataBuf,
3064 (int)(dataPtr - (ICHAR *)dataBuf));
3067 characterDataHandler(handlerArg,
3069 (int)((XML_Char *)end - (XML_Char *)s));
3071 else if (defaultHandler)
3072 reportDefault(parser, enc, s, end);
3073 /* We are at the end of the final buffer, should we check for
3074 XML_SUSPENDED, XML_FINISHED?
3076 if (startTagLevel == 0) {
3078 return XML_ERROR_NO_ELEMENTS;
3080 if (tagLevel != startTagLevel) {
3082 return XML_ERROR_ASYNC_ENTITY;
3085 return XML_ERROR_NONE;
3086 case XML_TOK_DATA_CHARS:
3088 XML_CharacterDataHandler charDataHandler = characterDataHandler;
3089 if (charDataHandler) {
3090 if (MUST_CONVERT(enc, s)) {
3092 ICHAR *dataPtr = (ICHAR *)dataBuf;
3093 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3095 charDataHandler(handlerArg, dataBuf,
3096 (int)(dataPtr - (ICHAR *)dataBuf));
3097 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3103 charDataHandler(handlerArg,
3105 (int)((XML_Char *)next - (XML_Char *)s));
3107 else if (defaultHandler)
3108 reportDefault(parser, enc, s, next);
3112 if (!reportProcessingInstruction(parser, enc, s, next))
3113 return XML_ERROR_NO_MEMORY;
3115 case XML_TOK_COMMENT:
3116 if (!reportComment(parser, enc, s, next))
3117 return XML_ERROR_NO_MEMORY;
3120 /* All of the tokens produced by XmlContentTok() have their own
3121 * explicit cases, so this default is not strictly necessary.
3122 * However it is a useful safety net, so we retain the code and
3123 * simply exclude it from the coverage tests.
3128 reportDefault(parser, enc, s, next);
3130 /* LCOV_EXCL_STOP */
3132 *eventPP = s = next;
3133 switch (ps_parsing) {
3136 return XML_ERROR_NONE;
3138 return XML_ERROR_ABORTED;
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.
3150 freeBindings(XML_Parser parser, BINDING *bindings)
3153 BINDING *b = bindings;
3155 /* startNamespaceDeclHandler will have been called for this
3156 * binding in addBindings(), so call the end handler now.
3158 if (endNamespaceDeclHandler)
3159 endNamespaceDeclHandler(handlerArg, b->prefix->name);
3161 bindings = bindings->nextTagBinding;
3162 b->nextTagBinding = freeBindingList;
3163 freeBindingList = b;
3164 b->prefix->binding = b->prevPrefixBinding;
3168 /* Precondition: all arguments must be non-NULL;
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)
3178 static enum XML_Error
3179 storeAtts(XML_Parser parser, const ENCODING *enc,
3180 const char *attStr, TAG_NAME *tagNamePtr,
3181 BINDING **bindingsPtr)
3183 DTD * const dtd = _dtd; /* save one level of indirection */
3184 ELEMENT_TYPE *elementType;
3186 const XML_Char **appAtts; /* the attribute list for the application */
3194 const XML_Char *localPart;
3196 /* lookup the element type name */
3197 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
3199 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
3201 return XML_ERROR_NO_MEMORY;
3202 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
3203 sizeof(ELEMENT_TYPE));
3205 return XML_ERROR_NO_MEMORY;
3206 if (ns && !setElementTypePrefix(parser, elementType))
3207 return XML_ERROR_NO_MEMORY;
3209 nDefaultAtts = elementType->nDefaultAtts;
3211 /* get the attributes from the tokenizer */
3212 n = XmlGetAttributes(enc, attStr, attsSize, atts);
3213 if (n + nDefaultAtts > attsSize) {
3214 int oldAttsSize = attsSize;
3216 #ifdef XML_ATTR_INFO
3217 XML_AttrInfo *temp2;
3219 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
3220 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
3222 attsSize = oldAttsSize;
3223 return XML_ERROR_NO_MEMORY;
3226 #ifdef XML_ATTR_INFO
3227 temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));
3228 if (temp2 == NULL) {
3229 attsSize = oldAttsSize;
3230 return XML_ERROR_NO_MEMORY;
3234 if (n > oldAttsSize)
3235 XmlGetAttributes(enc, attStr, n, atts);
3238 appAtts = (const XML_Char **)atts;
3239 for (i = 0; i < n; i++) {
3240 ATTRIBUTE *currAtt = &atts[i];
3241 #ifdef XML_ATTR_INFO
3242 XML_AttrInfo *currAttInfo = &attInfo[i];
3244 /* add the name and value to the attribute list */
3245 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
3247 + XmlNameLength(enc, currAtt->name));
3249 return XML_ERROR_NO_MEMORY;
3250 #ifdef XML_ATTR_INFO
3251 currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);
3252 currAttInfo->nameEnd = currAttInfo->nameStart +
3253 XmlNameLength(enc, currAtt->name);
3254 currAttInfo->valueStart = parseEndByteIndex -
3255 (parseEndPtr - currAtt->valuePtr);
3256 currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);
3258 /* Detect duplicate attributes by their QNames. This does not work when
3259 namespace processing is turned on and different prefixes for the same
3260 namespace are used. For this case we have a check further down.
3262 if ((attId->name)[-1]) {
3263 if (enc == encoding)
3264 eventPtr = atts[i].name;
3265 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3267 (attId->name)[-1] = 1;
3268 appAtts[attIndex++] = attId->name;
3269 if (!atts[i].normalized) {
3270 enum XML_Error result;
3271 XML_Bool isCdata = XML_TRUE;
3273 /* figure out whether declared as other than CDATA */
3274 if (attId->maybeTokenized) {
3276 for (j = 0; j < nDefaultAtts; j++) {
3277 if (attId == elementType->defaultAtts[j].id) {
3278 isCdata = elementType->defaultAtts[j].isCdata;
3284 /* normalize the attribute value */
3285 result = storeAttributeValue(parser, enc, isCdata,
3286 atts[i].valuePtr, atts[i].valueEnd,
3290 appAtts[attIndex] = poolStart(&tempPool);
3291 poolFinish(&tempPool);
3294 /* the value did not need normalizing */
3295 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
3297 if (appAtts[attIndex] == 0)
3298 return XML_ERROR_NO_MEMORY;
3299 poolFinish(&tempPool);
3301 /* handle prefixed attribute names */
3302 if (attId->prefix) {
3304 /* deal with namespace declarations here */
3305 enum XML_Error result = addBinding(parser, attId->prefix, attId,
3306 appAtts[attIndex], bindingsPtr);
3312 /* deal with other prefixed names later */
3315 (attId->name)[-1] = 2;
3322 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
3323 nSpecifiedAtts = attIndex;
3324 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
3325 for (i = 0; i < attIndex; i += 2)
3326 if (appAtts[i] == elementType->idAtt->name) {
3334 /* do attribute defaulting */
3335 for (i = 0; i < nDefaultAtts; i++) {
3336 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
3337 if (!(da->id->name)[-1] && da->value) {
3338 if (da->id->prefix) {
3339 if (da->id->xmlns) {
3340 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
3341 da->value, bindingsPtr);
3346 (da->id->name)[-1] = 2;
3348 appAtts[attIndex++] = da->id->name;
3349 appAtts[attIndex++] = da->value;
3353 (da->id->name)[-1] = 1;
3354 appAtts[attIndex++] = da->id->name;
3355 appAtts[attIndex++] = da->value;
3359 appAtts[attIndex] = 0;
3361 /* expand prefixed attribute names, check for duplicates,
3362 and clear flags that say whether attributes were specified */
3365 int j; /* hash table index */
3366 unsigned long version = nsAttsVersion;
3367 int nsAttsSize = (int)1 << nsAttsPower;
3368 unsigned char oldNsAttsPower = nsAttsPower;
3369 /* size of hash table must be at least 2 * (# of prefixed attributes) */
3370 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
3372 /* hash table size must also be a power of 2 and >= 8 */
3373 while (nPrefixes >> nsAttsPower++);
3374 if (nsAttsPower < 3)
3376 nsAttsSize = (int)1 << nsAttsPower;
3377 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
3379 /* Restore actual size of memory in nsAtts */
3380 nsAttsPower = oldNsAttsPower;
3381 return XML_ERROR_NO_MEMORY;
3384 version = 0; /* force re-initialization of nsAtts hash table */
3386 /* using a version flag saves us from initializing nsAtts every time */
3387 if (!version) { /* initialize version flags when version wraps around */
3388 version = INIT_ATTS_VERSION;
3389 for (j = nsAttsSize; j != 0; )
3390 nsAtts[--j].version = version;
3392 nsAttsVersion = --version;
3394 /* expand prefixed names and check for duplicates */
3395 for (; i < attIndex; i += 2) {
3396 const XML_Char *s = appAtts[i];
3397 if (s[-1] == 2) { /* prefixed */
3400 unsigned long uriHash;
3401 struct siphash sip_state;
3402 struct sipkey sip_key;
3404 copy_salt_to_sipkey(parser, &sip_key);
3405 sip24_init(&sip_state, &sip_key);
3407 ((XML_Char *)s)[-1] = 0; /* clear flag */
3408 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
3409 if (!id || !id->prefix) {
3410 /* This code is walking through the appAtts array, dealing
3411 * with (in this case) a prefixed attribute name. To be in
3412 * the array, the attribute must have already been bound, so
3413 * has to have passed through the hash table lookup once
3414 * already. That implies that an entry for it already
3415 * exists, so the lookup above will return a pointer to
3416 * already allocated memory. There is no opportunaity for
3417 * the allocator to fail, so the condition above cannot be
3420 * Since it is difficult to be certain that the above
3421 * analysis is complete, we retain the test and merely
3422 * remove the code from coverage tests.
3424 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
3426 b = id->prefix->binding;
3428 return XML_ERROR_UNBOUND_PREFIX;
3430 for (j = 0; j < b->uriLen; j++) {
3431 const XML_Char c = b->uri[j];
3432 if (!poolAppendChar(&tempPool, c))
3433 return XML_ERROR_NO_MEMORY;
3436 sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
3438 while (*s++ != XML_T(ASCII_COLON))
3441 sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
3443 do { /* copies null terminator */
3444 if (!poolAppendChar(&tempPool, *s))
3445 return XML_ERROR_NO_MEMORY;
3448 uriHash = (unsigned long)sip24_final(&sip_state);
3450 { /* Check hash table for duplicate of expanded name (uriName).
3451 Derived from code in lookup(parser, HASH_TABLE *table, ...).
3453 unsigned char step = 0;
3454 unsigned long mask = nsAttsSize - 1;
3455 j = uriHash & mask; /* index into hash table */
3456 while (nsAtts[j].version == version) {
3457 /* for speed we compare stored hash values first */
3458 if (uriHash == nsAtts[j].hash) {
3459 const XML_Char *s1 = poolStart(&tempPool);
3460 const XML_Char *s2 = nsAtts[j].uriName;
3461 /* s1 is null terminated, but not s2 */
3462 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
3464 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3467 step = PROBE_STEP(uriHash, mask, nsAttsPower);
3468 j < step ? (j += nsAttsSize - step) : (j -= step);
3472 if (ns_triplets) { /* append namespace separator and prefix */
3473 tempPool.ptr[-1] = namespaceSeparator;
3474 s = b->prefix->name;
3476 if (!poolAppendChar(&tempPool, *s))
3477 return XML_ERROR_NO_MEMORY;
3481 /* store expanded name in attribute list */
3482 s = poolStart(&tempPool);
3483 poolFinish(&tempPool);
3486 /* fill empty slot with new version, uriName and hash value */
3487 nsAtts[j].version = version;
3488 nsAtts[j].hash = uriHash;
3489 nsAtts[j].uriName = s;
3496 else /* not prefixed */
3497 ((XML_Char *)s)[-1] = 0; /* clear flag */
3500 /* clear flags for the remaining attributes */
3501 for (; i < attIndex; i += 2)
3502 ((XML_Char *)(appAtts[i]))[-1] = 0;
3503 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3504 binding->attId->name[-1] = 0;
3507 return XML_ERROR_NONE;
3509 /* expand the element type name */
3510 if (elementType->prefix) {
3511 binding = elementType->prefix->binding;
3513 return XML_ERROR_UNBOUND_PREFIX;
3514 localPart = tagNamePtr->str;
3515 while (*localPart++ != XML_T(ASCII_COLON))
3518 else if (dtd->defaultPrefix.binding) {
3519 binding = dtd->defaultPrefix.binding;
3520 localPart = tagNamePtr->str;
3523 return XML_ERROR_NONE;
3525 if (ns_triplets && binding->prefix->name) {
3526 for (; binding->prefix->name[prefixLen++];)
3527 ; /* prefixLen includes null terminator */
3529 tagNamePtr->localPart = localPart;
3530 tagNamePtr->uriLen = binding->uriLen;
3531 tagNamePtr->prefix = binding->prefix->name;
3532 tagNamePtr->prefixLen = prefixLen;
3533 for (i = 0; localPart[i++];)
3534 ; /* i includes null terminator */
3535 n = i + binding->uriLen + prefixLen;
3536 if (n > binding->uriAlloc) {
3538 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
3540 return XML_ERROR_NO_MEMORY;
3541 binding->uriAlloc = n + EXPAND_SPARE;
3542 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
3543 for (p = tagStack; p; p = p->parent)
3544 if (p->name.str == binding->uri)
3549 /* if namespaceSeparator != '\0' then uri includes it already */
3550 uri = binding->uri + binding->uriLen;
3551 memcpy(uri, localPart, i * sizeof(XML_Char));
3552 /* we always have a namespace separator between localPart and prefix */
3555 *uri = namespaceSeparator; /* replace null terminator */
3556 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3558 tagNamePtr->str = binding->uri;
3559 return XML_ERROR_NONE;
3562 /* addBinding() overwrites the value of prefix->binding without checking.
3563 Therefore one must keep track of the old value outside of addBinding().
3565 static enum XML_Error
3566 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3567 const XML_Char *uri, BINDING **bindingsPtr)
3569 static const XML_Char xmlNamespace[] = {
3570 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3571 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3572 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
3573 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
3574 ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
3577 static const int xmlLen =
3578 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
3579 static const XML_Char xmlnsNamespace[] = {
3580 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3581 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3582 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
3583 ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
3586 static const int xmlnsLen =
3587 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
3589 XML_Bool mustBeXML = XML_FALSE;
3590 XML_Bool isXML = XML_TRUE;
3591 XML_Bool isXMLNS = XML_TRUE;
3596 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3597 if (*uri == XML_T('\0') && prefix->name)
3598 return XML_ERROR_UNDECLARING_PREFIX;
3601 && prefix->name[0] == XML_T(ASCII_x)
3602 && prefix->name[1] == XML_T(ASCII_m)
3603 && prefix->name[2] == XML_T(ASCII_l)) {
3605 /* Not allowed to bind xmlns */
3606 if (prefix->name[3] == XML_T(ASCII_n)
3607 && prefix->name[4] == XML_T(ASCII_s)
3608 && prefix->name[5] == XML_T('\0'))
3609 return XML_ERROR_RESERVED_PREFIX_XMLNS;
3611 if (prefix->name[3] == XML_T('\0'))
3612 mustBeXML = XML_TRUE;
3615 for (len = 0; uri[len]; len++) {
3616 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3619 if (!mustBeXML && isXMLNS
3620 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3621 isXMLNS = XML_FALSE;
3623 isXML = isXML && len == xmlLen;
3624 isXMLNS = isXMLNS && len == xmlnsLen;
3626 if (mustBeXML != isXML)
3627 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3628 : XML_ERROR_RESERVED_NAMESPACE_URI;
3631 return XML_ERROR_RESERVED_NAMESPACE_URI;
3633 if (namespaceSeparator)
3635 if (freeBindingList) {
3636 b = freeBindingList;
3637 if (len > b->uriAlloc) {
3638 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
3639 sizeof(XML_Char) * (len + EXPAND_SPARE));
3641 return XML_ERROR_NO_MEMORY;
3643 b->uriAlloc = len + EXPAND_SPARE;
3645 freeBindingList = b->nextTagBinding;
3648 b = (BINDING *)MALLOC(sizeof(BINDING));
3650 return XML_ERROR_NO_MEMORY;
3651 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
3654 return XML_ERROR_NO_MEMORY;
3656 b->uriAlloc = len + EXPAND_SPARE;
3659 memcpy(b->uri, uri, len * sizeof(XML_Char));
3660 if (namespaceSeparator)
3661 b->uri[len - 1] = namespaceSeparator;
3664 b->prevPrefixBinding = prefix->binding;
3665 /* NULL binding when default namespace undeclared */
3666 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
3667 prefix->binding = NULL;
3669 prefix->binding = b;
3670 b->nextTagBinding = *bindingsPtr;
3672 /* if attId == NULL then we are not starting a namespace scope */
3673 if (attId && startNamespaceDeclHandler)
3674 startNamespaceDeclHandler(handlerArg, prefix->name,
3675 prefix->binding ? uri : 0);
3676 return XML_ERROR_NONE;
3679 /* The idea here is to avoid using stack for each CDATA section when
3680 the whole file is parsed with one call.
3682 static enum XML_Error PTRCALL
3683 cdataSectionProcessor(XML_Parser parser,
3686 const char **endPtr)
3688 enum XML_Error result = doCdataSection(parser, encoding, &start, end,
3689 endPtr, (XML_Bool)!ps_finalBuffer);
3690 if (result != XML_ERROR_NONE)
3693 if (parentParser) { /* we are parsing an external entity */
3694 processor = externalEntityContentProcessor;
3695 return externalEntityContentProcessor(parser, start, end, endPtr);
3698 processor = contentProcessor;
3699 return contentProcessor(parser, start, end, endPtr);
3705 /* startPtr gets set to non-null if the section is closed, and to null if
3706 the section is not yet closed.
3708 static enum XML_Error
3709 doCdataSection(XML_Parser parser,
3710 const ENCODING *enc,
3711 const char **startPtr,
3713 const char **nextPtr,
3716 const char *s = *startPtr;
3717 const char **eventPP;
3718 const char **eventEndPP;
3719 if (enc == encoding) {
3720 eventPP = &eventPtr;
3722 eventEndPP = &eventEndPtr;
3725 eventPP = &(openInternalEntities->internalEventPtr);
3726 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3733 int tok = XmlCdataSectionTok(enc, s, end, &next);
3736 case XML_TOK_CDATA_SECT_CLOSE:
3737 if (endCdataSectionHandler)
3738 endCdataSectionHandler(handlerArg);
3740 /* see comment under XML_TOK_CDATA_SECT_OPEN */
3741 else if (characterDataHandler)
3742 characterDataHandler(handlerArg, dataBuf, 0);
3744 else if (defaultHandler)
3745 reportDefault(parser, enc, s, next);
3748 if (ps_parsing == XML_FINISHED)
3749 return XML_ERROR_ABORTED;
3751 return XML_ERROR_NONE;
3752 case XML_TOK_DATA_NEWLINE:
3753 if (characterDataHandler) {
3755 characterDataHandler(handlerArg, &c, 1);
3757 else if (defaultHandler)
3758 reportDefault(parser, enc, s, next);
3760 case XML_TOK_DATA_CHARS:
3762 XML_CharacterDataHandler charDataHandler = characterDataHandler;
3763 if (charDataHandler) {
3764 if (MUST_CONVERT(enc, s)) {
3766 ICHAR *dataPtr = (ICHAR *)dataBuf;
3767 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3769 charDataHandler(handlerArg, dataBuf,
3770 (int)(dataPtr - (ICHAR *)dataBuf));
3771 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3777 charDataHandler(handlerArg,
3779 (int)((XML_Char *)next - (XML_Char *)s));
3781 else if (defaultHandler)
3782 reportDefault(parser, enc, s, next);
3785 case XML_TOK_INVALID:
3787 return XML_ERROR_INVALID_TOKEN;
3788 case XML_TOK_PARTIAL_CHAR:
3791 return XML_ERROR_NONE;
3793 return XML_ERROR_PARTIAL_CHAR;
3794 case XML_TOK_PARTIAL:
3798 return XML_ERROR_NONE;
3800 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3802 /* Every token returned by XmlCdataSectionTok() has its own
3803 * explicit case, so this default case will never be executed.
3804 * We retain it as a safety net and exclude it from the coverage
3810 return XML_ERROR_UNEXPECTED_STATE;
3811 /* LCOV_EXCL_STOP */
3814 *eventPP = s = next;
3815 switch (ps_parsing) {
3818 return XML_ERROR_NONE;
3820 return XML_ERROR_ABORTED;
3829 /* The idea here is to avoid using stack for each IGNORE section when
3830 the whole file is parsed with one call.
3832 static enum XML_Error PTRCALL
3833 ignoreSectionProcessor(XML_Parser parser,
3836 const char **endPtr)
3838 enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
3839 endPtr, (XML_Bool)!ps_finalBuffer);
3840 if (result != XML_ERROR_NONE)
3843 processor = prologProcessor;
3844 return prologProcessor(parser, start, end, endPtr);
3849 /* startPtr gets set to non-null is the section is closed, and to null
3850 if the section is not yet closed.
3852 static enum XML_Error
3853 doIgnoreSection(XML_Parser parser,
3854 const ENCODING *enc,
3855 const char **startPtr,
3857 const char **nextPtr,
3862 const char *s = *startPtr;
3863 const char **eventPP;
3864 const char **eventEndPP;
3865 if (enc == encoding) {
3866 eventPP = &eventPtr;
3868 eventEndPP = &eventEndPtr;
3871 /* It's not entirely clear, but it seems the following two lines
3872 * of code cannot be executed. The only occasions on which 'enc'
3873 * is not 'parser->m_encoding' are when this function is called
3874 * from the internal entity processing, and IGNORE sections are an
3875 * error in internal entities.
3877 * Since it really isn't clear that this is true, we keep the code
3878 * and just remove it from our coverage tests.
3882 eventPP = &(openInternalEntities->internalEventPtr);
3883 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3884 /* LCOV_EXCL_STOP */
3888 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3891 case XML_TOK_IGNORE_SECT:
3893 reportDefault(parser, enc, s, next);
3896 if (ps_parsing == XML_FINISHED)
3897 return XML_ERROR_ABORTED;
3899 return XML_ERROR_NONE;
3900 case XML_TOK_INVALID:
3902 return XML_ERROR_INVALID_TOKEN;
3903 case XML_TOK_PARTIAL_CHAR:
3906 return XML_ERROR_NONE;
3908 return XML_ERROR_PARTIAL_CHAR;
3909 case XML_TOK_PARTIAL:
3913 return XML_ERROR_NONE;
3915 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3917 /* All of the tokens that XmlIgnoreSectionTok() returns have
3918 * explicit cases to handle them, so this default case is never
3919 * executed. We keep it as a safety net anyway, and remove it
3920 * from our test coverage statistics.
3925 return XML_ERROR_UNEXPECTED_STATE;
3926 /* LCOV_EXCL_STOP */
3931 #endif /* XML_DTD */
3933 static enum XML_Error
3934 initializeEncoding(XML_Parser parser)
3938 char encodingBuf[128];
3939 /* See comments abount `protoclEncodingName` in parserInit() */
3940 if (!protocolEncodingName)
3944 for (i = 0; protocolEncodingName[i]; i++) {
3945 if (i == sizeof(encodingBuf) - 1
3946 || (protocolEncodingName[i] & ~0x7f) != 0) {
3947 encodingBuf[0] = '\0';
3950 encodingBuf[i] = (char)protocolEncodingName[i];
3952 encodingBuf[i] = '\0';
3956 s = protocolEncodingName;
3958 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
3959 return XML_ERROR_NONE;
3960 return handleUnknownEncoding(parser, protocolEncodingName);
3963 static enum XML_Error
3964 processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3965 const char *s, const char *next)
3967 const char *encodingName = NULL;
3968 const XML_Char *storedEncName = NULL;
3969 const ENCODING *newEncoding = NULL;
3970 const char *version = NULL;
3971 const char *versionend;
3972 const XML_Char *storedversion = NULL;
3973 int standalone = -1;
3976 : XmlParseXmlDecl)(isGeneralTextEntity,
3986 if (isGeneralTextEntity)
3987 return XML_ERROR_TEXT_DECL;
3989 return XML_ERROR_XML_DECL;
3991 if (!isGeneralTextEntity && standalone == 1) {
3992 _dtd->standalone = XML_TRUE;
3994 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3995 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
3996 #endif /* XML_DTD */
3998 if (xmlDeclHandler) {
3999 if (encodingName != NULL) {
4000 storedEncName = poolStoreString(&temp2Pool,
4004 + XmlNameLength(encoding, encodingName));
4006 return XML_ERROR_NO_MEMORY;
4007 poolFinish(&temp2Pool);
4010 storedversion = poolStoreString(&temp2Pool,
4013 versionend - encoding->minBytesPerChar);
4015 return XML_ERROR_NO_MEMORY;
4017 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
4019 else if (defaultHandler)
4020 reportDefault(parser, encoding, s, next);
4021 if (protocolEncodingName == NULL) {
4023 /* Check that the specified encoding does not conflict with what
4024 * the parser has already deduced. Do we have the same number
4025 * of bytes in the smallest representation of a character? If
4026 * this is UTF-16, is it the same endianness?
4028 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar
4029 || (newEncoding->minBytesPerChar == 2 &&
4030 newEncoding != encoding)) {
4031 eventPtr = encodingName;
4032 return XML_ERROR_INCORRECT_ENCODING;
4034 encoding = newEncoding;
4036 else if (encodingName) {
4037 enum XML_Error result;
4038 if (!storedEncName) {
4039 storedEncName = poolStoreString(
4040 &temp2Pool, encoding, encodingName,
4041 encodingName + XmlNameLength(encoding, encodingName));
4043 return XML_ERROR_NO_MEMORY;
4045 result = handleUnknownEncoding(parser, storedEncName);
4046 poolClear(&temp2Pool);
4047 if (result == XML_ERROR_UNKNOWN_ENCODING)
4048 eventPtr = encodingName;
4053 if (storedEncName || storedversion)
4054 poolClear(&temp2Pool);
4056 return XML_ERROR_NONE;
4059 static enum XML_Error
4060 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
4062 if (unknownEncodingHandler) {
4065 for (i = 0; i < 256; i++)
4067 info.convert = NULL;
4069 info.release = NULL;
4070 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
4073 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
4074 if (!unknownEncodingMem) {
4076 info.release(info.data);
4077 return XML_ERROR_NO_MEMORY;
4080 ? XmlInitUnknownEncodingNS
4081 : XmlInitUnknownEncoding)(unknownEncodingMem,
4086 unknownEncodingData = info.data;
4087 unknownEncodingRelease = info.release;
4089 return XML_ERROR_NONE;
4092 if (info.release != NULL)
4093 info.release(info.data);
4095 return XML_ERROR_UNKNOWN_ENCODING;
4098 static enum XML_Error PTRCALL
4099 prologInitProcessor(XML_Parser parser,
4102 const char **nextPtr)
4104 enum XML_Error result = initializeEncoding(parser);
4105 if (result != XML_ERROR_NONE)
4107 processor = prologProcessor;
4108 return prologProcessor(parser, s, end, nextPtr);
4113 static enum XML_Error PTRCALL
4114 externalParEntInitProcessor(XML_Parser parser,
4117 const char **nextPtr)
4119 enum XML_Error result = initializeEncoding(parser);
4120 if (result != XML_ERROR_NONE)
4123 /* we know now that XML_Parse(Buffer) has been called,
4124 so we consider the external parameter entity read */
4125 _dtd->paramEntityRead = XML_TRUE;
4127 if (prologState.inEntityValue) {
4128 processor = entityValueInitProcessor;
4129 return entityValueInitProcessor(parser, s, end, nextPtr);
4132 processor = externalParEntProcessor;
4133 return externalParEntProcessor(parser, s, end, nextPtr);
4137 static enum XML_Error PTRCALL
4138 entityValueInitProcessor(XML_Parser parser,
4141 const char **nextPtr)
4144 const char *start = s;
4145 const char *next = start;
4149 tok = XmlPrologTok(encoding, start, end, &next);
4152 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
4154 return XML_ERROR_NONE;
4157 case XML_TOK_INVALID:
4158 return XML_ERROR_INVALID_TOKEN;
4159 case XML_TOK_PARTIAL:
4160 return XML_ERROR_UNCLOSED_TOKEN;
4161 case XML_TOK_PARTIAL_CHAR:
4162 return XML_ERROR_PARTIAL_CHAR;
4163 case XML_TOK_NONE: /* start == end */
4167 /* found end of entity value - can store it now */
4168 return storeEntityValue(parser, encoding, s, end);
4170 else if (tok == XML_TOK_XML_DECL) {
4171 enum XML_Error result;
4172 result = processXmlDecl(parser, 0, start, next);
4173 if (result != XML_ERROR_NONE)
4175 /* At this point, ps_parsing cannot be XML_SUSPENDED. For that
4176 * to happen, a parameter entity parsing handler must have
4177 * attempted to suspend the parser, which fails and raises an
4178 * error. The parser can be aborted, but can't be suspended.
4180 if (ps_parsing == XML_FINISHED)
4181 return XML_ERROR_ABORTED;
4183 /* stop scanning for text declaration - we found one */
4184 processor = entityValueProcessor;
4185 return entityValueProcessor(parser, next, end, nextPtr);
4187 /* If we are at the end of the buffer, this would cause XmlPrologTok to
4188 return XML_TOK_NONE on the next call, which would then cause the
4189 function to exit with *nextPtr set to s - that is what we want for other
4190 tokens, but not for the BOM - we would rather like to skip it;
4191 then, when this routine is entered the next time, XmlPrologTok will
4192 return XML_TOK_INVALID, since the BOM is still in the buffer
4194 else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
4196 return XML_ERROR_NONE;
4198 /* If we get this token, we have the start of what might be a
4199 normal tag, but not a declaration (i.e. it doesn't begin with
4200 "<!"). In a DTD context, that isn't legal.
4202 else if (tok == XML_TOK_INSTANCE_START) {
4204 return XML_ERROR_SYNTAX;
4211 static enum XML_Error PTRCALL
4212 externalParEntProcessor(XML_Parser parser,
4215 const char **nextPtr)
4217 const char *next = s;
4220 tok = XmlPrologTok(encoding, s, end, &next);
4222 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
4224 return XML_ERROR_NONE;
4227 case XML_TOK_INVALID:
4228 return XML_ERROR_INVALID_TOKEN;
4229 case XML_TOK_PARTIAL:
4230 return XML_ERROR_UNCLOSED_TOKEN;
4231 case XML_TOK_PARTIAL_CHAR:
4232 return XML_ERROR_PARTIAL_CHAR;
4233 case XML_TOK_NONE: /* start == end */
4238 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
4239 However, when parsing an external subset, doProlog will not accept a BOM
4240 as valid, and report a syntax error, so we have to skip the BOM
4242 else if (tok == XML_TOK_BOM) {
4244 tok = XmlPrologTok(encoding, s, end, &next);
4247 processor = prologProcessor;
4248 return doProlog(parser, encoding, s, end, tok, next,
4249 nextPtr, (XML_Bool)!ps_finalBuffer);
4252 static enum XML_Error PTRCALL
4253 entityValueProcessor(XML_Parser parser,
4256 const char **nextPtr)
4258 const char *start = s;
4259 const char *next = s;
4260 const ENCODING *enc = encoding;
4264 tok = XmlPrologTok(enc, start, end, &next);
4266 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
4268 return XML_ERROR_NONE;
4271 case XML_TOK_INVALID:
4272 return XML_ERROR_INVALID_TOKEN;
4273 case XML_TOK_PARTIAL:
4274 return XML_ERROR_UNCLOSED_TOKEN;
4275 case XML_TOK_PARTIAL_CHAR:
4276 return XML_ERROR_PARTIAL_CHAR;
4277 case XML_TOK_NONE: /* start == end */
4281 /* found end of entity value - can store it now */
4282 return storeEntityValue(parser, enc, s, end);
4288 #endif /* XML_DTD */
4290 static enum XML_Error PTRCALL
4291 prologProcessor(XML_Parser parser,
4294 const char **nextPtr)
4296 const char *next = s;
4297 int tok = XmlPrologTok(encoding, s, end, &next);
4298 return doProlog(parser, encoding, s, end, tok, next,
4299 nextPtr, (XML_Bool)!ps_finalBuffer);
4302 static enum XML_Error
4303 doProlog(XML_Parser parser,
4304 const ENCODING *enc,
4309 const char **nextPtr,
4313 static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
4314 #endif /* XML_DTD */
4315 static const XML_Char atypeCDATA[] =
4316 { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
4317 static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
4318 static const XML_Char atypeIDREF[] =
4319 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
4320 static const XML_Char atypeIDREFS[] =
4321 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
4322 static const XML_Char atypeENTITY[] =
4323 { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
4324 static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
4325 ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
4326 static const XML_Char atypeNMTOKEN[] = {
4327 ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
4328 static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
4329 ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
4330 static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
4331 ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
4332 static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
4333 static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
4335 /* save one level of indirection */
4336 DTD * const dtd = _dtd;
4338 const char **eventPP;
4339 const char **eventEndPP;
4340 enum XML_Content_Quant quant;
4342 if (enc == encoding) {
4343 eventPP = &eventPtr;
4344 eventEndPP = &eventEndPtr;
4347 eventPP = &(openInternalEntities->internalEventPtr);
4348 eventEndPP = &(openInternalEntities->internalEventEndPtr);
4353 XML_Bool handleDefault = XML_TRUE;
4357 if (haveMore && tok != XML_TOK_INVALID) {
4359 return XML_ERROR_NONE;
4362 case XML_TOK_INVALID:
4364 return XML_ERROR_INVALID_TOKEN;
4365 case XML_TOK_PARTIAL:
4366 return XML_ERROR_UNCLOSED_TOKEN;
4367 case XML_TOK_PARTIAL_CHAR:
4368 return XML_ERROR_PARTIAL_CHAR;
4369 case -XML_TOK_PROLOG_S:
4374 /* for internal PE NOT referenced between declarations */
4375 if (enc != encoding && !openInternalEntities->betweenDecl) {
4377 return XML_ERROR_NONE;
4379 /* WFC: PE Between Declarations - must check that PE contains
4380 complete markup, not only for external PEs, but also for
4381 internal PEs if the reference occurs between declarations.
4383 if (isParamEntity || enc != encoding) {
4384 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
4386 return XML_ERROR_INCOMPLETE_PE;
4388 return XML_ERROR_NONE;
4390 #endif /* XML_DTD */
4391 return XML_ERROR_NO_ELEMENTS;
4398 role = XmlTokenRole(&prologState, tok, s, next, enc);
4400 case XML_ROLE_XML_DECL:
4402 enum XML_Error result = processXmlDecl(parser, 0, s, next);
4403 if (result != XML_ERROR_NONE)
4406 handleDefault = XML_FALSE;
4409 case XML_ROLE_DOCTYPE_NAME:
4410 if (startDoctypeDeclHandler) {
4411 doctypeName = poolStoreString(&tempPool, enc, s, next);
4413 return XML_ERROR_NO_MEMORY;
4414 poolFinish(&tempPool);
4415 doctypePubid = NULL;
4416 handleDefault = XML_FALSE;
4418 doctypeSysid = NULL; /* always initialize to NULL */
4420 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
4421 if (startDoctypeDeclHandler) {
4422 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
4425 poolClear(&tempPool);
4426 handleDefault = XML_FALSE;
4430 case XML_ROLE_TEXT_DECL:
4432 enum XML_Error result = processXmlDecl(parser, 1, s, next);
4433 if (result != XML_ERROR_NONE)
4436 handleDefault = XML_FALSE;
4439 #endif /* XML_DTD */
4440 case XML_ROLE_DOCTYPE_PUBLIC_ID:
4442 useForeignDTD = XML_FALSE;
4443 declEntity = (ENTITY *)lookup(parser,
4444 &dtd->paramEntities,
4448 return XML_ERROR_NO_MEMORY;
4449 #endif /* XML_DTD */
4450 dtd->hasParamEntityRefs = XML_TRUE;
4451 if (startDoctypeDeclHandler) {
4453 if (!XmlIsPublicId(enc, s, next, eventPP))
4454 return XML_ERROR_PUBLICID;
4455 pubId = poolStoreString(&tempPool, enc,
4456 s + enc->minBytesPerChar,
4457 next - enc->minBytesPerChar);
4459 return XML_ERROR_NO_MEMORY;
4460 normalizePublicId(pubId);
4461 poolFinish(&tempPool);
4462 doctypePubid = pubId;
4463 handleDefault = XML_FALSE;
4464 goto alreadyChecked;
4467 case XML_ROLE_ENTITY_PUBLIC_ID:
4468 if (!XmlIsPublicId(enc, s, next, eventPP))
4469 return XML_ERROR_PUBLICID;
4471 if (dtd->keepProcessing && declEntity) {
4472 XML_Char *tem = poolStoreString(&dtd->pool,
4474 s + enc->minBytesPerChar,
4475 next - enc->minBytesPerChar);
4477 return XML_ERROR_NO_MEMORY;
4478 normalizePublicId(tem);
4479 declEntity->publicId = tem;
4480 poolFinish(&dtd->pool);
4481 if (entityDeclHandler)
4482 handleDefault = XML_FALSE;
4485 case XML_ROLE_DOCTYPE_CLOSE:
4487 startDoctypeDeclHandler(handlerArg, doctypeName,
4488 doctypeSysid, doctypePubid, 0);
4489 poolClear(&tempPool);
4490 handleDefault = XML_FALSE;
4492 /* doctypeSysid will be non-NULL in the case of a previous
4493 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
4494 was not set, indicating an external subset
4497 if (doctypeSysid || useForeignDTD) {
4498 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4499 dtd->hasParamEntityRefs = XML_TRUE;
4500 if (paramEntityParsing && externalEntityRefHandler) {
4501 ENTITY *entity = (ENTITY *)lookup(parser,
4502 &dtd->paramEntities,
4506 /* The external subset name "#" will have already been
4507 * inserted into the hash table at the start of the
4508 * external entity parsing, so no allocation will happen
4509 * and lookup() cannot fail.
4511 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
4514 entity->base = curBase;
4515 dtd->paramEntityRead = XML_FALSE;
4516 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4521 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4522 if (dtd->paramEntityRead) {
4523 if (!dtd->standalone &&
4524 notStandaloneHandler &&
4525 !notStandaloneHandler(handlerArg))
4526 return XML_ERROR_NOT_STANDALONE;
4528 /* if we didn't read the foreign DTD then this means that there
4529 is no external subset and we must reset dtd->hasParamEntityRefs
4531 else if (!doctypeSysid)
4532 dtd->hasParamEntityRefs = hadParamEntityRefs;
4533 /* end of DTD - no need to update dtd->keepProcessing */
4535 useForeignDTD = XML_FALSE;
4537 #endif /* XML_DTD */
4538 if (endDoctypeDeclHandler) {
4539 endDoctypeDeclHandler(handlerArg);
4540 handleDefault = XML_FALSE;
4543 case XML_ROLE_INSTANCE_START:
4545 /* if there is no DOCTYPE declaration then now is the
4546 last chance to read the foreign DTD
4548 if (useForeignDTD) {
4549 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4550 dtd->hasParamEntityRefs = XML_TRUE;
4551 if (paramEntityParsing && externalEntityRefHandler) {
4552 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4556 return XML_ERROR_NO_MEMORY;
4557 entity->base = curBase;
4558 dtd->paramEntityRead = XML_FALSE;
4559 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4564 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4565 if (dtd->paramEntityRead) {
4566 if (!dtd->standalone &&
4567 notStandaloneHandler &&
4568 !notStandaloneHandler(handlerArg))
4569 return XML_ERROR_NOT_STANDALONE;
4571 /* if we didn't read the foreign DTD then this means that there
4572 is no external subset and we must reset dtd->hasParamEntityRefs
4575 dtd->hasParamEntityRefs = hadParamEntityRefs;
4576 /* end of DTD - no need to update dtd->keepProcessing */
4579 #endif /* XML_DTD */
4580 processor = contentProcessor;
4581 return contentProcessor(parser, s, end, nextPtr);
4582 case XML_ROLE_ATTLIST_ELEMENT_NAME:
4583 declElementType = getElementType(parser, enc, s, next);
4584 if (!declElementType)
4585 return XML_ERROR_NO_MEMORY;
4586 goto checkAttListDeclHandler;
4587 case XML_ROLE_ATTRIBUTE_NAME:
4588 declAttributeId = getAttributeId(parser, enc, s, next);
4589 if (!declAttributeId)
4590 return XML_ERROR_NO_MEMORY;
4591 declAttributeIsCdata = XML_FALSE;
4592 declAttributeType = NULL;
4593 declAttributeIsId = XML_FALSE;
4594 goto checkAttListDeclHandler;
4595 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
4596 declAttributeIsCdata = XML_TRUE;
4597 declAttributeType = atypeCDATA;
4598 goto checkAttListDeclHandler;
4599 case XML_ROLE_ATTRIBUTE_TYPE_ID:
4600 declAttributeIsId = XML_TRUE;
4601 declAttributeType = atypeID;
4602 goto checkAttListDeclHandler;
4603 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
4604 declAttributeType = atypeIDREF;
4605 goto checkAttListDeclHandler;
4606 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
4607 declAttributeType = atypeIDREFS;
4608 goto checkAttListDeclHandler;
4609 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
4610 declAttributeType = atypeENTITY;
4611 goto checkAttListDeclHandler;
4612 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
4613 declAttributeType = atypeENTITIES;
4614 goto checkAttListDeclHandler;
4615 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
4616 declAttributeType = atypeNMTOKEN;
4617 goto checkAttListDeclHandler;
4618 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
4619 declAttributeType = atypeNMTOKENS;
4620 checkAttListDeclHandler:
4621 if (dtd->keepProcessing && attlistDeclHandler)
4622 handleDefault = XML_FALSE;
4624 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4625 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
4626 if (dtd->keepProcessing && attlistDeclHandler) {
4627 const XML_Char *prefix;
4628 if (declAttributeType) {
4629 prefix = enumValueSep;
4632 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
4636 if (!poolAppendString(&tempPool, prefix))
4637 return XML_ERROR_NO_MEMORY;
4638 if (!poolAppend(&tempPool, enc, s, next))
4639 return XML_ERROR_NO_MEMORY;
4640 declAttributeType = tempPool.start;
4641 handleDefault = XML_FALSE;
4644 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4645 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4646 if (dtd->keepProcessing) {
4647 if (!defineAttribute(declElementType, declAttributeId,
4648 declAttributeIsCdata, declAttributeIsId,
4650 return XML_ERROR_NO_MEMORY;
4651 if (attlistDeclHandler && declAttributeType) {
4652 if (*declAttributeType == XML_T(ASCII_LPAREN)
4653 || (*declAttributeType == XML_T(ASCII_N)
4654 && declAttributeType[1] == XML_T(ASCII_O))) {
4655 /* Enumerated or Notation type */
4656 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4657 || !poolAppendChar(&tempPool, XML_T('\0')))
4658 return XML_ERROR_NO_MEMORY;
4659 declAttributeType = tempPool.start;
4660 poolFinish(&tempPool);
4663 attlistDeclHandler(handlerArg, declElementType->name,
4664 declAttributeId->name, declAttributeType,
4665 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
4666 poolClear(&tempPool);
4667 handleDefault = XML_FALSE;
4671 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4672 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4673 if (dtd->keepProcessing) {
4674 const XML_Char *attVal;
4675 enum XML_Error result =
4676 storeAttributeValue(parser, enc, declAttributeIsCdata,
4677 s + enc->minBytesPerChar,
4678 next - enc->minBytesPerChar,
4682 attVal = poolStart(&dtd->pool);
4683 poolFinish(&dtd->pool);
4684 /* ID attributes aren't allowed to have a default */
4685 if (!defineAttribute(declElementType, declAttributeId,
4686 declAttributeIsCdata, XML_FALSE, attVal, parser))
4687 return XML_ERROR_NO_MEMORY;
4688 if (attlistDeclHandler && declAttributeType) {
4689 if (*declAttributeType == XML_T(ASCII_LPAREN)
4690 || (*declAttributeType == XML_T(ASCII_N)
4691 && declAttributeType[1] == XML_T(ASCII_O))) {
4692 /* Enumerated or Notation type */
4693 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4694 || !poolAppendChar(&tempPool, XML_T('\0')))
4695 return XML_ERROR_NO_MEMORY;
4696 declAttributeType = tempPool.start;
4697 poolFinish(&tempPool);
4700 attlistDeclHandler(handlerArg, declElementType->name,
4701 declAttributeId->name, declAttributeType,
4703 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4704 poolClear(&tempPool);
4705 handleDefault = XML_FALSE;
4709 case XML_ROLE_ENTITY_VALUE:
4710 if (dtd->keepProcessing) {
4711 enum XML_Error result = storeEntityValue(parser, enc,
4712 s + enc->minBytesPerChar,
4713 next - enc->minBytesPerChar);
4715 declEntity->textPtr = poolStart(&dtd->entityValuePool);
4716 declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
4717 poolFinish(&dtd->entityValuePool);
4718 if (entityDeclHandler) {
4720 entityDeclHandler(handlerArg,
4722 declEntity->is_param,
4723 declEntity->textPtr,
4724 declEntity->textLen,
4726 handleDefault = XML_FALSE;
4730 poolDiscard(&dtd->entityValuePool);
4731 if (result != XML_ERROR_NONE)
4735 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4737 useForeignDTD = XML_FALSE;
4738 #endif /* XML_DTD */
4739 dtd->hasParamEntityRefs = XML_TRUE;
4740 if (startDoctypeDeclHandler) {
4741 doctypeSysid = poolStoreString(&tempPool, enc,
4742 s + enc->minBytesPerChar,
4743 next - enc->minBytesPerChar);
4744 if (doctypeSysid == NULL)
4745 return XML_ERROR_NO_MEMORY;
4746 poolFinish(&tempPool);
4747 handleDefault = XML_FALSE;
4751 /* use externalSubsetName to make doctypeSysid non-NULL
4752 for the case where no startDoctypeDeclHandler is set */
4753 doctypeSysid = externalSubsetName;
4754 #endif /* XML_DTD */
4755 if (!dtd->standalone
4757 && !paramEntityParsing
4758 #endif /* XML_DTD */
4759 && notStandaloneHandler
4760 && !notStandaloneHandler(handlerArg))
4761 return XML_ERROR_NOT_STANDALONE;
4766 declEntity = (ENTITY *)lookup(parser,
4767 &dtd->paramEntities,
4771 return XML_ERROR_NO_MEMORY;
4772 declEntity->publicId = NULL;
4775 #endif /* XML_DTD */
4776 case XML_ROLE_ENTITY_SYSTEM_ID:
4777 if (dtd->keepProcessing && declEntity) {
4778 declEntity->systemId = poolStoreString(&dtd->pool, enc,
4779 s + enc->minBytesPerChar,
4780 next - enc->minBytesPerChar);
4781 if (!declEntity->systemId)
4782 return XML_ERROR_NO_MEMORY;
4783 declEntity->base = curBase;
4784 poolFinish(&dtd->pool);
4785 if (entityDeclHandler)
4786 handleDefault = XML_FALSE;
4789 case XML_ROLE_ENTITY_COMPLETE:
4790 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
4792 entityDeclHandler(handlerArg,
4794 declEntity->is_param,
4797 declEntity->systemId,
4798 declEntity->publicId,
4800 handleDefault = XML_FALSE;
4803 case XML_ROLE_ENTITY_NOTATION_NAME:
4804 if (dtd->keepProcessing && declEntity) {
4805 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4806 if (!declEntity->notation)
4807 return XML_ERROR_NO_MEMORY;
4808 poolFinish(&dtd->pool);
4809 if (unparsedEntityDeclHandler) {
4811 unparsedEntityDeclHandler(handlerArg,
4814 declEntity->systemId,
4815 declEntity->publicId,
4816 declEntity->notation);
4817 handleDefault = XML_FALSE;
4819 else if (entityDeclHandler) {
4821 entityDeclHandler(handlerArg,
4825 declEntity->systemId,
4826 declEntity->publicId,
4827 declEntity->notation);
4828 handleDefault = XML_FALSE;
4832 case XML_ROLE_GENERAL_ENTITY_NAME:
4834 if (XmlPredefinedEntityName(enc, s, next)) {
4838 if (dtd->keepProcessing) {
4839 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4841 return XML_ERROR_NO_MEMORY;
4842 declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
4845 return XML_ERROR_NO_MEMORY;
4846 if (declEntity->name != name) {
4847 poolDiscard(&dtd->pool);
4851 poolFinish(&dtd->pool);
4852 declEntity->publicId = NULL;
4853 declEntity->is_param = XML_FALSE;
4854 /* if we have a parent parser or are reading an internal parameter
4855 entity, then the entity declaration is not considered "internal"
4857 declEntity->is_internal = !(parentParser || openInternalEntities);
4858 if (entityDeclHandler)
4859 handleDefault = XML_FALSE;
4863 poolDiscard(&dtd->pool);
4868 case XML_ROLE_PARAM_ENTITY_NAME:
4870 if (dtd->keepProcessing) {
4871 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4873 return XML_ERROR_NO_MEMORY;
4874 declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4875 name, sizeof(ENTITY));
4877 return XML_ERROR_NO_MEMORY;
4878 if (declEntity->name != name) {
4879 poolDiscard(&dtd->pool);
4883 poolFinish(&dtd->pool);
4884 declEntity->publicId = NULL;
4885 declEntity->is_param = XML_TRUE;
4886 /* if we have a parent parser or are reading an internal parameter
4887 entity, then the entity declaration is not considered "internal"
4889 declEntity->is_internal = !(parentParser || openInternalEntities);
4890 if (entityDeclHandler)
4891 handleDefault = XML_FALSE;
4895 poolDiscard(&dtd->pool);
4898 #else /* not XML_DTD */
4900 #endif /* XML_DTD */
4902 case XML_ROLE_NOTATION_NAME:
4903 declNotationPublicId = NULL;
4904 declNotationName = NULL;
4905 if (notationDeclHandler) {
4906 declNotationName = poolStoreString(&tempPool, enc, s, next);
4907 if (!declNotationName)
4908 return XML_ERROR_NO_MEMORY;
4909 poolFinish(&tempPool);
4910 handleDefault = XML_FALSE;
4913 case XML_ROLE_NOTATION_PUBLIC_ID:
4914 if (!XmlIsPublicId(enc, s, next, eventPP))
4915 return XML_ERROR_PUBLICID;
4916 if (declNotationName) { /* means notationDeclHandler != NULL */
4917 XML_Char *tem = poolStoreString(&tempPool,
4919 s + enc->minBytesPerChar,
4920 next - enc->minBytesPerChar);
4922 return XML_ERROR_NO_MEMORY;
4923 normalizePublicId(tem);
4924 declNotationPublicId = tem;
4925 poolFinish(&tempPool);
4926 handleDefault = XML_FALSE;
4929 case XML_ROLE_NOTATION_SYSTEM_ID:
4930 if (declNotationName && notationDeclHandler) {
4931 const XML_Char *systemId
4932 = poolStoreString(&tempPool, enc,
4933 s + enc->minBytesPerChar,
4934 next - enc->minBytesPerChar);
4936 return XML_ERROR_NO_MEMORY;
4938 notationDeclHandler(handlerArg,
4942 declNotationPublicId);
4943 handleDefault = XML_FALSE;
4945 poolClear(&tempPool);
4947 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4948 if (declNotationPublicId && notationDeclHandler) {
4950 notationDeclHandler(handlerArg,
4954 declNotationPublicId);
4955 handleDefault = XML_FALSE;
4957 poolClear(&tempPool);
4959 case XML_ROLE_ERROR:
4961 case XML_TOK_PARAM_ENTITY_REF:
4962 /* PE references in internal subset are
4963 not allowed within declarations. */
4964 return XML_ERROR_PARAM_ENTITY_REF;
4965 case XML_TOK_XML_DECL:
4966 return XML_ERROR_MISPLACED_XML_PI;
4968 return XML_ERROR_SYNTAX;
4971 case XML_ROLE_IGNORE_SECT:
4973 enum XML_Error result;
4975 reportDefault(parser, enc, s, next);
4976 handleDefault = XML_FALSE;
4977 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4978 if (result != XML_ERROR_NONE)
4981 processor = ignoreSectionProcessor;
4986 #endif /* XML_DTD */
4987 case XML_ROLE_GROUP_OPEN:
4988 if (prologState.level >= groupSize) {
4990 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
4993 return XML_ERROR_NO_MEMORY;
4995 groupConnector = temp;
4996 if (dtd->scaffIndex) {
4997 int *temp = (int *)REALLOC(dtd->scaffIndex,
4998 groupSize * sizeof(int));
5000 return XML_ERROR_NO_MEMORY;
5001 dtd->scaffIndex = temp;
5005 groupConnector = (char *)MALLOC(groupSize = 32);
5006 if (!groupConnector) {
5008 return XML_ERROR_NO_MEMORY;
5012 groupConnector[prologState.level] = 0;
5013 if (dtd->in_eldecl) {
5014 int myindex = nextScaffoldPart(parser);
5016 return XML_ERROR_NO_MEMORY;
5017 dtd->scaffIndex[dtd->scaffLevel] = myindex;
5019 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
5020 if (elementDeclHandler)
5021 handleDefault = XML_FALSE;
5024 case XML_ROLE_GROUP_SEQUENCE:
5025 if (groupConnector[prologState.level] == ASCII_PIPE)
5026 return XML_ERROR_SYNTAX;
5027 groupConnector[prologState.level] = ASCII_COMMA;
5028 if (dtd->in_eldecl && elementDeclHandler)
5029 handleDefault = XML_FALSE;
5031 case XML_ROLE_GROUP_CHOICE:
5032 if (groupConnector[prologState.level] == ASCII_COMMA)
5033 return XML_ERROR_SYNTAX;
5035 && !groupConnector[prologState.level]
5036 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5039 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5041 if (elementDeclHandler)
5042 handleDefault = XML_FALSE;
5044 groupConnector[prologState.level] = ASCII_PIPE;
5046 case XML_ROLE_PARAM_ENTITY_REF:
5048 case XML_ROLE_INNER_PARAM_ENTITY_REF:
5049 dtd->hasParamEntityRefs = XML_TRUE;
5050 if (!paramEntityParsing)
5051 dtd->keepProcessing = dtd->standalone;
5053 const XML_Char *name;
5055 name = poolStoreString(&dtd->pool, enc,
5056 s + enc->minBytesPerChar,
5057 next - enc->minBytesPerChar);
5059 return XML_ERROR_NO_MEMORY;
5060 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5061 poolDiscard(&dtd->pool);
5062 /* first, determine if a check for an existing declaration is needed;
5063 if yes, check that the entity exists, and that it is internal,
5064 otherwise call the skipped entity handler
5066 if (prologState.documentEntity &&
5068 ? !openInternalEntities
5069 : !dtd->hasParamEntityRefs)) {
5071 return XML_ERROR_UNDEFINED_ENTITY;
5072 else if (!entity->is_internal) {
5073 /* It's hard to exhaustively search the code to be sure,
5074 * but there doesn't seem to be a way of executing the
5075 * following line. There are two cases:
5077 * If 'standalone' is false, the DTD must have no
5078 * parameter entities or we wouldn't have passed the outer
5079 * 'if' statement. That measn the only entity in the hash
5080 * table is the external subset name "#" which cannot be
5081 * given as a parameter entity name in XML syntax, so the
5082 * lookup must have returned NULL and we don't even reach
5083 * the test for an internal entity.
5085 * If 'standalone' is true, it does not seem to be
5086 * possible to create entities taking this code path that
5087 * are not internal entities, so fail the test above.
5089 * Because this analysis is very uncertain, the code is
5090 * being left in place and merely removed from the
5091 * coverage test statistics.
5093 return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
5097 dtd->keepProcessing = dtd->standalone;
5098 /* cannot report skipped entities in declarations */
5099 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
5100 skippedEntityHandler(handlerArg, name, 1);
5101 handleDefault = XML_FALSE;
5106 return XML_ERROR_RECURSIVE_ENTITY_REF;
5107 if (entity->textPtr) {
5108 enum XML_Error result;
5109 XML_Bool betweenDecl =
5110 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
5111 result = processInternalEntity(parser, entity, betweenDecl);
5112 if (result != XML_ERROR_NONE)
5114 handleDefault = XML_FALSE;
5117 if (externalEntityRefHandler) {
5118 dtd->paramEntityRead = XML_FALSE;
5119 entity->open = XML_TRUE;
5120 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5124 entity->publicId)) {
5125 entity->open = XML_FALSE;
5126 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5128 entity->open = XML_FALSE;
5129 handleDefault = XML_FALSE;
5130 if (!dtd->paramEntityRead) {
5131 dtd->keepProcessing = dtd->standalone;
5136 dtd->keepProcessing = dtd->standalone;
5140 #endif /* XML_DTD */
5141 if (!dtd->standalone &&
5142 notStandaloneHandler &&
5143 !notStandaloneHandler(handlerArg))
5144 return XML_ERROR_NOT_STANDALONE;
5147 /* Element declaration stuff */
5149 case XML_ROLE_ELEMENT_NAME:
5150 if (elementDeclHandler) {
5151 declElementType = getElementType(parser, enc, s, next);
5152 if (!declElementType)
5153 return XML_ERROR_NO_MEMORY;
5154 dtd->scaffLevel = 0;
5155 dtd->scaffCount = 0;
5156 dtd->in_eldecl = XML_TRUE;
5157 handleDefault = XML_FALSE;
5161 case XML_ROLE_CONTENT_ANY:
5162 case XML_ROLE_CONTENT_EMPTY:
5163 if (dtd->in_eldecl) {
5164 if (elementDeclHandler) {
5165 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
5167 return XML_ERROR_NO_MEMORY;
5168 content->quant = XML_CQUANT_NONE;
5169 content->name = NULL;
5170 content->numchildren = 0;
5171 content->children = NULL;
5172 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
5176 elementDeclHandler(handlerArg, declElementType->name, content);
5177 handleDefault = XML_FALSE;
5179 dtd->in_eldecl = XML_FALSE;
5183 case XML_ROLE_CONTENT_PCDATA:
5184 if (dtd->in_eldecl) {
5185 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5187 if (elementDeclHandler)
5188 handleDefault = XML_FALSE;
5192 case XML_ROLE_CONTENT_ELEMENT:
5193 quant = XML_CQUANT_NONE;
5194 goto elementContent;
5195 case XML_ROLE_CONTENT_ELEMENT_OPT:
5196 quant = XML_CQUANT_OPT;
5197 goto elementContent;
5198 case XML_ROLE_CONTENT_ELEMENT_REP:
5199 quant = XML_CQUANT_REP;
5200 goto elementContent;
5201 case XML_ROLE_CONTENT_ELEMENT_PLUS:
5202 quant = XML_CQUANT_PLUS;
5204 if (dtd->in_eldecl) {
5206 const XML_Char *name;
5208 const char *nxt = (quant == XML_CQUANT_NONE
5210 : next - enc->minBytesPerChar);
5211 int myindex = nextScaffoldPart(parser);
5213 return XML_ERROR_NO_MEMORY;
5214 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
5215 dtd->scaffold[myindex].quant = quant;
5216 el = getElementType(parser, enc, s, nxt);
5218 return XML_ERROR_NO_MEMORY;
5220 dtd->scaffold[myindex].name = name;
5222 for (; name[nameLen++]; );
5223 dtd->contentStringLen += nameLen;
5224 if (elementDeclHandler)
5225 handleDefault = XML_FALSE;
5229 case XML_ROLE_GROUP_CLOSE:
5230 quant = XML_CQUANT_NONE;
5232 case XML_ROLE_GROUP_CLOSE_OPT:
5233 quant = XML_CQUANT_OPT;
5235 case XML_ROLE_GROUP_CLOSE_REP:
5236 quant = XML_CQUANT_REP;
5238 case XML_ROLE_GROUP_CLOSE_PLUS:
5239 quant = XML_CQUANT_PLUS;
5241 if (dtd->in_eldecl) {
5242 if (elementDeclHandler)
5243 handleDefault = XML_FALSE;
5245 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
5246 if (dtd->scaffLevel == 0) {
5247 if (!handleDefault) {
5248 XML_Content *model = build_model(parser);
5250 return XML_ERROR_NO_MEMORY;
5252 elementDeclHandler(handlerArg, declElementType->name, model);
5254 dtd->in_eldecl = XML_FALSE;
5255 dtd->contentStringLen = 0;
5259 /* End element declaration stuff */
5262 if (!reportProcessingInstruction(parser, enc, s, next))
5263 return XML_ERROR_NO_MEMORY;
5264 handleDefault = XML_FALSE;
5266 case XML_ROLE_COMMENT:
5267 if (!reportComment(parser, enc, s, next))
5268 return XML_ERROR_NO_MEMORY;
5269 handleDefault = XML_FALSE;
5274 handleDefault = XML_FALSE;
5278 case XML_ROLE_DOCTYPE_NONE:
5279 if (startDoctypeDeclHandler)
5280 handleDefault = XML_FALSE;
5282 case XML_ROLE_ENTITY_NONE:
5283 if (dtd->keepProcessing && entityDeclHandler)
5284 handleDefault = XML_FALSE;
5286 case XML_ROLE_NOTATION_NONE:
5287 if (notationDeclHandler)
5288 handleDefault = XML_FALSE;
5290 case XML_ROLE_ATTLIST_NONE:
5291 if (dtd->keepProcessing && attlistDeclHandler)
5292 handleDefault = XML_FALSE;
5294 case XML_ROLE_ELEMENT_NONE:
5295 if (elementDeclHandler)
5296 handleDefault = XML_FALSE;
5298 } /* end of big switch */
5300 if (handleDefault && defaultHandler)
5301 reportDefault(parser, enc, s, next);
5303 switch (ps_parsing) {
5306 return XML_ERROR_NONE;
5308 return XML_ERROR_ABORTED;
5311 tok = XmlPrologTok(enc, s, end, &next);
5317 static enum XML_Error PTRCALL
5318 epilogProcessor(XML_Parser parser,
5321 const char **nextPtr)
5323 processor = epilogProcessor;
5326 const char *next = NULL;
5327 int tok = XmlPrologTok(encoding, s, end, &next);
5330 /* report partial linebreak - it might be the last token */
5331 case -XML_TOK_PROLOG_S:
5332 if (defaultHandler) {
5333 reportDefault(parser, encoding, s, next);
5334 if (ps_parsing == XML_FINISHED)
5335 return XML_ERROR_ABORTED;
5338 return XML_ERROR_NONE;
5341 return XML_ERROR_NONE;
5342 case XML_TOK_PROLOG_S:
5344 reportDefault(parser, encoding, s, next);
5347 if (!reportProcessingInstruction(parser, encoding, s, next))
5348 return XML_ERROR_NO_MEMORY;
5350 case XML_TOK_COMMENT:
5351 if (!reportComment(parser, encoding, s, next))
5352 return XML_ERROR_NO_MEMORY;
5354 case XML_TOK_INVALID:
5356 return XML_ERROR_INVALID_TOKEN;
5357 case XML_TOK_PARTIAL:
5358 if (!ps_finalBuffer) {
5360 return XML_ERROR_NONE;
5362 return XML_ERROR_UNCLOSED_TOKEN;
5363 case XML_TOK_PARTIAL_CHAR:
5364 if (!ps_finalBuffer) {
5366 return XML_ERROR_NONE;
5368 return XML_ERROR_PARTIAL_CHAR;
5370 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
5372 eventPtr = s = next;
5373 switch (ps_parsing) {
5376 return XML_ERROR_NONE;
5378 return XML_ERROR_ABORTED;
5384 static enum XML_Error
5385 processInternalEntity(XML_Parser parser, ENTITY *entity,
5386 XML_Bool betweenDecl)
5388 const char *textStart, *textEnd;
5390 enum XML_Error result;
5391 OPEN_INTERNAL_ENTITY *openEntity;
5393 if (freeInternalEntities) {
5394 openEntity = freeInternalEntities;
5395 freeInternalEntities = openEntity->next;
5398 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
5400 return XML_ERROR_NO_MEMORY;
5402 entity->open = XML_TRUE;
5403 entity->processed = 0;
5404 openEntity->next = openInternalEntities;
5405 openInternalEntities = openEntity;
5406 openEntity->entity = entity;
5407 openEntity->startTagLevel = tagLevel;
5408 openEntity->betweenDecl = betweenDecl;
5409 openEntity->internalEventPtr = NULL;
5410 openEntity->internalEventEndPtr = NULL;
5411 textStart = (char *)entity->textPtr;
5412 textEnd = (char *)(entity->textPtr + entity->textLen);
5413 /* Set a safe default value in case 'next' does not get set */
5417 if (entity->is_param) {
5418 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
5419 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
5420 next, &next, XML_FALSE);
5423 #endif /* XML_DTD */
5424 result = doContent(parser, tagLevel, internalEncoding, textStart,
5425 textEnd, &next, XML_FALSE);
5427 if (result == XML_ERROR_NONE) {
5428 if (textEnd != next && ps_parsing == XML_SUSPENDED) {
5429 entity->processed = (int)(next - textStart);
5430 processor = internalEntityProcessor;
5433 entity->open = XML_FALSE;
5434 openInternalEntities = openEntity->next;
5435 /* put openEntity back in list of free instances */
5436 openEntity->next = freeInternalEntities;
5437 freeInternalEntities = openEntity;
5443 static enum XML_Error PTRCALL
5444 internalEntityProcessor(XML_Parser parser,
5447 const char **nextPtr)
5450 const char *textStart, *textEnd;
5452 enum XML_Error result;
5453 OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
5455 return XML_ERROR_UNEXPECTED_STATE;
5457 entity = openEntity->entity;
5458 textStart = ((char *)entity->textPtr) + entity->processed;
5459 textEnd = (char *)(entity->textPtr + entity->textLen);
5460 /* Set a safe default value in case 'next' does not get set */
5464 if (entity->is_param) {
5465 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
5466 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
5467 next, &next, XML_FALSE);
5470 #endif /* XML_DTD */
5471 result = doContent(parser, openEntity->startTagLevel, internalEncoding,
5472 textStart, textEnd, &next, XML_FALSE);
5474 if (result != XML_ERROR_NONE)
5476 else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
5477 entity->processed = (int)(next - (char *)entity->textPtr);
5481 entity->open = XML_FALSE;
5482 openInternalEntities = openEntity->next;
5483 /* put openEntity back in list of free instances */
5484 openEntity->next = freeInternalEntities;
5485 freeInternalEntities = openEntity;
5489 if (entity->is_param) {
5491 processor = prologProcessor;
5492 tok = XmlPrologTok(encoding, s, end, &next);
5493 return doProlog(parser, encoding, s, end, tok, next, nextPtr,
5494 (XML_Bool)!ps_finalBuffer);
5497 #endif /* XML_DTD */
5499 processor = contentProcessor;
5500 /* see externalEntityContentProcessor vs contentProcessor */
5501 return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
5502 nextPtr, (XML_Bool)!ps_finalBuffer);
5506 static enum XML_Error PTRCALL
5507 errorProcessor(XML_Parser parser,
5508 const char *UNUSED_P(s),
5509 const char *UNUSED_P(end),
5510 const char **UNUSED_P(nextPtr))
5515 static enum XML_Error
5516 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5517 const char *ptr, const char *end,
5520 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
5524 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
5526 if (!poolAppendChar(pool, XML_T('\0')))
5527 return XML_ERROR_NO_MEMORY;
5528 return XML_ERROR_NONE;
5531 static enum XML_Error
5532 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5533 const char *ptr, const char *end,
5536 DTD * const dtd = _dtd; /* save one level of indirection */
5539 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
5542 return XML_ERROR_NONE;
5543 case XML_TOK_INVALID:
5544 if (enc == encoding)
5546 return XML_ERROR_INVALID_TOKEN;
5547 case XML_TOK_PARTIAL:
5548 if (enc == encoding)
5550 return XML_ERROR_INVALID_TOKEN;
5551 case XML_TOK_CHAR_REF:
5553 XML_Char buf[XML_ENCODE_MAX];
5555 int n = XmlCharRefNumber(enc, ptr);
5557 if (enc == encoding)
5559 return XML_ERROR_BAD_CHAR_REF;
5562 && n == 0x20 /* space */
5563 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5565 n = XmlEncode(n, (ICHAR *)buf);
5566 /* The XmlEncode() functions can never return 0 here. That
5567 * error return happens if the code point passed in is either
5568 * negative or greater than or equal to 0x110000. The
5569 * XmlCharRefNumber() functions will all return a number
5570 * strictly less than 0x110000 or a negative value if an error
5571 * occurred. The negative value is intercepted above, so
5572 * XmlEncode() is never passed a value it might return an
5575 for (i = 0; i < n; i++) {
5576 if (!poolAppendChar(pool, buf[i]))
5577 return XML_ERROR_NO_MEMORY;
5581 case XML_TOK_DATA_CHARS:
5582 if (!poolAppend(pool, enc, ptr, next))
5583 return XML_ERROR_NO_MEMORY;
5585 case XML_TOK_TRAILING_CR:
5586 next = ptr + enc->minBytesPerChar;
5588 case XML_TOK_ATTRIBUTE_VALUE_S:
5589 case XML_TOK_DATA_NEWLINE:
5590 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5592 if (!poolAppendChar(pool, 0x20))
5593 return XML_ERROR_NO_MEMORY;
5595 case XML_TOK_ENTITY_REF:
5597 const XML_Char *name;
5599 char checkEntityDecl;
5600 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
5601 ptr + enc->minBytesPerChar,
5602 next - enc->minBytesPerChar);
5604 if (!poolAppendChar(pool, ch))
5605 return XML_ERROR_NO_MEMORY;
5608 name = poolStoreString(&temp2Pool, enc,
5609 ptr + enc->minBytesPerChar,
5610 next - enc->minBytesPerChar);
5612 return XML_ERROR_NO_MEMORY;
5613 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
5614 poolDiscard(&temp2Pool);
5615 /* First, determine if a check for an existing declaration is needed;
5616 if yes, check that the entity exists, and that it is internal.
5618 if (pool == &dtd->pool) /* are we called from prolog? */
5621 prologState.documentEntity &&
5622 #endif /* XML_DTD */
5624 ? !openInternalEntities
5625 : !dtd->hasParamEntityRefs);
5626 else /* if (pool == &tempPool): we are called from content */
5627 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
5628 if (checkEntityDecl) {
5630 return XML_ERROR_UNDEFINED_ENTITY;
5631 else if (!entity->is_internal)
5632 return XML_ERROR_ENTITY_DECLARED_IN_PE;
5635 /* Cannot report skipped entity here - see comments on
5636 skippedEntityHandler.
5637 if (skippedEntityHandler)
5638 skippedEntityHandler(handlerArg, name, 0);
5640 /* Cannot call the default handler because this would be
5641 out of sync with the call to the startElementHandler.
5642 if ((pool == &tempPool) && defaultHandler)
5643 reportDefault(parser, enc, ptr, next);
5648 if (enc == encoding) {
5649 /* It does not appear that this line can be executed.
5651 * The "if (entity->open)" check catches recursive entity
5652 * definitions. In order to be called with an open
5653 * entity, it must have gone through this code before and
5654 * been through the recursive call to
5655 * appendAttributeValue() some lines below. That call
5656 * sets the local encoding ("enc") to the parser's
5657 * internal encoding (internal_utf8 or internal_utf16),
5658 * which can never be the same as the principle encoding.
5659 * It doesn't appear there is another code path that gets
5660 * here with entity->open being TRUE.
5662 * Since it is not certain that this logic is watertight,
5663 * we keep the line and merely exclude it from coverage
5666 eventPtr = ptr; /* LCOV_EXCL_LINE */
5668 return XML_ERROR_RECURSIVE_ENTITY_REF;
5670 if (entity->notation) {
5671 if (enc == encoding)
5673 return XML_ERROR_BINARY_ENTITY_REF;
5675 if (!entity->textPtr) {
5676 if (enc == encoding)
5678 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
5681 enum XML_Error result;
5682 const XML_Char *textEnd = entity->textPtr + entity->textLen;
5683 entity->open = XML_TRUE;
5684 result = appendAttributeValue(parser, internalEncoding, isCdata,
5685 (char *)entity->textPtr,
5686 (char *)textEnd, pool);
5687 entity->open = XML_FALSE;
5694 /* The only token returned by XmlAttributeValueTok() that does
5695 * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
5696 * Getting that would require an entity name to contain an
5697 * incomplete XML character (e.g. \xE2\x82); however previous
5698 * tokenisers will have already recognised and rejected such
5699 * names before XmlAttributeValueTok() gets a look-in. This
5700 * default case should be retained as a safety net, but the code
5701 * excluded from coverage tests.
5705 if (enc == encoding)
5707 return XML_ERROR_UNEXPECTED_STATE;
5708 /* LCOV_EXCL_STOP */
5715 static enum XML_Error
5716 storeEntityValue(XML_Parser parser,
5717 const ENCODING *enc,
5718 const char *entityTextPtr,
5719 const char *entityTextEnd)
5721 DTD * const dtd = _dtd; /* save one level of indirection */
5722 STRING_POOL *pool = &(dtd->entityValuePool);
5723 enum XML_Error result = XML_ERROR_NONE;
5725 int oldInEntityValue = prologState.inEntityValue;
5726 prologState.inEntityValue = 1;
5727 #endif /* XML_DTD */
5728 /* never return Null for the value argument in EntityDeclHandler,
5729 since this would indicate an external entity; therefore we
5730 have to make sure that entityValuePool.start is not null */
5731 if (!pool->blocks) {
5732 if (!poolGrow(pool))
5733 return XML_ERROR_NO_MEMORY;
5738 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5740 case XML_TOK_PARAM_ENTITY_REF:
5742 if (isParamEntity || enc != encoding) {
5743 const XML_Char *name;
5745 name = poolStoreString(&tempPool, enc,
5746 entityTextPtr + enc->minBytesPerChar,
5747 next - enc->minBytesPerChar);
5749 result = XML_ERROR_NO_MEMORY;
5750 goto endEntityValue;
5752 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5753 poolDiscard(&tempPool);
5755 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5756 /* cannot report skipped entity here - see comments on
5757 skippedEntityHandler
5758 if (skippedEntityHandler)
5759 skippedEntityHandler(handlerArg, name, 0);
5761 dtd->keepProcessing = dtd->standalone;
5762 goto endEntityValue;
5765 if (enc == encoding)
5766 eventPtr = entityTextPtr;
5767 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5768 goto endEntityValue;
5770 if (entity->systemId) {
5771 if (externalEntityRefHandler) {
5772 dtd->paramEntityRead = XML_FALSE;
5773 entity->open = XML_TRUE;
5774 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5778 entity->publicId)) {
5779 entity->open = XML_FALSE;
5780 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5781 goto endEntityValue;
5783 entity->open = XML_FALSE;
5784 if (!dtd->paramEntityRead)
5785 dtd->keepProcessing = dtd->standalone;
5788 dtd->keepProcessing = dtd->standalone;
5791 entity->open = XML_TRUE;
5792 result = storeEntityValue(parser,
5794 (char *)entity->textPtr,
5795 (char *)(entity->textPtr
5796 + entity->textLen));
5797 entity->open = XML_FALSE;
5799 goto endEntityValue;
5803 #endif /* XML_DTD */
5804 /* In the internal subset, PE references are not legal
5805 within markup declarations, e.g entity values in this case. */
5806 eventPtr = entityTextPtr;
5807 result = XML_ERROR_PARAM_ENTITY_REF;
5808 goto endEntityValue;
5810 result = XML_ERROR_NONE;
5811 goto endEntityValue;
5812 case XML_TOK_ENTITY_REF:
5813 case XML_TOK_DATA_CHARS:
5814 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5815 result = XML_ERROR_NO_MEMORY;
5816 goto endEntityValue;
5819 case XML_TOK_TRAILING_CR:
5820 next = entityTextPtr + enc->minBytesPerChar;
5822 case XML_TOK_DATA_NEWLINE:
5823 if (pool->end == pool->ptr && !poolGrow(pool)) {
5824 result = XML_ERROR_NO_MEMORY;
5825 goto endEntityValue;
5827 *(pool->ptr)++ = 0xA;
5829 case XML_TOK_CHAR_REF:
5831 XML_Char buf[XML_ENCODE_MAX];
5833 int n = XmlCharRefNumber(enc, entityTextPtr);
5835 if (enc == encoding)
5836 eventPtr = entityTextPtr;
5837 result = XML_ERROR_BAD_CHAR_REF;
5838 goto endEntityValue;
5840 n = XmlEncode(n, (ICHAR *)buf);
5841 /* The XmlEncode() functions can never return 0 here. That
5842 * error return happens if the code point passed in is either
5843 * negative or greater than or equal to 0x110000. The
5844 * XmlCharRefNumber() functions will all return a number
5845 * strictly less than 0x110000 or a negative value if an error
5846 * occurred. The negative value is intercepted above, so
5847 * XmlEncode() is never passed a value it might return an
5850 for (i = 0; i < n; i++) {
5851 if (pool->end == pool->ptr && !poolGrow(pool)) {
5852 result = XML_ERROR_NO_MEMORY;
5853 goto endEntityValue;
5855 *(pool->ptr)++ = buf[i];
5859 case XML_TOK_PARTIAL:
5860 if (enc == encoding)
5861 eventPtr = entityTextPtr;
5862 result = XML_ERROR_INVALID_TOKEN;
5863 goto endEntityValue;
5864 case XML_TOK_INVALID:
5865 if (enc == encoding)
5867 result = XML_ERROR_INVALID_TOKEN;
5868 goto endEntityValue;
5870 /* This default case should be unnecessary -- all the tokens
5871 * that XmlEntityValueTok() can return have their own explicit
5872 * cases -- but should be retained for safety. We do however
5873 * exclude it from the coverage statistics.
5877 if (enc == encoding)
5878 eventPtr = entityTextPtr;
5879 result = XML_ERROR_UNEXPECTED_STATE;
5880 goto endEntityValue;
5881 /* LCOV_EXCL_STOP */
5883 entityTextPtr = next;
5887 prologState.inEntityValue = oldInEntityValue;
5888 #endif /* XML_DTD */
5892 static void FASTCALL
5893 normalizeLines(XML_Char *s)
5897 if (*s == XML_T('\0'))
5916 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5917 const char *start, const char *end)
5919 const XML_Char *target;
5922 if (!processingInstructionHandler) {
5924 reportDefault(parser, enc, start, end);
5927 start += enc->minBytesPerChar * 2;
5928 tem = start + XmlNameLength(enc, start);
5929 target = poolStoreString(&tempPool, enc, start, tem);
5932 poolFinish(&tempPool);
5933 data = poolStoreString(&tempPool, enc,
5935 end - enc->minBytesPerChar*2);
5938 normalizeLines(data);
5939 processingInstructionHandler(handlerArg, target, data);
5940 poolClear(&tempPool);
5945 reportComment(XML_Parser parser, const ENCODING *enc,
5946 const char *start, const char *end)
5949 if (!commentHandler) {
5951 reportDefault(parser, enc, start, end);
5954 data = poolStoreString(&tempPool,
5956 start + enc->minBytesPerChar * 4,
5957 end - enc->minBytesPerChar * 3);
5960 normalizeLines(data);
5961 commentHandler(handlerArg, data);
5962 poolClear(&tempPool);
5967 reportDefault(XML_Parser parser, const ENCODING *enc,
5968 const char *s, const char *end)
5970 if (MUST_CONVERT(enc, s)) {
5971 enum XML_Convert_Result convert_res;
5972 const char **eventPP;
5973 const char **eventEndPP;
5974 if (enc == encoding) {
5975 eventPP = &eventPtr;
5976 eventEndPP = &eventEndPtr;
5979 /* To get here, two things must be true; the parser must be
5980 * using a character encoding that is not the same as the
5981 * encoding passed in, and the encoding passed in must need
5982 * conversion to the internal format (UTF-8 unless XML_UNICODE
5983 * is defined). The only occasions on which the encoding passed
5984 * in is not the same as the parser's encoding are when it is
5985 * the internal encoding (e.g. a previously defined parameter
5986 * entity, already converted to internal format). This by
5987 * definition doesn't need conversion, so the whole branch never
5990 * For safety's sake we don't delete these lines and merely
5991 * exclude them from coverage statistics.
5995 eventPP = &(openInternalEntities->internalEventPtr);
5996 eventEndPP = &(openInternalEntities->internalEventEndPtr);
5997 /* LCOV_EXCL_STOP */
6000 ICHAR *dataPtr = (ICHAR *)dataBuf;
6001 convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
6003 defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
6005 } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
6008 defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
6013 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
6014 XML_Bool isId, const XML_Char *value, XML_Parser parser)
6016 DEFAULT_ATTRIBUTE *att;
6017 if (value || isId) {
6018 /* The handling of default attributes gets messed up if we have
6019 a default which duplicates a non-default. */
6021 for (i = 0; i < type->nDefaultAtts; i++)
6022 if (attId == type->defaultAtts[i].id)
6024 if (isId && !type->idAtt && !attId->xmlns)
6025 type->idAtt = attId;
6027 if (type->nDefaultAtts == type->allocDefaultAtts) {
6028 if (type->allocDefaultAtts == 0) {
6029 type->allocDefaultAtts = 8;
6030 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
6031 * sizeof(DEFAULT_ATTRIBUTE));
6032 if (!type->defaultAtts)
6036 DEFAULT_ATTRIBUTE *temp;
6037 int count = type->allocDefaultAtts * 2;
6038 temp = (DEFAULT_ATTRIBUTE *)
6039 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
6042 type->allocDefaultAtts = count;
6043 type->defaultAtts = temp;
6046 att = type->defaultAtts + type->nDefaultAtts;
6049 att->isCdata = isCdata;
6051 attId->maybeTokenized = XML_TRUE;
6052 type->nDefaultAtts += 1;
6057 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
6059 DTD * const dtd = _dtd; /* save one level of indirection */
6060 const XML_Char *name;
6061 for (name = elementType->name; *name; name++) {
6062 if (*name == XML_T(ASCII_COLON)) {
6065 for (s = elementType->name; s != name; s++) {
6066 if (!poolAppendChar(&dtd->pool, *s))
6069 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6071 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
6075 if (prefix->name == poolStart(&dtd->pool))
6076 poolFinish(&dtd->pool);
6078 poolDiscard(&dtd->pool);
6079 elementType->prefix = prefix;
6086 static ATTRIBUTE_ID *
6087 getAttributeId(XML_Parser parser, const ENCODING *enc,
6088 const char *start, const char *end)
6090 DTD * const dtd = _dtd; /* save one level of indirection */
6092 const XML_Char *name;
6093 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6095 name = poolStoreString(&dtd->pool, enc, start, end);
6098 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
6100 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
6103 if (id->name != name)
6104 poolDiscard(&dtd->pool);
6106 poolFinish(&dtd->pool);
6109 else if (name[0] == XML_T(ASCII_x)
6110 && name[1] == XML_T(ASCII_m)
6111 && name[2] == XML_T(ASCII_l)
6112 && name[3] == XML_T(ASCII_n)
6113 && name[4] == XML_T(ASCII_s)
6114 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
6115 if (name[5] == XML_T('\0'))
6116 id->prefix = &dtd->defaultPrefix;
6118 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
6119 id->xmlns = XML_TRUE;
6123 for (i = 0; name[i]; i++) {
6124 /* attributes without prefix are *not* in the default namespace */
6125 if (name[i] == XML_T(ASCII_COLON)) {
6127 for (j = 0; j < i; j++) {
6128 if (!poolAppendChar(&dtd->pool, name[j]))
6131 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6133 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
6137 if (id->prefix->name == poolStart(&dtd->pool))
6138 poolFinish(&dtd->pool);
6140 poolDiscard(&dtd->pool);
6149 #define CONTEXT_SEP XML_T(ASCII_FF)
6151 static const XML_Char *
6152 getContext(XML_Parser parser)
6154 DTD * const dtd = _dtd; /* save one level of indirection */
6155 HASH_TABLE_ITER iter;
6156 XML_Bool needSep = XML_FALSE;
6158 if (dtd->defaultPrefix.binding) {
6161 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
6163 len = dtd->defaultPrefix.binding->uriLen;
6164 if (namespaceSeparator)
6166 for (i = 0; i < len; i++) {
6167 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i])) {
6168 /* Because of memory caching, I don't believe this line can be
6171 * This is part of a loop copying the default prefix binding
6172 * URI into the parser's temporary string pool. Previously,
6173 * that URI was copied into the same string pool, with a
6174 * terminating NUL character, as part of setContext(). When
6175 * the pool was cleared, that leaves a block definitely big
6176 * enough to hold the URI on the free block list of the pool.
6177 * The URI copy in getContext() therefore cannot run out of
6180 * If the pool is used between the setContext() and
6181 * getContext() calls, the worst it can do is leave a bigger
6182 * block on the front of the free list. Given that this is
6183 * all somewhat inobvious and program logic can be changed, we
6184 * don't delete the line but we do exclude it from the test
6185 * coverage statistics.
6187 return NULL; /* LCOV_EXCL_LINE */
6193 hashTableIterInit(&iter, &(dtd->prefixes));
6198 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
6201 if (!prefix->binding) {
6202 /* This test appears to be (justifiable) paranoia. There does
6203 * not seem to be a way of injecting a prefix without a binding
6204 * that doesn't get errored long before this function is called.
6205 * The test should remain for safety's sake, so we instead
6206 * exclude the following line from the coverage statistics.
6208 continue; /* LCOV_EXCL_LINE */
6210 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
6212 for (s = prefix->name; *s; s++)
6213 if (!poolAppendChar(&tempPool, *s))
6215 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
6217 len = prefix->binding->uriLen;
6218 if (namespaceSeparator)
6220 for (i = 0; i < len; i++)
6221 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
6227 hashTableIterInit(&iter, &(dtd->generalEntities));
6230 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
6235 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
6237 for (s = e->name; *s; s++)
6238 if (!poolAppendChar(&tempPool, *s))
6243 if (!poolAppendChar(&tempPool, XML_T('\0')))
6245 return tempPool.start;
6249 setContext(XML_Parser parser, const XML_Char *context)
6251 DTD * const dtd = _dtd; /* save one level of indirection */
6252 const XML_Char *s = context;
6254 while (*context != XML_T('\0')) {
6255 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
6257 if (!poolAppendChar(&tempPool, XML_T('\0')))
6259 e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
6262 if (*s != XML_T('\0'))
6265 poolDiscard(&tempPool);
6267 else if (*s == XML_T(ASCII_EQUALS)) {
6269 if (poolLength(&tempPool) == 0)
6270 prefix = &dtd->defaultPrefix;
6272 if (!poolAppendChar(&tempPool, XML_T('\0')))
6274 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
6278 if (prefix->name == poolStart(&tempPool)) {
6279 prefix->name = poolCopyString(&dtd->pool, prefix->name);
6283 poolDiscard(&tempPool);
6285 for (context = s + 1;
6286 *context != CONTEXT_SEP && *context != XML_T('\0');
6288 if (!poolAppendChar(&tempPool, *context))
6290 if (!poolAppendChar(&tempPool, XML_T('\0')))
6292 if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
6293 &inheritedBindings) != XML_ERROR_NONE)
6295 poolDiscard(&tempPool);
6296 if (*context != XML_T('\0'))
6301 if (!poolAppendChar(&tempPool, *s))
6309 static void FASTCALL
6310 normalizePublicId(XML_Char *publicId)
6312 XML_Char *p = publicId;
6314 for (s = publicId; *s; s++) {
6319 if (p != publicId && p[-1] != 0x20)
6326 if (p != publicId && p[-1] == 0x20)
6332 dtdCreate(const XML_Memory_Handling_Suite *ms)
6334 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
6337 poolInit(&(p->pool), ms);
6338 poolInit(&(p->entityValuePool), ms);
6339 hashTableInit(&(p->generalEntities), ms);
6340 hashTableInit(&(p->elementTypes), ms);
6341 hashTableInit(&(p->attributeIds), ms);
6342 hashTableInit(&(p->prefixes), ms);
6344 p->paramEntityRead = XML_FALSE;
6345 hashTableInit(&(p->paramEntities), ms);
6346 #endif /* XML_DTD */
6347 p->defaultPrefix.name = NULL;
6348 p->defaultPrefix.binding = NULL;
6350 p->in_eldecl = XML_FALSE;
6351 p->scaffIndex = NULL;
6356 p->contentStringLen = 0;
6358 p->keepProcessing = XML_TRUE;
6359 p->hasParamEntityRefs = XML_FALSE;
6360 p->standalone = XML_FALSE;
6365 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
6367 HASH_TABLE_ITER iter;
6368 hashTableIterInit(&iter, &(p->elementTypes));
6370 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6373 if (e->allocDefaultAtts != 0)
6374 ms->free_fcn(e->defaultAtts);
6376 hashTableClear(&(p->generalEntities));
6378 p->paramEntityRead = XML_FALSE;
6379 hashTableClear(&(p->paramEntities));
6380 #endif /* XML_DTD */
6381 hashTableClear(&(p->elementTypes));
6382 hashTableClear(&(p->attributeIds));
6383 hashTableClear(&(p->prefixes));
6384 poolClear(&(p->pool));
6385 poolClear(&(p->entityValuePool));
6386 p->defaultPrefix.name = NULL;
6387 p->defaultPrefix.binding = NULL;
6389 p->in_eldecl = XML_FALSE;
6391 ms->free_fcn(p->scaffIndex);
6392 p->scaffIndex = NULL;
6393 ms->free_fcn(p->scaffold);
6399 p->contentStringLen = 0;
6401 p->keepProcessing = XML_TRUE;
6402 p->hasParamEntityRefs = XML_FALSE;
6403 p->standalone = XML_FALSE;
6407 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
6409 HASH_TABLE_ITER iter;
6410 hashTableIterInit(&iter, &(p->elementTypes));
6412 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6415 if (e->allocDefaultAtts != 0)
6416 ms->free_fcn(e->defaultAtts);
6418 hashTableDestroy(&(p->generalEntities));
6420 hashTableDestroy(&(p->paramEntities));
6421 #endif /* XML_DTD */
6422 hashTableDestroy(&(p->elementTypes));
6423 hashTableDestroy(&(p->attributeIds));
6424 hashTableDestroy(&(p->prefixes));
6425 poolDestroy(&(p->pool));
6426 poolDestroy(&(p->entityValuePool));
6428 ms->free_fcn(p->scaffIndex);
6429 ms->free_fcn(p->scaffold);
6434 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
6435 The new DTD has already been initialized.
6438 dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
6440 HASH_TABLE_ITER iter;
6442 /* Copy the prefix table. */
6444 hashTableIterInit(&iter, &(oldDtd->prefixes));
6446 const XML_Char *name;
6447 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
6450 name = poolCopyString(&(newDtd->pool), oldP->name);
6453 if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
6457 hashTableIterInit(&iter, &(oldDtd->attributeIds));
6459 /* Copy the attribute id table. */
6463 const XML_Char *name;
6464 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
6468 /* Remember to allocate the scratch byte before the name. */
6469 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
6471 name = poolCopyString(&(newDtd->pool), oldA->name);
6475 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
6476 sizeof(ATTRIBUTE_ID));
6479 newA->maybeTokenized = oldA->maybeTokenized;
6481 newA->xmlns = oldA->xmlns;
6482 if (oldA->prefix == &oldDtd->defaultPrefix)
6483 newA->prefix = &newDtd->defaultPrefix;
6485 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
6486 oldA->prefix->name, 0);
6490 /* Copy the element type table. */
6492 hashTableIterInit(&iter, &(oldDtd->elementTypes));
6497 const XML_Char *name;
6498 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6501 name = poolCopyString(&(newDtd->pool), oldE->name);
6504 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
6505 sizeof(ELEMENT_TYPE));
6508 if (oldE->nDefaultAtts) {
6509 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
6510 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6511 if (!newE->defaultAtts) {
6516 newE->idAtt = (ATTRIBUTE_ID *)
6517 lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
6518 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
6520 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
6521 oldE->prefix->name, 0);
6522 for (i = 0; i < newE->nDefaultAtts; i++) {
6523 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
6524 lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
6525 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
6526 if (oldE->defaultAtts[i].value) {
6527 newE->defaultAtts[i].value
6528 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
6529 if (!newE->defaultAtts[i].value)
6533 newE->defaultAtts[i].value = NULL;
6537 /* Copy the entity tables. */
6538 if (!copyEntityTable(oldParser,
6539 &(newDtd->generalEntities),
6541 &(oldDtd->generalEntities)))
6545 if (!copyEntityTable(oldParser,
6546 &(newDtd->paramEntities),
6548 &(oldDtd->paramEntities)))
6550 newDtd->paramEntityRead = oldDtd->paramEntityRead;
6551 #endif /* XML_DTD */
6553 newDtd->keepProcessing = oldDtd->keepProcessing;
6554 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
6555 newDtd->standalone = oldDtd->standalone;
6557 /* Don't want deep copying for scaffolding */
6558 newDtd->in_eldecl = oldDtd->in_eldecl;
6559 newDtd->scaffold = oldDtd->scaffold;
6560 newDtd->contentStringLen = oldDtd->contentStringLen;
6561 newDtd->scaffSize = oldDtd->scaffSize;
6562 newDtd->scaffLevel = oldDtd->scaffLevel;
6563 newDtd->scaffIndex = oldDtd->scaffIndex;
6569 copyEntityTable(XML_Parser oldParser,
6570 HASH_TABLE *newTable,
6571 STRING_POOL *newPool,
6572 const HASH_TABLE *oldTable)
6574 HASH_TABLE_ITER iter;
6575 const XML_Char *cachedOldBase = NULL;
6576 const XML_Char *cachedNewBase = NULL;
6578 hashTableIterInit(&iter, oldTable);
6582 const XML_Char *name;
6583 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
6586 name = poolCopyString(newPool, oldE->name);
6589 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
6592 if (oldE->systemId) {
6593 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
6596 newE->systemId = tem;
6598 if (oldE->base == cachedOldBase)
6599 newE->base = cachedNewBase;
6601 cachedOldBase = oldE->base;
6602 tem = poolCopyString(newPool, cachedOldBase);
6605 cachedNewBase = newE->base = tem;
6608 if (oldE->publicId) {
6609 tem = poolCopyString(newPool, oldE->publicId);
6612 newE->publicId = tem;
6616 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
6620 newE->textPtr = tem;
6621 newE->textLen = oldE->textLen;
6623 if (oldE->notation) {
6624 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
6627 newE->notation = tem;
6629 newE->is_param = oldE->is_param;
6630 newE->is_internal = oldE->is_internal;
6635 #define INIT_POWER 6
6637 static XML_Bool FASTCALL
6638 keyeq(KEY s1, KEY s2)
6640 for (; *s1 == *s2; s1++, s2++)
6650 for (; *s; s++, len++);
6655 copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key)
6658 key->k[1] = get_hash_secret_salt(parser);
6661 static unsigned long FASTCALL
6662 hash(XML_Parser parser, KEY s)
6664 struct siphash state;
6668 copy_salt_to_sipkey(parser, &key);
6669 sip24_init(&state, &key);
6670 sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
6671 return (unsigned long)sip24_final(&state);
6675 lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
6678 if (table->size == 0) {
6682 table->power = INIT_POWER;
6683 /* table->size is a power of 2 */
6684 table->size = (size_t)1 << INIT_POWER;
6685 tsize = table->size * sizeof(NAMED *);
6686 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
6691 memset(table->v, 0, tsize);
6692 i = hash(parser, name) & ((unsigned long)table->size - 1);
6695 unsigned long h = hash(parser, name);
6696 unsigned long mask = (unsigned long)table->size - 1;
6697 unsigned char step = 0;
6699 while (table->v[i]) {
6700 if (keyeq(name, table->v[i]->name))
6703 step = PROBE_STEP(h, mask, table->power);
6704 i < step ? (i += table->size - step) : (i -= step);
6709 /* check for overflow (table is half full) */
6710 if (table->used >> (table->power - 1)) {
6711 unsigned char newPower = table->power + 1;
6712 size_t newSize = (size_t)1 << newPower;
6713 unsigned long newMask = (unsigned long)newSize - 1;
6714 size_t tsize = newSize * sizeof(NAMED *);
6715 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
6718 memset(newV, 0, tsize);
6719 for (i = 0; i < table->size; i++)
6721 unsigned long newHash = hash(parser, table->v[i]->name);
6722 size_t j = newHash & newMask;
6726 step = PROBE_STEP(newHash, newMask, newPower);
6727 j < step ? (j += newSize - step) : (j -= step);
6729 newV[j] = table->v[i];
6731 table->mem->free_fcn(table->v);
6733 table->power = newPower;
6734 table->size = newSize;
6737 while (table->v[i]) {
6739 step = PROBE_STEP(h, newMask, newPower);
6740 i < step ? (i += newSize - step) : (i -= step);
6744 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
6747 memset(table->v[i], 0, createSize);
6748 table->v[i]->name = name;
6753 static void FASTCALL
6754 hashTableClear(HASH_TABLE *table)
6757 for (i = 0; i < table->size; i++) {
6758 table->mem->free_fcn(table->v[i]);
6764 static void FASTCALL
6765 hashTableDestroy(HASH_TABLE *table)
6768 for (i = 0; i < table->size; i++)
6769 table->mem->free_fcn(table->v[i]);
6770 table->mem->free_fcn(table->v);
6773 static void FASTCALL
6774 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
6783 static void FASTCALL
6784 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
6787 iter->end = iter->p + table->size;
6790 static NAMED * FASTCALL
6791 hashTableIterNext(HASH_TABLE_ITER *iter)
6793 while (iter->p != iter->end) {
6794 NAMED *tem = *(iter->p)++;
6801 static void FASTCALL
6802 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
6804 pool->blocks = NULL;
6805 pool->freeBlocks = NULL;
6812 static void FASTCALL
6813 poolClear(STRING_POOL *pool)
6815 if (!pool->freeBlocks)
6816 pool->freeBlocks = pool->blocks;
6818 BLOCK *p = pool->blocks;
6820 BLOCK *tem = p->next;
6821 p->next = pool->freeBlocks;
6822 pool->freeBlocks = p;
6826 pool->blocks = NULL;
6832 static void FASTCALL
6833 poolDestroy(STRING_POOL *pool)
6835 BLOCK *p = pool->blocks;
6837 BLOCK *tem = p->next;
6838 pool->mem->free_fcn(p);
6841 p = pool->freeBlocks;
6843 BLOCK *tem = p->next;
6844 pool->mem->free_fcn(p);
6850 poolAppend(STRING_POOL *pool, const ENCODING *enc,
6851 const char *ptr, const char *end)
6853 if (!pool->ptr && !poolGrow(pool))
6856 const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6857 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
6859 if (!poolGrow(pool))
6865 static const XML_Char * FASTCALL
6866 poolCopyString(STRING_POOL *pool, const XML_Char *s)
6869 if (!poolAppendChar(pool, *s))
6877 static const XML_Char *
6878 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6880 if (!pool->ptr && !poolGrow(pool)) {
6881 /* The following line is unreachable given the current usage of
6882 * poolCopyStringN(). Currently it is called from exactly one
6883 * place to copy the text of a simple general entity. By that
6884 * point, the name of the entity is already stored in the pool, so
6885 * pool->ptr cannot be NULL.
6887 * If poolCopyStringN() is used elsewhere as it well might be,
6888 * this line may well become executable again. Regardless, this
6889 * sort of check shouldn't be removed lightly, so we just exclude
6890 * it from the coverage statistics.
6892 return NULL; /* LCOV_EXCL_LINE */
6894 for (; n > 0; --n, s++) {
6895 if (!poolAppendChar(pool, *s))
6903 static const XML_Char * FASTCALL
6904 poolAppendString(STRING_POOL *pool, const XML_Char *s)
6907 if (!poolAppendChar(pool, *s))
6915 poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6916 const char *ptr, const char *end)
6918 if (!poolAppend(pool, enc, ptr, end))
6920 if (pool->ptr == pool->end && !poolGrow(pool))
6927 poolBytesToAllocateFor(int blockSize)
6929 /* Unprotected math would be:
6930 ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
6932 ** Detect overflow, avoiding _signed_ overflow undefined behavior
6933 ** For a + b * c we check b * c in isolation first, so that addition of a
6934 ** on top has no chance of making us accept a small non-negative number
6936 const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
6941 if (blockSize > (int)(INT_MAX / stretch))
6945 const int stretchedBlockSize = blockSize * (int)stretch;
6946 const int bytesToAllocate = (int)(
6947 offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
6948 if (bytesToAllocate < 0)
6951 return (size_t)bytesToAllocate;
6955 static XML_Bool FASTCALL
6956 poolGrow(STRING_POOL *pool)
6958 if (pool->freeBlocks) {
6959 if (pool->start == 0) {
6960 pool->blocks = pool->freeBlocks;
6961 pool->freeBlocks = pool->freeBlocks->next;
6962 pool->blocks->next = NULL;
6963 pool->start = pool->blocks->s;
6964 pool->end = pool->start + pool->blocks->size;
6965 pool->ptr = pool->start;
6968 if (pool->end - pool->start < pool->freeBlocks->size) {
6969 BLOCK *tem = pool->freeBlocks->next;
6970 pool->freeBlocks->next = pool->blocks;
6971 pool->blocks = pool->freeBlocks;
6972 pool->freeBlocks = tem;
6973 memcpy(pool->blocks->s, pool->start,
6974 (pool->end - pool->start) * sizeof(XML_Char));
6975 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6976 pool->start = pool->blocks->s;
6977 pool->end = pool->start + pool->blocks->size;
6981 if (pool->blocks && pool->start == pool->blocks->s) {
6983 int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
6984 size_t bytesToAllocate;
6986 // NOTE: Needs to be calculated prior to calling `realloc`
6987 // to avoid dangling pointers:
6988 const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
6990 if (blockSize < 0) {
6991 /* This condition traps a situation where either more than
6992 * INT_MAX/2 bytes have already been allocated. This isn't
6993 * readily testable, since it is unlikely that an average
6994 * machine will have that much memory, so we exclude it from the
6995 * coverage statistics.
6997 return XML_FALSE; /* LCOV_EXCL_LINE */
7000 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7001 if (bytesToAllocate == 0)
7005 pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate);
7008 pool->blocks = temp;
7009 pool->blocks->size = blockSize;
7010 pool->ptr = pool->blocks->s + offsetInsideBlock;
7011 pool->start = pool->blocks->s;
7012 pool->end = pool->start + blockSize;
7016 int blockSize = (int)(pool->end - pool->start);
7017 size_t bytesToAllocate;
7019 if (blockSize < 0) {
7020 /* This condition traps a situation where either more than
7021 * INT_MAX bytes have already been allocated (which is prevented
7022 * by various pieces of program logic, not least this one, never
7023 * mind the unlikelihood of actually having that much memory) or
7024 * the pool control fields have been corrupted (which could
7025 * conceivably happen in an extremely buggy user handler
7026 * function). Either way it isn't readily testable, so we
7027 * exclude it from the coverage statistics.
7029 return XML_FALSE; /* LCOV_EXCL_LINE */
7032 if (blockSize < INIT_BLOCK_SIZE)
7033 blockSize = INIT_BLOCK_SIZE;
7035 /* Detect overflow, avoiding _signed_ overflow undefined behavior */
7036 if ((int)((unsigned)blockSize * 2U) < 0) {
7042 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7043 if (bytesToAllocate == 0)
7046 tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
7049 tem->size = blockSize;
7050 tem->next = pool->blocks;
7052 if (pool->ptr != pool->start)
7053 memcpy(tem->s, pool->start,
7054 (pool->ptr - pool->start) * sizeof(XML_Char));
7055 pool->ptr = tem->s + (pool->ptr - pool->start);
7056 pool->start = tem->s;
7057 pool->end = tem->s + blockSize;
7063 nextScaffoldPart(XML_Parser parser)
7065 DTD * const dtd = _dtd; /* save one level of indirection */
7066 CONTENT_SCAFFOLD * me;
7069 if (!dtd->scaffIndex) {
7070 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
7071 if (!dtd->scaffIndex)
7073 dtd->scaffIndex[0] = 0;
7076 if (dtd->scaffCount >= dtd->scaffSize) {
7077 CONTENT_SCAFFOLD *temp;
7078 if (dtd->scaffold) {
7079 temp = (CONTENT_SCAFFOLD *)
7080 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
7083 dtd->scaffSize *= 2;
7086 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
7087 * sizeof(CONTENT_SCAFFOLD));
7090 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
7092 dtd->scaffold = temp;
7094 next = dtd->scaffCount++;
7095 me = &dtd->scaffold[next];
7096 if (dtd->scaffLevel) {
7097 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
7098 if (parent->lastchild) {
7099 dtd->scaffold[parent->lastchild].nextsib = next;
7101 if (!parent->childcnt)
7102 parent->firstchild = next;
7103 parent->lastchild = next;
7106 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
7111 build_node(XML_Parser parser,
7114 XML_Content **contpos,
7117 DTD * const dtd = _dtd; /* save one level of indirection */
7118 dest->type = dtd->scaffold[src_node].type;
7119 dest->quant = dtd->scaffold[src_node].quant;
7120 if (dest->type == XML_CTYPE_NAME) {
7121 const XML_Char *src;
7122 dest->name = *strpos;
7123 src = dtd->scaffold[src_node].name;
7125 *(*strpos)++ = *src;
7130 dest->numchildren = 0;
7131 dest->children = NULL;
7136 dest->numchildren = dtd->scaffold[src_node].childcnt;
7137 dest->children = *contpos;
7138 *contpos += dest->numchildren;
7139 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
7140 i < dest->numchildren;
7141 i++, cn = dtd->scaffold[cn].nextsib) {
7142 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
7148 static XML_Content *
7149 build_model (XML_Parser parser)
7151 DTD * const dtd = _dtd; /* save one level of indirection */
7155 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
7156 + (dtd->contentStringLen * sizeof(XML_Char)));
7158 ret = (XML_Content *)MALLOC(allocsize);
7162 str = (XML_Char *) (&ret[dtd->scaffCount]);
7165 build_node(parser, 0, ret, &cpos, &str);
7169 static ELEMENT_TYPE *
7170 getElementType(XML_Parser parser,
7171 const ENCODING *enc,
7175 DTD * const dtd = _dtd; /* save one level of indirection */
7176 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
7181 ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
7184 if (ret->name != name)
7185 poolDiscard(&dtd->pool);
7187 poolFinish(&dtd->pool);
7188 if (!setElementTypePrefix(parser, ret))
7195 copyString(const XML_Char *s,
7196 const XML_Memory_Handling_Suite *memsuite)
7198 int charsRequired = 0;
7201 /* First determine how long the string is */
7202 while (s[charsRequired] != 0) {
7205 /* Include the terminator */
7208 /* Now allocate space for the copy */
7209 result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
7212 /* Copy the original into place */
7213 memcpy(result, s, charsRequired * sizeof(XML_Char));