Coverage Report

Created: 2026-08-17 07:50

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