Coverage Report

Created: 2026-08-25 06:40

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