1 /* f519f27c7c3b79fee55aeb8b1e53b7384b079d9118bf3a62eb3a60986a6742f2 (2.2.9+)
4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
9 Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10 Copyright (c) 2000-2017 Expat development team
11 Licensed under the MIT license:
13 Permission is hereby granted, free of charge, to any person obtaining
14 a copy of this software and associated documentation files (the
15 "Software"), to deal in the Software without restriction, including
16 without limitation the rights to use, copy, modify, merge, publish,
17 distribute, sublicense, and/or sell copies of the Software, and to permit
18 persons to whom the Software is furnished to do so, subject to the
21 The above copyright notice and this permission notice shall be included
22 in all copies or substantial portions of the Software.
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
29 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30 USE OR OTHER DEALINGS IN THE SOFTWARE.
33 #if ! defined(_GNU_SOURCE)
34 # define _GNU_SOURCE 1 /* syscall prototype */
38 /* force stdlib to define rand_s() */
39 # if ! defined(_CRT_RAND_S)
45 #include <string.h> /* memset(), memcpy() */
47 #include <limits.h> /* UINT_MAX */
48 #include <stdio.h> /* fprintf */
49 #include <stdlib.h> /* getenv, rand_s */
52 # define getpid GetCurrentProcessId
54 # include <sys/time.h> /* gettimeofday() */
55 # include <sys/types.h> /* getpid() */
56 # include <unistd.h> /* getpid() */
57 # include <fcntl.h> /* O_RDONLY */
61 #define XML_BUILDING_EXPAT 1
64 # include "winconfig.h"
65 #elif defined(HAVE_EXPAT_CONFIG_H)
66 # include <expat_config.h>
67 #endif /* ndef _WIN32 */
73 #if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
74 # if defined(HAVE_GETRANDOM)
75 # include <sys/random.h> /* getrandom */
77 # include <unistd.h> /* syscall */
78 # include <sys/syscall.h> /* SYS_getrandom */
80 # if ! defined(GRND_NONBLOCK)
81 # define GRND_NONBLOCK 0x0001
82 # endif /* defined(GRND_NONBLOCK) */
83 #endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
85 #if defined(HAVE_LIBBSD) \
86 && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
87 # include <bsd/stdlib.h>
90 #if defined(_WIN32) && ! defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
91 # define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
94 #if ! defined(HAVE_GETRANDOM) && ! defined(HAVE_SYSCALL_GETRANDOM) \
95 && ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) \
96 && ! defined(XML_DEV_URANDOM) && ! defined(_WIN32) \
97 && ! defined(XML_POOR_ENTROPY)
98 # error You do not have support for any sources of high quality entropy \
99 enabled. For end user security, that is probably not what you want. \
101 Your options include: \
102 * Linux + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \
103 * Linux + glibc <2.25 (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \
104 * BSD / macOS >=10.7 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \
105 * BSD / macOS <10.7 (arc4random): HAVE_ARC4RANDOM, \
106 * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
107 * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
108 * Linux / BSD / macOS (/dev/urandom): XML_DEV_URANDOM \
109 * Windows (rand_s): _WIN32. \
111 If insist on not using any of these, bypass this error by defining \
112 XML_POOR_ENTROPY; you have been warned. \
114 If you have reasons to patch this detection code away or need changes \
115 to the build system, please open a bug. Thank you!
119 # define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
120 # define XmlConvert XmlUtf16Convert
121 # define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
122 # define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
123 # define XmlEncode XmlUtf16Encode
124 /* Using pointer subtraction to convert to integer type. */
125 # define MUST_CONVERT(enc, s) \
126 (! (enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
127 typedef unsigned short ICHAR;
129 # define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
130 # define XmlConvert XmlUtf8Convert
131 # define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
132 # define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
133 # define XmlEncode XmlUtf8Encode
134 # define MUST_CONVERT(enc, s) (! (enc)->isUtf8)
140 # define XmlInitEncodingNS XmlInitEncoding
141 # define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
142 # undef XmlGetInternalEncodingNS
143 # define XmlGetInternalEncodingNS XmlGetInternalEncoding
144 # define XmlParseXmlDeclNS XmlParseXmlDecl
150 # ifdef XML_UNICODE_WCHAR_T
151 # define XML_T(x) (const wchar_t) x
152 # define XML_L(x) L##x
154 # define XML_T(x) (const unsigned short)x
165 /* Round up n to be a multiple of sz, where sz is a power of 2. */
166 #define ROUND_UP(n, sz) (((n) + ((sz)-1)) & ~((sz)-1))
168 /* Do safe (NULL-aware) pointer arithmetic */
169 #define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
171 #include "internal.h"
175 typedef const XML_Char *KEY;
186 const XML_Memory_Handling_Suite *mem;
189 static size_t keylen(KEY s);
191 static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key);
193 /* For probing (after a collision) we need a step size relative prime
194 to the hash table size, which is a power of 2. We use double-hashing,
195 since we can calculate a second hash value cheaply by taking those bits
196 of the first hash value that were discarded (masked out) when the table
197 index was calculated: index = hash & mask, where mask = table->size - 1.
198 We limit the maximum step size to table->size / 4 (mask >> 2) and make
199 it odd, since odd numbers are always relative prime to a power of 2.
201 #define SECOND_HASH(hash, mask, power) \
202 ((((hash) & ~(mask)) >> ((power)-1)) & ((mask) >> 2))
203 #define PROBE_STEP(hash, mask, power) \
204 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
211 #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
212 #define INIT_DATA_BUF_SIZE 1024
213 #define INIT_ATTS_SIZE 16
214 #define INIT_ATTS_VERSION 0xFFFFFFFF
215 #define INIT_BLOCK_SIZE 1024
216 #define INIT_BUFFER_SIZE 1024
218 #define EXPAND_SPARE 24
220 typedef struct binding {
221 struct prefix *prefix;
222 struct binding *nextTagBinding;
223 struct binding *prevPrefixBinding;
224 const struct attribute_id *attId;
230 typedef struct prefix {
231 const XML_Char *name;
237 const XML_Char *localPart;
238 const XML_Char *prefix;
244 /* TAG represents an open element.
245 The name of the element is stored in both the document and API
246 encodings. The memory buffer 'buf' is a separately-allocated
247 memory area which stores the name. During the XML_Parse()/
248 XMLParseBuffer() when the element is open, the memory for the 'raw'
249 version of the name (in the document encoding) is shared with the
250 document buffer. If the element is open across calls to
251 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
252 contain the 'raw' name as well.
254 A parser re-uses these structures, maintaining a list of allocated
255 TAG objects in a free list.
258 struct tag *parent; /* parent of this element */
259 const char *rawName; /* tagName in the original encoding */
261 TAG_NAME name; /* tagName in the API encoding */
262 char *buf; /* buffer for name components */
263 char *bufEnd; /* end of the buffer */
268 const XML_Char *name;
269 const XML_Char *textPtr;
270 int textLen; /* length in XML_Chars */
271 int processed; /* # of processed bytes - when suspended */
272 const XML_Char *systemId;
273 const XML_Char *base;
274 const XML_Char *publicId;
275 const XML_Char *notation;
278 XML_Bool is_internal; /* true if declared in internal subset outside PE */
282 enum XML_Content_Type type;
283 enum XML_Content_Quant quant;
284 const XML_Char *name;
291 #define INIT_SCAFFOLD_ELEMENTS 32
293 typedef struct block {
305 const XML_Memory_Handling_Suite *mem;
308 /* The XML_Char before the name is used to determine whether
309 an attribute has been specified. */
310 typedef struct attribute_id {
313 XML_Bool maybeTokenized;
318 const ATTRIBUTE_ID *id;
320 const XML_Char *value;
324 unsigned long version;
326 const XML_Char *uriName;
330 const XML_Char *name;
332 const ATTRIBUTE_ID *idAtt;
334 int allocDefaultAtts;
335 DEFAULT_ATTRIBUTE *defaultAtts;
339 HASH_TABLE generalEntities;
340 HASH_TABLE elementTypes;
341 HASH_TABLE attributeIds;
344 STRING_POOL entityValuePool;
345 /* false once a parameter entity reference has been skipped */
346 XML_Bool keepProcessing;
347 /* true once an internal or external PE reference has been encountered;
348 this includes the reference to an external subset */
349 XML_Bool hasParamEntityRefs;
352 /* indicates if external PE has been read */
353 XML_Bool paramEntityRead;
354 HASH_TABLE paramEntities;
356 PREFIX defaultPrefix;
357 /* === scaffolding for building content model === */
359 CONTENT_SCAFFOLD *scaffold;
360 unsigned contentStringLen;
367 typedef struct open_internal_entity {
368 const char *internalEventPtr;
369 const char *internalEventEndPtr;
370 struct open_internal_entity *next;
373 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
374 } OPEN_INTERNAL_ENTITY;
376 typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
377 const char *end, const char **endPtr);
379 static Processor prologProcessor;
380 static Processor prologInitProcessor;
381 static Processor contentProcessor;
382 static Processor cdataSectionProcessor;
384 static Processor ignoreSectionProcessor;
385 static Processor externalParEntProcessor;
386 static Processor externalParEntInitProcessor;
387 static Processor entityValueProcessor;
388 static Processor entityValueInitProcessor;
390 static Processor epilogProcessor;
391 static Processor errorProcessor;
392 static Processor externalEntityInitProcessor;
393 static Processor externalEntityInitProcessor2;
394 static Processor externalEntityInitProcessor3;
395 static Processor externalEntityContentProcessor;
396 static Processor internalEntityProcessor;
398 static enum XML_Error handleUnknownEncoding(XML_Parser parser,
399 const XML_Char *encodingName);
400 static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
401 const char *s, const char *next);
402 static enum XML_Error initializeEncoding(XML_Parser parser);
403 static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
404 const char *s, const char *end, int tok,
405 const char *next, const char **nextPtr,
406 XML_Bool haveMore, XML_Bool allowClosingDoctype);
407 static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
408 XML_Bool betweenDecl);
409 static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
410 const ENCODING *enc, const char *start,
411 const char *end, const char **endPtr,
413 static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *,
414 const char **startPtr, const char *end,
415 const char **nextPtr, XML_Bool haveMore);
417 static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *,
418 const char **startPtr, const char *end,
419 const char **nextPtr, XML_Bool haveMore);
422 static void freeBindings(XML_Parser parser, BINDING *bindings);
423 static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *,
424 const char *s, TAG_NAME *tagNamePtr,
425 BINDING **bindingsPtr);
426 static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
427 const ATTRIBUTE_ID *attId, const XML_Char *uri,
428 BINDING **bindingsPtr);
429 static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
430 XML_Bool isId, const XML_Char *dfltValue,
432 static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *,
433 XML_Bool isCdata, const char *,
434 const char *, STRING_POOL *);
435 static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *,
436 XML_Bool isCdata, const char *,
437 const char *, STRING_POOL *);
438 static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
439 const char *start, const char *end);
440 static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
441 static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
442 const char *start, const char *end);
443 static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
444 const char *start, const char *end);
445 static int reportComment(XML_Parser parser, const ENCODING *enc,
446 const char *start, const char *end);
447 static void reportDefault(XML_Parser parser, const ENCODING *enc,
448 const char *start, const char *end);
450 static const XML_Char *getContext(XML_Parser parser);
451 static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
453 static void FASTCALL normalizePublicId(XML_Char *s);
455 static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms);
456 /* do not call if m_parentParser != NULL */
457 static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
458 static void dtdDestroy(DTD *p, XML_Bool isDocEntity,
459 const XML_Memory_Handling_Suite *ms);
460 static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
461 const XML_Memory_Handling_Suite *ms);
462 static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *, STRING_POOL *,
464 static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
466 static void FASTCALL hashTableInit(HASH_TABLE *,
467 const XML_Memory_Handling_Suite *ms);
468 static void FASTCALL hashTableClear(HASH_TABLE *);
469 static void FASTCALL hashTableDestroy(HASH_TABLE *);
470 static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
471 static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
473 static void FASTCALL poolInit(STRING_POOL *,
474 const XML_Memory_Handling_Suite *ms);
475 static void FASTCALL poolClear(STRING_POOL *);
476 static void FASTCALL poolDestroy(STRING_POOL *);
477 static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
478 const char *ptr, const char *end);
479 static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
480 const char *ptr, const char *end);
481 static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
482 static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
484 static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
486 static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
489 static int FASTCALL nextScaffoldPart(XML_Parser parser);
490 static XML_Content *build_model(XML_Parser parser);
491 static ELEMENT_TYPE *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);
500 static XML_Parser parserCreate(const XML_Char *encodingName,
501 const XML_Memory_Handling_Suite *memsuite,
502 const XML_Char *nameSep, DTD *dtd);
504 static void parserInit(XML_Parser parser, const XML_Char *encodingName);
506 #define poolStart(pool) ((pool)->start)
507 #define poolEnd(pool) ((pool)->ptr)
508 #define poolLength(pool) ((pool)->ptr - (pool)->start)
509 #define poolChop(pool) ((void)--(pool->ptr))
510 #define poolLastChar(pool) (((pool)->ptr)[-1])
511 #define poolDiscard(pool) ((pool)->ptr = (pool)->start)
512 #define poolFinish(pool) ((pool)->start = (pool)->ptr)
513 #define poolAppendChar(pool, c) \
514 (((pool)->ptr == (pool)->end && ! poolGrow(pool)) \
516 : ((*((pool)->ptr)++ = c), 1))
518 struct XML_ParserStruct {
519 /* The first member must be m_userData so that the XML_GetUserData
524 const XML_Memory_Handling_Suite m_mem;
525 /* first character to be parsed */
526 const char *m_bufferPtr;
527 /* past last character to be parsed */
529 /* allocated end of m_buffer */
530 const char *m_bufferLim;
531 XML_Index m_parseEndByteIndex;
532 const char *m_parseEndPtr;
534 XML_Char *m_dataBufEnd;
535 XML_StartElementHandler m_startElementHandler;
536 XML_EndElementHandler m_endElementHandler;
537 XML_CharacterDataHandler m_characterDataHandler;
538 XML_ProcessingInstructionHandler m_processingInstructionHandler;
539 XML_CommentHandler m_commentHandler;
540 XML_StartCdataSectionHandler m_startCdataSectionHandler;
541 XML_EndCdataSectionHandler m_endCdataSectionHandler;
542 XML_DefaultHandler m_defaultHandler;
543 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
544 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
545 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
546 XML_NotationDeclHandler m_notationDeclHandler;
547 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
548 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
549 XML_NotStandaloneHandler m_notStandaloneHandler;
550 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
551 XML_Parser m_externalEntityRefHandlerArg;
552 XML_SkippedEntityHandler m_skippedEntityHandler;
553 XML_UnknownEncodingHandler m_unknownEncodingHandler;
554 XML_ElementDeclHandler m_elementDeclHandler;
555 XML_AttlistDeclHandler m_attlistDeclHandler;
556 XML_EntityDeclHandler m_entityDeclHandler;
557 XML_XmlDeclHandler m_xmlDeclHandler;
558 const ENCODING *m_encoding;
559 INIT_ENCODING m_initEncoding;
560 const ENCODING *m_internalEncoding;
561 const XML_Char *m_protocolEncodingName;
563 XML_Bool m_ns_triplets;
564 void *m_unknownEncodingMem;
565 void *m_unknownEncodingData;
566 void *m_unknownEncodingHandlerData;
567 void(XMLCALL *m_unknownEncodingRelease)(void *);
568 PROLOG_STATE m_prologState;
569 Processor *m_processor;
570 enum XML_Error m_errorCode;
571 const char *m_eventPtr;
572 const char *m_eventEndPtr;
573 const char *m_positionPtr;
574 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
575 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
576 XML_Bool m_defaultExpandInternalEntities;
578 ENTITY *m_declEntity;
579 const XML_Char *m_doctypeName;
580 const XML_Char *m_doctypeSysid;
581 const XML_Char *m_doctypePubid;
582 const XML_Char *m_declAttributeType;
583 const XML_Char *m_declNotationName;
584 const XML_Char *m_declNotationPublicId;
585 ELEMENT_TYPE *m_declElementType;
586 ATTRIBUTE_ID *m_declAttributeId;
587 XML_Bool m_declAttributeIsCdata;
588 XML_Bool m_declAttributeIsId;
590 const XML_Char *m_curBase;
593 BINDING *m_inheritedBindings;
594 BINDING *m_freeBindingList;
596 int m_nSpecifiedAtts;
600 unsigned long m_nsAttsVersion;
601 unsigned char m_nsAttsPower;
603 XML_AttrInfo *m_attInfo;
606 STRING_POOL m_tempPool;
607 STRING_POOL m_temp2Pool;
608 char *m_groupConnector;
609 unsigned int m_groupSize;
610 XML_Char m_namespaceSeparator;
611 XML_Parser m_parentParser;
612 XML_ParsingStatus m_parsingStatus;
614 XML_Bool m_isParamEntity;
615 XML_Bool m_useForeignDTD;
616 enum XML_ParamEntityParsing m_paramEntityParsing;
618 unsigned long m_hash_secret_salt;
621 #define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
622 #define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
623 #define FREE(parser, p) (parser->m_mem.free_fcn((p)))
626 XML_ParserCreate(const XML_Char *encodingName) {
627 return XML_ParserCreate_MM(encodingName, NULL, NULL);
631 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
634 return XML_ParserCreate_MM(encodingName, NULL, tmp);
637 static const XML_Char implicitContext[]
638 = {ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h,
639 ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH,
640 ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD,
641 ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r,
642 ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
643 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8,
644 ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
645 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e,
648 /* To avoid warnings about unused functions: */
649 #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
651 # if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
653 /* Obtain entropy on Linux 3.17+ */
655 writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
656 int success = 0; /* full count bytes written? */
657 size_t bytesWrittenTotal = 0;
658 const unsigned int getrandomFlags = GRND_NONBLOCK;
661 void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
662 const size_t bytesToWrite = count - bytesWrittenTotal;
664 const int bytesWrittenMore =
665 # if defined(HAVE_GETRANDOM)
666 getrandom(currentTarget, bytesToWrite, getrandomFlags);
668 syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
671 if (bytesWrittenMore > 0) {
672 bytesWrittenTotal += bytesWrittenMore;
673 if (bytesWrittenTotal >= count)
676 } while (! success && (errno == EINTR));
681 # endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
683 # if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
685 /* Extract entropy from /dev/urandom */
687 writeRandomBytes_dev_urandom(void *target, size_t count) {
688 int success = 0; /* full count bytes written? */
689 size_t bytesWrittenTotal = 0;
691 const int fd = open("/dev/urandom", O_RDONLY);
697 void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
698 const size_t bytesToWrite = count - bytesWrittenTotal;
700 const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
702 if (bytesWrittenMore > 0) {
703 bytesWrittenTotal += bytesWrittenMore;
704 if (bytesWrittenTotal >= count)
707 } while (! success && (errno == EINTR));
713 # endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
715 #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
717 #if defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF)
720 writeRandomBytes_arc4random(void *target, size_t count) {
721 size_t bytesWrittenTotal = 0;
723 while (bytesWrittenTotal < count) {
724 const uint32_t random32 = arc4random();
727 for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
728 i++, bytesWrittenTotal++) {
729 const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
730 ((uint8_t *)target)[bytesWrittenTotal] = random8;
735 #endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */
739 /* Obtain entropy on Windows using the rand_s() function which
740 * generates cryptographically secure random numbers. Internally it
741 * uses RtlGenRandom API which is present in Windows XP and later.
744 writeRandomBytes_rand_s(void *target, size_t count) {
745 size_t bytesWrittenTotal = 0;
747 while (bytesWrittenTotal < count) {
748 unsigned int random32 = 0;
751 if (rand_s(&random32))
752 return 0; /* failure */
754 for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
755 i++, bytesWrittenTotal++) {
756 const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
757 ((uint8_t *)target)[bytesWrittenTotal] = random8;
760 return 1; /* success */
765 #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
768 gather_time_entropy(void) {
771 GetSystemTimeAsFileTime(&ft); /* never fails */
772 return ft.dwHighDateTime ^ ft.dwLowDateTime;
775 int gettimeofday_res;
777 gettimeofday_res = gettimeofday(&tv, NULL);
780 (void)gettimeofday_res;
782 assert(gettimeofday_res == 0);
783 # endif /* defined(NDEBUG) */
785 /* Microseconds time is <20 bits entropy */
790 #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
793 ENTROPY_DEBUG(const char *label, unsigned long entropy) {
794 const char *const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
795 if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
796 fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
797 (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
803 generate_hash_secret_salt(XML_Parser parser) {
804 unsigned long entropy;
807 /* "Failproof" high quality providers: */
808 #if defined(HAVE_ARC4RANDOM_BUF)
809 arc4random_buf(&entropy, sizeof(entropy));
810 return ENTROPY_DEBUG("arc4random_buf", entropy);
811 #elif defined(HAVE_ARC4RANDOM)
812 writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
813 return ENTROPY_DEBUG("arc4random", entropy);
815 /* Try high quality providers first .. */
817 if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
818 return ENTROPY_DEBUG("rand_s", entropy);
820 # elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
821 if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
822 return ENTROPY_DEBUG("getrandom", entropy);
825 # if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
826 if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
827 return ENTROPY_DEBUG("/dev/urandom", entropy);
829 # endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
830 /* .. and self-made low quality for backup: */
832 /* Process ID is 0 bits entropy if attacker has local access */
833 entropy = gather_time_entropy() ^ getpid();
835 /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
836 if (sizeof(unsigned long) == 4) {
837 return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
839 return ENTROPY_DEBUG("fallback(8)",
840 entropy * (unsigned long)2305843009213693951ULL);
846 get_hash_secret_salt(XML_Parser parser) {
847 if (parser->m_parentParser != NULL)
848 return get_hash_secret_salt(parser->m_parentParser);
849 return parser->m_hash_secret_salt;
852 static XML_Bool /* only valid for root parser */
853 startParsing(XML_Parser parser) {
854 /* hash functions must be initialized before setContext() is called */
855 if (parser->m_hash_secret_salt == 0)
856 parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
858 /* implicit context only set for root parser, since child
859 parsers (i.e. external entity parsers) will inherit it
861 return setContext(parser, implicitContext);
867 XML_ParserCreate_MM(const XML_Char *encodingName,
868 const XML_Memory_Handling_Suite *memsuite,
869 const XML_Char *nameSep) {
870 return parserCreate(encodingName, memsuite, nameSep, NULL);
874 parserCreate(const XML_Char *encodingName,
875 const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep,
880 XML_Memory_Handling_Suite *mtemp;
881 parser = (XML_Parser)memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
882 if (parser != NULL) {
883 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
884 mtemp->malloc_fcn = memsuite->malloc_fcn;
885 mtemp->realloc_fcn = memsuite->realloc_fcn;
886 mtemp->free_fcn = memsuite->free_fcn;
889 XML_Memory_Handling_Suite *mtemp;
890 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
891 if (parser != NULL) {
892 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
893 mtemp->malloc_fcn = malloc;
894 mtemp->realloc_fcn = realloc;
895 mtemp->free_fcn = free;
902 parser->m_buffer = NULL;
903 parser->m_bufferLim = NULL;
905 parser->m_attsSize = INIT_ATTS_SIZE;
907 = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
908 if (parser->m_atts == NULL) {
909 FREE(parser, parser);
913 parser->m_attInfo = (XML_AttrInfo *)MALLOC(
914 parser, parser->m_attsSize * sizeof(XML_AttrInfo));
915 if (parser->m_attInfo == NULL) {
916 FREE(parser, parser->m_atts);
917 FREE(parser, parser);
922 = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
923 if (parser->m_dataBuf == NULL) {
924 FREE(parser, parser->m_atts);
926 FREE(parser, parser->m_attInfo);
928 FREE(parser, parser);
931 parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
936 parser->m_dtd = dtdCreate(&parser->m_mem);
937 if (parser->m_dtd == NULL) {
938 FREE(parser, parser->m_dataBuf);
939 FREE(parser, parser->m_atts);
941 FREE(parser, parser->m_attInfo);
943 FREE(parser, parser);
948 parser->m_freeBindingList = NULL;
949 parser->m_freeTagList = NULL;
950 parser->m_freeInternalEntities = NULL;
952 parser->m_groupSize = 0;
953 parser->m_groupConnector = NULL;
955 parser->m_unknownEncodingHandler = NULL;
956 parser->m_unknownEncodingHandlerData = NULL;
958 parser->m_namespaceSeparator = ASCII_EXCL;
959 parser->m_ns = XML_FALSE;
960 parser->m_ns_triplets = XML_FALSE;
962 parser->m_nsAtts = NULL;
963 parser->m_nsAttsVersion = 0;
964 parser->m_nsAttsPower = 0;
966 parser->m_protocolEncodingName = NULL;
968 poolInit(&parser->m_tempPool, &(parser->m_mem));
969 poolInit(&parser->m_temp2Pool, &(parser->m_mem));
970 parserInit(parser, encodingName);
972 if (encodingName && ! parser->m_protocolEncodingName) {
973 XML_ParserFree(parser);
978 parser->m_ns = XML_TRUE;
979 parser->m_internalEncoding = XmlGetInternalEncodingNS();
980 parser->m_namespaceSeparator = *nameSep;
982 parser->m_internalEncoding = XmlGetInternalEncoding();
989 parserInit(XML_Parser parser, const XML_Char *encodingName) {
990 parser->m_processor = prologInitProcessor;
991 XmlPrologStateInit(&parser->m_prologState);
992 if (encodingName != NULL) {
993 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
995 parser->m_curBase = NULL;
996 XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
997 parser->m_userData = NULL;
998 parser->m_handlerArg = NULL;
999 parser->m_startElementHandler = NULL;
1000 parser->m_endElementHandler = NULL;
1001 parser->m_characterDataHandler = NULL;
1002 parser->m_processingInstructionHandler = NULL;
1003 parser->m_commentHandler = NULL;
1004 parser->m_startCdataSectionHandler = NULL;
1005 parser->m_endCdataSectionHandler = NULL;
1006 parser->m_defaultHandler = NULL;
1007 parser->m_startDoctypeDeclHandler = NULL;
1008 parser->m_endDoctypeDeclHandler = NULL;
1009 parser->m_unparsedEntityDeclHandler = NULL;
1010 parser->m_notationDeclHandler = NULL;
1011 parser->m_startNamespaceDeclHandler = NULL;
1012 parser->m_endNamespaceDeclHandler = NULL;
1013 parser->m_notStandaloneHandler = NULL;
1014 parser->m_externalEntityRefHandler = NULL;
1015 parser->m_externalEntityRefHandlerArg = parser;
1016 parser->m_skippedEntityHandler = NULL;
1017 parser->m_elementDeclHandler = NULL;
1018 parser->m_attlistDeclHandler = NULL;
1019 parser->m_entityDeclHandler = NULL;
1020 parser->m_xmlDeclHandler = NULL;
1021 parser->m_bufferPtr = parser->m_buffer;
1022 parser->m_bufferEnd = parser->m_buffer;
1023 parser->m_parseEndByteIndex = 0;
1024 parser->m_parseEndPtr = NULL;
1025 parser->m_declElementType = NULL;
1026 parser->m_declAttributeId = NULL;
1027 parser->m_declEntity = NULL;
1028 parser->m_doctypeName = NULL;
1029 parser->m_doctypeSysid = NULL;
1030 parser->m_doctypePubid = NULL;
1031 parser->m_declAttributeType = NULL;
1032 parser->m_declNotationName = NULL;
1033 parser->m_declNotationPublicId = NULL;
1034 parser->m_declAttributeIsCdata = XML_FALSE;
1035 parser->m_declAttributeIsId = XML_FALSE;
1036 memset(&parser->m_position, 0, sizeof(POSITION));
1037 parser->m_errorCode = XML_ERROR_NONE;
1038 parser->m_eventPtr = NULL;
1039 parser->m_eventEndPtr = NULL;
1040 parser->m_positionPtr = NULL;
1041 parser->m_openInternalEntities = NULL;
1042 parser->m_defaultExpandInternalEntities = XML_TRUE;
1043 parser->m_tagLevel = 0;
1044 parser->m_tagStack = NULL;
1045 parser->m_inheritedBindings = NULL;
1046 parser->m_nSpecifiedAtts = 0;
1047 parser->m_unknownEncodingMem = NULL;
1048 parser->m_unknownEncodingRelease = NULL;
1049 parser->m_unknownEncodingData = NULL;
1050 parser->m_parentParser = NULL;
1051 parser->m_parsingStatus.parsing = XML_INITIALIZED;
1053 parser->m_isParamEntity = XML_FALSE;
1054 parser->m_useForeignDTD = XML_FALSE;
1055 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
1057 parser->m_hash_secret_salt = 0;
1060 /* moves list of bindings to m_freeBindingList */
1061 static void FASTCALL
1062 moveToFreeBindingList(XML_Parser parser, BINDING *bindings) {
1064 BINDING *b = bindings;
1065 bindings = bindings->nextTagBinding;
1066 b->nextTagBinding = parser->m_freeBindingList;
1067 parser->m_freeBindingList = b;
1072 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
1074 OPEN_INTERNAL_ENTITY *openEntityList;
1079 if (parser->m_parentParser)
1081 /* move m_tagStack to m_freeTagList */
1082 tStk = parser->m_tagStack;
1085 tStk = tStk->parent;
1086 tag->parent = parser->m_freeTagList;
1087 moveToFreeBindingList(parser, tag->bindings);
1088 tag->bindings = NULL;
1089 parser->m_freeTagList = tag;
1091 /* move m_openInternalEntities to m_freeInternalEntities */
1092 openEntityList = parser->m_openInternalEntities;
1093 while (openEntityList) {
1094 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
1095 openEntityList = openEntity->next;
1096 openEntity->next = parser->m_freeInternalEntities;
1097 parser->m_freeInternalEntities = openEntity;
1099 moveToFreeBindingList(parser, parser->m_inheritedBindings);
1100 FREE(parser, parser->m_unknownEncodingMem);
1101 if (parser->m_unknownEncodingRelease)
1102 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1103 poolClear(&parser->m_tempPool);
1104 poolClear(&parser->m_temp2Pool);
1105 FREE(parser, (void *)parser->m_protocolEncodingName);
1106 parser->m_protocolEncodingName = NULL;
1107 parserInit(parser, encodingName);
1108 dtdReset(parser->m_dtd, &parser->m_mem);
1112 enum XML_Status XMLCALL
1113 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
1115 return XML_STATUS_ERROR;
1116 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
1117 XXX There's no way for the caller to determine which of the
1118 XXX possible error cases caused the XML_STATUS_ERROR return.
1120 if (parser->m_parsingStatus.parsing == XML_PARSING
1121 || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1122 return XML_STATUS_ERROR;
1124 /* Get rid of any previous encoding name */
1125 FREE(parser, (void *)parser->m_protocolEncodingName);
1127 if (encodingName == NULL)
1128 /* No new encoding name */
1129 parser->m_protocolEncodingName = NULL;
1131 /* Copy the new encoding name into allocated memory */
1132 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1133 if (! parser->m_protocolEncodingName)
1134 return XML_STATUS_ERROR;
1136 return XML_STATUS_OK;
1140 XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
1141 const XML_Char *encodingName) {
1142 XML_Parser parser = oldParser;
1145 XML_StartElementHandler oldStartElementHandler;
1146 XML_EndElementHandler oldEndElementHandler;
1147 XML_CharacterDataHandler oldCharacterDataHandler;
1148 XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
1149 XML_CommentHandler oldCommentHandler;
1150 XML_StartCdataSectionHandler oldStartCdataSectionHandler;
1151 XML_EndCdataSectionHandler oldEndCdataSectionHandler;
1152 XML_DefaultHandler oldDefaultHandler;
1153 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
1154 XML_NotationDeclHandler oldNotationDeclHandler;
1155 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
1156 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
1157 XML_NotStandaloneHandler oldNotStandaloneHandler;
1158 XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
1159 XML_SkippedEntityHandler oldSkippedEntityHandler;
1160 XML_UnknownEncodingHandler oldUnknownEncodingHandler;
1161 XML_ElementDeclHandler oldElementDeclHandler;
1162 XML_AttlistDeclHandler oldAttlistDeclHandler;
1163 XML_EntityDeclHandler oldEntityDeclHandler;
1164 XML_XmlDeclHandler oldXmlDeclHandler;
1165 ELEMENT_TYPE *oldDeclElementType;
1168 void *oldHandlerArg;
1169 XML_Bool oldDefaultExpandInternalEntities;
1170 XML_Parser oldExternalEntityRefHandlerArg;
1172 enum XML_ParamEntityParsing oldParamEntityParsing;
1173 int oldInEntityValue;
1175 XML_Bool oldns_triplets;
1176 /* Note that the new parser shares the same hash secret as the old
1177 parser, so that dtdCopy and copyEntityTable can lookup values
1178 from hash tables associated with either parser without us having
1179 to worry which hash secrets each table has.
1181 unsigned long oldhash_secret_salt;
1183 /* Validate the oldParser parameter before we pull everything out of it */
1184 if (oldParser == NULL)
1187 /* Stash the original parser contents on the stack */
1188 oldDtd = parser->m_dtd;
1189 oldStartElementHandler = parser->m_startElementHandler;
1190 oldEndElementHandler = parser->m_endElementHandler;
1191 oldCharacterDataHandler = parser->m_characterDataHandler;
1192 oldProcessingInstructionHandler = parser->m_processingInstructionHandler;
1193 oldCommentHandler = parser->m_commentHandler;
1194 oldStartCdataSectionHandler = parser->m_startCdataSectionHandler;
1195 oldEndCdataSectionHandler = parser->m_endCdataSectionHandler;
1196 oldDefaultHandler = parser->m_defaultHandler;
1197 oldUnparsedEntityDeclHandler = parser->m_unparsedEntityDeclHandler;
1198 oldNotationDeclHandler = parser->m_notationDeclHandler;
1199 oldStartNamespaceDeclHandler = parser->m_startNamespaceDeclHandler;
1200 oldEndNamespaceDeclHandler = parser->m_endNamespaceDeclHandler;
1201 oldNotStandaloneHandler = parser->m_notStandaloneHandler;
1202 oldExternalEntityRefHandler = parser->m_externalEntityRefHandler;
1203 oldSkippedEntityHandler = parser->m_skippedEntityHandler;
1204 oldUnknownEncodingHandler = parser->m_unknownEncodingHandler;
1205 oldElementDeclHandler = parser->m_elementDeclHandler;
1206 oldAttlistDeclHandler = parser->m_attlistDeclHandler;
1207 oldEntityDeclHandler = parser->m_entityDeclHandler;
1208 oldXmlDeclHandler = parser->m_xmlDeclHandler;
1209 oldDeclElementType = parser->m_declElementType;
1211 oldUserData = parser->m_userData;
1212 oldHandlerArg = parser->m_handlerArg;
1213 oldDefaultExpandInternalEntities = parser->m_defaultExpandInternalEntities;
1214 oldExternalEntityRefHandlerArg = parser->m_externalEntityRefHandlerArg;
1216 oldParamEntityParsing = parser->m_paramEntityParsing;
1217 oldInEntityValue = parser->m_prologState.inEntityValue;
1219 oldns_triplets = parser->m_ns_triplets;
1220 /* Note that the new parser shares the same hash secret as the old
1221 parser, so that dtdCopy and copyEntityTable can lookup values
1222 from hash tables associated with either parser without us having
1223 to worry which hash secrets each table has.
1225 oldhash_secret_salt = parser->m_hash_secret_salt;
1230 #endif /* XML_DTD */
1232 /* Note that the magical uses of the pre-processor to make field
1233 access look more like C++ require that `parser' be overwritten
1234 here. This makes this function more painful to follow than it
1239 *tmp = parser->m_namespaceSeparator;
1240 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1242 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1248 parser->m_startElementHandler = oldStartElementHandler;
1249 parser->m_endElementHandler = oldEndElementHandler;
1250 parser->m_characterDataHandler = oldCharacterDataHandler;
1251 parser->m_processingInstructionHandler = oldProcessingInstructionHandler;
1252 parser->m_commentHandler = oldCommentHandler;
1253 parser->m_startCdataSectionHandler = oldStartCdataSectionHandler;
1254 parser->m_endCdataSectionHandler = oldEndCdataSectionHandler;
1255 parser->m_defaultHandler = oldDefaultHandler;
1256 parser->m_unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1257 parser->m_notationDeclHandler = oldNotationDeclHandler;
1258 parser->m_startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1259 parser->m_endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1260 parser->m_notStandaloneHandler = oldNotStandaloneHandler;
1261 parser->m_externalEntityRefHandler = oldExternalEntityRefHandler;
1262 parser->m_skippedEntityHandler = oldSkippedEntityHandler;
1263 parser->m_unknownEncodingHandler = oldUnknownEncodingHandler;
1264 parser->m_elementDeclHandler = oldElementDeclHandler;
1265 parser->m_attlistDeclHandler = oldAttlistDeclHandler;
1266 parser->m_entityDeclHandler = oldEntityDeclHandler;
1267 parser->m_xmlDeclHandler = oldXmlDeclHandler;
1268 parser->m_declElementType = oldDeclElementType;
1269 parser->m_userData = oldUserData;
1270 if (oldUserData == oldHandlerArg)
1271 parser->m_handlerArg = parser->m_userData;
1273 parser->m_handlerArg = parser;
1274 if (oldExternalEntityRefHandlerArg != oldParser)
1275 parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1276 parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1277 parser->m_ns_triplets = oldns_triplets;
1278 parser->m_hash_secret_salt = oldhash_secret_salt;
1279 parser->m_parentParser = oldParser;
1281 parser->m_paramEntityParsing = oldParamEntityParsing;
1282 parser->m_prologState.inEntityValue = oldInEntityValue;
1284 #endif /* XML_DTD */
1285 if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
1286 || ! setContext(parser, context)) {
1287 XML_ParserFree(parser);
1290 parser->m_processor = externalEntityInitProcessor;
1293 /* The DTD instance referenced by parser->m_dtd is shared between the
1294 document's root parser and external PE parsers, therefore one does not
1295 need to call setContext. In addition, one also *must* not call
1296 setContext, because this would overwrite existing prefix->binding
1297 pointers in parser->m_dtd with ones that get destroyed with the external
1298 PE parser. This would leave those prefixes with dangling pointers.
1300 parser->m_isParamEntity = XML_TRUE;
1301 XmlPrologStateInitExternalEntity(&parser->m_prologState);
1302 parser->m_processor = externalParEntInitProcessor;
1304 #endif /* XML_DTD */
1308 static void FASTCALL
1309 destroyBindings(BINDING *bindings, XML_Parser parser) {
1311 BINDING *b = bindings;
1314 bindings = b->nextTagBinding;
1315 FREE(parser, b->uri);
1321 XML_ParserFree(XML_Parser parser) {
1323 OPEN_INTERNAL_ENTITY *entityList;
1326 /* free m_tagStack and m_freeTagList */
1327 tagList = parser->m_tagStack;
1330 if (tagList == NULL) {
1331 if (parser->m_freeTagList == NULL)
1333 tagList = parser->m_freeTagList;
1334 parser->m_freeTagList = NULL;
1337 tagList = tagList->parent;
1338 FREE(parser, p->buf);
1339 destroyBindings(p->bindings, parser);
1342 /* free m_openInternalEntities and m_freeInternalEntities */
1343 entityList = parser->m_openInternalEntities;
1345 OPEN_INTERNAL_ENTITY *openEntity;
1346 if (entityList == NULL) {
1347 if (parser->m_freeInternalEntities == NULL)
1349 entityList = parser->m_freeInternalEntities;
1350 parser->m_freeInternalEntities = NULL;
1352 openEntity = entityList;
1353 entityList = entityList->next;
1354 FREE(parser, openEntity);
1357 destroyBindings(parser->m_freeBindingList, parser);
1358 destroyBindings(parser->m_inheritedBindings, parser);
1359 poolDestroy(&parser->m_tempPool);
1360 poolDestroy(&parser->m_temp2Pool);
1361 FREE(parser, (void *)parser->m_protocolEncodingName);
1363 /* external parameter entity parsers share the DTD structure
1364 parser->m_dtd with the root parser, so we must not destroy it
1366 if (! parser->m_isParamEntity && parser->m_dtd)
1369 #endif /* XML_DTD */
1370 dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser,
1372 FREE(parser, (void *)parser->m_atts);
1373 #ifdef XML_ATTR_INFO
1374 FREE(parser, (void *)parser->m_attInfo);
1376 FREE(parser, parser->m_groupConnector);
1377 FREE(parser, parser->m_buffer);
1378 FREE(parser, parser->m_dataBuf);
1379 FREE(parser, parser->m_nsAtts);
1380 FREE(parser, parser->m_unknownEncodingMem);
1381 if (parser->m_unknownEncodingRelease)
1382 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1383 FREE(parser, parser);
1387 XML_UseParserAsHandlerArg(XML_Parser parser) {
1389 parser->m_handlerArg = parser;
1392 enum XML_Error XMLCALL
1393 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) {
1395 return XML_ERROR_INVALID_ARGUMENT;
1397 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1398 if (parser->m_parsingStatus.parsing == XML_PARSING
1399 || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1400 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1401 parser->m_useForeignDTD = useDTD;
1402 return XML_ERROR_NONE;
1404 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1409 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
1412 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1413 if (parser->m_parsingStatus.parsing == XML_PARSING
1414 || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1416 parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1420 XML_SetUserData(XML_Parser parser, void *p) {
1423 if (parser->m_handlerArg == parser->m_userData)
1424 parser->m_handlerArg = parser->m_userData = p;
1426 parser->m_userData = p;
1429 enum XML_Status XMLCALL
1430 XML_SetBase(XML_Parser parser, const XML_Char *p) {
1432 return XML_STATUS_ERROR;
1434 p = poolCopyString(&parser->m_dtd->pool, p);
1436 return XML_STATUS_ERROR;
1437 parser->m_curBase = p;
1439 parser->m_curBase = NULL;
1440 return XML_STATUS_OK;
1443 const XML_Char *XMLCALL
1444 XML_GetBase(XML_Parser parser) {
1447 return parser->m_curBase;
1451 XML_GetSpecifiedAttributeCount(XML_Parser parser) {
1454 return parser->m_nSpecifiedAtts;
1458 XML_GetIdAttributeIndex(XML_Parser parser) {
1461 return parser->m_idAttIndex;
1464 #ifdef XML_ATTR_INFO
1465 const XML_AttrInfo *XMLCALL
1466 XML_GetAttributeInfo(XML_Parser parser) {
1469 return parser->m_attInfo;
1474 XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start,
1475 XML_EndElementHandler end) {
1478 parser->m_startElementHandler = start;
1479 parser->m_endElementHandler = end;
1483 XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) {
1485 parser->m_startElementHandler = start;
1489 XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) {
1491 parser->m_endElementHandler = end;
1495 XML_SetCharacterDataHandler(XML_Parser parser,
1496 XML_CharacterDataHandler handler) {
1498 parser->m_characterDataHandler = handler;
1502 XML_SetProcessingInstructionHandler(XML_Parser parser,
1503 XML_ProcessingInstructionHandler handler) {
1505 parser->m_processingInstructionHandler = handler;
1509 XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) {
1511 parser->m_commentHandler = handler;
1515 XML_SetCdataSectionHandler(XML_Parser parser,
1516 XML_StartCdataSectionHandler start,
1517 XML_EndCdataSectionHandler end) {
1520 parser->m_startCdataSectionHandler = start;
1521 parser->m_endCdataSectionHandler = end;
1525 XML_SetStartCdataSectionHandler(XML_Parser parser,
1526 XML_StartCdataSectionHandler start) {
1528 parser->m_startCdataSectionHandler = start;
1532 XML_SetEndCdataSectionHandler(XML_Parser parser,
1533 XML_EndCdataSectionHandler end) {
1535 parser->m_endCdataSectionHandler = end;
1539 XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) {
1542 parser->m_defaultHandler = handler;
1543 parser->m_defaultExpandInternalEntities = XML_FALSE;
1547 XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) {
1550 parser->m_defaultHandler = handler;
1551 parser->m_defaultExpandInternalEntities = XML_TRUE;
1555 XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start,
1556 XML_EndDoctypeDeclHandler end) {
1559 parser->m_startDoctypeDeclHandler = start;
1560 parser->m_endDoctypeDeclHandler = end;
1564 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1565 XML_StartDoctypeDeclHandler start) {
1567 parser->m_startDoctypeDeclHandler = start;
1571 XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) {
1573 parser->m_endDoctypeDeclHandler = end;
1577 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1578 XML_UnparsedEntityDeclHandler handler) {
1580 parser->m_unparsedEntityDeclHandler = handler;
1584 XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) {
1586 parser->m_notationDeclHandler = handler;
1590 XML_SetNamespaceDeclHandler(XML_Parser parser,
1591 XML_StartNamespaceDeclHandler start,
1592 XML_EndNamespaceDeclHandler end) {
1595 parser->m_startNamespaceDeclHandler = start;
1596 parser->m_endNamespaceDeclHandler = end;
1600 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1601 XML_StartNamespaceDeclHandler start) {
1603 parser->m_startNamespaceDeclHandler = start;
1607 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1608 XML_EndNamespaceDeclHandler end) {
1610 parser->m_endNamespaceDeclHandler = end;
1614 XML_SetNotStandaloneHandler(XML_Parser parser,
1615 XML_NotStandaloneHandler handler) {
1617 parser->m_notStandaloneHandler = handler;
1621 XML_SetExternalEntityRefHandler(XML_Parser parser,
1622 XML_ExternalEntityRefHandler handler) {
1624 parser->m_externalEntityRefHandler = handler;
1628 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) {
1632 parser->m_externalEntityRefHandlerArg = (XML_Parser)arg;
1634 parser->m_externalEntityRefHandlerArg = parser;
1638 XML_SetSkippedEntityHandler(XML_Parser parser,
1639 XML_SkippedEntityHandler handler) {
1641 parser->m_skippedEntityHandler = handler;
1645 XML_SetUnknownEncodingHandler(XML_Parser parser,
1646 XML_UnknownEncodingHandler handler, void *data) {
1649 parser->m_unknownEncodingHandler = handler;
1650 parser->m_unknownEncodingHandlerData = data;
1654 XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) {
1656 parser->m_elementDeclHandler = eldecl;
1660 XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) {
1662 parser->m_attlistDeclHandler = attdecl;
1666 XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) {
1668 parser->m_entityDeclHandler = handler;
1672 XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) {
1674 parser->m_xmlDeclHandler = handler;
1678 XML_SetParamEntityParsing(XML_Parser parser,
1679 enum XML_ParamEntityParsing peParsing) {
1682 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1683 if (parser->m_parsingStatus.parsing == XML_PARSING
1684 || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1687 parser->m_paramEntityParsing = peParsing;
1690 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1695 XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
1698 if (parser->m_parentParser)
1699 return XML_SetHashSalt(parser->m_parentParser, hash_salt);
1700 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1701 if (parser->m_parsingStatus.parsing == XML_PARSING
1702 || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1704 parser->m_hash_secret_salt = hash_salt;
1708 enum XML_Status XMLCALL
1709 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
1710 if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
1712 parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
1713 return XML_STATUS_ERROR;
1715 switch (parser->m_parsingStatus.parsing) {
1717 parser->m_errorCode = XML_ERROR_SUSPENDED;
1718 return XML_STATUS_ERROR;
1720 parser->m_errorCode = XML_ERROR_FINISHED;
1721 return XML_STATUS_ERROR;
1722 case XML_INITIALIZED:
1723 if (parser->m_parentParser == NULL && ! startParsing(parser)) {
1724 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1725 return XML_STATUS_ERROR;
1729 parser->m_parsingStatus.parsing = XML_PARSING;
1733 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
1735 return XML_STATUS_OK;
1736 parser->m_positionPtr = parser->m_bufferPtr;
1737 parser->m_parseEndPtr = parser->m_bufferEnd;
1739 /* If data are left over from last buffer, and we now know that these
1740 data are the final chunk of input, then we have to check them again
1741 to detect errors based on that fact.
1744 = parser->m_processor(parser, parser->m_bufferPtr,
1745 parser->m_parseEndPtr, &parser->m_bufferPtr);
1747 if (parser->m_errorCode == XML_ERROR_NONE) {
1748 switch (parser->m_parsingStatus.parsing) {
1750 /* It is hard to be certain, but it seems that this case
1751 * cannot occur. This code is cleaning up a previous parse
1752 * with no new data (since len == 0). Changing the parsing
1753 * state requires getting to execute a handler function, and
1754 * there doesn't seem to be an opportunity for that while in
1755 * this circumstance.
1757 * Given the uncertainty, we retain the code but exclude it
1758 * from coverage tests.
1762 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
1763 parser->m_bufferPtr, &parser->m_position);
1764 parser->m_positionPtr = parser->m_bufferPtr;
1765 return XML_STATUS_SUSPENDED;
1766 /* LCOV_EXCL_STOP */
1767 case XML_INITIALIZED:
1769 parser->m_parsingStatus.parsing = XML_FINISHED;
1772 return XML_STATUS_OK;
1775 parser->m_eventEndPtr = parser->m_eventPtr;
1776 parser->m_processor = errorProcessor;
1777 return XML_STATUS_ERROR;
1779 #ifndef XML_CONTEXT_BYTES
1780 else if (parser->m_bufferPtr == parser->m_bufferEnd) {
1783 enum XML_Status result;
1784 /* Detect overflow (a+b > MAX <==> b > MAX-a) */
1785 if (len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) {
1786 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1787 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1788 parser->m_processor = errorProcessor;
1789 return XML_STATUS_ERROR;
1791 parser->m_parseEndByteIndex += len;
1792 parser->m_positionPtr = s;
1793 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
1796 = parser->m_processor(parser, s, parser->m_parseEndPtr = s + len, &end);
1798 if (parser->m_errorCode != XML_ERROR_NONE) {
1799 parser->m_eventEndPtr = parser->m_eventPtr;
1800 parser->m_processor = errorProcessor;
1801 return XML_STATUS_ERROR;
1803 switch (parser->m_parsingStatus.parsing) {
1805 result = XML_STATUS_SUSPENDED;
1807 case XML_INITIALIZED:
1810 parser->m_parsingStatus.parsing = XML_FINISHED;
1811 return XML_STATUS_OK;
1815 result = XML_STATUS_OK;
1819 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end,
1820 &parser->m_position);
1821 nLeftOver = s + len - end;
1823 if (parser->m_buffer == NULL
1824 || nLeftOver > parser->m_bufferLim - parser->m_buffer) {
1825 /* avoid _signed_ integer overflow */
1827 const int bytesToAllocate = (int)((unsigned)len * 2U);
1828 if (bytesToAllocate > 0) {
1829 temp = (char *)REALLOC(parser, parser->m_buffer, bytesToAllocate);
1832 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1833 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1834 parser->m_processor = errorProcessor;
1835 return XML_STATUS_ERROR;
1837 parser->m_buffer = temp;
1838 parser->m_bufferLim = parser->m_buffer + bytesToAllocate;
1840 memcpy(parser->m_buffer, end, nLeftOver);
1842 parser->m_bufferPtr = parser->m_buffer;
1843 parser->m_bufferEnd = parser->m_buffer + nLeftOver;
1844 parser->m_positionPtr = parser->m_bufferPtr;
1845 parser->m_parseEndPtr = parser->m_bufferEnd;
1846 parser->m_eventPtr = parser->m_bufferPtr;
1847 parser->m_eventEndPtr = parser->m_bufferPtr;
1850 #endif /* not defined XML_CONTEXT_BYTES */
1852 void *buff = XML_GetBuffer(parser, len);
1854 return XML_STATUS_ERROR;
1856 memcpy(buff, s, len);
1857 return XML_ParseBuffer(parser, len, isFinal);
1862 enum XML_Status XMLCALL
1863 XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
1865 enum XML_Status result = XML_STATUS_OK;
1868 return XML_STATUS_ERROR;
1869 switch (parser->m_parsingStatus.parsing) {
1871 parser->m_errorCode = XML_ERROR_SUSPENDED;
1872 return XML_STATUS_ERROR;
1874 parser->m_errorCode = XML_ERROR_FINISHED;
1875 return XML_STATUS_ERROR;
1876 case XML_INITIALIZED:
1877 if (parser->m_parentParser == NULL && ! startParsing(parser)) {
1878 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1879 return XML_STATUS_ERROR;
1883 parser->m_parsingStatus.parsing = XML_PARSING;
1886 start = parser->m_bufferPtr;
1887 parser->m_positionPtr = start;
1888 parser->m_bufferEnd += len;
1889 parser->m_parseEndPtr = parser->m_bufferEnd;
1890 parser->m_parseEndByteIndex += len;
1891 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
1893 parser->m_errorCode = parser->m_processor(
1894 parser, start, parser->m_parseEndPtr, &parser->m_bufferPtr);
1896 if (parser->m_errorCode != XML_ERROR_NONE) {
1897 parser->m_eventEndPtr = parser->m_eventPtr;
1898 parser->m_processor = errorProcessor;
1899 return XML_STATUS_ERROR;
1901 switch (parser->m_parsingStatus.parsing) {
1903 result = XML_STATUS_SUSPENDED;
1905 case XML_INITIALIZED:
1908 parser->m_parsingStatus.parsing = XML_FINISHED;
1911 default:; /* should not happen */
1915 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
1916 parser->m_bufferPtr, &parser->m_position);
1917 parser->m_positionPtr = parser->m_bufferPtr;
1922 XML_GetBuffer(XML_Parser parser, int len) {
1926 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1929 switch (parser->m_parsingStatus.parsing) {
1931 parser->m_errorCode = XML_ERROR_SUSPENDED;
1934 parser->m_errorCode = XML_ERROR_FINISHED;
1939 if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)) {
1940 #ifdef XML_CONTEXT_BYTES
1942 #endif /* defined XML_CONTEXT_BYTES */
1943 /* Do not invoke signed arithmetic overflow: */
1944 int neededSize = (int)((unsigned)len
1945 + (unsigned)EXPAT_SAFE_PTR_DIFF(
1946 parser->m_bufferEnd, parser->m_bufferPtr));
1947 if (neededSize < 0) {
1948 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1951 #ifdef XML_CONTEXT_BYTES
1952 keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
1953 if (keep > XML_CONTEXT_BYTES)
1954 keep = XML_CONTEXT_BYTES;
1956 #endif /* defined XML_CONTEXT_BYTES */
1958 <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) {
1959 #ifdef XML_CONTEXT_BYTES
1960 if (keep < EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)) {
1962 = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)
1964 /* The buffer pointers cannot be NULL here; we have at least some bytes
1966 memmove(parser->m_buffer, &parser->m_buffer[offset],
1967 parser->m_bufferEnd - parser->m_bufferPtr + keep);
1968 parser->m_bufferEnd -= offset;
1969 parser->m_bufferPtr -= offset;
1972 if (parser->m_buffer && parser->m_bufferPtr) {
1973 memmove(parser->m_buffer, parser->m_bufferPtr,
1974 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
1977 + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
1978 parser->m_bufferPtr = parser->m_buffer;
1980 #endif /* not defined XML_CONTEXT_BYTES */
1984 = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferPtr);
1985 if (bufferSize == 0)
1986 bufferSize = INIT_BUFFER_SIZE;
1988 /* Do not invoke signed arithmetic overflow: */
1989 bufferSize = (int)(2U * (unsigned)bufferSize);
1990 } while (bufferSize < neededSize && bufferSize > 0);
1991 if (bufferSize <= 0) {
1992 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1995 newBuf = (char *)MALLOC(parser, bufferSize);
1997 parser->m_errorCode = XML_ERROR_NO_MEMORY;
2000 parser->m_bufferLim = newBuf + bufferSize;
2001 #ifdef XML_CONTEXT_BYTES
2002 if (parser->m_bufferPtr) {
2003 memcpy(newBuf, &parser->m_bufferPtr[-keep],
2004 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
2006 FREE(parser, parser->m_buffer);
2007 parser->m_buffer = newBuf;
2010 + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
2012 parser->m_bufferPtr = parser->m_buffer + keep;
2014 /* This must be a brand new buffer with no data in it yet */
2015 parser->m_bufferEnd = newBuf;
2016 parser->m_bufferPtr = parser->m_buffer = newBuf;
2019 if (parser->m_bufferPtr) {
2020 memcpy(newBuf, parser->m_bufferPtr,
2021 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
2022 FREE(parser, parser->m_buffer);
2025 + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
2027 /* This must be a brand new buffer with no data in it yet */
2028 parser->m_bufferEnd = newBuf;
2030 parser->m_bufferPtr = parser->m_buffer = newBuf;
2031 #endif /* not defined XML_CONTEXT_BYTES */
2033 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
2034 parser->m_positionPtr = NULL;
2036 return parser->m_bufferEnd;
2039 enum XML_Status XMLCALL
2040 XML_StopParser(XML_Parser parser, XML_Bool resumable) {
2042 return XML_STATUS_ERROR;
2043 switch (parser->m_parsingStatus.parsing) {
2046 parser->m_errorCode = XML_ERROR_SUSPENDED;
2047 return XML_STATUS_ERROR;
2049 parser->m_parsingStatus.parsing = XML_FINISHED;
2052 parser->m_errorCode = XML_ERROR_FINISHED;
2053 return XML_STATUS_ERROR;
2057 if (parser->m_isParamEntity) {
2058 parser->m_errorCode = XML_ERROR_SUSPEND_PE;
2059 return XML_STATUS_ERROR;
2062 parser->m_parsingStatus.parsing = XML_SUSPENDED;
2064 parser->m_parsingStatus.parsing = XML_FINISHED;
2066 return XML_STATUS_OK;
2069 enum XML_Status XMLCALL
2070 XML_ResumeParser(XML_Parser parser) {
2071 enum XML_Status result = XML_STATUS_OK;
2074 return XML_STATUS_ERROR;
2075 if (parser->m_parsingStatus.parsing != XML_SUSPENDED) {
2076 parser->m_errorCode = XML_ERROR_NOT_SUSPENDED;
2077 return XML_STATUS_ERROR;
2079 parser->m_parsingStatus.parsing = XML_PARSING;
2081 parser->m_errorCode = parser->m_processor(
2082 parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr);
2084 if (parser->m_errorCode != XML_ERROR_NONE) {
2085 parser->m_eventEndPtr = parser->m_eventPtr;
2086 parser->m_processor = errorProcessor;
2087 return XML_STATUS_ERROR;
2089 switch (parser->m_parsingStatus.parsing) {
2091 result = XML_STATUS_SUSPENDED;
2093 case XML_INITIALIZED:
2095 if (parser->m_parsingStatus.finalBuffer) {
2096 parser->m_parsingStatus.parsing = XML_FINISHED;
2103 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2104 parser->m_bufferPtr, &parser->m_position);
2105 parser->m_positionPtr = parser->m_bufferPtr;
2110 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) {
2113 assert(status != NULL);
2114 *status = parser->m_parsingStatus;
2117 enum XML_Error XMLCALL
2118 XML_GetErrorCode(XML_Parser parser) {
2120 return XML_ERROR_INVALID_ARGUMENT;
2121 return parser->m_errorCode;
2125 XML_GetCurrentByteIndex(XML_Parser parser) {
2128 if (parser->m_eventPtr)
2129 return (XML_Index)(parser->m_parseEndByteIndex
2130 - (parser->m_parseEndPtr - parser->m_eventPtr));
2135 XML_GetCurrentByteCount(XML_Parser parser) {
2138 if (parser->m_eventEndPtr && parser->m_eventPtr)
2139 return (int)(parser->m_eventEndPtr - parser->m_eventPtr);
2144 XML_GetInputContext(XML_Parser parser, int *offset, int *size) {
2145 #ifdef XML_CONTEXT_BYTES
2148 if (parser->m_eventPtr && parser->m_buffer) {
2150 *offset = (int)(parser->m_eventPtr - parser->m_buffer);
2152 *size = (int)(parser->m_bufferEnd - parser->m_buffer);
2153 return parser->m_buffer;
2159 #endif /* defined XML_CONTEXT_BYTES */
2164 XML_GetCurrentLineNumber(XML_Parser parser) {
2167 if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2168 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2169 parser->m_eventPtr, &parser->m_position);
2170 parser->m_positionPtr = parser->m_eventPtr;
2172 return parser->m_position.lineNumber + 1;
2176 XML_GetCurrentColumnNumber(XML_Parser parser) {
2179 if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2180 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2181 parser->m_eventPtr, &parser->m_position);
2182 parser->m_positionPtr = parser->m_eventPtr;
2184 return parser->m_position.columnNumber;
2188 XML_FreeContentModel(XML_Parser parser, XML_Content *model) {
2190 FREE(parser, model);
2194 XML_MemMalloc(XML_Parser parser, size_t size) {
2197 return MALLOC(parser, size);
2201 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) {
2204 return REALLOC(parser, ptr, size);
2208 XML_MemFree(XML_Parser parser, void *ptr) {
2214 XML_DefaultCurrent(XML_Parser parser) {
2217 if (parser->m_defaultHandler) {
2218 if (parser->m_openInternalEntities)
2219 reportDefault(parser, parser->m_internalEncoding,
2220 parser->m_openInternalEntities->internalEventPtr,
2221 parser->m_openInternalEntities->internalEventEndPtr);
2223 reportDefault(parser, parser->m_encoding, parser->m_eventPtr,
2224 parser->m_eventEndPtr);
2228 const XML_LChar *XMLCALL
2229 XML_ErrorString(enum XML_Error code) {
2231 case XML_ERROR_NONE:
2233 case XML_ERROR_NO_MEMORY:
2234 return XML_L("out of memory");
2235 case XML_ERROR_SYNTAX:
2236 return XML_L("syntax error");
2237 case XML_ERROR_NO_ELEMENTS:
2238 return XML_L("no element found");
2239 case XML_ERROR_INVALID_TOKEN:
2240 return XML_L("not well-formed (invalid token)");
2241 case XML_ERROR_UNCLOSED_TOKEN:
2242 return XML_L("unclosed token");
2243 case XML_ERROR_PARTIAL_CHAR:
2244 return XML_L("partial character");
2245 case XML_ERROR_TAG_MISMATCH:
2246 return XML_L("mismatched tag");
2247 case XML_ERROR_DUPLICATE_ATTRIBUTE:
2248 return XML_L("duplicate attribute");
2249 case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
2250 return XML_L("junk after document element");
2251 case XML_ERROR_PARAM_ENTITY_REF:
2252 return XML_L("illegal parameter entity reference");
2253 case XML_ERROR_UNDEFINED_ENTITY:
2254 return XML_L("undefined entity");
2255 case XML_ERROR_RECURSIVE_ENTITY_REF:
2256 return XML_L("recursive entity reference");
2257 case XML_ERROR_ASYNC_ENTITY:
2258 return XML_L("asynchronous entity");
2259 case XML_ERROR_BAD_CHAR_REF:
2260 return XML_L("reference to invalid character number");
2261 case XML_ERROR_BINARY_ENTITY_REF:
2262 return XML_L("reference to binary entity");
2263 case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
2264 return XML_L("reference to external entity in attribute");
2265 case XML_ERROR_MISPLACED_XML_PI:
2266 return XML_L("XML or text declaration not at start of entity");
2267 case XML_ERROR_UNKNOWN_ENCODING:
2268 return XML_L("unknown encoding");
2269 case XML_ERROR_INCORRECT_ENCODING:
2270 return XML_L("encoding specified in XML declaration is incorrect");
2271 case XML_ERROR_UNCLOSED_CDATA_SECTION:
2272 return XML_L("unclosed CDATA section");
2273 case XML_ERROR_EXTERNAL_ENTITY_HANDLING:
2274 return XML_L("error in processing external entity reference");
2275 case XML_ERROR_NOT_STANDALONE:
2276 return XML_L("document is not standalone");
2277 case XML_ERROR_UNEXPECTED_STATE:
2278 return XML_L("unexpected parser state - please send a bug report");
2279 case XML_ERROR_ENTITY_DECLARED_IN_PE:
2280 return XML_L("entity declared in parameter entity");
2281 case XML_ERROR_FEATURE_REQUIRES_XML_DTD:
2282 return XML_L("requested feature requires XML_DTD support in Expat");
2283 case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:
2284 return XML_L("cannot change setting once parsing has begun");
2285 /* Added in 1.95.7. */
2286 case XML_ERROR_UNBOUND_PREFIX:
2287 return XML_L("unbound prefix");
2288 /* Added in 1.95.8. */
2289 case XML_ERROR_UNDECLARING_PREFIX:
2290 return XML_L("must not undeclare prefix");
2291 case XML_ERROR_INCOMPLETE_PE:
2292 return XML_L("incomplete markup in parameter entity");
2293 case XML_ERROR_XML_DECL:
2294 return XML_L("XML declaration not well-formed");
2295 case XML_ERROR_TEXT_DECL:
2296 return XML_L("text declaration not well-formed");
2297 case XML_ERROR_PUBLICID:
2298 return XML_L("illegal character(s) in public id");
2299 case XML_ERROR_SUSPENDED:
2300 return XML_L("parser suspended");
2301 case XML_ERROR_NOT_SUSPENDED:
2302 return XML_L("parser not suspended");
2303 case XML_ERROR_ABORTED:
2304 return XML_L("parsing aborted");
2305 case XML_ERROR_FINISHED:
2306 return XML_L("parsing finished");
2307 case XML_ERROR_SUSPEND_PE:
2308 return XML_L("cannot suspend in external parameter entity");
2309 /* Added in 2.0.0. */
2310 case XML_ERROR_RESERVED_PREFIX_XML:
2312 "reserved prefix (xml) must not be undeclared or bound to another namespace name");
2313 case XML_ERROR_RESERVED_PREFIX_XMLNS:
2314 return XML_L("reserved prefix (xmlns) must not be declared or undeclared");
2315 case XML_ERROR_RESERVED_NAMESPACE_URI:
2317 "prefix must not be bound to one of the reserved namespace names");
2318 /* Added in 2.2.5. */
2319 case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
2320 return XML_L("invalid argument");
2325 const XML_LChar *XMLCALL
2326 XML_ExpatVersion(void) {
2327 /* V1 is used to string-ize the version number. However, it would
2328 string-ize the actual version macro *names* unless we get them
2329 substituted before being passed to V1. CPP is defined to expand
2330 a macro, then rescan for more expansions. Thus, we use V2 to expand
2331 the version macros, then CPP will expand the resulting V1() macro
2332 with the correct numerals. */
2333 /* ### I'm assuming cpp is portable in this respect... */
2335 #define V1(a, b, c) XML_L(#a) XML_L(".") XML_L(#b) XML_L(".") XML_L(#c)
2336 #define V2(a, b, c) XML_L("expat_") V1(a, b, c)
2338 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
2344 XML_Expat_Version XMLCALL
2345 XML_ExpatVersionInfo(void) {
2346 XML_Expat_Version version;
2348 version.major = XML_MAJOR_VERSION;
2349 version.minor = XML_MINOR_VERSION;
2350 version.micro = XML_MICRO_VERSION;
2355 const XML_Feature *XMLCALL
2356 XML_GetFeatureList(void) {
2357 static const XML_Feature features[]
2358 = {{XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2360 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2363 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2365 #ifdef XML_UNICODE_WCHAR_T
2366 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2369 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2371 #ifdef XML_CONTEXT_BYTES
2372 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2376 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2379 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2381 #ifdef XML_LARGE_SIZE
2382 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
2384 #ifdef XML_ATTR_INFO
2385 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2387 {XML_FEATURE_END, NULL, 0}};
2392 /* Initially tag->rawName always points into the parse buffer;
2393 for those TAG instances opened while the current parse buffer was
2394 processed, and not yet closed, we need to store tag->rawName in a more
2395 permanent location, since the parse buffer is about to be discarded.
2398 storeRawNames(XML_Parser parser) {
2399 TAG *tag = parser->m_tagStack;
2402 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2403 char *rawNameBuf = tag->buf + nameLen;
2404 /* Stop if already stored. Since m_tagStack is a stack, we can stop
2405 at the first entry that has already been copied; everything
2406 below it in the stack is already been accounted for in a
2407 previous call to this function.
2409 if (tag->rawName == rawNameBuf)
2411 /* For re-use purposes we need to ensure that the
2412 size of tag->buf is a multiple of sizeof(XML_Char).
2414 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2415 if (bufSize > tag->bufEnd - tag->buf) {
2416 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
2419 /* if tag->name.str points to tag->buf (only when namespace
2420 processing is off) then we have to update it
2422 if (tag->name.str == (XML_Char *)tag->buf)
2423 tag->name.str = (XML_Char *)temp;
2424 /* if tag->name.localPart is set (when namespace processing is on)
2425 then update it as well, since it will always point into tag->buf
2427 if (tag->name.localPart)
2429 = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf);
2431 tag->bufEnd = temp + bufSize;
2432 rawNameBuf = temp + nameLen;
2434 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2435 tag->rawName = rawNameBuf;
2441 static enum XML_Error PTRCALL
2442 contentProcessor(XML_Parser parser, const char *start, const char *end,
2443 const char **endPtr) {
2444 enum XML_Error result
2445 = doContent(parser, 0, parser->m_encoding, start, end, endPtr,
2446 (XML_Bool)! parser->m_parsingStatus.finalBuffer);
2447 if (result == XML_ERROR_NONE) {
2448 if (! storeRawNames(parser))
2449 return XML_ERROR_NO_MEMORY;
2454 static enum XML_Error PTRCALL
2455 externalEntityInitProcessor(XML_Parser parser, const char *start,
2456 const char *end, const char **endPtr) {
2457 enum XML_Error result = initializeEncoding(parser);
2458 if (result != XML_ERROR_NONE)
2460 parser->m_processor = externalEntityInitProcessor2;
2461 return externalEntityInitProcessor2(parser, start, end, endPtr);
2464 static enum XML_Error PTRCALL
2465 externalEntityInitProcessor2(XML_Parser parser, const char *start,
2466 const char *end, const char **endPtr) {
2467 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2468 int tok = XmlContentTok(parser->m_encoding, start, end, &next);
2471 /* If we are at the end of the buffer, this would cause the next stage,
2472 i.e. externalEntityInitProcessor3, to pass control directly to
2473 doContent (by detecting XML_TOK_NONE) without processing any xml text
2474 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2476 if (next == end && ! parser->m_parsingStatus.finalBuffer) {
2478 return XML_ERROR_NONE;
2482 case XML_TOK_PARTIAL:
2483 if (! parser->m_parsingStatus.finalBuffer) {
2485 return XML_ERROR_NONE;
2487 parser->m_eventPtr = start;
2488 return XML_ERROR_UNCLOSED_TOKEN;
2489 case XML_TOK_PARTIAL_CHAR:
2490 if (! parser->m_parsingStatus.finalBuffer) {
2492 return XML_ERROR_NONE;
2494 parser->m_eventPtr = start;
2495 return XML_ERROR_PARTIAL_CHAR;
2497 parser->m_processor = externalEntityInitProcessor3;
2498 return externalEntityInitProcessor3(parser, start, end, endPtr);
2501 static enum XML_Error PTRCALL
2502 externalEntityInitProcessor3(XML_Parser parser, const char *start,
2503 const char *end, const char **endPtr) {
2505 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2506 parser->m_eventPtr = start;
2507 tok = XmlContentTok(parser->m_encoding, start, end, &next);
2508 parser->m_eventEndPtr = next;
2511 case XML_TOK_XML_DECL: {
2512 enum XML_Error result;
2513 result = processXmlDecl(parser, 1, start, next);
2514 if (result != XML_ERROR_NONE)
2516 switch (parser->m_parsingStatus.parsing) {
2519 return XML_ERROR_NONE;
2521 return XML_ERROR_ABORTED;
2526 case XML_TOK_PARTIAL:
2527 if (! parser->m_parsingStatus.finalBuffer) {
2529 return XML_ERROR_NONE;
2531 return XML_ERROR_UNCLOSED_TOKEN;
2532 case XML_TOK_PARTIAL_CHAR:
2533 if (! parser->m_parsingStatus.finalBuffer) {
2535 return XML_ERROR_NONE;
2537 return XML_ERROR_PARTIAL_CHAR;
2539 parser->m_processor = externalEntityContentProcessor;
2540 parser->m_tagLevel = 1;
2541 return externalEntityContentProcessor(parser, start, end, endPtr);
2544 static enum XML_Error PTRCALL
2545 externalEntityContentProcessor(XML_Parser parser, const char *start,
2546 const char *end, const char **endPtr) {
2547 enum XML_Error result
2548 = doContent(parser, 1, parser->m_encoding, start, end, endPtr,
2549 (XML_Bool)! parser->m_parsingStatus.finalBuffer);
2550 if (result == XML_ERROR_NONE) {
2551 if (! storeRawNames(parser))
2552 return XML_ERROR_NO_MEMORY;
2557 static enum XML_Error
2558 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
2559 const char *s, const char *end, const char **nextPtr,
2560 XML_Bool haveMore) {
2561 /* save one level of indirection */
2562 DTD *const dtd = parser->m_dtd;
2564 const char **eventPP;
2565 const char **eventEndPP;
2566 if (enc == parser->m_encoding) {
2567 eventPP = &parser->m_eventPtr;
2568 eventEndPP = &parser->m_eventEndPtr;
2570 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
2571 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
2576 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2577 int tok = XmlContentTok(enc, s, end, &next);
2580 case XML_TOK_TRAILING_CR:
2583 return XML_ERROR_NONE;
2586 if (parser->m_characterDataHandler) {
2588 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
2589 } else if (parser->m_defaultHandler)
2590 reportDefault(parser, enc, s, end);
2591 /* We are at the end of the final buffer, should we check for
2592 XML_SUSPENDED, XML_FINISHED?
2594 if (startTagLevel == 0)
2595 return XML_ERROR_NO_ELEMENTS;
2596 if (parser->m_tagLevel != startTagLevel)
2597 return XML_ERROR_ASYNC_ENTITY;
2599 return XML_ERROR_NONE;
2603 return XML_ERROR_NONE;
2605 if (startTagLevel > 0) {
2606 if (parser->m_tagLevel != startTagLevel)
2607 return XML_ERROR_ASYNC_ENTITY;
2609 return XML_ERROR_NONE;
2611 return XML_ERROR_NO_ELEMENTS;
2612 case XML_TOK_INVALID:
2614 return XML_ERROR_INVALID_TOKEN;
2615 case XML_TOK_PARTIAL:
2618 return XML_ERROR_NONE;
2620 return XML_ERROR_UNCLOSED_TOKEN;
2621 case XML_TOK_PARTIAL_CHAR:
2624 return XML_ERROR_NONE;
2626 return XML_ERROR_PARTIAL_CHAR;
2627 case XML_TOK_ENTITY_REF: {
2628 const XML_Char *name;
2630 XML_Char ch = (XML_Char)XmlPredefinedEntityName(
2631 enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
2633 if (parser->m_characterDataHandler)
2634 parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
2635 else if (parser->m_defaultHandler)
2636 reportDefault(parser, enc, s, next);
2639 name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
2640 next - enc->minBytesPerChar);
2642 return XML_ERROR_NO_MEMORY;
2643 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
2644 poolDiscard(&dtd->pool);
2645 /* First, determine if a check for an existing declaration is needed;
2646 if yes, check that the entity exists, and that it is internal,
2647 otherwise call the skipped entity or default handler.
2649 if (! dtd->hasParamEntityRefs || dtd->standalone) {
2651 return XML_ERROR_UNDEFINED_ENTITY;
2652 else if (! entity->is_internal)
2653 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2654 } else if (! entity) {
2655 if (parser->m_skippedEntityHandler)
2656 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
2657 else if (parser->m_defaultHandler)
2658 reportDefault(parser, enc, s, next);
2662 return XML_ERROR_RECURSIVE_ENTITY_REF;
2663 if (entity->notation)
2664 return XML_ERROR_BINARY_ENTITY_REF;
2665 if (entity->textPtr) {
2666 enum XML_Error result;
2667 if (! parser->m_defaultExpandInternalEntities) {
2668 if (parser->m_skippedEntityHandler)
2669 parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name,
2671 else if (parser->m_defaultHandler)
2672 reportDefault(parser, enc, s, next);
2675 result = processInternalEntity(parser, entity, XML_FALSE);
2676 if (result != XML_ERROR_NONE)
2678 } else if (parser->m_externalEntityRefHandler) {
2679 const XML_Char *context;
2680 entity->open = XML_TRUE;
2681 context = getContext(parser);
2682 entity->open = XML_FALSE;
2684 return XML_ERROR_NO_MEMORY;
2685 if (! parser->m_externalEntityRefHandler(
2686 parser->m_externalEntityRefHandlerArg, context, entity->base,
2687 entity->systemId, entity->publicId))
2688 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2689 poolDiscard(&parser->m_tempPool);
2690 } else if (parser->m_defaultHandler)
2691 reportDefault(parser, enc, s, next);
2694 case XML_TOK_START_TAG_NO_ATTS:
2696 case XML_TOK_START_TAG_WITH_ATTS: {
2698 enum XML_Error result;
2700 if (parser->m_freeTagList) {
2701 tag = parser->m_freeTagList;
2702 parser->m_freeTagList = parser->m_freeTagList->parent;
2704 tag = (TAG *)MALLOC(parser, sizeof(TAG));
2706 return XML_ERROR_NO_MEMORY;
2707 tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
2710 return XML_ERROR_NO_MEMORY;
2712 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2714 tag->bindings = NULL;
2715 tag->parent = parser->m_tagStack;
2716 parser->m_tagStack = tag;
2717 tag->name.localPart = NULL;
2718 tag->name.prefix = NULL;
2719 tag->rawName = s + enc->minBytesPerChar;
2720 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2721 ++parser->m_tagLevel;
2723 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2724 const char *fromPtr = tag->rawName;
2725 toPtr = (XML_Char *)tag->buf;
2729 const enum XML_Convert_Result convert_res
2730 = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr,
2731 (ICHAR *)tag->bufEnd - 1);
2732 convLen = (int)(toPtr - (XML_Char *)tag->buf);
2733 if ((fromPtr >= rawNameEnd)
2734 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
2735 tag->name.strLen = convLen;
2738 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2740 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
2742 return XML_ERROR_NO_MEMORY;
2744 tag->bufEnd = temp + bufSize;
2745 toPtr = (XML_Char *)temp + convLen;
2749 tag->name.str = (XML_Char *)tag->buf;
2750 *toPtr = XML_T('\0');
2751 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2754 if (parser->m_startElementHandler)
2755 parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
2756 (const XML_Char **)parser->m_atts);
2757 else if (parser->m_defaultHandler)
2758 reportDefault(parser, enc, s, next);
2759 poolClear(&parser->m_tempPool);
2762 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2764 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: {
2765 const char *rawName = s + enc->minBytesPerChar;
2766 enum XML_Error result;
2767 BINDING *bindings = NULL;
2768 XML_Bool noElmHandlers = XML_TRUE;
2770 name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
2771 rawName + XmlNameLength(enc, rawName));
2773 return XML_ERROR_NO_MEMORY;
2774 poolFinish(&parser->m_tempPool);
2775 result = storeAtts(parser, enc, s, &name, &bindings);
2776 if (result != XML_ERROR_NONE) {
2777 freeBindings(parser, bindings);
2780 poolFinish(&parser->m_tempPool);
2781 if (parser->m_startElementHandler) {
2782 parser->m_startElementHandler(parser->m_handlerArg, name.str,
2783 (const XML_Char **)parser->m_atts);
2784 noElmHandlers = XML_FALSE;
2786 if (parser->m_endElementHandler) {
2787 if (parser->m_startElementHandler)
2788 *eventPP = *eventEndPP;
2789 parser->m_endElementHandler(parser->m_handlerArg, name.str);
2790 noElmHandlers = XML_FALSE;
2792 if (noElmHandlers && parser->m_defaultHandler)
2793 reportDefault(parser, enc, s, next);
2794 poolClear(&parser->m_tempPool);
2795 freeBindings(parser, bindings);
2797 if ((parser->m_tagLevel == 0)
2798 && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
2799 if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
2800 parser->m_processor = epilogProcessor;
2802 return epilogProcessor(parser, next, end, nextPtr);
2805 case XML_TOK_END_TAG:
2806 if (parser->m_tagLevel == startTagLevel)
2807 return XML_ERROR_ASYNC_ENTITY;
2810 const char *rawName;
2811 TAG *tag = parser->m_tagStack;
2812 parser->m_tagStack = tag->parent;
2813 tag->parent = parser->m_freeTagList;
2814 parser->m_freeTagList = tag;
2815 rawName = s + enc->minBytesPerChar * 2;
2816 len = XmlNameLength(enc, rawName);
2817 if (len != tag->rawNameLength
2818 || memcmp(tag->rawName, rawName, len) != 0) {
2820 return XML_ERROR_TAG_MISMATCH;
2822 --parser->m_tagLevel;
2823 if (parser->m_endElementHandler) {
2824 const XML_Char *localPart;
2825 const XML_Char *prefix;
2827 localPart = tag->name.localPart;
2828 if (parser->m_ns && localPart) {
2829 /* localPart and prefix may have been overwritten in
2830 tag->name.str, since this points to the binding->uri
2831 buffer which gets re-used; so we have to add them again
2833 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2834 /* don't need to check for space - already done in storeAtts() */
2836 *uri++ = *localPart++;
2837 prefix = (XML_Char *)tag->name.prefix;
2838 if (parser->m_ns_triplets && prefix) {
2839 *uri++ = parser->m_namespaceSeparator;
2845 parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
2846 } else if (parser->m_defaultHandler)
2847 reportDefault(parser, enc, s, next);
2848 while (tag->bindings) {
2849 BINDING *b = tag->bindings;
2850 if (parser->m_endNamespaceDeclHandler)
2851 parser->m_endNamespaceDeclHandler(parser->m_handlerArg,
2853 tag->bindings = tag->bindings->nextTagBinding;
2854 b->nextTagBinding = parser->m_freeBindingList;
2855 parser->m_freeBindingList = b;
2856 b->prefix->binding = b->prevPrefixBinding;
2858 if ((parser->m_tagLevel == 0)
2859 && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
2860 if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
2861 parser->m_processor = epilogProcessor;
2863 return epilogProcessor(parser, next, end, nextPtr);
2867 case XML_TOK_CHAR_REF: {
2868 int n = XmlCharRefNumber(enc, s);
2870 return XML_ERROR_BAD_CHAR_REF;
2871 if (parser->m_characterDataHandler) {
2872 XML_Char buf[XML_ENCODE_MAX];
2873 parser->m_characterDataHandler(parser->m_handlerArg, buf,
2874 XmlEncode(n, (ICHAR *)buf));
2875 } else if (parser->m_defaultHandler)
2876 reportDefault(parser, enc, s, next);
2878 case XML_TOK_XML_DECL:
2879 return XML_ERROR_MISPLACED_XML_PI;
2880 case XML_TOK_DATA_NEWLINE:
2881 if (parser->m_characterDataHandler) {
2883 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
2884 } else if (parser->m_defaultHandler)
2885 reportDefault(parser, enc, s, next);
2887 case XML_TOK_CDATA_SECT_OPEN: {
2888 enum XML_Error result;
2889 if (parser->m_startCdataSectionHandler)
2890 parser->m_startCdataSectionHandler(parser->m_handlerArg);
2891 /* BEGIN disabled code */
2892 /* Suppose you doing a transformation on a document that involves
2893 changing only the character data. You set up a defaultHandler
2894 and a characterDataHandler. The defaultHandler simply copies
2895 characters through. The characterDataHandler does the
2896 transformation and writes the characters out escaping them as
2897 necessary. This case will fail to work if we leave out the
2898 following two lines (because & and < inside CDATA sections will
2899 be incorrectly escaped).
2901 However, now we have a start/endCdataSectionHandler, so it seems
2902 easier to let the user deal with this.
2904 else if (0 && parser->m_characterDataHandler)
2905 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
2907 /* END disabled code */
2908 else if (parser->m_defaultHandler)
2909 reportDefault(parser, enc, s, next);
2910 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
2911 if (result != XML_ERROR_NONE)
2914 parser->m_processor = cdataSectionProcessor;
2918 case XML_TOK_TRAILING_RSQB:
2921 return XML_ERROR_NONE;
2923 if (parser->m_characterDataHandler) {
2924 if (MUST_CONVERT(enc, s)) {
2925 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
2926 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
2927 parser->m_characterDataHandler(
2928 parser->m_handlerArg, parser->m_dataBuf,
2929 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
2931 parser->m_characterDataHandler(
2932 parser->m_handlerArg, (XML_Char *)s,
2933 (int)((XML_Char *)end - (XML_Char *)s));
2934 } else if (parser->m_defaultHandler)
2935 reportDefault(parser, enc, s, end);
2936 /* We are at the end of the final buffer, should we check for
2937 XML_SUSPENDED, XML_FINISHED?
2939 if (startTagLevel == 0) {
2941 return XML_ERROR_NO_ELEMENTS;
2943 if (parser->m_tagLevel != startTagLevel) {
2945 return XML_ERROR_ASYNC_ENTITY;
2948 return XML_ERROR_NONE;
2949 case XML_TOK_DATA_CHARS: {
2950 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
2951 if (charDataHandler) {
2952 if (MUST_CONVERT(enc, s)) {
2954 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
2955 const enum XML_Convert_Result convert_res = XmlConvert(
2956 enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
2958 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
2959 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
2960 if ((convert_res == XML_CONVERT_COMPLETED)
2961 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
2966 charDataHandler(parser->m_handlerArg, (XML_Char *)s,
2967 (int)((XML_Char *)next - (XML_Char *)s));
2968 } else if (parser->m_defaultHandler)
2969 reportDefault(parser, enc, s, next);
2972 if (! reportProcessingInstruction(parser, enc, s, next))
2973 return XML_ERROR_NO_MEMORY;
2975 case XML_TOK_COMMENT:
2976 if (! reportComment(parser, enc, s, next))
2977 return XML_ERROR_NO_MEMORY;
2980 /* All of the tokens produced by XmlContentTok() have their own
2981 * explicit cases, so this default is not strictly necessary.
2982 * However it is a useful safety net, so we retain the code and
2983 * simply exclude it from the coverage tests.
2987 if (parser->m_defaultHandler)
2988 reportDefault(parser, enc, s, next);
2990 /* LCOV_EXCL_STOP */
2992 *eventPP = s = next;
2993 switch (parser->m_parsingStatus.parsing) {
2996 return XML_ERROR_NONE;
2998 return XML_ERROR_ABORTED;
3005 /* This function does not call free() on the allocated memory, merely
3006 * moving it to the parser's m_freeBindingList where it can be freed or
3007 * reused as appropriate.
3010 freeBindings(XML_Parser parser, BINDING *bindings) {
3012 BINDING *b = bindings;
3014 /* m_startNamespaceDeclHandler will have been called for this
3015 * binding in addBindings(), so call the end handler now.
3017 if (parser->m_endNamespaceDeclHandler)
3018 parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
3020 bindings = bindings->nextTagBinding;
3021 b->nextTagBinding = parser->m_freeBindingList;
3022 parser->m_freeBindingList = b;
3023 b->prefix->binding = b->prevPrefixBinding;
3027 /* Precondition: all arguments must be non-NULL;
3029 - normalize attributes
3030 - check attributes for well-formedness
3031 - generate namespace aware attribute names (URI, prefix)
3032 - build list of attributes for startElementHandler
3033 - default attributes
3034 - process namespace declarations (check and report them)
3035 - generate namespace aware element name (URI, prefix)
3037 static enum XML_Error
3038 storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
3039 TAG_NAME *tagNamePtr, BINDING **bindingsPtr) {
3040 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
3041 ELEMENT_TYPE *elementType;
3043 const XML_Char **appAtts; /* the attribute list for the application */
3051 const XML_Char *localPart;
3053 /* lookup the element type name */
3055 = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str, 0);
3056 if (! elementType) {
3057 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
3059 return XML_ERROR_NO_MEMORY;
3060 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
3061 sizeof(ELEMENT_TYPE));
3063 return XML_ERROR_NO_MEMORY;
3064 if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
3065 return XML_ERROR_NO_MEMORY;
3067 nDefaultAtts = elementType->nDefaultAtts;
3069 /* get the attributes from the tokenizer */
3070 n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
3071 if (n + nDefaultAtts > parser->m_attsSize) {
3072 int oldAttsSize = parser->m_attsSize;
3074 #ifdef XML_ATTR_INFO
3075 XML_AttrInfo *temp2;
3077 parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
3078 temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
3079 parser->m_attsSize * sizeof(ATTRIBUTE));
3081 parser->m_attsSize = oldAttsSize;
3082 return XML_ERROR_NO_MEMORY;
3084 parser->m_atts = temp;
3085 #ifdef XML_ATTR_INFO
3086 temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
3087 parser->m_attsSize * sizeof(XML_AttrInfo));
3088 if (temp2 == NULL) {
3089 parser->m_attsSize = oldAttsSize;
3090 return XML_ERROR_NO_MEMORY;
3092 parser->m_attInfo = temp2;
3094 if (n > oldAttsSize)
3095 XmlGetAttributes(enc, attStr, n, parser->m_atts);
3098 appAtts = (const XML_Char **)parser->m_atts;
3099 for (i = 0; i < n; i++) {
3100 ATTRIBUTE *currAtt = &parser->m_atts[i];
3101 #ifdef XML_ATTR_INFO
3102 XML_AttrInfo *currAttInfo = &parser->m_attInfo[i];
3104 /* add the name and value to the attribute list */
3106 = getAttributeId(parser, enc, currAtt->name,
3107 currAtt->name + XmlNameLength(enc, currAtt->name));
3109 return XML_ERROR_NO_MEMORY;
3110 #ifdef XML_ATTR_INFO
3111 currAttInfo->nameStart
3112 = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name);
3113 currAttInfo->nameEnd
3114 = currAttInfo->nameStart + XmlNameLength(enc, currAtt->name);
3115 currAttInfo->valueStart = parser->m_parseEndByteIndex
3116 - (parser->m_parseEndPtr - currAtt->valuePtr);
3117 currAttInfo->valueEnd = parser->m_parseEndByteIndex
3118 - (parser->m_parseEndPtr - currAtt->valueEnd);
3120 /* Detect duplicate attributes by their QNames. This does not work when
3121 namespace processing is turned on and different prefixes for the same
3122 namespace are used. For this case we have a check further down.
3124 if ((attId->name)[-1]) {
3125 if (enc == parser->m_encoding)
3126 parser->m_eventPtr = parser->m_atts[i].name;
3127 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3129 (attId->name)[-1] = 1;
3130 appAtts[attIndex++] = attId->name;
3131 if (! parser->m_atts[i].normalized) {
3132 enum XML_Error result;
3133 XML_Bool isCdata = XML_TRUE;
3135 /* figure out whether declared as other than CDATA */
3136 if (attId->maybeTokenized) {
3138 for (j = 0; j < nDefaultAtts; j++) {
3139 if (attId == elementType->defaultAtts[j].id) {
3140 isCdata = elementType->defaultAtts[j].isCdata;
3146 /* normalize the attribute value */
3147 result = storeAttributeValue(
3148 parser, enc, isCdata, parser->m_atts[i].valuePtr,
3149 parser->m_atts[i].valueEnd, &parser->m_tempPool);
3152 appAtts[attIndex] = poolStart(&parser->m_tempPool);
3153 poolFinish(&parser->m_tempPool);
3155 /* the value did not need normalizing */
3156 appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc,
3157 parser->m_atts[i].valuePtr,
3158 parser->m_atts[i].valueEnd);
3159 if (appAtts[attIndex] == 0)
3160 return XML_ERROR_NO_MEMORY;
3161 poolFinish(&parser->m_tempPool);
3163 /* handle prefixed attribute names */
3164 if (attId->prefix) {
3166 /* deal with namespace declarations here */
3167 enum XML_Error result = addBinding(parser, attId->prefix, attId,
3168 appAtts[attIndex], bindingsPtr);
3173 /* deal with other prefixed names later */
3176 (attId->name)[-1] = 2;
3182 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
3183 parser->m_nSpecifiedAtts = attIndex;
3184 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
3185 for (i = 0; i < attIndex; i += 2)
3186 if (appAtts[i] == elementType->idAtt->name) {
3187 parser->m_idAttIndex = i;
3191 parser->m_idAttIndex = -1;
3193 /* do attribute defaulting */
3194 for (i = 0; i < nDefaultAtts; i++) {
3195 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
3196 if (! (da->id->name)[-1] && da->value) {
3197 if (da->id->prefix) {
3198 if (da->id->xmlns) {
3199 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
3200 da->value, bindingsPtr);
3204 (da->id->name)[-1] = 2;
3206 appAtts[attIndex++] = da->id->name;
3207 appAtts[attIndex++] = da->value;
3210 (da->id->name)[-1] = 1;
3211 appAtts[attIndex++] = da->id->name;
3212 appAtts[attIndex++] = da->value;
3216 appAtts[attIndex] = 0;
3218 /* expand prefixed attribute names, check for duplicates,
3219 and clear flags that say whether attributes were specified */
3222 int j; /* hash table index */
3223 unsigned long version = parser->m_nsAttsVersion;
3224 int nsAttsSize = (int)1 << parser->m_nsAttsPower;
3225 unsigned char oldNsAttsPower = parser->m_nsAttsPower;
3226 /* size of hash table must be at least 2 * (# of prefixed attributes) */
3227 if ((nPrefixes << 1)
3228 >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
3230 /* hash table size must also be a power of 2 and >= 8 */
3231 while (nPrefixes >> parser->m_nsAttsPower++)
3233 if (parser->m_nsAttsPower < 3)
3234 parser->m_nsAttsPower = 3;
3235 nsAttsSize = (int)1 << parser->m_nsAttsPower;
3236 temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
3237 nsAttsSize * sizeof(NS_ATT));
3239 /* Restore actual size of memory in m_nsAtts */
3240 parser->m_nsAttsPower = oldNsAttsPower;
3241 return XML_ERROR_NO_MEMORY;
3243 parser->m_nsAtts = temp;
3244 version = 0; /* force re-initialization of m_nsAtts hash table */
3246 /* using a version flag saves us from initializing m_nsAtts every time */
3247 if (! version) { /* initialize version flags when version wraps around */
3248 version = INIT_ATTS_VERSION;
3249 for (j = nsAttsSize; j != 0;)
3250 parser->m_nsAtts[--j].version = version;
3252 parser->m_nsAttsVersion = --version;
3254 /* expand prefixed names and check for duplicates */
3255 for (; i < attIndex; i += 2) {
3256 const XML_Char *s = appAtts[i];
3257 if (s[-1] == 2) { /* prefixed */
3260 unsigned long uriHash;
3261 struct siphash sip_state;
3262 struct sipkey sip_key;
3264 copy_salt_to_sipkey(parser, &sip_key);
3265 sip24_init(&sip_state, &sip_key);
3267 ((XML_Char *)s)[-1] = 0; /* clear flag */
3268 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
3269 if (! id || ! id->prefix) {
3270 /* This code is walking through the appAtts array, dealing
3271 * with (in this case) a prefixed attribute name. To be in
3272 * the array, the attribute must have already been bound, so
3273 * has to have passed through the hash table lookup once
3274 * already. That implies that an entry for it already
3275 * exists, so the lookup above will return a pointer to
3276 * already allocated memory. There is no opportunaity for
3277 * the allocator to fail, so the condition above cannot be
3280 * Since it is difficult to be certain that the above
3281 * analysis is complete, we retain the test and merely
3282 * remove the code from coverage tests.
3284 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
3286 b = id->prefix->binding;
3288 return XML_ERROR_UNBOUND_PREFIX;
3290 for (j = 0; j < b->uriLen; j++) {
3291 const XML_Char c = b->uri[j];
3292 if (! poolAppendChar(&parser->m_tempPool, c))
3293 return XML_ERROR_NO_MEMORY;
3296 sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
3298 while (*s++ != XML_T(ASCII_COLON))
3301 sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
3303 do { /* copies null terminator */
3304 if (! poolAppendChar(&parser->m_tempPool, *s))
3305 return XML_ERROR_NO_MEMORY;
3308 uriHash = (unsigned long)sip24_final(&sip_state);
3310 { /* Check hash table for duplicate of expanded name (uriName).
3311 Derived from code in lookup(parser, HASH_TABLE *table, ...).
3313 unsigned char step = 0;
3314 unsigned long mask = nsAttsSize - 1;
3315 j = uriHash & mask; /* index into hash table */
3316 while (parser->m_nsAtts[j].version == version) {
3317 /* for speed we compare stored hash values first */
3318 if (uriHash == parser->m_nsAtts[j].hash) {
3319 const XML_Char *s1 = poolStart(&parser->m_tempPool);
3320 const XML_Char *s2 = parser->m_nsAtts[j].uriName;
3321 /* s1 is null terminated, but not s2 */
3322 for (; *s1 == *s2 && *s1 != 0; s1++, s2++)
3325 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3328 step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower);
3329 j < step ? (j += nsAttsSize - step) : (j -= step);
3333 if (parser->m_ns_triplets) { /* append namespace separator and prefix */
3334 parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator;
3335 s = b->prefix->name;
3337 if (! poolAppendChar(&parser->m_tempPool, *s))
3338 return XML_ERROR_NO_MEMORY;
3342 /* store expanded name in attribute list */
3343 s = poolStart(&parser->m_tempPool);
3344 poolFinish(&parser->m_tempPool);
3347 /* fill empty slot with new version, uriName and hash value */
3348 parser->m_nsAtts[j].version = version;
3349 parser->m_nsAtts[j].hash = uriHash;
3350 parser->m_nsAtts[j].uriName = s;
3352 if (! --nPrefixes) {
3356 } else /* not prefixed */
3357 ((XML_Char *)s)[-1] = 0; /* clear flag */
3360 /* clear flags for the remaining attributes */
3361 for (; i < attIndex; i += 2)
3362 ((XML_Char *)(appAtts[i]))[-1] = 0;
3363 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3364 binding->attId->name[-1] = 0;
3367 return XML_ERROR_NONE;
3369 /* expand the element type name */
3370 if (elementType->prefix) {
3371 binding = elementType->prefix->binding;
3373 return XML_ERROR_UNBOUND_PREFIX;
3374 localPart = tagNamePtr->str;
3375 while (*localPart++ != XML_T(ASCII_COLON))
3377 } else if (dtd->defaultPrefix.binding) {
3378 binding = dtd->defaultPrefix.binding;
3379 localPart = tagNamePtr->str;
3381 return XML_ERROR_NONE;
3383 if (parser->m_ns_triplets && binding->prefix->name) {
3384 for (; binding->prefix->name[prefixLen++];)
3385 ; /* prefixLen includes null terminator */
3387 tagNamePtr->localPart = localPart;
3388 tagNamePtr->uriLen = binding->uriLen;
3389 tagNamePtr->prefix = binding->prefix->name;
3390 tagNamePtr->prefixLen = prefixLen;
3391 for (i = 0; localPart[i++];)
3392 ; /* i includes null terminator */
3393 n = i + binding->uriLen + prefixLen;
3394 if (n > binding->uriAlloc) {
3396 uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
3398 return XML_ERROR_NO_MEMORY;
3399 binding->uriAlloc = n + EXPAND_SPARE;
3400 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
3401 for (p = parser->m_tagStack; p; p = p->parent)
3402 if (p->name.str == binding->uri)
3404 FREE(parser, binding->uri);
3407 /* if m_namespaceSeparator != '\0' then uri includes it already */
3408 uri = binding->uri + binding->uriLen;
3409 memcpy(uri, localPart, i * sizeof(XML_Char));
3410 /* we always have a namespace separator between localPart and prefix */
3413 *uri = parser->m_namespaceSeparator; /* replace null terminator */
3414 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3416 tagNamePtr->str = binding->uri;
3417 return XML_ERROR_NONE;
3420 /* addBinding() overwrites the value of prefix->binding without checking.
3421 Therefore one must keep track of the old value outside of addBinding().
3423 static enum XML_Error
3424 addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3425 const XML_Char *uri, BINDING **bindingsPtr) {
3426 static const XML_Char xmlNamespace[]
3427 = {ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON,
3428 ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
3429 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o,
3430 ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M,
3431 ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9,
3432 ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m,
3433 ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
3435 static const int xmlLen = (int)sizeof(xmlNamespace) / sizeof(XML_Char) - 1;
3436 static const XML_Char xmlnsNamespace[]
3437 = {ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH,
3438 ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w,
3439 ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH,
3440 ASCII_2, ASCII_0, ASCII_0, ASCII_0, ASCII_SLASH, ASCII_x,
3441 ASCII_m, ASCII_l, ASCII_n, ASCII_s, ASCII_SLASH, '\0'};
3442 static const int xmlnsLen
3443 = (int)sizeof(xmlnsNamespace) / sizeof(XML_Char) - 1;
3445 XML_Bool mustBeXML = XML_FALSE;
3446 XML_Bool isXML = XML_TRUE;
3447 XML_Bool isXMLNS = XML_TRUE;
3452 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3453 if (*uri == XML_T('\0') && prefix->name)
3454 return XML_ERROR_UNDECLARING_PREFIX;
3456 if (prefix->name && prefix->name[0] == XML_T(ASCII_x)
3457 && prefix->name[1] == XML_T(ASCII_m)
3458 && prefix->name[2] == XML_T(ASCII_l)) {
3459 /* Not allowed to bind xmlns */
3460 if (prefix->name[3] == XML_T(ASCII_n) && prefix->name[4] == XML_T(ASCII_s)
3461 && prefix->name[5] == XML_T('\0'))
3462 return XML_ERROR_RESERVED_PREFIX_XMLNS;
3464 if (prefix->name[3] == XML_T('\0'))
3465 mustBeXML = XML_TRUE;
3468 for (len = 0; uri[len]; len++) {
3469 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3472 if (! mustBeXML && isXMLNS
3473 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3474 isXMLNS = XML_FALSE;
3476 isXML = isXML && len == xmlLen;
3477 isXMLNS = isXMLNS && len == xmlnsLen;
3479 if (mustBeXML != isXML)
3480 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3481 : XML_ERROR_RESERVED_NAMESPACE_URI;
3484 return XML_ERROR_RESERVED_NAMESPACE_URI;
3486 if (parser->m_namespaceSeparator)
3488 if (parser->m_freeBindingList) {
3489 b = parser->m_freeBindingList;
3490 if (len > b->uriAlloc) {
3491 XML_Char *temp = (XML_Char *)REALLOC(
3492 parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
3494 return XML_ERROR_NO_MEMORY;
3496 b->uriAlloc = len + EXPAND_SPARE;
3498 parser->m_freeBindingList = b->nextTagBinding;
3500 b = (BINDING *)MALLOC(parser, sizeof(BINDING));
3502 return XML_ERROR_NO_MEMORY;
3504 = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
3507 return XML_ERROR_NO_MEMORY;
3509 b->uriAlloc = len + EXPAND_SPARE;
3512 memcpy(b->uri, uri, len * sizeof(XML_Char));
3513 if (parser->m_namespaceSeparator)
3514 b->uri[len - 1] = parser->m_namespaceSeparator;
3517 b->prevPrefixBinding = prefix->binding;
3518 /* NULL binding when default namespace undeclared */
3519 if (*uri == XML_T('\0') && prefix == &parser->m_dtd->defaultPrefix)
3520 prefix->binding = NULL;
3522 prefix->binding = b;
3523 b->nextTagBinding = *bindingsPtr;
3525 /* if attId == NULL then we are not starting a namespace scope */
3526 if (attId && parser->m_startNamespaceDeclHandler)
3527 parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name,
3528 prefix->binding ? uri : 0);
3529 return XML_ERROR_NONE;
3532 /* The idea here is to avoid using stack for each CDATA section when
3533 the whole file is parsed with one call.
3535 static enum XML_Error PTRCALL
3536 cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
3537 const char **endPtr) {
3538 enum XML_Error result
3539 = doCdataSection(parser, parser->m_encoding, &start, end, endPtr,
3540 (XML_Bool)! parser->m_parsingStatus.finalBuffer);
3541 if (result != XML_ERROR_NONE)
3544 if (parser->m_parentParser) { /* we are parsing an external entity */
3545 parser->m_processor = externalEntityContentProcessor;
3546 return externalEntityContentProcessor(parser, start, end, endPtr);
3548 parser->m_processor = contentProcessor;
3549 return contentProcessor(parser, start, end, endPtr);
3555 /* startPtr gets set to non-null if the section is closed, and to null if
3556 the section is not yet closed.
3558 static enum XML_Error
3559 doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
3560 const char *end, const char **nextPtr, XML_Bool haveMore) {
3561 const char *s = *startPtr;
3562 const char **eventPP;
3563 const char **eventEndPP;
3564 if (enc == parser->m_encoding) {
3565 eventPP = &parser->m_eventPtr;
3567 eventEndPP = &parser->m_eventEndPtr;
3569 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3570 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
3577 int tok = XmlCdataSectionTok(enc, s, end, &next);
3580 case XML_TOK_CDATA_SECT_CLOSE:
3581 if (parser->m_endCdataSectionHandler)
3582 parser->m_endCdataSectionHandler(parser->m_handlerArg);
3583 /* BEGIN disabled code */
3584 /* see comment under XML_TOK_CDATA_SECT_OPEN */
3585 else if (0 && parser->m_characterDataHandler)
3586 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3588 /* END disabled code */
3589 else if (parser->m_defaultHandler)
3590 reportDefault(parser, enc, s, next);
3593 if (parser->m_parsingStatus.parsing == XML_FINISHED)
3594 return XML_ERROR_ABORTED;
3596 return XML_ERROR_NONE;
3597 case XML_TOK_DATA_NEWLINE:
3598 if (parser->m_characterDataHandler) {
3600 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
3601 } else if (parser->m_defaultHandler)
3602 reportDefault(parser, enc, s, next);
3604 case XML_TOK_DATA_CHARS: {
3605 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
3606 if (charDataHandler) {
3607 if (MUST_CONVERT(enc, s)) {
3609 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3610 const enum XML_Convert_Result convert_res = XmlConvert(
3611 enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3613 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3614 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
3615 if ((convert_res == XML_CONVERT_COMPLETED)
3616 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3621 charDataHandler(parser->m_handlerArg, (XML_Char *)s,
3622 (int)((XML_Char *)next - (XML_Char *)s));
3623 } else if (parser->m_defaultHandler)
3624 reportDefault(parser, enc, s, next);
3626 case XML_TOK_INVALID:
3628 return XML_ERROR_INVALID_TOKEN;
3629 case XML_TOK_PARTIAL_CHAR:
3632 return XML_ERROR_NONE;
3634 return XML_ERROR_PARTIAL_CHAR;
3635 case XML_TOK_PARTIAL:
3639 return XML_ERROR_NONE;
3641 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3643 /* Every token returned by XmlCdataSectionTok() has its own
3644 * explicit case, so this default case will never be executed.
3645 * We retain it as a safety net and exclude it from the coverage
3651 return XML_ERROR_UNEXPECTED_STATE;
3652 /* LCOV_EXCL_STOP */
3655 *eventPP = s = next;
3656 switch (parser->m_parsingStatus.parsing) {
3659 return XML_ERROR_NONE;
3661 return XML_ERROR_ABORTED;
3670 /* The idea here is to avoid using stack for each IGNORE section when
3671 the whole file is parsed with one call.
3673 static enum XML_Error PTRCALL
3674 ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end,
3675 const char **endPtr) {
3676 enum XML_Error result
3677 = doIgnoreSection(parser, parser->m_encoding, &start, end, endPtr,
3678 (XML_Bool)! parser->m_parsingStatus.finalBuffer);
3679 if (result != XML_ERROR_NONE)
3682 parser->m_processor = prologProcessor;
3683 return prologProcessor(parser, start, end, endPtr);
3688 /* startPtr gets set to non-null is the section is closed, and to null
3689 if the section is not yet closed.
3691 static enum XML_Error
3692 doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
3693 const char *end, const char **nextPtr, XML_Bool haveMore) {
3696 const char *s = *startPtr;
3697 const char **eventPP;
3698 const char **eventEndPP;
3699 if (enc == parser->m_encoding) {
3700 eventPP = &parser->m_eventPtr;
3702 eventEndPP = &parser->m_eventEndPtr;
3704 /* It's not entirely clear, but it seems the following two lines
3705 * of code cannot be executed. The only occasions on which 'enc'
3706 * is not 'encoding' are when this function is called
3707 * from the internal entity processing, and IGNORE sections are an
3708 * error in internal entities.
3710 * Since it really isn't clear that this is true, we keep the code
3711 * and just remove it from our coverage tests.
3715 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3716 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
3717 /* LCOV_EXCL_STOP */
3721 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3724 case XML_TOK_IGNORE_SECT:
3725 if (parser->m_defaultHandler)
3726 reportDefault(parser, enc, s, next);
3729 if (parser->m_parsingStatus.parsing == XML_FINISHED)
3730 return XML_ERROR_ABORTED;
3732 return XML_ERROR_NONE;
3733 case XML_TOK_INVALID:
3735 return XML_ERROR_INVALID_TOKEN;
3736 case XML_TOK_PARTIAL_CHAR:
3739 return XML_ERROR_NONE;
3741 return XML_ERROR_PARTIAL_CHAR;
3742 case XML_TOK_PARTIAL:
3746 return XML_ERROR_NONE;
3748 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3750 /* All of the tokens that XmlIgnoreSectionTok() returns have
3751 * explicit cases to handle them, so this default case is never
3752 * executed. We keep it as a safety net anyway, and remove it
3753 * from our test coverage statistics.
3758 return XML_ERROR_UNEXPECTED_STATE;
3759 /* LCOV_EXCL_STOP */
3764 #endif /* XML_DTD */
3766 static enum XML_Error
3767 initializeEncoding(XML_Parser parser) {
3770 char encodingBuf[128];
3771 /* See comments abount `protoclEncodingName` in parserInit() */
3772 if (! parser->m_protocolEncodingName)
3776 for (i = 0; parser->m_protocolEncodingName[i]; i++) {
3777 if (i == sizeof(encodingBuf) - 1
3778 || (parser->m_protocolEncodingName[i] & ~0x7f) != 0) {
3779 encodingBuf[0] = '\0';
3782 encodingBuf[i] = (char)parser->m_protocolEncodingName[i];
3784 encodingBuf[i] = '\0';
3788 s = parser->m_protocolEncodingName;
3790 if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(
3791 &parser->m_initEncoding, &parser->m_encoding, s))
3792 return XML_ERROR_NONE;
3793 return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
3796 static enum XML_Error
3797 processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
3799 const char *encodingName = NULL;
3800 const XML_Char *storedEncName = NULL;
3801 const ENCODING *newEncoding = NULL;
3802 const char *version = NULL;
3803 const char *versionend;
3804 const XML_Char *storedversion = NULL;
3805 int standalone = -1;
3806 if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
3807 isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
3808 &version, &versionend, &encodingName, &newEncoding, &standalone)) {
3809 if (isGeneralTextEntity)
3810 return XML_ERROR_TEXT_DECL;
3812 return XML_ERROR_XML_DECL;
3814 if (! isGeneralTextEntity && standalone == 1) {
3815 parser->m_dtd->standalone = XML_TRUE;
3817 if (parser->m_paramEntityParsing
3818 == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3819 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
3820 #endif /* XML_DTD */
3822 if (parser->m_xmlDeclHandler) {
3823 if (encodingName != NULL) {
3824 storedEncName = poolStoreString(
3825 &parser->m_temp2Pool, parser->m_encoding, encodingName,
3826 encodingName + XmlNameLength(parser->m_encoding, encodingName));
3827 if (! storedEncName)
3828 return XML_ERROR_NO_MEMORY;
3829 poolFinish(&parser->m_temp2Pool);
3833 = poolStoreString(&parser->m_temp2Pool, parser->m_encoding, version,
3834 versionend - parser->m_encoding->minBytesPerChar);
3835 if (! storedversion)
3836 return XML_ERROR_NO_MEMORY;
3838 parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName,
3840 } else if (parser->m_defaultHandler)
3841 reportDefault(parser, parser->m_encoding, s, next);
3842 if (parser->m_protocolEncodingName == NULL) {
3844 /* Check that the specified encoding does not conflict with what
3845 * the parser has already deduced. Do we have the same number
3846 * of bytes in the smallest representation of a character? If
3847 * this is UTF-16, is it the same endianness?
3849 if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
3850 || (newEncoding->minBytesPerChar == 2
3851 && newEncoding != parser->m_encoding)) {
3852 parser->m_eventPtr = encodingName;
3853 return XML_ERROR_INCORRECT_ENCODING;
3855 parser->m_encoding = newEncoding;
3856 } else if (encodingName) {
3857 enum XML_Error result;
3858 if (! storedEncName) {
3859 storedEncName = poolStoreString(
3860 &parser->m_temp2Pool, parser->m_encoding, encodingName,
3861 encodingName + XmlNameLength(parser->m_encoding, encodingName));
3862 if (! storedEncName)
3863 return XML_ERROR_NO_MEMORY;
3865 result = handleUnknownEncoding(parser, storedEncName);
3866 poolClear(&parser->m_temp2Pool);
3867 if (result == XML_ERROR_UNKNOWN_ENCODING)
3868 parser->m_eventPtr = encodingName;
3873 if (storedEncName || storedversion)
3874 poolClear(&parser->m_temp2Pool);
3876 return XML_ERROR_NONE;
3879 static enum XML_Error
3880 handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) {
3881 if (parser->m_unknownEncodingHandler) {
3884 for (i = 0; i < 256; i++)
3886 info.convert = NULL;
3888 info.release = NULL;
3889 if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData,
3890 encodingName, &info)) {
3892 parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding());
3893 if (! parser->m_unknownEncodingMem) {
3895 info.release(info.data);
3896 return XML_ERROR_NO_MEMORY;
3898 enc = (parser->m_ns ? XmlInitUnknownEncodingNS : XmlInitUnknownEncoding)(
3899 parser->m_unknownEncodingMem, info.map, info.convert, info.data);
3901 parser->m_unknownEncodingData = info.data;
3902 parser->m_unknownEncodingRelease = info.release;
3903 parser->m_encoding = enc;
3904 return XML_ERROR_NONE;
3907 if (info.release != NULL)
3908 info.release(info.data);
3910 return XML_ERROR_UNKNOWN_ENCODING;
3913 static enum XML_Error PTRCALL
3914 prologInitProcessor(XML_Parser parser, const char *s, const char *end,
3915 const char **nextPtr) {
3916 enum XML_Error result = initializeEncoding(parser);
3917 if (result != XML_ERROR_NONE)
3919 parser->m_processor = prologProcessor;
3920 return prologProcessor(parser, s, end, nextPtr);
3925 static enum XML_Error PTRCALL
3926 externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
3927 const char **nextPtr) {
3928 enum XML_Error result = initializeEncoding(parser);
3929 if (result != XML_ERROR_NONE)
3932 /* we know now that XML_Parse(Buffer) has been called,
3933 so we consider the external parameter entity read */
3934 parser->m_dtd->paramEntityRead = XML_TRUE;
3936 if (parser->m_prologState.inEntityValue) {
3937 parser->m_processor = entityValueInitProcessor;
3938 return entityValueInitProcessor(parser, s, end, nextPtr);
3940 parser->m_processor = externalParEntProcessor;
3941 return externalParEntProcessor(parser, s, end, nextPtr);
3945 static enum XML_Error PTRCALL
3946 entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
3947 const char **nextPtr) {
3949 const char *start = s;
3950 const char *next = start;
3951 parser->m_eventPtr = start;
3954 tok = XmlPrologTok(parser->m_encoding, start, end, &next);
3955 parser->m_eventEndPtr = next;
3957 if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
3959 return XML_ERROR_NONE;
3962 case XML_TOK_INVALID:
3963 return XML_ERROR_INVALID_TOKEN;
3964 case XML_TOK_PARTIAL:
3965 return XML_ERROR_UNCLOSED_TOKEN;
3966 case XML_TOK_PARTIAL_CHAR:
3967 return XML_ERROR_PARTIAL_CHAR;
3968 case XML_TOK_NONE: /* start == end */
3972 /* found end of entity value - can store it now */
3973 return storeEntityValue(parser, parser->m_encoding, s, end);
3974 } else if (tok == XML_TOK_XML_DECL) {
3975 enum XML_Error result;
3976 result = processXmlDecl(parser, 0, start, next);
3977 if (result != XML_ERROR_NONE)
3979 /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED. For
3980 * that to happen, a parameter entity parsing handler must have attempted
3981 * to suspend the parser, which fails and raises an error. The parser can
3982 * be aborted, but can't be suspended.
3984 if (parser->m_parsingStatus.parsing == XML_FINISHED)
3985 return XML_ERROR_ABORTED;
3987 /* stop scanning for text declaration - we found one */
3988 parser->m_processor = entityValueProcessor;
3989 return entityValueProcessor(parser, next, end, nextPtr);
3991 /* If we are at the end of the buffer, this would cause XmlPrologTok to
3992 return XML_TOK_NONE on the next call, which would then cause the
3993 function to exit with *nextPtr set to s - that is what we want for other
3994 tokens, but not for the BOM - we would rather like to skip it;
3995 then, when this routine is entered the next time, XmlPrologTok will
3996 return XML_TOK_INVALID, since the BOM is still in the buffer
3998 else if (tok == XML_TOK_BOM && next == end
3999 && ! parser->m_parsingStatus.finalBuffer) {
4001 return XML_ERROR_NONE;
4003 /* If we get this token, we have the start of what might be a
4004 normal tag, but not a declaration (i.e. it doesn't begin with
4005 "<!"). In a DTD context, that isn't legal.
4007 else if (tok == XML_TOK_INSTANCE_START) {
4009 return XML_ERROR_SYNTAX;
4012 parser->m_eventPtr = start;
4016 static enum XML_Error PTRCALL
4017 externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
4018 const char **nextPtr) {
4019 const char *next = s;
4022 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4024 if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
4026 return XML_ERROR_NONE;
4029 case XML_TOK_INVALID:
4030 return XML_ERROR_INVALID_TOKEN;
4031 case XML_TOK_PARTIAL:
4032 return XML_ERROR_UNCLOSED_TOKEN;
4033 case XML_TOK_PARTIAL_CHAR:
4034 return XML_ERROR_PARTIAL_CHAR;
4035 case XML_TOK_NONE: /* start == end */
4040 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
4041 However, when parsing an external subset, doProlog will not accept a BOM
4042 as valid, and report a syntax error, so we have to skip the BOM
4044 else if (tok == XML_TOK_BOM) {
4046 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4049 parser->m_processor = prologProcessor;
4050 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
4051 (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
4054 static enum XML_Error PTRCALL
4055 entityValueProcessor(XML_Parser parser, const char *s, const char *end,
4056 const char **nextPtr) {
4057 const char *start = s;
4058 const char *next = s;
4059 const ENCODING *enc = parser->m_encoding;
4063 tok = XmlPrologTok(enc, start, end, &next);
4065 if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
4067 return XML_ERROR_NONE;
4070 case XML_TOK_INVALID:
4071 return XML_ERROR_INVALID_TOKEN;
4072 case XML_TOK_PARTIAL:
4073 return XML_ERROR_UNCLOSED_TOKEN;
4074 case XML_TOK_PARTIAL_CHAR:
4075 return XML_ERROR_PARTIAL_CHAR;
4076 case XML_TOK_NONE: /* start == end */
4080 /* found end of entity value - can store it now */
4081 return storeEntityValue(parser, enc, s, end);
4087 #endif /* XML_DTD */
4089 static enum XML_Error PTRCALL
4090 prologProcessor(XML_Parser parser, const char *s, const char *end,
4091 const char **nextPtr) {
4092 const char *next = s;
4093 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4094 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
4095 (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
4098 static enum XML_Error
4099 doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
4100 int tok, const char *next, const char **nextPtr, XML_Bool haveMore,
4101 XML_Bool allowClosingDoctype) {
4103 static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
4104 #endif /* XML_DTD */
4105 static const XML_Char atypeCDATA[]
4106 = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
4107 static const XML_Char atypeID[] = {ASCII_I, ASCII_D, '\0'};
4108 static const XML_Char atypeIDREF[]
4109 = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'};
4110 static const XML_Char atypeIDREFS[]
4111 = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0'};
4112 static const XML_Char atypeENTITY[]
4113 = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0'};
4114 static const XML_Char atypeENTITIES[]
4115 = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T,
4116 ASCII_I, ASCII_E, ASCII_S, '\0'};
4117 static const XML_Char atypeNMTOKEN[]
4118 = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0'};
4119 static const XML_Char atypeNMTOKENS[]
4120 = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K,
4121 ASCII_E, ASCII_N, ASCII_S, '\0'};
4122 static const XML_Char notationPrefix[]
4123 = {ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T,
4124 ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0'};
4125 static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
4126 static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
4128 /* save one level of indirection */
4129 DTD *const dtd = parser->m_dtd;
4131 const char **eventPP;
4132 const char **eventEndPP;
4133 enum XML_Content_Quant quant;
4135 if (enc == parser->m_encoding) {
4136 eventPP = &parser->m_eventPtr;
4137 eventEndPP = &parser->m_eventEndPtr;
4139 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4140 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
4145 XML_Bool handleDefault = XML_TRUE;
4149 if (haveMore && tok != XML_TOK_INVALID) {
4151 return XML_ERROR_NONE;
4154 case XML_TOK_INVALID:
4156 return XML_ERROR_INVALID_TOKEN;
4157 case XML_TOK_PARTIAL:
4158 return XML_ERROR_UNCLOSED_TOKEN;
4159 case XML_TOK_PARTIAL_CHAR:
4160 return XML_ERROR_PARTIAL_CHAR;
4161 case -XML_TOK_PROLOG_S:
4166 /* for internal PE NOT referenced between declarations */
4167 if (enc != parser->m_encoding
4168 && ! parser->m_openInternalEntities->betweenDecl) {
4170 return XML_ERROR_NONE;
4172 /* WFC: PE Between Declarations - must check that PE contains
4173 complete markup, not only for external PEs, but also for
4174 internal PEs if the reference occurs between declarations.
4176 if (parser->m_isParamEntity || enc != parser->m_encoding) {
4177 if (XmlTokenRole(&parser->m_prologState, XML_TOK_NONE, end, end, enc)
4179 return XML_ERROR_INCOMPLETE_PE;
4181 return XML_ERROR_NONE;
4183 #endif /* XML_DTD */
4184 return XML_ERROR_NO_ELEMENTS;
4191 role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
4193 case XML_ROLE_XML_DECL: {
4194 enum XML_Error result = processXmlDecl(parser, 0, s, next);
4195 if (result != XML_ERROR_NONE)
4197 enc = parser->m_encoding;
4198 handleDefault = XML_FALSE;
4200 case XML_ROLE_DOCTYPE_NAME:
4201 if (parser->m_startDoctypeDeclHandler) {
4202 parser->m_doctypeName
4203 = poolStoreString(&parser->m_tempPool, enc, s, next);
4204 if (! parser->m_doctypeName)
4205 return XML_ERROR_NO_MEMORY;
4206 poolFinish(&parser->m_tempPool);
4207 parser->m_doctypePubid = NULL;
4208 handleDefault = XML_FALSE;
4210 parser->m_doctypeSysid = NULL; /* always initialize to NULL */
4212 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
4213 if (parser->m_startDoctypeDeclHandler) {
4214 parser->m_startDoctypeDeclHandler(
4215 parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
4216 parser->m_doctypePubid, 1);
4217 parser->m_doctypeName = NULL;
4218 poolClear(&parser->m_tempPool);
4219 handleDefault = XML_FALSE;
4223 case XML_ROLE_TEXT_DECL: {
4224 enum XML_Error result = processXmlDecl(parser, 1, s, next);
4225 if (result != XML_ERROR_NONE)
4227 enc = parser->m_encoding;
4228 handleDefault = XML_FALSE;
4230 #endif /* XML_DTD */
4231 case XML_ROLE_DOCTYPE_PUBLIC_ID:
4233 parser->m_useForeignDTD = XML_FALSE;
4234 parser->m_declEntity = (ENTITY *)lookup(
4235 parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
4236 if (! parser->m_declEntity)
4237 return XML_ERROR_NO_MEMORY;
4238 #endif /* XML_DTD */
4239 dtd->hasParamEntityRefs = XML_TRUE;
4240 if (parser->m_startDoctypeDeclHandler) {
4242 if (! XmlIsPublicId(enc, s, next, eventPP))
4243 return XML_ERROR_PUBLICID;
4244 pubId = poolStoreString(&parser->m_tempPool, enc,
4245 s + enc->minBytesPerChar,
4246 next - enc->minBytesPerChar);
4248 return XML_ERROR_NO_MEMORY;
4249 normalizePublicId(pubId);
4250 poolFinish(&parser->m_tempPool);
4251 parser->m_doctypePubid = pubId;
4252 handleDefault = XML_FALSE;
4253 goto alreadyChecked;
4256 case XML_ROLE_ENTITY_PUBLIC_ID:
4257 if (! XmlIsPublicId(enc, s, next, eventPP))
4258 return XML_ERROR_PUBLICID;
4260 if (dtd->keepProcessing && parser->m_declEntity) {
4262 = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
4263 next - enc->minBytesPerChar);
4265 return XML_ERROR_NO_MEMORY;
4266 normalizePublicId(tem);
4267 parser->m_declEntity->publicId = tem;
4268 poolFinish(&dtd->pool);
4269 /* Don't suppress the default handler if we fell through from
4270 * the XML_ROLE_DOCTYPE_PUBLIC_ID case.
4272 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID)
4273 handleDefault = XML_FALSE;
4276 case XML_ROLE_DOCTYPE_CLOSE:
4277 if (allowClosingDoctype != XML_TRUE) {
4278 /* Must not close doctype from within expanded parameter entities */
4279 return XML_ERROR_INVALID_TOKEN;
4282 if (parser->m_doctypeName) {
4283 parser->m_startDoctypeDeclHandler(
4284 parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
4285 parser->m_doctypePubid, 0);
4286 poolClear(&parser->m_tempPool);
4287 handleDefault = XML_FALSE;
4289 /* parser->m_doctypeSysid will be non-NULL in the case of a previous
4290 XML_ROLE_DOCTYPE_SYSTEM_ID, even if parser->m_startDoctypeDeclHandler
4291 was not set, indicating an external subset
4294 if (parser->m_doctypeSysid || parser->m_useForeignDTD) {
4295 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4296 dtd->hasParamEntityRefs = XML_TRUE;
4297 if (parser->m_paramEntityParsing
4298 && parser->m_externalEntityRefHandler) {
4299 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4300 externalSubsetName, sizeof(ENTITY));
4302 /* The external subset name "#" will have already been
4303 * inserted into the hash table at the start of the
4304 * external entity parsing, so no allocation will happen
4305 * and lookup() cannot fail.
4307 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
4309 if (parser->m_useForeignDTD)
4310 entity->base = parser->m_curBase;
4311 dtd->paramEntityRead = XML_FALSE;
4312 if (! parser->m_externalEntityRefHandler(
4313 parser->m_externalEntityRefHandlerArg, 0, entity->base,
4314 entity->systemId, entity->publicId))
4315 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4316 if (dtd->paramEntityRead) {
4317 if (! dtd->standalone && parser->m_notStandaloneHandler
4318 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
4319 return XML_ERROR_NOT_STANDALONE;
4321 /* if we didn't read the foreign DTD then this means that there
4322 is no external subset and we must reset dtd->hasParamEntityRefs
4324 else if (! parser->m_doctypeSysid)
4325 dtd->hasParamEntityRefs = hadParamEntityRefs;
4326 /* end of DTD - no need to update dtd->keepProcessing */
4328 parser->m_useForeignDTD = XML_FALSE;
4330 #endif /* XML_DTD */
4331 if (parser->m_endDoctypeDeclHandler) {
4332 parser->m_endDoctypeDeclHandler(parser->m_handlerArg);
4333 handleDefault = XML_FALSE;
4336 case XML_ROLE_INSTANCE_START:
4338 /* if there is no DOCTYPE declaration then now is the
4339 last chance to read the foreign DTD
4341 if (parser->m_useForeignDTD) {
4342 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4343 dtd->hasParamEntityRefs = XML_TRUE;
4344 if (parser->m_paramEntityParsing
4345 && parser->m_externalEntityRefHandler) {
4346 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4347 externalSubsetName, sizeof(ENTITY));
4349 return XML_ERROR_NO_MEMORY;
4350 entity->base = parser->m_curBase;
4351 dtd->paramEntityRead = XML_FALSE;
4352 if (! parser->m_externalEntityRefHandler(
4353 parser->m_externalEntityRefHandlerArg, 0, entity->base,
4354 entity->systemId, entity->publicId))
4355 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4356 if (dtd->paramEntityRead) {
4357 if (! dtd->standalone && parser->m_notStandaloneHandler
4358 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
4359 return XML_ERROR_NOT_STANDALONE;
4361 /* if we didn't read the foreign DTD then this means that there
4362 is no external subset and we must reset dtd->hasParamEntityRefs
4365 dtd->hasParamEntityRefs = hadParamEntityRefs;
4366 /* end of DTD - no need to update dtd->keepProcessing */
4369 #endif /* XML_DTD */
4370 parser->m_processor = contentProcessor;
4371 return contentProcessor(parser, s, end, nextPtr);
4372 case XML_ROLE_ATTLIST_ELEMENT_NAME:
4373 parser->m_declElementType = getElementType(parser, enc, s, next);
4374 if (! parser->m_declElementType)
4375 return XML_ERROR_NO_MEMORY;
4376 goto checkAttListDeclHandler;
4377 case XML_ROLE_ATTRIBUTE_NAME:
4378 parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
4379 if (! parser->m_declAttributeId)
4380 return XML_ERROR_NO_MEMORY;
4381 parser->m_declAttributeIsCdata = XML_FALSE;
4382 parser->m_declAttributeType = NULL;
4383 parser->m_declAttributeIsId = XML_FALSE;
4384 goto checkAttListDeclHandler;
4385 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
4386 parser->m_declAttributeIsCdata = XML_TRUE;
4387 parser->m_declAttributeType = atypeCDATA;
4388 goto checkAttListDeclHandler;
4389 case XML_ROLE_ATTRIBUTE_TYPE_ID:
4390 parser->m_declAttributeIsId = XML_TRUE;
4391 parser->m_declAttributeType = atypeID;
4392 goto checkAttListDeclHandler;
4393 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
4394 parser->m_declAttributeType = atypeIDREF;
4395 goto checkAttListDeclHandler;
4396 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
4397 parser->m_declAttributeType = atypeIDREFS;
4398 goto checkAttListDeclHandler;
4399 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
4400 parser->m_declAttributeType = atypeENTITY;
4401 goto checkAttListDeclHandler;
4402 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
4403 parser->m_declAttributeType = atypeENTITIES;
4404 goto checkAttListDeclHandler;
4405 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
4406 parser->m_declAttributeType = atypeNMTOKEN;
4407 goto checkAttListDeclHandler;
4408 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
4409 parser->m_declAttributeType = atypeNMTOKENS;
4410 checkAttListDeclHandler:
4411 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
4412 handleDefault = XML_FALSE;
4414 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4415 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
4416 if (dtd->keepProcessing && parser->m_attlistDeclHandler) {
4417 const XML_Char *prefix;
4418 if (parser->m_declAttributeType) {
4419 prefix = enumValueSep;
4421 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE ? notationPrefix
4424 if (! poolAppendString(&parser->m_tempPool, prefix))
4425 return XML_ERROR_NO_MEMORY;
4426 if (! poolAppend(&parser->m_tempPool, enc, s, next))
4427 return XML_ERROR_NO_MEMORY;
4428 parser->m_declAttributeType = parser->m_tempPool.start;
4429 handleDefault = XML_FALSE;
4432 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4433 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4434 if (dtd->keepProcessing) {
4435 if (! defineAttribute(parser->m_declElementType,
4436 parser->m_declAttributeId,
4437 parser->m_declAttributeIsCdata,
4438 parser->m_declAttributeIsId, 0, parser))
4439 return XML_ERROR_NO_MEMORY;
4440 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
4441 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
4442 || (*parser->m_declAttributeType == XML_T(ASCII_N)
4443 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
4444 /* Enumerated or Notation type */
4445 if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
4446 || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
4447 return XML_ERROR_NO_MEMORY;
4448 parser->m_declAttributeType = parser->m_tempPool.start;
4449 poolFinish(&parser->m_tempPool);
4452 parser->m_attlistDeclHandler(
4453 parser->m_handlerArg, parser->m_declElementType->name,
4454 parser->m_declAttributeId->name, parser->m_declAttributeType, 0,
4455 role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
4456 poolClear(&parser->m_tempPool);
4457 handleDefault = XML_FALSE;
4461 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4462 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4463 if (dtd->keepProcessing) {
4464 const XML_Char *attVal;
4465 enum XML_Error result = storeAttributeValue(
4466 parser, enc, parser->m_declAttributeIsCdata,
4467 s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool);
4470 attVal = poolStart(&dtd->pool);
4471 poolFinish(&dtd->pool);
4472 /* ID attributes aren't allowed to have a default */
4473 if (! defineAttribute(
4474 parser->m_declElementType, parser->m_declAttributeId,
4475 parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
4476 return XML_ERROR_NO_MEMORY;
4477 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
4478 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
4479 || (*parser->m_declAttributeType == XML_T(ASCII_N)
4480 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
4481 /* Enumerated or Notation type */
4482 if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
4483 || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
4484 return XML_ERROR_NO_MEMORY;
4485 parser->m_declAttributeType = parser->m_tempPool.start;
4486 poolFinish(&parser->m_tempPool);
4489 parser->m_attlistDeclHandler(
4490 parser->m_handlerArg, parser->m_declElementType->name,
4491 parser->m_declAttributeId->name, parser->m_declAttributeType,
4492 attVal, role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4493 poolClear(&parser->m_tempPool);
4494 handleDefault = XML_FALSE;
4498 case XML_ROLE_ENTITY_VALUE:
4499 if (dtd->keepProcessing) {
4500 enum XML_Error result = storeEntityValue(
4501 parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
4502 if (parser->m_declEntity) {
4503 parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
4504 parser->m_declEntity->textLen
4505 = (int)(poolLength(&dtd->entityValuePool));
4506 poolFinish(&dtd->entityValuePool);
4507 if (parser->m_entityDeclHandler) {
4509 parser->m_entityDeclHandler(
4510 parser->m_handlerArg, parser->m_declEntity->name,
4511 parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
4512 parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
4513 handleDefault = XML_FALSE;
4516 poolDiscard(&dtd->entityValuePool);
4517 if (result != XML_ERROR_NONE)
4521 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4523 parser->m_useForeignDTD = XML_FALSE;
4524 #endif /* XML_DTD */
4525 dtd->hasParamEntityRefs = XML_TRUE;
4526 if (parser->m_startDoctypeDeclHandler) {
4527 parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc,
4528 s + enc->minBytesPerChar,
4529 next - enc->minBytesPerChar);
4530 if (parser->m_doctypeSysid == NULL)
4531 return XML_ERROR_NO_MEMORY;
4532 poolFinish(&parser->m_tempPool);
4533 handleDefault = XML_FALSE;
4537 /* use externalSubsetName to make parser->m_doctypeSysid non-NULL
4538 for the case where no parser->m_startDoctypeDeclHandler is set */
4539 parser->m_doctypeSysid = externalSubsetName;
4540 #endif /* XML_DTD */
4541 if (! dtd->standalone
4543 && ! parser->m_paramEntityParsing
4544 #endif /* XML_DTD */
4545 && parser->m_notStandaloneHandler
4546 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
4547 return XML_ERROR_NOT_STANDALONE;
4551 if (! parser->m_declEntity) {
4552 parser->m_declEntity = (ENTITY *)lookup(
4553 parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
4554 if (! parser->m_declEntity)
4555 return XML_ERROR_NO_MEMORY;
4556 parser->m_declEntity->publicId = NULL;
4558 #endif /* XML_DTD */
4560 case XML_ROLE_ENTITY_SYSTEM_ID:
4561 if (dtd->keepProcessing && parser->m_declEntity) {
4562 parser->m_declEntity->systemId
4563 = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
4564 next - enc->minBytesPerChar);
4565 if (! parser->m_declEntity->systemId)
4566 return XML_ERROR_NO_MEMORY;
4567 parser->m_declEntity->base = parser->m_curBase;
4568 poolFinish(&dtd->pool);
4569 /* Don't suppress the default handler if we fell through from
4570 * the XML_ROLE_DOCTYPE_SYSTEM_ID case.
4572 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID)
4573 handleDefault = XML_FALSE;
4576 case XML_ROLE_ENTITY_COMPLETE:
4577 if (dtd->keepProcessing && parser->m_declEntity
4578 && parser->m_entityDeclHandler) {
4580 parser->m_entityDeclHandler(
4581 parser->m_handlerArg, parser->m_declEntity->name,
4582 parser->m_declEntity->is_param, 0, 0, parser->m_declEntity->base,
4583 parser->m_declEntity->systemId, parser->m_declEntity->publicId, 0);
4584 handleDefault = XML_FALSE;
4587 case XML_ROLE_ENTITY_NOTATION_NAME:
4588 if (dtd->keepProcessing && parser->m_declEntity) {
4589 parser->m_declEntity->notation
4590 = poolStoreString(&dtd->pool, enc, s, next);
4591 if (! parser->m_declEntity->notation)
4592 return XML_ERROR_NO_MEMORY;
4593 poolFinish(&dtd->pool);
4594 if (parser->m_unparsedEntityDeclHandler) {
4596 parser->m_unparsedEntityDeclHandler(
4597 parser->m_handlerArg, parser->m_declEntity->name,
4598 parser->m_declEntity->base, parser->m_declEntity->systemId,
4599 parser->m_declEntity->publicId, parser->m_declEntity->notation);
4600 handleDefault = XML_FALSE;
4601 } else if (parser->m_entityDeclHandler) {
4603 parser->m_entityDeclHandler(
4604 parser->m_handlerArg, parser->m_declEntity->name, 0, 0, 0,
4605 parser->m_declEntity->base, parser->m_declEntity->systemId,
4606 parser->m_declEntity->publicId, parser->m_declEntity->notation);
4607 handleDefault = XML_FALSE;
4611 case XML_ROLE_GENERAL_ENTITY_NAME: {
4612 if (XmlPredefinedEntityName(enc, s, next)) {
4613 parser->m_declEntity = NULL;
4616 if (dtd->keepProcessing) {
4617 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4619 return XML_ERROR_NO_MEMORY;
4620 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities,
4621 name, sizeof(ENTITY));
4622 if (! parser->m_declEntity)
4623 return XML_ERROR_NO_MEMORY;
4624 if (parser->m_declEntity->name != name) {
4625 poolDiscard(&dtd->pool);
4626 parser->m_declEntity = NULL;
4628 poolFinish(&dtd->pool);
4629 parser->m_declEntity->publicId = NULL;
4630 parser->m_declEntity->is_param = XML_FALSE;
4631 /* if we have a parent parser or are reading an internal parameter
4632 entity, then the entity declaration is not considered "internal"
4634 parser->m_declEntity->is_internal
4635 = ! (parser->m_parentParser || parser->m_openInternalEntities);
4636 if (parser->m_entityDeclHandler)
4637 handleDefault = XML_FALSE;
4640 poolDiscard(&dtd->pool);
4641 parser->m_declEntity = NULL;
4644 case XML_ROLE_PARAM_ENTITY_NAME:
4646 if (dtd->keepProcessing) {
4647 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4649 return XML_ERROR_NO_MEMORY;
4650 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4651 name, sizeof(ENTITY));
4652 if (! parser->m_declEntity)
4653 return XML_ERROR_NO_MEMORY;
4654 if (parser->m_declEntity->name != name) {
4655 poolDiscard(&dtd->pool);
4656 parser->m_declEntity = NULL;
4658 poolFinish(&dtd->pool);
4659 parser->m_declEntity->publicId = NULL;
4660 parser->m_declEntity->is_param = XML_TRUE;
4661 /* if we have a parent parser or are reading an internal parameter
4662 entity, then the entity declaration is not considered "internal"
4664 parser->m_declEntity->is_internal
4665 = ! (parser->m_parentParser || parser->m_openInternalEntities);
4666 if (parser->m_entityDeclHandler)
4667 handleDefault = XML_FALSE;
4670 poolDiscard(&dtd->pool);
4671 parser->m_declEntity = NULL;
4673 #else /* not XML_DTD */
4674 parser->m_declEntity = NULL;
4675 #endif /* XML_DTD */
4677 case XML_ROLE_NOTATION_NAME:
4678 parser->m_declNotationPublicId = NULL;
4679 parser->m_declNotationName = NULL;
4680 if (parser->m_notationDeclHandler) {
4681 parser->m_declNotationName
4682 = poolStoreString(&parser->m_tempPool, enc, s, next);
4683 if (! parser->m_declNotationName)
4684 return XML_ERROR_NO_MEMORY;
4685 poolFinish(&parser->m_tempPool);
4686 handleDefault = XML_FALSE;
4689 case XML_ROLE_NOTATION_PUBLIC_ID:
4690 if (! XmlIsPublicId(enc, s, next, eventPP))
4691 return XML_ERROR_PUBLICID;
4693 ->m_declNotationName) { /* means m_notationDeclHandler != NULL */
4694 XML_Char *tem = poolStoreString(&parser->m_tempPool, enc,
4695 s + enc->minBytesPerChar,
4696 next - enc->minBytesPerChar);
4698 return XML_ERROR_NO_MEMORY;
4699 normalizePublicId(tem);
4700 parser->m_declNotationPublicId = tem;
4701 poolFinish(&parser->m_tempPool);
4702 handleDefault = XML_FALSE;
4705 case XML_ROLE_NOTATION_SYSTEM_ID:
4706 if (parser->m_declNotationName && parser->m_notationDeclHandler) {
4707 const XML_Char *systemId = poolStoreString(&parser->m_tempPool, enc,
4708 s + enc->minBytesPerChar,
4709 next - enc->minBytesPerChar);
4711 return XML_ERROR_NO_MEMORY;
4713 parser->m_notationDeclHandler(
4714 parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
4715 systemId, parser->m_declNotationPublicId);
4716 handleDefault = XML_FALSE;
4718 poolClear(&parser->m_tempPool);
4720 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4721 if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) {
4723 parser->m_notationDeclHandler(
4724 parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
4725 0, parser->m_declNotationPublicId);
4726 handleDefault = XML_FALSE;
4728 poolClear(&parser->m_tempPool);
4730 case XML_ROLE_ERROR:
4732 case XML_TOK_PARAM_ENTITY_REF:
4733 /* PE references in internal subset are
4734 not allowed within declarations. */
4735 return XML_ERROR_PARAM_ENTITY_REF;
4736 case XML_TOK_XML_DECL:
4737 return XML_ERROR_MISPLACED_XML_PI;
4739 return XML_ERROR_SYNTAX;
4742 case XML_ROLE_IGNORE_SECT: {
4743 enum XML_Error result;
4744 if (parser->m_defaultHandler)
4745 reportDefault(parser, enc, s, next);
4746 handleDefault = XML_FALSE;
4747 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4748 if (result != XML_ERROR_NONE)
4751 parser->m_processor = ignoreSectionProcessor;
4755 #endif /* XML_DTD */
4756 case XML_ROLE_GROUP_OPEN:
4757 if (parser->m_prologState.level >= parser->m_groupSize) {
4758 if (parser->m_groupSize) {
4760 char *const new_connector = (char *)REALLOC(
4761 parser, parser->m_groupConnector, parser->m_groupSize *= 2);
4762 if (new_connector == NULL) {
4763 parser->m_groupSize /= 2;
4764 return XML_ERROR_NO_MEMORY;
4766 parser->m_groupConnector = new_connector;
4769 if (dtd->scaffIndex) {
4770 int *const new_scaff_index = (int *)REALLOC(
4771 parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
4772 if (new_scaff_index == NULL)
4773 return XML_ERROR_NO_MEMORY;
4774 dtd->scaffIndex = new_scaff_index;
4777 parser->m_groupConnector
4778 = (char *)MALLOC(parser, parser->m_groupSize = 32);
4779 if (! parser->m_groupConnector) {
4780 parser->m_groupSize = 0;
4781 return XML_ERROR_NO_MEMORY;
4785 parser->m_groupConnector[parser->m_prologState.level] = 0;
4786 if (dtd->in_eldecl) {
4787 int myindex = nextScaffoldPart(parser);
4789 return XML_ERROR_NO_MEMORY;
4790 assert(dtd->scaffIndex != NULL);
4791 dtd->scaffIndex[dtd->scaffLevel] = myindex;
4793 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
4794 if (parser->m_elementDeclHandler)
4795 handleDefault = XML_FALSE;
4798 case XML_ROLE_GROUP_SEQUENCE:
4799 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE)
4800 return XML_ERROR_SYNTAX;
4801 parser->m_groupConnector[parser->m_prologState.level] = ASCII_COMMA;
4802 if (dtd->in_eldecl && parser->m_elementDeclHandler)
4803 handleDefault = XML_FALSE;
4805 case XML_ROLE_GROUP_CHOICE:
4806 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
4807 return XML_ERROR_SYNTAX;
4809 && ! parser->m_groupConnector[parser->m_prologState.level]
4810 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4811 != XML_CTYPE_MIXED)) {
4812 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4814 if (parser->m_elementDeclHandler)
4815 handleDefault = XML_FALSE;
4817 parser->m_groupConnector[parser->m_prologState.level] = ASCII_PIPE;
4819 case XML_ROLE_PARAM_ENTITY_REF:
4821 case XML_ROLE_INNER_PARAM_ENTITY_REF:
4822 dtd->hasParamEntityRefs = XML_TRUE;
4823 if (! parser->m_paramEntityParsing)
4824 dtd->keepProcessing = dtd->standalone;
4826 const XML_Char *name;
4828 name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
4829 next - enc->minBytesPerChar);
4831 return XML_ERROR_NO_MEMORY;
4832 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
4833 poolDiscard(&dtd->pool);
4834 /* first, determine if a check for an existing declaration is needed;
4835 if yes, check that the entity exists, and that it is internal,
4836 otherwise call the skipped entity handler
4838 if (parser->m_prologState.documentEntity
4839 && (dtd->standalone ? ! parser->m_openInternalEntities
4840 : ! dtd->hasParamEntityRefs)) {
4842 return XML_ERROR_UNDEFINED_ENTITY;
4843 else if (! entity->is_internal) {
4844 /* It's hard to exhaustively search the code to be sure,
4845 * but there doesn't seem to be a way of executing the
4846 * following line. There are two cases:
4848 * If 'standalone' is false, the DTD must have no
4849 * parameter entities or we wouldn't have passed the outer
4850 * 'if' statement. That measn the only entity in the hash
4851 * table is the external subset name "#" which cannot be
4852 * given as a parameter entity name in XML syntax, so the
4853 * lookup must have returned NULL and we don't even reach
4854 * the test for an internal entity.
4856 * If 'standalone' is true, it does not seem to be
4857 * possible to create entities taking this code path that
4858 * are not internal entities, so fail the test above.
4860 * Because this analysis is very uncertain, the code is
4861 * being left in place and merely removed from the
4862 * coverage test statistics.
4864 return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
4866 } else if (! entity) {
4867 dtd->keepProcessing = dtd->standalone;
4868 /* cannot report skipped entities in declarations */
4869 if ((role == XML_ROLE_PARAM_ENTITY_REF)
4870 && parser->m_skippedEntityHandler) {
4871 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1);
4872 handleDefault = XML_FALSE;
4877 return XML_ERROR_RECURSIVE_ENTITY_REF;
4878 if (entity->textPtr) {
4879 enum XML_Error result;
4880 XML_Bool betweenDecl
4881 = (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
4882 result = processInternalEntity(parser, entity, betweenDecl);
4883 if (result != XML_ERROR_NONE)
4885 handleDefault = XML_FALSE;
4888 if (parser->m_externalEntityRefHandler) {
4889 dtd->paramEntityRead = XML_FALSE;
4890 entity->open = XML_TRUE;
4891 if (! parser->m_externalEntityRefHandler(
4892 parser->m_externalEntityRefHandlerArg, 0, entity->base,
4893 entity->systemId, entity->publicId)) {
4894 entity->open = XML_FALSE;
4895 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4897 entity->open = XML_FALSE;
4898 handleDefault = XML_FALSE;
4899 if (! dtd->paramEntityRead) {
4900 dtd->keepProcessing = dtd->standalone;
4904 dtd->keepProcessing = dtd->standalone;
4908 #endif /* XML_DTD */
4909 if (! dtd->standalone && parser->m_notStandaloneHandler
4910 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
4911 return XML_ERROR_NOT_STANDALONE;
4914 /* Element declaration stuff */
4916 case XML_ROLE_ELEMENT_NAME:
4917 if (parser->m_elementDeclHandler) {
4918 parser->m_declElementType = getElementType(parser, enc, s, next);
4919 if (! parser->m_declElementType)
4920 return XML_ERROR_NO_MEMORY;
4921 dtd->scaffLevel = 0;
4922 dtd->scaffCount = 0;
4923 dtd->in_eldecl = XML_TRUE;
4924 handleDefault = XML_FALSE;
4928 case XML_ROLE_CONTENT_ANY:
4929 case XML_ROLE_CONTENT_EMPTY:
4930 if (dtd->in_eldecl) {
4931 if (parser->m_elementDeclHandler) {
4932 XML_Content *content
4933 = (XML_Content *)MALLOC(parser, sizeof(XML_Content));
4935 return XML_ERROR_NO_MEMORY;
4936 content->quant = XML_CQUANT_NONE;
4937 content->name = NULL;
4938 content->numchildren = 0;
4939 content->children = NULL;
4940 content->type = ((role == XML_ROLE_CONTENT_ANY) ? XML_CTYPE_ANY
4943 parser->m_elementDeclHandler(
4944 parser->m_handlerArg, parser->m_declElementType->name, content);
4945 handleDefault = XML_FALSE;
4947 dtd->in_eldecl = XML_FALSE;
4951 case XML_ROLE_CONTENT_PCDATA:
4952 if (dtd->in_eldecl) {
4953 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
4955 if (parser->m_elementDeclHandler)
4956 handleDefault = XML_FALSE;
4960 case XML_ROLE_CONTENT_ELEMENT:
4961 quant = XML_CQUANT_NONE;
4962 goto elementContent;
4963 case XML_ROLE_CONTENT_ELEMENT_OPT:
4964 quant = XML_CQUANT_OPT;
4965 goto elementContent;
4966 case XML_ROLE_CONTENT_ELEMENT_REP:
4967 quant = XML_CQUANT_REP;
4968 goto elementContent;
4969 case XML_ROLE_CONTENT_ELEMENT_PLUS:
4970 quant = XML_CQUANT_PLUS;
4972 if (dtd->in_eldecl) {
4974 const XML_Char *name;
4977 = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
4978 int myindex = nextScaffoldPart(parser);
4980 return XML_ERROR_NO_MEMORY;
4981 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
4982 dtd->scaffold[myindex].quant = quant;
4983 el = getElementType(parser, enc, s, nxt);
4985 return XML_ERROR_NO_MEMORY;
4987 dtd->scaffold[myindex].name = name;
4989 for (; name[nameLen++];)
4991 dtd->contentStringLen += nameLen;
4992 if (parser->m_elementDeclHandler)
4993 handleDefault = XML_FALSE;
4997 case XML_ROLE_GROUP_CLOSE:
4998 quant = XML_CQUANT_NONE;
5000 case XML_ROLE_GROUP_CLOSE_OPT:
5001 quant = XML_CQUANT_OPT;
5003 case XML_ROLE_GROUP_CLOSE_REP:
5004 quant = XML_CQUANT_REP;
5006 case XML_ROLE_GROUP_CLOSE_PLUS:
5007 quant = XML_CQUANT_PLUS;
5009 if (dtd->in_eldecl) {
5010 if (parser->m_elementDeclHandler)
5011 handleDefault = XML_FALSE;
5013 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
5014 if (dtd->scaffLevel == 0) {
5015 if (! handleDefault) {
5016 XML_Content *model = build_model(parser);
5018 return XML_ERROR_NO_MEMORY;
5020 parser->m_elementDeclHandler(
5021 parser->m_handlerArg, parser->m_declElementType->name, model);
5023 dtd->in_eldecl = XML_FALSE;
5024 dtd->contentStringLen = 0;
5028 /* End element declaration stuff */
5031 if (! reportProcessingInstruction(parser, enc, s, next))
5032 return XML_ERROR_NO_MEMORY;
5033 handleDefault = XML_FALSE;
5035 case XML_ROLE_COMMENT:
5036 if (! reportComment(parser, enc, s, next))
5037 return XML_ERROR_NO_MEMORY;
5038 handleDefault = XML_FALSE;
5043 handleDefault = XML_FALSE;
5047 case XML_ROLE_DOCTYPE_NONE:
5048 if (parser->m_startDoctypeDeclHandler)
5049 handleDefault = XML_FALSE;
5051 case XML_ROLE_ENTITY_NONE:
5052 if (dtd->keepProcessing && parser->m_entityDeclHandler)
5053 handleDefault = XML_FALSE;
5055 case XML_ROLE_NOTATION_NONE:
5056 if (parser->m_notationDeclHandler)
5057 handleDefault = XML_FALSE;
5059 case XML_ROLE_ATTLIST_NONE:
5060 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
5061 handleDefault = XML_FALSE;
5063 case XML_ROLE_ELEMENT_NONE:
5064 if (parser->m_elementDeclHandler)
5065 handleDefault = XML_FALSE;
5067 } /* end of big switch */
5069 if (handleDefault && parser->m_defaultHandler)
5070 reportDefault(parser, enc, s, next);
5072 switch (parser->m_parsingStatus.parsing) {
5075 return XML_ERROR_NONE;
5077 return XML_ERROR_ABORTED;
5080 tok = XmlPrologTok(enc, s, end, &next);
5086 static enum XML_Error PTRCALL
5087 epilogProcessor(XML_Parser parser, const char *s, const char *end,
5088 const char **nextPtr) {
5089 parser->m_processor = epilogProcessor;
5090 parser->m_eventPtr = s;
5092 const char *next = NULL;
5093 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5094 parser->m_eventEndPtr = next;
5096 /* report partial linebreak - it might be the last token */
5097 case -XML_TOK_PROLOG_S:
5098 if (parser->m_defaultHandler) {
5099 reportDefault(parser, parser->m_encoding, s, next);
5100 if (parser->m_parsingStatus.parsing == XML_FINISHED)
5101 return XML_ERROR_ABORTED;
5104 return XML_ERROR_NONE;
5107 return XML_ERROR_NONE;
5108 case XML_TOK_PROLOG_S:
5109 if (parser->m_defaultHandler)
5110 reportDefault(parser, parser->m_encoding, s, next);
5113 if (! reportProcessingInstruction(parser, parser->m_encoding, s, next))
5114 return XML_ERROR_NO_MEMORY;
5116 case XML_TOK_COMMENT:
5117 if (! reportComment(parser, parser->m_encoding, s, next))
5118 return XML_ERROR_NO_MEMORY;
5120 case XML_TOK_INVALID:
5121 parser->m_eventPtr = next;
5122 return XML_ERROR_INVALID_TOKEN;
5123 case XML_TOK_PARTIAL:
5124 if (! parser->m_parsingStatus.finalBuffer) {
5126 return XML_ERROR_NONE;
5128 return XML_ERROR_UNCLOSED_TOKEN;
5129 case XML_TOK_PARTIAL_CHAR:
5130 if (! parser->m_parsingStatus.finalBuffer) {
5132 return XML_ERROR_NONE;
5134 return XML_ERROR_PARTIAL_CHAR;
5136 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
5138 parser->m_eventPtr = s = next;
5139 switch (parser->m_parsingStatus.parsing) {
5142 return XML_ERROR_NONE;
5144 return XML_ERROR_ABORTED;
5150 static enum XML_Error
5151 processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
5152 const char *textStart, *textEnd;
5154 enum XML_Error result;
5155 OPEN_INTERNAL_ENTITY *openEntity;
5157 if (parser->m_freeInternalEntities) {
5158 openEntity = parser->m_freeInternalEntities;
5159 parser->m_freeInternalEntities = openEntity->next;
5162 = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
5164 return XML_ERROR_NO_MEMORY;
5166 entity->open = XML_TRUE;
5167 entity->processed = 0;
5168 openEntity->next = parser->m_openInternalEntities;
5169 parser->m_openInternalEntities = openEntity;
5170 openEntity->entity = entity;
5171 openEntity->startTagLevel = parser->m_tagLevel;
5172 openEntity->betweenDecl = betweenDecl;
5173 openEntity->internalEventPtr = NULL;
5174 openEntity->internalEventEndPtr = NULL;
5175 textStart = (char *)entity->textPtr;
5176 textEnd = (char *)(entity->textPtr + entity->textLen);
5177 /* Set a safe default value in case 'next' does not get set */
5181 if (entity->is_param) {
5183 = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5184 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
5185 tok, next, &next, XML_FALSE, XML_FALSE);
5187 #endif /* XML_DTD */
5188 result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
5189 textStart, textEnd, &next, XML_FALSE);
5191 if (result == XML_ERROR_NONE) {
5192 if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
5193 entity->processed = (int)(next - textStart);
5194 parser->m_processor = internalEntityProcessor;
5196 entity->open = XML_FALSE;
5197 parser->m_openInternalEntities = openEntity->next;
5198 /* put openEntity back in list of free instances */
5199 openEntity->next = parser->m_freeInternalEntities;
5200 parser->m_freeInternalEntities = openEntity;
5206 static enum XML_Error PTRCALL
5207 internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
5208 const char **nextPtr) {
5210 const char *textStart, *textEnd;
5212 enum XML_Error result;
5213 OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
5215 return XML_ERROR_UNEXPECTED_STATE;
5217 entity = openEntity->entity;
5218 textStart = ((char *)entity->textPtr) + entity->processed;
5219 textEnd = (char *)(entity->textPtr + entity->textLen);
5220 /* Set a safe default value in case 'next' does not get set */
5224 if (entity->is_param) {
5226 = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5227 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
5228 tok, next, &next, XML_FALSE, XML_TRUE);
5230 #endif /* XML_DTD */
5231 result = doContent(parser, openEntity->startTagLevel,
5232 parser->m_internalEncoding, textStart, textEnd, &next,
5235 if (result != XML_ERROR_NONE)
5237 else if (textEnd != next
5238 && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
5239 entity->processed = (int)(next - (char *)entity->textPtr);
5242 entity->open = XML_FALSE;
5243 parser->m_openInternalEntities = openEntity->next;
5244 /* put openEntity back in list of free instances */
5245 openEntity->next = parser->m_freeInternalEntities;
5246 parser->m_freeInternalEntities = openEntity;
5250 if (entity->is_param) {
5252 parser->m_processor = prologProcessor;
5253 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5254 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
5255 (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
5257 #endif /* XML_DTD */
5259 parser->m_processor = contentProcessor;
5260 /* see externalEntityContentProcessor vs contentProcessor */
5261 return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
5263 (XML_Bool)! parser->m_parsingStatus.finalBuffer);
5267 static enum XML_Error PTRCALL
5268 errorProcessor(XML_Parser parser, const char *s, const char *end,
5269 const char **nextPtr) {
5273 return parser->m_errorCode;
5276 static enum XML_Error
5277 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5278 const char *ptr, const char *end, STRING_POOL *pool) {
5279 enum XML_Error result
5280 = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
5283 if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
5285 if (! poolAppendChar(pool, XML_T('\0')))
5286 return XML_ERROR_NO_MEMORY;
5287 return XML_ERROR_NONE;
5290 static enum XML_Error
5291 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5292 const char *ptr, const char *end, STRING_POOL *pool) {
5293 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5296 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
5299 return XML_ERROR_NONE;
5300 case XML_TOK_INVALID:
5301 if (enc == parser->m_encoding)
5302 parser->m_eventPtr = next;
5303 return XML_ERROR_INVALID_TOKEN;
5304 case XML_TOK_PARTIAL:
5305 if (enc == parser->m_encoding)
5306 parser->m_eventPtr = ptr;
5307 return XML_ERROR_INVALID_TOKEN;
5308 case XML_TOK_CHAR_REF: {
5309 XML_Char buf[XML_ENCODE_MAX];
5311 int n = XmlCharRefNumber(enc, ptr);
5313 if (enc == parser->m_encoding)
5314 parser->m_eventPtr = ptr;
5315 return XML_ERROR_BAD_CHAR_REF;
5317 if (! isCdata && n == 0x20 /* space */
5318 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5320 n = XmlEncode(n, (ICHAR *)buf);
5321 /* The XmlEncode() functions can never return 0 here. That
5322 * error return happens if the code point passed in is either
5323 * negative or greater than or equal to 0x110000. The
5324 * XmlCharRefNumber() functions will all return a number
5325 * strictly less than 0x110000 or a negative value if an error
5326 * occurred. The negative value is intercepted above, so
5327 * XmlEncode() is never passed a value it might return an
5330 for (i = 0; i < n; i++) {
5331 if (! poolAppendChar(pool, buf[i]))
5332 return XML_ERROR_NO_MEMORY;
5335 case XML_TOK_DATA_CHARS:
5336 if (! poolAppend(pool, enc, ptr, next))
5337 return XML_ERROR_NO_MEMORY;
5339 case XML_TOK_TRAILING_CR:
5340 next = ptr + enc->minBytesPerChar;
5342 case XML_TOK_ATTRIBUTE_VALUE_S:
5343 case XML_TOK_DATA_NEWLINE:
5344 if (! isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5346 if (! poolAppendChar(pool, 0x20))
5347 return XML_ERROR_NO_MEMORY;
5349 case XML_TOK_ENTITY_REF: {
5350 const XML_Char *name;
5352 char checkEntityDecl;
5353 XML_Char ch = (XML_Char)XmlPredefinedEntityName(
5354 enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
5356 if (! poolAppendChar(pool, ch))
5357 return XML_ERROR_NO_MEMORY;
5360 name = poolStoreString(&parser->m_temp2Pool, enc,
5361 ptr + enc->minBytesPerChar,
5362 next - enc->minBytesPerChar);
5364 return XML_ERROR_NO_MEMORY;
5365 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
5366 poolDiscard(&parser->m_temp2Pool);
5367 /* First, determine if a check for an existing declaration is needed;
5368 if yes, check that the entity exists, and that it is internal.
5370 if (pool == &dtd->pool) /* are we called from prolog? */
5373 parser->m_prologState.documentEntity &&
5374 #endif /* XML_DTD */
5375 (dtd->standalone ? ! parser->m_openInternalEntities
5376 : ! dtd->hasParamEntityRefs);
5377 else /* if (pool == &parser->m_tempPool): we are called from content */
5378 checkEntityDecl = ! dtd->hasParamEntityRefs || dtd->standalone;
5379 if (checkEntityDecl) {
5381 return XML_ERROR_UNDEFINED_ENTITY;
5382 else if (! entity->is_internal)
5383 return XML_ERROR_ENTITY_DECLARED_IN_PE;
5384 } else if (! entity) {
5385 /* Cannot report skipped entity here - see comments on
5386 parser->m_skippedEntityHandler.
5387 if (parser->m_skippedEntityHandler)
5388 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
5390 /* Cannot call the default handler because this would be
5391 out of sync with the call to the startElementHandler.
5392 if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
5393 reportDefault(parser, enc, ptr, next);
5398 if (enc == parser->m_encoding) {
5399 /* It does not appear that this line can be executed.
5401 * The "if (entity->open)" check catches recursive entity
5402 * definitions. In order to be called with an open
5403 * entity, it must have gone through this code before and
5404 * been through the recursive call to
5405 * appendAttributeValue() some lines below. That call
5406 * sets the local encoding ("enc") to the parser's
5407 * internal encoding (internal_utf8 or internal_utf16),
5408 * which can never be the same as the principle encoding.
5409 * It doesn't appear there is another code path that gets
5410 * here with entity->open being TRUE.
5412 * Since it is not certain that this logic is watertight,
5413 * we keep the line and merely exclude it from coverage
5416 parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
5418 return XML_ERROR_RECURSIVE_ENTITY_REF;
5420 if (entity->notation) {
5421 if (enc == parser->m_encoding)
5422 parser->m_eventPtr = ptr;
5423 return XML_ERROR_BINARY_ENTITY_REF;
5425 if (! entity->textPtr) {
5426 if (enc == parser->m_encoding)
5427 parser->m_eventPtr = ptr;
5428 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
5430 enum XML_Error result;
5431 const XML_Char *textEnd = entity->textPtr + entity->textLen;
5432 entity->open = XML_TRUE;
5433 result = appendAttributeValue(parser, parser->m_internalEncoding,
5434 isCdata, (char *)entity->textPtr,
5435 (char *)textEnd, pool);
5436 entity->open = XML_FALSE;
5442 /* The only token returned by XmlAttributeValueTok() that does
5443 * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
5444 * Getting that would require an entity name to contain an
5445 * incomplete XML character (e.g. \xE2\x82); however previous
5446 * tokenisers will have already recognised and rejected such
5447 * names before XmlAttributeValueTok() gets a look-in. This
5448 * default case should be retained as a safety net, but the code
5449 * excluded from coverage tests.
5453 if (enc == parser->m_encoding)
5454 parser->m_eventPtr = ptr;
5455 return XML_ERROR_UNEXPECTED_STATE;
5456 /* LCOV_EXCL_STOP */
5463 static enum XML_Error
5464 storeEntityValue(XML_Parser parser, const ENCODING *enc,
5465 const char *entityTextPtr, const char *entityTextEnd) {
5466 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5467 STRING_POOL *pool = &(dtd->entityValuePool);
5468 enum XML_Error result = XML_ERROR_NONE;
5470 int oldInEntityValue = parser->m_prologState.inEntityValue;
5471 parser->m_prologState.inEntityValue = 1;
5472 #endif /* XML_DTD */
5473 /* never return Null for the value argument in EntityDeclHandler,
5474 since this would indicate an external entity; therefore we
5475 have to make sure that entityValuePool.start is not null */
5476 if (! pool->blocks) {
5477 if (! poolGrow(pool))
5478 return XML_ERROR_NO_MEMORY;
5483 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5485 case XML_TOK_PARAM_ENTITY_REF:
5487 if (parser->m_isParamEntity || enc != parser->m_encoding) {
5488 const XML_Char *name;
5490 name = poolStoreString(&parser->m_tempPool, enc,
5491 entityTextPtr + enc->minBytesPerChar,
5492 next - enc->minBytesPerChar);
5494 result = XML_ERROR_NO_MEMORY;
5495 goto endEntityValue;
5497 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5498 poolDiscard(&parser->m_tempPool);
5500 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5501 /* cannot report skipped entity here - see comments on
5502 parser->m_skippedEntityHandler
5503 if (parser->m_skippedEntityHandler)
5504 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
5506 dtd->keepProcessing = dtd->standalone;
5507 goto endEntityValue;
5510 if (enc == parser->m_encoding)
5511 parser->m_eventPtr = entityTextPtr;
5512 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5513 goto endEntityValue;
5515 if (entity->systemId) {
5516 if (parser->m_externalEntityRefHandler) {
5517 dtd->paramEntityRead = XML_FALSE;
5518 entity->open = XML_TRUE;
5519 if (! parser->m_externalEntityRefHandler(
5520 parser->m_externalEntityRefHandlerArg, 0, entity->base,
5521 entity->systemId, entity->publicId)) {
5522 entity->open = XML_FALSE;
5523 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5524 goto endEntityValue;
5526 entity->open = XML_FALSE;
5527 if (! dtd->paramEntityRead)
5528 dtd->keepProcessing = dtd->standalone;
5530 dtd->keepProcessing = dtd->standalone;
5532 entity->open = XML_TRUE;
5533 result = storeEntityValue(
5534 parser, parser->m_internalEncoding, (char *)entity->textPtr,
5535 (char *)(entity->textPtr + entity->textLen));
5536 entity->open = XML_FALSE;
5538 goto endEntityValue;
5542 #endif /* XML_DTD */
5543 /* In the internal subset, PE references are not legal
5544 within markup declarations, e.g entity values in this case. */
5545 parser->m_eventPtr = entityTextPtr;
5546 result = XML_ERROR_PARAM_ENTITY_REF;
5547 goto endEntityValue;
5549 result = XML_ERROR_NONE;
5550 goto endEntityValue;
5551 case XML_TOK_ENTITY_REF:
5552 case XML_TOK_DATA_CHARS:
5553 if (! poolAppend(pool, enc, entityTextPtr, next)) {
5554 result = XML_ERROR_NO_MEMORY;
5555 goto endEntityValue;
5558 case XML_TOK_TRAILING_CR:
5559 next = entityTextPtr + enc->minBytesPerChar;
5561 case XML_TOK_DATA_NEWLINE:
5562 if (pool->end == pool->ptr && ! poolGrow(pool)) {
5563 result = XML_ERROR_NO_MEMORY;
5564 goto endEntityValue;
5566 *(pool->ptr)++ = 0xA;
5568 case XML_TOK_CHAR_REF: {
5569 XML_Char buf[XML_ENCODE_MAX];
5571 int n = XmlCharRefNumber(enc, entityTextPtr);
5573 if (enc == parser->m_encoding)
5574 parser->m_eventPtr = entityTextPtr;
5575 result = XML_ERROR_BAD_CHAR_REF;
5576 goto endEntityValue;
5578 n = XmlEncode(n, (ICHAR *)buf);
5579 /* The XmlEncode() functions can never return 0 here. That
5580 * error return happens if the code point passed in is either
5581 * negative or greater than or equal to 0x110000. The
5582 * XmlCharRefNumber() functions will all return a number
5583 * strictly less than 0x110000 or a negative value if an error
5584 * occurred. The negative value is intercepted above, so
5585 * XmlEncode() is never passed a value it might return an
5588 for (i = 0; i < n; i++) {
5589 if (pool->end == pool->ptr && ! poolGrow(pool)) {
5590 result = XML_ERROR_NO_MEMORY;
5591 goto endEntityValue;
5593 *(pool->ptr)++ = buf[i];
5596 case XML_TOK_PARTIAL:
5597 if (enc == parser->m_encoding)
5598 parser->m_eventPtr = entityTextPtr;
5599 result = XML_ERROR_INVALID_TOKEN;
5600 goto endEntityValue;
5601 case XML_TOK_INVALID:
5602 if (enc == parser->m_encoding)
5603 parser->m_eventPtr = next;
5604 result = XML_ERROR_INVALID_TOKEN;
5605 goto endEntityValue;
5607 /* This default case should be unnecessary -- all the tokens
5608 * that XmlEntityValueTok() can return have their own explicit
5609 * cases -- but should be retained for safety. We do however
5610 * exclude it from the coverage statistics.
5614 if (enc == parser->m_encoding)
5615 parser->m_eventPtr = entityTextPtr;
5616 result = XML_ERROR_UNEXPECTED_STATE;
5617 goto endEntityValue;
5618 /* LCOV_EXCL_STOP */
5620 entityTextPtr = next;
5624 parser->m_prologState.inEntityValue = oldInEntityValue;
5625 #endif /* XML_DTD */
5629 static void FASTCALL
5630 normalizeLines(XML_Char *s) {
5633 if (*s == XML_T('\0'))
5651 reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5652 const char *start, const char *end) {
5653 const XML_Char *target;
5656 if (! parser->m_processingInstructionHandler) {
5657 if (parser->m_defaultHandler)
5658 reportDefault(parser, enc, start, end);
5661 start += enc->minBytesPerChar * 2;
5662 tem = start + XmlNameLength(enc, start);
5663 target = poolStoreString(&parser->m_tempPool, enc, start, tem);
5666 poolFinish(&parser->m_tempPool);
5667 data = poolStoreString(&parser->m_tempPool, enc, XmlSkipS(enc, tem),
5668 end - enc->minBytesPerChar * 2);
5671 normalizeLines(data);
5672 parser->m_processingInstructionHandler(parser->m_handlerArg, target, data);
5673 poolClear(&parser->m_tempPool);
5678 reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
5681 if (! parser->m_commentHandler) {
5682 if (parser->m_defaultHandler)
5683 reportDefault(parser, enc, start, end);
5686 data = poolStoreString(&parser->m_tempPool, enc,
5687 start + enc->minBytesPerChar * 4,
5688 end - enc->minBytesPerChar * 3);
5691 normalizeLines(data);
5692 parser->m_commentHandler(parser->m_handlerArg, data);
5693 poolClear(&parser->m_tempPool);
5698 reportDefault(XML_Parser parser, const ENCODING *enc, const char *s,
5700 if (MUST_CONVERT(enc, s)) {
5701 enum XML_Convert_Result convert_res;
5702 const char **eventPP;
5703 const char **eventEndPP;
5704 if (enc == parser->m_encoding) {
5705 eventPP = &parser->m_eventPtr;
5706 eventEndPP = &parser->m_eventEndPtr;
5708 /* To get here, two things must be true; the parser must be
5709 * using a character encoding that is not the same as the
5710 * encoding passed in, and the encoding passed in must need
5711 * conversion to the internal format (UTF-8 unless XML_UNICODE
5712 * is defined). The only occasions on which the encoding passed
5713 * in is not the same as the parser's encoding are when it is
5714 * the internal encoding (e.g. a previously defined parameter
5715 * entity, already converted to internal format). This by
5716 * definition doesn't need conversion, so the whole branch never
5719 * For safety's sake we don't delete these lines and merely
5720 * exclude them from coverage statistics.
5724 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
5725 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
5726 /* LCOV_EXCL_STOP */
5729 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
5731 = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
5733 parser->m_defaultHandler(parser->m_handlerArg, parser->m_dataBuf,
5734 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
5736 } while ((convert_res != XML_CONVERT_COMPLETED)
5737 && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
5739 parser->m_defaultHandler(parser->m_handlerArg, (XML_Char *)s,
5740 (int)((XML_Char *)end - (XML_Char *)s));
5744 defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
5745 XML_Bool isId, const XML_Char *value, XML_Parser parser) {
5746 DEFAULT_ATTRIBUTE *att;
5747 if (value || isId) {
5748 /* The handling of default attributes gets messed up if we have
5749 a default which duplicates a non-default. */
5751 for (i = 0; i < type->nDefaultAtts; i++)
5752 if (attId == type->defaultAtts[i].id)
5754 if (isId && ! type->idAtt && ! attId->xmlns)
5755 type->idAtt = attId;
5757 if (type->nDefaultAtts == type->allocDefaultAtts) {
5758 if (type->allocDefaultAtts == 0) {
5759 type->allocDefaultAtts = 8;
5760 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(
5761 parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
5762 if (! type->defaultAtts) {
5763 type->allocDefaultAtts = 0;
5767 DEFAULT_ATTRIBUTE *temp;
5768 int count = type->allocDefaultAtts * 2;
5769 temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
5770 (count * sizeof(DEFAULT_ATTRIBUTE)));
5773 type->allocDefaultAtts = count;
5774 type->defaultAtts = temp;
5777 att = type->defaultAtts + type->nDefaultAtts;
5780 att->isCdata = isCdata;
5782 attId->maybeTokenized = XML_TRUE;
5783 type->nDefaultAtts += 1;
5788 setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) {
5789 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5790 const XML_Char *name;
5791 for (name = elementType->name; *name; name++) {
5792 if (*name == XML_T(ASCII_COLON)) {
5795 for (s = elementType->name; s != name; s++) {
5796 if (! poolAppendChar(&dtd->pool, *s))
5799 if (! poolAppendChar(&dtd->pool, XML_T('\0')))
5801 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
5805 if (prefix->name == poolStart(&dtd->pool))
5806 poolFinish(&dtd->pool);
5808 poolDiscard(&dtd->pool);
5809 elementType->prefix = prefix;
5816 static ATTRIBUTE_ID *
5817 getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
5819 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5821 const XML_Char *name;
5822 if (! poolAppendChar(&dtd->pool, XML_T('\0')))
5824 name = poolStoreString(&dtd->pool, enc, start, end);
5827 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
5829 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name,
5830 sizeof(ATTRIBUTE_ID));
5833 if (id->name != name)
5834 poolDiscard(&dtd->pool);
5836 poolFinish(&dtd->pool);
5839 else if (name[0] == XML_T(ASCII_x) && name[1] == XML_T(ASCII_m)
5840 && name[2] == XML_T(ASCII_l) && name[3] == XML_T(ASCII_n)
5841 && name[4] == XML_T(ASCII_s)
5842 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
5843 if (name[5] == XML_T('\0'))
5844 id->prefix = &dtd->defaultPrefix;
5846 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6,
5848 id->xmlns = XML_TRUE;
5851 for (i = 0; name[i]; i++) {
5852 /* attributes without prefix are *not* in the default namespace */
5853 if (name[i] == XML_T(ASCII_COLON)) {
5855 for (j = 0; j < i; j++) {
5856 if (! poolAppendChar(&dtd->pool, name[j]))
5859 if (! poolAppendChar(&dtd->pool, XML_T('\0')))
5861 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes,
5862 poolStart(&dtd->pool), sizeof(PREFIX));
5865 if (id->prefix->name == poolStart(&dtd->pool))
5866 poolFinish(&dtd->pool);
5868 poolDiscard(&dtd->pool);
5877 #define CONTEXT_SEP XML_T(ASCII_FF)
5879 static const XML_Char *
5880 getContext(XML_Parser parser) {
5881 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5882 HASH_TABLE_ITER iter;
5883 XML_Bool needSep = XML_FALSE;
5885 if (dtd->defaultPrefix.binding) {
5888 if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
5890 len = dtd->defaultPrefix.binding->uriLen;
5891 if (parser->m_namespaceSeparator)
5893 for (i = 0; i < len; i++) {
5894 if (! poolAppendChar(&parser->m_tempPool,
5895 dtd->defaultPrefix.binding->uri[i])) {
5896 /* Because of memory caching, I don't believe this line can be
5899 * This is part of a loop copying the default prefix binding
5900 * URI into the parser's temporary string pool. Previously,
5901 * that URI was copied into the same string pool, with a
5902 * terminating NUL character, as part of setContext(). When
5903 * the pool was cleared, that leaves a block definitely big
5904 * enough to hold the URI on the free block list of the pool.
5905 * The URI copy in getContext() therefore cannot run out of
5908 * If the pool is used between the setContext() and
5909 * getContext() calls, the worst it can do is leave a bigger
5910 * block on the front of the free list. Given that this is
5911 * all somewhat inobvious and program logic can be changed, we
5912 * don't delete the line but we do exclude it from the test
5913 * coverage statistics.
5915 return NULL; /* LCOV_EXCL_LINE */
5921 hashTableIterInit(&iter, &(dtd->prefixes));
5926 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
5929 if (! prefix->binding) {
5930 /* This test appears to be (justifiable) paranoia. There does
5931 * not seem to be a way of injecting a prefix without a binding
5932 * that doesn't get errored long before this function is called.
5933 * The test should remain for safety's sake, so we instead
5934 * exclude the following line from the coverage statistics.
5936 continue; /* LCOV_EXCL_LINE */
5938 if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
5940 for (s = prefix->name; *s; s++)
5941 if (! poolAppendChar(&parser->m_tempPool, *s))
5943 if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
5945 len = prefix->binding->uriLen;
5946 if (parser->m_namespaceSeparator)
5948 for (i = 0; i < len; i++)
5949 if (! poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i]))
5954 hashTableIterInit(&iter, &(dtd->generalEntities));
5957 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
5962 if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
5964 for (s = e->name; *s; s++)
5965 if (! poolAppendChar(&parser->m_tempPool, *s))
5970 if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
5972 return parser->m_tempPool.start;
5976 setContext(XML_Parser parser, const XML_Char *context) {
5977 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5978 const XML_Char *s = context;
5980 while (*context != XML_T('\0')) {
5981 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
5983 if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
5985 e = (ENTITY *)lookup(parser, &dtd->generalEntities,
5986 poolStart(&parser->m_tempPool), 0);
5989 if (*s != XML_T('\0'))
5992 poolDiscard(&parser->m_tempPool);
5993 } else if (*s == XML_T(ASCII_EQUALS)) {
5995 if (poolLength(&parser->m_tempPool) == 0)
5996 prefix = &dtd->defaultPrefix;
5998 if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6001 = (PREFIX *)lookup(parser, &dtd->prefixes,
6002 poolStart(&parser->m_tempPool), sizeof(PREFIX));
6005 if (prefix->name == poolStart(&parser->m_tempPool)) {
6006 prefix->name = poolCopyString(&dtd->pool, prefix->name);
6010 poolDiscard(&parser->m_tempPool);
6012 for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0');
6014 if (! poolAppendChar(&parser->m_tempPool, *context))
6016 if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6018 if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool),
6019 &parser->m_inheritedBindings)
6022 poolDiscard(&parser->m_tempPool);
6023 if (*context != XML_T('\0'))
6027 if (! poolAppendChar(&parser->m_tempPool, *s))
6035 static void FASTCALL
6036 normalizePublicId(XML_Char *publicId) {
6037 XML_Char *p = publicId;
6039 for (s = publicId; *s; s++) {
6044 if (p != publicId && p[-1] != 0x20)
6051 if (p != publicId && p[-1] == 0x20)
6057 dtdCreate(const XML_Memory_Handling_Suite *ms) {
6058 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
6061 poolInit(&(p->pool), ms);
6062 poolInit(&(p->entityValuePool), ms);
6063 hashTableInit(&(p->generalEntities), ms);
6064 hashTableInit(&(p->elementTypes), ms);
6065 hashTableInit(&(p->attributeIds), ms);
6066 hashTableInit(&(p->prefixes), ms);
6068 p->paramEntityRead = XML_FALSE;
6069 hashTableInit(&(p->paramEntities), ms);
6070 #endif /* XML_DTD */
6071 p->defaultPrefix.name = NULL;
6072 p->defaultPrefix.binding = NULL;
6074 p->in_eldecl = XML_FALSE;
6075 p->scaffIndex = NULL;
6080 p->contentStringLen = 0;
6082 p->keepProcessing = XML_TRUE;
6083 p->hasParamEntityRefs = XML_FALSE;
6084 p->standalone = XML_FALSE;
6089 dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {
6090 HASH_TABLE_ITER iter;
6091 hashTableIterInit(&iter, &(p->elementTypes));
6093 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6096 if (e->allocDefaultAtts != 0)
6097 ms->free_fcn(e->defaultAtts);
6099 hashTableClear(&(p->generalEntities));
6101 p->paramEntityRead = XML_FALSE;
6102 hashTableClear(&(p->paramEntities));
6103 #endif /* XML_DTD */
6104 hashTableClear(&(p->elementTypes));
6105 hashTableClear(&(p->attributeIds));
6106 hashTableClear(&(p->prefixes));
6107 poolClear(&(p->pool));
6108 poolClear(&(p->entityValuePool));
6109 p->defaultPrefix.name = NULL;
6110 p->defaultPrefix.binding = NULL;
6112 p->in_eldecl = XML_FALSE;
6114 ms->free_fcn(p->scaffIndex);
6115 p->scaffIndex = NULL;
6116 ms->free_fcn(p->scaffold);
6122 p->contentStringLen = 0;
6124 p->keepProcessing = XML_TRUE;
6125 p->hasParamEntityRefs = XML_FALSE;
6126 p->standalone = XML_FALSE;
6130 dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
6131 HASH_TABLE_ITER iter;
6132 hashTableIterInit(&iter, &(p->elementTypes));
6134 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6137 if (e->allocDefaultAtts != 0)
6138 ms->free_fcn(e->defaultAtts);
6140 hashTableDestroy(&(p->generalEntities));
6142 hashTableDestroy(&(p->paramEntities));
6143 #endif /* XML_DTD */
6144 hashTableDestroy(&(p->elementTypes));
6145 hashTableDestroy(&(p->attributeIds));
6146 hashTableDestroy(&(p->prefixes));
6147 poolDestroy(&(p->pool));
6148 poolDestroy(&(p->entityValuePool));
6150 ms->free_fcn(p->scaffIndex);
6151 ms->free_fcn(p->scaffold);
6156 /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
6157 The new DTD has already been initialized.
6160 dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
6161 const XML_Memory_Handling_Suite *ms) {
6162 HASH_TABLE_ITER iter;
6164 /* Copy the prefix table. */
6166 hashTableIterInit(&iter, &(oldDtd->prefixes));
6168 const XML_Char *name;
6169 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
6172 name = poolCopyString(&(newDtd->pool), oldP->name);
6175 if (! lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
6179 hashTableIterInit(&iter, &(oldDtd->attributeIds));
6181 /* Copy the attribute id table. */
6185 const XML_Char *name;
6186 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
6190 /* Remember to allocate the scratch byte before the name. */
6191 if (! poolAppendChar(&(newDtd->pool), XML_T('\0')))
6193 name = poolCopyString(&(newDtd->pool), oldA->name);
6197 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
6198 sizeof(ATTRIBUTE_ID));
6201 newA->maybeTokenized = oldA->maybeTokenized;
6203 newA->xmlns = oldA->xmlns;
6204 if (oldA->prefix == &oldDtd->defaultPrefix)
6205 newA->prefix = &newDtd->defaultPrefix;
6207 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
6208 oldA->prefix->name, 0);
6212 /* Copy the element type table. */
6214 hashTableIterInit(&iter, &(oldDtd->elementTypes));
6219 const XML_Char *name;
6220 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6223 name = poolCopyString(&(newDtd->pool), oldE->name);
6226 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
6227 sizeof(ELEMENT_TYPE));
6230 if (oldE->nDefaultAtts) {
6231 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)ms->malloc_fcn(
6232 oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6233 if (! newE->defaultAtts) {
6238 newE->idAtt = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds),
6239 oldE->idAtt->name, 0);
6240 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
6242 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
6243 oldE->prefix->name, 0);
6244 for (i = 0; i < newE->nDefaultAtts; i++) {
6245 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(
6246 oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
6247 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
6248 if (oldE->defaultAtts[i].value) {
6249 newE->defaultAtts[i].value
6250 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
6251 if (! newE->defaultAtts[i].value)
6254 newE->defaultAtts[i].value = NULL;
6258 /* Copy the entity tables. */
6259 if (! copyEntityTable(oldParser, &(newDtd->generalEntities), &(newDtd->pool),
6260 &(oldDtd->generalEntities)))
6264 if (! copyEntityTable(oldParser, &(newDtd->paramEntities), &(newDtd->pool),
6265 &(oldDtd->paramEntities)))
6267 newDtd->paramEntityRead = oldDtd->paramEntityRead;
6268 #endif /* XML_DTD */
6270 newDtd->keepProcessing = oldDtd->keepProcessing;
6271 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
6272 newDtd->standalone = oldDtd->standalone;
6274 /* Don't want deep copying for scaffolding */
6275 newDtd->in_eldecl = oldDtd->in_eldecl;
6276 newDtd->scaffold = oldDtd->scaffold;
6277 newDtd->contentStringLen = oldDtd->contentStringLen;
6278 newDtd->scaffSize = oldDtd->scaffSize;
6279 newDtd->scaffLevel = oldDtd->scaffLevel;
6280 newDtd->scaffIndex = oldDtd->scaffIndex;
6286 copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
6287 STRING_POOL *newPool, const HASH_TABLE *oldTable) {
6288 HASH_TABLE_ITER iter;
6289 const XML_Char *cachedOldBase = NULL;
6290 const XML_Char *cachedNewBase = NULL;
6292 hashTableIterInit(&iter, oldTable);
6296 const XML_Char *name;
6297 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
6300 name = poolCopyString(newPool, oldE->name);
6303 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
6306 if (oldE->systemId) {
6307 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
6310 newE->systemId = tem;
6312 if (oldE->base == cachedOldBase)
6313 newE->base = cachedNewBase;
6315 cachedOldBase = oldE->base;
6316 tem = poolCopyString(newPool, cachedOldBase);
6319 cachedNewBase = newE->base = tem;
6322 if (oldE->publicId) {
6323 tem = poolCopyString(newPool, oldE->publicId);
6326 newE->publicId = tem;
6330 = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
6333 newE->textPtr = tem;
6334 newE->textLen = oldE->textLen;
6336 if (oldE->notation) {
6337 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
6340 newE->notation = tem;
6342 newE->is_param = oldE->is_param;
6343 newE->is_internal = oldE->is_internal;
6348 #define INIT_POWER 6
6350 static XML_Bool FASTCALL
6351 keyeq(KEY s1, KEY s2) {
6352 for (; *s1 == *s2; s1++, s2++)
6361 for (; *s; s++, len++)
6367 copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
6369 key->k[1] = get_hash_secret_salt(parser);
6372 static unsigned long FASTCALL
6373 hash(XML_Parser parser, KEY s) {
6374 struct siphash state;
6377 copy_salt_to_sipkey(parser, &key);
6378 sip24_init(&state, &key);
6379 sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
6380 return (unsigned long)sip24_final(&state);
6384 lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
6386 if (table->size == 0) {
6390 table->power = INIT_POWER;
6391 /* table->size is a power of 2 */
6392 table->size = (size_t)1 << INIT_POWER;
6393 tsize = table->size * sizeof(NAMED *);
6394 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
6399 memset(table->v, 0, tsize);
6400 i = hash(parser, name) & ((unsigned long)table->size - 1);
6402 unsigned long h = hash(parser, name);
6403 unsigned long mask = (unsigned long)table->size - 1;
6404 unsigned char step = 0;
6406 while (table->v[i]) {
6407 if (keyeq(name, table->v[i]->name))
6410 step = PROBE_STEP(h, mask, table->power);
6411 i < step ? (i += table->size - step) : (i -= step);
6416 /* check for overflow (table is half full) */
6417 if (table->used >> (table->power - 1)) {
6418 unsigned char newPower = table->power + 1;
6419 size_t newSize = (size_t)1 << newPower;
6420 unsigned long newMask = (unsigned long)newSize - 1;
6421 size_t tsize = newSize * sizeof(NAMED *);
6422 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
6425 memset(newV, 0, tsize);
6426 for (i = 0; i < table->size; i++)
6428 unsigned long newHash = hash(parser, table->v[i]->name);
6429 size_t j = newHash & newMask;
6433 step = PROBE_STEP(newHash, newMask, newPower);
6434 j < step ? (j += newSize - step) : (j -= step);
6436 newV[j] = table->v[i];
6438 table->mem->free_fcn(table->v);
6440 table->power = newPower;
6441 table->size = newSize;
6444 while (table->v[i]) {
6446 step = PROBE_STEP(h, newMask, newPower);
6447 i < step ? (i += newSize - step) : (i -= step);
6451 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
6454 memset(table->v[i], 0, createSize);
6455 table->v[i]->name = name;
6460 static void FASTCALL
6461 hashTableClear(HASH_TABLE *table) {
6463 for (i = 0; i < table->size; i++) {
6464 table->mem->free_fcn(table->v[i]);
6470 static void FASTCALL
6471 hashTableDestroy(HASH_TABLE *table) {
6473 for (i = 0; i < table->size; i++)
6474 table->mem->free_fcn(table->v[i]);
6475 table->mem->free_fcn(table->v);
6478 static void FASTCALL
6479 hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) {
6487 static void FASTCALL
6488 hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
6490 iter->end = iter->p + table->size;
6493 static NAMED *FASTCALL
6494 hashTableIterNext(HASH_TABLE_ITER *iter) {
6495 while (iter->p != iter->end) {
6496 NAMED *tem = *(iter->p)++;
6503 static void FASTCALL
6504 poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) {
6505 pool->blocks = NULL;
6506 pool->freeBlocks = NULL;
6513 static void FASTCALL
6514 poolClear(STRING_POOL *pool) {
6515 if (! pool->freeBlocks)
6516 pool->freeBlocks = pool->blocks;
6518 BLOCK *p = pool->blocks;
6520 BLOCK *tem = p->next;
6521 p->next = pool->freeBlocks;
6522 pool->freeBlocks = p;
6526 pool->blocks = NULL;
6532 static void FASTCALL
6533 poolDestroy(STRING_POOL *pool) {
6534 BLOCK *p = pool->blocks;
6536 BLOCK *tem = p->next;
6537 pool->mem->free_fcn(p);
6540 p = pool->freeBlocks;
6542 BLOCK *tem = p->next;
6543 pool->mem->free_fcn(p);
6549 poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
6551 if (! pool->ptr && ! poolGrow(pool))
6554 const enum XML_Convert_Result convert_res = XmlConvert(
6555 enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6556 if ((convert_res == XML_CONVERT_COMPLETED)
6557 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
6559 if (! poolGrow(pool))
6565 static const XML_Char *FASTCALL
6566 poolCopyString(STRING_POOL *pool, const XML_Char *s) {
6568 if (! poolAppendChar(pool, *s))
6576 static const XML_Char *
6577 poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) {
6578 if (! pool->ptr && ! poolGrow(pool)) {
6579 /* The following line is unreachable given the current usage of
6580 * poolCopyStringN(). Currently it is called from exactly one
6581 * place to copy the text of a simple general entity. By that
6582 * point, the name of the entity is already stored in the pool, so
6583 * pool->ptr cannot be NULL.
6585 * If poolCopyStringN() is used elsewhere as it well might be,
6586 * this line may well become executable again. Regardless, this
6587 * sort of check shouldn't be removed lightly, so we just exclude
6588 * it from the coverage statistics.
6590 return NULL; /* LCOV_EXCL_LINE */
6592 for (; n > 0; --n, s++) {
6593 if (! poolAppendChar(pool, *s))
6601 static const XML_Char *FASTCALL
6602 poolAppendString(STRING_POOL *pool, const XML_Char *s) {
6604 if (! poolAppendChar(pool, *s))
6612 poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
6614 if (! poolAppend(pool, enc, ptr, end))
6616 if (pool->ptr == pool->end && ! poolGrow(pool))
6623 poolBytesToAllocateFor(int blockSize) {
6624 /* Unprotected math would be:
6625 ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
6627 ** Detect overflow, avoiding _signed_ overflow undefined behavior
6628 ** For a + b * c we check b * c in isolation first, so that addition of a
6629 ** on top has no chance of making us accept a small non-negative number
6631 const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
6636 if (blockSize > (int)(INT_MAX / stretch))
6640 const int stretchedBlockSize = blockSize * (int)stretch;
6641 const int bytesToAllocate
6642 = (int)(offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
6643 if (bytesToAllocate < 0)
6646 return (size_t)bytesToAllocate;
6650 static XML_Bool FASTCALL
6651 poolGrow(STRING_POOL *pool) {
6652 if (pool->freeBlocks) {
6653 if (pool->start == 0) {
6654 pool->blocks = pool->freeBlocks;
6655 pool->freeBlocks = pool->freeBlocks->next;
6656 pool->blocks->next = NULL;
6657 pool->start = pool->blocks->s;
6658 pool->end = pool->start + pool->blocks->size;
6659 pool->ptr = pool->start;
6662 if (pool->end - pool->start < pool->freeBlocks->size) {
6663 BLOCK *tem = pool->freeBlocks->next;
6664 pool->freeBlocks->next = pool->blocks;
6665 pool->blocks = pool->freeBlocks;
6666 pool->freeBlocks = tem;
6667 memcpy(pool->blocks->s, pool->start,
6668 (pool->end - pool->start) * sizeof(XML_Char));
6669 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6670 pool->start = pool->blocks->s;
6671 pool->end = pool->start + pool->blocks->size;
6675 if (pool->blocks && pool->start == pool->blocks->s) {
6677 int blockSize = (int)((unsigned)(pool->end - pool->start) * 2U);
6678 size_t bytesToAllocate;
6680 /* NOTE: Needs to be calculated prior to calling `realloc`
6681 to avoid dangling pointers: */
6682 const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
6684 if (blockSize < 0) {
6685 /* This condition traps a situation where either more than
6686 * INT_MAX/2 bytes have already been allocated. This isn't
6687 * readily testable, since it is unlikely that an average
6688 * machine will have that much memory, so we exclude it from the
6689 * coverage statistics.
6691 return XML_FALSE; /* LCOV_EXCL_LINE */
6694 bytesToAllocate = poolBytesToAllocateFor(blockSize);
6695 if (bytesToAllocate == 0)
6698 temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks,
6699 (unsigned)bytesToAllocate);
6702 pool->blocks = temp;
6703 pool->blocks->size = blockSize;
6704 pool->ptr = pool->blocks->s + offsetInsideBlock;
6705 pool->start = pool->blocks->s;
6706 pool->end = pool->start + blockSize;
6709 int blockSize = (int)(pool->end - pool->start);
6710 size_t bytesToAllocate;
6712 if (blockSize < 0) {
6713 /* This condition traps a situation where either more than
6714 * INT_MAX bytes have already been allocated (which is prevented
6715 * by various pieces of program logic, not least this one, never
6716 * mind the unlikelihood of actually having that much memory) or
6717 * the pool control fields have been corrupted (which could
6718 * conceivably happen in an extremely buggy user handler
6719 * function). Either way it isn't readily testable, so we
6720 * exclude it from the coverage statistics.
6722 return XML_FALSE; /* LCOV_EXCL_LINE */
6725 if (blockSize < INIT_BLOCK_SIZE)
6726 blockSize = INIT_BLOCK_SIZE;
6728 /* Detect overflow, avoiding _signed_ overflow undefined behavior */
6729 if ((int)((unsigned)blockSize * 2U) < 0) {
6735 bytesToAllocate = poolBytesToAllocateFor(blockSize);
6736 if (bytesToAllocate == 0)
6739 tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
6742 tem->size = blockSize;
6743 tem->next = pool->blocks;
6745 if (pool->ptr != pool->start)
6746 memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
6747 pool->ptr = tem->s + (pool->ptr - pool->start);
6748 pool->start = tem->s;
6749 pool->end = tem->s + blockSize;
6755 nextScaffoldPart(XML_Parser parser) {
6756 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6757 CONTENT_SCAFFOLD *me;
6760 if (! dtd->scaffIndex) {
6761 dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
6762 if (! dtd->scaffIndex)
6764 dtd->scaffIndex[0] = 0;
6767 if (dtd->scaffCount >= dtd->scaffSize) {
6768 CONTENT_SCAFFOLD *temp;
6769 if (dtd->scaffold) {
6770 temp = (CONTENT_SCAFFOLD *)REALLOC(
6771 parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
6774 dtd->scaffSize *= 2;
6776 temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS
6777 * sizeof(CONTENT_SCAFFOLD));
6780 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
6782 dtd->scaffold = temp;
6784 next = dtd->scaffCount++;
6785 me = &dtd->scaffold[next];
6786 if (dtd->scaffLevel) {
6787 CONTENT_SCAFFOLD *parent
6788 = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]];
6789 if (parent->lastchild) {
6790 dtd->scaffold[parent->lastchild].nextsib = next;
6792 if (! parent->childcnt)
6793 parent->firstchild = next;
6794 parent->lastchild = next;
6797 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
6802 build_node(XML_Parser parser, int src_node, XML_Content *dest,
6803 XML_Content **contpos, XML_Char **strpos) {
6804 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6805 dest->type = dtd->scaffold[src_node].type;
6806 dest->quant = dtd->scaffold[src_node].quant;
6807 if (dest->type == XML_CTYPE_NAME) {
6808 const XML_Char *src;
6809 dest->name = *strpos;
6810 src = dtd->scaffold[src_node].name;
6812 *(*strpos)++ = *src;
6817 dest->numchildren = 0;
6818 dest->children = NULL;
6822 dest->numchildren = dtd->scaffold[src_node].childcnt;
6823 dest->children = *contpos;
6824 *contpos += dest->numchildren;
6825 for (i = 0, cn = dtd->scaffold[src_node].firstchild; i < dest->numchildren;
6826 i++, cn = dtd->scaffold[cn].nextsib) {
6827 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
6833 static XML_Content *
6834 build_model(XML_Parser parser) {
6835 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6839 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
6840 + (dtd->contentStringLen * sizeof(XML_Char)));
6842 ret = (XML_Content *)MALLOC(parser, allocsize);
6846 str = (XML_Char *)(&ret[dtd->scaffCount]);
6849 build_node(parser, 0, ret, &cpos, &str);
6853 static ELEMENT_TYPE *
6854 getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
6856 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6857 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
6862 ret = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
6863 sizeof(ELEMENT_TYPE));
6866 if (ret->name != name)
6867 poolDiscard(&dtd->pool);
6869 poolFinish(&dtd->pool);
6870 if (! setElementTypePrefix(parser, ret))
6877 copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
6878 int charsRequired = 0;
6881 /* First determine how long the string is */
6882 while (s[charsRequired] != 0) {
6885 /* Include the terminator */
6888 /* Now allocate space for the copy */
6889 result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
6892 /* Copy the original into place */
6893 memcpy(result, s, charsRequired * sizeof(XML_Char));