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