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