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