Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
xmlparse.c
Go to the documentation of this file.
1/* 90815a2b2c80c03b2b889fe1d427bb2b9e3282aa065e42784e001db4f23de324 (2.4.9+)
2 __ __ _
3 ___\ \/ /_ __ __ _| |_
4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
7 |_| XML parser
8
9 Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10 Copyright (c) 2000 Clark Cooper <[email protected]>
11 Copyright (c) 2000-2006 Fred L. Drake, Jr. <[email protected]>
12 Copyright (c) 2001-2002 Greg Stein <[email protected]>
13 Copyright (c) 2002-2016 Karl Waclawek <[email protected]>
14 Copyright (c) 2005-2009 Steven Solie <[email protected]>
15 Copyright (c) 2016 Eric Rahm <[email protected]>
16 Copyright (c) 2016-2022 Sebastian Pipping <[email protected]>
17 Copyright (c) 2016 Gaurav <[email protected]>
18 Copyright (c) 2016 Thomas Beutlich <[email protected]>
19 Copyright (c) 2016 Gustavo Grieco <[email protected]>
20 Copyright (c) 2016 Pascal Cuoq <[email protected]>
21 Copyright (c) 2016 Ed Schouten <[email protected]>
22 Copyright (c) 2017-2022 Rhodri James <[email protected]>
23 Copyright (c) 2017 Václav Slavík <[email protected]>
24 Copyright (c) 2017 Viktor Szakats <[email protected]>
25 Copyright (c) 2017 Chanho Park <[email protected]>
26 Copyright (c) 2017 Rolf Eike Beer <[email protected]>
27 Copyright (c) 2017 Hans Wennborg <[email protected]>
28 Copyright (c) 2018 Anton Maklakov <[email protected]>
29 Copyright (c) 2018 Benjamin Peterson <[email protected]>
30 Copyright (c) 2018 Marco Maggi <[email protected]>
31 Copyright (c) 2018 Mariusz Zaborski <[email protected]>
32 Copyright (c) 2019 David Loffredo <[email protected]>
33 Copyright (c) 2019-2020 Ben Wagner <[email protected]>
34 Copyright (c) 2019 Vadim Zeitlin <[email protected]>
35 Copyright (c) 2021 Dong-hee Na <[email protected]>
36 Copyright (c) 2022 Samanta Navarro <[email protected]>
37 Copyright (c) 2022 Jeffrey Walton <[email protected]>
38 Licensed under the MIT license:
39
40 Permission is hereby granted, free of charge, to any person obtaining
41 a copy of this software and associated documentation files (the
42 "Software"), to deal in the Software without restriction, including
43 without limitation the rights to use, copy, modify, merge, publish,
44 distribute, sublicense, and/or sell copies of the Software, and to permit
45 persons to whom the Software is furnished to do so, subject to the
46 following conditions:
47
48 The above copyright notice and this permission notice shall be included
49 in all copies or substantial portions of the Software.
50
51 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
52 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
53 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
54 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
55 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
56 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
57 USE OR OTHER DEALINGS IN THE SOFTWARE.
58*/
59
60#define XML_BUILDING_EXPAT 1
61
62#include <expat_config.h>
63
64#if ! defined(_GNU_SOURCE)
65# define _GNU_SOURCE 1 /* syscall prototype */
66#endif
67
68#ifdef _WIN32
69/* force stdlib to define rand_s() */
70# if ! defined(_CRT_RAND_S)
71# define _CRT_RAND_S
72# endif
73#endif
74
75#include <stddef.h>
76#include <string.h> /* memset(), memcpy() */
77#include <assert.h>
78#include <limits.h> /* UINT_MAX */
79#include <stdio.h> /* fprintf */
80#include <stdlib.h> /* getenv, rand_s */
81#include <stdint.h> /* uintptr_t */
82#include <math.h> /* isnan */
83
84#ifdef _WIN32
85# define getpid GetCurrentProcessId
86#else
87# include <sys/time.h> /* gettimeofday() */
88# include <sys/types.h> /* getpid() */
89# include <unistd.h> /* getpid() */
90# include <fcntl.h> /* O_RDONLY */
91# include <errno.h>
92#endif
93
94#ifdef _WIN32
95# include "winconfig.h"
96#endif
97
98#include "ascii.h"
99#include "expat.h"
100#include "siphash.h"
101
102#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
103# if defined(HAVE_GETRANDOM)
104# include <sys/random.h> /* getrandom */
105# else
106# include <unistd.h> /* syscall */
107# include <sys/syscall.h> /* SYS_getrandom */
108# endif
109# if ! defined(GRND_NONBLOCK)
110# define GRND_NONBLOCK 0x0001
111# endif /* defined(GRND_NONBLOCK) */
112#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
113
114#if defined(HAVE_LIBBSD) \
115 && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
116# include <bsd/stdlib.h>
117#endif
118
119#if defined(_WIN32) && ! defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
120# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
121#endif
122
123#if ! defined(HAVE_GETRANDOM) && ! defined(HAVE_SYSCALL_GETRANDOM) \
124 && ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) \
125 && ! defined(XML_DEV_URANDOM) && ! defined(_WIN32) \
126 && ! defined(XML_POOR_ENTROPY)
127# error You do not have support for any sources of high quality entropy \
128 enabled. For end user security, that is probably not what you want. \
129 \
130 Your options include: \
131 * Linux >=3.17 + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \
132 * Linux >=3.17 + glibc (including <2.25) (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \
133 * BSD / macOS >=10.7 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \
134 * BSD / macOS (including <10.7) (arc4random): HAVE_ARC4RANDOM, \
135 * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
136 * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
137 * Linux (including <3.17) / BSD / macOS (including <10.7) / Solaris >=8 (/dev/urandom): XML_DEV_URANDOM, \
138 * Windows >=Vista (rand_s): _WIN32. \
139 \
140 If insist on not using any of these, bypass this error by defining \
141 XML_POOR_ENTROPY; you have been warned. \
142 \
143 If you have reasons to patch this detection code away or need changes \
144 to the build system, please open a bug. Thank you!
145#endif
146
147#ifdef XML_UNICODE
148# define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
149# define XmlConvert XmlUtf16Convert
150# define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
151# define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
152# define XmlEncode XmlUtf16Encode
153# define MUST_CONVERT(enc, s) (! (enc)->isUtf16 || (((uintptr_t)(s)) & 1))
154typedef unsigned short ICHAR;
155#else
156# define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
157# define XmlConvert XmlUtf8Convert
158# define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
159# define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
160# define XmlEncode XmlUtf8Encode
161# define MUST_CONVERT(enc, s) (! (enc)->isUtf8)
162typedef char ICHAR;
163#endif
164
165#ifndef XML_NS
166
167# define XmlInitEncodingNS XmlInitEncoding
168# define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
169# undef XmlGetInternalEncodingNS
170# define XmlGetInternalEncodingNS XmlGetInternalEncoding
171# define XmlParseXmlDeclNS XmlParseXmlDecl
172
173#endif
174
175#ifdef XML_UNICODE
176
177# ifdef XML_UNICODE_WCHAR_T
178# define XML_T(x) (const wchar_t) x
179# define XML_L(x) L##x
180# else
181# define XML_T(x) (const unsigned short)x
182# define XML_L(x) x
183# endif
184
185#else
186
187# define XML_T(x) x
188# define XML_L(x) x
189
190#endif
191
192/* Round up n to be a multiple of sz, where sz is a power of 2. */
193#define ROUND_UP(n, sz) (((n) + ((sz)-1)) & ~((sz)-1))
194
195/* Do safe (NULL-aware) pointer arithmetic */
196#define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
197
198#include "internal.h"
199#include "xmltok.h"
200#include "xmlrole.h"
201
202typedef const XML_Char *KEY;
203
204typedef struct {
206} NAMED;
207
208typedef struct {
210 unsigned char power;
211 size_t size;
212 size_t used;
214} HASH_TABLE;
215
216static size_t keylen(KEY s);
217
218static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key);
219
220/* For probing (after a collision) we need a step size relative prime
221 to the hash table size, which is a power of 2. We use double-hashing,
222 since we can calculate a second hash value cheaply by taking those bits
223 of the first hash value that were discarded (masked out) when the table
224 index was calculated: index = hash & mask, where mask = table->size - 1.
225 We limit the maximum step size to table->size / 4 (mask >> 2) and make
226 it odd, since odd numbers are always relative prime to a power of 2.
227*/
228#define SECOND_HASH(hash, mask, power) \
229 ((((hash) & ~(mask)) >> ((power)-1)) & ((mask) >> 2))
230#define PROBE_STEP(hash, mask, power) \
231 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
232
233typedef struct {
237
238#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
239#define INIT_DATA_BUF_SIZE 1024
240#define INIT_ATTS_SIZE 16
241#define INIT_ATTS_VERSION 0xFFFFFFFF
242#define INIT_BLOCK_SIZE 1024
243#define INIT_BUFFER_SIZE 1024
244
245#define EXPAND_SPARE 24
246
247typedef struct binding {
248 struct prefix *prefix;
251 const struct attribute_id *attId;
256
257typedef struct prefix {
261
262typedef struct {
263 const XML_Char *str;
269} TAG_NAME;
270
271/* TAG represents an open element.
272 The name of the element is stored in both the document and API
273 encodings. The memory buffer 'buf' is a separately-allocated
274 memory area which stores the name. During the XML_Parse()/
275 XMLParseBuffer() when the element is open, the memory for the 'raw'
276 version of the name (in the document encoding) is shared with the
277 document buffer. If the element is open across calls to
278 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
279 contain the 'raw' name as well.
280
281 A parser re-uses these structures, maintaining a list of allocated
282 TAG objects in a free list.
283*/
284typedef struct tag {
285 struct tag *parent; /* parent of this element */
286 const char *rawName; /* tagName in the original encoding */
288 TAG_NAME name; /* tagName in the API encoding */
289 char *buf; /* buffer for name components */
290 char *bufEnd; /* end of the buffer */
293
294typedef struct {
297 int textLen; /* length in XML_Chars */
298 int processed; /* # of processed bytes - when suspended */
305 XML_Bool is_internal; /* true if declared in internal subset outside PE */
306} ENTITY;
307
308typedef struct {
317
318#define INIT_SCAFFOLD_ELEMENTS 32
319
320typedef struct block {
321 struct block *next;
322 int size;
325
326typedef struct {
329 const XML_Char *end;
334
335/* The XML_Char before the name is used to determine whether
336 an attribute has been specified. */
337typedef struct attribute_id {
343
344typedef struct {
349
350typedef struct {
351 unsigned long version;
352 unsigned long hash;
354} NS_ATT;
355
356typedef struct {
364
365typedef struct {
372 /* false once a parameter entity reference has been skipped */
374 /* true once an internal or external PE reference has been encountered;
375 this includes the reference to an external subset */
378#ifdef XML_DTD
379 /* indicates if external PE has been read */
380 XML_Bool paramEntityRead;
381 HASH_TABLE paramEntities;
382#endif /* XML_DTD */
384 /* === scaffolding for building content model === */
388 unsigned scaffSize;
389 unsigned scaffCount;
392} DTD;
393
394typedef struct open_internal_entity {
395 const char *internalEventPtr;
400 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
402
404 XML_ACCOUNT_DIRECT, /* bytes directly passed to the Expat parser */
405 XML_ACCOUNT_ENTITY_EXPANSION, /* intermediate bytes produced during entity
406 expansion */
407 XML_ACCOUNT_NONE /* i.e. do not account, was accounted already */
409
410#ifdef XML_DTD
411typedef unsigned long long XmlBigCount;
412typedef struct accounting {
413 XmlBigCount countBytesDirect;
414 XmlBigCount countBytesIndirect;
415 int debugLevel;
416 float maximumAmplificationFactor; // >=1.0
417 unsigned long long activationThresholdBytes;
418} ACCOUNTING;
419
420typedef struct entity_stats {
421 unsigned int countEverOpened;
422 unsigned int currentDepth;
423 unsigned int maximumDepthSeen;
424 int debugLevel;
425} ENTITY_STATS;
426#endif /* XML_DTD */
427
428typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
429 const char *end, const char **endPtr);
430
431static Processor prologProcessor;
432static Processor prologInitProcessor;
433static Processor contentProcessor;
434static Processor cdataSectionProcessor;
435#ifdef XML_DTD
436static Processor ignoreSectionProcessor;
437static Processor externalParEntProcessor;
438static Processor externalParEntInitProcessor;
439static Processor entityValueProcessor;
440static Processor entityValueInitProcessor;
441#endif /* XML_DTD */
442static Processor epilogProcessor;
443static Processor errorProcessor;
444static Processor externalEntityInitProcessor;
445static Processor externalEntityInitProcessor2;
446static Processor externalEntityInitProcessor3;
447static Processor externalEntityContentProcessor;
448static Processor internalEntityProcessor;
449
450static enum XML_Error handleUnknownEncoding(XML_Parser parser,
451 const XML_Char *encodingName);
452static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
453 const char *s, const char *next);
454static enum XML_Error initializeEncoding(XML_Parser parser);
455static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
456 const char *s, const char *end, int tok,
457 const char *next, const char **nextPtr,
458 XML_Bool haveMore, XML_Bool allowClosingDoctype,
459 enum XML_Account account);
460static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
461 XML_Bool betweenDecl);
462static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
463 const ENCODING *enc, const char *start,
464 const char *end, const char **endPtr,
465 XML_Bool haveMore, enum XML_Account account);
466static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *,
467 const char **startPtr, const char *end,
468 const char **nextPtr, XML_Bool haveMore,
469 enum XML_Account account);
470#ifdef XML_DTD
471static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *,
472 const char **startPtr, const char *end,
473 const char **nextPtr, XML_Bool haveMore);
474#endif /* XML_DTD */
475
476static void freeBindings(XML_Parser parser, BINDING *bindings);
477static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *,
478 const char *s, TAG_NAME *tagNamePtr,
479 BINDING **bindingsPtr,
480 enum XML_Account account);
481static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
482 const ATTRIBUTE_ID *attId, const XML_Char *uri,
483 BINDING **bindingsPtr);
484static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
485 XML_Bool isId, const XML_Char *dfltValue,
486 XML_Parser parser);
487static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *,
488 XML_Bool isCdata, const char *,
489 const char *, STRING_POOL *,
490 enum XML_Account account);
491static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *,
492 XML_Bool isCdata, const char *,
493 const char *, STRING_POOL *,
494 enum XML_Account account);
495static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
496 const char *start, const char *end);
497static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
498static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
499 const char *start, const char *end,
500 enum XML_Account account);
501static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
502 const char *start, const char *end);
503static int reportComment(XML_Parser parser, const ENCODING *enc,
504 const char *start, const char *end);
505static void reportDefault(XML_Parser parser, const ENCODING *enc,
506 const char *start, const char *end);
507
508static const XML_Char *getContext(XML_Parser parser);
509static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
510
511static void FASTCALL normalizePublicId(XML_Char *s);
512
513static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms);
514/* do not call if m_parentParser != NULL */
515static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
516static void dtdDestroy(DTD *p, XML_Bool isDocEntity,
517 const XML_Memory_Handling_Suite *ms);
518static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
519 const XML_Memory_Handling_Suite *ms);
520static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *, STRING_POOL *,
521 const HASH_TABLE *);
522static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
523 size_t createSize);
524static void FASTCALL hashTableInit(HASH_TABLE *,
525 const XML_Memory_Handling_Suite *ms);
526static void FASTCALL hashTableClear(HASH_TABLE *);
527static void FASTCALL hashTableDestroy(HASH_TABLE *);
528static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
529static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
530
531static void FASTCALL poolInit(STRING_POOL *,
532 const XML_Memory_Handling_Suite *ms);
533static void FASTCALL poolClear(STRING_POOL *);
534static void FASTCALL poolDestroy(STRING_POOL *);
535static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
536 const char *ptr, const char *end);
537static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
538 const char *ptr, const char *end);
539static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
540static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
541 const XML_Char *s);
542static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
543 int n);
544static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
545 const XML_Char *s);
546
547static int FASTCALL nextScaffoldPart(XML_Parser parser);
548static XML_Content *build_model(XML_Parser parser);
549static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
550 const char *ptr, const char *end);
551
552static XML_Char *copyString(const XML_Char *s,
553 const XML_Memory_Handling_Suite *memsuite);
554
555static unsigned long generate_hash_secret_salt(XML_Parser parser);
556static XML_Bool startParsing(XML_Parser parser);
557
558static XML_Parser parserCreate(const XML_Char *encodingName,
559 const XML_Memory_Handling_Suite *memsuite,
560 const XML_Char *nameSep, DTD *dtd);
561
562static void parserInit(XML_Parser parser, const XML_Char *encodingName);
563
564#ifdef XML_DTD
565static float accountingGetCurrentAmplification(XML_Parser rootParser);
566static void accountingReportStats(XML_Parser originParser, const char *epilog);
567static void accountingOnAbort(XML_Parser originParser);
568static void accountingReportDiff(XML_Parser rootParser,
569 unsigned int levelsAwayFromRootParser,
570 const char *before, const char *after,
571 ptrdiff_t bytesMore, int source_line,
572 enum XML_Account account);
573static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok,
574 const char *before, const char *after,
575 int source_line,
576 enum XML_Account account);
577
578static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity,
579 const char *action, int sourceLine);
580static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity,
581 int sourceLine);
582static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity,
583 int sourceLine);
584
585static XML_Parser getRootParserOf(XML_Parser parser,
586 unsigned int *outLevelDiff);
587#endif /* XML_DTD */
588
589static unsigned long getDebugLevel(const char *variableName,
590 unsigned long defaultDebugLevel);
591
592#define poolStart(pool) ((pool)->start)
593#define poolEnd(pool) ((pool)->ptr)
594#define poolLength(pool) ((pool)->ptr - (pool)->start)
595#define poolChop(pool) ((void)--(pool->ptr))
596#define poolLastChar(pool) (((pool)->ptr)[-1])
597#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
598#define poolFinish(pool) ((pool)->start = (pool)->ptr)
599#define poolAppendChar(pool, c) \
600 (((pool)->ptr == (pool)->end && ! poolGrow(pool)) \
601 ? 0 \
602 : ((*((pool)->ptr)++ = c), 1))
603
605 /* The first member must be m_userData so that the XML_GetUserData
606 macro works. */
609 char *m_buffer;
611 /* first character to be parsed */
612 const char *m_bufferPtr;
613 /* past last character to be parsed */
615 /* allocated end of m_buffer */
616 const char *m_bufferLim;
618 const char *m_parseEndPtr;
653 void(XMLCALL *m_unknownEncodingRelease)(void *);
657 const char *m_eventPtr;
658 const char *m_eventEndPtr;
659 const char *m_positionPtr;
686 unsigned long m_nsAttsVersion;
687 unsigned char m_nsAttsPower;
688#ifdef XML_ATTR_INFO
689 XML_AttrInfo *m_attInfo;
690#endif
695 unsigned int m_groupSize;
699#ifdef XML_DTD
700 XML_Bool m_isParamEntity;
701 XML_Bool m_useForeignDTD;
702 enum XML_ParamEntityParsing m_paramEntityParsing;
703#endif
704 unsigned long m_hash_secret_salt;
705#ifdef XML_DTD
706 ACCOUNTING m_accounting;
707 ENTITY_STATS m_entity_stats;
708#endif
709};
710
711#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
712#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
713#define FREE(parser, p) (parser->m_mem.free_fcn((p)))
714
716XML_ParserCreate(const XML_Char *encodingName) {
717 return XML_ParserCreate_MM(encodingName, NULL, NULL);
718}
719
721XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
722 XML_Char tmp[2] = {nsSep, 0};
723 return XML_ParserCreate_MM(encodingName, NULL, tmp);
724}
725
726// "xml=http://www.w3.org/XML/1998/namespace"
727static const XML_Char implicitContext[]
736 '\0'};
737
738/* To avoid warnings about unused functions: */
739#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
740
741# if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
742
743/* Obtain entropy on Linux 3.17+ */
744static int
745writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
746 int success = 0; /* full count bytes written? */
747 size_t bytesWrittenTotal = 0;
748 const unsigned int getrandomFlags = GRND_NONBLOCK;
749
750 do {
751 void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
752 const size_t bytesToWrite = count - bytesWrittenTotal;
753
754 const int bytesWrittenMore =
755# if defined(HAVE_GETRANDOM)
756 getrandom(currentTarget, bytesToWrite, getrandomFlags);
757# else
758 syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
759# endif
760
761 if (bytesWrittenMore > 0) {
762 bytesWrittenTotal += bytesWrittenMore;
763 if (bytesWrittenTotal >= count)
764 success = 1;
765 }
766 } while (! success && (errno == EINTR));
767
768 return success;
769}
770
771# endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
772
773# if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
774
775/* Extract entropy from /dev/urandom */
776static int
777writeRandomBytes_dev_urandom(void *target, size_t count) {
778 int success = 0; /* full count bytes written? */
779 size_t bytesWrittenTotal = 0;
780
781 const int fd = open("/dev/urandom", O_RDONLY);
782 if (fd < 0) {
783 return 0;
784 }
785
786 do {
787 void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
788 const size_t bytesToWrite = count - bytesWrittenTotal;
789
790 const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
791
792 if (bytesWrittenMore > 0) {
793 bytesWrittenTotal += bytesWrittenMore;
794 if (bytesWrittenTotal >= count)
795 success = 1;
796 }
797 } while (! success && (errno == EINTR));
798
799 close(fd);
800 return success;
801}
802
803# endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
804
805#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
806
807#if defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF)
808
809static void
810writeRandomBytes_arc4random(void *target, size_t count) {
811 size_t bytesWrittenTotal = 0;
812
813 while (bytesWrittenTotal < count) {
814 const uint32_t random32 = arc4random();
815 size_t i = 0;
816
817 for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
818 i++, bytesWrittenTotal++) {
819 const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
820 ((uint8_t *)target)[bytesWrittenTotal] = random8;
821 }
822 }
823}
824
825#endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */
826
827#ifdef _WIN32
828
829/* Provide declaration of rand_s() for MinGW-32 (not 64, which has it),
830 as it didn't declare it in its header prior to version 5.3.0 of its
831 runtime package (mingwrt, containing stdlib.h). The upstream fix
832 was introduced at https://osdn.net/projects/mingw/ticket/39658 . */
833# if defined(__MINGW32__) && defined(__MINGW32_VERSION) \
834 && __MINGW32_VERSION < 5003000L && ! defined(__MINGW64_VERSION_MAJOR)
835__declspec(dllimport) int rand_s(unsigned int *);
836# endif
837
838/* Obtain entropy on Windows using the rand_s() function which
839 * generates cryptographically secure random numbers. Internally it
840 * uses RtlGenRandom API which is present in Windows XP and later.
841 */
842static int
843writeRandomBytes_rand_s(void *target, size_t count) {
844 size_t bytesWrittenTotal = 0;
845
846 while (bytesWrittenTotal < count) {
847 unsigned int random32 = 0;
848 size_t i = 0;
849
850 if (rand_s(&random32))
851 return 0; /* failure */
852
853 for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
854 i++, bytesWrittenTotal++) {
855 const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
856 ((uint8_t *)target)[bytesWrittenTotal] = random8;
857 }
858 }
859 return 1; /* success */
860}
861
862#endif /* _WIN32 */
863
864#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
865
866static unsigned long
867gather_time_entropy(void) {
868# ifdef _WIN32
869 FILETIME ft;
870 GetSystemTimeAsFileTime(&ft); /* never fails */
871 return ft.dwHighDateTime ^ ft.dwLowDateTime;
872# else
873 struct timeval tv;
874 int gettimeofday_res;
875
876 gettimeofday_res = gettimeofday(&tv, NULL);
877
878# if defined(NDEBUG)
879 (void)gettimeofday_res;
880# else
881 assert(gettimeofday_res == 0);
882# endif /* defined(NDEBUG) */
883
884 /* Microseconds time is <20 bits entropy */
885 return tv.tv_usec;
886# endif
887}
888
889#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
890
891static unsigned long
892ENTROPY_DEBUG(const char *label, unsigned long entropy) {
893 if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) {
894 fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
895 (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
896 }
897 return entropy;
898}
899
900static unsigned long
901generate_hash_secret_salt(XML_Parser parser) {
902 unsigned long entropy;
903 (void)parser;
904
905 /* "Failproof" high quality providers: */
906#if defined(HAVE_ARC4RANDOM_BUF)
907 arc4random_buf(&entropy, sizeof(entropy));
908 return ENTROPY_DEBUG("arc4random_buf", entropy);
909#elif defined(HAVE_ARC4RANDOM)
910 writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
911 return ENTROPY_DEBUG("arc4random", entropy);
912#else
913 /* Try high quality providers first .. */
914# ifdef _WIN32
915 if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
916 return ENTROPY_DEBUG("rand_s", entropy);
917 }
918# elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
919 if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
920 return ENTROPY_DEBUG("getrandom", entropy);
921 }
922# endif
923# if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
924 if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
925 return ENTROPY_DEBUG("/dev/urandom", entropy);
926 }
927# endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
928 /* .. and self-made low quality for backup: */
929
930 /* Process ID is 0 bits entropy if attacker has local access */
931 entropy = gather_time_entropy() ^ getpid();
932
933 /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
934 if (sizeof(unsigned long) == 4) {
935 return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
936 } else {
937 return ENTROPY_DEBUG("fallback(8)",
938 entropy * (unsigned long)2305843009213693951ULL);
939 }
940#endif
941}
942
943static unsigned long
944get_hash_secret_salt(XML_Parser parser) {
945 if (parser->m_parentParser != NULL)
946 return get_hash_secret_salt(parser->m_parentParser);
947 return parser->m_hash_secret_salt;
948}
949
950static XML_Bool /* only valid for root parser */
951startParsing(XML_Parser parser) {
952 /* hash functions must be initialized before setContext() is called */
953 if (parser->m_hash_secret_salt == 0)
954 parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
955 if (parser->m_ns) {
956 /* implicit context only set for root parser, since child
957 parsers (i.e. external entity parsers) will inherit it
958 */
959 return setContext(parser, implicitContext);
960 }
961 return XML_TRUE;
962}
963
965XML_ParserCreate_MM(const XML_Char *encodingName,
966 const XML_Memory_Handling_Suite *memsuite,
967 const XML_Char *nameSep) {
968 return parserCreate(encodingName, memsuite, nameSep, NULL);
969}
970
971static XML_Parser
972parserCreate(const XML_Char *encodingName,
973 const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep,
974 DTD *dtd) {
975 XML_Parser parser;
976
977 if (memsuite) {
979 parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
980 if (parser != NULL) {
981 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
982 mtemp->malloc_fcn = memsuite->malloc_fcn;
983 mtemp->realloc_fcn = memsuite->realloc_fcn;
984 mtemp->free_fcn = memsuite->free_fcn;
985 }
986 } else {
988 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
989 if (parser != NULL) {
990 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
991 mtemp->malloc_fcn = malloc;
992 mtemp->realloc_fcn = realloc;
993 mtemp->free_fcn = free;
994 }
995 }
996
997 if (! parser)
998 return parser;
999
1000 parser->m_buffer = NULL;
1001 parser->m_bufferLim = NULL;
1002
1003 parser->m_attsSize = INIT_ATTS_SIZE;
1004 parser->m_atts
1005 = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
1006 if (parser->m_atts == NULL) {
1007 FREE(parser, parser);
1008 return NULL;
1009 }
1010#ifdef XML_ATTR_INFO
1011 parser->m_attInfo = (XML_AttrInfo *)MALLOC(
1012 parser, parser->m_attsSize * sizeof(XML_AttrInfo));
1013 if (parser->m_attInfo == NULL) {
1014 FREE(parser, parser->m_atts);
1015 FREE(parser, parser);
1016 return NULL;
1017 }
1018#endif
1019 parser->m_dataBuf
1020 = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
1021 if (parser->m_dataBuf == NULL) {
1022 FREE(parser, parser->m_atts);
1023#ifdef XML_ATTR_INFO
1024 FREE(parser, parser->m_attInfo);
1025#endif
1026 FREE(parser, parser);
1027 return NULL;
1028 }
1029 parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
1030
1031 if (dtd)
1032 parser->m_dtd = dtd;
1033 else {
1034 parser->m_dtd = dtdCreate(&parser->m_mem);
1035 if (parser->m_dtd == NULL) {
1036 FREE(parser, parser->m_dataBuf);
1037 FREE(parser, parser->m_atts);
1038#ifdef XML_ATTR_INFO
1039 FREE(parser, parser->m_attInfo);
1040#endif
1041 FREE(parser, parser);
1042 return NULL;
1043 }
1044 }
1045
1046 parser->m_freeBindingList = NULL;
1047 parser->m_freeTagList = NULL;
1048 parser->m_freeInternalEntities = NULL;
1049
1050 parser->m_groupSize = 0;
1051 parser->m_groupConnector = NULL;
1052
1053 parser->m_unknownEncodingHandler = NULL;
1054 parser->m_unknownEncodingHandlerData = NULL;
1055
1057 parser->m_ns = XML_FALSE;
1058 parser->m_ns_triplets = XML_FALSE;
1059
1060 parser->m_nsAtts = NULL;
1061 parser->m_nsAttsVersion = 0;
1062 parser->m_nsAttsPower = 0;
1063
1064 parser->m_protocolEncodingName = NULL;
1065
1066 poolInit(&parser->m_tempPool, &(parser->m_mem));
1067 poolInit(&parser->m_temp2Pool, &(parser->m_mem));
1068 parserInit(parser, encodingName);
1069
1070 if (encodingName && ! parser->m_protocolEncodingName) {
1071 XML_ParserFree(parser);
1072 return NULL;
1073 }
1074
1075 if (nameSep) {
1076 parser->m_ns = XML_TRUE;
1078 parser->m_namespaceSeparator = *nameSep;
1079 } else {
1081 }
1082
1083 return parser;
1084}
1085
1086static void
1087parserInit(XML_Parser parser, const XML_Char *encodingName) {
1088 parser->m_processor = prologInitProcessor;
1090 if (encodingName != NULL) {
1091 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1092 }
1093 parser->m_curBase = NULL;
1094 XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
1095 parser->m_userData = NULL;
1096 parser->m_handlerArg = NULL;
1097 parser->m_startElementHandler = NULL;
1098 parser->m_endElementHandler = NULL;
1099 parser->m_characterDataHandler = NULL;
1100 parser->m_processingInstructionHandler = NULL;
1101 parser->m_commentHandler = NULL;
1102 parser->m_startCdataSectionHandler = NULL;
1103 parser->m_endCdataSectionHandler = NULL;
1104 parser->m_defaultHandler = NULL;
1105 parser->m_startDoctypeDeclHandler = NULL;
1106 parser->m_endDoctypeDeclHandler = NULL;
1107 parser->m_unparsedEntityDeclHandler = NULL;
1108 parser->m_notationDeclHandler = NULL;
1109 parser->m_startNamespaceDeclHandler = NULL;
1110 parser->m_endNamespaceDeclHandler = NULL;
1111 parser->m_notStandaloneHandler = NULL;
1112 parser->m_externalEntityRefHandler = NULL;
1113 parser->m_externalEntityRefHandlerArg = parser;
1114 parser->m_skippedEntityHandler = NULL;
1115 parser->m_elementDeclHandler = NULL;
1116 parser->m_attlistDeclHandler = NULL;
1117 parser->m_entityDeclHandler = NULL;
1118 parser->m_xmlDeclHandler = NULL;
1119 parser->m_bufferPtr = parser->m_buffer;
1120 parser->m_bufferEnd = parser->m_buffer;
1121 parser->m_parseEndByteIndex = 0;
1122 parser->m_parseEndPtr = NULL;
1123 parser->m_declElementType = NULL;
1124 parser->m_declAttributeId = NULL;
1125 parser->m_declEntity = NULL;
1126 parser->m_doctypeName = NULL;
1127 parser->m_doctypeSysid = NULL;
1128 parser->m_doctypePubid = NULL;
1129 parser->m_declAttributeType = NULL;
1130 parser->m_declNotationName = NULL;
1131 parser->m_declNotationPublicId = NULL;
1134 memset(&parser->m_position, 0, sizeof(POSITION));
1135 parser->m_errorCode = XML_ERROR_NONE;
1136 parser->m_eventPtr = NULL;
1137 parser->m_eventEndPtr = NULL;
1138 parser->m_positionPtr = NULL;
1139 parser->m_openInternalEntities = NULL;
1141 parser->m_tagLevel = 0;
1142 parser->m_tagStack = NULL;
1143 parser->m_inheritedBindings = NULL;
1144 parser->m_nSpecifiedAtts = 0;
1145 parser->m_unknownEncodingMem = NULL;
1146 parser->m_unknownEncodingRelease = NULL;
1147 parser->m_unknownEncodingData = NULL;
1148 parser->m_parentParser = NULL;
1150#ifdef XML_DTD
1151 parser->m_isParamEntity = XML_FALSE;
1152 parser->m_useForeignDTD = XML_FALSE;
1153 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
1154#endif
1155 parser->m_hash_secret_salt = 0;
1156
1157#ifdef XML_DTD
1158 memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
1159 parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
1160 parser->m_accounting.maximumAmplificationFactor
1162 parser->m_accounting.activationThresholdBytes
1164
1165 memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS));
1166 parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u);
1167#endif
1168}
1169
1170/* moves list of bindings to m_freeBindingList */
1171static void FASTCALL
1172moveToFreeBindingList(XML_Parser parser, BINDING *bindings) {
1173 while (bindings) {
1174 BINDING *b = bindings;
1175 bindings = bindings->nextTagBinding;
1176 b->nextTagBinding = parser->m_freeBindingList;
1177 parser->m_freeBindingList = b;
1178 }
1179}
1180
1182XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
1183 TAG *tStk;
1184 OPEN_INTERNAL_ENTITY *openEntityList;
1185
1186 if (parser == NULL)
1187 return XML_FALSE;
1188
1189 if (parser->m_parentParser)
1190 return XML_FALSE;
1191 /* move m_tagStack to m_freeTagList */
1192 tStk = parser->m_tagStack;
1193 while (tStk) {
1194 TAG *tag = tStk;
1195 tStk = tStk->parent;
1196 tag->parent = parser->m_freeTagList;
1197 moveToFreeBindingList(parser, tag->bindings);
1198 tag->bindings = NULL;
1199 parser->m_freeTagList = tag;
1200 }
1201 /* move m_openInternalEntities to m_freeInternalEntities */
1202 openEntityList = parser->m_openInternalEntities;
1203 while (openEntityList) {
1204 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
1205 openEntityList = openEntity->next;
1206 openEntity->next = parser->m_freeInternalEntities;
1207 parser->m_freeInternalEntities = openEntity;
1208 }
1209 moveToFreeBindingList(parser, parser->m_inheritedBindings);
1210 FREE(parser, parser->m_unknownEncodingMem);
1211 if (parser->m_unknownEncodingRelease)
1212 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1213 poolClear(&parser->m_tempPool);
1214 poolClear(&parser->m_temp2Pool);
1215 FREE(parser, (void *)parser->m_protocolEncodingName);
1216 parser->m_protocolEncodingName = NULL;
1217 parserInit(parser, encodingName);
1218 dtdReset(parser->m_dtd, &parser->m_mem);
1219 return XML_TRUE;
1220}
1221
1223XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
1224 if (parser == NULL)
1225 return XML_STATUS_ERROR;
1226 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
1227 XXX There's no way for the caller to determine which of the
1228 XXX possible error cases caused the XML_STATUS_ERROR return.
1229 */
1230 if (parser->m_parsingStatus.parsing == XML_PARSING
1232 return XML_STATUS_ERROR;
1233
1234 /* Get rid of any previous encoding name */
1235 FREE(parser, (void *)parser->m_protocolEncodingName);
1236
1237 if (encodingName == NULL)
1238 /* No new encoding name */
1239 parser->m_protocolEncodingName = NULL;
1240 else {
1241 /* Copy the new encoding name into allocated memory */
1242 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1243 if (! parser->m_protocolEncodingName)
1244 return XML_STATUS_ERROR;
1245 }
1246 return XML_STATUS_OK;
1247}
1248
1251 const XML_Char *encodingName) {
1252 XML_Parser parser = oldParser;
1253 DTD *newDtd = NULL;
1254 DTD *oldDtd;
1255 XML_StartElementHandler oldStartElementHandler;
1256 XML_EndElementHandler oldEndElementHandler;
1257 XML_CharacterDataHandler oldCharacterDataHandler;
1258 XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
1259 XML_CommentHandler oldCommentHandler;
1260 XML_StartCdataSectionHandler oldStartCdataSectionHandler;
1261 XML_EndCdataSectionHandler oldEndCdataSectionHandler;
1262 XML_DefaultHandler oldDefaultHandler;
1263 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
1264 XML_NotationDeclHandler oldNotationDeclHandler;
1265 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
1266 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
1267 XML_NotStandaloneHandler oldNotStandaloneHandler;
1268 XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
1269 XML_SkippedEntityHandler oldSkippedEntityHandler;
1270 XML_UnknownEncodingHandler oldUnknownEncodingHandler;
1271 XML_ElementDeclHandler oldElementDeclHandler;
1272 XML_AttlistDeclHandler oldAttlistDeclHandler;
1273 XML_EntityDeclHandler oldEntityDeclHandler;
1274 XML_XmlDeclHandler oldXmlDeclHandler;
1275 ELEMENT_TYPE *oldDeclElementType;
1276
1277 void *oldUserData;
1278 void *oldHandlerArg;
1279 XML_Bool oldDefaultExpandInternalEntities;
1280 XML_Parser oldExternalEntityRefHandlerArg;
1281#ifdef XML_DTD
1282 enum XML_ParamEntityParsing oldParamEntityParsing;
1283 int oldInEntityValue;
1284#endif
1285 XML_Bool oldns_triplets;
1286 /* Note that the new parser shares the same hash secret as the old
1287 parser, so that dtdCopy and copyEntityTable can lookup values
1288 from hash tables associated with either parser without us having
1289 to worry which hash secrets each table has.
1290 */
1291 unsigned long oldhash_secret_salt;
1292
1293 /* Validate the oldParser parameter before we pull everything out of it */
1294 if (oldParser == NULL)
1295 return NULL;
1296
1297 /* Stash the original parser contents on the stack */
1298 oldDtd = parser->m_dtd;
1299 oldStartElementHandler = parser->m_startElementHandler;
1300 oldEndElementHandler = parser->m_endElementHandler;
1301 oldCharacterDataHandler = parser->m_characterDataHandler;
1302 oldProcessingInstructionHandler = parser->m_processingInstructionHandler;
1303 oldCommentHandler = parser->m_commentHandler;
1304 oldStartCdataSectionHandler = parser->m_startCdataSectionHandler;
1305 oldEndCdataSectionHandler = parser->m_endCdataSectionHandler;
1306 oldDefaultHandler = parser->m_defaultHandler;
1307 oldUnparsedEntityDeclHandler = parser->m_unparsedEntityDeclHandler;
1308 oldNotationDeclHandler = parser->m_notationDeclHandler;
1309 oldStartNamespaceDeclHandler = parser->m_startNamespaceDeclHandler;
1310 oldEndNamespaceDeclHandler = parser->m_endNamespaceDeclHandler;
1311 oldNotStandaloneHandler = parser->m_notStandaloneHandler;
1312 oldExternalEntityRefHandler = parser->m_externalEntityRefHandler;
1313 oldSkippedEntityHandler = parser->m_skippedEntityHandler;
1314 oldUnknownEncodingHandler = parser->m_unknownEncodingHandler;
1315 oldElementDeclHandler = parser->m_elementDeclHandler;
1316 oldAttlistDeclHandler = parser->m_attlistDeclHandler;
1317 oldEntityDeclHandler = parser->m_entityDeclHandler;
1318 oldXmlDeclHandler = parser->m_xmlDeclHandler;
1319 oldDeclElementType = parser->m_declElementType;
1320
1321 oldUserData = parser->m_userData;
1322 oldHandlerArg = parser->m_handlerArg;
1323 oldDefaultExpandInternalEntities = parser->m_defaultExpandInternalEntities;
1324 oldExternalEntityRefHandlerArg = parser->m_externalEntityRefHandlerArg;
1325#ifdef XML_DTD
1326 oldParamEntityParsing = parser->m_paramEntityParsing;
1327 oldInEntityValue = parser->m_prologState.inEntityValue;
1328#endif
1329 oldns_triplets = parser->m_ns_triplets;
1330 /* Note that the new parser shares the same hash secret as the old
1331 parser, so that dtdCopy and copyEntityTable can lookup values
1332 from hash tables associated with either parser without us having
1333 to worry which hash secrets each table has.
1334 */
1335 oldhash_secret_salt = parser->m_hash_secret_salt;
1336
1337#ifdef XML_DTD
1338 if (! context)
1339 newDtd = oldDtd;
1340#endif /* XML_DTD */
1341
1342 /* Note that the magical uses of the pre-processor to make field
1343 access look more like C++ require that `parser' be overwritten
1344 here. This makes this function more painful to follow than it
1345 would be otherwise.
1346 */
1347 if (parser->m_ns) {
1348 XML_Char tmp[2] = {parser->m_namespaceSeparator, 0};
1349 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1350 } else {
1351 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1352 }
1353
1354 if (! parser)
1355 return NULL;
1356
1357 parser->m_startElementHandler = oldStartElementHandler;
1358 parser->m_endElementHandler = oldEndElementHandler;
1359 parser->m_characterDataHandler = oldCharacterDataHandler;
1360 parser->m_processingInstructionHandler = oldProcessingInstructionHandler;
1361 parser->m_commentHandler = oldCommentHandler;
1362 parser->m_startCdataSectionHandler = oldStartCdataSectionHandler;
1363 parser->m_endCdataSectionHandler = oldEndCdataSectionHandler;
1364 parser->m_defaultHandler = oldDefaultHandler;
1365 parser->m_unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1366 parser->m_notationDeclHandler = oldNotationDeclHandler;
1367 parser->m_startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1368 parser->m_endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1369 parser->m_notStandaloneHandler = oldNotStandaloneHandler;
1370 parser->m_externalEntityRefHandler = oldExternalEntityRefHandler;
1371 parser->m_skippedEntityHandler = oldSkippedEntityHandler;
1372 parser->m_unknownEncodingHandler = oldUnknownEncodingHandler;
1373 parser->m_elementDeclHandler = oldElementDeclHandler;
1374 parser->m_attlistDeclHandler = oldAttlistDeclHandler;
1375 parser->m_entityDeclHandler = oldEntityDeclHandler;
1376 parser->m_xmlDeclHandler = oldXmlDeclHandler;
1377 parser->m_declElementType = oldDeclElementType;
1378 parser->m_userData = oldUserData;
1379 if (oldUserData == oldHandlerArg)
1380 parser->m_handlerArg = parser->m_userData;
1381 else
1382 parser->m_handlerArg = parser;
1383 if (oldExternalEntityRefHandlerArg != oldParser)
1384 parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1385 parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1386 parser->m_ns_triplets = oldns_triplets;
1387 parser->m_hash_secret_salt = oldhash_secret_salt;
1388 parser->m_parentParser = oldParser;
1389#ifdef XML_DTD
1390 parser->m_paramEntityParsing = oldParamEntityParsing;
1391 parser->m_prologState.inEntityValue = oldInEntityValue;
1392 if (context) {
1393#endif /* XML_DTD */
1394 if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
1395 || ! setContext(parser, context)) {
1396 XML_ParserFree(parser);
1397 return NULL;
1398 }
1399 parser->m_processor = externalEntityInitProcessor;
1400#ifdef XML_DTD
1401 } else {
1402 /* The DTD instance referenced by parser->m_dtd is shared between the
1403 document's root parser and external PE parsers, therefore one does not
1404 need to call setContext. In addition, one also *must* not call
1405 setContext, because this would overwrite existing prefix->binding
1406 pointers in parser->m_dtd with ones that get destroyed with the external
1407 PE parser. This would leave those prefixes with dangling pointers.
1408 */
1409 parser->m_isParamEntity = XML_TRUE;
1410 XmlPrologStateInitExternalEntity(&parser->m_prologState);
1411 parser->m_processor = externalParEntInitProcessor;
1412 }
1413#endif /* XML_DTD */
1414 return parser;
1415}
1416
1417static void FASTCALL
1418destroyBindings(BINDING *bindings, XML_Parser parser) {
1419 for (;;) {
1420 BINDING *b = bindings;
1421 if (! b)
1422 break;
1423 bindings = b->nextTagBinding;
1424 FREE(parser, b->uri);
1425 FREE(parser, b);
1426 }
1427}
1428
1429void XMLCALL
1431 TAG *tagList;
1432 OPEN_INTERNAL_ENTITY *entityList;
1433 if (parser == NULL)
1434 return;
1435 /* free m_tagStack and m_freeTagList */
1436 tagList = parser->m_tagStack;
1437 for (;;) {
1438 TAG *p;
1439 if (tagList == NULL) {
1440 if (parser->m_freeTagList == NULL)
1441 break;
1442 tagList = parser->m_freeTagList;
1443 parser->m_freeTagList = NULL;
1444 }
1445 p = tagList;
1446 tagList = tagList->parent;
1447 FREE(parser, p->buf);
1448 destroyBindings(p->bindings, parser);
1449 FREE(parser, p);
1450 }
1451 /* free m_openInternalEntities and m_freeInternalEntities */
1452 entityList = parser->m_openInternalEntities;
1453 for (;;) {
1454 OPEN_INTERNAL_ENTITY *openEntity;
1455 if (entityList == NULL) {
1456 if (parser->m_freeInternalEntities == NULL)
1457 break;
1458 entityList = parser->m_freeInternalEntities;
1459 parser->m_freeInternalEntities = NULL;
1460 }
1461 openEntity = entityList;
1462 entityList = entityList->next;
1463 FREE(parser, openEntity);
1464 }
1465
1466 destroyBindings(parser->m_freeBindingList, parser);
1467 destroyBindings(parser->m_inheritedBindings, parser);
1468 poolDestroy(&parser->m_tempPool);
1469 poolDestroy(&parser->m_temp2Pool);
1470 FREE(parser, (void *)parser->m_protocolEncodingName);
1471#ifdef XML_DTD
1472 /* external parameter entity parsers share the DTD structure
1473 parser->m_dtd with the root parser, so we must not destroy it
1474 */
1475 if (! parser->m_isParamEntity && parser->m_dtd)
1476#else
1477 if (parser->m_dtd)
1478#endif /* XML_DTD */
1479 dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser,
1480 &parser->m_mem);
1481 FREE(parser, (void *)parser->m_atts);
1482#ifdef XML_ATTR_INFO
1483 FREE(parser, (void *)parser->m_attInfo);
1484#endif
1485 FREE(parser, parser->m_groupConnector);
1486 FREE(parser, parser->m_buffer);
1487 FREE(parser, parser->m_dataBuf);
1488 FREE(parser, parser->m_nsAtts);
1489 FREE(parser, parser->m_unknownEncodingMem);
1490 if (parser->m_unknownEncodingRelease)
1491 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1492 FREE(parser, parser);
1493}
1494
1495void XMLCALL
1497 if (parser != NULL)
1498 parser->m_handlerArg = parser;
1499}
1500
1501enum XML_Error XMLCALL
1503 if (parser == NULL)
1505#ifdef XML_DTD
1506 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1507 if (parser->m_parsingStatus.parsing == XML_PARSING
1510 parser->m_useForeignDTD = useDTD;
1511 return XML_ERROR_NONE;
1512#else
1513 UNUSED_P(useDTD);
1515#endif
1516}
1517
1518void XMLCALL
1520 if (parser == NULL)
1521 return;
1522 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1523 if (parser->m_parsingStatus.parsing == XML_PARSING
1525 return;
1526 parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1527}
1528
1529void XMLCALL
1530XML_SetUserData(XML_Parser parser, void *p) {
1531 if (parser == NULL)
1532 return;
1533 if (parser->m_handlerArg == parser->m_userData)
1534 parser->m_handlerArg = parser->m_userData = p;
1535 else
1536 parser->m_userData = p;
1537}
1538
1541 if (parser == NULL)
1542 return XML_STATUS_ERROR;
1543 if (p) {
1544 p = poolCopyString(&parser->m_dtd->pool, p);
1545 if (! p)
1546 return XML_STATUS_ERROR;
1547 parser->m_curBase = p;
1548 } else
1549 parser->m_curBase = NULL;
1550 return XML_STATUS_OK;
1551}
1552
1553const XML_Char *XMLCALL
1555 if (parser == NULL)
1556 return NULL;
1557 return parser->m_curBase;
1558}
1559
1560int XMLCALL
1562 if (parser == NULL)
1563 return -1;
1564 return parser->m_nSpecifiedAtts;
1565}
1566
1567int XMLCALL
1569 if (parser == NULL)
1570 return -1;
1571 return parser->m_idAttIndex;
1572}
1573
1574#ifdef XML_ATTR_INFO
1575const XML_AttrInfo *XMLCALL
1576XML_GetAttributeInfo(XML_Parser parser) {
1577 if (parser == NULL)
1578 return NULL;
1579 return parser->m_attInfo;
1580}
1581#endif
1582
1583void XMLCALL
1586 if (parser == NULL)
1587 return;
1588 parser->m_startElementHandler = start;
1589 parser->m_endElementHandler = end;
1590}
1591
1592void XMLCALL
1594 if (parser != NULL)
1595 parser->m_startElementHandler = start;
1596}
1597
1598void XMLCALL
1600 if (parser != NULL)
1601 parser->m_endElementHandler = end;
1602}
1603
1604void XMLCALL
1606 XML_CharacterDataHandler handler) {
1607 if (parser != NULL)
1608 parser->m_characterDataHandler = handler;
1609}
1610
1611void XMLCALL
1614 if (parser != NULL)
1615 parser->m_processingInstructionHandler = handler;
1616}
1617
1618void XMLCALL
1620 if (parser != NULL)
1621 parser->m_commentHandler = handler;
1622}
1623
1624void XMLCALL
1628 if (parser == NULL)
1629 return;
1630 parser->m_startCdataSectionHandler = start;
1631 parser->m_endCdataSectionHandler = end;
1632}
1633
1634void XMLCALL
1637 if (parser != NULL)
1638 parser->m_startCdataSectionHandler = start;
1639}
1640
1641void XMLCALL
1644 if (parser != NULL)
1645 parser->m_endCdataSectionHandler = end;
1646}
1647
1648void XMLCALL
1650 if (parser == NULL)
1651 return;
1652 parser->m_defaultHandler = handler;
1654}
1655
1656void XMLCALL
1658 if (parser == NULL)
1659 return;
1660 parser->m_defaultHandler = handler;
1662}
1663
1664void XMLCALL
1667 if (parser == NULL)
1668 return;
1669 parser->m_startDoctypeDeclHandler = start;
1670 parser->m_endDoctypeDeclHandler = end;
1671}
1672
1673void XMLCALL
1676 if (parser != NULL)
1677 parser->m_startDoctypeDeclHandler = start;
1678}
1679
1680void XMLCALL
1682 if (parser != NULL)
1683 parser->m_endDoctypeDeclHandler = end;
1684}
1685
1686void XMLCALL
1689 if (parser != NULL)
1690 parser->m_unparsedEntityDeclHandler = handler;
1691}
1692
1693void XMLCALL
1695 if (parser != NULL)
1696 parser->m_notationDeclHandler = handler;
1697}
1698
1699void XMLCALL
1703 if (parser == NULL)
1704 return;
1705 parser->m_startNamespaceDeclHandler = start;
1706 parser->m_endNamespaceDeclHandler = end;
1707}
1708
1709void XMLCALL
1712 if (parser != NULL)
1713 parser->m_startNamespaceDeclHandler = start;
1714}
1715
1716void XMLCALL
1719 if (parser != NULL)
1720 parser->m_endNamespaceDeclHandler = end;
1721}
1722
1723void XMLCALL
1725 XML_NotStandaloneHandler handler) {
1726 if (parser != NULL)
1727 parser->m_notStandaloneHandler = handler;
1728}
1729
1730void XMLCALL
1733 if (parser != NULL)
1734 parser->m_externalEntityRefHandler = handler;
1735}
1736
1737void XMLCALL
1739 if (parser == NULL)
1740 return;
1741 if (arg)
1743 else
1744 parser->m_externalEntityRefHandlerArg = parser;
1745}
1746
1747void XMLCALL
1749 XML_SkippedEntityHandler handler) {
1750 if (parser != NULL)
1751 parser->m_skippedEntityHandler = handler;
1752}
1753
1754void XMLCALL
1756 XML_UnknownEncodingHandler handler, void *data) {
1757 if (parser == NULL)
1758 return;
1759 parser->m_unknownEncodingHandler = handler;
1760 parser->m_unknownEncodingHandlerData = data;
1761}
1762
1763void XMLCALL
1765 if (parser != NULL)
1766 parser->m_elementDeclHandler = eldecl;
1767}
1768
1769void XMLCALL
1771 if (parser != NULL)
1772 parser->m_attlistDeclHandler = attdecl;
1773}
1774
1775void XMLCALL
1777 if (parser != NULL)
1778 parser->m_entityDeclHandler = handler;
1779}
1780
1781void XMLCALL
1783 if (parser != NULL)
1784 parser->m_xmlDeclHandler = handler;
1785}
1786
1787int XMLCALL
1789 enum XML_ParamEntityParsing peParsing) {
1790 if (parser == NULL)
1791 return 0;
1792 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1793 if (parser->m_parsingStatus.parsing == XML_PARSING
1795 return 0;
1796#ifdef XML_DTD
1797 parser->m_paramEntityParsing = peParsing;
1798 return 1;
1799#else
1800 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1801#endif
1802}
1803
1804int XMLCALL
1805XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
1806 if (parser == NULL)
1807 return 0;
1808 if (parser->m_parentParser)
1809 return XML_SetHashSalt(parser->m_parentParser, hash_salt);
1810 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1811 if (parser->m_parsingStatus.parsing == XML_PARSING
1813 return 0;
1814 parser->m_hash_secret_salt = hash_salt;
1815 return 1;
1816}
1817
1819XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
1820 if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
1821 if (parser != NULL)
1823 return XML_STATUS_ERROR;
1824 }
1825 switch (parser->m_parsingStatus.parsing) {
1826 case XML_SUSPENDED:
1828 return XML_STATUS_ERROR;
1829 case XML_FINISHED:
1831 return XML_STATUS_ERROR;
1832 case XML_INITIALIZED:
1833 if (parser->m_parentParser == NULL && ! startParsing(parser)) {
1835 return XML_STATUS_ERROR;
1836 }
1837 /* fall through */
1838 default:
1840 }
1841
1842 if (len == 0) {
1843 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
1844 if (! isFinal)
1845 return XML_STATUS_OK;
1846 parser->m_positionPtr = parser->m_bufferPtr;
1847 parser->m_parseEndPtr = parser->m_bufferEnd;
1848
1849 /* If data are left over from last buffer, and we now know that these
1850 data are the final chunk of input, then we have to check them again
1851 to detect errors based on that fact.
1852 */
1853 parser->m_errorCode
1854 = parser->m_processor(parser, parser->m_bufferPtr,
1855 parser->m_parseEndPtr, &parser->m_bufferPtr);
1856
1857 if (parser->m_errorCode == XML_ERROR_NONE) {
1858 switch (parser->m_parsingStatus.parsing) {
1859 case XML_SUSPENDED:
1860 /* It is hard to be certain, but it seems that this case
1861 * cannot occur. This code is cleaning up a previous parse
1862 * with no new data (since len == 0). Changing the parsing
1863 * state requires getting to execute a handler function, and
1864 * there doesn't seem to be an opportunity for that while in
1865 * this circumstance.
1866 *
1867 * Given the uncertainty, we retain the code but exclude it
1868 * from coverage tests.
1869 *
1870 * LCOV_EXCL_START
1871 */
1873 parser->m_bufferPtr, &parser->m_position);
1874 parser->m_positionPtr = parser->m_bufferPtr;
1875 return XML_STATUS_SUSPENDED;
1876 /* LCOV_EXCL_STOP */
1877 case XML_INITIALIZED:
1878 case XML_PARSING:
1880 /* fall through */
1881 default:
1882 return XML_STATUS_OK;
1883 }
1884 }
1885 parser->m_eventEndPtr = parser->m_eventPtr;
1886 parser->m_processor = errorProcessor;
1887 return XML_STATUS_ERROR;
1888 }
1889#ifndef XML_CONTEXT_BYTES
1890 else if (parser->m_bufferPtr == parser->m_bufferEnd) {
1891 const char *end;
1892 int nLeftOver;
1893 enum XML_Status result;
1894 /* Detect overflow (a+b > MAX <==> b > MAX-a) */
1895 if ((XML_Size)len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) {
1897 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1898 parser->m_processor = errorProcessor;
1899 return XML_STATUS_ERROR;
1900 }
1901 parser->m_parseEndByteIndex += len;
1902 parser->m_positionPtr = s;
1903 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
1904
1905 parser->m_errorCode
1906 = parser->m_processor(parser, s, parser->m_parseEndPtr = s + len, &end);
1907
1908 if (parser->m_errorCode != XML_ERROR_NONE) {
1909 parser->m_eventEndPtr = parser->m_eventPtr;
1910 parser->m_processor = errorProcessor;
1911 return XML_STATUS_ERROR;
1912 } else {
1913 switch (parser->m_parsingStatus.parsing) {
1914 case XML_SUSPENDED:
1915 result = XML_STATUS_SUSPENDED;
1916 break;
1917 case XML_INITIALIZED:
1918 case XML_PARSING:
1919 if (isFinal) {
1921 return XML_STATUS_OK;
1922 }
1923 /* fall through */
1924 default:
1925 result = XML_STATUS_OK;
1926 }
1927 }
1928
1929 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end,
1930 &parser->m_position);
1931 nLeftOver = s + len - end;
1932 if (nLeftOver) {
1933 if (parser->m_buffer == NULL
1934 || nLeftOver > parser->m_bufferLim - parser->m_buffer) {
1935 /* avoid _signed_ integer overflow */
1936 char *temp = NULL;
1937 const int bytesToAllocate = (int)((unsigned)len * 2U);
1938 if (bytesToAllocate > 0) {
1939 temp = (char *)REALLOC(parser, parser->m_buffer, bytesToAllocate);
1940 }
1941 if (temp == NULL) {
1943 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1944 parser->m_processor = errorProcessor;
1945 return XML_STATUS_ERROR;
1946 }
1947 parser->m_buffer = temp;
1948 parser->m_bufferLim = parser->m_buffer + bytesToAllocate;
1949 }
1950 memcpy(parser->m_buffer, end, nLeftOver);
1951 }
1952 parser->m_bufferPtr = parser->m_buffer;
1953 parser->m_bufferEnd = parser->m_buffer + nLeftOver;
1954 parser->m_positionPtr = parser->m_bufferPtr;
1955 parser->m_parseEndPtr = parser->m_bufferEnd;
1956 parser->m_eventPtr = parser->m_bufferPtr;
1957 parser->m_eventEndPtr = parser->m_bufferPtr;
1958 return result;
1959 }
1960#endif /* not defined XML_CONTEXT_BYTES */
1961 else {
1962 void *buff = XML_GetBuffer(parser, len);
1963 if (buff == NULL)
1964 return XML_STATUS_ERROR;
1965 else {
1966 memcpy(buff, s, len);
1967 return XML_ParseBuffer(parser, len, isFinal);
1968 }
1969 }
1970}
1971
1973XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
1974 const char *start;
1975 enum XML_Status result = XML_STATUS_OK;
1976
1977 if (parser == NULL)
1978 return XML_STATUS_ERROR;
1979 switch (parser->m_parsingStatus.parsing) {
1980 case XML_SUSPENDED:
1982 return XML_STATUS_ERROR;
1983 case XML_FINISHED:
1985 return XML_STATUS_ERROR;
1986 case XML_INITIALIZED:
1987 /* Has someone called XML_GetBuffer successfully before? */
1988 if (! parser->m_bufferPtr) {
1990 return XML_STATUS_ERROR;
1991 }
1992
1993 if (parser->m_parentParser == NULL && ! startParsing(parser)) {
1995 return XML_STATUS_ERROR;
1996 }
1997 /* fall through */
1998 default:
2000 }
2001
2002 start = parser->m_bufferPtr;
2003 parser->m_positionPtr = start;
2004 parser->m_bufferEnd += len;
2005 parser->m_parseEndPtr = parser->m_bufferEnd;
2006 parser->m_parseEndByteIndex += len;
2007 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
2008
2009 parser->m_errorCode = parser->m_processor(
2010 parser, start, parser->m_parseEndPtr, &parser->m_bufferPtr);
2011
2012 if (parser->m_errorCode != XML_ERROR_NONE) {
2013 parser->m_eventEndPtr = parser->m_eventPtr;
2014 parser->m_processor = errorProcessor;
2015 return XML_STATUS_ERROR;
2016 } else {
2017 switch (parser->m_parsingStatus.parsing) {
2018 case XML_SUSPENDED:
2019 result = XML_STATUS_SUSPENDED;
2020 break;
2021 case XML_INITIALIZED:
2022 case XML_PARSING:
2023 if (isFinal) {
2025 return result;
2026 }
2027 default:; /* should not happen */
2028 }
2029 }
2030
2032 parser->m_bufferPtr, &parser->m_position);
2033 parser->m_positionPtr = parser->m_bufferPtr;
2034 return result;
2035}
2036
2037void *XMLCALL
2038XML_GetBuffer(XML_Parser parser, int len) {
2039 if (parser == NULL)
2040 return NULL;
2041 if (len < 0) {
2043 return NULL;
2044 }
2045 switch (parser->m_parsingStatus.parsing) {
2046 case XML_SUSPENDED:
2048 return NULL;
2049 case XML_FINISHED:
2051 return NULL;
2052 default:;
2053 }
2054
2055 if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)) {
2056#ifdef XML_CONTEXT_BYTES
2057 int keep;
2058#endif /* defined XML_CONTEXT_BYTES */
2059 /* Do not invoke signed arithmetic overflow: */
2060 int neededSize = (int)((unsigned)len
2061 + (unsigned)EXPAT_SAFE_PTR_DIFF(
2062 parser->m_bufferEnd, parser->m_bufferPtr));
2063 if (neededSize < 0) {
2065 return NULL;
2066 }
2067#ifdef XML_CONTEXT_BYTES
2068 keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
2069 if (keep > XML_CONTEXT_BYTES)
2070 keep = XML_CONTEXT_BYTES;
2071 /* Detect and prevent integer overflow */
2072 if (keep > INT_MAX - neededSize) {
2074 return NULL;
2075 }
2076 neededSize += keep;
2077#endif /* defined XML_CONTEXT_BYTES */
2078 if (neededSize
2079 <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) {
2080#ifdef XML_CONTEXT_BYTES
2081 if (keep < EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)) {
2082 int offset
2083 = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)
2084 - keep;
2085 /* The buffer pointers cannot be NULL here; we have at least some bytes
2086 * in the buffer */
2087 memmove(parser->m_buffer, &parser->m_buffer[offset],
2088 parser->m_bufferEnd - parser->m_bufferPtr + keep);
2089 parser->m_bufferEnd -= offset;
2090 parser->m_bufferPtr -= offset;
2091 }
2092#else
2093 if (parser->m_buffer && parser->m_bufferPtr) {
2094 memmove(parser->m_buffer, parser->m_bufferPtr,
2095 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
2096 parser->m_bufferEnd
2097 = parser->m_buffer
2098 + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
2099 parser->m_bufferPtr = parser->m_buffer;
2100 }
2101#endif /* not defined XML_CONTEXT_BYTES */
2102 } else {
2103 char *newBuf;
2104 int bufferSize
2105 = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferPtr);
2106 if (bufferSize == 0)
2107 bufferSize = INIT_BUFFER_SIZE;
2108 do {
2109 /* Do not invoke signed arithmetic overflow: */
2110 bufferSize = (int)(2U * (unsigned)bufferSize);
2111 } while (bufferSize < neededSize && bufferSize > 0);
2112 if (bufferSize <= 0) {
2114 return NULL;
2115 }
2116 newBuf = (char *)MALLOC(parser, bufferSize);
2117 if (newBuf == 0) {
2119 return NULL;
2120 }
2121 parser->m_bufferLim = newBuf + bufferSize;
2122#ifdef XML_CONTEXT_BYTES
2123 if (parser->m_bufferPtr) {
2124 memcpy(newBuf, &parser->m_bufferPtr[-keep],
2126 + keep);
2127 FREE(parser, parser->m_buffer);
2128 parser->m_buffer = newBuf;
2129 parser->m_bufferEnd
2130 = parser->m_buffer
2131 + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
2132 + keep;
2133 parser->m_bufferPtr = parser->m_buffer + keep;
2134 } else {
2135 /* This must be a brand new buffer with no data in it yet */
2136 parser->m_bufferEnd = newBuf;
2137 parser->m_bufferPtr = parser->m_buffer = newBuf;
2138 }
2139#else
2140 if (parser->m_bufferPtr) {
2141 memcpy(newBuf, parser->m_bufferPtr,
2142 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
2143 FREE(parser, parser->m_buffer);
2144 parser->m_bufferEnd
2145 = newBuf
2146 + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
2147 } else {
2148 /* This must be a brand new buffer with no data in it yet */
2149 parser->m_bufferEnd = newBuf;
2150 }
2151 parser->m_bufferPtr = parser->m_buffer = newBuf;
2152#endif /* not defined XML_CONTEXT_BYTES */
2153 }
2154 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
2155 parser->m_positionPtr = NULL;
2156 }
2157 return parser->m_bufferEnd;
2158}
2159
2162 if (parser == NULL)
2163 return XML_STATUS_ERROR;
2164 switch (parser->m_parsingStatus.parsing) {
2165 case XML_SUSPENDED:
2166 if (resumable) {
2168 return XML_STATUS_ERROR;
2169 }
2171 break;
2172 case XML_FINISHED:
2174 return XML_STATUS_ERROR;
2175 default:
2176 if (resumable) {
2177#ifdef XML_DTD
2178 if (parser->m_isParamEntity) {
2180 return XML_STATUS_ERROR;
2181 }
2182#endif
2184 } else
2186 }
2187 return XML_STATUS_OK;
2188}
2189
2192 enum XML_Status result = XML_STATUS_OK;
2193
2194 if (parser == NULL)
2195 return XML_STATUS_ERROR;
2196 if (parser->m_parsingStatus.parsing != XML_SUSPENDED) {
2198 return XML_STATUS_ERROR;
2199 }
2201
2202 parser->m_errorCode = parser->m_processor(
2203 parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr);
2204
2205 if (parser->m_errorCode != XML_ERROR_NONE) {
2206 parser->m_eventEndPtr = parser->m_eventPtr;
2207 parser->m_processor = errorProcessor;
2208 return XML_STATUS_ERROR;
2209 } else {
2210 switch (parser->m_parsingStatus.parsing) {
2211 case XML_SUSPENDED:
2212 result = XML_STATUS_SUSPENDED;
2213 break;
2214 case XML_INITIALIZED:
2215 case XML_PARSING:
2216 if (parser->m_parsingStatus.finalBuffer) {
2218 return result;
2219 }
2220 default:;
2221 }
2222 }
2223
2225 parser->m_bufferPtr, &parser->m_position);
2226 parser->m_positionPtr = parser->m_bufferPtr;
2227 return result;
2228}
2229
2230void XMLCALL
2232 if (parser == NULL)
2233 return;
2234 assert(status != NULL);
2235 *status = parser->m_parsingStatus;
2236}
2237
2238enum XML_Error XMLCALL
2240 if (parser == NULL)
2242 return parser->m_errorCode;
2243}
2244
2247 if (parser == NULL)
2248 return -1;
2249 if (parser->m_eventPtr)
2250 return (XML_Index)(parser->m_parseEndByteIndex
2251 - (parser->m_parseEndPtr - parser->m_eventPtr));
2252 return -1;
2253}
2254
2255int XMLCALL
2257 if (parser == NULL)
2258 return 0;
2259 if (parser->m_eventEndPtr && parser->m_eventPtr)
2260 return (int)(parser->m_eventEndPtr - parser->m_eventPtr);
2261 return 0;
2262}
2263
2264const char *XMLCALL
2265XML_GetInputContext(XML_Parser parser, int *offset, int *size) {
2266#ifdef XML_CONTEXT_BYTES
2267 if (parser == NULL)
2268 return NULL;
2269 if (parser->m_eventPtr && parser->m_buffer) {
2270 if (offset != NULL)
2271 *offset = (int)(parser->m_eventPtr - parser->m_buffer);
2272 if (size != NULL)
2273 *size = (int)(parser->m_bufferEnd - parser->m_buffer);
2274 return parser->m_buffer;
2275 }
2276#else
2277 (void)parser;
2278 (void)offset;
2279 (void)size;
2280#endif /* defined XML_CONTEXT_BYTES */
2281 return (const char *)0;
2282}
2283
2286 if (parser == NULL)
2287 return 0;
2288 if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2290 parser->m_eventPtr, &parser->m_position);
2291 parser->m_positionPtr = parser->m_eventPtr;
2292 }
2293 return parser->m_position.lineNumber + 1;
2294}
2295
2298 if (parser == NULL)
2299 return 0;
2300 if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2302 parser->m_eventPtr, &parser->m_position);
2303 parser->m_positionPtr = parser->m_eventPtr;
2304 }
2305 return parser->m_position.columnNumber;
2306}
2307
2308void XMLCALL
2310 if (parser != NULL)
2311 FREE(parser, model);
2312}
2313
2314void *XMLCALL
2315XML_MemMalloc(XML_Parser parser, size_t size) {
2316 if (parser == NULL)
2317 return NULL;
2318 return MALLOC(parser, size);
2319}
2320
2321void *XMLCALL
2322XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) {
2323 if (parser == NULL)
2324 return NULL;
2325 return REALLOC(parser, ptr, size);
2326}
2327
2328void XMLCALL
2329XML_MemFree(XML_Parser parser, void *ptr) {
2330 if (parser != NULL)
2331 FREE(parser, ptr);
2332}
2333
2334void XMLCALL
2336 if (parser == NULL)
2337 return;
2338 if (parser->m_defaultHandler) {
2339 if (parser->m_openInternalEntities)
2340 reportDefault(parser, parser->m_internalEncoding,
2343 else
2344 reportDefault(parser, parser->m_encoding, parser->m_eventPtr,
2345 parser->m_eventEndPtr);
2346 }
2347}
2348
2349const XML_LChar *XMLCALL
2351 switch (code) {
2352 case XML_ERROR_NONE:
2353 return NULL;
2355 return XML_L("out of memory");
2356 case XML_ERROR_SYNTAX:
2357 return XML_L("syntax error");
2359 return XML_L("no element found");
2361 return XML_L("not well-formed (invalid token)");
2363 return XML_L("unclosed token");
2365 return XML_L("partial character");
2367 return XML_L("mismatched tag");
2369 return XML_L("duplicate attribute");
2371 return XML_L("junk after document element");
2373 return XML_L("illegal parameter entity reference");
2375 return XML_L("undefined entity");
2377 return XML_L("recursive entity reference");
2379 return XML_L("asynchronous entity");
2381 return XML_L("reference to invalid character number");
2383 return XML_L("reference to binary entity");
2385 return XML_L("reference to external entity in attribute");
2387 return XML_L("XML or text declaration not at start of entity");
2389 return XML_L("unknown encoding");
2391 return XML_L("encoding specified in XML declaration is incorrect");
2393 return XML_L("unclosed CDATA section");
2395 return XML_L("error in processing external entity reference");
2397 return XML_L("document is not standalone");
2399 return XML_L("unexpected parser state - please send a bug report");
2401 return XML_L("entity declared in parameter entity");
2403 return XML_L("requested feature requires XML_DTD support in Expat");
2405 return XML_L("cannot change setting once parsing has begun");
2406 /* Added in 1.95.7. */
2408 return XML_L("unbound prefix");
2409 /* Added in 1.95.8. */
2411 return XML_L("must not undeclare prefix");
2413 return XML_L("incomplete markup in parameter entity");
2414 case XML_ERROR_XML_DECL:
2415 return XML_L("XML declaration not well-formed");
2417 return XML_L("text declaration not well-formed");
2418 case XML_ERROR_PUBLICID:
2419 return XML_L("illegal character(s) in public id");
2421 return XML_L("parser suspended");
2423 return XML_L("parser not suspended");
2424 case XML_ERROR_ABORTED:
2425 return XML_L("parsing aborted");
2426 case XML_ERROR_FINISHED:
2427 return XML_L("parsing finished");
2429 return XML_L("cannot suspend in external parameter entity");
2430 /* Added in 2.0.0. */
2432 return XML_L(
2433 "reserved prefix (xml) must not be undeclared or bound to another namespace name");
2435 return XML_L("reserved prefix (xmlns) must not be declared or undeclared");
2437 return XML_L(
2438 "prefix must not be bound to one of the reserved namespace names");
2439 /* Added in 2.2.5. */
2440 case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
2441 return XML_L("invalid argument");
2442 /* Added in 2.3.0. */
2444 return XML_L(
2445 "a successful prior call to function XML_GetBuffer is required");
2446 /* Added in 2.4.0. */
2448 return XML_L(
2449 "limit on input amplification factor (from DTD and entities) breached");
2450 }
2451 return NULL;
2452}
2453
2454const XML_LChar *XMLCALL
2456 /* V1 is used to string-ize the version number. However, it would
2457 string-ize the actual version macro *names* unless we get them
2458 substituted before being passed to V1. CPP is defined to expand
2459 a macro, then rescan for more expansions. Thus, we use V2 to expand
2460 the version macros, then CPP will expand the resulting V1() macro
2461 with the correct numerals. */
2462 /* ### I'm assuming cpp is portable in this respect... */
2463
2464#define V1(a, b, c) XML_L(#a) XML_L(".") XML_L(#b) XML_L(".") XML_L(#c)
2465#define V2(a, b, c) XML_L("expat_") V1(a, b, c)
2466
2468
2469#undef V1
2470#undef V2
2471}
2472
2475 XML_Expat_Version version;
2476
2477 version.major = XML_MAJOR_VERSION;
2478 version.minor = XML_MINOR_VERSION;
2479 version.micro = XML_MICRO_VERSION;
2480
2481 return version;
2482}
2483
2484const XML_Feature *XMLCALL
2486 static const XML_Feature features[] = {
2487 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2488 sizeof(XML_Char)},
2489 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2490 sizeof(XML_LChar)},
2491#ifdef XML_UNICODE
2492 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2493#endif
2494#ifdef XML_UNICODE_WCHAR_T
2495 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2496#endif
2497#ifdef XML_DTD
2498 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2499#endif
2500#ifdef XML_CONTEXT_BYTES
2501 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2503#endif
2504#ifdef XML_MIN_SIZE
2505 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2506#endif
2507#ifdef XML_NS
2508 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2509#endif
2510#ifdef XML_LARGE_SIZE
2511 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
2512#endif
2513#ifdef XML_ATTR_INFO
2514 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2515#endif
2516#ifdef XML_DTD
2517 /* Added in Expat 2.4.0. */
2519 XML_L("XML_BLAP_MAX_AMP"),
2520 (long int)
2523 XML_L("XML_BLAP_ACT_THRES"),
2525#endif
2526 {XML_FEATURE_END, NULL, 0}};
2527
2528 return features;
2529}
2530
2531#ifdef XML_DTD
2533XML_SetBillionLaughsAttackProtectionMaximumAmplification(
2534 XML_Parser parser, float maximumAmplificationFactor) {
2535 if ((parser == NULL) || (parser->m_parentParser != NULL)
2536 || isnan(maximumAmplificationFactor)
2537 || (maximumAmplificationFactor < 1.0f)) {
2538 return XML_FALSE;
2539 }
2540 parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor;
2541 return XML_TRUE;
2542}
2543
2545XML_SetBillionLaughsAttackProtectionActivationThreshold(
2546 XML_Parser parser, unsigned long long activationThresholdBytes) {
2547 if ((parser == NULL) || (parser->m_parentParser != NULL)) {
2548 return XML_FALSE;
2549 }
2550 parser->m_accounting.activationThresholdBytes = activationThresholdBytes;
2551 return XML_TRUE;
2552}
2553#endif /* XML_DTD */
2554
2555/* Initially tag->rawName always points into the parse buffer;
2556 for those TAG instances opened while the current parse buffer was
2557 processed, and not yet closed, we need to store tag->rawName in a more
2558 permanent location, since the parse buffer is about to be discarded.
2559*/
2560static XML_Bool
2561storeRawNames(XML_Parser parser) {
2562 TAG *tag = parser->m_tagStack;
2563 while (tag) {
2564 int bufSize;
2565 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2566 size_t rawNameLen;
2567 char *rawNameBuf = tag->buf + nameLen;
2568 /* Stop if already stored. Since m_tagStack is a stack, we can stop
2569 at the first entry that has already been copied; everything
2570 below it in the stack is already been accounted for in a
2571 previous call to this function.
2572 */
2573 if (tag->rawName == rawNameBuf)
2574 break;
2575 /* For re-use purposes we need to ensure that the
2576 size of tag->buf is a multiple of sizeof(XML_Char).
2577 */
2578 rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2579 /* Detect and prevent integer overflow. */
2580 if (rawNameLen > (size_t)INT_MAX - nameLen)
2581 return XML_FALSE;
2582 bufSize = nameLen + (int)rawNameLen;
2583 if (bufSize > tag->bufEnd - tag->buf) {
2584 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
2585 if (temp == NULL)
2586 return XML_FALSE;
2587 /* if tag->name.str points to tag->buf (only when namespace
2588 processing is off) then we have to update it
2589 */
2590 if (tag->name.str == (XML_Char *)tag->buf)
2591 tag->name.str = (XML_Char *)temp;
2592 /* if tag->name.localPart is set (when namespace processing is on)
2593 then update it as well, since it will always point into tag->buf
2594 */
2595 if (tag->name.localPart)
2597 = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf);
2598 tag->buf = temp;
2599 tag->bufEnd = temp + bufSize;
2600 rawNameBuf = temp + nameLen;
2601 }
2602 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2603 tag->rawName = rawNameBuf;
2604 tag = tag->parent;
2605 }
2606 return XML_TRUE;
2607}
2608
2609static enum XML_Error PTRCALL
2610contentProcessor(XML_Parser parser, const char *start, const char *end,
2611 const char **endPtr) {
2612 enum XML_Error result = doContent(
2613 parser, 0, parser->m_encoding, start, end, endPtr,
2615 if (result == XML_ERROR_NONE) {
2616 if (! storeRawNames(parser))
2617 return XML_ERROR_NO_MEMORY;
2618 }
2619 return result;
2620}
2621
2622static enum XML_Error PTRCALL
2623externalEntityInitProcessor(XML_Parser parser, const char *start,
2624 const char *end, const char **endPtr) {
2625 enum XML_Error result = initializeEncoding(parser);
2626 if (result != XML_ERROR_NONE)
2627 return result;
2628 parser->m_processor = externalEntityInitProcessor2;
2629 return externalEntityInitProcessor2(parser, start, end, endPtr);
2630}
2631
2632static enum XML_Error PTRCALL
2633externalEntityInitProcessor2(XML_Parser parser, const char *start,
2634 const char *end, const char **endPtr) {
2635 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2636 int tok = XmlContentTok(parser->m_encoding, start, end, &next);
2637 switch (tok) {
2638 case XML_TOK_BOM:
2639#ifdef XML_DTD
2640 if (! accountingDiffTolerated(parser, tok, start, next, __LINE__,
2642 accountingOnAbort(parser);
2644 }
2645#endif /* XML_DTD */
2646
2647 /* If we are at the end of the buffer, this would cause the next stage,
2648 i.e. externalEntityInitProcessor3, to pass control directly to
2649 doContent (by detecting XML_TOK_NONE) without processing any xml text
2650 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2651 */
2652 if (next == end && ! parser->m_parsingStatus.finalBuffer) {
2653 *endPtr = next;
2654 return XML_ERROR_NONE;
2655 }
2656 start = next;
2657 break;
2658 case XML_TOK_PARTIAL:
2659 if (! parser->m_parsingStatus.finalBuffer) {
2660 *endPtr = start;
2661 return XML_ERROR_NONE;
2662 }
2663 parser->m_eventPtr = start;
2666 if (! parser->m_parsingStatus.finalBuffer) {
2667 *endPtr = start;
2668 return XML_ERROR_NONE;
2669 }
2670 parser->m_eventPtr = start;
2672 }
2673 parser->m_processor = externalEntityInitProcessor3;
2674 return externalEntityInitProcessor3(parser, start, end, endPtr);
2675}
2676
2677static enum XML_Error PTRCALL
2678externalEntityInitProcessor3(XML_Parser parser, const char *start,
2679 const char *end, const char **endPtr) {
2680 int tok;
2681 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2682 parser->m_eventPtr = start;
2683 tok = XmlContentTok(parser->m_encoding, start, end, &next);
2684 /* Note: These bytes are accounted later in:
2685 - processXmlDecl
2686 - externalEntityContentProcessor
2687 */
2688 parser->m_eventEndPtr = next;
2689
2690 switch (tok) {
2691 case XML_TOK_XML_DECL: {
2692 enum XML_Error result;
2693 result = processXmlDecl(parser, 1, start, next);
2694 if (result != XML_ERROR_NONE)
2695 return result;
2696 switch (parser->m_parsingStatus.parsing) {
2697 case XML_SUSPENDED:
2698 *endPtr = next;
2699 return XML_ERROR_NONE;
2700 case XML_FINISHED:
2701 return XML_ERROR_ABORTED;
2702 default:
2703 start = next;
2704 }
2705 } break;
2706 case XML_TOK_PARTIAL:
2707 if (! parser->m_parsingStatus.finalBuffer) {
2708 *endPtr = start;
2709 return XML_ERROR_NONE;
2710 }
2713 if (! parser->m_parsingStatus.finalBuffer) {
2714 *endPtr = start;
2715 return XML_ERROR_NONE;
2716 }
2718 }
2719 parser->m_processor = externalEntityContentProcessor;
2720 parser->m_tagLevel = 1;
2721 return externalEntityContentProcessor(parser, start, end, endPtr);
2722}
2723
2724static enum XML_Error PTRCALL
2725externalEntityContentProcessor(XML_Parser parser, const char *start,
2726 const char *end, const char **endPtr) {
2727 enum XML_Error result
2728 = doContent(parser, 1, parser->m_encoding, start, end, endPtr,
2731 if (result == XML_ERROR_NONE) {
2732 if (! storeRawNames(parser))
2733 return XML_ERROR_NO_MEMORY;
2734 }
2735 return result;
2736}
2737
2738static enum XML_Error
2739doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
2740 const char *s, const char *end, const char **nextPtr,
2741 XML_Bool haveMore, enum XML_Account account) {
2742 /* save one level of indirection */
2743 DTD *const dtd = parser->m_dtd;
2744
2745 const char **eventPP;
2746 const char **eventEndPP;
2747 if (enc == parser->m_encoding) {
2748 eventPP = &parser->m_eventPtr;
2749 eventEndPP = &parser->m_eventEndPtr;
2750 } else {
2751 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
2752 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
2753 }
2754 *eventPP = s;
2755
2756 for (;;) {
2757 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2758 int tok = XmlContentTok(enc, s, end, &next);
2759#ifdef XML_DTD
2760 const char *accountAfter
2761 = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR))
2762 ? (haveMore ? s /* i.e. 0 bytes */ : end)
2763 : next;
2764 if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__,
2765 account)) {
2766 accountingOnAbort(parser);
2768 }
2769#endif
2770 *eventEndPP = next;
2771 switch (tok) {
2773 if (haveMore) {
2774 *nextPtr = s;
2775 return XML_ERROR_NONE;
2776 }
2777 *eventEndPP = end;
2778 if (parser->m_characterDataHandler) {
2779 XML_Char c = 0xA;
2780 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
2781 } else if (parser->m_defaultHandler)
2782 reportDefault(parser, enc, s, end);
2783 /* We are at the end of the final buffer, should we check for
2784 XML_SUSPENDED, XML_FINISHED?
2785 */
2786 if (startTagLevel == 0)
2787 return XML_ERROR_NO_ELEMENTS;
2788 if (parser->m_tagLevel != startTagLevel)
2790 *nextPtr = end;
2791 return XML_ERROR_NONE;
2792 case XML_TOK_NONE:
2793 if (haveMore) {
2794 *nextPtr = s;
2795 return XML_ERROR_NONE;
2796 }
2797 if (startTagLevel > 0) {
2798 if (parser->m_tagLevel != startTagLevel)
2800 *nextPtr = s;
2801 return XML_ERROR_NONE;
2802 }
2803 return XML_ERROR_NO_ELEMENTS;
2804 case XML_TOK_INVALID:
2805 *eventPP = next;
2807 case XML_TOK_PARTIAL:
2808 if (haveMore) {
2809 *nextPtr = s;
2810 return XML_ERROR_NONE;
2811 }
2814 if (haveMore) {
2815 *nextPtr = s;
2816 return XML_ERROR_NONE;
2817 }
2819 case XML_TOK_ENTITY_REF: {
2820 const XML_Char *name;
2821 ENTITY *entity;
2823 enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
2824 if (ch) {
2825#ifdef XML_DTD
2826 /* NOTE: We are replacing 4-6 characters original input for 1 character
2827 * so there is no amplification and hence recording without
2828 * protection. */
2829 accountingDiffTolerated(parser, tok, (char *)&ch,
2830 ((char *)&ch) + sizeof(XML_Char), __LINE__,
2832#endif /* XML_DTD */
2833 if (parser->m_characterDataHandler)
2834 parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
2835 else if (parser->m_defaultHandler)
2836 reportDefault(parser, enc, s, next);
2837 break;
2838 }
2839 name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
2840 next - enc->minBytesPerChar);
2841 if (! name)
2842 return XML_ERROR_NO_MEMORY;
2843 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
2844 poolDiscard(&dtd->pool);
2845 /* First, determine if a check for an existing declaration is needed;
2846 if yes, check that the entity exists, and that it is internal,
2847 otherwise call the skipped entity or default handler.
2848 */
2849 if (! dtd->hasParamEntityRefs || dtd->standalone) {
2850 if (! entity)
2852 else if (! entity->is_internal)
2854 } else if (! entity) {
2855 if (parser->m_skippedEntityHandler)
2856 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
2857 else if (parser->m_defaultHandler)
2858 reportDefault(parser, enc, s, next);
2859 break;
2860 }
2861 if (entity->open)
2863 if (entity->notation)
2865 if (entity->textPtr) {
2866 enum XML_Error result;
2867 if (! parser->m_defaultExpandInternalEntities) {
2868 if (parser->m_skippedEntityHandler)
2869 parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name,
2870 0);
2871 else if (parser->m_defaultHandler)
2872 reportDefault(parser, enc, s, next);
2873 break;
2874 }
2875 result = processInternalEntity(parser, entity, XML_FALSE);
2876 if (result != XML_ERROR_NONE)
2877 return result;
2878 } else if (parser->m_externalEntityRefHandler) {
2879 const XML_Char *context;
2880 entity->open = XML_TRUE;
2881 context = getContext(parser);
2882 entity->open = XML_FALSE;
2883 if (! context)
2884 return XML_ERROR_NO_MEMORY;
2885 if (! parser->m_externalEntityRefHandler(
2886 parser->m_externalEntityRefHandlerArg, context, entity->base,
2887 entity->systemId, entity->publicId))
2889 poolDiscard(&parser->m_tempPool);
2890 } else if (parser->m_defaultHandler)
2891 reportDefault(parser, enc, s, next);
2892 break;
2893 }
2895 /* fall through */
2897 TAG *tag;
2898 enum XML_Error result;
2899 XML_Char *toPtr;
2900 if (parser->m_freeTagList) {
2901 tag = parser->m_freeTagList;
2902 parser->m_freeTagList = parser->m_freeTagList->parent;
2903 } else {
2904 tag = (TAG *)MALLOC(parser, sizeof(TAG));
2905 if (! tag)
2906 return XML_ERROR_NO_MEMORY;
2907 tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
2908 if (! tag->buf) {
2909 FREE(parser, tag);
2910 return XML_ERROR_NO_MEMORY;
2911 }
2913 }
2914 tag->bindings = NULL;
2915 tag->parent = parser->m_tagStack;
2916 parser->m_tagStack = tag;
2917 tag->name.localPart = NULL;
2918 tag->name.prefix = NULL;
2919 tag->rawName = s + enc->minBytesPerChar;
2921 ++parser->m_tagLevel;
2922 {
2923 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2924 const char *fromPtr = tag->rawName;
2925 toPtr = (XML_Char *)tag->buf;
2926 for (;;) {
2927 int bufSize;
2928 int convLen;
2929 const enum XML_Convert_Result convert_res
2930 = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr,
2931 (ICHAR *)tag->bufEnd - 1);
2932 convLen = (int)(toPtr - (XML_Char *)tag->buf);
2933 if ((fromPtr >= rawNameEnd)
2934 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
2935 tag->name.strLen = convLen;
2936 break;
2937 }
2938 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2939 {
2940 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
2941 if (temp == NULL)
2942 return XML_ERROR_NO_MEMORY;
2943 tag->buf = temp;
2944 tag->bufEnd = temp + bufSize;
2945 toPtr = (XML_Char *)temp + convLen;
2946 }
2947 }
2948 }
2949 tag->name.str = (XML_Char *)tag->buf;
2950 *toPtr = XML_T('\0');
2951 result
2952 = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account);
2953 if (result)
2954 return result;
2955 if (parser->m_startElementHandler)
2956 parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
2957 (const XML_Char **)parser->m_atts);
2958 else if (parser->m_defaultHandler)
2959 reportDefault(parser, enc, s, next);
2960 poolClear(&parser->m_tempPool);
2961 break;
2962 }
2964 /* fall through */
2966 const char *rawName = s + enc->minBytesPerChar;
2967 enum XML_Error result;
2968 BINDING *bindings = NULL;
2969 XML_Bool noElmHandlers = XML_TRUE;
2970 TAG_NAME name;
2971 name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
2972 rawName + XmlNameLength(enc, rawName));
2973 if (! name.str)
2974 return XML_ERROR_NO_MEMORY;
2975 poolFinish(&parser->m_tempPool);
2976 result = storeAtts(parser, enc, s, &name, &bindings,
2977 XML_ACCOUNT_NONE /* token spans whole start tag */);
2978 if (result != XML_ERROR_NONE) {
2979 freeBindings(parser, bindings);
2980 return result;
2981 }
2982 poolFinish(&parser->m_tempPool);
2983 if (parser->m_startElementHandler) {
2984 parser->m_startElementHandler(parser->m_handlerArg, name.str,
2985 (const XML_Char **)parser->m_atts);
2986 noElmHandlers = XML_FALSE;
2987 }
2988 if (parser->m_endElementHandler) {
2989 if (parser->m_startElementHandler)
2990 *eventPP = *eventEndPP;
2991 parser->m_endElementHandler(parser->m_handlerArg, name.str);
2992 noElmHandlers = XML_FALSE;
2993 }
2994 if (noElmHandlers && parser->m_defaultHandler)
2995 reportDefault(parser, enc, s, next);
2996 poolClear(&parser->m_tempPool);
2997 freeBindings(parser, bindings);
2998 }
2999 if ((parser->m_tagLevel == 0)
3000 && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
3001 if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
3002 parser->m_processor = epilogProcessor;
3003 else
3004 return epilogProcessor(parser, next, end, nextPtr);
3005 }
3006 break;
3007 case XML_TOK_END_TAG:
3008 if (parser->m_tagLevel == startTagLevel)
3010 else {
3011 int len;
3012 const char *rawName;
3013 TAG *tag = parser->m_tagStack;
3014 parser->m_tagStack = tag->parent;
3015 tag->parent = parser->m_freeTagList;
3016 parser->m_freeTagList = tag;
3017 rawName = s + enc->minBytesPerChar * 2;
3018 len = XmlNameLength(enc, rawName);
3019 if (len != tag->rawNameLength
3020 || memcmp(tag->rawName, rawName, len) != 0) {
3021 *eventPP = rawName;
3023 }
3024 --parser->m_tagLevel;
3025 if (parser->m_endElementHandler) {
3026 const XML_Char *localPart;
3027 const XML_Char *prefix;
3028 XML_Char *uri;
3029 localPart = tag->name.localPart;
3030 if (parser->m_ns && localPart) {
3031 /* localPart and prefix may have been overwritten in
3032 tag->name.str, since this points to the binding->uri
3033 buffer which gets re-used; so we have to add them again
3034 */
3035 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
3036 /* don't need to check for space - already done in storeAtts() */
3037 while (*localPart)
3038 *uri++ = *localPart++;
3040 if (parser->m_ns_triplets && prefix) {
3041 *uri++ = parser->m_namespaceSeparator;
3042 while (*prefix)
3043 *uri++ = *prefix++;
3044 }
3045 *uri = XML_T('\0');
3046 }
3047 parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
3048 } else if (parser->m_defaultHandler)
3049 reportDefault(parser, enc, s, next);
3050 while (tag->bindings) {
3051 BINDING *b = tag->bindings;
3052 if (parser->m_endNamespaceDeclHandler)
3054 b->prefix->name);
3056 b->nextTagBinding = parser->m_freeBindingList;
3057 parser->m_freeBindingList = b;
3059 }
3060 if ((parser->m_tagLevel == 0)
3061 && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
3062 if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
3063 parser->m_processor = epilogProcessor;
3064 else
3065 return epilogProcessor(parser, next, end, nextPtr);
3066 }
3067 }
3068 break;
3069 case XML_TOK_CHAR_REF: {
3070 int n = XmlCharRefNumber(enc, s);
3071 if (n < 0)
3073 if (parser->m_characterDataHandler) {
3075 parser->m_characterDataHandler(parser->m_handlerArg, buf,
3076 XmlEncode(n, (ICHAR *)buf));
3077 } else if (parser->m_defaultHandler)
3078 reportDefault(parser, enc, s, next);
3079 } break;
3080 case XML_TOK_XML_DECL:
3083 if (parser->m_characterDataHandler) {
3084 XML_Char c = 0xA;
3085 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
3086 } else if (parser->m_defaultHandler)
3087 reportDefault(parser, enc, s, next);
3088 break;
3090 enum XML_Error result;
3091 if (parser->m_startCdataSectionHandler)
3093 /* BEGIN disabled code */
3094 /* Suppose you doing a transformation on a document that involves
3095 changing only the character data. You set up a defaultHandler
3096 and a characterDataHandler. The defaultHandler simply copies
3097 characters through. The characterDataHandler does the
3098 transformation and writes the characters out escaping them as
3099 necessary. This case will fail to work if we leave out the
3100 following two lines (because & and < inside CDATA sections will
3101 be incorrectly escaped).
3102
3103 However, now we have a start/endCdataSectionHandler, so it seems
3104 easier to let the user deal with this.
3105 */
3106 else if (0 && parser->m_characterDataHandler)
3107 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3108 0);
3109 /* END disabled code */
3110 else if (parser->m_defaultHandler)
3111 reportDefault(parser, enc, s, next);
3112 result
3113 = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account);
3114 if (result != XML_ERROR_NONE)
3115 return result;
3116 else if (! next) {
3117 parser->m_processor = cdataSectionProcessor;
3118 return result;
3119 }
3120 } break;
3122 if (haveMore) {
3123 *nextPtr = s;
3124 return XML_ERROR_NONE;
3125 }
3126 if (parser->m_characterDataHandler) {
3127 if (MUST_CONVERT(enc, s)) {
3128 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3129 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3130 parser->m_characterDataHandler(
3131 parser->m_handlerArg, parser->m_dataBuf,
3132 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
3133 } else
3134 parser->m_characterDataHandler(
3135 parser->m_handlerArg, (XML_Char *)s,
3136 (int)((XML_Char *)end - (XML_Char *)s));
3137 } else if (parser->m_defaultHandler)
3138 reportDefault(parser, enc, s, end);
3139 /* We are at the end of the final buffer, should we check for
3140 XML_SUSPENDED, XML_FINISHED?
3141 */
3142 if (startTagLevel == 0) {
3143 *eventPP = end;
3144 return XML_ERROR_NO_ELEMENTS;
3145 }
3146 if (parser->m_tagLevel != startTagLevel) {
3147 *eventPP = end;
3149 }
3150 *nextPtr = end;
3151 return XML_ERROR_NONE;
3152 case XML_TOK_DATA_CHARS: {
3153 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
3154 if (charDataHandler) {
3155 if (MUST_CONVERT(enc, s)) {
3156 for (;;) {
3157 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3158 const enum XML_Convert_Result convert_res = XmlConvert(
3159 enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3160 *eventEndPP = s;
3161 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3162 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
3163 if ((convert_res == XML_CONVERT_COMPLETED)
3164 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3165 break;
3166 *eventPP = s;
3167 }
3168 } else
3169 charDataHandler(parser->m_handlerArg, (XML_Char *)s,
3170 (int)((XML_Char *)next - (XML_Char *)s));
3171 } else if (parser->m_defaultHandler)
3172 reportDefault(parser, enc, s, next);
3173 } break;
3174 case XML_TOK_PI:
3175 if (! reportProcessingInstruction(parser, enc, s, next))
3176 return XML_ERROR_NO_MEMORY;
3177 break;
3178 case XML_TOK_COMMENT:
3179 if (! reportComment(parser, enc, s, next))
3180 return XML_ERROR_NO_MEMORY;
3181 break;
3182 default:
3183 /* All of the tokens produced by XmlContentTok() have their own
3184 * explicit cases, so this default is not strictly necessary.
3185 * However it is a useful safety net, so we retain the code and
3186 * simply exclude it from the coverage tests.
3187 *
3188 * LCOV_EXCL_START
3189 */
3190 if (parser->m_defaultHandler)
3191 reportDefault(parser, enc, s, next);
3192 break;
3193 /* LCOV_EXCL_STOP */
3194 }
3195 *eventPP = s = next;
3196 switch (parser->m_parsingStatus.parsing) {
3197 case XML_SUSPENDED:
3198 *nextPtr = next;
3199 return XML_ERROR_NONE;
3200 case XML_FINISHED:
3201 return XML_ERROR_ABORTED;
3202 default:;
3203 }
3204 }
3205 /* not reached */
3206}
3207
3208/* This function does not call free() on the allocated memory, merely
3209 * moving it to the parser's m_freeBindingList where it can be freed or
3210 * reused as appropriate.
3211 */
3212static void
3213freeBindings(XML_Parser parser, BINDING *bindings) {
3214 while (bindings) {
3215 BINDING *b = bindings;
3216
3217 /* m_startNamespaceDeclHandler will have been called for this
3218 * binding in addBindings(), so call the end handler now.
3219 */
3220 if (parser->m_endNamespaceDeclHandler)
3221 parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
3222
3223 bindings = bindings->nextTagBinding;
3224 b->nextTagBinding = parser->m_freeBindingList;
3225 parser->m_freeBindingList = b;
3227 }
3228}
3229
3230/* Precondition: all arguments must be non-NULL;
3231 Purpose:
3232 - normalize attributes
3233 - check attributes for well-formedness
3234 - generate namespace aware attribute names (URI, prefix)
3235 - build list of attributes for startElementHandler
3236 - default attributes
3237 - process namespace declarations (check and report them)
3238 - generate namespace aware element name (URI, prefix)
3239*/
3240static enum XML_Error
3241storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
3242 TAG_NAME *tagNamePtr, BINDING **bindingsPtr,
3243 enum XML_Account account) {
3244 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
3245 ELEMENT_TYPE *elementType;
3246 int nDefaultAtts;
3247 const XML_Char **appAtts; /* the attribute list for the application */
3248 int attIndex = 0;
3249 int prefixLen;
3250 int i;
3251 int n;
3252 XML_Char *uri;
3253 int nPrefixes = 0;
3255 const XML_Char *localPart;
3256
3257 /* lookup the element type name */
3258 elementType
3259 = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str, 0);
3260 if (! elementType) {
3261 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
3262 if (! name)
3263 return XML_ERROR_NO_MEMORY;
3264 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
3265 sizeof(ELEMENT_TYPE));
3266 if (! elementType)
3267 return XML_ERROR_NO_MEMORY;
3268 if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
3269 return XML_ERROR_NO_MEMORY;
3270 }
3271 nDefaultAtts = elementType->nDefaultAtts;
3272
3273 /* get the attributes from the tokenizer */
3274 n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
3275
3276 /* Detect and prevent integer overflow */
3277 if (n > INT_MAX - nDefaultAtts) {
3278 return XML_ERROR_NO_MEMORY;
3279 }
3280
3281 if (n + nDefaultAtts > parser->m_attsSize) {
3282 int oldAttsSize = parser->m_attsSize;
3283 ATTRIBUTE *temp;
3284#ifdef XML_ATTR_INFO
3285 XML_AttrInfo *temp2;
3286#endif
3287
3288 /* Detect and prevent integer overflow */
3289 if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE)
3290 || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
3291 return XML_ERROR_NO_MEMORY;
3292 }
3293
3294 parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
3295
3296 /* Detect and prevent integer overflow.
3297 * The preprocessor guard addresses the "always false" warning
3298 * from -Wtype-limits on platforms where
3299 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3300#if UINT_MAX >= SIZE_MAX
3301 if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) {
3302 parser->m_attsSize = oldAttsSize;
3303 return XML_ERROR_NO_MEMORY;
3304 }
3305#endif
3306
3307 temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
3308 parser->m_attsSize * sizeof(ATTRIBUTE));
3309 if (temp == NULL) {
3310 parser->m_attsSize = oldAttsSize;
3311 return XML_ERROR_NO_MEMORY;
3312 }
3313 parser->m_atts = temp;
3314#ifdef XML_ATTR_INFO
3315 /* Detect and prevent integer overflow.
3316 * The preprocessor guard addresses the "always false" warning
3317 * from -Wtype-limits on platforms where
3318 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3319# if UINT_MAX >= SIZE_MAX
3320 if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) {
3321 parser->m_attsSize = oldAttsSize;
3322 return XML_ERROR_NO_MEMORY;
3323 }
3324# endif
3325
3326 temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
3327 parser->m_attsSize * sizeof(XML_AttrInfo));
3328 if (temp2 == NULL) {
3329 parser->m_attsSize = oldAttsSize;
3330 return XML_ERROR_NO_MEMORY;
3331 }
3332 parser->m_attInfo = temp2;
3333#endif
3334 if (n > oldAttsSize)
3335 XmlGetAttributes(enc, attStr, n, parser->m_atts);
3336 }
3337
3338 appAtts = (const XML_Char **)parser->m_atts;
3339 for (i = 0; i < n; i++) {
3340 ATTRIBUTE *currAtt = &parser->m_atts[i];
3341#ifdef XML_ATTR_INFO
3342 XML_AttrInfo *currAttInfo = &parser->m_attInfo[i];
3343#endif
3344 /* add the name and value to the attribute list */
3345 ATTRIBUTE_ID *attId
3346 = getAttributeId(parser, enc, currAtt->name,
3347 currAtt->name + XmlNameLength(enc, currAtt->name));
3348 if (! attId)
3349 return XML_ERROR_NO_MEMORY;
3350#ifdef XML_ATTR_INFO
3351 currAttInfo->nameStart
3352 = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name);
3353 currAttInfo->nameEnd
3354 = currAttInfo->nameStart + XmlNameLength(enc, currAtt->name);
3355 currAttInfo->valueStart = parser->m_parseEndByteIndex
3356 - (parser->m_parseEndPtr - currAtt->valuePtr);
3357 currAttInfo->valueEnd = parser->m_parseEndByteIndex
3358 - (parser->m_parseEndPtr - currAtt->valueEnd);
3359#endif
3360 /* Detect duplicate attributes by their QNames. This does not work when
3361 namespace processing is turned on and different prefixes for the same
3362 namespace are used. For this case we have a check further down.
3363 */
3364 if ((attId->name)[-1]) {
3365 if (enc == parser->m_encoding)
3366 parser->m_eventPtr = parser->m_atts[i].name;
3368 }
3369 (attId->name)[-1] = 1;
3370 appAtts[attIndex++] = attId->name;
3371 if (! parser->m_atts[i].normalized) {
3372 enum XML_Error result;
3373 XML_Bool isCdata = XML_TRUE;
3374
3375 /* figure out whether declared as other than CDATA */
3376 if (attId->maybeTokenized) {
3377 int j;
3378 for (j = 0; j < nDefaultAtts; j++) {
3379 if (attId == elementType->defaultAtts[j].id) {
3380 isCdata = elementType->defaultAtts[j].isCdata;
3381 break;
3382 }
3383 }
3384 }
3385
3386 /* normalize the attribute value */
3387 result = storeAttributeValue(
3388 parser, enc, isCdata, parser->m_atts[i].valuePtr,
3389 parser->m_atts[i].valueEnd, &parser->m_tempPool, account);
3390 if (result)
3391 return result;
3392 appAtts[attIndex] = poolStart(&parser->m_tempPool);
3393 poolFinish(&parser->m_tempPool);
3394 } else {
3395 /* the value did not need normalizing */
3396 appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc,
3397 parser->m_atts[i].valuePtr,
3398 parser->m_atts[i].valueEnd);
3399 if (appAtts[attIndex] == 0)
3400 return XML_ERROR_NO_MEMORY;
3401 poolFinish(&parser->m_tempPool);
3402 }
3403 /* handle prefixed attribute names */
3404 if (attId->prefix) {
3405 if (attId->xmlns) {
3406 /* deal with namespace declarations here */
3407 enum XML_Error result = addBinding(parser, attId->prefix, attId,
3408 appAtts[attIndex], bindingsPtr);
3409 if (result)
3410 return result;
3411 --attIndex;
3412 } else {
3413 /* deal with other prefixed names later */
3414 attIndex++;
3415 nPrefixes++;
3416 (attId->name)[-1] = 2;
3417 }
3418 } else
3419 attIndex++;
3420 }
3421
3422 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
3423 parser->m_nSpecifiedAtts = attIndex;
3424 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
3425 for (i = 0; i < attIndex; i += 2)
3426 if (appAtts[i] == elementType->idAtt->name) {
3427 parser->m_idAttIndex = i;
3428 break;
3429 }
3430 } else
3431 parser->m_idAttIndex = -1;
3432
3433 /* do attribute defaulting */
3434 for (i = 0; i < nDefaultAtts; i++) {
3435 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
3436 if (! (da->id->name)[-1] && da->value) {
3437 if (da->id->prefix) {
3438 if (da->id->xmlns) {
3439 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
3440 da->value, bindingsPtr);
3441 if (result)
3442 return result;
3443 } else {
3444 (da->id->name)[-1] = 2;
3445 nPrefixes++;
3446 appAtts[attIndex++] = da->id->name;
3447 appAtts[attIndex++] = da->value;
3448 }
3449 } else {
3450 (da->id->name)[-1] = 1;
3451 appAtts[attIndex++] = da->id->name;
3452 appAtts[attIndex++] = da->value;
3453 }
3454 }
3455 }
3456 appAtts[attIndex] = 0;
3457
3458 /* expand prefixed attribute names, check for duplicates,
3459 and clear flags that say whether attributes were specified */
3460 i = 0;
3461 if (nPrefixes) {
3462 int j; /* hash table index */
3463 unsigned long version = parser->m_nsAttsVersion;
3464
3465 /* Detect and prevent invalid shift */
3466 if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
3467 return XML_ERROR_NO_MEMORY;
3468 }
3469
3470 unsigned int nsAttsSize = 1u << parser->m_nsAttsPower;
3471 unsigned char oldNsAttsPower = parser->m_nsAttsPower;
3472 /* size of hash table must be at least 2 * (# of prefixed attributes) */
3473 if ((nPrefixes << 1)
3474 >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
3475 NS_ATT *temp;
3476 /* hash table size must also be a power of 2 and >= 8 */
3477 while (nPrefixes >> parser->m_nsAttsPower++)
3478 ;
3479 if (parser->m_nsAttsPower < 3)
3480 parser->m_nsAttsPower = 3;
3481
3482 /* Detect and prevent invalid shift */
3483 if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) {
3484 /* Restore actual size of memory in m_nsAtts */
3485 parser->m_nsAttsPower = oldNsAttsPower;
3486 return XML_ERROR_NO_MEMORY;
3487 }
3488
3489 nsAttsSize = 1u << parser->m_nsAttsPower;
3490
3491 /* Detect and prevent integer overflow.
3492 * The preprocessor guard addresses the "always false" warning
3493 * from -Wtype-limits on platforms where
3494 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3495#if UINT_MAX >= SIZE_MAX
3496 if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) {
3497 /* Restore actual size of memory in m_nsAtts */
3498 parser->m_nsAttsPower = oldNsAttsPower;
3499 return XML_ERROR_NO_MEMORY;
3500 }
3501#endif
3502
3503 temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
3504 nsAttsSize * sizeof(NS_ATT));
3505 if (! temp) {
3506 /* Restore actual size of memory in m_nsAtts */
3507 parser->m_nsAttsPower = oldNsAttsPower;
3508 return XML_ERROR_NO_MEMORY;
3509 }
3510 parser->m_nsAtts = temp;
3511 version = 0; /* force re-initialization of m_nsAtts hash table */
3512 }
3513 /* using a version flag saves us from initializing m_nsAtts every time */
3514 if (! version) { /* initialize version flags when version wraps around */
3515 version = INIT_ATTS_VERSION;
3516 for (j = nsAttsSize; j != 0;)
3517 parser->m_nsAtts[--j].version = version;
3518 }
3519 parser->m_nsAttsVersion = --version;
3520
3521 /* expand prefixed names and check for duplicates */
3522 for (; i < attIndex; i += 2) {
3523 const XML_Char *s = appAtts[i];
3524 if (s[-1] == 2) { /* prefixed */
3525 ATTRIBUTE_ID *id;
3526 const BINDING *b;
3527 unsigned long uriHash;
3528 struct siphash sip_state;
3529 struct sipkey sip_key;
3530
3531 copy_salt_to_sipkey(parser, &sip_key);
3532 sip24_init(&sip_state, &sip_key);
3533
3534 ((XML_Char *)s)[-1] = 0; /* clear flag */
3535 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
3536 if (! id || ! id->prefix) {
3537 /* This code is walking through the appAtts array, dealing
3538 * with (in this case) a prefixed attribute name. To be in
3539 * the array, the attribute must have already been bound, so
3540 * has to have passed through the hash table lookup once
3541 * already. That implies that an entry for it already
3542 * exists, so the lookup above will return a pointer to
3543 * already allocated memory. There is no opportunaity for
3544 * the allocator to fail, so the condition above cannot be
3545 * fulfilled.
3546 *
3547 * Since it is difficult to be certain that the above
3548 * analysis is complete, we retain the test and merely
3549 * remove the code from coverage tests.
3550 */
3551 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
3552 }
3553 b = id->prefix->binding;
3554 if (! b)
3556
3557 for (j = 0; j < b->uriLen; j++) {
3558 const XML_Char c = b->uri[j];
3559 if (! poolAppendChar(&parser->m_tempPool, c))
3560 return XML_ERROR_NO_MEMORY;
3561 }
3562
3563 sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
3564
3565 while (*s++ != XML_T(ASCII_COLON))
3566 ;
3567
3568 sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
3569
3570 do { /* copies null terminator */
3571 if (! poolAppendChar(&parser->m_tempPool, *s))
3572 return XML_ERROR_NO_MEMORY;
3573 } while (*s++);
3574
3575 uriHash = (unsigned long)sip24_final(&sip_state);
3576
3577 { /* Check hash table for duplicate of expanded name (uriName).
3578 Derived from code in lookup(parser, HASH_TABLE *table, ...).
3579 */
3580 unsigned char step = 0;
3581 unsigned long mask = nsAttsSize - 1;
3582 j = uriHash & mask; /* index into hash table */
3583 while (parser->m_nsAtts[j].version == version) {
3584 /* for speed we compare stored hash values first */
3585 if (uriHash == parser->m_nsAtts[j].hash) {
3586 const XML_Char *s1 = poolStart(&parser->m_tempPool);
3587 const XML_Char *s2 = parser->m_nsAtts[j].uriName;
3588 /* s1 is null terminated, but not s2 */
3589 for (; *s1 == *s2 && *s1 != 0; s1++, s2++)
3590 ;
3591 if (*s1 == 0)
3593 }
3594 if (! step)
3595 step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower);
3596 j < step ? (j += nsAttsSize - step) : (j -= step);
3597 }
3598 }
3599
3600 if (parser->m_ns_triplets) { /* append namespace separator and prefix */
3601 parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator;
3602 s = b->prefix->name;
3603 do {
3604 if (! poolAppendChar(&parser->m_tempPool, *s))
3605 return XML_ERROR_NO_MEMORY;
3606 } while (*s++);
3607 }
3608
3609 /* store expanded name in attribute list */
3610 s = poolStart(&parser->m_tempPool);
3611 poolFinish(&parser->m_tempPool);
3612 appAtts[i] = s;
3613
3614 /* fill empty slot with new version, uriName and hash value */
3615 parser->m_nsAtts[j].version = version;
3616 parser->m_nsAtts[j].hash = uriHash;
3617 parser->m_nsAtts[j].uriName = s;
3618
3619 if (! --nPrefixes) {
3620 i += 2;
3621 break;
3622 }
3623 } else /* not prefixed */
3624 ((XML_Char *)s)[-1] = 0; /* clear flag */
3625 }
3626 }
3627 /* clear flags for the remaining attributes */
3628 for (; i < attIndex; i += 2)
3629 ((XML_Char *)(appAtts[i]))[-1] = 0;
3630 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3631 binding->attId->name[-1] = 0;
3632
3633 if (! parser->m_ns)
3634 return XML_ERROR_NONE;
3635
3636 /* expand the element type name */
3637 if (elementType->prefix) {
3638 binding = elementType->prefix->binding;
3639 if (! binding)
3641 localPart = tagNamePtr->str;
3642 while (*localPart++ != XML_T(ASCII_COLON))
3643 ;
3644 } else if (dtd->defaultPrefix.binding) {
3646 localPart = tagNamePtr->str;
3647 } else
3648 return XML_ERROR_NONE;
3649 prefixLen = 0;
3650 if (parser->m_ns_triplets && binding->prefix->name) {
3651 for (; binding->prefix->name[prefixLen++];)
3652 ; /* prefixLen includes null terminator */
3653 }
3654 tagNamePtr->localPart = localPart;
3655 tagNamePtr->uriLen = binding->uriLen;
3656 tagNamePtr->prefix = binding->prefix->name;
3657 tagNamePtr->prefixLen = prefixLen;
3658 for (i = 0; localPart[i++];)
3659 ; /* i includes null terminator */
3660
3661 /* Detect and prevent integer overflow */
3662 if (binding->uriLen > INT_MAX - prefixLen
3663 || i > INT_MAX - (binding->uriLen + prefixLen)) {
3664 return XML_ERROR_NO_MEMORY;
3665 }
3666
3667 n = i + binding->uriLen + prefixLen;
3668 if (n > binding->uriAlloc) {
3669 TAG *p;
3670
3671 /* Detect and prevent integer overflow */
3672 if (n > INT_MAX - EXPAND_SPARE) {
3673 return XML_ERROR_NO_MEMORY;
3674 }
3675 /* Detect and prevent integer overflow.
3676 * The preprocessor guard addresses the "always false" warning
3677 * from -Wtype-limits on platforms where
3678 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3679#if UINT_MAX >= SIZE_MAX
3680 if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
3681 return XML_ERROR_NO_MEMORY;
3682 }
3683#endif
3684
3685 uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
3686 if (! uri)
3687 return XML_ERROR_NO_MEMORY;
3689 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
3690 for (p = parser->m_tagStack; p; p = p->parent)
3691 if (p->name.str == binding->uri)
3692 p->name.str = uri;
3693 FREE(parser, binding->uri);
3694 binding->uri = uri;
3695 }
3696 /* if m_namespaceSeparator != '\0' then uri includes it already */
3697 uri = binding->uri + binding->uriLen;
3698 memcpy(uri, localPart, i * sizeof(XML_Char));
3699 /* we always have a namespace separator between localPart and prefix */
3700 if (prefixLen) {
3701 uri += i - 1;
3702 *uri = parser->m_namespaceSeparator; /* replace null terminator */
3703 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3704 }
3705 tagNamePtr->str = binding->uri;
3706 return XML_ERROR_NONE;
3707}
3708
3709static XML_Bool
3710is_rfc3986_uri_char(XML_Char candidate) {
3711 // For the RFC 3986 ANBF grammar see
3712 // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A
3713
3714 switch (candidate) {
3715 // From rule "ALPHA" (uppercase half)
3716 case 'A':
3717 case 'B':
3718 case 'C':
3719 case 'D':
3720 case 'E':
3721 case 'F':
3722 case 'G':
3723 case 'H':
3724 case 'I':
3725 case 'J':
3726 case 'K':
3727 case 'L':
3728 case 'M':
3729 case 'N':
3730 case 'O':
3731 case 'P':
3732 case 'Q':
3733 case 'R':
3734 case 'S':
3735 case 'T':
3736 case 'U':
3737 case 'V':
3738 case 'W':
3739 case 'X':
3740 case 'Y':
3741 case 'Z':
3742
3743 // From rule "ALPHA" (lowercase half)
3744 case 'a':
3745 case 'b':
3746 case 'c':
3747 case 'd':
3748 case 'e':
3749 case 'f':
3750 case 'g':
3751 case 'h':
3752 case 'i':
3753 case 'j':
3754 case 'k':
3755 case 'l':
3756 case 'm':
3757 case 'n':
3758 case 'o':
3759 case 'p':
3760 case 'q':
3761 case 'r':
3762 case 's':
3763 case 't':
3764 case 'u':
3765 case 'v':
3766 case 'w':
3767 case 'x':
3768 case 'y':
3769 case 'z':
3770
3771 // From rule "DIGIT"
3772 case '0':
3773 case '1':
3774 case '2':
3775 case '3':
3776 case '4':
3777 case '5':
3778 case '6':
3779 case '7':
3780 case '8':
3781 case '9':
3782
3783 // From rule "pct-encoded"
3784 case '%':
3785
3786 // From rule "unreserved"
3787 case '-':
3788 case '.':
3789 case '_':
3790 case '~':
3791
3792 // From rule "gen-delims"
3793 case ':':
3794 case '/':
3795 case '?':
3796 case '#':
3797 case '[':
3798 case ']':
3799 case '@':
3800
3801 // From rule "sub-delims"
3802 case '!':
3803 case '$':
3804 case '&':
3805 case '\'':
3806 case '(':
3807 case ')':
3808 case '*':
3809 case '+':
3810 case ',':
3811 case ';':
3812 case '=':
3813 return XML_TRUE;
3814
3815 default:
3816 return XML_FALSE;
3817 }
3818}
3819
3820/* addBinding() overwrites the value of prefix->binding without checking.
3821 Therefore one must keep track of the old value outside of addBinding().
3822*/
3823static enum XML_Error
3824addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3825 const XML_Char *uri, BINDING **bindingsPtr) {
3826 // "http://www.w3.org/XML/1998/namespace"
3827 static const XML_Char xmlNamespace[]
3835 ASCII_e, '\0'};
3836 static const int xmlLen = (int)sizeof(xmlNamespace) / sizeof(XML_Char) - 1;
3837 // "http://www.w3.org/2000/xmlns/"
3838 static const XML_Char xmlnsNamespace[]
3844 static const int xmlnsLen
3845 = (int)sizeof(xmlnsNamespace) / sizeof(XML_Char) - 1;
3846
3847 XML_Bool mustBeXML = XML_FALSE;
3848 XML_Bool isXML = XML_TRUE;
3849 XML_Bool isXMLNS = XML_TRUE;
3850
3851 BINDING *b;
3852 int len;
3853
3854 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3855 if (*uri == XML_T('\0') && prefix->name)
3857
3858 if (prefix->name && prefix->name[0] == XML_T(ASCII_x)
3859 && prefix->name[1] == XML_T(ASCII_m)
3860 && prefix->name[2] == XML_T(ASCII_l)) {
3861 /* Not allowed to bind xmlns */
3862 if (prefix->name[3] == XML_T(ASCII_n) && prefix->name[4] == XML_T(ASCII_s)
3863 && prefix->name[5] == XML_T('\0'))
3865
3866 if (prefix->name[3] == XML_T('\0'))
3867 mustBeXML = XML_TRUE;
3868 }
3869
3870 for (len = 0; uri[len]; len++) {
3871 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3872 isXML = XML_FALSE;
3873
3874 if (! mustBeXML && isXMLNS
3875 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3876 isXMLNS = XML_FALSE;
3877
3878 // NOTE: While Expat does not validate namespace URIs against RFC 3986
3879 // today (and is not REQUIRED to do so with regard to the XML 1.0
3880 // namespaces specification) we have to at least make sure, that
3881 // the application on top of Expat (that is likely splitting expanded
3882 // element names ("qualified names") of form
3883 // "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces
3884 // in its element handler code) cannot be confused by an attacker
3885 // putting additional namespace separator characters into namespace
3886 // declarations. That would be ambiguous and not to be expected.
3887 //
3888 // While the HTML API docs of function XML_ParserCreateNS have been
3889 // advising against use of a namespace separator character that can
3890 // appear in a URI for >20 years now, some widespread applications
3891 // are using URI characters (':' (colon) in particular) for a
3892 // namespace separator, in practice. To keep these applications
3893 // functional, we only reject namespaces URIs containing the
3894 // application-chosen namespace separator if the chosen separator
3895 // is a non-URI character with regard to RFC 3986.
3896 if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)
3897 && ! is_rfc3986_uri_char(uri[len])) {
3898 return XML_ERROR_SYNTAX;
3899 }
3900 }
3901 isXML = isXML && len == xmlLen;
3902 isXMLNS = isXMLNS && len == xmlnsLen;
3903
3904 if (mustBeXML != isXML)
3905 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3907
3908 if (isXMLNS)
3910
3911 if (parser->m_namespaceSeparator)
3912 len++;
3913 if (parser->m_freeBindingList) {
3914 b = parser->m_freeBindingList;
3915 if (len > b->uriAlloc) {
3916 /* Detect and prevent integer overflow */
3917 if (len > INT_MAX - EXPAND_SPARE) {
3918 return XML_ERROR_NO_MEMORY;
3919 }
3920
3921 /* Detect and prevent integer overflow.
3922 * The preprocessor guard addresses the "always false" warning
3923 * from -Wtype-limits on platforms where
3924 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3925#if UINT_MAX >= SIZE_MAX
3926 if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
3927 return XML_ERROR_NO_MEMORY;
3928 }
3929#endif
3930
3931 XML_Char *temp = (XML_Char *)REALLOC(
3932 parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
3933 if (temp == NULL)
3934 return XML_ERROR_NO_MEMORY;
3935 b->uri = temp;
3936 b->uriAlloc = len + EXPAND_SPARE;
3937 }
3938 parser->m_freeBindingList = b->nextTagBinding;
3939 } else {
3940 b = (BINDING *)MALLOC(parser, sizeof(BINDING));
3941 if (! b)
3942 return XML_ERROR_NO_MEMORY;
3943
3944 /* Detect and prevent integer overflow */
3945 if (len > INT_MAX - EXPAND_SPARE) {
3946 return XML_ERROR_NO_MEMORY;
3947 }
3948 /* Detect and prevent integer overflow.
3949 * The preprocessor guard addresses the "always false" warning
3950 * from -Wtype-limits on platforms where
3951 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
3952#if UINT_MAX >= SIZE_MAX
3953 if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
3954 return XML_ERROR_NO_MEMORY;
3955 }
3956#endif
3957
3958 b->uri
3959 = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
3960 if (! b->uri) {
3961 FREE(parser, b);
3962 return XML_ERROR_NO_MEMORY;
3963 }
3964 b->uriAlloc = len + EXPAND_SPARE;
3965 }
3966 b->uriLen = len;
3967 memcpy(b->uri, uri, len * sizeof(XML_Char));
3968 if (parser->m_namespaceSeparator)
3969 b->uri[len - 1] = parser->m_namespaceSeparator;
3970 b->prefix = prefix;
3971 b->attId = attId;
3973 /* NULL binding when default namespace undeclared */
3974 if (*uri == XML_T('\0') && prefix == &parser->m_dtd->defaultPrefix)
3975 prefix->binding = NULL;
3976 else
3977 prefix->binding = b;
3978 b->nextTagBinding = *bindingsPtr;
3979 *bindingsPtr = b;
3980 /* if attId == NULL then we are not starting a namespace scope */
3981 if (attId && parser->m_startNamespaceDeclHandler)
3983 prefix->binding ? uri : 0);
3984 return XML_ERROR_NONE;
3985}
3986
3987/* The idea here is to avoid using stack for each CDATA section when
3988 the whole file is parsed with one call.
3989*/
3990static enum XML_Error PTRCALL
3991cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
3992 const char **endPtr) {
3993 enum XML_Error result = doCdataSection(
3994 parser, parser->m_encoding, &start, end, endPtr,
3996 if (result != XML_ERROR_NONE)
3997 return result;
3998 if (start) {
3999 if (parser->m_parentParser) { /* we are parsing an external entity */
4000 parser->m_processor = externalEntityContentProcessor;
4001 return externalEntityContentProcessor(parser, start, end, endPtr);
4002 } else {
4003 parser->m_processor = contentProcessor;
4004 return contentProcessor(parser, start, end, endPtr);
4005 }
4006 }
4007 return result;
4008}
4009
4010/* startPtr gets set to non-null if the section is closed, and to null if
4011 the section is not yet closed.
4012*/
4013static enum XML_Error
4014doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
4015 const char *end, const char **nextPtr, XML_Bool haveMore,
4016 enum XML_Account account) {
4017 const char *s = *startPtr;
4018 const char **eventPP;
4019 const char **eventEndPP;
4020 if (enc == parser->m_encoding) {
4021 eventPP = &parser->m_eventPtr;
4022 *eventPP = s;
4023 eventEndPP = &parser->m_eventEndPtr;
4024 } else {
4025 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4026 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
4027 }
4028 *eventPP = s;
4029 *startPtr = NULL;
4030
4031 for (;;) {
4032 const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
4033 int tok = XmlCdataSectionTok(enc, s, end, &next);
4034#ifdef XML_DTD
4035 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
4036 accountingOnAbort(parser);
4038 }
4039#else
4040 UNUSED_P(account);
4041#endif
4042 *eventEndPP = next;
4043 switch (tok) {
4045 if (parser->m_endCdataSectionHandler)
4046 parser->m_endCdataSectionHandler(parser->m_handlerArg);
4047 /* BEGIN disabled code */
4048 /* see comment under XML_TOK_CDATA_SECT_OPEN */
4049 else if (0 && parser->m_characterDataHandler)
4050 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
4051 0);
4052 /* END disabled code */
4053 else if (parser->m_defaultHandler)
4054 reportDefault(parser, enc, s, next);
4055 *startPtr = next;
4056 *nextPtr = next;
4057 if (parser->m_parsingStatus.parsing == XML_FINISHED)
4058 return XML_ERROR_ABORTED;
4059 else
4060 return XML_ERROR_NONE;
4062 if (parser->m_characterDataHandler) {
4063 XML_Char c = 0xA;
4064 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
4065 } else if (parser->m_defaultHandler)
4066 reportDefault(parser, enc, s, next);
4067 break;
4068 case XML_TOK_DATA_CHARS: {
4069 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
4070 if (charDataHandler) {
4071 if (MUST_CONVERT(enc, s)) {
4072 for (;;) {
4073 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
4074 const enum XML_Convert_Result convert_res = XmlConvert(
4075 enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
4076 *eventEndPP = next;
4077 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
4078 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
4079 if ((convert_res == XML_CONVERT_COMPLETED)
4080 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
4081 break;
4082 *eventPP = s;
4083 }
4084 } else
4085 charDataHandler(parser->m_handlerArg, (XML_Char *)s,
4086 (int)((XML_Char *)next - (XML_Char *)s));
4087 } else if (parser->m_defaultHandler)
4088 reportDefault(parser, enc, s, next);
4089 } break;
4090 case XML_TOK_INVALID:
4091 *eventPP = next;
4094 if (haveMore) {
4095 *nextPtr = s;
4096 return XML_ERROR_NONE;
4097 }
4099 case XML_TOK_PARTIAL:
4100 case XML_TOK_NONE:
4101 if (haveMore) {
4102 *nextPtr = s;
4103 return XML_ERROR_NONE;
4104 }
4106 default:
4107 /* Every token returned by XmlCdataSectionTok() has its own
4108 * explicit case, so this default case will never be executed.
4109 * We retain it as a safety net and exclude it from the coverage
4110 * statistics.
4111 *
4112 * LCOV_EXCL_START
4113 */
4114 *eventPP = next;
4116 /* LCOV_EXCL_STOP */
4117 }
4118
4119 *eventPP = s = next;
4120 switch (parser->m_parsingStatus.parsing) {
4121 case XML_SUSPENDED:
4122 *nextPtr = next;
4123 return XML_ERROR_NONE;
4124 case XML_FINISHED:
4125 return XML_ERROR_ABORTED;
4126 default:;
4127 }
4128 }
4129 /* not reached */
4130}
4131
4132#ifdef XML_DTD
4133
4134/* The idea here is to avoid using stack for each IGNORE section when
4135 the whole file is parsed with one call.
4136*/
4137static enum XML_Error PTRCALL
4138ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end,
4139 const char **endPtr) {
4140 enum XML_Error result
4141 = doIgnoreSection(parser, parser->m_encoding, &start, end, endPtr,
4143 if (result != XML_ERROR_NONE)
4144 return result;
4145 if (start) {
4146 parser->m_processor = prologProcessor;
4147 return prologProcessor(parser, start, end, endPtr);
4148 }
4149 return result;
4150}
4151
4152/* startPtr gets set to non-null is the section is closed, and to null
4153 if the section is not yet closed.
4154*/
4155static enum XML_Error
4156doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
4157 const char *end, const char **nextPtr, XML_Bool haveMore) {
4158 const char *next = *startPtr; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
4159 int tok;
4160 const char *s = *startPtr;
4161 const char **eventPP;
4162 const char **eventEndPP;
4163 if (enc == parser->m_encoding) {
4164 eventPP = &parser->m_eventPtr;
4165 *eventPP = s;
4166 eventEndPP = &parser->m_eventEndPtr;
4167 } else {
4168 /* It's not entirely clear, but it seems the following two lines
4169 * of code cannot be executed. The only occasions on which 'enc'
4170 * is not 'encoding' are when this function is called
4171 * from the internal entity processing, and IGNORE sections are an
4172 * error in internal entities.
4173 *
4174 * Since it really isn't clear that this is true, we keep the code
4175 * and just remove it from our coverage tests.
4176 *
4177 * LCOV_EXCL_START
4178 */
4179 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4180 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
4181 /* LCOV_EXCL_STOP */
4182 }
4183 *eventPP = s;
4184 *startPtr = NULL;
4185 tok = XmlIgnoreSectionTok(enc, s, end, &next);
4186# ifdef XML_DTD
4187 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
4189 accountingOnAbort(parser);
4191 }
4192# endif
4193 *eventEndPP = next;
4194 switch (tok) {
4195 case XML_TOK_IGNORE_SECT:
4196 if (parser->m_defaultHandler)
4197 reportDefault(parser, enc, s, next);
4198 *startPtr = next;
4199 *nextPtr = next;
4200 if (parser->m_parsingStatus.parsing == XML_FINISHED)
4201 return XML_ERROR_ABORTED;
4202 else
4203 return XML_ERROR_NONE;
4204 case XML_TOK_INVALID:
4205 *eventPP = next;
4208 if (haveMore) {
4209 *nextPtr = s;
4210 return XML_ERROR_NONE;
4211 }
4213 case XML_TOK_PARTIAL:
4214 case XML_TOK_NONE:
4215 if (haveMore) {
4216 *nextPtr = s;
4217 return XML_ERROR_NONE;
4218 }
4219 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
4220 default:
4221 /* All of the tokens that XmlIgnoreSectionTok() returns have
4222 * explicit cases to handle them, so this default case is never
4223 * executed. We keep it as a safety net anyway, and remove it
4224 * from our test coverage statistics.
4225 *
4226 * LCOV_EXCL_START
4227 */
4228 *eventPP = next;
4230 /* LCOV_EXCL_STOP */
4231 }
4232 /* not reached */
4233}
4234
4235#endif /* XML_DTD */
4236
4237static enum XML_Error
4238initializeEncoding(XML_Parser parser) {
4239 const char *s;
4240#ifdef XML_UNICODE
4241 char encodingBuf[128];
4242 /* See comments about `protocolEncodingName` in parserInit() */
4243 if (! parser->m_protocolEncodingName)
4244 s = NULL;
4245 else {
4246 int i;
4247 for (i = 0; parser->m_protocolEncodingName[i]; i++) {
4248 if (i == sizeof(encodingBuf) - 1
4249 || (parser->m_protocolEncodingName[i] & ~0x7f) != 0) {
4250 encodingBuf[0] = '\0';
4251 break;
4252 }
4253 encodingBuf[i] = (char)parser->m_protocolEncodingName[i];
4254 }
4255 encodingBuf[i] = '\0';
4256 s = encodingBuf;
4257 }
4258#else
4259 s = parser->m_protocolEncodingName;
4260#endif
4261 if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(
4262 &parser->m_initEncoding, &parser->m_encoding, s))
4263 return XML_ERROR_NONE;
4264 return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
4265}
4266
4267static enum XML_Error
4268processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
4269 const char *next) {
4270 const char *encodingName = NULL;
4271 const XML_Char *storedEncName = NULL;
4272 const ENCODING *newEncoding = NULL;
4273 const char *version = NULL;
4274 const char *versionend = NULL;
4275 const XML_Char *storedversion = NULL;
4276 int standalone = -1;
4277
4278#ifdef XML_DTD
4279 if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__,
4281 accountingOnAbort(parser);
4283 }
4284#endif
4285
4286 if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
4287 isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
4288 &version, &versionend, &encodingName, &newEncoding, &standalone)) {
4289 if (isGeneralTextEntity)
4290 return XML_ERROR_TEXT_DECL;
4291 else
4292 return XML_ERROR_XML_DECL;
4293 }
4294 if (! isGeneralTextEntity && standalone == 1) {
4295 parser->m_dtd->standalone = XML_TRUE;
4296#ifdef XML_DTD
4297 if (parser->m_paramEntityParsing
4299 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
4300#endif /* XML_DTD */
4301 }
4302 if (parser->m_xmlDeclHandler) {
4303 if (encodingName != NULL) {
4304 storedEncName = poolStoreString(
4305 &parser->m_temp2Pool, parser->m_encoding, encodingName,
4306 encodingName + XmlNameLength(parser->m_encoding, encodingName));
4307 if (! storedEncName)
4308 return XML_ERROR_NO_MEMORY;
4309 poolFinish(&parser->m_temp2Pool);
4310 }
4311 if (version) {
4312 storedversion
4313 = poolStoreString(&parser->m_temp2Pool, parser->m_encoding, version,
4314 versionend - parser->m_encoding->minBytesPerChar);
4315 if (! storedversion)
4316 return XML_ERROR_NO_MEMORY;
4317 }
4318 parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName,
4319 standalone);
4320 } else if (parser->m_defaultHandler)
4321 reportDefault(parser, parser->m_encoding, s, next);
4322 if (parser->m_protocolEncodingName == NULL) {
4323 if (newEncoding) {
4324 /* Check that the specified encoding does not conflict with what
4325 * the parser has already deduced. Do we have the same number
4326 * of bytes in the smallest representation of a character? If
4327 * this is UTF-16, is it the same endianness?
4328 */
4329 if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
4330 || (newEncoding->minBytesPerChar == 2
4331 && newEncoding != parser->m_encoding)) {
4332 parser->m_eventPtr = encodingName;
4334 }
4335 parser->m_encoding = newEncoding;
4336 } else if (encodingName) {
4337 enum XML_Error result;
4338 if (! storedEncName) {
4339 storedEncName = poolStoreString(
4340 &parser->m_temp2Pool, parser->m_encoding, encodingName,
4341 encodingName + XmlNameLength(parser->m_encoding, encodingName));
4342 if (! storedEncName)
4343 return XML_ERROR_NO_MEMORY;
4344 }
4345 result = handleUnknownEncoding(parser, storedEncName);
4346 poolClear(&parser->m_temp2Pool);
4347 if (result == XML_ERROR_UNKNOWN_ENCODING)
4348 parser->m_eventPtr = encodingName;
4349 return result;
4350 }
4351 }
4352
4353 if (storedEncName || storedversion)
4354 poolClear(&parser->m_temp2Pool);
4355
4356 return XML_ERROR_NONE;
4357}
4358
4359static enum XML_Error
4360handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) {
4361 if (parser->m_unknownEncodingHandler) {
4362 XML_Encoding info;
4363 int i;
4364 for (i = 0; i < 256; i++)
4365 info.map[i] = -1;
4366 info.convert = NULL;
4367 info.data = NULL;
4368 info.release = NULL;
4370 encodingName, &info)) {
4371 ENCODING *enc;
4373 if (! parser->m_unknownEncodingMem) {
4374 if (info.release)
4375 info.release(info.data);
4376 return XML_ERROR_NO_MEMORY;
4377 }
4379 parser->m_unknownEncodingMem, info.map, info.convert, info.data);
4380 if (enc) {
4381 parser->m_unknownEncodingData = info.data;
4382 parser->m_unknownEncodingRelease = info.release;
4383 parser->m_encoding = enc;
4384 return XML_ERROR_NONE;
4385 }
4386 }
4387 if (info.release != NULL)
4388 info.release(info.data);
4389 }
4391}
4392
4393static enum XML_Error PTRCALL
4394prologInitProcessor(XML_Parser parser, const char *s, const char *end,
4395 const char **nextPtr) {
4396 enum XML_Error result = initializeEncoding(parser);
4397 if (result != XML_ERROR_NONE)
4398 return result;
4399 parser->m_processor = prologProcessor;
4400 return prologProcessor(parser, s, end, nextPtr);
4401}
4402
4403#ifdef XML_DTD
4404
4405static enum XML_Error PTRCALL
4406externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
4407 const char **nextPtr) {
4408 enum XML_Error result = initializeEncoding(parser);
4409 if (result != XML_ERROR_NONE)
4410 return result;
4411
4412 /* we know now that XML_Parse(Buffer) has been called,
4413 so we consider the external parameter entity read */
4414 parser->m_dtd->paramEntityRead = XML_TRUE;
4415
4416 if (parser->m_prologState.inEntityValue) {
4417 parser->m_processor = entityValueInitProcessor;
4418 return entityValueInitProcessor(parser, s, end, nextPtr);
4419 } else {
4420 parser->m_processor = externalParEntProcessor;
4421 return externalParEntProcessor(parser, s, end, nextPtr);
4422 }
4423}
4424
4425static enum XML_Error PTRCALL
4426entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
4427 const char **nextPtr) {
4428 int tok;
4429 const char *start = s;
4430 const char *next = start;
4431 parser->m_eventPtr = start;
4432
4433 for (;;) {
4434 tok = XmlPrologTok(parser->m_encoding, start, end, &next);
4435 /* Note: Except for XML_TOK_BOM below, these bytes are accounted later in:
4436 - storeEntityValue
4437 - processXmlDecl
4438 */
4439 parser->m_eventEndPtr = next;
4440 if (tok <= 0) {
4441 if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
4442 *nextPtr = s;
4443 return XML_ERROR_NONE;
4444 }
4445 switch (tok) {
4446 case XML_TOK_INVALID:
4448 case XML_TOK_PARTIAL:
4452 case XML_TOK_NONE: /* start == end */
4453 default:
4454 break;
4455 }
4456 /* found end of entity value - can store it now */
4457 return storeEntityValue(parser, parser->m_encoding, s, end,
4459 } else if (tok == XML_TOK_XML_DECL) {
4460 enum XML_Error result;
4461 result = processXmlDecl(parser, 0, start, next);
4462 if (result != XML_ERROR_NONE)
4463 return result;
4464 /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED. For
4465 * that to happen, a parameter entity parsing handler must have attempted
4466 * to suspend the parser, which fails and raises an error. The parser can
4467 * be aborted, but can't be suspended.
4468 */
4469 if (parser->m_parsingStatus.parsing == XML_FINISHED)
4470 return XML_ERROR_ABORTED;
4471 *nextPtr = next;
4472 /* stop scanning for text declaration - we found one */
4473 parser->m_processor = entityValueProcessor;
4474 return entityValueProcessor(parser, next, end, nextPtr);
4475 }
4476 /* If we are at the end of the buffer, this would cause XmlPrologTok to
4477 return XML_TOK_NONE on the next call, which would then cause the
4478 function to exit with *nextPtr set to s - that is what we want for other
4479 tokens, but not for the BOM - we would rather like to skip it;
4480 then, when this routine is entered the next time, XmlPrologTok will
4481 return XML_TOK_INVALID, since the BOM is still in the buffer
4482 */
4483 else if (tok == XML_TOK_BOM && next == end
4484 && ! parser->m_parsingStatus.finalBuffer) {
4485# ifdef XML_DTD
4486 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
4488 accountingOnAbort(parser);
4490 }
4491# endif
4492
4493 *nextPtr = next;
4494 return XML_ERROR_NONE;
4495 }
4496 /* If we get this token, we have the start of what might be a
4497 normal tag, but not a declaration (i.e. it doesn't begin with
4498 "<!"). In a DTD context, that isn't legal.
4499 */
4500 else if (tok == XML_TOK_INSTANCE_START) {
4501 *nextPtr = next;
4502 return XML_ERROR_SYNTAX;
4503 }
4504 start = next;
4505 parser->m_eventPtr = start;
4506 }
4507}
4508
4509static enum XML_Error PTRCALL
4510externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
4511 const char **nextPtr) {
4512 const char *next = s;
4513 int tok;
4514
4515 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4516 if (tok <= 0) {
4517 if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
4518 *nextPtr = s;
4519 return XML_ERROR_NONE;
4520 }
4521 switch (tok) {
4522 case XML_TOK_INVALID:
4524 case XML_TOK_PARTIAL:
4528 case XML_TOK_NONE: /* start == end */
4529 default:
4530 break;
4531 }
4532 }
4533 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
4534 However, when parsing an external subset, doProlog will not accept a BOM
4535 as valid, and report a syntax error, so we have to skip the BOM, and
4536 account for the BOM bytes.
4537 */
4538 else if (tok == XML_TOK_BOM) {
4539 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
4541 accountingOnAbort(parser);
4543 }
4544
4545 s = next;
4546 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4547 }
4548
4549 parser->m_processor = prologProcessor;
4550 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
4553}
4554
4555static enum XML_Error PTRCALL
4556entityValueProcessor(XML_Parser parser, const char *s, const char *end,
4557 const char **nextPtr) {
4558 const char *start = s;
4559 const char *next = s;
4560 const ENCODING *enc = parser->m_encoding;
4561 int tok;
4562
4563 for (;;) {
4564 tok = XmlPrologTok(enc, start, end, &next);
4565 /* Note: These bytes are accounted later in:
4566 - storeEntityValue
4567 */
4568 if (tok <= 0) {
4569 if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
4570 *nextPtr = s;
4571 return XML_ERROR_NONE;
4572 }
4573 switch (tok) {
4574 case XML_TOK_INVALID:
4576 case XML_TOK_PARTIAL:
4580 case XML_TOK_NONE: /* start == end */
4581 default:
4582 break;
4583 }
4584 /* found end of entity value - can store it now */
4585 return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT);
4586 }
4587 start = next;
4588 }
4589}
4590
4591#endif /* XML_DTD */
4592
4593static enum XML_Error PTRCALL
4594prologProcessor(XML_Parser parser, const char *s, const char *end,
4595 const char **nextPtr) {
4596 const char *next = s;
4597 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4598 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
4601}
4602
4603static enum XML_Error
4604doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
4605 int tok, const char *next, const char **nextPtr, XML_Bool haveMore,
4606 XML_Bool allowClosingDoctype, enum XML_Account account) {
4607#ifdef XML_DTD
4608 static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
4609#endif /* XML_DTD */
4610 static const XML_Char atypeCDATA[]
4611 = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
4612 static const XML_Char atypeID[] = {ASCII_I, ASCII_D, '\0'};
4613 static const XML_Char atypeIDREF[]
4614 = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'};
4615 static const XML_Char atypeIDREFS[]
4617 static const XML_Char atypeENTITY[]
4619 static const XML_Char atypeENTITIES[]
4621 ASCII_I, ASCII_E, ASCII_S, '\0'};
4622 static const XML_Char atypeNMTOKEN[]
4624 static const XML_Char atypeNMTOKENS[]
4626 ASCII_E, ASCII_N, ASCII_S, '\0'};
4627 static const XML_Char notationPrefix[]
4630 static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
4631 static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
4632
4633#ifndef XML_DTD
4634 UNUSED_P(account);
4635#endif
4636
4637 /* save one level of indirection */
4638 DTD *const dtd = parser->m_dtd;
4639
4640 const char **eventPP;
4641 const char **eventEndPP;
4642 enum XML_Content_Quant quant;
4643
4644 if (enc == parser->m_encoding) {
4645 eventPP = &parser->m_eventPtr;
4646 eventEndPP = &parser->m_eventEndPtr;
4647 } else {
4648 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4649 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
4650 }
4651
4652 for (;;) {
4653 int role;
4654 XML_Bool handleDefault = XML_TRUE;
4655 *eventPP = s;
4656 *eventEndPP = next;
4657 if (tok <= 0) {
4658 if (haveMore && tok != XML_TOK_INVALID) {
4659 *nextPtr = s;
4660 return XML_ERROR_NONE;
4661 }
4662 switch (tok) {
4663 case XML_TOK_INVALID:
4664 *eventPP = next;
4666 case XML_TOK_PARTIAL:
4670 case -XML_TOK_PROLOG_S:
4671 tok = -tok;
4672 break;
4673 case XML_TOK_NONE:
4674#ifdef XML_DTD
4675 /* for internal PE NOT referenced between declarations */
4676 if (enc != parser->m_encoding
4677 && ! parser->m_openInternalEntities->betweenDecl) {
4678 *nextPtr = s;
4679 return XML_ERROR_NONE;
4680 }
4681 /* WFC: PE Between Declarations - must check that PE contains
4682 complete markup, not only for external PEs, but also for
4683 internal PEs if the reference occurs between declarations.
4684 */
4685 if (parser->m_isParamEntity || enc != parser->m_encoding) {
4686 if (XmlTokenRole(&parser->m_prologState, XML_TOK_NONE, end, end, enc)
4687 == XML_ROLE_ERROR)
4689 *nextPtr = s;
4690 return XML_ERROR_NONE;
4691 }
4692#endif /* XML_DTD */
4693 return XML_ERROR_NO_ELEMENTS;
4694 default:
4695 tok = -tok;
4696 next = end;
4697 break;
4698 }
4699 }
4700 role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
4701#ifdef XML_DTD
4702 switch (role) {
4703 case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor
4704 case XML_ROLE_XML_DECL: // bytes accounted in processXmlDecl
4705 case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl
4706 break;
4707 default:
4708 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
4709 accountingOnAbort(parser);
4711 }
4712 }
4713#endif
4714 switch (role) {
4715 case XML_ROLE_XML_DECL: {
4716 enum XML_Error result = processXmlDecl(parser, 0, s, next);
4717 if (result != XML_ERROR_NONE)
4718 return result;
4719 enc = parser->m_encoding;
4720 handleDefault = XML_FALSE;
4721 } break;
4723 if (parser->m_startDoctypeDeclHandler) {
4724 parser->m_doctypeName
4725 = poolStoreString(&parser->m_tempPool, enc, s, next);
4726 if (! parser->m_doctypeName)
4727 return XML_ERROR_NO_MEMORY;
4728 poolFinish(&parser->m_tempPool);
4729 parser->m_doctypePubid = NULL;
4730 handleDefault = XML_FALSE;
4731 }
4732 parser->m_doctypeSysid = NULL; /* always initialize to NULL */
4733 break;
4735 if (parser->m_startDoctypeDeclHandler) {
4737 parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
4738 parser->m_doctypePubid, 1);
4739 parser->m_doctypeName = NULL;
4740 poolClear(&parser->m_tempPool);
4741 handleDefault = XML_FALSE;
4742 }
4743 break;
4744#ifdef XML_DTD
4745 case XML_ROLE_TEXT_DECL: {
4746 enum XML_Error result = processXmlDecl(parser, 1, s, next);
4747 if (result != XML_ERROR_NONE)
4748 return result;
4749 enc = parser->m_encoding;
4750 handleDefault = XML_FALSE;
4751 } break;
4752#endif /* XML_DTD */
4754#ifdef XML_DTD
4755 parser->m_useForeignDTD = XML_FALSE;
4756 parser->m_declEntity = (ENTITY *)lookup(
4757 parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
4758 if (! parser->m_declEntity)
4759 return XML_ERROR_NO_MEMORY;
4760#endif /* XML_DTD */
4762 if (parser->m_startDoctypeDeclHandler) {
4763 XML_Char *pubId;
4764 if (! XmlIsPublicId(enc, s, next, eventPP))
4765 return XML_ERROR_PUBLICID;
4766 pubId = poolStoreString(&parser->m_tempPool, enc,
4767 s + enc->minBytesPerChar,
4768 next - enc->minBytesPerChar);
4769 if (! pubId)
4770 return XML_ERROR_NO_MEMORY;
4771 normalizePublicId(pubId);
4772 poolFinish(&parser->m_tempPool);
4773 parser->m_doctypePubid = pubId;
4774 handleDefault = XML_FALSE;
4775 goto alreadyChecked;
4776 }
4777 /* fall through */
4779 if (! XmlIsPublicId(enc, s, next, eventPP))
4780 return XML_ERROR_PUBLICID;
4781 alreadyChecked:
4782 if (dtd->keepProcessing && parser->m_declEntity) {
4783 XML_Char *tem
4784 = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
4785 next - enc->minBytesPerChar);
4786 if (! tem)
4787 return XML_ERROR_NO_MEMORY;
4788 normalizePublicId(tem);
4789 parser->m_declEntity->publicId = tem;
4790 poolFinish(&dtd->pool);
4791 /* Don't suppress the default handler if we fell through from
4792 * the XML_ROLE_DOCTYPE_PUBLIC_ID case.
4793 */
4794 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID)
4795 handleDefault = XML_FALSE;
4796 }
4797 break;
4799 if (allowClosingDoctype != XML_TRUE) {
4800 /* Must not close doctype from within expanded parameter entities */
4802 }
4803
4804 if (parser->m_doctypeName) {
4806 parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
4807 parser->m_doctypePubid, 0);
4808 poolClear(&parser->m_tempPool);
4809 handleDefault = XML_FALSE;
4810 }
4811 /* parser->m_doctypeSysid will be non-NULL in the case of a previous
4812 XML_ROLE_DOCTYPE_SYSTEM_ID, even if parser->m_startDoctypeDeclHandler
4813 was not set, indicating an external subset
4814 */
4815#ifdef XML_DTD
4816 if (parser->m_doctypeSysid || parser->m_useForeignDTD) {
4817 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4819 if (parser->m_paramEntityParsing
4820 && parser->m_externalEntityRefHandler) {
4821 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4822 externalSubsetName, sizeof(ENTITY));
4823 if (! entity) {
4824 /* The external subset name "#" will have already been
4825 * inserted into the hash table at the start of the
4826 * external entity parsing, so no allocation will happen
4827 * and lookup() cannot fail.
4828 */
4829 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
4830 }
4831 if (parser->m_useForeignDTD)
4832 entity->base = parser->m_curBase;
4833 dtd->paramEntityRead = XML_FALSE;
4834 if (! parser->m_externalEntityRefHandler(
4835 parser->m_externalEntityRefHandlerArg, 0, entity->base,
4836 entity->systemId, entity->publicId))
4838 if (dtd->paramEntityRead) {
4839 if (! dtd->standalone && parser->m_notStandaloneHandler
4840 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
4842 }
4843 /* if we didn't read the foreign DTD then this means that there
4844 is no external subset and we must reset dtd->hasParamEntityRefs
4845 */
4846 else if (! parser->m_doctypeSysid)
4847 dtd->hasParamEntityRefs = hadParamEntityRefs;
4848 /* end of DTD - no need to update dtd->keepProcessing */
4849 }
4850 parser->m_useForeignDTD = XML_FALSE;
4851 }
4852#endif /* XML_DTD */
4853 if (parser->m_endDoctypeDeclHandler) {
4854 parser->m_endDoctypeDeclHandler(parser->m_handlerArg);
4855 handleDefault = XML_FALSE;
4856 }
4857 break;
4859#ifdef XML_DTD
4860 /* if there is no DOCTYPE declaration then now is the
4861 last chance to read the foreign DTD
4862 */
4863 if (parser->m_useForeignDTD) {
4864 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4866 if (parser->m_paramEntityParsing
4867 && parser->m_externalEntityRefHandler) {
4868 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4869 externalSubsetName, sizeof(ENTITY));
4870 if (! entity)
4871 return XML_ERROR_NO_MEMORY;
4872 entity->base = parser->m_curBase;
4873 dtd->paramEntityRead = XML_FALSE;
4874 if (! parser->m_externalEntityRefHandler(
4875 parser->m_externalEntityRefHandlerArg, 0, entity->base,
4876 entity->systemId, entity->publicId))
4878 if (dtd->paramEntityRead) {
4879 if (! dtd->standalone && parser->m_notStandaloneHandler
4880 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
4882 }
4883 /* if we didn't read the foreign DTD then this means that there
4884 is no external subset and we must reset dtd->hasParamEntityRefs
4885 */
4886 else
4887 dtd->hasParamEntityRefs = hadParamEntityRefs;
4888 /* end of DTD - no need to update dtd->keepProcessing */
4889 }
4890 }
4891#endif /* XML_DTD */
4892 parser->m_processor = contentProcessor;
4893 return contentProcessor(parser, s, end, nextPtr);
4895 parser->m_declElementType = getElementType(parser, enc, s, next);
4896 if (! parser->m_declElementType)
4897 return XML_ERROR_NO_MEMORY;
4898 goto checkAttListDeclHandler;
4900 parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
4901 if (! parser->m_declAttributeId)
4902 return XML_ERROR_NO_MEMORY;
4904 parser->m_declAttributeType = NULL;
4906 goto checkAttListDeclHandler;
4909 parser->m_declAttributeType = atypeCDATA;
4910 goto checkAttListDeclHandler;
4912 parser->m_declAttributeIsId = XML_TRUE;
4913 parser->m_declAttributeType = atypeID;
4914 goto checkAttListDeclHandler;
4916 parser->m_declAttributeType = atypeIDREF;
4917 goto checkAttListDeclHandler;
4919 parser->m_declAttributeType = atypeIDREFS;
4920 goto checkAttListDeclHandler;
4922 parser->m_declAttributeType = atypeENTITY;
4923 goto checkAttListDeclHandler;
4925 parser->m_declAttributeType = atypeENTITIES;
4926 goto checkAttListDeclHandler;
4928 parser->m_declAttributeType = atypeNMTOKEN;
4929 goto checkAttListDeclHandler;
4931 parser->m_declAttributeType = atypeNMTOKENS;
4932 checkAttListDeclHandler:
4933 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
4934 handleDefault = XML_FALSE;
4935 break;
4938 if (dtd->keepProcessing && parser->m_attlistDeclHandler) {
4939 const XML_Char *prefix;
4940 if (parser->m_declAttributeType) {
4941 prefix = enumValueSep;
4942 } else {
4943 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE ? notationPrefix
4944 : enumValueStart);
4945 }
4946 if (! poolAppendString(&parser->m_tempPool, prefix))
4947 return XML_ERROR_NO_MEMORY;
4948 if (! poolAppend(&parser->m_tempPool, enc, s, next))
4949 return XML_ERROR_NO_MEMORY;
4950 parser->m_declAttributeType = parser->m_tempPool.start;
4951 handleDefault = XML_FALSE;
4952 }
4953 break;
4956 if (dtd->keepProcessing) {
4957 if (! defineAttribute(parser->m_declElementType,
4958 parser->m_declAttributeId,
4959 parser->m_declAttributeIsCdata,
4960 parser->m_declAttributeIsId, 0, parser))
4961 return XML_ERROR_NO_MEMORY;
4962 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
4963 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
4964 || (*parser->m_declAttributeType == XML_T(ASCII_N)
4965 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
4966 /* Enumerated or Notation type */
4968 || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
4969 return XML_ERROR_NO_MEMORY;
4970 parser->m_declAttributeType = parser->m_tempPool.start;
4971 poolFinish(&parser->m_tempPool);
4972 }
4973 *eventEndPP = s;
4974 parser->m_attlistDeclHandler(
4975 parser->m_handlerArg, parser->m_declElementType->name,
4976 parser->m_declAttributeId->name, parser->m_declAttributeType, 0,
4978 poolClear(&parser->m_tempPool);
4979 handleDefault = XML_FALSE;
4980 }
4981 }
4982 break;
4985 if (dtd->keepProcessing) {
4986 const XML_Char *attVal;
4987 enum XML_Error result = storeAttributeValue(
4988 parser, enc, parser->m_declAttributeIsCdata,
4989 s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool,
4991 if (result)
4992 return result;
4993 attVal = poolStart(&dtd->pool);
4994 poolFinish(&dtd->pool);
4995 /* ID attributes aren't allowed to have a default */
4996 if (! defineAttribute(
4997 parser->m_declElementType, parser->m_declAttributeId,
4998 parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
4999 return XML_ERROR_NO_MEMORY;
5000 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
5001 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
5002 || (*parser->m_declAttributeType == XML_T(ASCII_N)
5003 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
5004 /* Enumerated or Notation type */
5006 || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
5007 return XML_ERROR_NO_MEMORY;
5008 parser->m_declAttributeType = parser->m_tempPool.start;
5009 poolFinish(&parser->m_tempPool);
5010 }
5011 *eventEndPP = s;
5012 parser->m_attlistDeclHandler(
5013 parser->m_handlerArg, parser->m_declElementType->name,
5014 parser->m_declAttributeId->name, parser->m_declAttributeType,
5015 attVal, role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
5016 poolClear(&parser->m_tempPool);
5017 handleDefault = XML_FALSE;
5018 }
5019 }
5020 break;
5022 if (dtd->keepProcessing) {
5023 enum XML_Error result
5024 = storeEntityValue(parser, enc, s + enc->minBytesPerChar,
5025 next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
5026 if (parser->m_declEntity) {
5028 parser->m_declEntity->textLen
5029 = (int)(poolLength(&dtd->entityValuePool));
5031 if (parser->m_entityDeclHandler) {
5032 *eventEndPP = s;
5033 parser->m_entityDeclHandler(
5034 parser->m_handlerArg, parser->m_declEntity->name,
5035 parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
5036 parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
5037 handleDefault = XML_FALSE;
5038 }
5039 } else
5041 if (result != XML_ERROR_NONE)
5042 return result;
5043 }
5044 break;
5046#ifdef XML_DTD
5047 parser->m_useForeignDTD = XML_FALSE;
5048#endif /* XML_DTD */
5050 if (parser->m_startDoctypeDeclHandler) {
5051 parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc,
5052 s + enc->minBytesPerChar,
5053 next - enc->minBytesPerChar);
5054 if (parser->m_doctypeSysid == NULL)
5055 return XML_ERROR_NO_MEMORY;
5056 poolFinish(&parser->m_tempPool);
5057 handleDefault = XML_FALSE;
5058 }
5059#ifdef XML_DTD
5060 else
5061 /* use externalSubsetName to make parser->m_doctypeSysid non-NULL
5062 for the case where no parser->m_startDoctypeDeclHandler is set */
5063 parser->m_doctypeSysid = externalSubsetName;
5064#endif /* XML_DTD */
5065 if (! dtd->standalone
5066#ifdef XML_DTD
5067 && ! parser->m_paramEntityParsing
5068#endif /* XML_DTD */
5069 && parser->m_notStandaloneHandler
5070 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
5072#ifndef XML_DTD
5073 break;
5074#else /* XML_DTD */
5075 if (! parser->m_declEntity) {
5076 parser->m_declEntity = (ENTITY *)lookup(
5077 parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
5078 if (! parser->m_declEntity)
5079 return XML_ERROR_NO_MEMORY;
5080 parser->m_declEntity->publicId = NULL;
5081 }
5082#endif /* XML_DTD */
5083 /* fall through */
5085 if (dtd->keepProcessing && parser->m_declEntity) {
5086 parser->m_declEntity->systemId
5087 = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
5088 next - enc->minBytesPerChar);
5089 if (! parser->m_declEntity->systemId)
5090 return XML_ERROR_NO_MEMORY;
5091 parser->m_declEntity->base = parser->m_curBase;
5092 poolFinish(&dtd->pool);
5093 /* Don't suppress the default handler if we fell through from
5094 * the XML_ROLE_DOCTYPE_SYSTEM_ID case.
5095 */
5096 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID)
5097 handleDefault = XML_FALSE;
5098 }
5099 break;
5101 if (dtd->keepProcessing && parser->m_declEntity
5102 && parser->m_entityDeclHandler) {
5103 *eventEndPP = s;
5104 parser->m_entityDeclHandler(
5105 parser->m_handlerArg, parser->m_declEntity->name,
5106 parser->m_declEntity->is_param, 0, 0, parser->m_declEntity->base,
5107 parser->m_declEntity->systemId, parser->m_declEntity->publicId, 0);
5108 handleDefault = XML_FALSE;
5109 }
5110 break;
5112 if (dtd->keepProcessing && parser->m_declEntity) {
5113 parser->m_declEntity->notation
5114 = poolStoreString(&dtd->pool, enc, s, next);
5115 if (! parser->m_declEntity->notation)
5116 return XML_ERROR_NO_MEMORY;
5117 poolFinish(&dtd->pool);
5118 if (parser->m_unparsedEntityDeclHandler) {
5119 *eventEndPP = s;
5121 parser->m_handlerArg, parser->m_declEntity->name,
5122 parser->m_declEntity->base, parser->m_declEntity->systemId,
5123 parser->m_declEntity->publicId, parser->m_declEntity->notation);
5124 handleDefault = XML_FALSE;
5125 } else if (parser->m_entityDeclHandler) {
5126 *eventEndPP = s;
5127 parser->m_entityDeclHandler(
5128 parser->m_handlerArg, parser->m_declEntity->name, 0, 0, 0,
5129 parser->m_declEntity->base, parser->m_declEntity->systemId,
5130 parser->m_declEntity->publicId, parser->m_declEntity->notation);
5131 handleDefault = XML_FALSE;
5132 }
5133 }
5134 break;
5136 if (XmlPredefinedEntityName(enc, s, next)) {
5137 parser->m_declEntity = NULL;
5138 break;
5139 }
5140 if (dtd->keepProcessing) {
5141 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
5142 if (! name)
5143 return XML_ERROR_NO_MEMORY;
5144 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities,
5145 name, sizeof(ENTITY));
5146 if (! parser->m_declEntity)
5147 return XML_ERROR_NO_MEMORY;
5148 if (parser->m_declEntity->name != name) {
5149 poolDiscard(&dtd->pool);
5150 parser->m_declEntity = NULL;
5151 } else {
5152 poolFinish(&dtd->pool);
5153 parser->m_declEntity->publicId = NULL;
5154 parser->m_declEntity->is_param = XML_FALSE;
5155 /* if we have a parent parser or are reading an internal parameter
5156 entity, then the entity declaration is not considered "internal"
5157 */
5158 parser->m_declEntity->is_internal
5159 = ! (parser->m_parentParser || parser->m_openInternalEntities);
5160 if (parser->m_entityDeclHandler)
5161 handleDefault = XML_FALSE;
5162 }
5163 } else {
5164 poolDiscard(&dtd->pool);
5165 parser->m_declEntity = NULL;
5166 }
5167 } break;
5169#ifdef XML_DTD
5170 if (dtd->keepProcessing) {
5171 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
5172 if (! name)
5173 return XML_ERROR_NO_MEMORY;
5174 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
5175 name, sizeof(ENTITY));
5176 if (! parser->m_declEntity)
5177 return XML_ERROR_NO_MEMORY;
5178 if (parser->m_declEntity->name != name) {
5179 poolDiscard(&dtd->pool);
5180 parser->m_declEntity = NULL;
5181 } else {
5182 poolFinish(&dtd->pool);
5183 parser->m_declEntity->publicId = NULL;
5184 parser->m_declEntity->is_param = XML_TRUE;
5185 /* if we have a parent parser or are reading an internal parameter
5186 entity, then the entity declaration is not considered "internal"
5187 */
5188 parser->m_declEntity->is_internal
5189 = ! (parser->m_parentParser || parser->m_openInternalEntities);
5190 if (parser->m_entityDeclHandler)
5191 handleDefault = XML_FALSE;
5192 }
5193 } else {
5194 poolDiscard(&dtd->pool);
5195 parser->m_declEntity = NULL;
5196 }
5197#else /* not XML_DTD */
5198 parser->m_declEntity = NULL;
5199#endif /* XML_DTD */
5200 break;
5202 parser->m_declNotationPublicId = NULL;
5203 parser->m_declNotationName = NULL;
5204 if (parser->m_notationDeclHandler) {
5205 parser->m_declNotationName
5206 = poolStoreString(&parser->m_tempPool, enc, s, next);
5207 if (! parser->m_declNotationName)
5208 return XML_ERROR_NO_MEMORY;
5209 poolFinish(&parser->m_tempPool);
5210 handleDefault = XML_FALSE;
5211 }
5212 break;
5214 if (! XmlIsPublicId(enc, s, next, eventPP))
5215 return XML_ERROR_PUBLICID;
5216 if (parser
5217 ->m_declNotationName) { /* means m_notationDeclHandler != NULL */
5218 XML_Char *tem = poolStoreString(&parser->m_tempPool, enc,
5219 s + enc->minBytesPerChar,
5220 next - enc->minBytesPerChar);
5221 if (! tem)
5222 return XML_ERROR_NO_MEMORY;
5223 normalizePublicId(tem);
5224 parser->m_declNotationPublicId = tem;
5225 poolFinish(&parser->m_tempPool);
5226 handleDefault = XML_FALSE;
5227 }
5228 break;
5230 if (parser->m_declNotationName && parser->m_notationDeclHandler) {
5231 const XML_Char *systemId = poolStoreString(&parser->m_tempPool, enc,
5232 s + enc->minBytesPerChar,
5233 next - enc->minBytesPerChar);
5234 if (! systemId)
5235 return XML_ERROR_NO_MEMORY;
5236 *eventEndPP = s;
5237 parser->m_notationDeclHandler(
5238 parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
5239 systemId, parser->m_declNotationPublicId);
5240 handleDefault = XML_FALSE;
5241 }
5242 poolClear(&parser->m_tempPool);
5243 break;
5245 if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) {
5246 *eventEndPP = s;
5247 parser->m_notationDeclHandler(
5248 parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
5249 0, parser->m_declNotationPublicId);
5250 handleDefault = XML_FALSE;
5251 }
5252 poolClear(&parser->m_tempPool);
5253 break;
5254 case XML_ROLE_ERROR:
5255 switch (tok) {
5257 /* PE references in internal subset are
5258 not allowed within declarations. */
5260 case XML_TOK_XML_DECL:
5262 default:
5263 return XML_ERROR_SYNTAX;
5264 }
5265#ifdef XML_DTD
5266 case XML_ROLE_IGNORE_SECT: {
5267 enum XML_Error result;
5268 if (parser->m_defaultHandler)
5269 reportDefault(parser, enc, s, next);
5270 handleDefault = XML_FALSE;
5271 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
5272 if (result != XML_ERROR_NONE)
5273 return result;
5274 else if (! next) {
5275 parser->m_processor = ignoreSectionProcessor;
5276 return result;
5277 }
5278 } break;
5279#endif /* XML_DTD */
5281 if (parser->m_prologState.level >= parser->m_groupSize) {
5282 if (parser->m_groupSize) {
5283 {
5284 /* Detect and prevent integer overflow */
5285 if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
5286 return XML_ERROR_NO_MEMORY;
5287 }
5288
5289 char *const new_connector = (char *)REALLOC(
5290 parser, parser->m_groupConnector, parser->m_groupSize *= 2);
5291 if (new_connector == NULL) {
5292 parser->m_groupSize /= 2;
5293 return XML_ERROR_NO_MEMORY;
5294 }
5295 parser->m_groupConnector = new_connector;
5296 }
5297
5298 if (dtd->scaffIndex) {
5299 /* Detect and prevent integer overflow.
5300 * The preprocessor guard addresses the "always false" warning
5301 * from -Wtype-limits on platforms where
5302 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
5303#if UINT_MAX >= SIZE_MAX
5304 if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) {
5305 return XML_ERROR_NO_MEMORY;
5306 }
5307#endif
5308
5309 int *const new_scaff_index = (int *)REALLOC(
5310 parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
5311 if (new_scaff_index == NULL)
5312 return XML_ERROR_NO_MEMORY;
5313 dtd->scaffIndex = new_scaff_index;
5314 }
5315 } else {
5316 parser->m_groupConnector
5317 = (char *)MALLOC(parser, parser->m_groupSize = 32);
5318 if (! parser->m_groupConnector) {
5319 parser->m_groupSize = 0;
5320 return XML_ERROR_NO_MEMORY;
5321 }
5322 }
5323 }
5324 parser->m_groupConnector[parser->m_prologState.level] = 0;
5325 if (dtd->in_eldecl) {
5326 int myindex = nextScaffoldPart(parser);
5327 if (myindex < 0)
5328 return XML_ERROR_NO_MEMORY;
5329 assert(dtd->scaffIndex != NULL);
5330 dtd->scaffIndex[dtd->scaffLevel] = myindex;
5331 dtd->scaffLevel++;
5332 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
5333 if (parser->m_elementDeclHandler)
5334 handleDefault = XML_FALSE;
5335 }
5336 break;
5338 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE)
5339 return XML_ERROR_SYNTAX;
5341 if (dtd->in_eldecl && parser->m_elementDeclHandler)
5342 handleDefault = XML_FALSE;
5343 break;
5345 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
5346 return XML_ERROR_SYNTAX;
5347 if (dtd->in_eldecl
5348 && ! parser->m_groupConnector[parser->m_prologState.level]
5349 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5350 != XML_CTYPE_MIXED)) {
5351 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5353 if (parser->m_elementDeclHandler)
5354 handleDefault = XML_FALSE;
5355 }
5357 break;
5359#ifdef XML_DTD
5360 case XML_ROLE_INNER_PARAM_ENTITY_REF:
5362 if (! parser->m_paramEntityParsing)
5363 dtd->keepProcessing = dtd->standalone;
5364 else {
5365 const XML_Char *name;
5366 ENTITY *entity;
5367 name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
5368 next - enc->minBytesPerChar);
5369 if (! name)
5370 return XML_ERROR_NO_MEMORY;
5371 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5372 poolDiscard(&dtd->pool);
5373 /* first, determine if a check for an existing declaration is needed;
5374 if yes, check that the entity exists, and that it is internal,
5375 otherwise call the skipped entity handler
5376 */
5377 if (parser->m_prologState.documentEntity
5378 && (dtd->standalone ? ! parser->m_openInternalEntities
5379 : ! dtd->hasParamEntityRefs)) {
5380 if (! entity)
5382 else if (! entity->is_internal) {
5383 /* It's hard to exhaustively search the code to be sure,
5384 * but there doesn't seem to be a way of executing the
5385 * following line. There are two cases:
5386 *
5387 * If 'standalone' is false, the DTD must have no
5388 * parameter entities or we wouldn't have passed the outer
5389 * 'if' statement. That means the only entity in the hash
5390 * table is the external subset name "#" which cannot be
5391 * given as a parameter entity name in XML syntax, so the
5392 * lookup must have returned NULL and we don't even reach
5393 * the test for an internal entity.
5394 *
5395 * If 'standalone' is true, it does not seem to be
5396 * possible to create entities taking this code path that
5397 * are not internal entities, so fail the test above.
5398 *
5399 * Because this analysis is very uncertain, the code is
5400 * being left in place and merely removed from the
5401 * coverage test statistics.
5402 */
5403 return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
5404 }
5405 } else if (! entity) {
5406 dtd->keepProcessing = dtd->standalone;
5407 /* cannot report skipped entities in declarations */
5408 if ((role == XML_ROLE_PARAM_ENTITY_REF)
5409 && parser->m_skippedEntityHandler) {
5410 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1);
5411 handleDefault = XML_FALSE;
5412 }
5413 break;
5414 }
5415 if (entity->open)
5417 if (entity->textPtr) {
5418 enum XML_Error result;
5419 XML_Bool betweenDecl
5421 result = processInternalEntity(parser, entity, betweenDecl);
5422 if (result != XML_ERROR_NONE)
5423 return result;
5424 handleDefault = XML_FALSE;
5425 break;
5426 }
5427 if (parser->m_externalEntityRefHandler) {
5428 dtd->paramEntityRead = XML_FALSE;
5429 entity->open = XML_TRUE;
5430 entityTrackingOnOpen(parser, entity, __LINE__);
5431 if (! parser->m_externalEntityRefHandler(
5432 parser->m_externalEntityRefHandlerArg, 0, entity->base,
5433 entity->systemId, entity->publicId)) {
5434 entityTrackingOnClose(parser, entity, __LINE__);
5435 entity->open = XML_FALSE;
5437 }
5438 entityTrackingOnClose(parser, entity, __LINE__);
5439 entity->open = XML_FALSE;
5440 handleDefault = XML_FALSE;
5441 if (! dtd->paramEntityRead) {
5442 dtd->keepProcessing = dtd->standalone;
5443 break;
5444 }
5445 } else {
5446 dtd->keepProcessing = dtd->standalone;
5447 break;
5448 }
5449 }
5450#endif /* XML_DTD */
5451 if (! dtd->standalone && parser->m_notStandaloneHandler
5452 && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
5454 break;
5455
5456 /* Element declaration stuff */
5457
5459 if (parser->m_elementDeclHandler) {
5460 parser->m_declElementType = getElementType(parser, enc, s, next);
5461 if (! parser->m_declElementType)
5462 return XML_ERROR_NO_MEMORY;
5463 dtd->scaffLevel = 0;
5464 dtd->scaffCount = 0;
5465 dtd->in_eldecl = XML_TRUE;
5466 handleDefault = XML_FALSE;
5467 }
5468 break;
5469
5472 if (dtd->in_eldecl) {
5473 if (parser->m_elementDeclHandler) {
5474 XML_Content *content
5475 = (XML_Content *)MALLOC(parser, sizeof(XML_Content));
5476 if (! content)
5477 return XML_ERROR_NO_MEMORY;
5478 content->quant = XML_CQUANT_NONE;
5479 content->name = NULL;
5480 content->numchildren = 0;
5481 content->children = NULL;
5482 content->type = ((role == XML_ROLE_CONTENT_ANY) ? XML_CTYPE_ANY
5483 : XML_CTYPE_EMPTY);
5484 *eventEndPP = s;
5485 parser->m_elementDeclHandler(
5486 parser->m_handlerArg, parser->m_declElementType->name, content);
5487 handleDefault = XML_FALSE;
5488 }
5489 dtd->in_eldecl = XML_FALSE;
5490 }
5491 break;
5492
5494 if (dtd->in_eldecl) {
5495 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5497 if (parser->m_elementDeclHandler)
5498 handleDefault = XML_FALSE;
5499 }
5500 break;
5501
5503 quant = XML_CQUANT_NONE;
5504 goto elementContent;
5506 quant = XML_CQUANT_OPT;
5507 goto elementContent;
5509 quant = XML_CQUANT_REP;
5510 goto elementContent;
5512 quant = XML_CQUANT_PLUS;
5513 elementContent:
5514 if (dtd->in_eldecl) {
5515 ELEMENT_TYPE *el;
5516 const XML_Char *name;
5517 size_t nameLen;
5518 const char *nxt
5519 = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
5520 int myindex = nextScaffoldPart(parser);
5521 if (myindex < 0)
5522 return XML_ERROR_NO_MEMORY;
5523 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
5524 dtd->scaffold[myindex].quant = quant;
5525 el = getElementType(parser, enc, s, nxt);
5526 if (! el)
5527 return XML_ERROR_NO_MEMORY;
5528 name = el->name;
5529 dtd->scaffold[myindex].name = name;
5530 nameLen = 0;
5531 for (; name[nameLen++];)
5532 ;
5533
5534 /* Detect and prevent integer overflow */
5535 if (nameLen > UINT_MAX - dtd->contentStringLen) {
5536 return XML_ERROR_NO_MEMORY;
5537 }
5538
5539 dtd->contentStringLen += (unsigned)nameLen;
5540 if (parser->m_elementDeclHandler)
5541 handleDefault = XML_FALSE;
5542 }
5543 break;
5544
5546 quant = XML_CQUANT_NONE;
5547 goto closeGroup;
5549 quant = XML_CQUANT_OPT;
5550 goto closeGroup;
5552 quant = XML_CQUANT_REP;
5553 goto closeGroup;
5555 quant = XML_CQUANT_PLUS;
5556 closeGroup:
5557 if (dtd->in_eldecl) {
5558 if (parser->m_elementDeclHandler)
5559 handleDefault = XML_FALSE;
5560 dtd->scaffLevel--;
5561 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
5562 if (dtd->scaffLevel == 0) {
5563 if (! handleDefault) {
5564 XML_Content *model = build_model(parser);
5565 if (! model)
5566 return XML_ERROR_NO_MEMORY;
5567 *eventEndPP = s;
5568 parser->m_elementDeclHandler(
5569 parser->m_handlerArg, parser->m_declElementType->name, model);
5570 }
5571 dtd->in_eldecl = XML_FALSE;
5572 dtd->contentStringLen = 0;
5573 }
5574 }
5575 break;
5576 /* End element declaration stuff */
5577
5578 case XML_ROLE_PI:
5579 if (! reportProcessingInstruction(parser, enc, s, next))
5580 return XML_ERROR_NO_MEMORY;
5581 handleDefault = XML_FALSE;
5582 break;
5583 case XML_ROLE_COMMENT:
5584 if (! reportComment(parser, enc, s, next))
5585 return XML_ERROR_NO_MEMORY;
5586 handleDefault = XML_FALSE;
5587 break;
5588 case XML_ROLE_NONE:
5589 switch (tok) {
5590 case XML_TOK_BOM:
5591 handleDefault = XML_FALSE;
5592 break;
5593 }
5594 break;
5596 if (parser->m_startDoctypeDeclHandler)
5597 handleDefault = XML_FALSE;
5598 break;
5600 if (dtd->keepProcessing && parser->m_entityDeclHandler)
5601 handleDefault = XML_FALSE;
5602 break;
5604 if (parser->m_notationDeclHandler)
5605 handleDefault = XML_FALSE;
5606 break;
5608 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
5609 handleDefault = XML_FALSE;
5610 break;
5612 if (parser->m_elementDeclHandler)
5613 handleDefault = XML_FALSE;
5614 break;
5615 } /* end of big switch */
5616
5617 if (handleDefault && parser->m_defaultHandler)
5618 reportDefault(parser, enc, s, next);
5619
5620 switch (parser->m_parsingStatus.parsing) {
5621 case XML_SUSPENDED:
5622 *nextPtr = next;
5623 return XML_ERROR_NONE;
5624 case XML_FINISHED:
5625 return XML_ERROR_ABORTED;
5626 default:
5627 s = next;
5628 tok = XmlPrologTok(enc, s, end, &next);
5629 }
5630 }
5631 /* not reached */
5632}
5633
5634static enum XML_Error PTRCALL
5635epilogProcessor(XML_Parser parser, const char *s, const char *end,
5636 const char **nextPtr) {
5637 parser->m_processor = epilogProcessor;
5638 parser->m_eventPtr = s;
5639 for (;;) {
5640 const char *next = NULL;
5641 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5642#ifdef XML_DTD
5643 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
5645 accountingOnAbort(parser);
5647 }
5648#endif
5649 parser->m_eventEndPtr = next;
5650 switch (tok) {
5651 /* report partial linebreak - it might be the last token */
5652 case -XML_TOK_PROLOG_S:
5653 if (parser->m_defaultHandler) {
5654 reportDefault(parser, parser->m_encoding, s, next);
5655 if (parser->m_parsingStatus.parsing == XML_FINISHED)
5656 return XML_ERROR_ABORTED;
5657 }
5658 *nextPtr = next;
5659 return XML_ERROR_NONE;
5660 case XML_TOK_NONE:
5661 *nextPtr = s;
5662 return XML_ERROR_NONE;
5663 case XML_TOK_PROLOG_S:
5664 if (parser->m_defaultHandler)
5665 reportDefault(parser, parser->m_encoding, s, next);
5666 break;
5667 case XML_TOK_PI:
5668 if (! reportProcessingInstruction(parser, parser->m_encoding, s, next))
5669 return XML_ERROR_NO_MEMORY;
5670 break;
5671 case XML_TOK_COMMENT:
5672 if (! reportComment(parser, parser->m_encoding, s, next))
5673 return XML_ERROR_NO_MEMORY;
5674 break;
5675 case XML_TOK_INVALID:
5676 parser->m_eventPtr = next;
5678 case XML_TOK_PARTIAL:
5679 if (! parser->m_parsingStatus.finalBuffer) {
5680 *nextPtr = s;
5681 return XML_ERROR_NONE;
5682 }
5685 if (! parser->m_parsingStatus.finalBuffer) {
5686 *nextPtr = s;
5687 return XML_ERROR_NONE;
5688 }
5690 default:
5692 }
5693 parser->m_eventPtr = s = next;
5694 switch (parser->m_parsingStatus.parsing) {
5695 case XML_SUSPENDED:
5696 *nextPtr = next;
5697 return XML_ERROR_NONE;
5698 case XML_FINISHED:
5699 return XML_ERROR_ABORTED;
5700 default:;
5701 }
5702 }
5703}
5704
5705static enum XML_Error
5706processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
5707 const char *textStart, *textEnd;
5708 const char *next;
5709 enum XML_Error result;
5710 OPEN_INTERNAL_ENTITY *openEntity;
5711
5712 if (parser->m_freeInternalEntities) {
5713 openEntity = parser->m_freeInternalEntities;
5714 parser->m_freeInternalEntities = openEntity->next;
5715 } else {
5716 openEntity
5717 = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
5718 if (! openEntity)
5719 return XML_ERROR_NO_MEMORY;
5720 }
5721 entity->open = XML_TRUE;
5722#ifdef XML_DTD
5723 entityTrackingOnOpen(parser, entity, __LINE__);
5724#endif
5725 entity->processed = 0;
5726 openEntity->next = parser->m_openInternalEntities;
5727 parser->m_openInternalEntities = openEntity;
5728 openEntity->entity = entity;
5729 openEntity->startTagLevel = parser->m_tagLevel;
5730 openEntity->betweenDecl = betweenDecl;
5731 openEntity->internalEventPtr = NULL;
5732 openEntity->internalEventEndPtr = NULL;
5733 textStart = (const char *)entity->textPtr;
5734 textEnd = (const char *)(entity->textPtr + entity->textLen);
5735 /* Set a safe default value in case 'next' does not get set */
5736 next = textStart;
5737
5738#ifdef XML_DTD
5739 if (entity->is_param) {
5740 int tok
5741 = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5742 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
5743 tok, next, &next, XML_FALSE, XML_FALSE,
5745 } else
5746#endif /* XML_DTD */
5747 result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
5748 textStart, textEnd, &next, XML_FALSE,
5750
5751 if (result == XML_ERROR_NONE) {
5752 if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
5753 entity->processed = (int)(next - textStart);
5754 parser->m_processor = internalEntityProcessor;
5755 } else {
5756#ifdef XML_DTD
5757 entityTrackingOnClose(parser, entity, __LINE__);
5758#endif /* XML_DTD */
5759 entity->open = XML_FALSE;
5760 parser->m_openInternalEntities = openEntity->next;
5761 /* put openEntity back in list of free instances */
5762 openEntity->next = parser->m_freeInternalEntities;
5763 parser->m_freeInternalEntities = openEntity;
5764 }
5765 }
5766 return result;
5767}
5768
5769static enum XML_Error PTRCALL
5770internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
5771 const char **nextPtr) {
5772 ENTITY *entity;
5773 const char *textStart, *textEnd;
5774 const char *next;
5775 enum XML_Error result;
5776 OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
5777 if (! openEntity)
5779
5780 entity = openEntity->entity;
5781 textStart = ((const char *)entity->textPtr) + entity->processed;
5782 textEnd = (const char *)(entity->textPtr + entity->textLen);
5783 /* Set a safe default value in case 'next' does not get set */
5784 next = textStart;
5785
5786#ifdef XML_DTD
5787 if (entity->is_param) {
5788 int tok
5789 = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5790 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
5791 tok, next, &next, XML_FALSE, XML_TRUE,
5793 } else
5794#endif /* XML_DTD */
5795 result = doContent(parser, openEntity->startTagLevel,
5796 parser->m_internalEncoding, textStart, textEnd, &next,
5798
5799 if (result != XML_ERROR_NONE)
5800 return result;
5801 else if (textEnd != next
5802 && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
5803 entity->processed = (int)(next - (const char *)entity->textPtr);
5804 return result;
5805 } else {
5806#ifdef XML_DTD
5807 entityTrackingOnClose(parser, entity, __LINE__);
5808#endif
5809 entity->open = XML_FALSE;
5810 parser->m_openInternalEntities = openEntity->next;
5811 /* put openEntity back in list of free instances */
5812 openEntity->next = parser->m_freeInternalEntities;
5813 parser->m_freeInternalEntities = openEntity;
5814 }
5815
5816#ifdef XML_DTD
5817 if (entity->is_param) {
5818 int tok;
5819 parser->m_processor = prologProcessor;
5820 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5821 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
5824 } else
5825#endif /* XML_DTD */
5826 {
5827 parser->m_processor = contentProcessor;
5828 /* see externalEntityContentProcessor vs contentProcessor */
5829 result = doContent(parser, parser->m_parentParser ? 1 : 0,
5830 parser->m_encoding, s, end, nextPtr,
5833 if (result == XML_ERROR_NONE) {
5834 if (! storeRawNames(parser))
5835 return XML_ERROR_NO_MEMORY;
5836 }
5837 return result;
5838 }
5839}
5840
5841static enum XML_Error PTRCALL
5842errorProcessor(XML_Parser parser, const char *s, const char *end,
5843 const char **nextPtr) {
5844 UNUSED_P(s);
5845 UNUSED_P(end);
5846 UNUSED_P(nextPtr);
5847 return parser->m_errorCode;
5848}
5849
5850static enum XML_Error
5851storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5852 const char *ptr, const char *end, STRING_POOL *pool,
5853 enum XML_Account account) {
5854 enum XML_Error result
5855 = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
5856 if (result)
5857 return result;
5858 if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
5859 poolChop(pool);
5860 if (! poolAppendChar(pool, XML_T('\0')))
5861 return XML_ERROR_NO_MEMORY;
5862 return XML_ERROR_NONE;
5863}
5864
5865static enum XML_Error
5866appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5867 const char *ptr, const char *end, STRING_POOL *pool,
5868 enum XML_Account account) {
5869 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5870#ifndef XML_DTD
5871 UNUSED_P(account);
5872#endif
5873
5874 for (;;) {
5875 const char *next
5876 = ptr; /* XmlAttributeValueTok doesn't always set the last arg */
5877 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
5878#ifdef XML_DTD
5879 if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) {
5880 accountingOnAbort(parser);
5882 }
5883#endif
5884 switch (tok) {
5885 case XML_TOK_NONE:
5886 return XML_ERROR_NONE;
5887 case XML_TOK_INVALID:
5888 if (enc == parser->m_encoding)
5889 parser->m_eventPtr = next;
5891 case XML_TOK_PARTIAL:
5892 if (enc == parser->m_encoding)
5893 parser->m_eventPtr = ptr;
5895 case XML_TOK_CHAR_REF: {
5897 int i;
5898 int n = XmlCharRefNumber(enc, ptr);
5899 if (n < 0) {
5900 if (enc == parser->m_encoding)
5901 parser->m_eventPtr = ptr;
5903 }
5904 if (! isCdata && n == 0x20 /* space */
5905 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5906 break;
5907 n = XmlEncode(n, (ICHAR *)buf);
5908 /* The XmlEncode() functions can never return 0 here. That
5909 * error return happens if the code point passed in is either
5910 * negative or greater than or equal to 0x110000. The
5911 * XmlCharRefNumber() functions will all return a number
5912 * strictly less than 0x110000 or a negative value if an error
5913 * occurred. The negative value is intercepted above, so
5914 * XmlEncode() is never passed a value it might return an
5915 * error for.
5916 */
5917 for (i = 0; i < n; i++) {
5918 if (! poolAppendChar(pool, buf[i]))
5919 return XML_ERROR_NO_MEMORY;
5920 }
5921 } break;
5922 case XML_TOK_DATA_CHARS:
5923 if (! poolAppend(pool, enc, ptr, next))
5924 return XML_ERROR_NO_MEMORY;
5925 break;
5927 next = ptr + enc->minBytesPerChar;
5928 /* fall through */
5931 if (! isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5932 break;
5933 if (! poolAppendChar(pool, 0x20))
5934 return XML_ERROR_NO_MEMORY;
5935 break;
5936 case XML_TOK_ENTITY_REF: {
5937 const XML_Char *name;
5938 ENTITY *entity;
5939 char checkEntityDecl;
5941 enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
5942 if (ch) {
5943#ifdef XML_DTD
5944 /* NOTE: We are replacing 4-6 characters original input for 1 character
5945 * so there is no amplification and hence recording without
5946 * protection. */
5947 accountingDiffTolerated(parser, tok, (char *)&ch,
5948 ((char *)&ch) + sizeof(XML_Char), __LINE__,
5950#endif /* XML_DTD */
5951 if (! poolAppendChar(pool, ch))
5952 return XML_ERROR_NO_MEMORY;
5953 break;
5954 }
5955 name = poolStoreString(&parser->m_temp2Pool, enc,
5956 ptr + enc->minBytesPerChar,
5957 next - enc->minBytesPerChar);
5958 if (! name)
5959 return XML_ERROR_NO_MEMORY;
5960 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
5961 poolDiscard(&parser->m_temp2Pool);
5962 /* First, determine if a check for an existing declaration is needed;
5963 if yes, check that the entity exists, and that it is internal.
5964 */
5965 if (pool == &dtd->pool) /* are we called from prolog? */
5966 checkEntityDecl =
5967#ifdef XML_DTD
5968 parser->m_prologState.documentEntity &&
5969#endif /* XML_DTD */
5970 (dtd->standalone ? ! parser->m_openInternalEntities
5971 : ! dtd->hasParamEntityRefs);
5972 else /* if (pool == &parser->m_tempPool): we are called from content */
5973 checkEntityDecl = ! dtd->hasParamEntityRefs || dtd->standalone;
5974 if (checkEntityDecl) {
5975 if (! entity)
5977 else if (! entity->is_internal)
5979 } else if (! entity) {
5980 /* Cannot report skipped entity here - see comments on
5981 parser->m_skippedEntityHandler.
5982 if (parser->m_skippedEntityHandler)
5983 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
5984 */
5985 /* Cannot call the default handler because this would be
5986 out of sync with the call to the startElementHandler.
5987 if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
5988 reportDefault(parser, enc, ptr, next);
5989 */
5990 break;
5991 }
5992 if (entity->open) {
5993 if (enc == parser->m_encoding) {
5994 /* It does not appear that this line can be executed.
5995 *
5996 * The "if (entity->open)" check catches recursive entity
5997 * definitions. In order to be called with an open
5998 * entity, it must have gone through this code before and
5999 * been through the recursive call to
6000 * appendAttributeValue() some lines below. That call
6001 * sets the local encoding ("enc") to the parser's
6002 * internal encoding (internal_utf8 or internal_utf16),
6003 * which can never be the same as the principle encoding.
6004 * It doesn't appear there is another code path that gets
6005 * here with entity->open being TRUE.
6006 *
6007 * Since it is not certain that this logic is watertight,
6008 * we keep the line and merely exclude it from coverage
6009 * tests.
6010 */
6011 parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
6012 }
6014 }
6015 if (entity->notation) {
6016 if (enc == parser->m_encoding)
6017 parser->m_eventPtr = ptr;
6019 }
6020 if (! entity->textPtr) {
6021 if (enc == parser->m_encoding)
6022 parser->m_eventPtr = ptr;
6024 } else {
6025 enum XML_Error result;
6026 const XML_Char *textEnd = entity->textPtr + entity->textLen;
6027 entity->open = XML_TRUE;
6028#ifdef XML_DTD
6029 entityTrackingOnOpen(parser, entity, __LINE__);
6030#endif
6031 result = appendAttributeValue(parser, parser->m_internalEncoding,
6032 isCdata, (const char *)entity->textPtr,
6033 (const char *)textEnd, pool,
6035#ifdef XML_DTD
6036 entityTrackingOnClose(parser, entity, __LINE__);
6037#endif
6038 entity->open = XML_FALSE;
6039 if (result)
6040 return result;
6041 }
6042 } break;
6043 default:
6044 /* The only token returned by XmlAttributeValueTok() that does
6045 * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
6046 * Getting that would require an entity name to contain an
6047 * incomplete XML character (e.g. \xE2\x82); however previous
6048 * tokenisers will have already recognised and rejected such
6049 * names before XmlAttributeValueTok() gets a look-in. This
6050 * default case should be retained as a safety net, but the code
6051 * excluded from coverage tests.
6052 *
6053 * LCOV_EXCL_START
6054 */
6055 if (enc == parser->m_encoding)
6056 parser->m_eventPtr = ptr;
6058 /* LCOV_EXCL_STOP */
6059 }
6060 ptr = next;
6061 }
6062 /* not reached */
6063}
6064
6065static enum XML_Error
6066storeEntityValue(XML_Parser parser, const ENCODING *enc,
6067 const char *entityTextPtr, const char *entityTextEnd,
6068 enum XML_Account account) {
6069 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6070 STRING_POOL *pool = &(dtd->entityValuePool);
6071 enum XML_Error result = XML_ERROR_NONE;
6072#ifdef XML_DTD
6073 int oldInEntityValue = parser->m_prologState.inEntityValue;
6074 parser->m_prologState.inEntityValue = 1;
6075#else
6076 UNUSED_P(account);
6077#endif /* XML_DTD */
6078 /* never return Null for the value argument in EntityDeclHandler,
6079 since this would indicate an external entity; therefore we
6080 have to make sure that entityValuePool.start is not null */
6081 if (! pool->blocks) {
6082 if (! poolGrow(pool))
6083 return XML_ERROR_NO_MEMORY;
6084 }
6085
6086 for (;;) {
6087 const char *next
6088 = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
6089 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
6090
6091#ifdef XML_DTD
6092 if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__,
6093 account)) {
6094 accountingOnAbort(parser);
6096 goto endEntityValue;
6097 }
6098#endif
6099
6100 switch (tok) {
6102#ifdef XML_DTD
6103 if (parser->m_isParamEntity || enc != parser->m_encoding) {
6104 const XML_Char *name;
6105 ENTITY *entity;
6106 name = poolStoreString(&parser->m_tempPool, enc,
6107 entityTextPtr + enc->minBytesPerChar,
6108 next - enc->minBytesPerChar);
6109 if (! name) {
6110 result = XML_ERROR_NO_MEMORY;
6111 goto endEntityValue;
6112 }
6113 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
6114 poolDiscard(&parser->m_tempPool);
6115 if (! entity) {
6116 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
6117 /* cannot report skipped entity here - see comments on
6118 parser->m_skippedEntityHandler
6119 if (parser->m_skippedEntityHandler)
6120 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
6121 */
6122 dtd->keepProcessing = dtd->standalone;
6123 goto endEntityValue;
6124 }
6125 if (entity->open) {
6126 if (enc == parser->m_encoding)
6127 parser->m_eventPtr = entityTextPtr;
6129 goto endEntityValue;
6130 }
6131 if (entity->systemId) {
6132 if (parser->m_externalEntityRefHandler) {
6133 dtd->paramEntityRead = XML_FALSE;
6134 entity->open = XML_TRUE;
6135 entityTrackingOnOpen(parser, entity, __LINE__);
6136 if (! parser->m_externalEntityRefHandler(
6137 parser->m_externalEntityRefHandlerArg, 0, entity->base,
6138 entity->systemId, entity->publicId)) {
6139 entityTrackingOnClose(parser, entity, __LINE__);
6140 entity->open = XML_FALSE;
6142 goto endEntityValue;
6143 }
6144 entityTrackingOnClose(parser, entity, __LINE__);
6145 entity->open = XML_FALSE;
6146 if (! dtd->paramEntityRead)
6147 dtd->keepProcessing = dtd->standalone;
6148 } else
6149 dtd->keepProcessing = dtd->standalone;
6150 } else {
6151 entity->open = XML_TRUE;
6152 entityTrackingOnOpen(parser, entity, __LINE__);
6153 result = storeEntityValue(
6154 parser, parser->m_internalEncoding, (const char *)entity->textPtr,
6155 (const char *)(entity->textPtr + entity->textLen),
6157 entityTrackingOnClose(parser, entity, __LINE__);
6158 entity->open = XML_FALSE;
6159 if (result)
6160 goto endEntityValue;
6161 }
6162 break;
6163 }
6164#endif /* XML_DTD */
6165 /* In the internal subset, PE references are not legal
6166 within markup declarations, e.g entity values in this case. */
6167 parser->m_eventPtr = entityTextPtr;
6169 goto endEntityValue;
6170 case XML_TOK_NONE:
6171 result = XML_ERROR_NONE;
6172 goto endEntityValue;
6173 case XML_TOK_ENTITY_REF:
6174 case XML_TOK_DATA_CHARS:
6175 if (! poolAppend(pool, enc, entityTextPtr, next)) {
6176 result = XML_ERROR_NO_MEMORY;
6177 goto endEntityValue;
6178 }
6179 break;
6181 next = entityTextPtr + enc->minBytesPerChar;
6182 /* fall through */
6184 if (pool->end == pool->ptr && ! poolGrow(pool)) {
6185 result = XML_ERROR_NO_MEMORY;
6186 goto endEntityValue;
6187 }
6188 *(pool->ptr)++ = 0xA;
6189 break;
6190 case XML_TOK_CHAR_REF: {
6192 int i;
6193 int n = XmlCharRefNumber(enc, entityTextPtr);
6194 if (n < 0) {
6195 if (enc == parser->m_encoding)
6196 parser->m_eventPtr = entityTextPtr;
6197 result = XML_ERROR_BAD_CHAR_REF;
6198 goto endEntityValue;
6199 }
6200 n = XmlEncode(n, (ICHAR *)buf);
6201 /* The XmlEncode() functions can never return 0 here. That
6202 * error return happens if the code point passed in is either
6203 * negative or greater than or equal to 0x110000. The
6204 * XmlCharRefNumber() functions will all return a number
6205 * strictly less than 0x110000 or a negative value if an error
6206 * occurred. The negative value is intercepted above, so
6207 * XmlEncode() is never passed a value it might return an
6208 * error for.
6209 */
6210 for (i = 0; i < n; i++) {
6211 if (pool->end == pool->ptr && ! poolGrow(pool)) {
6212 result = XML_ERROR_NO_MEMORY;
6213 goto endEntityValue;
6214 }
6215 *(pool->ptr)++ = buf[i];
6216 }
6217 } break;
6218 case XML_TOK_PARTIAL:
6219 if (enc == parser->m_encoding)
6220 parser->m_eventPtr = entityTextPtr;
6221 result = XML_ERROR_INVALID_TOKEN;
6222 goto endEntityValue;
6223 case XML_TOK_INVALID:
6224 if (enc == parser->m_encoding)
6225 parser->m_eventPtr = next;
6226 result = XML_ERROR_INVALID_TOKEN;
6227 goto endEntityValue;
6228 default:
6229 /* This default case should be unnecessary -- all the tokens
6230 * that XmlEntityValueTok() can return have their own explicit
6231 * cases -- but should be retained for safety. We do however
6232 * exclude it from the coverage statistics.
6233 *
6234 * LCOV_EXCL_START
6235 */
6236 if (enc == parser->m_encoding)
6237 parser->m_eventPtr = entityTextPtr;
6239 goto endEntityValue;
6240 /* LCOV_EXCL_STOP */
6241 }
6242 entityTextPtr = next;
6243 }
6244endEntityValue:
6245#ifdef XML_DTD
6246 parser->m_prologState.inEntityValue = oldInEntityValue;
6247#endif /* XML_DTD */
6248 return result;
6249}
6250
6251static void FASTCALL
6252normalizeLines(XML_Char *s) {
6253 XML_Char *p;
6254 for (;; s++) {
6255 if (*s == XML_T('\0'))
6256 return;
6257 if (*s == 0xD)
6258 break;
6259 }
6260 p = s;
6261 do {
6262 if (*s == 0xD) {
6263 *p++ = 0xA;
6264 if (*++s == 0xA)
6265 s++;
6266 } else
6267 *p++ = *s++;
6268 } while (*s);
6269 *p = XML_T('\0');
6270}
6271
6272static int
6273reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
6274 const char *start, const char *end) {
6275 const XML_Char *target;
6276 XML_Char *data;
6277 const char *tem;
6278 if (! parser->m_processingInstructionHandler) {
6279 if (parser->m_defaultHandler)
6280 reportDefault(parser, enc, start, end);
6281 return 1;
6282 }
6283 start += enc->minBytesPerChar * 2;
6284 tem = start + XmlNameLength(enc, start);
6285 target = poolStoreString(&parser->m_tempPool, enc, start, tem);
6286 if (! target)
6287 return 0;
6288 poolFinish(&parser->m_tempPool);
6289 data = poolStoreString(&parser->m_tempPool, enc, XmlSkipS(enc, tem),
6290 end - enc->minBytesPerChar * 2);
6291 if (! data)
6292 return 0;
6293 normalizeLines(data);
6294 parser->m_processingInstructionHandler(parser->m_handlerArg, target, data);
6295 poolClear(&parser->m_tempPool);
6296 return 1;
6297}
6298
6299static int
6300reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
6301 const char *end) {
6302 XML_Char *data;
6303 if (! parser->m_commentHandler) {
6304 if (parser->m_defaultHandler)
6305 reportDefault(parser, enc, start, end);
6306 return 1;
6307 }
6308 data = poolStoreString(&parser->m_tempPool, enc,
6309 start + enc->minBytesPerChar * 4,
6310 end - enc->minBytesPerChar * 3);
6311 if (! data)
6312 return 0;
6313 normalizeLines(data);
6314 parser->m_commentHandler(parser->m_handlerArg, data);
6315 poolClear(&parser->m_tempPool);
6316 return 1;
6317}
6318
6319static void
6320reportDefault(XML_Parser parser, const ENCODING *enc, const char *s,
6321 const char *end) {
6322 if (MUST_CONVERT(enc, s)) {
6323 enum XML_Convert_Result convert_res;
6324 const char **eventPP;
6325 const char **eventEndPP;
6326 if (enc == parser->m_encoding) {
6327 eventPP = &parser->m_eventPtr;
6328 eventEndPP = &parser->m_eventEndPtr;
6329 } else {
6330 /* To get here, two things must be true; the parser must be
6331 * using a character encoding that is not the same as the
6332 * encoding passed in, and the encoding passed in must need
6333 * conversion to the internal format (UTF-8 unless XML_UNICODE
6334 * is defined). The only occasions on which the encoding passed
6335 * in is not the same as the parser's encoding are when it is
6336 * the internal encoding (e.g. a previously defined parameter
6337 * entity, already converted to internal format). This by
6338 * definition doesn't need conversion, so the whole branch never
6339 * gets executed.
6340 *
6341 * For safety's sake we don't delete these lines and merely
6342 * exclude them from coverage statistics.
6343 *
6344 * LCOV_EXCL_START
6345 */
6346 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
6347 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
6348 /* LCOV_EXCL_STOP */
6349 }
6350 do {
6351 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
6352 convert_res
6353 = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
6354 *eventEndPP = s;
6355 parser->m_defaultHandler(parser->m_handlerArg, parser->m_dataBuf,
6356 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
6357 *eventPP = s;
6358 } while ((convert_res != XML_CONVERT_COMPLETED)
6359 && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
6360 } else
6361 parser->m_defaultHandler(parser->m_handlerArg, (XML_Char *)s,
6362 (int)((XML_Char *)end - (XML_Char *)s));
6363}
6364
6365static int
6366defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
6367 XML_Bool isId, const XML_Char *value, XML_Parser parser) {
6368 DEFAULT_ATTRIBUTE *att;
6369 if (value || isId) {
6370 /* The handling of default attributes gets messed up if we have
6371 a default which duplicates a non-default. */
6372 int i;
6373 for (i = 0; i < type->nDefaultAtts; i++)
6374 if (attId == type->defaultAtts[i].id)
6375 return 1;
6376 if (isId && ! type->idAtt && ! attId->xmlns)
6377 type->idAtt = attId;
6378 }
6379 if (type->nDefaultAtts == type->allocDefaultAtts) {
6380 if (type->allocDefaultAtts == 0) {
6381 type->allocDefaultAtts = 8;
6383 parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6384 if (! type->defaultAtts) {
6385 type->allocDefaultAtts = 0;
6386 return 0;
6387 }
6388 } else {
6389 DEFAULT_ATTRIBUTE *temp;
6390
6391 /* Detect and prevent integer overflow */
6392 if (type->allocDefaultAtts > INT_MAX / 2) {
6393 return 0;
6394 }
6395
6396 int count = type->allocDefaultAtts * 2;
6397
6398 /* Detect and prevent integer overflow.
6399 * The preprocessor guard addresses the "always false" warning
6400 * from -Wtype-limits on platforms where
6401 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
6402#if UINT_MAX >= SIZE_MAX
6403 if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) {
6404 return 0;
6405 }
6406#endif
6407
6408 temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
6409 (count * sizeof(DEFAULT_ATTRIBUTE)));
6410 if (temp == NULL)
6411 return 0;
6412 type->allocDefaultAtts = count;
6413 type->defaultAtts = temp;
6414 }
6415 }
6416 att = type->defaultAtts + type->nDefaultAtts;
6417 att->id = attId;
6418 att->value = value;
6419 att->isCdata = isCdata;
6420 if (! isCdata)
6421 attId->maybeTokenized = XML_TRUE;
6422 type->nDefaultAtts += 1;
6423 return 1;
6424}
6425
6426static int
6427setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) {
6428 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6429 const XML_Char *name;
6430 for (name = elementType->name; *name; name++) {
6431 if (*name == XML_T(ASCII_COLON)) {
6432 PREFIX *prefix;
6433 const XML_Char *s;
6434 for (s = elementType->name; s != name; s++) {
6435 if (! poolAppendChar(&dtd->pool, *s))
6436 return 0;
6437 }
6438 if (! poolAppendChar(&dtd->pool, XML_T('\0')))
6439 return 0;
6440 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
6441 sizeof(PREFIX));
6442 if (! prefix)
6443 return 0;
6444 if (prefix->name == poolStart(&dtd->pool))
6445 poolFinish(&dtd->pool);
6446 else
6447 poolDiscard(&dtd->pool);
6448 elementType->prefix = prefix;
6449 break;
6450 }
6451 }
6452 return 1;
6453}
6454
6455static ATTRIBUTE_ID *
6456getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
6457 const char *end) {
6458 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6459 ATTRIBUTE_ID *id;
6460 const XML_Char *name;
6461 if (! poolAppendChar(&dtd->pool, XML_T('\0')))
6462 return NULL;
6463 name = poolStoreString(&dtd->pool, enc, start, end);
6464 if (! name)
6465 return NULL;
6466 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
6467 ++name;
6468 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name,
6469 sizeof(ATTRIBUTE_ID));
6470 if (! id)
6471 return NULL;
6472 if (id->name != name)
6473 poolDiscard(&dtd->pool);
6474 else {
6475 poolFinish(&dtd->pool);
6476 if (! parser->m_ns)
6477 ;
6478 else if (name[0] == XML_T(ASCII_x) && name[1] == XML_T(ASCII_m)
6479 && name[2] == XML_T(ASCII_l) && name[3] == XML_T(ASCII_n)
6480 && name[4] == XML_T(ASCII_s)
6481 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
6482 if (name[5] == XML_T('\0'))
6483 id->prefix = &dtd->defaultPrefix;
6484 else
6485 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6,
6486 sizeof(PREFIX));
6487 id->xmlns = XML_TRUE;
6488 } else {
6489 int i;
6490 for (i = 0; name[i]; i++) {
6491 /* attributes without prefix are *not* in the default namespace */
6492 if (name[i] == XML_T(ASCII_COLON)) {
6493 int j;
6494 for (j = 0; j < i; j++) {
6495 if (! poolAppendChar(&dtd->pool, name[j]))
6496 return NULL;
6497 }
6498 if (! poolAppendChar(&dtd->pool, XML_T('\0')))
6499 return NULL;
6500 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes,
6501 poolStart(&dtd->pool), sizeof(PREFIX));
6502 if (! id->prefix)
6503 return NULL;
6504 if (id->prefix->name == poolStart(&dtd->pool))
6505 poolFinish(&dtd->pool);
6506 else
6507 poolDiscard(&dtd->pool);
6508 break;
6509 }
6510 }
6511 }
6512 }
6513 return id;
6514}
6515
6516#define CONTEXT_SEP XML_T(ASCII_FF)
6517
6518static const XML_Char *
6519getContext(XML_Parser parser) {
6520 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6521 HASH_TABLE_ITER iter;
6522 XML_Bool needSep = XML_FALSE;
6523
6524 if (dtd->defaultPrefix.binding) {
6525 int i;
6526 int len;
6527 if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
6528 return NULL;
6529 len = dtd->defaultPrefix.binding->uriLen;
6530 if (parser->m_namespaceSeparator)
6531 len--;
6532 for (i = 0; i < len; i++) {
6533 if (! poolAppendChar(&parser->m_tempPool,
6534 dtd->defaultPrefix.binding->uri[i])) {
6535 /* Because of memory caching, I don't believe this line can be
6536 * executed.
6537 *
6538 * This is part of a loop copying the default prefix binding
6539 * URI into the parser's temporary string pool. Previously,
6540 * that URI was copied into the same string pool, with a
6541 * terminating NUL character, as part of setContext(). When
6542 * the pool was cleared, that leaves a block definitely big
6543 * enough to hold the URI on the free block list of the pool.
6544 * The URI copy in getContext() therefore cannot run out of
6545 * memory.
6546 *
6547 * If the pool is used between the setContext() and
6548 * getContext() calls, the worst it can do is leave a bigger
6549 * block on the front of the free list. Given that this is
6550 * all somewhat inobvious and program logic can be changed, we
6551 * don't delete the line but we do exclude it from the test
6552 * coverage statistics.
6553 */
6554 return NULL; /* LCOV_EXCL_LINE */
6555 }
6556 }
6557 needSep = XML_TRUE;
6558 }
6559
6560 hashTableIterInit(&iter, &(dtd->prefixes));
6561 for (;;) {
6562 int i;
6563 int len;
6564 const XML_Char *s;
6565 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
6566 if (! prefix)
6567 break;
6568 if (! prefix->binding) {
6569 /* This test appears to be (justifiable) paranoia. There does
6570 * not seem to be a way of injecting a prefix without a binding
6571 * that doesn't get errored long before this function is called.
6572 * The test should remain for safety's sake, so we instead
6573 * exclude the following line from the coverage statistics.
6574 */
6575 continue; /* LCOV_EXCL_LINE */
6576 }
6577 if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
6578 return NULL;
6579 for (s = prefix->name; *s; s++)
6580 if (! poolAppendChar(&parser->m_tempPool, *s))
6581 return NULL;
6582 if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
6583 return NULL;
6584 len = prefix->binding->uriLen;
6585 if (parser->m_namespaceSeparator)
6586 len--;
6587 for (i = 0; i < len; i++)
6588 if (! poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i]))
6589 return NULL;
6590 needSep = XML_TRUE;
6591 }
6592
6593 hashTableIterInit(&iter, &(dtd->generalEntities));
6594 for (;;) {
6595 const XML_Char *s;
6596 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
6597 if (! e)
6598 break;
6599 if (! e->open)
6600 continue;
6601 if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
6602 return NULL;
6603 for (s = e->name; *s; s++)
6604 if (! poolAppendChar(&parser->m_tempPool, *s))
6605 return 0;
6606 needSep = XML_TRUE;
6607 }
6608
6609 if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6610 return NULL;
6611 return parser->m_tempPool.start;
6612}
6613
6614static XML_Bool
6615setContext(XML_Parser parser, const XML_Char *context) {
6616 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6617 const XML_Char *s = context;
6618
6619 while (*context != XML_T('\0')) {
6620 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
6621 ENTITY *e;
6622 if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6623 return XML_FALSE;
6624 e = (ENTITY *)lookup(parser, &dtd->generalEntities,
6625 poolStart(&parser->m_tempPool), 0);
6626 if (e)
6627 e->open = XML_TRUE;
6628 if (*s != XML_T('\0'))
6629 s++;
6630 context = s;
6631 poolDiscard(&parser->m_tempPool);
6632 } else if (*s == XML_T(ASCII_EQUALS)) {
6633 PREFIX *prefix;
6634 if (poolLength(&parser->m_tempPool) == 0)
6635 prefix = &dtd->defaultPrefix;
6636 else {
6637 if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6638 return XML_FALSE;
6639 prefix
6640 = (PREFIX *)lookup(parser, &dtd->prefixes,
6641 poolStart(&parser->m_tempPool), sizeof(PREFIX));
6642 if (! prefix)
6643 return XML_FALSE;
6644 if (prefix->name == poolStart(&parser->m_tempPool)) {
6645 prefix->name = poolCopyString(&dtd->pool, prefix->name);
6646 if (! prefix->name)
6647 return XML_FALSE;
6648 }
6649 poolDiscard(&parser->m_tempPool);
6650 }
6651 for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0');
6652 context++)
6653 if (! poolAppendChar(&parser->m_tempPool, *context))
6654 return XML_FALSE;
6655 if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
6656 return XML_FALSE;
6657 if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool),
6658 &parser->m_inheritedBindings)
6659 != XML_ERROR_NONE)
6660 return XML_FALSE;
6661 poolDiscard(&parser->m_tempPool);
6662 if (*context != XML_T('\0'))
6663 ++context;
6664 s = context;
6665 } else {
6666 if (! poolAppendChar(&parser->m_tempPool, *s))
6667 return XML_FALSE;
6668 s++;
6669 }
6670 }
6671 return XML_TRUE;
6672}
6673
6674static void FASTCALL
6675normalizePublicId(XML_Char *publicId) {
6676 XML_Char *p = publicId;
6677 XML_Char *s;
6678 for (s = publicId; *s; s++) {
6679 switch (*s) {
6680 case 0x20:
6681 case 0xD:
6682 case 0xA:
6683 if (p != publicId && p[-1] != 0x20)
6684 *p++ = 0x20;
6685 break;
6686 default:
6687 *p++ = *s;
6688 }
6689 }
6690 if (p != publicId && p[-1] == 0x20)
6691 --p;
6692 *p = XML_T('\0');
6693}
6694
6695static DTD *
6696dtdCreate(const XML_Memory_Handling_Suite *ms) {
6697 DTD *p = ms->malloc_fcn(sizeof(DTD));
6698 if (p == NULL)
6699 return p;
6700 poolInit(&(p->pool), ms);
6701 poolInit(&(p->entityValuePool), ms);
6702 hashTableInit(&(p->generalEntities), ms);
6703 hashTableInit(&(p->elementTypes), ms);
6704 hashTableInit(&(p->attributeIds), ms);
6705 hashTableInit(&(p->prefixes), ms);
6706#ifdef XML_DTD
6707 p->paramEntityRead = XML_FALSE;
6708 hashTableInit(&(p->paramEntities), ms);
6709#endif /* XML_DTD */
6710 p->defaultPrefix.name = NULL;
6711 p->defaultPrefix.binding = NULL;
6712
6713 p->in_eldecl = XML_FALSE;
6714 p->scaffIndex = NULL;
6715 p->scaffold = NULL;
6716 p->scaffLevel = 0;
6717 p->scaffSize = 0;
6718 p->scaffCount = 0;
6719 p->contentStringLen = 0;
6720
6723 p->standalone = XML_FALSE;
6724 return p;
6725}
6726
6727static void
6728dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {
6729 HASH_TABLE_ITER iter;
6730 hashTableIterInit(&iter, &(p->elementTypes));
6731 for (;;) {
6732 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6733 if (! e)
6734 break;
6735 if (e->allocDefaultAtts != 0)
6736 ms->free_fcn(e->defaultAtts);
6737 }
6738 hashTableClear(&(p->generalEntities));
6739#ifdef XML_DTD
6740 p->paramEntityRead = XML_FALSE;
6741 hashTableClear(&(p->paramEntities));
6742#endif /* XML_DTD */
6743 hashTableClear(&(p->elementTypes));
6744 hashTableClear(&(p->attributeIds));
6745 hashTableClear(&(p->prefixes));
6746 poolClear(&(p->pool));
6747 poolClear(&(p->entityValuePool));
6748 p->defaultPrefix.name = NULL;
6749 p->defaultPrefix.binding = NULL;
6750
6751 p->in_eldecl = XML_FALSE;
6752
6753 ms->free_fcn(p->scaffIndex);
6754 p->scaffIndex = NULL;
6755 ms->free_fcn(p->scaffold);
6756 p->scaffold = NULL;
6757
6758 p->scaffLevel = 0;
6759 p->scaffSize = 0;
6760 p->scaffCount = 0;
6761 p->contentStringLen = 0;
6762
6765 p->standalone = XML_FALSE;
6766}
6767
6768static void
6769dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
6770 HASH_TABLE_ITER iter;
6771 hashTableIterInit(&iter, &(p->elementTypes));
6772 for (;;) {
6773 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6774 if (! e)
6775 break;
6776 if (e->allocDefaultAtts != 0)
6777 ms->free_fcn(e->defaultAtts);
6778 }
6779 hashTableDestroy(&(p->generalEntities));
6780#ifdef XML_DTD
6781 hashTableDestroy(&(p->paramEntities));
6782#endif /* XML_DTD */
6783 hashTableDestroy(&(p->elementTypes));
6784 hashTableDestroy(&(p->attributeIds));
6785 hashTableDestroy(&(p->prefixes));
6786 poolDestroy(&(p->pool));
6787 poolDestroy(&(p->entityValuePool));
6788 if (isDocEntity) {
6789 ms->free_fcn(p->scaffIndex);
6790 ms->free_fcn(p->scaffold);
6791 }
6792 ms->free_fcn(p);
6793}
6794
6795/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
6796 The new DTD has already been initialized.
6797*/
6798static int
6799dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
6800 const XML_Memory_Handling_Suite *ms) {
6801 HASH_TABLE_ITER iter;
6802
6803 /* Copy the prefix table. */
6804
6805 hashTableIterInit(&iter, &(oldDtd->prefixes));
6806 for (;;) {
6807 const XML_Char *name;
6808 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
6809 if (! oldP)
6810 break;
6811 name = poolCopyString(&(newDtd->pool), oldP->name);
6812 if (! name)
6813 return 0;
6814 if (! lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
6815 return 0;
6816 }
6817
6818 hashTableIterInit(&iter, &(oldDtd->attributeIds));
6819
6820 /* Copy the attribute id table. */
6821
6822 for (;;) {
6823 ATTRIBUTE_ID *newA;
6824 const XML_Char *name;
6825 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
6826
6827 if (! oldA)
6828 break;
6829 /* Remember to allocate the scratch byte before the name. */
6830 if (! poolAppendChar(&(newDtd->pool), XML_T('\0')))
6831 return 0;
6832 name = poolCopyString(&(newDtd->pool), oldA->name);
6833 if (! name)
6834 return 0;
6835 ++name;
6836 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
6837 sizeof(ATTRIBUTE_ID));
6838 if (! newA)
6839 return 0;
6840 newA->maybeTokenized = oldA->maybeTokenized;
6841 if (oldA->prefix) {
6842 newA->xmlns = oldA->xmlns;
6843 if (oldA->prefix == &oldDtd->defaultPrefix)
6844 newA->prefix = &newDtd->defaultPrefix;
6845 else
6846 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
6847 oldA->prefix->name, 0);
6848 }
6849 }
6850
6851 /* Copy the element type table. */
6852
6853 hashTableIterInit(&iter, &(oldDtd->elementTypes));
6854
6855 for (;;) {
6856 int i;
6857 ELEMENT_TYPE *newE;
6858 const XML_Char *name;
6859 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6860 if (! oldE)
6861 break;
6862 name = poolCopyString(&(newDtd->pool), oldE->name);
6863 if (! name)
6864 return 0;
6865 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
6866 sizeof(ELEMENT_TYPE));
6867 if (! newE)
6868 return 0;
6869 if (oldE->nDefaultAtts) {
6870 newE->defaultAtts
6871 = ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6872 if (! newE->defaultAtts) {
6873 return 0;
6874 }
6875 }
6876 if (oldE->idAtt)
6877 newE->idAtt = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds),
6878 oldE->idAtt->name, 0);
6879 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
6880 if (oldE->prefix)
6881 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
6882 oldE->prefix->name, 0);
6883 for (i = 0; i < newE->nDefaultAtts; i++) {
6884 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(
6885 oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
6886 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
6887 if (oldE->defaultAtts[i].value) {
6888 newE->defaultAtts[i].value
6889 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
6890 if (! newE->defaultAtts[i].value)
6891 return 0;
6892 } else
6893 newE->defaultAtts[i].value = NULL;
6894 }
6895 }
6896
6897 /* Copy the entity tables. */
6898 if (! copyEntityTable(oldParser, &(newDtd->generalEntities), &(newDtd->pool),
6899 &(oldDtd->generalEntities)))
6900 return 0;
6901
6902#ifdef XML_DTD
6903 if (! copyEntityTable(oldParser, &(newDtd->paramEntities), &(newDtd->pool),
6904 &(oldDtd->paramEntities)))
6905 return 0;
6906 newDtd->paramEntityRead = oldDtd->paramEntityRead;
6907#endif /* XML_DTD */
6908
6909 newDtd->keepProcessing = oldDtd->keepProcessing;
6910 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
6911 newDtd->standalone = oldDtd->standalone;
6912
6913 /* Don't want deep copying for scaffolding */
6914 newDtd->in_eldecl = oldDtd->in_eldecl;
6915 newDtd->scaffold = oldDtd->scaffold;
6916 newDtd->contentStringLen = oldDtd->contentStringLen;
6917 newDtd->scaffSize = oldDtd->scaffSize;
6918 newDtd->scaffLevel = oldDtd->scaffLevel;
6919 newDtd->scaffIndex = oldDtd->scaffIndex;
6920
6921 return 1;
6922} /* End dtdCopy */
6923
6924static int
6925copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
6926 STRING_POOL *newPool, const HASH_TABLE *oldTable) {
6927 HASH_TABLE_ITER iter;
6928 const XML_Char *cachedOldBase = NULL;
6929 const XML_Char *cachedNewBase = NULL;
6930
6931 hashTableIterInit(&iter, oldTable);
6932
6933 for (;;) {
6934 ENTITY *newE;
6935 const XML_Char *name;
6936 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
6937 if (! oldE)
6938 break;
6939 name = poolCopyString(newPool, oldE->name);
6940 if (! name)
6941 return 0;
6942 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
6943 if (! newE)
6944 return 0;
6945 if (oldE->systemId) {
6946 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
6947 if (! tem)
6948 return 0;
6949 newE->systemId = tem;
6950 if (oldE->base) {
6951 if (oldE->base == cachedOldBase)
6952 newE->base = cachedNewBase;
6953 else {
6954 cachedOldBase = oldE->base;
6955 tem = poolCopyString(newPool, cachedOldBase);
6956 if (! tem)
6957 return 0;
6958 cachedNewBase = newE->base = tem;
6959 }
6960 }
6961 if (oldE->publicId) {
6962 tem = poolCopyString(newPool, oldE->publicId);
6963 if (! tem)
6964 return 0;
6965 newE->publicId = tem;
6966 }
6967 } else {
6968 const XML_Char *tem
6969 = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
6970 if (! tem)
6971 return 0;
6972 newE->textPtr = tem;
6973 newE->textLen = oldE->textLen;
6974 }
6975 if (oldE->notation) {
6976 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
6977 if (! tem)
6978 return 0;
6979 newE->notation = tem;
6980 }
6981 newE->is_param = oldE->is_param;
6982 newE->is_internal = oldE->is_internal;
6983 }
6984 return 1;
6985}
6986
6987#define INIT_POWER 6
6988
6989static XML_Bool FASTCALL
6990keyeq(KEY s1, KEY s2) {
6991 for (; *s1 == *s2; s1++, s2++)
6992 if (*s1 == 0)
6993 return XML_TRUE;
6994 return XML_FALSE;
6995}
6996
6997static size_t
6998keylen(KEY s) {
6999 size_t len = 0;
7000 for (; *s; s++, len++)
7001 ;
7002 return len;
7003}
7004
7005static void
7006copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
7007 key->k[0] = 0;
7008 key->k[1] = get_hash_secret_salt(parser);
7009}
7010
7011static unsigned long FASTCALL
7012hash(XML_Parser parser, KEY s) {
7013 struct siphash state;
7014 struct sipkey key;
7015 (void)sip24_valid;
7016 copy_salt_to_sipkey(parser, &key);
7017 sip24_init(&state, &key);
7018 sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
7019 return (unsigned long)sip24_final(&state);
7020}
7021
7022static NAMED *
7023lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
7024 size_t i;
7025 if (table->size == 0) {
7026 size_t tsize;
7027 if (! createSize)
7028 return NULL;
7029 table->power = INIT_POWER;
7030 /* table->size is a power of 2 */
7031 table->size = (size_t)1 << INIT_POWER;
7032 tsize = table->size * sizeof(NAMED *);
7033 table->v = table->mem->malloc_fcn(tsize);
7034 if (! table->v) {
7035 table->size = 0;
7036 return NULL;
7037 }
7038 memset(table->v, 0, tsize);
7039 i = hash(parser, name) & ((unsigned long)table->size - 1);
7040 } else {
7041 unsigned long h = hash(parser, name);
7042 unsigned long mask = (unsigned long)table->size - 1;
7043 unsigned char step = 0;
7044 i = h & mask;
7045 while (table->v[i]) {
7046 if (keyeq(name, table->v[i]->name))
7047 return table->v[i];
7048 if (! step)
7049 step = PROBE_STEP(h, mask, table->power);
7050 i < step ? (i += table->size - step) : (i -= step);
7051 }
7052 if (! createSize)
7053 return NULL;
7054
7055 /* check for overflow (table is half full) */
7056 if (table->used >> (table->power - 1)) {
7057 unsigned char newPower = table->power + 1;
7058
7059 /* Detect and prevent invalid shift */
7060 if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
7061 return NULL;
7062 }
7063
7064 size_t newSize = (size_t)1 << newPower;
7065 unsigned long newMask = (unsigned long)newSize - 1;
7066
7067 /* Detect and prevent integer overflow */
7068 if (newSize > (size_t)(-1) / sizeof(NAMED *)) {
7069 return NULL;
7070 }
7071
7072 size_t tsize = newSize * sizeof(NAMED *);
7073 NAMED **newV = table->mem->malloc_fcn(tsize);
7074 if (! newV)
7075 return NULL;
7076 memset(newV, 0, tsize);
7077 for (i = 0; i < table->size; i++)
7078 if (table->v[i]) {
7079 unsigned long newHash = hash(parser, table->v[i]->name);
7080 size_t j = newHash & newMask;
7081 step = 0;
7082 while (newV[j]) {
7083 if (! step)
7084 step = PROBE_STEP(newHash, newMask, newPower);
7085 j < step ? (j += newSize - step) : (j -= step);
7086 }
7087 newV[j] = table->v[i];
7088 }
7089 table->mem->free_fcn(table->v);
7090 table->v = newV;
7091 table->power = newPower;
7092 table->size = newSize;
7093 i = h & newMask;
7094 step = 0;
7095 while (table->v[i]) {
7096 if (! step)
7097 step = PROBE_STEP(h, newMask, newPower);
7098 i < step ? (i += newSize - step) : (i -= step);
7099 }
7100 }
7101 }
7102 table->v[i] = table->mem->malloc_fcn(createSize);
7103 if (! table->v[i])
7104 return NULL;
7105 memset(table->v[i], 0, createSize);
7106 table->v[i]->name = name;
7107 (table->used)++;
7108 return table->v[i];
7109}
7110
7111static void FASTCALL
7112hashTableClear(HASH_TABLE *table) {
7113 size_t i;
7114 for (i = 0; i < table->size; i++) {
7115 table->mem->free_fcn(table->v[i]);
7116 table->v[i] = NULL;
7117 }
7118 table->used = 0;
7119}
7120
7121static void FASTCALL
7122hashTableDestroy(HASH_TABLE *table) {
7123 size_t i;
7124 for (i = 0; i < table->size; i++)
7125 table->mem->free_fcn(table->v[i]);
7126 table->mem->free_fcn(table->v);
7127}
7128
7129static void FASTCALL
7130hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) {
7131 p->power = 0;
7132 p->size = 0;
7133 p->used = 0;
7134 p->v = NULL;
7135 p->mem = ms;
7136}
7137
7138static void FASTCALL
7139hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
7140 iter->p = table->v;
7141 iter->end = iter->p ? iter->p + table->size : NULL;
7142}
7143
7144static NAMED *FASTCALL
7145hashTableIterNext(HASH_TABLE_ITER *iter) {
7146 while (iter->p != iter->end) {
7147 NAMED *tem = *(iter->p)++;
7148 if (tem)
7149 return tem;
7150 }
7151 return NULL;
7152}
7153
7154static void FASTCALL
7155poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) {
7156 pool->blocks = NULL;
7157 pool->freeBlocks = NULL;
7158 pool->start = NULL;
7159 pool->ptr = NULL;
7160 pool->end = NULL;
7161 pool->mem = ms;
7162}
7163
7164static void FASTCALL
7165poolClear(STRING_POOL *pool) {
7166 if (! pool->freeBlocks)
7167 pool->freeBlocks = pool->blocks;
7168 else {
7169 BLOCK *p = pool->blocks;
7170 while (p) {
7171 BLOCK *tem = p->next;
7172 p->next = pool->freeBlocks;
7173 pool->freeBlocks = p;
7174 p = tem;
7175 }
7176 }
7177 pool->blocks = NULL;
7178 pool->start = NULL;
7179 pool->ptr = NULL;
7180 pool->end = NULL;
7181}
7182
7183static void FASTCALL
7184poolDestroy(STRING_POOL *pool) {
7185 BLOCK *p = pool->blocks;
7186 while (p) {
7187 BLOCK *tem = p->next;
7188 pool->mem->free_fcn(p);
7189 p = tem;
7190 }
7191 p = pool->freeBlocks;
7192 while (p) {
7193 BLOCK *tem = p->next;
7194 pool->mem->free_fcn(p);
7195 p = tem;
7196 }
7197}
7198
7199static XML_Char *
7200poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
7201 const char *end) {
7202 if (! pool->ptr && ! poolGrow(pool))
7203 return NULL;
7204 for (;;) {
7205 const enum XML_Convert_Result convert_res = XmlConvert(
7206 enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
7207 if ((convert_res == XML_CONVERT_COMPLETED)
7208 || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
7209 break;
7210 if (! poolGrow(pool))
7211 return NULL;
7212 }
7213 return pool->start;
7214}
7215
7216static const XML_Char *FASTCALL
7217poolCopyString(STRING_POOL *pool, const XML_Char *s) {
7218 do {
7219 if (! poolAppendChar(pool, *s))
7220 return NULL;
7221 } while (*s++);
7222 s = pool->start;
7223 poolFinish(pool);
7224 return s;
7225}
7226
7227static const XML_Char *
7228poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) {
7229 if (! pool->ptr && ! poolGrow(pool)) {
7230 /* The following line is unreachable given the current usage of
7231 * poolCopyStringN(). Currently it is called from exactly one
7232 * place to copy the text of a simple general entity. By that
7233 * point, the name of the entity is already stored in the pool, so
7234 * pool->ptr cannot be NULL.
7235 *
7236 * If poolCopyStringN() is used elsewhere as it well might be,
7237 * this line may well become executable again. Regardless, this
7238 * sort of check shouldn't be removed lightly, so we just exclude
7239 * it from the coverage statistics.
7240 */
7241 return NULL; /* LCOV_EXCL_LINE */
7242 }
7243 for (; n > 0; --n, s++) {
7244 if (! poolAppendChar(pool, *s))
7245 return NULL;
7246 }
7247 s = pool->start;
7248 poolFinish(pool);
7249 return s;
7250}
7251
7252static const XML_Char *FASTCALL
7253poolAppendString(STRING_POOL *pool, const XML_Char *s) {
7254 while (*s) {
7255 if (! poolAppendChar(pool, *s))
7256 return NULL;
7257 s++;
7258 }
7259 return pool->start;
7260}
7261
7262static XML_Char *
7263poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
7264 const char *end) {
7265 if (! poolAppend(pool, enc, ptr, end))
7266 return NULL;
7267 if (pool->ptr == pool->end && ! poolGrow(pool))
7268 return NULL;
7269 *(pool->ptr)++ = 0;
7270 return pool->start;
7271}
7272
7273static size_t
7274poolBytesToAllocateFor(int blockSize) {
7275 /* Unprotected math would be:
7276 ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
7277 **
7278 ** Detect overflow, avoiding _signed_ overflow undefined behavior
7279 ** For a + b * c we check b * c in isolation first, so that addition of a
7280 ** on top has no chance of making us accept a small non-negative number
7281 */
7282 const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
7283
7284 if (blockSize <= 0)
7285 return 0;
7286
7287 if (blockSize > (int)(INT_MAX / stretch))
7288 return 0;
7289
7290 {
7291 const int stretchedBlockSize = blockSize * (int)stretch;
7292 const int bytesToAllocate
7293 = (int)(offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
7294 if (bytesToAllocate < 0)
7295 return 0;
7296
7297 return (size_t)bytesToAllocate;
7298 }
7299}
7300
7301static XML_Bool FASTCALL
7302poolGrow(STRING_POOL *pool) {
7303 if (pool->freeBlocks) {
7304 if (pool->start == 0) {
7305 pool->blocks = pool->freeBlocks;
7306 pool->freeBlocks = pool->freeBlocks->next;
7307 pool->blocks->next = NULL;
7308 pool->start = pool->blocks->s;
7309 pool->end = pool->start + pool->blocks->size;
7310 pool->ptr = pool->start;
7311 return XML_TRUE;
7312 }
7313 if (pool->end - pool->start < pool->freeBlocks->size) {
7314 BLOCK *tem = pool->freeBlocks->next;
7315 pool->freeBlocks->next = pool->blocks;
7316 pool->blocks = pool->freeBlocks;
7317 pool->freeBlocks = tem;
7318 memcpy(pool->blocks->s, pool->start,
7319 (pool->end - pool->start) * sizeof(XML_Char));
7320 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
7321 pool->start = pool->blocks->s;
7322 pool->end = pool->start + pool->blocks->size;
7323 return XML_TRUE;
7324 }
7325 }
7326 if (pool->blocks && pool->start == pool->blocks->s) {
7327 BLOCK *temp;
7328 int blockSize = (int)((unsigned)(pool->end - pool->start) * 2U);
7329 size_t bytesToAllocate;
7330
7331 /* NOTE: Needs to be calculated prior to calling `realloc`
7332 to avoid dangling pointers: */
7333 const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
7334
7335 if (blockSize < 0) {
7336 /* This condition traps a situation where either more than
7337 * INT_MAX/2 bytes have already been allocated. This isn't
7338 * readily testable, since it is unlikely that an average
7339 * machine will have that much memory, so we exclude it from the
7340 * coverage statistics.
7341 */
7342 return XML_FALSE; /* LCOV_EXCL_LINE */
7343 }
7344
7345 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7346 if (bytesToAllocate == 0)
7347 return XML_FALSE;
7348
7349 temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks,
7350 (unsigned)bytesToAllocate);
7351 if (temp == NULL)
7352 return XML_FALSE;
7353 pool->blocks = temp;
7354 pool->blocks->size = blockSize;
7355 pool->ptr = pool->blocks->s + offsetInsideBlock;
7356 pool->start = pool->blocks->s;
7357 pool->end = pool->start + blockSize;
7358 } else {
7359 BLOCK *tem;
7360 int blockSize = (int)(pool->end - pool->start);
7361 size_t bytesToAllocate;
7362
7363 if (blockSize < 0) {
7364 /* This condition traps a situation where either more than
7365 * INT_MAX bytes have already been allocated (which is prevented
7366 * by various pieces of program logic, not least this one, never
7367 * mind the unlikelihood of actually having that much memory) or
7368 * the pool control fields have been corrupted (which could
7369 * conceivably happen in an extremely buggy user handler
7370 * function). Either way it isn't readily testable, so we
7371 * exclude it from the coverage statistics.
7372 */
7373 return XML_FALSE; /* LCOV_EXCL_LINE */
7374 }
7375
7376 if (blockSize < INIT_BLOCK_SIZE)
7377 blockSize = INIT_BLOCK_SIZE;
7378 else {
7379 /* Detect overflow, avoiding _signed_ overflow undefined behavior */
7380 if ((int)((unsigned)blockSize * 2U) < 0) {
7381 return XML_FALSE;
7382 }
7383 blockSize *= 2;
7384 }
7385
7386 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7387 if (bytesToAllocate == 0)
7388 return XML_FALSE;
7389
7390 tem = pool->mem->malloc_fcn(bytesToAllocate);
7391 if (! tem)
7392 return XML_FALSE;
7393 tem->size = blockSize;
7394 tem->next = pool->blocks;
7395 pool->blocks = tem;
7396 if (pool->ptr != pool->start)
7397 memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
7398 pool->ptr = tem->s + (pool->ptr - pool->start);
7399 pool->start = tem->s;
7400 pool->end = tem->s + blockSize;
7401 }
7402 return XML_TRUE;
7403}
7404
7405static int FASTCALL
7406nextScaffoldPart(XML_Parser parser) {
7407 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7408 CONTENT_SCAFFOLD *me;
7409 int next;
7410
7411 if (! dtd->scaffIndex) {
7412 dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
7413 if (! dtd->scaffIndex)
7414 return -1;
7415 dtd->scaffIndex[0] = 0;
7416 }
7417
7418 if (dtd->scaffCount >= dtd->scaffSize) {
7419 CONTENT_SCAFFOLD *temp;
7420 if (dtd->scaffold) {
7421 /* Detect and prevent integer overflow */
7422 if (dtd->scaffSize > UINT_MAX / 2u) {
7423 return -1;
7424 }
7425 /* Detect and prevent integer overflow.
7426 * The preprocessor guard addresses the "always false" warning
7427 * from -Wtype-limits on platforms where
7428 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
7429#if UINT_MAX >= SIZE_MAX
7430 if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) {
7431 return -1;
7432 }
7433#endif
7434
7435 temp = (CONTENT_SCAFFOLD *)REALLOC(
7436 parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
7437 if (temp == NULL)
7438 return -1;
7439 dtd->scaffSize *= 2;
7440 } else {
7442 * sizeof(CONTENT_SCAFFOLD));
7443 if (temp == NULL)
7444 return -1;
7446 }
7447 dtd->scaffold = temp;
7448 }
7449 next = dtd->scaffCount++;
7450 me = &dtd->scaffold[next];
7451 if (dtd->scaffLevel) {
7452 CONTENT_SCAFFOLD *parent
7453 = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]];
7454 if (parent->lastchild) {
7455 dtd->scaffold[parent->lastchild].nextsib = next;
7456 }
7457 if (! parent->childcnt)
7458 parent->firstchild = next;
7459 parent->lastchild = next;
7460 parent->childcnt++;
7461 }
7462 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
7463 return next;
7464}
7465
7466static XML_Content *
7467build_model(XML_Parser parser) {
7468 /* Function build_model transforms the existing parser->m_dtd->scaffold
7469 * array of CONTENT_SCAFFOLD tree nodes into a new array of
7470 * XML_Content tree nodes followed by a gapless list of zero-terminated
7471 * strings. */
7472 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7473 XML_Content *ret;
7474 XML_Char *str; /* the current string writing location */
7475
7476 /* Detect and prevent integer overflow.
7477 * The preprocessor guard addresses the "always false" warning
7478 * from -Wtype-limits on platforms where
7479 * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
7480#if UINT_MAX >= SIZE_MAX
7481 if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) {
7482 return NULL;
7483 }
7484 if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) {
7485 return NULL;
7486 }
7487#endif
7488 if (dtd->scaffCount * sizeof(XML_Content)
7489 > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) {
7490 return NULL;
7491 }
7492
7493 const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
7494 + (dtd->contentStringLen * sizeof(XML_Char)));
7495
7496 ret = (XML_Content *)MALLOC(parser, allocsize);
7497 if (! ret)
7498 return NULL;
7499
7500 /* What follows is an iterative implementation (of what was previously done
7501 * recursively in a dedicated function called "build_node". The old recursive
7502 * build_node could be forced into stack exhaustion from input as small as a
7503 * few megabyte, and so that was a security issue. Hence, a function call
7504 * stack is avoided now by resolving recursion.)
7505 *
7506 * The iterative approach works as follows:
7507 *
7508 * - We have two writing pointers, both walking up the result array; one does
7509 * the work, the other creates "jobs" for its colleague to do, and leads
7510 * the way:
7511 *
7512 * - The faster one, pointer jobDest, always leads and writes "what job
7513 * to do" by the other, once they reach that place in the
7514 * array: leader "jobDest" stores the source node array index (relative
7515 * to array dtd->scaffold) in field "numchildren".
7516 *
7517 * - The slower one, pointer dest, looks at the value stored in the
7518 * "numchildren" field (which actually holds a source node array index
7519 * at that time) and puts the real data from dtd->scaffold in.
7520 *
7521 * - Before the loop starts, jobDest writes source array index 0
7522 * (where the root node is located) so that dest will have something to do
7523 * when it starts operation.
7524 *
7525 * - Whenever nodes with children are encountered, jobDest appends
7526 * them as new jobs, in order. As a result, tree node siblings are
7527 * adjacent in the resulting array, for example:
7528 *
7529 * [0] root, has two children
7530 * [1] first child of 0, has three children
7531 * [3] first child of 1, does not have children
7532 * [4] second child of 1, does not have children
7533 * [5] third child of 1, does not have children
7534 * [2] second child of 0, does not have children
7535 *
7536 * Or (the same data) presented in flat array view:
7537 *
7538 * [0] root, has two children
7539 *
7540 * [1] first child of 0, has three children
7541 * [2] second child of 0, does not have children
7542 *
7543 * [3] first child of 1, does not have children
7544 * [4] second child of 1, does not have children
7545 * [5] third child of 1, does not have children
7546 *
7547 * - The algorithm repeats until all target array indices have been processed.
7548 */
7549 XML_Content *dest = ret; /* tree node writing location, moves upwards */
7550 XML_Content *const destLimit = &ret[dtd->scaffCount];
7551 XML_Content *jobDest = ret; /* next free writing location in target array */
7552 str = (XML_Char *)&ret[dtd->scaffCount];
7553
7554 /* Add the starting job, the root node (index 0) of the source tree */
7555 (jobDest++)->numchildren = 0;
7556
7557 for (; dest < destLimit; dest++) {
7558 /* Retrieve source tree array index from job storage */
7559 const int src_node = (int)dest->numchildren;
7560
7561 /* Convert item */
7562 dest->type = dtd->scaffold[src_node].type;
7563 dest->quant = dtd->scaffold[src_node].quant;
7564 if (dest->type == XML_CTYPE_NAME) {
7565 const XML_Char *src;
7566 dest->name = str;
7567 src = dtd->scaffold[src_node].name;
7568 for (;;) {
7569 *str++ = *src;
7570 if (! *src)
7571 break;
7572 src++;
7573 }
7574 dest->numchildren = 0;
7575 dest->children = NULL;
7576 } else {
7577 unsigned int i;
7578 int cn;
7579 dest->name = NULL;
7580 dest->numchildren = dtd->scaffold[src_node].childcnt;
7581 dest->children = jobDest;
7582
7583 /* Append scaffold indices of children to array */
7584 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
7585 i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib)
7586 (jobDest++)->numchildren = (unsigned int)cn;
7587 }
7588 }
7589
7590 return ret;
7591}
7592
7593static ELEMENT_TYPE *
7594getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
7595 const char *end) {
7596 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7597 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
7598 ELEMENT_TYPE *ret;
7599
7600 if (! name)
7601 return NULL;
7602 ret = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
7603 sizeof(ELEMENT_TYPE));
7604 if (! ret)
7605 return NULL;
7606 if (ret->name != name)
7607 poolDiscard(&dtd->pool);
7608 else {
7609 poolFinish(&dtd->pool);
7610 if (! setElementTypePrefix(parser, ret))
7611 return NULL;
7612 }
7613 return ret;
7614}
7615
7616static XML_Char *
7617copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
7618 size_t charsRequired = 0;
7619 XML_Char *result;
7620
7621 /* First determine how long the string is */
7622 while (s[charsRequired] != 0) {
7623 charsRequired++;
7624 }
7625 /* Include the terminator */
7626 charsRequired++;
7627
7628 /* Now allocate space for the copy */
7629 result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
7630 if (result == NULL)
7631 return NULL;
7632 /* Copy the original into place */
7633 memcpy(result, s, charsRequired * sizeof(XML_Char));
7634 return result;
7635}
7636
7637#ifdef XML_DTD
7638
7639static float
7640accountingGetCurrentAmplification(XML_Parser rootParser) {
7641 const XmlBigCount countBytesOutput
7642 = rootParser->m_accounting.countBytesDirect
7643 + rootParser->m_accounting.countBytesIndirect;
7644 const float amplificationFactor
7645 = rootParser->m_accounting.countBytesDirect
7646 ? (countBytesOutput
7647 / (float)(rootParser->m_accounting.countBytesDirect))
7648 : 1.0f;
7649 assert(! rootParser->m_parentParser);
7650 return amplificationFactor;
7651}
7652
7653static void
7654accountingReportStats(XML_Parser originParser, const char *epilog) {
7655 const XML_Parser rootParser = getRootParserOf(originParser, NULL);
7656 assert(! rootParser->m_parentParser);
7657
7658 if (rootParser->m_accounting.debugLevel < 1) {
7659 return;
7660 }
7661
7662 const float amplificationFactor
7663 = accountingGetCurrentAmplification(rootParser);
7664 fprintf(stderr,
7665 "expat: Accounting(%p): Direct " EXPAT_FMT_ULL(
7666 "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s",
7667 (void *)rootParser, rootParser->m_accounting.countBytesDirect,
7668 rootParser->m_accounting.countBytesIndirect,
7669 (double)amplificationFactor, epilog);
7670}
7671
7672static void
7673accountingOnAbort(XML_Parser originParser) {
7674 accountingReportStats(originParser, " ABORTING\n");
7675}
7676
7677static void
7678accountingReportDiff(XML_Parser rootParser,
7679 unsigned int levelsAwayFromRootParser, const char *before,
7680 const char *after, ptrdiff_t bytesMore, int source_line,
7681 enum XML_Account account) {
7682 assert(! rootParser->m_parentParser);
7683
7684 fprintf(stderr,
7685 " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"",
7686 bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP",
7687 levelsAwayFromRootParser, source_line, 10, "");
7688
7689 const char ellipis[] = "[..]";
7690 const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1;
7691 const unsigned int contextLength = 10;
7692
7693 /* Note: Performance is of no concern here */
7694 const char *walker = before;
7695 if ((rootParser->m_accounting.debugLevel >= 3)
7696 || (after - before)
7697 <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) {
7698 for (; walker < after; walker++) {
7699 fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
7700 }
7701 } else {
7702 for (; walker < before + contextLength; walker++) {
7703 fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
7704 }
7705 fprintf(stderr, ellipis);
7706 walker = after - contextLength;
7707 for (; walker < after; walker++) {
7708 fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
7709 }
7710 }
7711 fprintf(stderr, "\"\n");
7712}
7713
7714static XML_Bool
7715accountingDiffTolerated(XML_Parser originParser, int tok, const char *before,
7716 const char *after, int source_line,
7717 enum XML_Account account) {
7718 /* Note: We need to check the token type *first* to be sure that
7719 * we can even access variable <after>, safely.
7720 * E.g. for XML_TOK_NONE <after> may hold an invalid pointer. */
7721 switch (tok) {
7722 case XML_TOK_INVALID:
7723 case XML_TOK_PARTIAL:
7725 case XML_TOK_NONE:
7726 return XML_TRUE;
7727 }
7728
7729 if (account == XML_ACCOUNT_NONE)
7730 return XML_TRUE; /* because these bytes have been accounted for, already */
7731
7732 unsigned int levelsAwayFromRootParser;
7733 const XML_Parser rootParser
7734 = getRootParserOf(originParser, &levelsAwayFromRootParser);
7735 assert(! rootParser->m_parentParser);
7736
7737 const int isDirect
7738 = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser);
7739 const ptrdiff_t bytesMore = after - before;
7740
7741 XmlBigCount *const additionTarget
7742 = isDirect ? &rootParser->m_accounting.countBytesDirect
7743 : &rootParser->m_accounting.countBytesIndirect;
7744
7745 /* Detect and avoid integer overflow */
7746 if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore)
7747 return XML_FALSE;
7748 *additionTarget += bytesMore;
7749
7750 const XmlBigCount countBytesOutput
7751 = rootParser->m_accounting.countBytesDirect
7752 + rootParser->m_accounting.countBytesIndirect;
7753 const float amplificationFactor
7754 = accountingGetCurrentAmplification(rootParser);
7755 const XML_Bool tolerated
7756 = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes)
7757 || (amplificationFactor
7758 <= rootParser->m_accounting.maximumAmplificationFactor);
7759
7760 if (rootParser->m_accounting.debugLevel >= 2) {
7761 accountingReportStats(rootParser, "");
7762 accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after,
7763 bytesMore, source_line, account);
7764 }
7765
7766 return tolerated;
7767}
7768
7769unsigned long long
7770testingAccountingGetCountBytesDirect(XML_Parser parser) {
7771 if (! parser)
7772 return 0;
7773 return parser->m_accounting.countBytesDirect;
7774}
7775
7776unsigned long long
7777testingAccountingGetCountBytesIndirect(XML_Parser parser) {
7778 if (! parser)
7779 return 0;
7780 return parser->m_accounting.countBytesIndirect;
7781}
7782
7783static void
7784entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
7785 const char *action, int sourceLine) {
7786 assert(! rootParser->m_parentParser);
7787 if (rootParser->m_entity_stats.debugLevel < 1)
7788 return;
7789
7790# if defined(XML_UNICODE)
7791 const char *const entityName = "[..]";
7792# else
7793 const char *const entityName = entity->name;
7794# endif
7795
7796 fprintf(
7797 stderr,
7798 "expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n",
7799 (void *)rootParser, rootParser->m_entity_stats.countEverOpened,
7800 rootParser->m_entity_stats.currentDepth,
7801 rootParser->m_entity_stats.maximumDepthSeen,
7802 (rootParser->m_entity_stats.currentDepth - 1) * 2, "",
7803 entity->is_param ? "%" : "&", entityName, action, entity->textLen,
7804 sourceLine);
7805}
7806
7807static void
7808entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) {
7809 const XML_Parser rootParser = getRootParserOf(originParser, NULL);
7810 assert(! rootParser->m_parentParser);
7811
7812 rootParser->m_entity_stats.countEverOpened++;
7813 rootParser->m_entity_stats.currentDepth++;
7814 if (rootParser->m_entity_stats.currentDepth
7815 > rootParser->m_entity_stats.maximumDepthSeen) {
7816 rootParser->m_entity_stats.maximumDepthSeen++;
7817 }
7818
7819 entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine);
7820}
7821
7822static void
7823entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) {
7824 const XML_Parser rootParser = getRootParserOf(originParser, NULL);
7825 assert(! rootParser->m_parentParser);
7826
7827 entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine);
7828 rootParser->m_entity_stats.currentDepth--;
7829}
7830
7831static XML_Parser
7832getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {
7833 XML_Parser rootParser = parser;
7834 unsigned int stepsTakenUpwards = 0;
7835 while (rootParser->m_parentParser) {
7836 rootParser = rootParser->m_parentParser;
7837 stepsTakenUpwards++;
7838 }
7839 assert(! rootParser->m_parentParser);
7840 if (outLevelDiff != NULL) {
7841 *outLevelDiff = stepsTakenUpwards;
7842 }
7843 return rootParser;
7844}
7845
7846const char *
7847unsignedCharToPrintable(unsigned char c) {
7848 switch (c) {
7849 case 0:
7850 return "\\0";
7851 case 1:
7852 return "\\x1";
7853 case 2:
7854 return "\\x2";
7855 case 3:
7856 return "\\x3";
7857 case 4:
7858 return "\\x4";
7859 case 5:
7860 return "\\x5";
7861 case 6:
7862 return "\\x6";
7863 case 7:
7864 return "\\x7";
7865 case 8:
7866 return "\\x8";
7867 case 9:
7868 return "\\t";
7869 case 10:
7870 return "\\n";
7871 case 11:
7872 return "\\xB";
7873 case 12:
7874 return "\\xC";
7875 case 13:
7876 return "\\r";
7877 case 14:
7878 return "\\xE";
7879 case 15:
7880 return "\\xF";
7881 case 16:
7882 return "\\x10";
7883 case 17:
7884 return "\\x11";
7885 case 18:
7886 return "\\x12";
7887 case 19:
7888 return "\\x13";
7889 case 20:
7890 return "\\x14";
7891 case 21:
7892 return "\\x15";
7893 case 22:
7894 return "\\x16";
7895 case 23:
7896 return "\\x17";
7897 case 24:
7898 return "\\x18";
7899 case 25:
7900 return "\\x19";
7901 case 26:
7902 return "\\x1A";
7903 case 27:
7904 return "\\x1B";
7905 case 28:
7906 return "\\x1C";
7907 case 29:
7908 return "\\x1D";
7909 case 30:
7910 return "\\x1E";
7911 case 31:
7912 return "\\x1F";
7913 case 32:
7914 return " ";
7915 case 33:
7916 return "!";
7917 case 34:
7918 return "\\\"";
7919 case 35:
7920 return "#";
7921 case 36:
7922 return "$";
7923 case 37:
7924 return "%";
7925 case 38:
7926 return "&";
7927 case 39:
7928 return "'";
7929 case 40:
7930 return "(";
7931 case 41:
7932 return ")";
7933 case 42:
7934 return "*";
7935 case 43:
7936 return "+";
7937 case 44:
7938 return ",";
7939 case 45:
7940 return "-";
7941 case 46:
7942 return ".";
7943 case 47:
7944 return "/";
7945 case 48:
7946 return "0";
7947 case 49:
7948 return "1";
7949 case 50:
7950 return "2";
7951 case 51:
7952 return "3";
7953 case 52:
7954 return "4";
7955 case 53:
7956 return "5";
7957 case 54:
7958 return "6";
7959 case 55:
7960 return "7";
7961 case 56:
7962 return "8";
7963 case 57:
7964 return "9";
7965 case 58:
7966 return ":";
7967 case 59:
7968 return ";";
7969 case 60:
7970 return "<";
7971 case 61:
7972 return "=";
7973 case 62:
7974 return ">";
7975 case 63:
7976 return "?";
7977 case 64:
7978 return "@";
7979 case 65:
7980 return "A";
7981 case 66:
7982 return "B";
7983 case 67:
7984 return "C";
7985 case 68:
7986 return "D";
7987 case 69:
7988 return "E";
7989 case 70:
7990 return "F";
7991 case 71:
7992 return "G";
7993 case 72:
7994 return "H";
7995 case 73:
7996 return "I";
7997 case 74:
7998 return "J";
7999 case 75:
8000 return "K";
8001 case 76:
8002 return "L";
8003 case 77:
8004 return "M";
8005 case 78:
8006 return "N";
8007 case 79:
8008 return "O";
8009 case 80:
8010 return "P";
8011 case 81:
8012 return "Q";
8013 case 82:
8014 return "R";
8015 case 83:
8016 return "S";
8017 case 84:
8018 return "T";
8019 case 85:
8020 return "U";
8021 case 86:
8022 return "V";
8023 case 87:
8024 return "W";
8025 case 88:
8026 return "X";
8027 case 89:
8028 return "Y";
8029 case 90:
8030 return "Z";
8031 case 91:
8032 return "[";
8033 case 92:
8034 return "\\\\";
8035 case 93:
8036 return "]";
8037 case 94:
8038 return "^";
8039 case 95:
8040 return "_";
8041 case 96:
8042 return "`";
8043 case 97:
8044 return "a";
8045 case 98:
8046 return "b";
8047 case 99:
8048 return "c";
8049 case 100:
8050 return "d";
8051 case 101:
8052 return "e";
8053 case 102:
8054 return "f";
8055 case 103:
8056 return "g";
8057 case 104:
8058 return "h";
8059 case 105:
8060 return "i";
8061 case 106:
8062 return "j";
8063 case 107:
8064 return "k";
8065 case 108:
8066 return "l";
8067 case 109:
8068 return "m";
8069 case 110:
8070 return "n";
8071 case 111:
8072 return "o";
8073 case 112:
8074 return "p";
8075 case 113:
8076 return "q";
8077 case 114:
8078 return "r";
8079 case 115:
8080 return "s";
8081 case 116:
8082 return "t";
8083 case 117:
8084 return "u";
8085 case 118:
8086 return "v";
8087 case 119:
8088 return "w";
8089 case 120:
8090 return "x";
8091 case 121:
8092 return "y";
8093 case 122:
8094 return "z";
8095 case 123:
8096 return "{";
8097 case 124:
8098 return "|";
8099 case 125:
8100 return "}";
8101 case 126:
8102 return "~";
8103 case 127:
8104 return "\\x7F";
8105 case 128:
8106 return "\\x80";
8107 case 129:
8108 return "\\x81";
8109 case 130:
8110 return "\\x82";
8111 case 131:
8112 return "\\x83";
8113 case 132:
8114 return "\\x84";
8115 case 133:
8116 return "\\x85";
8117 case 134:
8118 return "\\x86";
8119 case 135:
8120 return "\\x87";
8121 case 136:
8122 return "\\x88";
8123 case 137:
8124 return "\\x89";
8125 case 138:
8126 return "\\x8A";
8127 case 139:
8128 return "\\x8B";
8129 case 140:
8130 return "\\x8C";
8131 case 141:
8132 return "\\x8D";
8133 case 142:
8134 return "\\x8E";
8135 case 143:
8136 return "\\x8F";
8137 case 144:
8138 return "\\x90";
8139 case 145:
8140 return "\\x91";
8141 case 146:
8142 return "\\x92";
8143 case 147:
8144 return "\\x93";
8145 case 148:
8146 return "\\x94";
8147 case 149:
8148 return "\\x95";
8149 case 150:
8150 return "\\x96";
8151 case 151:
8152 return "\\x97";
8153 case 152:
8154 return "\\x98";
8155 case 153:
8156 return "\\x99";
8157 case 154:
8158 return "\\x9A";
8159 case 155:
8160 return "\\x9B";
8161 case 156:
8162 return "\\x9C";
8163 case 157:
8164 return "\\x9D";
8165 case 158:
8166 return "\\x9E";
8167 case 159:
8168 return "\\x9F";
8169 case 160:
8170 return "\\xA0";
8171 case 161:
8172 return "\\xA1";
8173 case 162:
8174 return "\\xA2";
8175 case 163:
8176 return "\\xA3";
8177 case 164:
8178 return "\\xA4";
8179 case 165:
8180 return "\\xA5";
8181 case 166:
8182 return "\\xA6";
8183 case 167:
8184 return "\\xA7";
8185 case 168:
8186 return "\\xA8";
8187 case 169:
8188 return "\\xA9";
8189 case 170:
8190 return "\\xAA";
8191 case 171:
8192 return "\\xAB";
8193 case 172:
8194 return "\\xAC";
8195 case 173:
8196 return "\\xAD";
8197 case 174:
8198 return "\\xAE";
8199 case 175:
8200 return "\\xAF";
8201 case 176:
8202 return "\\xB0";
8203 case 177:
8204 return "\\xB1";
8205 case 178:
8206 return "\\xB2";
8207 case 179:
8208 return "\\xB3";
8209 case 180:
8210 return "\\xB4";
8211 case 181:
8212 return "\\xB5";
8213 case 182:
8214 return "\\xB6";
8215 case 183:
8216 return "\\xB7";
8217 case 184:
8218 return "\\xB8";
8219 case 185:
8220 return "\\xB9";
8221 case 186:
8222 return "\\xBA";
8223 case 187:
8224 return "\\xBB";
8225 case 188:
8226 return "\\xBC";
8227 case 189:
8228 return "\\xBD";
8229 case 190:
8230 return "\\xBE";
8231 case 191:
8232 return "\\xBF";
8233 case 192:
8234 return "\\xC0";
8235 case 193:
8236 return "\\xC1";
8237 case 194:
8238 return "\\xC2";
8239 case 195:
8240 return "\\xC3";
8241 case 196:
8242 return "\\xC4";
8243 case 197:
8244 return "\\xC5";
8245 case 198:
8246 return "\\xC6";
8247 case 199:
8248 return "\\xC7";
8249 case 200:
8250 return "\\xC8";
8251 case 201:
8252 return "\\xC9";
8253 case 202:
8254 return "\\xCA";
8255 case 203:
8256 return "\\xCB";
8257 case 204:
8258 return "\\xCC";
8259 case 205:
8260 return "\\xCD";
8261 case 206:
8262 return "\\xCE";
8263 case 207:
8264 return "\\xCF";
8265 case 208:
8266 return "\\xD0";
8267 case 209:
8268 return "\\xD1";
8269 case 210:
8270 return "\\xD2";
8271 case 211:
8272 return "\\xD3";
8273 case 212:
8274 return "\\xD4";
8275 case 213:
8276 return "\\xD5";
8277 case 214:
8278 return "\\xD6";
8279 case 215:
8280 return "\\xD7";
8281 case 216:
8282 return "\\xD8";
8283 case 217:
8284 return "\\xD9";
8285 case 218:
8286 return "\\xDA";
8287 case 219:
8288 return "\\xDB";
8289 case 220:
8290 return "\\xDC";
8291 case 221:
8292 return "\\xDD";
8293 case 222:
8294 return "\\xDE";
8295 case 223:
8296 return "\\xDF";
8297 case 224:
8298 return "\\xE0";
8299 case 225:
8300 return "\\xE1";
8301 case 226:
8302 return "\\xE2";
8303 case 227:
8304 return "\\xE3";
8305 case 228:
8306 return "\\xE4";
8307 case 229:
8308 return "\\xE5";
8309 case 230:
8310 return "\\xE6";
8311 case 231:
8312 return "\\xE7";
8313 case 232:
8314 return "\\xE8";
8315 case 233:
8316 return "\\xE9";
8317 case 234:
8318 return "\\xEA";
8319 case 235:
8320 return "\\xEB";
8321 case 236:
8322 return "\\xEC";
8323 case 237:
8324 return "\\xED";
8325 case 238:
8326 return "\\xEE";
8327 case 239:
8328 return "\\xEF";
8329 case 240:
8330 return "\\xF0";
8331 case 241:
8332 return "\\xF1";
8333 case 242:
8334 return "\\xF2";
8335 case 243:
8336 return "\\xF3";
8337 case 244:
8338 return "\\xF4";
8339 case 245:
8340 return "\\xF5";
8341 case 246:
8342 return "\\xF6";
8343 case 247:
8344 return "\\xF7";
8345 case 248:
8346 return "\\xF8";
8347 case 249:
8348 return "\\xF9";
8349 case 250:
8350 return "\\xFA";
8351 case 251:
8352 return "\\xFB";
8353 case 252:
8354 return "\\xFC";
8355 case 253:
8356 return "\\xFD";
8357 case 254:
8358 return "\\xFE";
8359 case 255:
8360 return "\\xFF";
8361 default:
8362 assert(0); /* never gets here */
8363 return "dead code";
8364 }
8365 assert(0); /* never gets here */
8366}
8367
8368#endif /* XML_DTD */
8369
8370static unsigned long
8371getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {
8372 const char *const valueOrNull = getenv(variableName);
8373 if (valueOrNull == NULL) {
8374 return defaultDebugLevel;
8375 }
8376 const char *const value = valueOrNull;
8377
8378 errno = 0;
8379 char *afterValue = (char *)value;
8380 unsigned long debugLevel = strtoul(value, &afterValue, 10);
8381 if ((errno != 0) || (afterValue[0] != '\0')) {
8382 errno = 0;
8383 return defaultDebugLevel;
8384 }
8385
8386 return debugLevel;
8387}
#define ASCII_l
Definition: ascii.h:74
#define ASCII_X
Definition: ascii.h:59
#define ASCII_SLASH
Definition: ascii.h:120
#define ASCII_PIPE
Definition: ascii.h:122
#define ASCII_F
Definition: ascii.h:41
#define ASCII_o
Definition: ascii.h:77
#define ASCII_E
Definition: ascii.h:40
#define ASCII_C
Definition: ascii.h:38
#define ASCII_O
Definition: ascii.h:50
#define ASCII_LPAREN
Definition: ascii.h:117
#define ASCII_n
Definition: ascii.h:76
#define ASCII_N
Definition: ascii.h:49
#define ASCII_s
Definition: ascii.h:81
#define ASCII_t
Definition: ascii.h:82
#define ASCII_D
Definition: ascii.h:39
#define ASCII_RPAREN
Definition: ascii.h:118
#define ASCII_c
Definition: ascii.h:65
#define ASCII_PERIOD
Definition: ascii.h:108
#define ASCII_h
Definition: ascii.h:70
#define ASCII_I
Definition: ascii.h:44
#define ASCII_A
Definition: ascii.h:36
#define ASCII_COMMA
Definition: ascii.h:123
#define ASCII_R
Definition: ascii.h:53
#define ASCII_9
Definition: ascii.h:99
#define ASCII_e
Definition: ascii.h:67
#define ASCII_w
Definition: ascii.h:85
#define ASCII_M
Definition: ascii.h:48
#define ASCII_8
Definition: ascii.h:98
#define ASCII_r
Definition: ascii.h:80
#define ASCII_p
Definition: ascii.h:78
#define ASCII_COLON
Definition: ascii.h:109
#define ASCII_0
Definition: ascii.h:90
#define ASCII_K
Definition: ascii.h:46
#define ASCII_L
Definition: ascii.h:47
#define ASCII_1
Definition: ascii.h:91
#define ASCII_EXCL
Definition: ascii.h:103
#define ASCII_a
Definition: ascii.h:63
#define ASCII_S
Definition: ascii.h:54
#define ASCII_m
Definition: ascii.h:75
#define ASCII_g
Definition: ascii.h:69
#define ASCII_EQUALS
Definition: ascii.h:112
#define ASCII_T
Definition: ascii.h:55
#define ASCII_2
Definition: ascii.h:92
#define ASCII_x
Definition: ascii.h:86
#define ASCII_3
Definition: ascii.h:93
#define ASCII_HASH
Definition: ascii.h:121
#define ASCII_Y
Definition: ascii.h:60
void(XMLCALL * XML_CommentHandler)(void *userData, const XML_Char *data)
Definition: expat.h:304
#define XML_FALSE
Definition: expat.h:56
void(XMLCALL * XML_EndElementHandler)(void *userData, const XML_Char *name)
Definition: expat.h:291
void(XMLCALL * XML_EndNamespaceDeclHandler)(void *userData, const XML_Char *prefix)
Definition: expat.h:401
@ XML_PARSING
Definition: expat.h:840
@ XML_SUSPENDED
Definition: expat.h:840
@ XML_FINISHED
Definition: expat.h:840
@ XML_INITIALIZED
Definition: expat.h:840
#define XML_STATUS_ERROR
Definition: expat.h:73
void(XMLCALL * XML_SkippedEntityHandler)(void *userData, const XML_Char *entityName, int is_parameter_entity)
Definition: expat.h:465
int(XMLCALL * XML_ExternalEntityRefHandler)(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId)
Definition: expat.h:449
@ XML_FEATURE_DTD
Definition: expat.h:1018
@ XML_FEATURE_SIZEOF_XML_LCHAR
Definition: expat.h:1022
@ XML_FEATURE_NS
Definition: expat.h:1023
@ XML_FEATURE_UNICODE
Definition: expat.h:1016
@ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT
Definition: expat.h:1027
@ XML_FEATURE_SIZEOF_XML_CHAR
Definition: expat.h:1021
@ XML_FEATURE_MIN_SIZE
Definition: expat.h:1020
@ XML_FEATURE_END
Definition: expat.h:1015
@ XML_FEATURE_UNICODE_WCHAR_T
Definition: expat.h:1017
@ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT
Definition: expat.h:1028
@ XML_FEATURE_CONTEXT_BYTES
Definition: expat.h:1019
@ XML_FEATURE_LARGE_SIZE
Definition: expat.h:1024
@ XML_FEATURE_ATTR_INFO
Definition: expat.h:1025
void(XMLCALL * XML_EndCdataSectionHandler)(void *userData)
Definition: expat.h:307
int(XMLCALL * XML_UnknownEncodingHandler)(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info)
Definition: expat.h:543
void(XMLCALL * XML_EndDoctypeDeclHandler)(void *userData)
Definition: expat.h:338
#define XML_MAJOR_VERSION
Definition: expat.h:1056
void(XMLCALL * XML_StartElementHandler)(void *userData, const XML_Char *name, const XML_Char **atts)
Definition: expat.h:287
void(XMLCALL * XML_ProcessingInstructionHandler)(void *userData, const XML_Char *target, const XML_Char *data)
Definition: expat.h:299
#define XML_MINOR_VERSION
Definition: expat.h:1057
void(XMLCALL * XML_StartNamespaceDeclHandler)(void *userData, const XML_Char *prefix, const XML_Char *uri)
Definition: expat.h:397
unsigned char XML_Bool
Definition: expat.h:54
void(XMLCALL * XML_XmlDeclHandler)(void *userData, const XML_Char *version, const XML_Char *encoding, int standalone)
Definition: expat.h:213
XML_Content_Quant
Definition: expat.h:142
@ XML_CQUANT_PLUS
Definition: expat.h:146
@ XML_CQUANT_OPT
Definition: expat.h:144
@ XML_CQUANT_NONE
Definition: expat.h:143
@ XML_CQUANT_REP
Definition: expat.h:145
void(XMLCALL * XML_StartCdataSectionHandler)(void *userData)
Definition: expat.h:306
void(XMLCALL * XML_UnparsedEntityDeclHandler)(void *userData, const XML_Char *entityName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName)
Definition: expat.h:376
XML_Error
Definition: expat.h:80
@ XML_ERROR_UNCLOSED_TOKEN
Definition: expat.h:86
@ XML_ERROR_ASYNC_ENTITY
Definition: expat.h:94
@ XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF
Definition: expat.h:97
@ XML_ERROR_NO_BUFFER
Definition: expat.h:128
@ XML_ERROR_ABORTED
Definition: expat.h:118
@ XML_ERROR_XML_DECL
Definition: expat.h:113
@ XML_ERROR_NO_ELEMENTS
Definition: expat.h:84
@ XML_ERROR_NOT_STANDALONE
Definition: expat.h:103
@ XML_ERROR_INCOMPLETE_PE
Definition: expat.h:112
@ XML_ERROR_TEXT_DECL
Definition: expat.h:114
@ XML_ERROR_RECURSIVE_ENTITY_REF
Definition: expat.h:93
@ XML_ERROR_PARTIAL_CHAR
Definition: expat.h:87
@ XML_ERROR_SUSPENDED
Definition: expat.h:116
@ XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING
Definition: expat.h:107
@ XML_ERROR_ENTITY_DECLARED_IN_PE
Definition: expat.h:105
@ XML_ERROR_DUPLICATE_ATTRIBUTE
Definition: expat.h:89
@ XML_ERROR_EXTERNAL_ENTITY_HANDLING
Definition: expat.h:102
@ XML_ERROR_INCORRECT_ENCODING
Definition: expat.h:100
@ XML_ERROR_NO_MEMORY
Definition: expat.h:82
@ XML_ERROR_MISPLACED_XML_PI
Definition: expat.h:98
@ XML_ERROR_AMPLIFICATION_LIMIT_BREACH
Definition: expat.h:130
@ XML_ERROR_NONE
Definition: expat.h:81
@ XML_ERROR_PARAM_ENTITY_REF
Definition: expat.h:91
@ XML_ERROR_FEATURE_REQUIRES_XML_DTD
Definition: expat.h:106
@ XML_ERROR_RESERVED_PREFIX_XML
Definition: expat.h:122
@ XML_ERROR_UNEXPECTED_STATE
Definition: expat.h:104
@ XML_ERROR_TAG_MISMATCH
Definition: expat.h:88
@ XML_ERROR_FINISHED
Definition: expat.h:119
@ XML_ERROR_JUNK_AFTER_DOC_ELEMENT
Definition: expat.h:90
@ XML_ERROR_NOT_SUSPENDED
Definition: expat.h:117
@ XML_ERROR_UNCLOSED_CDATA_SECTION
Definition: expat.h:101
@ XML_ERROR_RESERVED_NAMESPACE_URI
Definition: expat.h:124
@ XML_ERROR_BAD_CHAR_REF
Definition: expat.h:95
@ XML_ERROR_UNDEFINED_ENTITY
Definition: expat.h:92
@ XML_ERROR_UNBOUND_PREFIX
Definition: expat.h:109
@ XML_ERROR_PUBLICID
Definition: expat.h:115
@ XML_ERROR_UNDECLARING_PREFIX
Definition: expat.h:111
@ XML_ERROR_INVALID_TOKEN
Definition: expat.h:85
@ XML_ERROR_BINARY_ENTITY_REF
Definition: expat.h:96
@ XML_ERROR_UNKNOWN_ENCODING
Definition: expat.h:99
@ XML_ERROR_SUSPEND_PE
Definition: expat.h:120
@ XML_ERROR_INVALID_ARGUMENT
Definition: expat.h:126
@ XML_ERROR_SYNTAX
Definition: expat.h:83
@ XML_ERROR_RESERVED_PREFIX_XMLNS
Definition: expat.h:123
#define XML_STATUS_SUSPENDED
struct XML_cp XML_Content
Definition: expat.h:167
XML_ParamEntityParsing
Definition: expat.h:875
@ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE
Definition: expat.h:877
@ XML_PARAM_ENTITY_PARSING_NEVER
Definition: expat.h:876
void(XMLCALL * XML_AttlistDeclHandler)(void *userData, const XML_Char *elname, const XML_Char *attname, const XML_Char *att_type, const XML_Char *dflt, int isrequired)
Definition: expat.h:198
int(XMLCALL * XML_NotStandaloneHandler)(void *userData)
Definition: expat.h:413
#define XML_MICRO_VERSION
Definition: expat.h:1058
struct XML_ParserStruct * XML_Parser
Definition: expat.h:52
#define XML_STATUS_OK
Definition: expat.h:75
void(XMLCALL * XML_StartDoctypeDeclHandler)(void *userData, const XML_Char *doctypeName, const XML_Char *sysid, const XML_Char *pubid, int has_internal_subset)
Definition: expat.h:328
XML_Content_Type
Definition: expat.h:133
@ XML_CTYPE_ANY
Definition: expat.h:135
@ XML_CTYPE_SEQ
Definition: expat.h:139
@ XML_CTYPE_MIXED
Definition: expat.h:136
@ XML_CTYPE_CHOICE
Definition: expat.h:138
@ XML_CTYPE_EMPTY
Definition: expat.h:134
@ XML_CTYPE_NAME
Definition: expat.h:137
#define XML_TRUE
Definition: expat.h:55
void(XMLCALL * XML_CharacterDataHandler)(void *userData, const XML_Char *s, int len)
Definition: expat.h:295
XML_Status
Definition: expat.h:71
void(XMLCALL * XML_EntityDeclHandler)(void *userData, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName)
Definition: expat.h:358
void(XMLCALL * XML_NotationDeclHandler)(void *userData, const XML_Char *notationName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId)
Definition: expat.h:385
void(XMLCALL * XML_DefaultHandler)(void *userData, const XML_Char *s, int len)
Definition: expat.h:322
void(XMLCALL * XML_ElementDeclHandler)(void *userData, const XML_Char *name, XML_Content *model)
Definition: expat.h:183
#define XML_CONTEXT_BYTES
Definition: expat_config.h:75
#define XML_DTD
Definition: expat_config.h:78
char XML_Char
char XML_LChar
#define XMLCALL
unsigned long XML_Size
long XML_Index
#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT
Definition: internal.h:142
#define FASTCALL
Definition: internal.h:81
#define UNUSED_P(p)
Definition: internal.h:135
#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT
Definition: internal.h:144
#define EXPAT_FMT_ULL(midpart)
Definition: internal.h:122
#define PTRCALL
Definition: internal.h:85
const char * name(G4int ptype)
const char * name
Definition: xmltok.h:151
const char * valuePtr
Definition: xmltok.h:152
char normalized
Definition: xmltok.h:154
const char * valueEnd
Definition: xmltok.h:153
enum XML_Content_Quant quant
Definition: xmlparse.c:310
enum XML_Content_Type type
Definition: xmlparse.c:309
const XML_Char * name
Definition: xmlparse.c:311
XML_Bool isCdata
Definition: xmlparse.c:346
const ATTRIBUTE_ID * id
Definition: xmlparse.c:345
const XML_Char * value
Definition: xmlparse.c:347
Definition: xmlparse.c:365
unsigned contentStringLen
Definition: xmlparse.c:387
unsigned scaffSize
Definition: xmlparse.c:388
HASH_TABLE attributeIds
Definition: xmlparse.c:368
CONTENT_SCAFFOLD * scaffold
Definition: xmlparse.c:386
int * scaffIndex
Definition: xmlparse.c:391
XML_Bool hasParamEntityRefs
Definition: xmlparse.c:376
XML_Bool keepProcessing
Definition: xmlparse.c:373
XML_Bool in_eldecl
Definition: xmlparse.c:385
int scaffLevel
Definition: xmlparse.c:390
HASH_TABLE generalEntities
Definition: xmlparse.c:366
STRING_POOL entityValuePool
Definition: xmlparse.c:371
HASH_TABLE elementTypes
Definition: xmlparse.c:367
STRING_POOL pool
Definition: xmlparse.c:370
XML_Bool standalone
Definition: xmlparse.c:377
HASH_TABLE prefixes
Definition: xmlparse.c:369
PREFIX defaultPrefix
Definition: xmlparse.c:383
unsigned scaffCount
Definition: xmlparse.c:389
int nDefaultAtts
Definition: xmlparse.c:360
const XML_Char * name
Definition: xmlparse.c:357
int allocDefaultAtts
Definition: xmlparse.c:361
DEFAULT_ATTRIBUTE * defaultAtts
Definition: xmlparse.c:362
const ATTRIBUTE_ID * idAtt
Definition: xmlparse.c:359
PREFIX * prefix
Definition: xmlparse.c:358
XML_Bool is_internal
Definition: xmlparse.c:305
const XML_Char * base
Definition: xmlparse.c:300
int processed
Definition: xmlparse.c:298
const XML_Char * publicId
Definition: xmlparse.c:301
XML_Bool is_param
Definition: xmlparse.c:304
const XML_Char * textPtr
Definition: xmlparse.c:296
const XML_Char * systemId
Definition: xmlparse.c:299
XML_Bool open
Definition: xmlparse.c:303
const XML_Char * name
Definition: xmlparse.c:295
int textLen
Definition: xmlparse.c:297
const XML_Char * notation
Definition: xmlparse.c:302
NAMED ** p
Definition: xmlparse.c:234
NAMED ** end
Definition: xmlparse.c:235
NAMED ** v
Definition: xmlparse.c:209
unsigned char power
Definition: xmlparse.c:210
size_t used
Definition: xmlparse.c:212
const XML_Memory_Handling_Suite * mem
Definition: xmlparse.c:213
size_t size
Definition: xmlparse.c:211
KEY name
Definition: xmlparse.c:205
const XML_Char * uriName
Definition: xmlparse.c:353
unsigned long version
Definition: xmlparse.c:351
unsigned long hash
Definition: xmlparse.c:352
const XML_Char * end
Definition: xmlparse.c:329
BLOCK * blocks
Definition: xmlparse.c:327
BLOCK * freeBlocks
Definition: xmlparse.c:328
XML_Char * ptr
Definition: xmlparse.c:330
XML_Char * start
Definition: xmlparse.c:331
const XML_Memory_Handling_Suite * mem
Definition: xmlparse.c:332
int prefixLen
Definition: xmlparse.c:268
int strLen
Definition: xmlparse.c:266
const XML_Char * localPart
Definition: xmlparse.c:264
const XML_Char * str
Definition: xmlparse.c:263
const XML_Char * prefix
Definition: xmlparse.c:265
int uriLen
Definition: xmlparse.c:267
void * data
Definition: expat.h:523
int map[256]
Definition: expat.h:522
void *(* realloc_fcn)(void *ptr, size_t size)
Definition: expat.h:223
void *(* malloc_fcn)(size_t size)
Definition: expat.h:222
void(* free_fcn)(void *ptr)
Definition: expat.h:224
TAG * m_tagStack
Definition: xmlparse.c:677
XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler
Definition: xmlparse.c:630
XML_XmlDeclHandler m_xmlDeclHandler
Definition: xmlparse.c:643
char * m_bufferEnd
Definition: xmlparse.c:614
XML_Bool m_ns
Definition: xmlparse.c:648
const ENCODING * m_encoding
Definition: xmlparse.c:644
XML_CommentHandler m_commentHandler
Definition: xmlparse.c:625
XML_Bool m_declAttributeIsCdata
Definition: xmlparse.c:673
XML_ExternalEntityRefHandler m_externalEntityRefHandler
Definition: xmlparse.c:636
int m_nSpecifiedAtts
Definition: xmlparse.c:682
XML_UnknownEncodingHandler m_unknownEncodingHandler
Definition: xmlparse.c:639
unsigned int m_groupSize
Definition: xmlparse.c:695
XML_Char * m_dataBuf
Definition: xmlparse.c:619
STRING_POOL m_temp2Pool
Definition: xmlparse.c:693
ENTITY * m_declEntity
Definition: xmlparse.c:664
enum XML_Error m_errorCode
Definition: xmlparse.c:656
XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler
Definition: xmlparse.c:634
unsigned char m_nsAttsPower
Definition: xmlparse.c:687
XML_StartElementHandler m_startElementHandler
Definition: xmlparse.c:621
XML_Bool m_defaultExpandInternalEntities
Definition: xmlparse.c:662
const char * m_eventEndPtr
Definition: xmlparse.c:658
const XML_Char * m_doctypeName
Definition: xmlparse.c:665
char * m_groupConnector
Definition: xmlparse.c:694
void * m_unknownEncodingMem
Definition: xmlparse.c:650
XML_SkippedEntityHandler m_skippedEntityHandler
Definition: xmlparse.c:638
XML_EndElementHandler m_endElementHandler
Definition: xmlparse.c:622
XML_EntityDeclHandler m_entityDeclHandler
Definition: xmlparse.c:642
XML_Parser m_externalEntityRefHandlerArg
Definition: xmlparse.c:637
void(XMLCALL *m_unknownEncodingRelease)(void *)
const XML_Memory_Handling_Suite m_mem
Definition: xmlparse.c:610
NS_ATT * m_nsAtts
Definition: xmlparse.c:685
XML_Bool m_declAttributeIsId
Definition: xmlparse.c:674
void * m_unknownEncodingHandlerData
Definition: xmlparse.c:652
XML_AttlistDeclHandler m_attlistDeclHandler
Definition: xmlparse.c:641
const XML_Char * m_curBase
Definition: xmlparse.c:676
void * m_userData
Definition: xmlparse.c:607
XML_Parser m_parentParser
Definition: xmlparse.c:697
char * m_buffer
Definition: xmlparse.c:609
void * m_unknownEncodingData
Definition: xmlparse.c:651
STRING_POOL m_tempPool
Definition: xmlparse.c:692
ELEMENT_TYPE * m_declElementType
Definition: xmlparse.c:671
ATTRIBUTE_ID * m_declAttributeId
Definition: xmlparse.c:672
const ENCODING * m_internalEncoding
Definition: xmlparse.c:646
unsigned long m_hash_secret_salt
Definition: xmlparse.c:704
XML_Bool m_ns_triplets
Definition: xmlparse.c:649
XML_Index m_parseEndByteIndex
Definition: xmlparse.c:617
XML_EndCdataSectionHandler m_endCdataSectionHandler
Definition: xmlparse.c:627
const XML_Char * m_protocolEncodingName
Definition: xmlparse.c:647
const XML_Char * m_declAttributeType
Definition: xmlparse.c:668
const XML_Char * m_declNotationName
Definition: xmlparse.c:669
XML_NotationDeclHandler m_notationDeclHandler
Definition: xmlparse.c:632
POSITION m_position
Definition: xmlparse.c:691
OPEN_INTERNAL_ENTITY * m_freeInternalEntities
Definition: xmlparse.c:661
OPEN_INTERNAL_ENTITY * m_openInternalEntities
Definition: xmlparse.c:660
XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler
Definition: xmlparse.c:631
BINDING * m_inheritedBindings
Definition: xmlparse.c:679
TAG * m_freeTagList
Definition: xmlparse.c:678
BINDING * m_freeBindingList
Definition: xmlparse.c:680
XML_ElementDeclHandler m_elementDeclHandler
Definition: xmlparse.c:640
Processor * m_processor
Definition: xmlparse.c:655
XML_DefaultHandler m_defaultHandler
Definition: xmlparse.c:628
const char * m_bufferLim
Definition: xmlparse.c:616
XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler
Definition: xmlparse.c:629
INIT_ENCODING m_initEncoding
Definition: xmlparse.c:645
XML_Char m_namespaceSeparator
Definition: xmlparse.c:696
const XML_Char * m_declNotationPublicId
Definition: xmlparse.c:670
XML_ParsingStatus m_parsingStatus
Definition: xmlparse.c:698
ATTRIBUTE * m_atts
Definition: xmlparse.c:684
const XML_Char * m_doctypeSysid
Definition: xmlparse.c:666
const char * m_parseEndPtr
Definition: xmlparse.c:618
const char * m_bufferPtr
Definition: xmlparse.c:612
const char * m_positionPtr
Definition: xmlparse.c:659
XML_NotStandaloneHandler m_notStandaloneHandler
Definition: xmlparse.c:635
XML_ProcessingInstructionHandler m_processingInstructionHandler
Definition: xmlparse.c:624
XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler
Definition: xmlparse.c:633
XML_CharacterDataHandler m_characterDataHandler
Definition: xmlparse.c:623
PROLOG_STATE m_prologState
Definition: xmlparse.c:654
const char * m_eventPtr
Definition: xmlparse.c:657
XML_Char * m_dataBufEnd
Definition: xmlparse.c:620
unsigned long m_nsAttsVersion
Definition: xmlparse.c:686
XML_StartCdataSectionHandler m_startCdataSectionHandler
Definition: xmlparse.c:626
const XML_Char * m_doctypePubid
Definition: xmlparse.c:667
void * m_handlerArg
Definition: xmlparse.c:608
XML_Bool finalBuffer
Definition: expat.h:844
enum XML_Parsing parsing
Definition: expat.h:843
Definition: expat.h:169
XML_Content * children
Definition: expat.h:174
unsigned int numchildren
Definition: expat.h:173
XML_Char * name
Definition: expat.h:172
enum XML_Content_Quant quant
Definition: expat.h:171
enum XML_Content_Type type
Definition: expat.h:170
XML_Bool xmlns
Definition: xmlparse.c:341
XML_Bool maybeTokenized
Definition: xmlparse.c:340
XML_Char * name
Definition: xmlparse.c:338
PREFIX * prefix
Definition: xmlparse.c:339
struct binding * prevPrefixBinding
Definition: xmlparse.c:250
const struct attribute_id * attId
Definition: xmlparse.c:251
XML_Char * uri
Definition: xmlparse.c:252
struct binding * nextTagBinding
Definition: xmlparse.c:249
int uriLen
Definition: xmlparse.c:253
struct prefix * prefix
Definition: xmlparse.c:248
int uriAlloc
Definition: xmlparse.c:254
int size
Definition: xmlparse.c:322
struct block * next
Definition: xmlparse.c:321
XML_Char s[1]
Definition: xmlparse.c:323
Definition: inftrees.h:24
int minBytesPerChar
Definition: xmltok.h:195
struct open_internal_entity * next
Definition: xmlparse.c:397
XML_Bool betweenDecl
Definition: xmlparse.c:400
const char * internalEventEndPtr
Definition: xmlparse.c:396
const char * internalEventPtr
Definition: xmlparse.c:395
XML_Size columnNumber
Definition: xmltok.h:147
XML_Size lineNumber
Definition: xmltok.h:146
const XML_Char * name
Definition: xmlparse.c:258
BINDING * binding
Definition: xmlparse.c:259
unsigned level
Definition: xmlrole.h:121
uint64_t k[2]
Definition: siphash.h:142
Definition: xmlparse.c:284
struct tag * parent
Definition: xmlparse.c:285
int rawNameLength
Definition: xmlparse.c:287
BINDING * bindings
Definition: xmlparse.c:291
char * buf
Definition: xmlparse.c:289
const char * rawName
Definition: xmlparse.c:286
char * bufEnd
Definition: xmlparse.c:290
TAG_NAME name
Definition: xmlparse.c:288
#define INT_MAX
Definition: templates.hh:90
#define XML_Char
#define INIT_POWER
Definition: xmlparse.c:6987
XML_Parser XMLCALL XML_ParserCreate(const XML_Char *encodingName)
Definition: xmlparse.c:716
void *XMLCALL XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
Definition: xmlparse.c:2322
void XMLCALL XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end)
Definition: xmlparse.c:1681
void XMLCALL XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *data)
Definition: xmlparse.c:1755
enum XML_Status XMLCALL XML_SetBase(XML_Parser parser, const XML_Char *p)
Definition: xmlparse.c:1540
const XML_Feature *XMLCALL XML_GetFeatureList(void)
Definition: xmlparse.c:2485
void XMLCALL XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler)
Definition: xmlparse.c:1694
#define INIT_BLOCK_SIZE
Definition: xmlparse.c:242
void XMLCALL XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler)
Definition: xmlparse.c:1612
#define CONTEXT_SEP
Definition: xmlparse.c:6516
void XMLCALL XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler)
Definition: xmlparse.c:1657
#define PROBE_STEP(hash, mask, power)
Definition: xmlparse.c:230
struct prefix PREFIX
#define XmlConvert
Definition: xmlparse.c:157
int XMLCALL XML_GetSpecifiedAttributeCount(XML_Parser parser)
Definition: xmlparse.c:1561
void XMLCALL XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl)
Definition: xmlparse.c:1770
enum XML_Status XMLCALL XML_StopParser(XML_Parser parser, XML_Bool resumable)
Definition: xmlparse.c:2161
#define INIT_SCAFFOLD_ELEMENTS
Definition: xmlparse.c:318
#define REALLOC(parser, p, s)
Definition: xmlparse.c:712
#define XML_ENCODE_MAX
Definition: xmlparse.c:156
void XMLCALL XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler)
Definition: xmlparse.c:1724
void XMLCALL XML_FreeContentModel(XML_Parser parser, XML_Content *model)
Definition: xmlparse.c:2309
const char *XMLCALL XML_GetInputContext(XML_Parser parser, int *offset, int *size)
Definition: xmlparse.c:2265
XML_Parser XMLCALL XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
Definition: xmlparse.c:721
#define poolStart(pool)
Definition: xmlparse.c:592
XML_Parser XMLCALL XML_ParserCreate_MM(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep)
Definition: xmlparse.c:965
#define INIT_DATA_BUF_SIZE
Definition: xmlparse.c:239
void XMLCALL XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl)
Definition: xmlparse.c:1764
#define INIT_BUFFER_SIZE
Definition: xmlparse.c:243
XML_Size XMLCALL XML_GetCurrentColumnNumber(XML_Parser parser)
Definition: xmlparse.c:2297
void XMLCALL XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end)
Definition: xmlparse.c:1584
XML_Expat_Version XMLCALL XML_ExpatVersionInfo(void)
Definition: xmlparse.c:2474
struct tag TAG
#define XmlInitUnknownEncodingNS
Definition: xmlparse.c:168
XML_Parser XMLCALL XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, const XML_Char *encodingName)
Definition: xmlparse.c:1250
void *XMLCALL XML_MemMalloc(XML_Parser parser, size_t size)
Definition: xmlparse.c:2315
#define INIT_ATTS_VERSION
Definition: xmlparse.c:241
XML_Size XMLCALL XML_GetCurrentLineNumber(XML_Parser parser)
Definition: xmlparse.c:2285
struct block BLOCK
int XMLCALL XML_GetIdAttributeIndex(XML_Parser parser)
Definition: xmlparse.c:1568
enum XML_Error XMLCALL XML_GetErrorCode(XML_Parser parser)
Definition: xmlparse.c:2239
#define MUST_CONVERT(enc, s)
Definition: xmlparse.c:161
enum XML_Status XMLCALL XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
Definition: xmlparse.c:1819
#define poolLength(pool)
Definition: xmlparse.c:594
XML_Index XMLCALL XML_GetCurrentByteIndex(XML_Parser parser)
Definition: xmlparse.c:2246
const XML_LChar *XMLCALL XML_ErrorString(enum XML_Error code)
Definition: xmlparse.c:2350
void XMLCALL XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end)
Definition: xmlparse.c:1700
#define ROUND_UP(n, sz)
Definition: xmlparse.c:193
void XMLCALL XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
Definition: xmlparse.c:2231
enum XML_Status XMLCALL XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
Definition: xmlparse.c:1223
void *XMLCALL XML_GetBuffer(XML_Parser parser, int len)
Definition: xmlparse.c:2038
void XMLCALL XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end)
Definition: xmlparse.c:1717
#define INIT_ATTS_SIZE
Definition: xmlparse.c:240
#define XmlGetInternalEncodingNS
Definition: xmlparse.c:170
#define MALLOC(parser, s)
Definition: xmlparse.c:711
void XMLCALL XML_DefaultCurrent(XML_Parser parser)
Definition: xmlparse.c:2335
#define INIT_TAG_BUF_SIZE
Definition: xmlparse.c:238
void XMLCALL XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler)
Definition: xmlparse.c:1782
const XML_Char *XMLCALL XML_GetBase(XML_Parser parser)
Definition: xmlparse.c:1554
void XMLCALL XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler)
Definition: xmlparse.c:1649
void XMLCALL XML_SetEndCdataSectionHandler(XML_Parser parser, XML_EndCdataSectionHandler end)
Definition: xmlparse.c:1642
enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start, const char *end, const char **endPtr)
struct open_internal_entity OPEN_INTERNAL_ENTITY
#define XML_L(x)
Definition: xmlparse.c:188
void XMLCALL XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end)
Definition: xmlparse.c:1599
#define poolFinish(pool)
Definition: xmlparse.c:598
#define XmlGetInternalEncoding
Definition: xmlparse.c:158
void XMLCALL XML_MemFree(XML_Parser parser, void *ptr)
Definition: xmlparse.c:2329
struct binding BINDING
const XML_LChar *XMLCALL XML_ExpatVersion(void)
Definition: xmlparse.c:2455
#define XmlInitEncodingNS
Definition: xmlparse.c:167
XML_Bool XMLCALL XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
Definition: xmlparse.c:1182
#define FREE(parser, p)
Definition: xmlparse.c:713
const XML_Char * KEY
Definition: xmlparse.c:202
void XMLCALL XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start)
Definition: xmlparse.c:1710
#define EXPAND_SPARE
Definition: xmlparse.c:245
void XMLCALL XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler)
Definition: xmlparse.c:1731
#define poolDiscard(pool)
Definition: xmlparse.c:597
char ICHAR
Definition: xmlparse.c:162
int XMLCALL XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt)
Definition: xmlparse.c:1805
void XMLCALL XML_SetUserData(XML_Parser parser, void *p)
Definition: xmlparse.c:1530
void XMLCALL XML_SetStartCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start)
Definition: xmlparse.c:1635
struct attribute_id ATTRIBUTE_ID
enum XML_Error XMLCALL XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
Definition: xmlparse.c:1502
void XMLCALL XML_SetSkippedEntityHandler(XML_Parser parser, XML_SkippedEntityHandler handler)
Definition: xmlparse.c:1748
#define EXPAT_SAFE_PTR_DIFF(p, q)
Definition: xmlparse.c:196
void XMLCALL XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end)
Definition: xmlparse.c:1665
#define poolChop(pool)
Definition: xmlparse.c:595
#define poolAppendChar(pool, c)
Definition: xmlparse.c:599
void XMLCALL XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end)
Definition: xmlparse.c:1625
void XMLCALL XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler)
Definition: xmlparse.c:1605
void XMLCALL XML_SetStartDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start)
Definition: xmlparse.c:1674
void XMLCALL XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start)
Definition: xmlparse.c:1593
#define XML_T(x)
Definition: xmlparse.c:187
#define poolLastChar(pool)
Definition: xmlparse.c:596
void XMLCALL XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler)
Definition: xmlparse.c:1776
#define XmlParseXmlDeclNS
Definition: xmlparse.c:171
int XMLCALL XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing peParsing)
Definition: xmlparse.c:1788
enum XML_Status XMLCALL XML_ResumeParser(XML_Parser parser)
Definition: xmlparse.c:2191
void XMLCALL XML_UseParserAsHandlerArg(XML_Parser parser)
Definition: xmlparse.c:1496
enum XML_Status XMLCALL XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
Definition: xmlparse.c:1973
void XMLCALL XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
Definition: xmlparse.c:1519
void XMLCALL XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler)
Definition: xmlparse.c:1687
void XMLCALL XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
Definition: xmlparse.c:1738
int XMLCALL XML_GetCurrentByteCount(XML_Parser parser)
Definition: xmlparse.c:2256
void XMLCALL XML_ParserFree(XML_Parser parser)
Definition: xmlparse.c:1430
void XMLCALL XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler)
Definition: xmlparse.c:1619
XML_Account
Definition: xmlparse.c:403
@ XML_ACCOUNT_DIRECT
Definition: xmlparse.c:404
@ XML_ACCOUNT_NONE
Definition: xmlparse.c:407
@ XML_ACCOUNT_ENTITY_EXPANSION
Definition: xmlparse.c:405
#define V2(a, b, c)
#define XmlEncode
Definition: xmlparse.c:160
void XmlPrologStateInit(PROLOG_STATE *state)
Definition: xmlrole.c:1237
@ XML_ROLE_GROUP_CHOICE
Definition: xmlrole.h:102
@ XML_ROLE_NOTATION_PUBLIC_ID
Definition: xmlrole.h:74
@ XML_ROLE_ERROR
Definition: xmlrole.h:52
@ XML_ROLE_GROUP_CLOSE_REP
Definition: xmlrole.h:99
@ XML_ROLE_CONTENT_PCDATA
Definition: xmlrole.h:96
@ XML_ROLE_CONTENT_ELEMENT_REP
Definition: xmlrole.h:105
@ XML_ROLE_ENTITY_COMPLETE
Definition: xmlrole.h:68
@ XML_ROLE_DOCTYPE_INTERNAL_SUBSET
Definition: xmlrole.h:60
@ XML_ROLE_ATTRIBUTE_TYPE_ENTITY
Definition: xmlrole.h:80
@ XML_ROLE_NOTATION_NO_SYSTEM_ID
Definition: xmlrole.h:73
@ XML_ROLE_DOCTYPE_NONE
Definition: xmlrole.h:56
@ XML_ROLE_PARAM_ENTITY_REF
Definition: xmlrole.h:115
@ XML_ROLE_ATTRIBUTE_TYPE_ENTITIES
Definition: xmlrole.h:81
@ XML_ROLE_GROUP_CLOSE
Definition: xmlrole.h:98
@ XML_ROLE_DOCTYPE_CLOSE
Definition: xmlrole.h:61
@ XML_ROLE_ENTITY_NOTATION_NAME
Definition: xmlrole.h:69
@ XML_ROLE_GROUP_SEQUENCE
Definition: xmlrole.h:103
@ XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS
Definition: xmlrole.h:83
@ XML_ROLE_ATTLIST_ELEMENT_NAME
Definition: xmlrole.h:87
@ XML_ROLE_GROUP_CLOSE_OPT
Definition: xmlrole.h:100
@ XML_ROLE_IMPLIED_ATTRIBUTE_VALUE
Definition: xmlrole.h:88
@ XML_ROLE_ATTRIBUTE_TYPE_CDATA
Definition: xmlrole.h:76
@ XML_ROLE_COMMENT
Definition: xmlrole.h:109
@ XML_ROLE_ATTRIBUTE_ENUM_VALUE
Definition: xmlrole.h:84
@ XML_ROLE_ENTITY_SYSTEM_ID
Definition: xmlrole.h:66
@ XML_ROLE_CONTENT_ELEMENT
Definition: xmlrole.h:104
@ XML_ROLE_ATTLIST_NONE
Definition: xmlrole.h:86
@ XML_ROLE_ATTRIBUTE_NOTATION_VALUE
Definition: xmlrole.h:85
@ XML_ROLE_DOCTYPE_SYSTEM_ID
Definition: xmlrole.h:58
@ XML_ROLE_NOTATION_SYSTEM_ID
Definition: xmlrole.h:72
@ XML_ROLE_PI
Definition: xmlrole.h:108
@ XML_ROLE_ATTRIBUTE_NAME
Definition: xmlrole.h:75
@ XML_ROLE_CONTENT_ANY
Definition: xmlrole.h:94
@ XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN
Definition: xmlrole.h:82
@ XML_ROLE_ATTRIBUTE_TYPE_ID
Definition: xmlrole.h:77
@ XML_ROLE_ENTITY_NONE
Definition: xmlrole.h:64
@ XML_ROLE_NONE
Definition: xmlrole.h:53
@ XML_ROLE_ELEMENT_NONE
Definition: xmlrole.h:92
@ XML_ROLE_ENTITY_PUBLIC_ID
Definition: xmlrole.h:67
@ XML_ROLE_INSTANCE_START
Definition: xmlrole.h:55
@ XML_ROLE_DOCTYPE_NAME
Definition: xmlrole.h:57
@ XML_ROLE_NOTATION_NAME
Definition: xmlrole.h:71
@ XML_ROLE_CONTENT_ELEMENT_PLUS
Definition: xmlrole.h:107
@ XML_ROLE_GENERAL_ENTITY_NAME
Definition: xmlrole.h:62
@ XML_ROLE_PARAM_ENTITY_NAME
Definition: xmlrole.h:63
@ XML_ROLE_DEFAULT_ATTRIBUTE_VALUE
Definition: xmlrole.h:90
@ XML_ROLE_NOTATION_NONE
Definition: xmlrole.h:70
@ XML_ROLE_XML_DECL
Definition: xmlrole.h:54
@ XML_ROLE_GROUP_CLOSE_PLUS
Definition: xmlrole.h:101
@ XML_ROLE_REQUIRED_ATTRIBUTE_VALUE
Definition: xmlrole.h:89
@ XML_ROLE_GROUP_OPEN
Definition: xmlrole.h:97
@ XML_ROLE_CONTENT_EMPTY
Definition: xmlrole.h:95
@ XML_ROLE_FIXED_ATTRIBUTE_VALUE
Definition: xmlrole.h:91
@ XML_ROLE_CONTENT_ELEMENT_OPT
Definition: xmlrole.h:106
@ XML_ROLE_ATTRIBUTE_TYPE_IDREFS
Definition: xmlrole.h:79
@ XML_ROLE_DOCTYPE_PUBLIC_ID
Definition: xmlrole.h:59
@ XML_ROLE_ATTRIBUTE_TYPE_IDREF
Definition: xmlrole.h:78
@ XML_ROLE_ELEMENT_NAME
Definition: xmlrole.h:93
@ XML_ROLE_ENTITY_VALUE
Definition: xmlrole.h:65
#define XmlTokenRole(state, tok, ptr, end, enc)
Definition: xmlrole.h:135
ENCODING * XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert, void *userData)
Definition: xmltok.c:1406
int XmlSizeOfUnknownEncoding(void)
Definition: xmltok.c:1325
#define XmlGetAttributes(enc, ptr, attsMax, atts)
Definition: xmltok.h:259
int XmlParseXmlDecl(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **versionEndPtr, const char **encodingNamePtr, const ENCODING **namedEncodingPtr, int *standalonePtr)
#define XML_TOK_CHAR_REF
Definition: xmltok.h:69
#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr)
Definition: xmltok.h:230
#define XML_TOK_PI
Definition: xmltok.h:74
#define XmlNameLength(enc, ptr)
Definition: xmltok.h:255
#define XML_TOK_PARTIAL_CHAR
Definition: xmltok.h:53
#define XmlEntityValueTok(enc, ptr, end, nextTokPtr)
Definition: xmltok.h:249
#define XML_TOK_EMPTY_ELEMENT_NO_ATTS
Definition: xmltok.h:63
#define XML_TOK_ENTITY_REF
Definition: xmltok.h:68
#define XmlContentTok(enc, ptr, end, nextTokPtr)
Definition: xmltok.h:227
#define XML_TOK_DATA_NEWLINE
Definition: xmltok.h:66
#define XML_TOK_END_TAG
Definition: xmltok.h:64
#define XML_TOK_COMMENT
Definition: xmltok.h:76
#define XML_TOK_XML_DECL
Definition: xmltok.h:75
#define XML_TOK_PROLOG_S
Definition: xmltok.h:80
#define XmlPrologTok(enc, ptr, end, nextTokPtr)
Definition: xmltok.h:224
#define XmlIsPublicId(enc, ptr, end, badPtr)
Definition: xmltok.h:270
#define XML_TOK_PARTIAL
Definition: xmltok.h:54
#define XML_TOK_START_TAG_WITH_ATTS
Definition: xmltok.h:60
#define XML_TOK_CDATA_SECT_CLOSE
Definition: xmltok.h:111
int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name)
#define XML_TOK_DATA_CHARS
Definition: xmltok.h:65
#define XML_TOK_PARAM_ENTITY_REF
Definition: xmltok.h:93
#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS
Definition: xmltok.h:62
#define XML_TOK_TRAILING_RSQB
Definition: xmltok.h:45
#define XmlCharRefNumber(enc, ptr)
Definition: xmltok.h:262
#define XmlPredefinedEntityName(enc, ptr, end)
Definition: xmltok.h:264
XML_Convert_Result
Definition: xmltok.h:163
@ XML_CONVERT_COMPLETED
Definition: xmltok.h:164
@ XML_CONVERT_INPUT_INCOMPLETE
Definition: xmltok.h:165
#define XML_TOK_ATTRIBUTE_VALUE_S
Definition: xmltok.h:108
#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr)
Definition: xmltok.h:246
#define XML_TOK_START_TAG_NO_ATTS
Definition: xmltok.h:61
#define XML_TOK_NONE
Definition: xmltok.h:50
#define XmlSkipS(enc, ptr)
Definition: xmltok.h:257
#define XML_TOK_INVALID
Definition: xmltok.h:55
#define XML_TOK_TRAILING_CR
Definition: xmltok.h:51
#define XML_TOK_CDATA_SECT_OPEN
Definition: xmltok.h:67
#define XML_TOK_INSTANCE_START
Definition: xmltok.h:94
#define XML_TOK_BOM
Definition: xmltok.h:77
#define XmlUpdatePosition(enc, ptr, end, pos)
Definition: xmltok.h:267