Coverage Report

Created: 2026-09-28 10:59

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