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