Coverage Report

Created: 2026-10-28 06:38

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