Coverage Report

Created: 2026-08-11 07:29

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