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