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