Coverage Report

Created: 2026-10-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libexpat/expat/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
304k
#  define XmlConvert XmlUtf8Convert
191
1
#  define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
192
107k
#  define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
193
141
#  define XmlEncode XmlUtf8Encode
194
35.0k
#  define MUST_CONVERT(enc, s) (! (enc)->isUtf8)
195
typedef char ICHAR;
196
#endif
197
198
#ifndef XML_NS
199
200
#  define XmlInitEncodingNS XmlInitEncoding
201
#  define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
202
#  undef XmlGetInternalEncodingNS
203
#  define XmlGetInternalEncodingNS XmlGetInternalEncoding
204
#  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
18.4M
#  define XML_T(x) x
221
101k
#  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
0
#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
227
228
/* Do safe (NULL-aware) pointer arithmetic */
229
976k
#define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
230
231
158
#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
65.0k
  ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
250
#define PROBE_STEP(hash, mask, power)                                          \
251
65.0k
  ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
252
253
50.5k
#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
254
107k
#define INIT_DATA_BUF_SIZE 1024
255
112k
#define INIT_ATTS_SIZE 16
256
5.47k
#define INIT_ATTS_VERSION 0xFFFFFFFF
257
441k
#define INIT_BLOCK_SIZE 1024
258
107k
#define INIT_BUFFER_SIZE 1024
259
260
534k
#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
  size_t textLen;   /* length in XML_Chars */
316
  size_t 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
  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
                           bool isCdata, bool isId, const XML_Char *value,
541
                           XML_Parser parser);
542
static enum XML_Error storeAttributeValue(XML_Parser parser,
543
                                          const ENCODING *enc, 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, 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
                                       size_t 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
462k
#define poolStart(pool) ((pool)->start)
672
116k
#define poolLength(pool) ((pool)->ptr - (pool)->start)
673
0
#define poolChop(pool) ((void)--(pool->ptr))
674
0
#define poolLastChar(pool) (((pool)->ptr)[-1])
675
303k
#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
676
444k
#define poolFinish(pool) ((pool)->start = (pool)->ptr)
677
678
bool
679
5.96M
poolAppendChar(STRING_POOL *pool, XML_Char c) {
680
5.96M
  if (pool->ptr == pool->end && ! poolGrow(pool))
681
0
    return false;
682
683
5.96M
  *(pool->ptr)++ = c;
684
5.96M
  return true;
685
5.96M
}
686
687
bool
688
242k
poolAppendChars(STRING_POOL *pool, const XML_Char *s, size_t len) {
689
  // Detect and prevent integer overflow
690
242k
  if (len > SIZE_MAX / sizeof(XML_Char))
691
0
    return false;
692
693
242k
  if (! poolGrowUntil(pool, len))
694
0
    return false;
695
696
242k
  memcpy(pool->ptr, s, len * sizeof(XML_Char));
697
242k
  pool->ptr += len;
698
699
242k
  return true;
700
242k
}
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
  bool m_declAttributeIsCdata;
796
  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
1.34M
#  define MALLOC(parser, s) (expat_malloc((parser), (s), __LINE__))
836
10.4k
#  define REALLOC(parser, p, s) (expat_realloc((parser), (p), (s), __LINE__))
837
12.0M
#  define FREE(parser, p) (expat_free((parser), (p), __LINE__))
838
#else
839
#  define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
840
#  define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
841
#  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
0
                size_t newTotal, size_t peakTotal, int sourceLine) {
848
  // NOTE: This can be +infinity or -nan
849
0
  const float amplification
850
0
      = (float)newTotal / (float)rootParser->m_accounting.countBytesDirect;
851
0
  fprintf(
852
0
      stderr,
853
0
      "expat: Allocations(%p): Direct " EXPAT_FMT_ULL("10") ", allocated %c" EXPAT_FMT_SIZE_T(
854
0
          "10") " to " EXPAT_FMT_SIZE_T("10") " (" EXPAT_FMT_SIZE_T("10") " peak), amplification %8.2f (xmlparse.c:%d)\n",
855
0
      (void *)rootParser, rootParser->m_accounting.countBytesDirect, operator,
856
0
      absDiff, newTotal, peakTotal, (double)amplification, sourceLine);
857
0
}
858
859
static bool
860
expat_heap_increase_tolerable(XML_Parser rootParser, size_t increase,
861
1.35M
                              int sourceLine) {
862
1.35M
  assert(rootParser != NULL);
863
1.35M
  assert(increase > 0);
864
865
1.35M
  size_t newTotal = 0;
866
1.35M
  bool tolerable = true;
867
868
  // Detect integer overflow
869
1.35M
  if (SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated < increase) {
870
0
    tolerable = false;
871
1.35M
  } else {
872
1.35M
    newTotal = rootParser->m_alloc_tracker.bytesAllocated + increase;
873
874
1.35M
    if (newTotal >= rootParser->m_alloc_tracker.activationThresholdBytes) {
875
0
      assert(newTotal > 0);
876
      // NOTE: This can be +infinity when dividing by zero but not -nan
877
0
      const float amplification
878
0
          = (float)newTotal / (float)rootParser->m_accounting.countBytesDirect;
879
0
      if (amplification
880
0
          > rootParser->m_alloc_tracker.maximumAmplificationFactor) {
881
0
        tolerable = false;
882
0
      }
883
0
    }
884
1.35M
  }
885
886
1.35M
  if (! tolerable && (rootParser->m_alloc_tracker.debugLevel >= 1)) {
887
0
    expat_heap_stat(rootParser, '+', increase, newTotal, newTotal, sourceLine);
888
0
  }
889
890
1.35M
  return tolerable;
891
1.35M
}
892
893
#  if defined(XML_TESTING)
894
void *
895
#  else
896
static void *
897
#  endif
898
1.34M
expat_malloc(XML_Parser parser, size_t size, int sourceLine) {
899
  // Detect integer overflow
900
1.34M
  if (SIZE_MAX - size < sizeof(size_t) + EXPAT_MALLOC_PADDING) {
901
0
    return NULL;
902
0
  }
903
904
1.34M
  const XML_Parser rootParser = getRootParserOf(parser, NULL);
905
1.34M
  assert(rootParser->m_parentParser == NULL);
906
907
1.34M
  const size_t bytesToAllocate = sizeof(size_t) + EXPAT_MALLOC_PADDING + size;
908
909
1.34M
  if (SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated < bytesToAllocate) {
910
0
    return NULL; // i.e. signal integer overflow as out-of-memory
911
0
  }
912
913
1.34M
  if (! expat_heap_increase_tolerable(rootParser, bytesToAllocate,
914
1.34M
                                      sourceLine)) {
915
0
    return NULL; // i.e. signal violation as out-of-memory
916
0
  }
917
918
  // Actually allocate
919
1.34M
  void *const mallocedPtr = parser->m_mem.malloc_fcn(bytesToAllocate);
920
921
1.34M
  if (mallocedPtr == NULL) {
922
0
    return NULL;
923
0
  }
924
925
  // Update in-block recorded size
926
1.34M
  *(size_t *)mallocedPtr = size;
927
928
  // Update accounting
929
1.34M
  rootParser->m_alloc_tracker.bytesAllocated += bytesToAllocate;
930
931
  // Report as needed
932
1.34M
  if (rootParser->m_alloc_tracker.debugLevel >= 2) {
933
0
    if (rootParser->m_alloc_tracker.bytesAllocated
934
0
        > rootParser->m_alloc_tracker.peakBytesAllocated) {
935
0
      rootParser->m_alloc_tracker.peakBytesAllocated
936
0
          = rootParser->m_alloc_tracker.bytesAllocated;
937
0
    }
938
0
    expat_heap_stat(rootParser, '+', bytesToAllocate,
939
0
                    rootParser->m_alloc_tracker.bytesAllocated,
940
0
                    rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine);
941
0
  }
942
943
1.34M
  return (char *)mallocedPtr + sizeof(size_t) + EXPAT_MALLOC_PADDING;
944
1.34M
}
945
946
#  if defined(XML_TESTING)
947
void
948
#  else
949
static void
950
#  endif
951
12.0M
expat_free(XML_Parser parser, void *ptr, int sourceLine) {
952
12.0M
  assert(parser != NULL);
953
954
12.0M
  if (ptr == NULL) {
955
10.5M
    return;
956
10.5M
  }
957
958
1.45M
  const XML_Parser rootParser = getRootParserOf(parser, NULL);
959
1.45M
  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
1.45M
  void *const mallocedPtr = (char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t);
964
1.45M
  const size_t bytesAllocated
965
1.45M
      = sizeof(size_t) + EXPAT_MALLOC_PADDING + *(size_t *)mallocedPtr;
966
967
  // Update accounting
968
1.45M
  assert(rootParser->m_alloc_tracker.bytesAllocated >= bytesAllocated);
969
1.45M
  rootParser->m_alloc_tracker.bytesAllocated -= bytesAllocated;
970
971
  // Report as needed
972
1.45M
  if (rootParser->m_alloc_tracker.debugLevel >= 2) {
973
0
    expat_heap_stat(rootParser, '-', bytesAllocated,
974
0
                    rootParser->m_alloc_tracker.bytesAllocated,
975
0
                    rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine);
976
0
  }
977
978
  // NOTE: This may be freeing rootParser, so freeing has to come last
979
1.45M
  parser->m_mem.free_fcn(mallocedPtr);
980
1.45M
}
981
982
#  if defined(XML_TESTING)
983
void *
984
#  else
985
static void *
986
#  endif
987
10.4k
expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine) {
988
10.4k
  assert(parser != NULL);
989
990
10.4k
  if (ptr == NULL) {
991
3.75k
    return expat_malloc(parser, size, sourceLine);
992
3.75k
  }
993
994
6.65k
  if (size == 0) {
995
0
    expat_free(parser, ptr, sourceLine);
996
0
    return NULL;
997
0
  }
998
999
6.65k
  const XML_Parser rootParser = getRootParserOf(parser, NULL);
1000
6.65k
  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
6.65k
  void *mallocedPtr = (char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t);
1005
6.65k
  const size_t prevSize = *(size_t *)mallocedPtr;
1006
1007
  // Classify upcoming change
1008
6.65k
  const bool isIncrease = (size > prevSize);
1009
6.65k
  const size_t absDiff
1010
6.65k
      = (size > prevSize) ? (size - prevSize) : (prevSize - size);
1011
1012
  // Ask for permission from accounting
1013
6.65k
  if (isIncrease) {
1014
6.65k
    if (! expat_heap_increase_tolerable(rootParser, absDiff, sourceLine)) {
1015
0
      return NULL; // i.e. signal violation as out-of-memory
1016
0
    }
1017
6.65k
  }
1018
1019
  // Detect and prevent integer overflow
1020
6.65k
  if (size > SIZE_MAX - sizeof(size_t) - EXPAT_MALLOC_PADDING) {
1021
0
    return NULL;
1022
0
  }
1023
1024
  // Actually allocate
1025
6.65k
  mallocedPtr = parser->m_mem.realloc_fcn(
1026
6.65k
      mallocedPtr, sizeof(size_t) + EXPAT_MALLOC_PADDING + size);
1027
1028
6.65k
  if (mallocedPtr == NULL) {
1029
0
    return NULL;
1030
0
  }
1031
1032
  // Update accounting
1033
6.65k
  if (isIncrease) {
1034
6.65k
    assert(SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated >= absDiff);
1035
6.65k
    rootParser->m_alloc_tracker.bytesAllocated += absDiff;
1036
6.65k
  } else { // i.e. decrease
1037
0
    assert(rootParser->m_alloc_tracker.bytesAllocated >= absDiff);
1038
0
    rootParser->m_alloc_tracker.bytesAllocated -= absDiff;
1039
0
  }
1040
1041
  // Report as needed
1042
6.65k
  if (rootParser->m_alloc_tracker.debugLevel >= 2) {
1043
0
    if (rootParser->m_alloc_tracker.bytesAllocated
1044
0
        > rootParser->m_alloc_tracker.peakBytesAllocated) {
1045
0
      rootParser->m_alloc_tracker.peakBytesAllocated
1046
0
          = rootParser->m_alloc_tracker.bytesAllocated;
1047
0
    }
1048
0
    expat_heap_stat(rootParser, isIncrease ? '+' : '-', absDiff,
1049
0
                    rootParser->m_alloc_tracker.bytesAllocated,
1050
0
                    rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine);
1051
0
  }
1052
1053
  // Update in-block recorded size
1054
6.65k
  *(size_t *)mallocedPtr = size;
1055
1056
6.65k
  return (char *)mallocedPtr + sizeof(size_t) + EXPAT_MALLOC_PADDING;
1057
6.65k
}
1058
#endif // XML_GE == 1
1059
1060
XML_Parser XMLCALL
1061
1
XML_ParserCreate(const XML_Char *encodingName) {
1062
1
  return XML_ParserCreate_MM(encodingName, NULL, NULL);
1063
1
}
1064
1065
XML_Parser XMLCALL
1066
107k
XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
1067
107k
  XML_Char tmp[2] = {nsSep, 0};
1068
107k
  return XML_ParserCreate_MM(encodingName, NULL, tmp);
1069
107k
}
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
#    if defined(NDEBUG)
1098
  (void)gettimeofday_res;
1099
#    else
1100
0
  assert(gettimeofday_res == 0);
1101
0
#    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
107k
ENTROPY_DEBUG(const char *label, struct sipkey entropy_128) {
1112
107k
  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
107k
  return entropy_128;
1120
107k
}
1121
1122
static struct sipkey
1123
107k
generate_hash_secret_salt(void) {
1124
107k
  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
107k
  if (writeRandomBytes_getentropy(&entropy, sizeof(entropy))) {
1141
107k
    return ENTROPY_DEBUG("getentropy", entropy);
1142
107k
  }
1143
107k
  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
#  if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
1150
  if (writeRandomBytes_dev_urandom(&entropy, sizeof(entropy))) {
1151
    return ENTROPY_DEBUG("/dev/urandom", entropy);
1152
  }
1153
#  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
238k
beforeHandler(XML_Parser parser) {
1176
238k
  assert(parser->m_handlerCallDepth < UINT_MAX);
1177
238k
  parser->m_handlerCallDepth++;
1178
238k
}
1179
1180
static void
1181
238k
afterHandler(XML_Parser parser) {
1182
238k
  assert(parser->m_handlerCallDepth > 0);
1183
238k
  parser->m_handlerCallDepth--;
1184
238k
}
1185
1186
static bool
1187
429k
isCalledFromInsideHandler(XML_Parser parser) {
1188
429k
  return parser->m_handlerCallDepth > 0;
1189
429k
}
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
107k
              const char **endPtr) {
1213
107k
  const size_t have_now = EXPAT_SAFE_PTR_DIFF(end, start);
1214
1215
107k
  if (parser->m_reparseDeferralEnabled
1216
107k
      && ! 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
158
    const size_t had_before = parser->m_partialTokenBytesBefore;
1220
    // ...but *do* try anyway if we're close to causing a reallocation.
1221
158
    size_t available_buffer
1222
158
        = EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
1223
158
#if XML_CONTEXT_BYTES > 0
1224
158
    available_buffer -= EXPAT_MIN(available_buffer, XML_CONTEXT_BYTES);
1225
158
#endif
1226
158
    available_buffer
1227
158
        += 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
158
    const bool enough
1230
158
        = (have_now >= 2 * had_before)
1231
0
          || ((size_t)parser->m_lastBufferRequestSize > available_buffer);
1232
1233
158
    if (! enough) {
1234
0
      *endPtr = start; // callers may expect this to be set
1235
0
      return XML_ERROR_NONE;
1236
0
    }
1237
158
  }
1238
#if defined(XML_TESTING)
1239
  g_bytesScanned += (unsigned)have_now;
1240
#endif
1241
  // Run in a loop to eliminate dangerous recursion depths
1242
107k
  enum XML_Error ret;
1243
107k
  *endPtr = start;
1244
107k
  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
107k
    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
107k
    if (parser->m_parsingStatus.parsing != XML_PARSING) {
1252
0
      parser->m_reenter = XML_FALSE;
1253
0
    }
1254
1255
107k
    if (! parser->m_reenter) {
1256
107k
      break;
1257
107k
    }
1258
1259
0
    parser->m_reenter = XML_FALSE;
1260
0
    if (ret != XML_ERROR_NONE)
1261
0
      return ret;
1262
0
  }
1263
1264
107k
  if (ret == XML_ERROR_NONE) {
1265
    // if we consumed nothing, remember what we had on this parse attempt.
1266
6.12k
    if (*endPtr == start) {
1267
1
      parser->m_partialTokenBytesBefore = have_now;
1268
6.12k
    } else {
1269
6.12k
      parser->m_partialTokenBytesBefore = 0;
1270
6.12k
    }
1271
6.12k
  }
1272
107k
  return ret;
1273
107k
}
1274
1275
static XML_Bool /* only valid for root parser */
1276
107k
startParsing(XML_Parser parser) {
1277
  /* hash functions must be initialized before setContext() is called */
1278
107k
  if (parser->m_hash_secret_salt_set != XML_TRUE) {
1279
107k
    parser->m_hash_secret_salt_128 = generate_hash_secret_salt();
1280
107k
    parser->m_hash_secret_salt_set = XML_TRUE;
1281
107k
  }
1282
107k
  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
107k
    return setContext(parser, implicitContext);
1287
107k
  }
1288
1
  return XML_TRUE;
1289
107k
}
1290
1291
XML_Parser XMLCALL
1292
XML_ParserCreate_MM(const XML_Char *encodingName,
1293
                    const XML_Memory_Handling_Suite *memsuite,
1294
107k
                    const XML_Char *nameSep) {
1295
107k
  return parserCreate(encodingName, memsuite, nameSep, NULL, NULL);
1296
107k
}
1297
1298
static XML_Parser
1299
parserCreate(const XML_Char *encodingName,
1300
             const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep,
1301
107k
             DTD *dtd, XML_Parser parentParser) {
1302
107k
  XML_Parser parser = NULL;
1303
1304
107k
#if XML_GE == 1
1305
107k
  const size_t increase
1306
107k
      = sizeof(size_t) + EXPAT_MALLOC_PADDING + sizeof(struct XML_ParserStruct);
1307
1308
107k
  if (parentParser != NULL) {
1309
0
    const XML_Parser rootParser = getRootParserOf(parentParser, NULL);
1310
0
    if (! expat_heap_increase_tolerable(rootParser, increase, __LINE__)) {
1311
0
      return NULL;
1312
0
    }
1313
0
  }
1314
#else
1315
  UNUSED_P(parentParser);
1316
#endif
1317
1318
107k
  if (memsuite) {
1319
0
    XML_Memory_Handling_Suite *mtemp;
1320
0
#if XML_GE == 1
1321
0
    void *const sizeAndParser
1322
0
        = memsuite->malloc_fcn(sizeof(size_t) + EXPAT_MALLOC_PADDING
1323
0
                               + sizeof(struct XML_ParserStruct));
1324
0
    if (sizeAndParser != NULL) {
1325
0
      *(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct);
1326
0
      parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)
1327
0
                            + EXPAT_MALLOC_PADDING);
1328
#else
1329
    parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
1330
    if (parser != NULL) {
1331
#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
107k
  } else {
1338
107k
    XML_Memory_Handling_Suite *mtemp;
1339
107k
#if XML_GE == 1
1340
107k
    void *const sizeAndParser = malloc(sizeof(size_t) + EXPAT_MALLOC_PADDING
1341
107k
                                       + sizeof(struct XML_ParserStruct));
1342
107k
    if (sizeAndParser != NULL) {
1343
107k
      *(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct);
1344
107k
      parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)
1345
107k
                            + EXPAT_MALLOC_PADDING);
1346
#else
1347
    parser = malloc(sizeof(struct XML_ParserStruct));
1348
    if (parser != NULL) {
1349
#endif
1350
107k
      mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
1351
107k
      mtemp->malloc_fcn = malloc;
1352
107k
      mtemp->realloc_fcn = realloc;
1353
107k
      mtemp->free_fcn = free;
1354
107k
    }
1355
107k
  } // cppcheck-suppress[memleak symbolName=sizeAndParser] // Cppcheck >=2.18.0
1356
1357
107k
  if (! parser)
1358
0
    return parser;
1359
1360
107k
#if XML_GE == 1
1361
  // Initialize .m_alloc_tracker
1362
107k
  memset(&parser->m_alloc_tracker, 0, sizeof(MALLOC_TRACKER));
1363
107k
  if (parentParser == NULL) {
1364
107k
    parser->m_alloc_tracker.debugLevel
1365
107k
        = getDebugLevel("EXPAT_MALLOC_DEBUG", 0u);
1366
107k
    parser->m_alloc_tracker.maximumAmplificationFactor
1367
107k
        = EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT;
1368
107k
    parser->m_alloc_tracker.activationThresholdBytes
1369
107k
        = 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
107k
    parser->m_parentParser = NULL;
1374
107k
    parser->m_accounting.countBytesDirect = 0;
1375
107k
  } else {
1376
0
    parser->m_parentParser = parentParser;
1377
0
  }
1378
1379
  // Record XML_ParserStruct allocation we did a few lines up before
1380
107k
  const XML_Parser rootParser = getRootParserOf(parser, NULL);
1381
107k
  assert(rootParser->m_parentParser == NULL);
1382
107k
  assert(SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated >= increase);
1383
107k
  rootParser->m_alloc_tracker.bytesAllocated += increase;
1384
1385
  // Report on allocation
1386
107k
  if (rootParser->m_alloc_tracker.debugLevel >= 2) {
1387
0
    if (rootParser->m_alloc_tracker.bytesAllocated
1388
0
        > rootParser->m_alloc_tracker.peakBytesAllocated) {
1389
0
      rootParser->m_alloc_tracker.peakBytesAllocated
1390
0
          = rootParser->m_alloc_tracker.bytesAllocated;
1391
0
    }
1392
1393
0
    expat_heap_stat(rootParser, '+', increase,
1394
0
                    rootParser->m_alloc_tracker.bytesAllocated,
1395
0
                    rootParser->m_alloc_tracker.peakBytesAllocated, __LINE__);
1396
0
  }
1397
#else
1398
  parser->m_parentParser = NULL;
1399
#endif // XML_GE == 1
1400
1401
107k
  parser->m_buffer = NULL;
1402
107k
  parser->m_bufferLim = NULL;
1403
1404
107k
  parser->m_attsSize = INIT_ATTS_SIZE;
1405
107k
  parser->m_atts = MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
1406
107k
  if (parser->m_atts == NULL) {
1407
0
    FREE(parser, parser);
1408
0
    return NULL;
1409
0
  }
1410
107k
  parser->m_dataBuf = MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
1411
107k
  if (parser->m_dataBuf == NULL) {
1412
0
    FREE(parser, parser->m_atts);
1413
0
    FREE(parser, parser);
1414
0
    return NULL;
1415
0
  }
1416
107k
  parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
1417
1418
107k
  if (dtd)
1419
0
    parser->m_dtd = dtd;
1420
107k
  else {
1421
107k
    parser->m_dtd = dtdCreate(parser);
1422
107k
    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
107k
  }
1429
1430
107k
  parser->m_freeBindingList = NULL;
1431
107k
  parser->m_freeTagList = NULL;
1432
107k
  parser->m_freeEntities = NULL;
1433
1434
107k
  parser->m_groupSize = 0;
1435
107k
  parser->m_groupConnector = NULL;
1436
1437
107k
  parser->m_unknownEncodingHandler = NULL;
1438
107k
  parser->m_unknownEncodingHandlerData = NULL;
1439
1440
107k
  parser->m_namespaceSeparator = ASCII_EXCL;
1441
107k
  parser->m_ns = XML_FALSE;
1442
107k
  parser->m_ns_triplets = XML_FALSE;
1443
1444
107k
  parser->m_nsAtts = NULL;
1445
107k
  parser->m_nsAttsVersion = 0;
1446
107k
  parser->m_nsAttsPower = 0;
1447
1448
107k
  parser->m_protocolEncodingName = NULL;
1449
1450
107k
  poolInit(&parser->m_tempPool, parser);
1451
107k
  poolInit(&parser->m_temp2Pool, parser);
1452
107k
  parserInit(parser, encodingName);
1453
1454
107k
  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
107k
  if (nameSep) {
1468
107k
    parser->m_ns = XML_TRUE;
1469
107k
    parser->m_internalEncoding = XmlGetInternalEncodingNS();
1470
107k
    parser->m_namespaceSeparator = *nameSep;
1471
107k
  } else {
1472
1
    parser->m_internalEncoding = XmlGetInternalEncoding();
1473
1
  }
1474
1475
107k
  return parser;
1476
107k
}
1477
1478
static void
1479
107k
parserInit(XML_Parser parser, const XML_Char *encodingName) {
1480
107k
  parser->m_processor = prologInitProcessor;
1481
107k
  XmlPrologStateInit(&parser->m_prologState);
1482
107k
  if (encodingName != NULL) {
1483
1
    parser->m_protocolEncodingName = copyString(encodingName, parser);
1484
1
  }
1485
107k
  parser->m_curBase = NULL;
1486
107k
  XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
1487
107k
  parser->m_userData = NULL;
1488
107k
  parser->m_handlerArg = NULL;
1489
107k
  parser->m_startElementHandler = NULL;
1490
107k
  parser->m_endElementHandler = NULL;
1491
107k
  parser->m_characterDataHandler = NULL;
1492
107k
  parser->m_processingInstructionHandler = NULL;
1493
107k
  parser->m_commentHandler = NULL;
1494
107k
  parser->m_startCdataSectionHandler = NULL;
1495
107k
  parser->m_endCdataSectionHandler = NULL;
1496
107k
  parser->m_defaultHandler = NULL;
1497
107k
  parser->m_startDoctypeDeclHandler = NULL;
1498
107k
  parser->m_endDoctypeDeclHandler = NULL;
1499
107k
  parser->m_unparsedEntityDeclHandler = NULL;
1500
107k
  parser->m_notationDeclHandler = NULL;
1501
107k
  parser->m_startNamespaceDeclHandler = NULL;
1502
107k
  parser->m_endNamespaceDeclHandler = NULL;
1503
107k
  parser->m_notStandaloneHandler = NULL;
1504
107k
  parser->m_externalEntityRefHandler = NULL;
1505
107k
  parser->m_externalEntityRefHandlerArg = parser;
1506
107k
  parser->m_skippedEntityHandler = NULL;
1507
107k
  parser->m_elementDeclHandler = NULL;
1508
107k
  parser->m_attlistDeclHandler = NULL;
1509
107k
  parser->m_entityDeclHandler = NULL;
1510
107k
  parser->m_xmlDeclHandler = NULL;
1511
107k
  parser->m_bufferPtr = parser->m_buffer;
1512
107k
  parser->m_bufferEnd = parser->m_buffer;
1513
107k
  parser->m_parseEndByteIndex = 0;
1514
107k
  parser->m_parseEndPtr = NULL;
1515
107k
  parser->m_partialTokenBytesBefore = 0;
1516
107k
  parser->m_reparseDeferralEnabled = g_reparseDeferralEnabledDefault;
1517
107k
  parser->m_lastBufferRequestSize = 0;
1518
107k
  parser->m_declElementType = NULL;
1519
107k
  parser->m_declAttributeId = NULL;
1520
107k
  parser->m_declEntity = NULL;
1521
107k
  parser->m_doctypeName = NULL;
1522
107k
  parser->m_doctypeSysid = NULL;
1523
107k
  parser->m_doctypePubid = NULL;
1524
107k
  parser->m_declAttributeType = NULL;
1525
107k
  parser->m_declNotationName = NULL;
1526
107k
  parser->m_declNotationPublicId = NULL;
1527
107k
  parser->m_declAttributeIsCdata = false;
1528
107k
  parser->m_declAttributeIsId = false;
1529
107k
  memset(&parser->m_position, 0, sizeof(POSITION));
1530
107k
  parser->m_errorCode = XML_ERROR_NONE;
1531
107k
  parser->m_eventPtr = NULL;
1532
107k
  parser->m_eventEndPtr = NULL;
1533
107k
  parser->m_positionPtr = NULL;
1534
107k
  parser->m_openInternalEntities = NULL;
1535
107k
  parser->m_openAttributeEntities = NULL;
1536
107k
  parser->m_openValueEntities = NULL;
1537
107k
  parser->m_defaultExpandInternalEntities = XML_TRUE;
1538
107k
  parser->m_tagLevel = 0;
1539
107k
  parser->m_tagStack = NULL;
1540
107k
  parser->m_inheritedBindings = NULL;
1541
107k
  parser->m_nSpecifiedAtts = 0;
1542
107k
  parser->m_unknownEncodingMem = NULL;
1543
107k
  parser->m_unknownEncodingConvert = NULL;
1544
107k
  parser->m_unknownEncodingRelease = NULL;
1545
107k
  parser->m_unknownEncodingData = NULL;
1546
107k
  parser->m_parsingStatus.parsing = XML_INITIALIZED;
1547
  // Reentry can only be triggered inside m_processor calls
1548
107k
  parser->m_reenter = XML_FALSE;
1549
107k
  parser->m_handlerCallDepth = 0;
1550
107k
#ifdef XML_DTD
1551
107k
  parser->m_isParamEntity = XML_FALSE;
1552
107k
  parser->m_useForeignDTD = XML_FALSE;
1553
107k
  parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
1554
107k
#endif
1555
107k
  parser->m_hash_secret_salt_128.k[0] = 0;
1556
107k
  parser->m_hash_secret_salt_128.k[1] = 0;
1557
107k
  parser->m_hash_secret_salt_set = XML_FALSE;
1558
1559
107k
#if XML_GE == 1
1560
107k
  memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
1561
107k
  parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
1562
107k
  parser->m_accounting.maximumAmplificationFactor
1563
107k
      = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT;
1564
107k
  parser->m_accounting.activationThresholdBytes
1565
107k
      = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT;
1566
1567
107k
  memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS));
1568
107k
  parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u);
1569
107k
#endif
1570
107k
}
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
0
#ifdef XML_DTD
1713
0
  enum XML_ParamEntityParsing oldParamEntityParsing;
1714
0
  int oldInEntityValue;
1715
0
#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
0
#ifdef XML_DTD
1760
0
  oldParamEntityParsing = parser->m_paramEntityParsing;
1761
0
  oldInEntityValue = parser->m_prologState.inEntityValue;
1762
0
#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
0
#ifdef XML_DTD
1774
0
  if (! context)
1775
0
    newDtd = oldDtd;
1776
0
#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
0
#ifdef XML_DTD
1825
0
  parser->m_paramEntityParsing = oldParamEntityParsing;
1826
0
  parser->m_prologState.inEntityValue = oldInEntityValue;
1827
0
  if (context) {
1828
0
#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
0
#ifdef XML_DTD
1836
0
  } 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
0
    parser->m_isParamEntity = XML_TRUE;
1845
0
    XmlPrologStateInitExternalEntity(&parser->m_prologState);
1846
0
    parser->m_processor = externalParEntInitProcessor;
1847
0
  }
1848
0
#endif /* XML_DTD */
1849
0
  return parser;
1850
0
}
1851
1852
static void
1853
265k
destroyBindings(BINDING *bindings, XML_Parser parser) {
1854
398k
  for (;;) {
1855
398k
    BINDING *b = bindings;
1856
398k
    if (! b)
1857
265k
      break;
1858
133k
    bindings = b->nextTagBinding;
1859
133k
    FREE(parser, b->uri);
1860
133k
    FREE(parser, b);
1861
133k
  }
1862
265k
}
1863
1864
void XMLCALL
1865
107k
XML_ParserFree(XML_Parser parser) {
1866
107k
  TAG *tagList;
1867
107k
  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
107k
  if (parser->m_unknownEncodingRelease)
1872
0
    callUnknownEncodingRelease(parser);
1873
  /* free m_tagStack and m_freeTagList */
1874
107k
  tagList = parser->m_tagStack;
1875
157k
  for (;;) {
1876
157k
    TAG *p;
1877
157k
    if (tagList == NULL) {
1878
110k
      if (parser->m_freeTagList == NULL)
1879
107k
        break;
1880
2.73k
      tagList = parser->m_freeTagList;
1881
2.73k
      parser->m_freeTagList = NULL;
1882
2.73k
    }
1883
50.5k
    p = tagList;
1884
50.5k
    tagList = tagList->parent;
1885
50.5k
    FREE(parser, p->buf.raw);
1886
50.5k
    destroyBindings(p->bindings, parser);
1887
50.5k
    FREE(parser, p);
1888
50.5k
  }
1889
  /* free m_openInternalEntities */
1890
107k
  for (OPEN_INTERNAL_ENTITY *entityList = parser->m_openInternalEntities;
1891
107k
       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
107k
  for (OPEN_INTERNAL_ENTITY *entityList = parser->m_openAttributeEntities;
1898
107k
       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
107k
  for (OPEN_INTERNAL_ENTITY *entityList = parser->m_openValueEntities;
1905
107k
       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
107k
  for (OPEN_INTERNAL_ENTITY *entityList = parser->m_freeEntities;
1912
107k
       entityList != NULL;) {
1913
0
    OPEN_INTERNAL_ENTITY *const openEntity = entityList;
1914
0
    entityList = entityList->next;
1915
0
    FREE(parser, openEntity);
1916
0
  }
1917
107k
  parser->m_freeEntities = NULL;
1918
107k
  destroyBindings(parser->m_freeBindingList, parser);
1919
107k
  destroyBindings(parser->m_inheritedBindings, parser);
1920
107k
  poolDestroy(&parser->m_tempPool);
1921
107k
  poolDestroy(&parser->m_temp2Pool);
1922
107k
  FREE(parser, (void *)parser->m_protocolEncodingName);
1923
107k
#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
107k
  if (! parser->m_isParamEntity && parser->m_dtd)
1928
#else
1929
  if (parser->m_dtd)
1930
#endif /* XML_DTD */
1931
107k
    dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser, parser);
1932
107k
  FREE(parser, parser->m_atts);
1933
107k
  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
107k
  parser->m_mem.free_fcn(parser->m_buffer);
1938
107k
  FREE(parser, parser->m_dataBuf);
1939
107k
  FREE(parser, parser->m_nsAtts);
1940
107k
  FREE(parser, parser->m_unknownEncodingMem);
1941
107k
  FREE(parser, parser);
1942
107k
}
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
0
#ifdef XML_DTD
1955
  /* block after XML_Parse()/XML_ParseBuffer() has been called */
1956
0
  if (parserBusy(parser))
1957
0
    return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1958
0
  parser->m_useForeignDTD = useDTD;
1959
0
  return XML_ERROR_NONE;
1960
#else
1961
  UNUSED_P(useDTD);
1962
  return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1963
#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
107k
XML_SetUserData(XML_Parser parser, void *p) {
1978
107k
  if (parser == NULL)
1979
0
    return;
1980
107k
  if (parser->m_handlerArg == parser->m_userData)
1981
107k
    parser->m_handlerArg = parser->m_userData = p;
1982
0
  else
1983
0
    parser->m_userData = p;
1984
107k
}
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
107k
                      XML_EndElementHandler end) {
2024
107k
  if (parser == NULL)
2025
0
    return;
2026
107k
  parser->m_startElementHandler = start;
2027
107k
  parser->m_endElementHandler = end;
2028
107k
}
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
3.06k
                            XML_CharacterDataHandler handler) {
2045
3.06k
  if (parser != NULL)
2046
3.06k
    parser->m_characterDataHandler = handler;
2047
3.06k
}
2048
2049
void XMLCALL
2050
XML_SetProcessingInstructionHandler(XML_Parser parser,
2051
3.06k
                                    XML_ProcessingInstructionHandler handler) {
2052
3.06k
  if (parser != NULL)
2053
3.06k
    parser->m_processingInstructionHandler = handler;
2054
3.06k
}
2055
2056
void XMLCALL
2057
3.06k
XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) {
2058
3.06k
  if (parser != NULL)
2059
3.06k
    parser->m_commentHandler = handler;
2060
3.06k
}
2061
2062
void XMLCALL
2063
XML_SetCdataSectionHandler(XML_Parser parser,
2064
                           XML_StartCdataSectionHandler start,
2065
3.06k
                           XML_EndCdataSectionHandler end) {
2066
3.06k
  if (parser == NULL)
2067
0
    return;
2068
3.06k
  parser->m_startCdataSectionHandler = start;
2069
3.06k
  parser->m_endCdataSectionHandler = end;
2070
3.06k
}
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
1
                          XML_EndDoctypeDeclHandler end) {
2105
1
  if (parser == NULL)
2106
0
    return;
2107
1
  parser->m_startDoctypeDeclHandler = start;
2108
1
  parser->m_endDoctypeDeclHandler = end;
2109
1
}
2110
2111
void XMLCALL
2112
XML_SetStartDoctypeDeclHandler(XML_Parser parser,
2113
107k
                               XML_StartDoctypeDeclHandler start) {
2114
107k
  if (parser != NULL)
2115
107k
    parser->m_startDoctypeDeclHandler = start;
2116
107k
}
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
107k
                            XML_EndNamespaceDeclHandler end) {
2141
107k
  if (parser == NULL)
2142
0
    return;
2143
107k
  parser->m_startNamespaceDeclHandler = start;
2144
107k
  parser->m_endNamespaceDeclHandler = end;
2145
107k
}
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
0
#ifdef XML_DTD
2234
0
  parser->m_paramEntityParsing = peParsing;
2235
0
  return 1;
2236
#else
2237
  return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
2238
#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
107k
XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
2302
107k
  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
107k
  if (isCalledFromInsideHandler(parser))
2308
0
    return XML_STATUS_ERROR;
2309
107k
  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
79
  case XML_FINISHED:
2314
79
    parser->m_errorCode = XML_ERROR_FINISHED;
2315
79
    return XML_STATUS_ERROR;
2316
107k
  case XML_INITIALIZED:
2317
107k
    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
107k
    EXPAT_FALLTHROUGH;
2322
107k
  default:
2323
107k
    parser->m_parsingStatus.parsing = XML_PARSING;
2324
107k
  }
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
107k
  void *buff = XML_GetBuffer(parser, len);
2404
107k
  if (buff == NULL)
2405
0
    return XML_STATUS_ERROR;
2406
107k
  if (len > 0) {
2407
107k
    assert(s != NULL); // make sure s==NULL && len!=0 was rejected above
2408
107k
    memcpy(buff, s, len);
2409
107k
  }
2410
107k
  return XML_ParseBuffer(parser, len, isFinal);
2411
107k
}
2412
2413
enum XML_Status XMLCALL
2414
107k
XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
2415
107k
  const char *start;
2416
107k
  enum XML_Status result = XML_STATUS_OK;
2417
2418
107k
  if ((parser == NULL) || isCalledFromInsideHandler(parser))
2419
0
    return XML_STATUS_ERROR;
2420
2421
107k
  if (len < 0) {
2422
0
    parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
2423
0
    return XML_STATUS_ERROR;
2424
0
  }
2425
2426
107k
  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
1
  case XML_INITIALIZED:
2434
    /* Has someone called XML_GetBuffer successfully before? */
2435
1
    if (! parser->m_bufferPtr) {
2436
0
      parser->m_errorCode = XML_ERROR_NO_BUFFER;
2437
0
      return XML_STATUS_ERROR;
2438
0
    }
2439
2440
1
    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
1
    EXPAT_FALLTHROUGH;
2445
107k
  default:
2446
107k
    parser->m_parsingStatus.parsing = XML_PARSING;
2447
107k
  }
2448
2449
107k
  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
107k
  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
107k
  start = parser->m_bufferPtr;
2463
107k
  parser->m_positionPtr = start;
2464
107k
  parser->m_bufferEnd += len;
2465
107k
  parser->m_parseEndPtr = parser->m_bufferEnd;
2466
107k
  parser->m_parseEndByteIndex += len;
2467
107k
  parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
2468
2469
107k
  parser->m_errorCode = callProcessor(parser, start, parser->m_parseEndPtr,
2470
107k
                                      &parser->m_bufferPtr);
2471
2472
107k
  if (parser->m_errorCode != XML_ERROR_NONE) {
2473
101k
    parser->m_eventEndPtr = parser->m_eventPtr;
2474
101k
    parser->m_processor = errorProcessor;
2475
101k
    return XML_STATUS_ERROR;
2476
101k
  } else {
2477
6.12k
    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
6.12k
    case XML_PARSING:
2483
6.12k
      if (isFinal) {
2484
5.96k
        parser->m_parsingStatus.parsing = XML_FINISHED;
2485
5.96k
        return result;
2486
5.96k
      }
2487
158
      break;
2488
158
    default:; /* should not happen */
2489
6.12k
    }
2490
6.12k
  }
2491
2492
158
  XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2493
158
                    parser->m_bufferPtr, &parser->m_position);
2494
158
  parser->m_positionPtr = parser->m_bufferPtr;
2495
158
  return result;
2496
107k
}
2497
2498
/* Modifies `parser`’s buffer to be backed by `newBuf`. */
2499
static void
2500
107k
setParserBuffer(XML_Parser parser, char *newBuf, int newBufSize, int keep) {
2501
107k
  parser->m_bufferLim = newBuf + newBufSize;
2502
107k
  if (parser->m_bufferPtr) {
2503
1
    const int parsing
2504
1
        = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
2505
1
    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
1
    parser->m_mem.free_fcn(parser->m_buffer);
2510
1
    parser->m_buffer = newBuf;
2511
1
    parser->m_bufferEnd = newBuf + parsing + keep;
2512
1
    parser->m_bufferPtr = newBuf + keep;
2513
107k
  } else {
2514
    /* This must be a brand new buffer with no data in it yet */
2515
107k
    parser->m_buffer = newBuf;
2516
107k
    parser->m_bufferEnd = newBuf;
2517
107k
    parser->m_bufferPtr = newBuf;
2518
107k
  }
2519
107k
}
2520
2521
void *XMLCALL
2522
107k
XML_GetBuffer(XML_Parser parser, int len) {
2523
107k
  if ((parser == NULL) || isCalledFromInsideHandler(parser))
2524
0
    return NULL;
2525
107k
  if (len < 0) {
2526
0
    parser->m_errorCode = XML_ERROR_NO_MEMORY;
2527
0
    return NULL;
2528
0
  }
2529
107k
  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
107k
  default:;
2537
107k
  }
2538
2539
  // whether or not the request succeeds, `len` seems to be the app's preferred
2540
  // buffer fill size; remember it.
2541
107k
  parser->m_lastBufferRequestSize = len;
2542
107k
  if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)
2543
107k
      || parser->m_buffer == NULL) {
2544
    /* Do not invoke signed arithmetic overflow: */
2545
107k
    int neededSize = (int)((unsigned)len
2546
107k
                           + (unsigned)EXPAT_SAFE_PTR_DIFF(
2547
107k
                               parser->m_bufferEnd, parser->m_bufferPtr));
2548
107k
    if (neededSize < 0) {
2549
0
      parser->m_errorCode = XML_ERROR_NO_MEMORY;
2550
0
      return NULL;
2551
0
    }
2552
107k
#if XML_CONTEXT_BYTES > 0
2553
107k
    const int parsed
2554
107k
        = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
2555
107k
    int keep = parsed;
2556
107k
    if (keep > XML_CONTEXT_BYTES)
2557
0
      keep = XML_CONTEXT_BYTES;
2558
    /* Detect and prevent integer overflow */
2559
107k
    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
107k
    neededSize += keep;
2567
107k
    if (parser->m_buffer && parser->m_bufferPtr
2568
1
        && neededSize
2569
1
               <= 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
107k
    } else {
2589
107k
      int bufferSize
2590
107k
          = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer);
2591
107k
      if (bufferSize == 0)
2592
107k
        bufferSize = INIT_BUFFER_SIZE;
2593
112k
      do {
2594
        /* Do not invoke signed arithmetic overflow: */
2595
112k
        bufferSize = (int)(2U * (unsigned)bufferSize);
2596
112k
      } while (bufferSize < neededSize && bufferSize > 0);
2597
107k
      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
107k
      char *const newBuf = parser->m_mem.malloc_fcn(bufferSize);
2604
107k
      if (newBuf == NULL) {
2605
0
        parser->m_errorCode = XML_ERROR_NO_MEMORY;
2606
0
        return NULL;
2607
0
      }
2608
107k
      setParserBuffer(parser, newBuf, bufferSize, keep);
2609
107k
    }
2610
107k
    parser->m_eventPtr = parser->m_eventEndPtr = NULL;
2611
107k
    parser->m_positionPtr = NULL;
2612
107k
  }
2613
107k
  return parser->m_bufferEnd;
2614
107k
}
2615
2616
static void
2617
0
triggerReenter(XML_Parser parser) {
2618
0
  parser->m_reenter = XML_TRUE;
2619
0
}
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
0
#ifdef XML_DTD
2642
0
      if (parser->m_isParamEntity) {
2643
0
        parser->m_errorCode = XML_ERROR_SUSPEND_PE;
2644
0
        return XML_STATUS_ERROR;
2645
0
      }
2646
0
#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
101k
XML_GetErrorCode(XML_Parser parser) {
2708
101k
  if (parser == NULL)
2709
0
    return XML_ERROR_INVALID_ARGUMENT;
2710
101k
  return parser->m_errorCode;
2711
101k
}
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
104k
XML_GetCurrentLineNumber64(XML_Parser parser) {
2809
104k
  if (parser == NULL)
2810
0
    return 0;
2811
104k
  if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2812
104k
    XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2813
104k
                      parser->m_eventPtr, &parser->m_position);
2814
104k
    parser->m_positionPtr = parser->m_eventPtr;
2815
104k
  }
2816
104k
  return parser->m_position.lineNumber + 1;
2817
104k
}
2818
2819
// DEPRECATED since Expat 2.9.0.
2820
XML_Size XMLCALL
2821
104k
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
104k
  return (XML_Size)XML_GetCurrentLineNumber64(parser);
2828
104k
}
2829
2830
uint64_t XMLCALL
2831
104k
XML_GetCurrentColumnNumber64(XML_Parser parser) {
2832
104k
  if (parser == NULL)
2833
0
    return 0;
2834
104k
  if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2835
104k
    XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2836
104k
                      parser->m_eventPtr, &parser->m_position);
2837
104k
    parser->m_positionPtr = parser->m_eventPtr;
2838
104k
  }
2839
104k
  return parser->m_position.columnNumber;
2840
104k
}
2841
2842
// DEPRECATED since Expat 2.9.0.
2843
XML_Size XMLCALL
2844
104k
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
104k
  return (XML_Size)XML_GetCurrentColumnNumber64(parser);
2851
104k
}
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
101k
XML_ErrorString(enum XML_Error code) {
2911
101k
  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
11.4k
  case XML_ERROR_SYNTAX:
2917
11.4k
    return XML_L("syntax error");
2918
1.54k
  case XML_ERROR_NO_ELEMENTS:
2919
1.54k
    return XML_L("no element found");
2920
63.8k
  case XML_ERROR_INVALID_TOKEN:
2921
63.8k
    return XML_L("not well-formed (invalid token)");
2922
10.2k
  case XML_ERROR_UNCLOSED_TOKEN:
2923
10.2k
    return XML_L("unclosed token");
2924
6.65k
  case XML_ERROR_PARTIAL_CHAR:
2925
6.65k
    return XML_L("partial character");
2926
238
  case XML_ERROR_TAG_MISMATCH:
2927
238
    return XML_L("mismatched tag");
2928
136
  case XML_ERROR_DUPLICATE_ATTRIBUTE:
2929
136
    return XML_L("duplicate attribute");
2930
969
  case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
2931
969
    return XML_L("junk after document element");
2932
158
  case XML_ERROR_PARAM_ENTITY_REF:
2933
158
    return XML_L("illegal parameter entity reference");
2934
1.00k
  case XML_ERROR_UNDEFINED_ENTITY:
2935
1.00k
    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
2.08k
  case XML_ERROR_BAD_CHAR_REF:
2941
2.08k
    return XML_L("reference to invalid character number");
2942
0
  case XML_ERROR_BINARY_ENTITY_REF:
2943
0
    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
28
  case XML_ERROR_MISPLACED_XML_PI:
2947
28
    return XML_L("XML or text declaration not at start of entity");
2948
0
  case XML_ERROR_UNKNOWN_ENCODING:
2949
0
    return XML_L("unknown encoding");
2950
0
  case XML_ERROR_INCORRECT_ENCODING:
2951
0
    return XML_L("encoding specified in XML declaration is incorrect");
2952
375
  case XML_ERROR_UNCLOSED_CDATA_SECTION:
2953
375
    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
1.18k
  case XML_ERROR_UNBOUND_PREFIX:
2968
1.18k
    return XML_L("unbound prefix");
2969
  /* Added in 1.95.8. */
2970
34
  case XML_ERROR_UNDECLARING_PREFIX:
2971
34
    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
1.15k
  case XML_ERROR_XML_DECL:
2975
1.15k
    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
0
  case XML_ERROR_PUBLICID:
2979
0
    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
46
  case XML_ERROR_RESERVED_PREFIX_XML:
2992
46
    return XML_L(
2993
0
        "reserved prefix (xml) must not be undeclared or bound to another namespace name");
2994
21
  case XML_ERROR_RESERVED_PREFIX_XMLNS:
2995
21
    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
101k
  }
3014
0
  return NULL;
3015
101k
}
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
0
#ifdef XML_DTD
3061
0
      {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
3062
0
#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
0
#ifdef XML_NS
3068
0
      {XML_FEATURE_NS, XML_L("XML_NS"), 0},
3069
0
#endif
3070
#ifdef XML_LARGE_SIZE
3071
      {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
3072
#endif
3073
0
#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
0
      {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
3077
0
       XML_L("XML_BLAP_MAX_AMP"),
3078
0
       (long int)
3079
0
           EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT},
3080
0
      {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
3081
0
       XML_L("XML_BLAP_ACT_THRES"),
3082
0
       EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT},
3083
      /* Added in Expat 2.6.0. */
3084
0
      {XML_FEATURE_GE, XML_L("XML_GE"), 0},
3085
      /* Added in Expat 2.7.2. */
3086
0
      {XML_FEATURE_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT,
3087
0
       XML_L("XML_AT_MAX_AMP"),
3088
0
       (long int)EXPAT_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION_DEFAULT},
3089
0
      {XML_FEATURE_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT,
3090
0
       XML_L("XML_AT_ACT_THRES"),
3091
0
       (long int)EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT},
3092
0
#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
0
    XML_Parser parser, float maximumAmplificationFactor) {
3102
0
  if (parser == NULL)
3103
0
    return XML_PROP_ERROR_PARSER_NULL;
3104
3105
0
  if (parser->m_parentParser != NULL)
3106
0
    return XML_PROP_ERROR_PARSER_NOT_ROOT;
3107
3108
0
  if (isnan(maximumAmplificationFactor) || (maximumAmplificationFactor < 1.0f))
3109
0
    return XML_PROP_ERROR_INVALID_VALUE;
3110
3111
0
  parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor;
3112
3113
0
  return XML_PROP_ERROR_NONE;
3114
0
}
3115
3116
XML_Bool XMLCALL
3117
XML_SetBillionLaughsAttackProtectionMaximumAmplification(
3118
0
    XML_Parser parser, float maximumAmplificationFactor) {
3119
0
  return (setBillionLaughsAttackProtectionMaximumAmplification(
3120
0
              parser, maximumAmplificationFactor)
3121
0
          == XML_PROP_ERROR_NONE)
3122
0
             ? XML_TRUE
3123
0
             : XML_FALSE;
3124
0
}
3125
3126
static enum XML_Prop_Error
3127
setBillionLaughsAttackProtectionActivationThreshold(
3128
0
    XML_Parser parser, unsigned long long activationThresholdBytes) {
3129
0
  if (parser == NULL)
3130
0
    return XML_PROP_ERROR_PARSER_NULL;
3131
3132
0
  if (parser->m_parentParser != NULL)
3133
0
    return XML_PROP_ERROR_PARSER_NOT_ROOT;
3134
3135
0
  parser->m_accounting.activationThresholdBytes = activationThresholdBytes;
3136
3137
0
  return XML_PROP_ERROR_NONE;
3138
0
}
3139
3140
XML_Bool XMLCALL
3141
XML_SetBillionLaughsAttackProtectionActivationThreshold(
3142
0
    XML_Parser parser, unsigned long long activationThresholdBytes) {
3143
0
  return (setBillionLaughsAttackProtectionActivationThreshold(
3144
0
              parser, activationThresholdBytes)
3145
0
          == XML_PROP_ERROR_NONE)
3146
0
             ? XML_TRUE
3147
0
             : XML_FALSE;
3148
0
}
3149
3150
static enum XML_Prop_Error
3151
setAllocTrackerMaximumAmplification(XML_Parser parser,
3152
0
                                    float maximumAmplificationFactor) {
3153
0
  if (parser == NULL)
3154
0
    return XML_PROP_ERROR_PARSER_NULL;
3155
3156
0
  if (parser->m_parentParser != NULL)
3157
0
    return XML_PROP_ERROR_PARSER_NOT_ROOT;
3158
3159
0
  if (isnan(maximumAmplificationFactor) || (maximumAmplificationFactor < 1.0f))
3160
0
    return XML_PROP_ERROR_INVALID_VALUE;
3161
3162
0
  parser->m_alloc_tracker.maximumAmplificationFactor
3163
0
      = maximumAmplificationFactor;
3164
3165
0
  return XML_PROP_ERROR_NONE;
3166
0
}
3167
3168
XML_Bool XMLCALL
3169
XML_SetAllocTrackerMaximumAmplification(XML_Parser parser,
3170
0
                                        float maximumAmplificationFactor) {
3171
0
  return (setAllocTrackerMaximumAmplification(parser,
3172
0
                                              maximumAmplificationFactor)
3173
0
          == XML_PROP_ERROR_NONE)
3174
0
             ? XML_TRUE
3175
0
             : XML_FALSE;
3176
0
}
3177
3178
static enum XML_Prop_Error
3179
setAllocTrackerActivationThreshold(
3180
0
    XML_Parser parser, unsigned long long activationThresholdBytes) {
3181
0
  if (parser == NULL)
3182
0
    return XML_PROP_ERROR_PARSER_NULL;
3183
3184
0
  if (parser->m_parentParser != NULL)
3185
0
    return XML_PROP_ERROR_PARSER_NOT_ROOT;
3186
3187
0
  parser->m_alloc_tracker.activationThresholdBytes = activationThresholdBytes;
3188
3189
0
  return XML_PROP_ERROR_NONE;
3190
0
}
3191
3192
XML_Bool XMLCALL
3193
XML_SetAllocTrackerActivationThreshold(
3194
0
    XML_Parser parser, unsigned long long activationThresholdBytes) {
3195
0
  return (setAllocTrackerActivationThreshold(parser, activationThresholdBytes)
3196
0
          == XML_PROP_ERROR_NONE)
3197
0
             ? XML_TRUE
3198
0
             : XML_FALSE;
3199
0
}
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
0
#if XML_GE == 1
3230
0
  case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD:
3231
0
  case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION:
3232
0
  case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD:
3233
0
  case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION:
3234
0
    return XML_PROP_ERROR_INVALID_TYPE;
3235
0
#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
#if XML_GE == 0
3252
  UNUSED_P(value);
3253
#endif
3254
3255
0
  switch (property) {
3256
0
#if XML_GE == 1
3257
0
  case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION:
3258
0
    return setAllocTrackerMaximumAmplification(parser, (float)value);
3259
0
  case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION:
3260
0
    return setBillionLaughsAttackProtectionMaximumAmplification(parser,
3261
0
                                                                (float)value);
3262
0
  case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD:
3263
0
  case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD:
3264
0
#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
#if XML_GE == 0
3281
  UNUSED_P(value);
3282
#endif
3283
3284
0
  switch (property) {
3285
0
#if XML_GE == 1
3286
0
  case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD:
3287
0
    return setAllocTrackerActivationThreshold(parser,
3288
0
                                              (unsigned long long)value);
3289
0
  case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD:
3290
0
    return setBillionLaughsAttackProtectionActivationThreshold(
3291
0
        parser, (unsigned long long)value);
3292
0
  case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION:
3293
0
  case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION:
3294
0
#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
0
#if XML_GE == 1
3315
0
  case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD:
3316
0
  case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION:
3317
0
  case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD:
3318
0
  case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION:
3319
0
    return XML_PROP_ERROR_INVALID_TYPE;
3320
0
#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
0
#if XML_GE == 1
3342
0
  case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION:
3343
0
    *value = (double)parser->m_accounting.maximumAmplificationFactor;
3344
0
    break;
3345
0
  case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION:
3346
0
    *value = (double)parser->m_alloc_tracker.maximumAmplificationFactor;
3347
0
    break;
3348
0
  case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD:
3349
0
  case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD:
3350
0
#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
0
#if XML_GE == 1
3371
0
  case XML_PROP_BILLION_LAUGHS_ACTIVATION_THRESHOLD:
3372
0
    *value = parser->m_accounting.activationThresholdBytes;
3373
0
    break;
3374
0
  case XML_PROP_ALLOC_TRACKER_ACTIVATION_THRESHOLD:
3375
0
    *value = parser->m_alloc_tracker.activationThresholdBytes;
3376
0
    break;
3377
0
  case XML_PROP_ALLOC_TRACKER_MAXIMUM_AMPLIFICATION:
3378
0
  case XML_PROP_BILLION_LAUGHS_MAXIMUM_AMPLIFICATION:
3379
0
#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
6.12k
storeRawNames(XML_Parser parser) {
3396
6.12k
  TAG *tag = parser->m_tagStack;
3397
6.12k
  while (tag) {
3398
0
    size_t bufSize;
3399
0
    size_t nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
3400
0
    size_t rawNameLen;
3401
0
    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
0
    if (tag->rawName == rawNameBuf)
3408
0
      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
0
    rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
3413
    /* Detect and prevent integer overflow. */
3414
0
    if (rawNameLen > SIZE_MAX - nameLen)
3415
0
      return XML_FALSE;
3416
0
    bufSize = nameLen + rawNameLen;
3417
0
    if (bufSize > (size_t)(tag->bufEnd - tag->buf.raw)) {
3418
0
      char *temp = REALLOC(parser, tag->buf.raw, bufSize);
3419
0
      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
0
      if (tag->name.str == tag->buf.str)
3425
0
        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
0
      if (tag->name.localPart)
3430
0
        tag->name.localPart
3431
0
            = (XML_Char *)temp + (tag->name.localPart - tag->buf.str);
3432
0
      tag->buf.raw = temp;
3433
0
      tag->bufEnd = temp + bufSize;
3434
0
      rawNameBuf = temp + nameLen;
3435
0
    }
3436
0
    memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
3437
0
    tag->rawName = rawNameBuf;
3438
0
    tag = tag->parent;
3439
0
  }
3440
6.12k
  return XML_TRUE;
3441
6.12k
}
3442
3443
static enum XML_Error
3444
contentProcessor(XML_Parser parser, const char *start, const char *end,
3445
56.2k
                 const char **endPtr) {
3446
56.2k
  enum XML_Error result = doContent(
3447
56.2k
      parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, start, end,
3448
56.2k
      endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer,
3449
56.2k
      XML_ACCOUNT_DIRECT);
3450
56.2k
  if (result == XML_ERROR_NONE) {
3451
6.12k
    if (! storeRawNames(parser))
3452
0
      return XML_ERROR_NO_MEMORY;
3453
6.12k
  }
3454
56.2k
  return result;
3455
56.2k
}
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
0
#if XML_GE == 1
3475
0
    if (! accountingDiffTolerated(parser, tok, start, next, __LINE__,
3476
0
                                  XML_ACCOUNT_DIRECT)) {
3477
0
      accountingOnAbort(parser);
3478
0
      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
3479
0
    }
3480
0
#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
56.2k
          XML_Bool haveMore, enum XML_Account account) {
3582
  /* save one level of indirection */
3583
56.2k
  DTD *const dtd = parser->m_dtd;
3584
3585
56.2k
  const char **eventPP;
3586
56.2k
  const char **eventEndPP;
3587
56.2k
  if (enc == parser->m_encoding) {
3588
56.2k
    eventPP = &parser->m_eventPtr;
3589
56.2k
    eventEndPP = &parser->m_eventEndPtr;
3590
56.2k
  } else {
3591
0
    eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3592
0
    eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
3593
0
  }
3594
56.2k
  *eventPP = s;
3595
3596
343k
  for (;;) {
3597
343k
    const char *next = s; /* XmlContentTok doesn't always set the last arg */
3598
343k
    int tok = XmlContentTok(enc, s, end, &next);
3599
343k
#if XML_GE == 1
3600
343k
    const char *accountAfter
3601
343k
        = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR))
3602
343k
              ? (haveMore ? s /* i.e. 0 bytes */ : end)
3603
343k
              : next;
3604
343k
    if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__,
3605
343k
                                  account)) {
3606
0
      accountingOnAbort(parser);
3607
0
      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
3608
0
    }
3609
343k
#endif
3610
343k
    *eventEndPP = next;
3611
343k
    switch (tok) {
3612
129
    case XML_TOK_TRAILING_CR:
3613
129
      if (haveMore) {
3614
0
        *nextPtr = s;
3615
0
        return XML_ERROR_NONE;
3616
0
      }
3617
129
      *eventEndPP = end;
3618
129
      if (parser->m_characterDataHandler) {
3619
0
        XML_Char c = 0xA;
3620
0
        beforeHandler(parser);
3621
0
        parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
3622
0
        afterHandler(parser);
3623
129
      } 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
129
      if (startTagLevel == 0)
3629
129
        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
669
    case XML_TOK_NONE:
3635
669
      if (haveMore) {
3636
0
        *nextPtr = s;
3637
0
        return XML_ERROR_NONE;
3638
0
      }
3639
669
      if (startTagLevel > 0) {
3640
0
        if (parser->m_tagLevel != startTagLevel)
3641
0
          return XML_ERROR_ASYNC_ENTITY;
3642
0
        *nextPtr = s;
3643
0
        return XML_ERROR_NONE;
3644
0
      }
3645
669
      return XML_ERROR_NO_ELEMENTS;
3646
29.9k
    case XML_TOK_INVALID:
3647
29.9k
      *eventPP = next;
3648
29.9k
      return XML_ERROR_INVALID_TOKEN;
3649
6.06k
    case XML_TOK_PARTIAL:
3650
6.06k
      if (haveMore) {
3651
0
        *nextPtr = s;
3652
0
        return XML_ERROR_NONE;
3653
0
      }
3654
6.06k
      return XML_ERROR_UNCLOSED_TOKEN;
3655
3.59k
    case XML_TOK_PARTIAL_CHAR:
3656
3.59k
      if (haveMore) {
3657
0
        *nextPtr = s;
3658
0
        return XML_ERROR_NONE;
3659
0
      }
3660
3.59k
      return XML_ERROR_PARTIAL_CHAR;
3661
884
    case XML_TOK_ENTITY_REF: {
3662
884
      const XML_Char *name;
3663
884
      ENTITY *entity;
3664
884
      XML_Char ch = (XML_Char)XmlPredefinedEntityName(
3665
884
          enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
3666
884
      if (ch) {
3667
69
#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
69
        accountingDiffTolerated(parser, tok, (char *)&ch,
3672
69
                                ((char *)&ch) + sizeof(XML_Char), __LINE__,
3673
69
                                XML_ACCOUNT_ENTITY_EXPANSION);
3674
69
#endif /* XML_GE == 1 */
3675
69
        if (parser->m_characterDataHandler) {
3676
19
          beforeHandler(parser);
3677
19
          parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
3678
19
          afterHandler(parser);
3679
50
        } else if (parser->m_defaultHandler)
3680
0
          reportDefault(parser, enc, s, next);
3681
69
        break;
3682
69
      }
3683
815
      name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
3684
815
                             next - enc->minBytesPerChar);
3685
815
      if (! name)
3686
0
        return XML_ERROR_NO_MEMORY;
3687
815
      entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
3688
815
      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
815
      if (! dtd->hasParamEntityRefs || dtd->standalone) {
3694
815
        if (! entity)
3695
815
          return XML_ERROR_UNDEFINED_ENTITY;
3696
0
        else if (! entity->is_internal)
3697
0
          return XML_ERROR_ENTITY_DECLARED_IN_PE;
3698
815
      } else if (! entity) {
3699
0
        if (parser->m_skippedEntityHandler) {
3700
0
          beforeHandler(parser);
3701
0
          parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
3702
0
          afterHandler(parser);
3703
0
        } else if (parser->m_defaultHandler)
3704
0
          reportDefault(parser, enc, s, next);
3705
0
        break;
3706
0
      }
3707
0
      if (entity->open)
3708
0
        return XML_ERROR_RECURSIVE_ENTITY_REF;
3709
0
      if (entity->notation)
3710
0
        return XML_ERROR_BINARY_ENTITY_REF;
3711
0
      if (entity->textPtr) {
3712
0
        enum XML_Error result;
3713
0
        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
0
        result = processEntity(parser, entity, XML_FALSE, ENTITY_INTERNAL);
3724
0
        if (result != XML_ERROR_NONE)
3725
0
          return result;
3726
0
      } 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
0
      break;
3744
0
    }
3745
58.7k
    case XML_TOK_START_TAG_NO_ATTS:
3746
75.7k
    case XML_TOK_START_TAG_WITH_ATTS: {
3747
75.7k
      TAG *tag;
3748
75.7k
      enum XML_Error result;
3749
75.7k
      XML_Char *toPtr;
3750
75.7k
      if (parser->m_freeTagList) {
3751
25.2k
        tag = parser->m_freeTagList;
3752
25.2k
        parser->m_freeTagList = parser->m_freeTagList->parent;
3753
50.5k
      } else {
3754
50.5k
        tag = MALLOC(parser, sizeof(TAG));
3755
50.5k
        if (! tag)
3756
0
          return XML_ERROR_NO_MEMORY;
3757
50.5k
        tag->buf.raw = MALLOC(parser, INIT_TAG_BUF_SIZE);
3758
50.5k
        if (! tag->buf.raw) {
3759
0
          FREE(parser, tag);
3760
0
          return XML_ERROR_NO_MEMORY;
3761
0
        }
3762
50.5k
        tag->bufEnd = tag->buf.raw + INIT_TAG_BUF_SIZE;
3763
50.5k
      }
3764
75.7k
      tag->bindings = NULL;
3765
75.7k
      tag->parent = parser->m_tagStack;
3766
75.7k
      parser->m_tagStack = tag;
3767
75.7k
      tag->name.localPart = NULL;
3768
75.7k
      tag->name.prefix = NULL;
3769
75.7k
      tag->rawName = s + enc->minBytesPerChar;
3770
75.7k
      tag->rawNameLength = XmlNameLength(enc, tag->rawName);
3771
75.7k
      ++parser->m_tagLevel;
3772
75.7k
      {
3773
75.7k
        const char *rawNameEnd = tag->rawName + tag->rawNameLength;
3774
75.7k
        const char *fromPtr = tag->rawName;
3775
75.7k
        toPtr = tag->buf.str;
3776
77.7k
        for (;;) {
3777
77.7k
          const enum XML_Convert_Result convert_res
3778
77.7k
              = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr,
3779
77.7k
                           (ICHAR *)tag->bufEnd - 1);
3780
77.7k
          const size_t convLen = (size_t)(toPtr - tag->buf.str);
3781
77.7k
          if ((fromPtr >= rawNameEnd)
3782
75.7k
              || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
3783
75.7k
            tag->name.strLen = convLen;
3784
75.7k
            break;
3785
75.7k
          }
3786
1.95k
          if (SIZE_MAX / 2 < (size_t)(tag->bufEnd - tag->buf.raw))
3787
0
            return XML_ERROR_NO_MEMORY;
3788
1.95k
          const size_t bufSize = (size_t)(tag->bufEnd - tag->buf.raw) * 2;
3789
1.95k
          {
3790
1.95k
            char *temp = REALLOC(parser, tag->buf.raw, bufSize);
3791
1.95k
            if (temp == NULL)
3792
0
              return XML_ERROR_NO_MEMORY;
3793
1.95k
            tag->buf.raw = temp;
3794
1.95k
            tag->bufEnd = temp + bufSize;
3795
1.95k
            toPtr = (XML_Char *)temp + convLen;
3796
1.95k
          }
3797
1.95k
        }
3798
75.7k
      }
3799
75.7k
      tag->name.str = tag->buf.str;
3800
75.7k
      *toPtr = XML_T('\0');
3801
75.7k
      result
3802
75.7k
          = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account);
3803
75.7k
      if (result)
3804
1.27k
        return result;
3805
74.5k
      if (parser->m_startElementHandler) {
3806
74.5k
        beforeHandler(parser);
3807
74.5k
        parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
3808
74.5k
                                      (const XML_Char **)parser->m_atts);
3809
74.5k
        afterHandler(parser);
3810
74.5k
      } else if (parser->m_defaultHandler)
3811
0
        reportDefault(parser, enc, s, next);
3812
74.5k
      poolClear(&parser->m_tempPool);
3813
74.5k
      break;
3814
75.7k
    }
3815
3.49k
    case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
3816
8.97k
    case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: {
3817
8.97k
      const char *rawName = s + enc->minBytesPerChar;
3818
8.97k
      enum XML_Error result;
3819
8.97k
      BINDING *bindings = NULL;
3820
8.97k
      XML_Bool noElmHandlers = XML_TRUE;
3821
8.97k
      TAG_NAME name;
3822
8.97k
      name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
3823
8.97k
                                 rawName + XmlNameLength(enc, rawName));
3824
8.97k
      if (! name.str)
3825
0
        return XML_ERROR_NO_MEMORY;
3826
8.97k
      poolFinish(&parser->m_tempPool);
3827
8.97k
      result = storeAtts(parser, enc, s, &name, &bindings,
3828
8.97k
                         XML_ACCOUNT_NONE /* token spans whole start tag */);
3829
8.97k
      if (result != XML_ERROR_NONE) {
3830
382
        freeBindings(parser, bindings);
3831
382
        return result;
3832
382
      }
3833
8.59k
      poolFinish(&parser->m_tempPool);
3834
8.59k
      if (parser->m_startElementHandler) {
3835
8.59k
        beforeHandler(parser);
3836
8.59k
        parser->m_startElementHandler(parser->m_handlerArg, name.str,
3837
8.59k
                                      (const XML_Char **)parser->m_atts);
3838
8.59k
        afterHandler(parser);
3839
8.59k
        noElmHandlers = XML_FALSE;
3840
8.59k
      }
3841
8.59k
      if (parser->m_endElementHandler) {
3842
8.59k
        if (parser->m_startElementHandler)
3843
8.59k
          *eventPP = *eventEndPP;
3844
8.59k
        beforeHandler(parser);
3845
8.59k
        parser->m_endElementHandler(parser->m_handlerArg, name.str);
3846
8.59k
        afterHandler(parser);
3847
8.59k
        noElmHandlers = XML_FALSE;
3848
8.59k
      }
3849
8.59k
      if (noElmHandlers && parser->m_defaultHandler)
3850
0
        reportDefault(parser, enc, s, next);
3851
8.59k
      poolClear(&parser->m_tempPool);
3852
8.59k
      freeBindings(parser, bindings);
3853
8.59k
    }
3854
8.59k
      if ((parser->m_tagLevel == 0)
3855
6.73k
          && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
3856
6.73k
        if (parser->m_parsingStatus.parsing == XML_SUSPENDED
3857
6.73k
            || (parser->m_parsingStatus.parsing == XML_PARSING
3858
6.73k
                && parser->m_reenter))
3859
0
          parser->m_processor = epilogProcessor;
3860
6.73k
        else
3861
6.73k
          return epilogProcessor(parser, next, end, nextPtr);
3862
6.73k
      }
3863
1.86k
      break;
3864
39.8k
    case XML_TOK_END_TAG:
3865
39.8k
      if (parser->m_tagLevel == startTagLevel)
3866
0
        return XML_ERROR_ASYNC_ENTITY;
3867
39.8k
      else {
3868
39.8k
        int len;
3869
39.8k
        const char *rawName;
3870
39.8k
        TAG *tag = parser->m_tagStack;
3871
39.8k
        rawName = s + enc->minBytesPerChar * 2;
3872
39.8k
        len = XmlNameLength(enc, rawName);
3873
39.8k
        if (len != tag->rawNameLength
3874
39.7k
            || memcmp(tag->rawName, rawName, len) != 0) {
3875
238
          *eventPP = rawName;
3876
238
          return XML_ERROR_TAG_MISMATCH;
3877
238
        }
3878
39.5k
        parser->m_tagStack = tag->parent;
3879
39.5k
        tag->parent = parser->m_freeTagList;
3880
39.5k
        parser->m_freeTagList = tag;
3881
39.5k
        --parser->m_tagLevel;
3882
39.5k
        if (parser->m_endElementHandler) {
3883
39.5k
          const XML_Char *localPart;
3884
39.5k
          const XML_Char *prefix;
3885
39.5k
          XML_Char *uri;
3886
39.5k
          localPart = tag->name.localPart;
3887
39.5k
          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
38.8k
            uri = (XML_Char *)tag->name.str + tag->name.uriLen;
3893
            /* don't need to check for space - already done in storeAtts() */
3894
263k
            while (*localPart)
3895
224k
              *uri++ = *localPart++;
3896
38.8k
            prefix = tag->name.prefix;
3897
38.8k
            if (parser->m_ns_triplets && prefix) {
3898
0
              *uri++ = parser->m_namespaceSeparator;
3899
0
              while (*prefix)
3900
0
                *uri++ = *prefix++;
3901
0
            }
3902
38.8k
            *uri = XML_T('\0');
3903
38.8k
          }
3904
39.5k
          beforeHandler(parser);
3905
39.5k
          parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
3906
39.5k
          afterHandler(parser);
3907
39.5k
        } else if (parser->m_defaultHandler)
3908
0
          reportDefault(parser, enc, s, next);
3909
57.3k
        while (tag->bindings) {
3910
17.7k
          BINDING *b = tag->bindings;
3911
17.7k
          if (parser->m_endNamespaceDeclHandler) {
3912
17.7k
            beforeHandler(parser);
3913
17.7k
            parser->m_endNamespaceDeclHandler(parser->m_handlerArg,
3914
17.7k
                                              b->prefix->name);
3915
17.7k
            afterHandler(parser);
3916
17.7k
          }
3917
17.7k
          tag->bindings = tag->bindings->nextTagBinding;
3918
17.7k
          b->nextTagBinding = parser->m_freeBindingList;
3919
17.7k
          parser->m_freeBindingList = b;
3920
17.7k
          b->prefix->binding = b->prevPrefixBinding;
3921
17.7k
        }
3922
39.5k
        if ((parser->m_tagLevel == 0)
3923
2.52k
            && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
3924
2.52k
          if (parser->m_parsingStatus.parsing == XML_SUSPENDED
3925
2.52k
              || (parser->m_parsingStatus.parsing == XML_PARSING
3926
2.52k
                  && parser->m_reenter))
3927
0
            parser->m_processor = epilogProcessor;
3928
2.52k
          else
3929
2.52k
            return epilogProcessor(parser, next, end, nextPtr);
3930
2.52k
        }
3931
39.5k
      }
3932
37.0k
      break;
3933
37.0k
    case XML_TOK_CHAR_REF: {
3934
3.10k
      int n = XmlCharRefNumber(enc, s);
3935
3.10k
      if (n < 0)
3936
2.04k
        return XML_ERROR_BAD_CHAR_REF;
3937
1.06k
      if (parser->m_characterDataHandler) {
3938
0
        XML_Char buf[XML_ENCODE_MAX];
3939
0
        beforeHandler(parser);
3940
0
        parser->m_characterDataHandler(parser->m_handlerArg, buf,
3941
0
                                       XmlEncode(n, (ICHAR *)buf));
3942
0
        afterHandler(parser);
3943
1.06k
      } else if (parser->m_defaultHandler)
3944
0
        reportDefault(parser, enc, s, next);
3945
1.06k
    } break;
3946
18
    case XML_TOK_XML_DECL:
3947
18
      return XML_ERROR_MISPLACED_XML_PI;
3948
57.3k
    case XML_TOK_DATA_NEWLINE:
3949
57.3k
      if (parser->m_characterDataHandler) {
3950
17.9k
        XML_Char c = 0xA;
3951
17.9k
        beforeHandler(parser);
3952
17.9k
        parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
3953
17.9k
        afterHandler(parser);
3954
39.3k
      } else if (parser->m_defaultHandler)
3955
0
        reportDefault(parser, enc, s, next);
3956
57.3k
      break;
3957
1.60k
    case XML_TOK_CDATA_SECT_OPEN: {
3958
1.60k
      enum XML_Error result;
3959
1.60k
      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
1.60k
      } 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
1.60k
      } else if (parser->m_defaultHandler)
3983
0
        reportDefault(parser, enc, s, next);
3984
1.60k
      result
3985
1.60k
          = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account);
3986
1.60k
      if (result != XML_ERROR_NONE)
3987
1.56k
        return result;
3988
43
      else if (! next) {
3989
0
        parser->m_processor = cdataSectionProcessor;
3990
0
        return result;
3991
0
      }
3992
1.60k
    } break;
3993
286
    case XML_TOK_TRAILING_RSQB:
3994
286
      if (haveMore) {
3995
0
        *nextPtr = s;
3996
0
        return XML_ERROR_NONE;
3997
0
      }
3998
286
      if (parser->m_characterDataHandler) {
3999
0
        if (MUST_CONVERT(enc, s)) {
4000
0
          ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
4001
0
          XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
4002
0
          beforeHandler(parser);
4003
0
          parser->m_characterDataHandler(
4004
0
              parser->m_handlerArg, parser->m_dataBuf,
4005
0
              (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
4006
0
          afterHandler(parser);
4007
0
        } else {
4008
0
          beforeHandler(parser);
4009
0
          parser->m_characterDataHandler(
4010
0
              parser->m_handlerArg, (const XML_Char *)s,
4011
0
              (int)((const XML_Char *)end - (const XML_Char *)s));
4012
0
          afterHandler(parser);
4013
0
        }
4014
286
      } 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
286
      if (startTagLevel == 0) {
4020
286
        *eventPP = end;
4021
286
        return XML_ERROR_NO_ELEMENTS;
4022
286
      }
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
114k
    case XML_TOK_DATA_CHARS: {
4030
114k
      XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
4031
114k
      if (charDataHandler) {
4032
35.0k
        if (MUST_CONVERT(enc, s)) {
4033
37
          for (;;) {
4034
37
            ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
4035
37
            const enum XML_Convert_Result convert_res = XmlConvert(
4036
37
                enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
4037
37
            *eventEndPP = s;
4038
37
            beforeHandler(parser);
4039
37
            charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
4040
37
                            (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
4041
37
            afterHandler(parser);
4042
37
            if ((convert_res == XML_CONVERT_COMPLETED)
4043
0
                || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
4044
37
              break;
4045
0
            *eventPP = s;
4046
0
          }
4047
35.0k
        } else {
4048
35.0k
          beforeHandler(parser);
4049
35.0k
          charDataHandler(parser->m_handlerArg, (const XML_Char *)s,
4050
35.0k
                          (int)((const XML_Char *)next - (const XML_Char *)s));
4051
35.0k
          afterHandler(parser);
4052
35.0k
        }
4053
79.8k
      } else if (parser->m_defaultHandler)
4054
0
        reportDefault(parser, enc, s, next);
4055
114k
    } break;
4056
44
    case XML_TOK_PI:
4057
44
      if (! reportProcessingInstruction(parser, enc, s, next))
4058
0
        return XML_ERROR_NO_MEMORY;
4059
44
      break;
4060
90
    case XML_TOK_COMMENT:
4061
90
      if (! reportComment(parser, enc, s, next))
4062
0
        return XML_ERROR_NO_MEMORY;
4063
90
      break;
4064
90
    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
343k
    }
4077
286k
    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
286k
    case XML_PARSING:
4086
286k
      if (parser->m_reenter) {
4087
0
        *nextPtr = next;
4088
0
        return XML_ERROR_NONE;
4089
0
      }
4090
286k
      EXPAT_FALLTHROUGH;
4091
286k
    default:;
4092
286k
      *eventPP = s = next;
4093
286k
    }
4094
286k
  }
4095
  /* not reached */
4096
56.2k
}
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
8.97k
freeBindings(XML_Parser parser, BINDING *bindings) {
4104
13.0k
  while (bindings) {
4105
4.04k
    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
4.04k
    if (parser->m_endNamespaceDeclHandler) {
4111
4.04k
      beforeHandler(parser);
4112
4.04k
      parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
4113
4.04k
      afterHandler(parser);
4114
4.04k
    }
4115
4116
4.04k
    bindings = bindings->nextTagBinding;
4117
4.04k
    b->nextTagBinding = parser->m_freeBindingList;
4118
4.04k
    parser->m_freeBindingList = b;
4119
4.04k
    b->prefix->binding = b->prevPrefixBinding;
4120
4.04k
  }
4121
8.97k
}
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
84.7k
          enum XML_Account account) {
4137
84.7k
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
4138
84.7k
  int attIndex = 0;
4139
84.7k
  XML_Char *uri;
4140
84.7k
  int nPrefixes = 0;
4141
84.7k
  BINDING *binding;
4142
84.7k
  const XML_Char *localPart;
4143
4144
  /* lookup the element type name */
4145
84.7k
  ELEMENT_TYPE *elementType
4146
84.7k
      = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str, 0);
4147
84.7k
  if (! elementType) {
4148
60.9k
    const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
4149
60.9k
    if (! name)
4150
0
      return XML_ERROR_NO_MEMORY;
4151
60.9k
    elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
4152
60.9k
                                         sizeof(ELEMENT_TYPE));
4153
60.9k
    if (! elementType)
4154
0
      return XML_ERROR_NO_MEMORY;
4155
60.9k
    if (! elementType->defaultAttForName.parser)
4156
60.9k
      hashTableInit(&(elementType->defaultAttForName), parser);
4157
60.9k
    if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
4158
0
      return XML_ERROR_NO_MEMORY;
4159
60.9k
  }
4160
84.7k
  const size_t nDefaultAtts = elementType->nDefaultAtts;
4161
4162
  /* Detect and prevent integer overflow. */
4163
84.7k
  if (parser->m_attsSize > (size_t)INT_MAX)
4164
0
    return XML_ERROR_NO_MEMORY;
4165
4166
  /* get the attributes from the tokenizer */
4167
84.7k
  size_t n = (size_t)XmlGetAttributes(enc, attStr, (int)parser->m_attsSize,
4168
84.7k
                                      parser->m_atts);
4169
4170
  /* Detect and prevent integer overflow */
4171
84.7k
  if (n > SIZE_MAX - nDefaultAtts) {
4172
0
    return XML_ERROR_NO_MEMORY;
4173
0
  }
4174
4175
84.7k
  if (n + nDefaultAtts > parser->m_attsSize) {
4176
1.66k
    size_t oldAttsSize = parser->m_attsSize;
4177
4178
    /* Detect and prevent integer overflow */
4179
1.66k
    if ((nDefaultAtts > SIZE_MAX - INIT_ATTS_SIZE)
4180
1.66k
        || (n > SIZE_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
4181
0
      return XML_ERROR_NO_MEMORY;
4182
0
    }
4183
4184
1.66k
    parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
4185
4186
    /* Detect and prevent integer overflow. */
4187
1.66k
    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
1.66k
    ATTRIBUTE *const temp = REALLOC(parser, parser->m_atts,
4193
1.66k
                                    parser->m_attsSize * sizeof(ATTRIBUTE));
4194
1.66k
    if (temp == NULL) {
4195
0
      parser->m_attsSize = oldAttsSize;
4196
0
      return XML_ERROR_NO_MEMORY;
4197
0
    }
4198
1.66k
    parser->m_atts = temp;
4199
1.66k
    if (n > oldAttsSize) {
4200
      /* Detect and prevent integer overflow. */
4201
1.66k
      if (n > (size_t)INT_MAX)
4202
0
        return XML_ERROR_NO_MEMORY;
4203
1.66k
      XmlGetAttributes(enc, attStr, (int)n, parser->m_atts);
4204
1.66k
    }
4205
1.66k
  }
4206
4207
  /* the attribute list for the application */
4208
84.7k
  const XML_Char **const appAtts = (const XML_Char **)parser->m_atts;
4209
179k
  for (size_t i = 0; i < n; i++) {
4210
95.1k
    ATTRIBUTE *currAtt = &parser->m_atts[i];
4211
    /* add the name and value to the attribute list */
4212
95.1k
    ATTRIBUTE_ID *attId
4213
95.1k
        = getAttributeId(parser, enc, currAtt->name,
4214
95.1k
                         currAtt->name + XmlNameLength(enc, currAtt->name));
4215
95.1k
    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
95.1k
    if ((attId->name)[-1]) {
4222
136
      if (enc == parser->m_encoding)
4223
136
        parser->m_eventPtr = parser->m_atts[i].name;
4224
136
      return XML_ERROR_DUPLICATE_ATTRIBUTE;
4225
136
    }
4226
95.0k
    (attId->name)[-1] = 1;
4227
95.0k
    appAtts[attIndex++] = attId->name;
4228
95.0k
    if (! parser->m_atts[i].normalized) {
4229
8.99k
      bool isCdata = true;
4230
4231
      /* figure out whether declared as other than CDATA */
4232
8.99k
      if (attId->maybeTokenized) {
4233
0
        NAME_AND_DEFAULT_ATTRIBUTE *const nameAndDefaultAttribute
4234
0
            = (NAME_AND_DEFAULT_ATTRIBUTE *)lookup(
4235
0
                parser, &(elementType->defaultAttForName), attId->name, 0);
4236
0
        if (nameAndDefaultAttribute != NULL) {
4237
0
          assert(nameAndDefaultAttribute->attIndex < elementType->nDefaultAtts);
4238
0
          const DEFAULT_ATTRIBUTE *const att
4239
0
              = elementType->defaultAtts + nameAndDefaultAttribute->attIndex;
4240
0
          isCdata = att->isCdata;
4241
0
        }
4242
0
      }
4243
4244
      /* normalize the attribute value */
4245
8.99k
      const enum XML_Error result = storeAttributeValue(
4246
8.99k
          parser, enc, isCdata, parser->m_atts[i].valuePtr,
4247
8.99k
          parser->m_atts[i].valueEnd, &parser->m_tempPool, account);
4248
8.99k
      if (result)
4249
227
        return result;
4250
8.76k
      appAtts[attIndex] = poolStart(&parser->m_tempPool);
4251
8.76k
      poolFinish(&parser->m_tempPool);
4252
86.0k
    } else {
4253
      /* the value did not need normalizing */
4254
86.0k
      appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc,
4255
86.0k
                                          parser->m_atts[i].valuePtr,
4256
86.0k
                                          parser->m_atts[i].valueEnd);
4257
86.0k
      if (appAtts[attIndex] == 0)
4258
0
        return XML_ERROR_NO_MEMORY;
4259
86.0k
      poolFinish(&parser->m_tempPool);
4260
86.0k
    }
4261
    /* handle prefixed attribute names */
4262
94.7k
    if (attId->prefix) {
4263
92.1k
      if (attId->xmlns) {
4264
        /* deal with namespace declarations here */
4265
27.4k
        enum XML_Error result = addBinding(parser, attId->prefix, attId,
4266
27.4k
                                           appAtts[attIndex], bindingsPtr);
4267
27.4k
        if (result)
4268
101
          return result;
4269
27.3k
        --attIndex;
4270
64.7k
      } else {
4271
        /* deal with other prefixed names later */
4272
64.7k
        attIndex++;
4273
64.7k
        nPrefixes++;
4274
64.7k
        (attId->name)[-1] = 2;
4275
64.7k
      }
4276
92.1k
    } else
4277
2.58k
      attIndex++;
4278
94.7k
  }
4279
4280
  /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
4281
84.3k
  parser->m_nSpecifiedAtts = attIndex;
4282
84.3k
  if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
4283
0
    for (int i = 0; i < attIndex; i += 2)
4284
0
      if (appAtts[i] == elementType->idAtt->name) {
4285
0
        parser->m_idAttIndex = i;
4286
0
        break;
4287
0
      }
4288
0
  } else
4289
84.3k
    parser->m_idAttIndex = -1;
4290
4291
  /* do attribute defaulting */
4292
84.3k
  for (size_t i = 0; i < nDefaultAtts; i++) {
4293
0
    const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
4294
0
    if (! (da->id->name)[-1] && da->value) {
4295
0
      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
0
      } else {
4308
0
        (da->id->name)[-1] = 1;
4309
0
        appAtts[attIndex++] = da->id->name;
4310
0
        appAtts[attIndex++] = da->value;
4311
0
      }
4312
0
    }
4313
0
  }
4314
84.3k
  appAtts[attIndex] = 0;
4315
4316
  /* expand prefixed attribute names, check for duplicates,
4317
     and clear flags that say whether attributes were specified */
4318
84.3k
  int i = 0;
4319
84.3k
  if (nPrefixes) {
4320
13.9k
    unsigned int j; /* hash table index */
4321
13.9k
    unsigned long version = parser->m_nsAttsVersion;
4322
4323
    /* Detect and prevent invalid shift */
4324
13.9k
    if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
4325
0
      return XML_ERROR_NO_MEMORY;
4326
0
    }
4327
4328
13.9k
    unsigned int nsAttsSize = 1u << parser->m_nsAttsPower;
4329
13.9k
    unsigned char oldNsAttsPower = parser->m_nsAttsPower;
4330
    /* size of hash table must be at least 2 * (# of prefixed attributes) */
4331
13.9k
    if (parser->m_nsAttsPower == 0
4332
10.1k
        || (nPrefixes >> (parser->m_nsAttsPower - 1))) {
4333
      /* hash table size must also be a power of 2 and >= 8 */
4334
12.7k
      while (nPrefixes >> parser->m_nsAttsPower++)
4335
7.25k
        ;
4336
5.47k
      if (parser->m_nsAttsPower < 3)
4337
3.34k
        parser->m_nsAttsPower = 3;
4338
4339
      /* Detect and prevent invalid shift */
4340
5.47k
      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
5.47k
      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
5.47k
      NS_ATT *const temp
4361
5.47k
          = REALLOC(parser, parser->m_nsAtts, nsAttsSize * sizeof(NS_ATT));
4362
5.47k
      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
5.47k
      parser->m_nsAtts = temp;
4368
5.47k
      version = 0; /* force re-initialization of m_nsAtts hash table */
4369
5.47k
    }
4370
    /* using a version flag saves us from initializing m_nsAtts every time */
4371
13.9k
    if (! version) { /* initialize version flags when version wraps around */
4372
5.47k
      version = INIT_ATTS_VERSION;
4373
158k
      for (j = nsAttsSize; j != 0;)
4374
153k
        parser->m_nsAtts[--j].version = version;
4375
5.47k
    }
4376
13.9k
    parser->m_nsAttsVersion = --version;
4377
4378
    /* expand prefixed names and check for duplicates */
4379
61.7k
    for (; i < attIndex; i += 2) {
4380
61.7k
      const XML_Char *s = appAtts[i];
4381
61.7k
      if (s[-1] == 2) { /* prefixed */
4382
61.5k
        struct siphash sip_state;
4383
61.5k
        struct sipkey sip_key;
4384
4385
61.5k
        copy_salt_to_sipkey(parser, &sip_key);
4386
61.5k
        sip24_init(&sip_state, &sip_key);
4387
4388
61.5k
        ((XML_Char *)s)[-1] = 0; /* clear flag */
4389
61.5k
        ATTRIBUTE_ID *const id
4390
61.5k
            = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
4391
61.5k
        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
61.5k
        const BINDING *const b = id->prefix->binding;
4409
61.5k
        if (! b)
4410
620
          return XML_ERROR_UNBOUND_PREFIX;
4411
4412
60.8k
        if (! poolAppendChars(&parser->m_tempPool, b->uri, b->uriLen))
4413
0
          return XML_ERROR_NO_MEMORY;
4414
4415
60.8k
        sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
4416
4417
284k
        while (*s++ != XML_T(ASCII_COLON))
4418
223k
          ;
4419
4420
60.8k
        sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
4421
4422
60.8k
        {
4423
60.8k
          const size_t len = xcslen(s) + /*null terminator*/ 1;
4424
60.8k
          if (! poolAppendChars(&parser->m_tempPool, s, len))
4425
0
            return XML_ERROR_NO_MEMORY;
4426
60.8k
        }
4427
4428
60.8k
        const unsigned long uriHash = (unsigned long)sip24_final(&sip_state);
4429
4430
60.8k
        { /* Check hash table for duplicate of expanded name (uriName).
4431
             Derived from code in lookup(parser, HASH_TABLE *table, ...).
4432
          */
4433
60.8k
          unsigned char step = 0;
4434
60.8k
          unsigned long mask = nsAttsSize - 1;
4435
60.8k
          j = uriHash & mask; /* index into hash table */
4436
71.7k
          while (parser->m_nsAtts[j].version == version) {
4437
            /* for speed we compare stored hash values first */
4438
10.8k
            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
10.8k
            if (! step)
4448
8.12k
              step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower);
4449
10.8k
            j < step ? (j += nsAttsSize - step) : (j -= step);
4450
10.8k
          }
4451
60.8k
        }
4452
4453
60.8k
        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
60.8k
        s = poolStart(&parser->m_tempPool);
4463
60.8k
        poolFinish(&parser->m_tempPool);
4464
60.8k
        appAtts[i] = s;
4465
4466
        /* fill empty slot with new version, uriName and hash value */
4467
60.8k
        parser->m_nsAtts[j].version = version;
4468
60.8k
        parser->m_nsAtts[j].hash = uriHash;
4469
60.8k
        parser->m_nsAtts[j].uriName = s;
4470
4471
60.8k
        if (! --nPrefixes) {
4472
13.2k
          i += 2;
4473
13.2k
          break;
4474
13.2k
        }
4475
60.8k
      } else                     /* not prefixed */
4476
274
        ((XML_Char *)s)[-1] = 0; /* clear flag */
4477
61.7k
    }
4478
13.9k
  }
4479
  /* clear flags for the remaining attributes */
4480
85.9k
  for (; i < attIndex; i += 2)
4481
2.24k
    ((XML_Char *)(appAtts[i]))[-1] = 0;
4482
110k
  for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
4483
26.3k
    binding->attId->name[-1] = 0;
4484
4485
83.6k
  if (! parser->m_ns)
4486
9
    return XML_ERROR_NONE;
4487
4488
  /* expand the element type name */
4489
83.6k
  if (elementType->prefix) {
4490
45.0k
    binding = elementType->prefix->binding;
4491
45.0k
    if (! binding)
4492
569
      return XML_ERROR_UNBOUND_PREFIX;
4493
44.4k
    localPart = tagNamePtr->str;
4494
179k
    while (*localPart++ != XML_T(ASCII_COLON))
4495
134k
      ;
4496
44.4k
  } else if (dtd->defaultPrefix.binding) {
4497
151
    binding = dtd->defaultPrefix.binding;
4498
151
    localPart = tagNamePtr->str;
4499
151
  } else
4500
38.4k
    return XML_ERROR_NONE;
4501
44.6k
  size_t prefixLen = 0;
4502
44.6k
  if (parser->m_ns_triplets && binding->prefix->name)
4503
0
    prefixLen = xcslen(binding->prefix->name) + /*null terminator*/ 1;
4504
44.6k
  tagNamePtr->localPart = localPart;
4505
44.6k
  tagNamePtr->uriLen = binding->uriLen;
4506
44.6k
  tagNamePtr->prefix = binding->prefix->name;
4507
44.6k
  tagNamePtr->prefixLen = prefixLen;
4508
4509
44.6k
  const size_t localPartLen = xcslen(localPart) + /*null terminator*/ 1;
4510
4511
  /* Detect and prevent integer overflow */
4512
44.6k
  if (binding->uriLen > SIZE_MAX - prefixLen
4513
44.6k
      || localPartLen > SIZE_MAX - (binding->uriLen + prefixLen)) {
4514
0
    return XML_ERROR_NO_MEMORY;
4515
0
  }
4516
4517
44.6k
  const size_t totalLen = localPartLen + binding->uriLen + prefixLen;
4518
44.6k
  if (totalLen > binding->uriAlloc) {
4519
    /* Detect and prevent integer overflow */
4520
278
    if (totalLen > SIZE_MAX - EXPAND_SPARE
4521
278
        || totalLen + EXPAND_SPARE > SIZE_MAX / sizeof(XML_Char)) {
4522
0
      return XML_ERROR_NO_MEMORY;
4523
0
    }
4524
4525
278
    uri = MALLOC(parser, (totalLen + EXPAND_SPARE) * sizeof(XML_Char));
4526
278
    if (! uri)
4527
0
      return XML_ERROR_NO_MEMORY;
4528
278
    binding->uriAlloc = totalLen + EXPAND_SPARE;
4529
278
    memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
4530
576
    for (TAG *p = parser->m_tagStack; p; p = p->parent)
4531
298
      if (p->name.str == binding->uri)
4532
92
        p->name.str = uri;
4533
278
    FREE(parser, binding->uri);
4534
278
    binding->uri = uri;
4535
278
  }
4536
  /* if m_namespaceSeparator != '\0' then uri includes it already */
4537
44.6k
  uri = binding->uri + binding->uriLen;
4538
  /* Detect and prevent integer overflow */
4539
44.6k
  if (localPartLen > SIZE_MAX / sizeof(XML_Char)) {
4540
0
    return XML_ERROR_NO_MEMORY;
4541
0
  }
4542
44.6k
  memcpy(uri, localPart, localPartLen * sizeof(XML_Char));
4543
  /* we always have a namespace separator between localPart and prefix */
4544
44.6k
  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
44.6k
  tagNamePtr->str = binding->uri;
4550
44.6k
  return XML_ERROR_NONE;
4551
44.6k
}
4552
4553
static XML_Bool
4554
550
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
550
  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
550
  case '@':
4644
4645
  // From rule "sub-delims"
4646
550
  case '!':
4647
550
  case '$':
4648
550
  case '&':
4649
550
  case '\'':
4650
550
  case '(':
4651
550
  case ')':
4652
550
  case '*':
4653
550
  case '+':
4654
550
  case ',':
4655
550
  case ';':
4656
550
  case '=':
4657
550
    return XML_TRUE;
4658
4659
0
  default:
4660
0
    return XML_FALSE;
4661
550
  }
4662
550
}
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
134k
           const XML_Char *uri, BINDING **bindingsPtr) {
4670
  // "http://www.w3.org/XML/1998/namespace"
4671
134k
  static const XML_Char xmlNamespace[]
4672
134k
      = {ASCII_h,      ASCII_t,     ASCII_t,     ASCII_p,      ASCII_COLON,
4673
134k
         ASCII_SLASH,  ASCII_SLASH, ASCII_w,     ASCII_w,      ASCII_w,
4674
134k
         ASCII_PERIOD, ASCII_w,     ASCII_3,     ASCII_PERIOD, ASCII_o,
4675
134k
         ASCII_r,      ASCII_g,     ASCII_SLASH, ASCII_X,      ASCII_M,
4676
134k
         ASCII_L,      ASCII_SLASH, ASCII_1,     ASCII_9,      ASCII_9,
4677
134k
         ASCII_8,      ASCII_SLASH, ASCII_n,     ASCII_a,      ASCII_m,
4678
134k
         ASCII_e,      ASCII_s,     ASCII_p,     ASCII_a,      ASCII_c,
4679
134k
         ASCII_e,      '\0'};
4680
134k
  static const size_t xmlLen = sizeof(xmlNamespace) / sizeof(XML_Char) - 1;
4681
  // "http://www.w3.org/2000/xmlns/"
4682
134k
  static const XML_Char xmlnsNamespace[]
4683
134k
      = {ASCII_h,     ASCII_t,      ASCII_t, ASCII_p, ASCII_COLON,  ASCII_SLASH,
4684
134k
         ASCII_SLASH, ASCII_w,      ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w,
4685
134k
         ASCII_3,     ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,      ASCII_SLASH,
4686
134k
         ASCII_2,     ASCII_0,      ASCII_0, ASCII_0, ASCII_SLASH,  ASCII_x,
4687
134k
         ASCII_m,     ASCII_l,      ASCII_n, ASCII_s, ASCII_SLASH,  '\0'};
4688
134k
  static const size_t xmlnsLen = sizeof(xmlnsNamespace) / sizeof(XML_Char) - 1;
4689
4690
134k
  XML_Bool mustBeXML = XML_FALSE;
4691
134k
  XML_Bool isXML = XML_TRUE;
4692
134k
  XML_Bool isXMLNS = XML_TRUE;
4693
4694
134k
  BINDING *b;
4695
134k
  size_t len;
4696
4697
  /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
4698
134k
  if (*uri == XML_T('\0') && prefix->name)
4699
34
    return XML_ERROR_UNDECLARING_PREFIX;
4700
4701
134k
  if (prefix->name && prefix->name[0] == XML_T(ASCII_x)
4702
117k
      && prefix->name[1] == XML_T(ASCII_m)
4703
111k
      && prefix->name[2] == XML_T(ASCII_l)) {
4704
    /* Not allowed to bind xmlns */
4705
107k
    if (prefix->name[3] == XML_T(ASCII_n) && prefix->name[4] == XML_T(ASCII_s)
4706
59
        && prefix->name[5] == XML_T('\0'))
4707
21
      return XML_ERROR_RESERVED_PREFIX_XMLNS;
4708
4709
107k
    if (prefix->name[3] == XML_T('\0'))
4710
107k
      mustBeXML = XML_TRUE;
4711
107k
  }
4712
4713
5.56M
  for (len = 0; uri[len]; len++) {
4714
    /* Detect and prevent integer overflow */
4715
5.43M
    if (len == SIZE_MAX) {
4716
0
      return XML_ERROR_NO_MEMORY;
4717
0
    }
4718
5.43M
    if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
4719
27.3k
      isXML = XML_FALSE;
4720
4721
5.43M
    if (! mustBeXML && isXMLNS
4722
196k
        && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
4723
27.2k
      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
5.43M
    if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)
4744
550
        && ! is_rfc3986_uri_char(uri[len])) {
4745
0
      return XML_ERROR_SYNTAX;
4746
0
    }
4747
5.43M
  }
4748
134k
  isXML = isXML && len == xmlLen;
4749
134k
  isXMLNS = isXMLNS && len == xmlnsLen;
4750
4751
134k
  if (mustBeXML != isXML)
4752
46
    return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
4753
46
                     : XML_ERROR_RESERVED_NAMESPACE_URI;
4754
4755
134k
  if (isXMLNS)
4756
0
    return XML_ERROR_RESERVED_NAMESPACE_URI;
4757
4758
134k
  if (parser->m_namespaceSeparator) {
4759
    /* Detect and prevent integer overflow */
4760
134k
    if (len == SIZE_MAX) {
4761
0
      return XML_ERROR_NO_MEMORY;
4762
0
    }
4763
134k
    len++;
4764
134k
  }
4765
134k
  if (parser->m_freeBindingList) {
4766
1.37k
    b = parser->m_freeBindingList;
4767
1.37k
    if (len > b->uriAlloc) {
4768
      /* Detect and prevent integer overflow */
4769
45
      if (len > SIZE_MAX - EXPAND_SPARE
4770
45
          || len + EXPAND_SPARE > SIZE_MAX / sizeof(XML_Char)) {
4771
0
        return XML_ERROR_NO_MEMORY;
4772
0
      }
4773
4774
45
      XML_Char *temp
4775
45
          = REALLOC(parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
4776
45
      if (temp == NULL)
4777
0
        return XML_ERROR_NO_MEMORY;
4778
45
      b->uri = temp;
4779
45
      b->uriAlloc = len + EXPAND_SPARE;
4780
45
    }
4781
1.37k
    parser->m_freeBindingList = b->nextTagBinding;
4782
133k
  } else {
4783
133k
    b = MALLOC(parser, sizeof(BINDING));
4784
133k
    if (! b)
4785
0
      return XML_ERROR_NO_MEMORY;
4786
4787
    /* Detect and prevent integer overflow */
4788
133k
    if (len > SIZE_MAX - EXPAND_SPARE
4789
133k
        || len + EXPAND_SPARE > SIZE_MAX / sizeof(XML_Char)) {
4790
0
      FREE(parser, b);
4791
0
      return XML_ERROR_NO_MEMORY;
4792
0
    }
4793
4794
133k
    b->uri = MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
4795
133k
    if (! b->uri) {
4796
0
      FREE(parser, b);
4797
0
      return XML_ERROR_NO_MEMORY;
4798
0
    }
4799
133k
    b->uriAlloc = len + EXPAND_SPARE;
4800
133k
  }
4801
134k
  b->uriLen = len;
4802
134k
  memcpy(b->uri, uri, len * sizeof(XML_Char));
4803
134k
  if (parser->m_namespaceSeparator)
4804
134k
    b->uri[len - 1] = parser->m_namespaceSeparator;
4805
134k
  b->prefix = prefix;
4806
134k
  b->attId = attId;
4807
134k
  b->prevPrefixBinding = prefix->binding;
4808
  /* NULL binding when default namespace undeclared */
4809
134k
  if (*uri == XML_T('\0') && prefix == &parser->m_dtd->defaultPrefix)
4810
38
    prefix->binding = NULL;
4811
134k
  else
4812
134k
    prefix->binding = b;
4813
134k
  b->nextTagBinding = *bindingsPtr;
4814
134k
  *bindingsPtr = b;
4815
  /* if attId == NULL then we are not starting a namespace scope */
4816
134k
  if (attId && parser->m_startNamespaceDeclHandler) {
4817
27.3k
    beforeHandler(parser);
4818
27.3k
    parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name,
4819
27.3k
                                        prefix->binding ? uri : 0);
4820
27.3k
    afterHandler(parser);
4821
27.3k
  }
4822
134k
  return XML_ERROR_NONE;
4823
134k
}
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
0
                      const char **endPtr) {
4831
0
  enum XML_Error result = doCdataSection(
4832
0
      parser, parser->m_encoding, &start, end, endPtr,
4833
0
      (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
4834
0
  if (result != XML_ERROR_NONE)
4835
0
    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
1.60k
               enum XML_Account account) {
4855
1.60k
  const char *s = *startPtr;
4856
1.60k
  const char **eventPP;
4857
1.60k
  const char **eventEndPP;
4858
1.60k
  if (enc == parser->m_encoding) {
4859
1.60k
    eventPP = &parser->m_eventPtr;
4860
1.60k
    *eventPP = s;
4861
1.60k
    eventEndPP = &parser->m_eventEndPtr;
4862
1.60k
  } else {
4863
0
    eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4864
0
    eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
4865
0
  }
4866
1.60k
  *eventPP = s;
4867
1.60k
  *startPtr = NULL;
4868
4869
6.83k
  for (;;) {
4870
6.83k
    const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
4871
6.83k
    int tok = XmlCdataSectionTok(enc, s, end, &next);
4872
6.83k
#if XML_GE == 1
4873
6.83k
    if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
4874
0
      accountingOnAbort(parser);
4875
0
      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
4876
0
    }
4877
#else
4878
    UNUSED_P(account);
4879
#endif
4880
6.83k
    *eventEndPP = next;
4881
6.83k
    switch (tok) {
4882
43
    case XML_TOK_CDATA_SECT_CLOSE:
4883
43
      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
43
      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
43
      } else if (parser->m_defaultHandler)
4897
0
        reportDefault(parser, enc, s, next);
4898
43
      *startPtr = next;
4899
43
      *nextPtr = next;
4900
43
      if (parser->m_parsingStatus.parsing == XML_FINISHED)
4901
0
        return XML_ERROR_ABORTED;
4902
43
      else
4903
43
        return XML_ERROR_NONE;
4904
1.56k
    case XML_TOK_DATA_NEWLINE:
4905
1.56k
      if (parser->m_characterDataHandler) {
4906
0
        XML_Char c = 0xA;
4907
0
        beforeHandler(parser);
4908
0
        parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
4909
0
        afterHandler(parser);
4910
1.56k
      } else if (parser->m_defaultHandler)
4911
0
        reportDefault(parser, enc, s, next);
4912
1.56k
      break;
4913
3.67k
    case XML_TOK_DATA_CHARS: {
4914
3.67k
      XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
4915
3.67k
      if (charDataHandler) {
4916
0
        if (MUST_CONVERT(enc, s)) {
4917
0
          for (;;) {
4918
0
            ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
4919
0
            const enum XML_Convert_Result convert_res = XmlConvert(
4920
0
                enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
4921
0
            *eventEndPP = next;
4922
0
            beforeHandler(parser);
4923
0
            charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
4924
0
                            (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
4925
0
            afterHandler(parser);
4926
0
            if ((convert_res == XML_CONVERT_COMPLETED)
4927
0
                || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
4928
0
              break;
4929
0
            *eventPP = s;
4930
0
          }
4931
0
        } else {
4932
0
          beforeHandler(parser);
4933
0
          charDataHandler(parser->m_handlerArg, (const XML_Char *)s,
4934
0
                          (int)((const XML_Char *)next - (const XML_Char *)s));
4935
0
          afterHandler(parser);
4936
0
        }
4937
3.67k
      } else if (parser->m_defaultHandler)
4938
0
        reportDefault(parser, enc, s, next);
4939
3.67k
    } break;
4940
908
    case XML_TOK_INVALID:
4941
908
      *eventPP = next;
4942
908
      return XML_ERROR_INVALID_TOKEN;
4943
278
    case XML_TOK_PARTIAL_CHAR:
4944
278
      if (haveMore) {
4945
0
        *nextPtr = s;
4946
0
        return XML_ERROR_NONE;
4947
0
      }
4948
278
      return XML_ERROR_PARTIAL_CHAR;
4949
151
    case XML_TOK_PARTIAL:
4950
375
    case XML_TOK_NONE:
4951
375
      if (haveMore) {
4952
0
        *nextPtr = s;
4953
0
        return XML_ERROR_NONE;
4954
0
      }
4955
375
      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
6.83k
    }
4968
4969
5.23k
    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
5.23k
    case XML_PARSING:
4978
5.23k
      if (parser->m_reenter) {
4979
0
        return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
4980
0
      }
4981
5.23k
      EXPAT_FALLTHROUGH;
4982
5.23k
    default:;
4983
5.23k
      *eventPP = s = next;
4984
5.23k
    }
4985
5.23k
  }
4986
  /* not reached */
4987
1.60k
}
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
0
                       const char **endPtr) {
4997
0
  enum XML_Error result
4998
0
      = doIgnoreSection(parser, parser->m_encoding, &start, end, endPtr,
4999
0
                        (XML_Bool)! parser->m_parsingStatus.finalBuffer);
5000
0
  if (result != XML_ERROR_NONE)
5001
0
    return result;
5002
0
  if (start) {
5003
0
    parser->m_processor = prologProcessor;
5004
0
    return prologProcessor(parser, start, end, endPtr);
5005
0
  }
5006
0
  return result;
5007
0
}
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
0
                const char *end, const char **nextPtr, XML_Bool haveMore) {
5015
0
  const char *next = *startPtr; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
5016
0
  int tok;
5017
0
  const char *s = *startPtr;
5018
0
  const char **eventPP;
5019
0
  const char **eventEndPP;
5020
0
  if (enc == parser->m_encoding) {
5021
0
    eventPP = &parser->m_eventPtr;
5022
0
    *eventPP = s;
5023
0
    eventEndPP = &parser->m_eventEndPtr;
5024
0
  } 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
0
    eventPP = &(parser->m_openInternalEntities->internalEventPtr);
5037
0
    eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
5038
    /* LCOV_EXCL_STOP */
5039
0
  }
5040
0
  *eventPP = s;
5041
0
  *startPtr = NULL;
5042
0
  tok = XmlIgnoreSectionTok(enc, s, end, &next);
5043
0
#  if XML_GE == 1
5044
0
  if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
5045
0
                                XML_ACCOUNT_DIRECT)) {
5046
0
    accountingOnAbort(parser);
5047
0
    return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
5048
0
  }
5049
0
#  endif
5050
0
  *eventEndPP = next;
5051
0
  switch (tok) {
5052
0
  case XML_TOK_IGNORE_SECT:
5053
0
    if (parser->m_defaultHandler)
5054
0
      reportDefault(parser, enc, s, next);
5055
0
    *startPtr = next;
5056
0
    *nextPtr = next;
5057
0
    if (parser->m_parsingStatus.parsing == XML_FINISHED)
5058
0
      return XML_ERROR_ABORTED;
5059
0
    else
5060
0
      return XML_ERROR_NONE;
5061
0
  case XML_TOK_INVALID:
5062
0
    *eventPP = next;
5063
0
    return XML_ERROR_INVALID_TOKEN;
5064
0
  case XML_TOK_PARTIAL_CHAR:
5065
0
    if (haveMore) {
5066
0
      *nextPtr = s;
5067
0
      return XML_ERROR_NONE;
5068
0
    }
5069
0
    return XML_ERROR_PARTIAL_CHAR;
5070
0
  case XML_TOK_PARTIAL:
5071
0
  case XML_TOK_NONE:
5072
0
    if (haveMore) {
5073
0
      *nextPtr = s;
5074
0
      return XML_ERROR_NONE;
5075
0
    }
5076
0
    return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
5077
0
  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
0
    *eventPP = next;
5086
0
    return XML_ERROR_UNEXPECTED_STATE;
5087
    /* LCOV_EXCL_STOP */
5088
0
  }
5089
  /* not reached */
5090
0
}
5091
5092
#endif /* XML_DTD */
5093
5094
static enum XML_Error
5095
107k
initializeEncoding(XML_Parser parser) {
5096
107k
  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
107k
  s = parser->m_protocolEncodingName;
5117
107k
#endif
5118
107k
  if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(
5119
107k
          &parser->m_initEncoding, &parser->m_encoding, s))
5120
107k
    return XML_ERROR_NONE;
5121
0
  return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
5122
107k
}
5123
5124
static enum XML_Error
5125
processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
5126
1.15k
               const char *next) {
5127
1.15k
  const char *encodingName = NULL;
5128
1.15k
  const XML_Char *storedEncName = NULL;
5129
1.15k
  const ENCODING *newEncoding = NULL;
5130
1.15k
  const char *version = NULL;
5131
1.15k
  const char *versionend = NULL;
5132
1.15k
  const XML_Char *storedversion = NULL;
5133
1.15k
  int standalone = -1;
5134
5135
1.15k
#if XML_GE == 1
5136
1.15k
  if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__,
5137
1.15k
                                XML_ACCOUNT_DIRECT)) {
5138
0
    accountingOnAbort(parser);
5139
0
    return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
5140
0
  }
5141
1.15k
#endif
5142
5143
1.15k
  if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
5144
1.15k
          isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
5145
1.15k
          &version, &versionend, &encodingName, &newEncoding, &standalone)) {
5146
1.15k
    if (isGeneralTextEntity)
5147
0
      return XML_ERROR_TEXT_DECL;
5148
1.15k
    else
5149
1.15k
      return XML_ERROR_XML_DECL;
5150
1.15k
  }
5151
0
  if (! isGeneralTextEntity && standalone == 1) {
5152
0
    parser->m_dtd->standalone = XML_TRUE;
5153
0
#ifdef XML_DTD
5154
0
    if (parser->m_paramEntityParsing
5155
0
        == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
5156
0
      parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
5157
0
#endif /* XML_DTD */
5158
0
  }
5159
0
  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
0
  } else if (parser->m_defaultHandler)
5180
0
    reportDefault(parser, parser->m_encoding, s, next);
5181
0
  if (parser->m_protocolEncodingName == NULL) {
5182
0
    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
0
      if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
5189
0
          || (newEncoding->minBytesPerChar == 2
5190
0
              && newEncoding != parser->m_encoding)) {
5191
0
        parser->m_eventPtr = encodingName;
5192
0
        return XML_ERROR_INCORRECT_ENCODING;
5193
0
      }
5194
0
      parser->m_encoding = newEncoding;
5195
0
    } else if (encodingName) {
5196
0
      enum XML_Error result;
5197
0
      if (! storedEncName) {
5198
0
        storedEncName = poolStoreString(
5199
0
            &parser->m_temp2Pool, parser->m_encoding, encodingName,
5200
0
            encodingName + XmlNameLength(parser->m_encoding, encodingName));
5201
0
        if (! storedEncName)
5202
0
          return XML_ERROR_NO_MEMORY;
5203
0
      }
5204
0
      result = handleUnknownEncoding(parser, storedEncName);
5205
0
      poolClear(&parser->m_temp2Pool);
5206
0
      if (result == XML_ERROR_UNKNOWN_ENCODING)
5207
0
        parser->m_eventPtr = encodingName;
5208
0
      return result;
5209
0
    }
5210
0
  }
5211
5212
0
  if (storedEncName || storedversion)
5213
0
    poolClear(&parser->m_temp2Pool);
5214
5215
0
  return XML_ERROR_NONE;
5216
0
}
5217
5218
static enum XML_Error
5219
0
handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) {
5220
0
  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
0
  return XML_ERROR_UNKNOWN_ENCODING;
5262
0
}
5263
5264
static enum XML_Error
5265
prologInitProcessor(XML_Parser parser, const char *s, const char *end,
5266
107k
                    const char **nextPtr) {
5267
107k
  enum XML_Error result = initializeEncoding(parser);
5268
107k
  if (result != XML_ERROR_NONE)
5269
0
    return result;
5270
107k
  parser->m_processor = prologProcessor;
5271
107k
  return prologProcessor(parser, s, end, nextPtr);
5272
107k
}
5273
5274
#ifdef XML_DTD
5275
5276
static enum XML_Error
5277
externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
5278
0
                            const char **nextPtr) {
5279
0
  enum XML_Error result = initializeEncoding(parser);
5280
0
  if (result != XML_ERROR_NONE)
5281
0
    return result;
5282
5283
  /* we know now that XML_Parse(Buffer) has been called,
5284
     so we consider the external parameter entity read */
5285
0
  parser->m_dtd->paramEntityRead = true;
5286
5287
0
  if (parser->m_prologState.inEntityValue) {
5288
0
    parser->m_processor = entityValueInitProcessor;
5289
0
    return entityValueInitProcessor(parser, s, end, nextPtr);
5290
0
  } else {
5291
0
    parser->m_processor = externalParEntProcessor;
5292
0
    return externalParEntProcessor(parser, s, end, nextPtr);
5293
0
  }
5294
0
}
5295
5296
static enum XML_Error
5297
entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
5298
0
                         const char **nextPtr) {
5299
0
  int tok;
5300
0
  const char *start = s;
5301
0
  const char *next = start;
5302
0
  parser->m_eventPtr = start;
5303
5304
0
  for (;;) {
5305
0
    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
0
    parser->m_eventEndPtr = next;
5311
0
    if (tok <= 0) {
5312
0
      if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
5313
0
        *nextPtr = s;
5314
0
        return XML_ERROR_NONE;
5315
0
      }
5316
0
      switch (tok) {
5317
0
      case XML_TOK_INVALID:
5318
0
        return XML_ERROR_INVALID_TOKEN;
5319
0
      case XML_TOK_PARTIAL:
5320
0
        return XML_ERROR_UNCLOSED_TOKEN;
5321
0
      case XML_TOK_PARTIAL_CHAR:
5322
0
        return XML_ERROR_PARTIAL_CHAR;
5323
0
      case XML_TOK_NONE: /* start == end */
5324
0
      default:
5325
0
        break;
5326
0
      }
5327
      /* found end of entity value - can store it now */
5328
0
      return storeEntityValue(parser, parser->m_encoding, s, end,
5329
0
                              XML_ACCOUNT_DIRECT, NULL);
5330
0
    } else if (tok == XML_TOK_XML_DECL) {
5331
0
      enum XML_Error result;
5332
0
      result = processXmlDecl(parser, 0, start, next);
5333
0
      if (result != XML_ERROR_NONE)
5334
0
        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
0
      if (parser->m_parsingStatus.parsing == XML_FINISHED)
5341
0
        return XML_ERROR_ABORTED;
5342
0
      *nextPtr = next;
5343
      /* stop scanning for text declaration - we found one */
5344
0
      parser->m_processor = entityValueProcessor;
5345
0
      return entityValueProcessor(parser, next, end, nextPtr);
5346
0
    }
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
0
    else if (tok == XML_TOK_BOM) {
5356
0
#  if XML_GE == 1
5357
0
      if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
5358
0
                                    XML_ACCOUNT_DIRECT)) {
5359
0
        accountingOnAbort(parser);
5360
0
        return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
5361
0
      }
5362
0
#  endif
5363
5364
0
      *nextPtr = next;
5365
0
      s = next;
5366
0
    }
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
0
    else if (tok == XML_TOK_INSTANCE_START) {
5372
0
      *nextPtr = next;
5373
0
      return XML_ERROR_SYNTAX;
5374
0
    }
5375
0
    start = next;
5376
0
    parser->m_eventPtr = start;
5377
0
  }
5378
0
}
5379
5380
static enum XML_Error
5381
externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
5382
0
                        const char **nextPtr) {
5383
0
  const char *next = s;
5384
0
  int tok;
5385
5386
0
  tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5387
0
  if (tok <= 0) {
5388
0
    if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
5389
0
      *nextPtr = s;
5390
0
      return XML_ERROR_NONE;
5391
0
    }
5392
0
    switch (tok) {
5393
0
    case XML_TOK_INVALID:
5394
0
      return XML_ERROR_INVALID_TOKEN;
5395
0
    case XML_TOK_PARTIAL:
5396
0
      return XML_ERROR_UNCLOSED_TOKEN;
5397
0
    case XML_TOK_PARTIAL_CHAR:
5398
0
      return XML_ERROR_PARTIAL_CHAR;
5399
0
    case XML_TOK_NONE: /* start == end */
5400
0
    default:
5401
0
      break;
5402
0
    }
5403
0
  }
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
0
  else if (tok == XML_TOK_BOM) {
5410
0
    if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
5411
0
                                  XML_ACCOUNT_DIRECT)) {
5412
0
      accountingOnAbort(parser);
5413
0
      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
5414
0
    }
5415
5416
0
    s = next;
5417
0
    tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5418
0
  }
5419
5420
0
  parser->m_processor = prologProcessor;
5421
0
  return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
5422
0
                  (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
5423
0
                  XML_ACCOUNT_DIRECT);
5424
0
}
5425
5426
static enum XML_Error
5427
entityValueProcessor(XML_Parser parser, const char *s, const char *end,
5428
0
                     const char **nextPtr) {
5429
0
  const char *start = s;
5430
0
  const char *next = s;
5431
0
  const ENCODING *enc = parser->m_encoding;
5432
0
  int tok;
5433
5434
0
  for (;;) {
5435
0
    tok = XmlPrologTok(enc, start, end, &next);
5436
    /* Note: These bytes are accounted later in:
5437
             - storeEntityValue
5438
    */
5439
0
    if (tok <= 0) {
5440
0
      if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
5441
0
        *nextPtr = s;
5442
0
        return XML_ERROR_NONE;
5443
0
      }
5444
0
      switch (tok) {
5445
0
      case XML_TOK_INVALID:
5446
0
        return XML_ERROR_INVALID_TOKEN;
5447
0
      case XML_TOK_PARTIAL:
5448
0
        return XML_ERROR_UNCLOSED_TOKEN;
5449
0
      case XML_TOK_PARTIAL_CHAR:
5450
0
        return XML_ERROR_PARTIAL_CHAR;
5451
0
      case XML_TOK_NONE: /* start == end */
5452
0
      default:
5453
0
        break;
5454
0
      }
5455
      /* found end of entity value - can store it now */
5456
0
      return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT, NULL);
5457
0
    }
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
0
    else if (tok == XML_TOK_INSTANCE_START) {
5463
0
      *nextPtr = next;
5464
0
      return XML_ERROR_SYNTAX;
5465
0
    }
5466
5467
0
    start = next;
5468
0
  }
5469
0
}
5470
5471
#endif /* XML_DTD */
5472
5473
static enum XML_Error
5474
prologProcessor(XML_Parser parser, const char *s, const char *end,
5475
107k
                const char **nextPtr) {
5476
107k
  const char *next = s;
5477
107k
  int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5478
107k
  return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
5479
107k
                  (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
5480
107k
                  XML_ACCOUNT_DIRECT);
5481
107k
}
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
107k
         XML_Bool allowClosingDoctype, enum XML_Account account) {
5487
107k
#ifdef XML_DTD
5488
107k
  static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
5489
107k
#endif /* XML_DTD */
5490
107k
  static const XML_Char atypeCDATA[]
5491
107k
      = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
5492
107k
  static const XML_Char atypeID[] = {ASCII_I, ASCII_D, '\0'};
5493
107k
  static const XML_Char atypeIDREF[]
5494
107k
      = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'};
5495
107k
  static const XML_Char atypeIDREFS[]
5496
107k
      = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0'};
5497
107k
  static const XML_Char atypeENTITY[]
5498
107k
      = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0'};
5499
107k
  static const XML_Char atypeENTITIES[]
5500
107k
      = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T,
5501
107k
         ASCII_I, ASCII_E, ASCII_S, '\0'};
5502
107k
  static const XML_Char atypeNMTOKEN[]
5503
107k
      = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0'};
5504
107k
  static const XML_Char atypeNMTOKENS[]
5505
107k
      = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K,
5506
107k
         ASCII_E, ASCII_N, ASCII_S, '\0'};
5507
107k
  static const XML_Char notationPrefix[]
5508
107k
      = {ASCII_N, ASCII_O, ASCII_T, ASCII_A,      ASCII_T,
5509
107k
         ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0'};
5510
107k
  static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
5511
107k
  static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
5512
5513
#ifndef XML_DTD
5514
  UNUSED_P(account);
5515
#endif
5516
5517
  /* save one level of indirection */
5518
107k
  DTD *const dtd = parser->m_dtd;
5519
5520
107k
  const char **eventPP;
5521
107k
  const char **eventEndPP;
5522
107k
  enum XML_Content_Quant quant;
5523
5524
107k
  if (enc == parser->m_encoding) {
5525
107k
    eventPP = &parser->m_eventPtr;
5526
107k
    eventEndPP = &parser->m_eventEndPtr;
5527
107k
  } else {
5528
0
    eventPP = &(parser->m_openInternalEntities->internalEventPtr);
5529
0
    eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
5530
0
  }
5531
5532
147k
  for (;;) {
5533
147k
    int role;
5534
147k
    XML_Bool handleDefault = XML_TRUE;
5535
147k
    *eventPP = s;
5536
147k
    *eventEndPP = next;
5537
147k
    if (tok <= 0) {
5538
39.5k
      if (haveMore && tok != XML_TOK_INVALID) {
5539
0
        *nextPtr = s;
5540
0
        return XML_ERROR_NONE;
5541
0
      }
5542
39.5k
      switch (tok) {
5543
31.9k
      case XML_TOK_INVALID:
5544
31.9k
        *eventPP = next;
5545
31.9k
        return XML_ERROR_INVALID_TOKEN;
5546
3.73k
      case XML_TOK_PARTIAL:
5547
3.73k
        return XML_ERROR_UNCLOSED_TOKEN;
5548
2.26k
      case XML_TOK_PARTIAL_CHAR:
5549
2.26k
        return XML_ERROR_PARTIAL_CHAR;
5550
134
      case -XML_TOK_PROLOG_S:
5551
134
        tok = -tok;
5552
134
        break;
5553
461
      case XML_TOK_NONE:
5554
461
#ifdef XML_DTD
5555
        /* for internal PE NOT referenced between declarations */
5556
461
        if (enc != parser->m_encoding
5557
0
            && ! parser->m_openInternalEntities->betweenDecl) {
5558
0
          *nextPtr = s;
5559
0
          return XML_ERROR_NONE;
5560
0
        }
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
461
        if (parser->m_isParamEntity || enc != parser->m_encoding) {
5566
0
          if (XmlTokenRole(&parser->m_prologState, XML_TOK_NONE, end, end, enc)
5567
0
              == XML_ROLE_ERROR)
5568
0
            return XML_ERROR_INCOMPLETE_PE;
5569
0
          *nextPtr = s;
5570
0
          return XML_ERROR_NONE;
5571
0
        }
5572
461
#endif /* XML_DTD */
5573
461
        return XML_ERROR_NO_ELEMENTS;
5574
1.00k
      default:
5575
1.00k
        tok = -tok;
5576
1.00k
        next = end;
5577
1.00k
        break;
5578
39.5k
      }
5579
39.5k
    }
5580
108k
    role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
5581
108k
#if XML_GE == 1
5582
108k
    switch (role) {
5583
56.2k
    case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor
5584
57.4k
    case XML_ROLE_XML_DECL:       // bytes accounted in processXmlDecl
5585
57.4k
#  ifdef XML_DTD
5586
57.4k
    case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl
5587
57.4k
#  endif
5588
57.4k
      break;
5589
51.4k
    default:
5590
51.4k
      if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
5591
0
        accountingOnAbort(parser);
5592
0
        return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
5593
0
      }
5594
108k
    }
5595
108k
#endif
5596
108k
    switch (role) {
5597
1.15k
    case XML_ROLE_XML_DECL: {
5598
1.15k
      enum XML_Error result = processXmlDecl(parser, 0, s, next);
5599
1.15k
      if (result != XML_ERROR_NONE)
5600
1.15k
        return result;
5601
0
      enc = parser->m_encoding;
5602
0
      handleDefault = XML_FALSE;
5603
0
    } break;
5604
4.31k
    case XML_ROLE_DOCTYPE_NAME:
5605
4.31k
      if (parser->m_startDoctypeDeclHandler) {
5606
4.31k
        parser->m_doctypeName
5607
4.31k
            = poolStoreString(&parser->m_tempPool, enc, s, next);
5608
4.31k
        if (! parser->m_doctypeName)
5609
0
          return XML_ERROR_NO_MEMORY;
5610
4.31k
        poolFinish(&parser->m_tempPool);
5611
4.31k
        parser->m_doctypePubid = NULL;
5612
4.31k
        handleDefault = XML_FALSE;
5613
4.31k
      }
5614
4.31k
      parser->m_doctypeSysid = NULL; /* always initialize to NULL */
5615
4.31k
      break;
5616
2.11k
    case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
5617
2.11k
      if (parser->m_startDoctypeDeclHandler) {
5618
2.11k
        beforeHandler(parser);
5619
2.11k
        parser->m_startDoctypeDeclHandler(
5620
2.11k
            parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
5621
2.11k
            parser->m_doctypePubid, 1);
5622
2.11k
        afterHandler(parser);
5623
2.11k
        parser->m_doctypeName = NULL;
5624
2.11k
        poolClear(&parser->m_tempPool);
5625
2.11k
        handleDefault = XML_FALSE;
5626
2.11k
      }
5627
2.11k
      break;
5628
0
#ifdef XML_DTD
5629
0
    case XML_ROLE_TEXT_DECL: {
5630
0
      enum XML_Error result = processXmlDecl(parser, 1, s, next);
5631
0
      if (result != XML_ERROR_NONE)
5632
0
        return result;
5633
0
      enc = parser->m_encoding;
5634
0
      handleDefault = XML_FALSE;
5635
0
    } break;
5636
0
#endif /* XML_DTD */
5637
0
    case XML_ROLE_DOCTYPE_PUBLIC_ID:
5638
0
#ifdef XML_DTD
5639
0
      parser->m_useForeignDTD = XML_FALSE;
5640
0
      parser->m_declEntity = (ENTITY *)lookup(
5641
0
          parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
5642
0
      if (! parser->m_declEntity)
5643
0
        return XML_ERROR_NO_MEMORY;
5644
0
#endif /* XML_DTD */
5645
0
      dtd->hasParamEntityRefs = XML_TRUE;
5646
0
      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
0
      EXPAT_FALLTHROUGH;
5662
0
    case XML_ROLE_ENTITY_PUBLIC_ID:
5663
0
      if (! XmlIsPublicId(enc, s, next, eventPP))
5664
0
        return XML_ERROR_PUBLICID;
5665
0
    alreadyChecked:
5666
0
      if (dtd->keepProcessing && parser->m_declEntity) {
5667
0
        XML_Char *tem
5668
0
            = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
5669
0
                              next - enc->minBytesPerChar);
5670
0
        if (! tem)
5671
0
          return XML_ERROR_NO_MEMORY;
5672
0
        normalizePublicId(tem);
5673
0
        parser->m_declEntity->publicId = tem;
5674
0
        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
0
        if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID)
5679
0
          handleDefault = XML_FALSE;
5680
0
      }
5681
0
      break;
5682
1.35k
    case XML_ROLE_DOCTYPE_CLOSE:
5683
1.35k
      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.35k
      if (parser->m_doctypeName) {
5689
1.10k
        beforeHandler(parser);
5690
1.10k
        parser->m_startDoctypeDeclHandler(
5691
1.10k
            parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
5692
1.10k
            parser->m_doctypePubid, 0);
5693
1.10k
        afterHandler(parser);
5694
1.10k
        poolClear(&parser->m_tempPool);
5695
1.10k
        handleDefault = XML_FALSE;
5696
1.10k
      }
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
1.35k
#ifdef XML_DTD
5702
1.35k
      if (parser->m_doctypeSysid || parser->m_useForeignDTD) {
5703
0
        XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
5704
0
        dtd->hasParamEntityRefs = XML_TRUE;
5705
0
        if (parser->m_paramEntityParsing
5706
0
            && parser->m_externalEntityRefHandler) {
5707
0
          ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
5708
0
                                            externalSubsetName, sizeof(ENTITY));
5709
0
          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
0
            return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
5716
0
          }
5717
0
          if (parser->m_useForeignDTD)
5718
0
            entity->base = parser->m_curBase;
5719
0
          dtd->paramEntityRead = false;
5720
0
          beforeHandler(parser);
5721
0
          const int status = parser->m_externalEntityRefHandler(
5722
0
              parser->m_externalEntityRefHandlerArg, 0, entity->base,
5723
0
              entity->systemId, entity->publicId);
5724
0
          afterHandler(parser);
5725
0
          if (! status)
5726
0
            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5727
0
          if (dtd->paramEntityRead) {
5728
0
            if (! dtd->standalone && parser->m_notStandaloneHandler) {
5729
0
              beforeHandler(parser);
5730
0
              const int handlerStatus
5731
0
                  = parser->m_notStandaloneHandler(parser->m_handlerArg);
5732
0
              afterHandler(parser);
5733
0
              if (! handlerStatus)
5734
0
                return XML_ERROR_NOT_STANDALONE;
5735
0
            }
5736
0
          }
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
0
          else if (! parser->m_doctypeSysid)
5741
0
            dtd->hasParamEntityRefs = hadParamEntityRefs;
5742
          /* end of DTD - no need to update dtd->keepProcessing */
5743
0
        }
5744
0
        parser->m_useForeignDTD = XML_FALSE;
5745
0
      }
5746
1.35k
#endif /* XML_DTD */
5747
1.35k
      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.35k
      break;
5754
56.2k
    case XML_ROLE_INSTANCE_START:
5755
56.2k
#ifdef XML_DTD
5756
      /* if there is no DOCTYPE declaration then now is the
5757
         last chance to read the foreign DTD
5758
      */
5759
56.2k
      if (parser->m_useForeignDTD) {
5760
0
        XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
5761
0
        dtd->hasParamEntityRefs = XML_TRUE;
5762
0
        if (parser->m_paramEntityParsing
5763
0
            && parser->m_externalEntityRefHandler) {
5764
0
          ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
5765
0
                                            externalSubsetName, sizeof(ENTITY));
5766
0
          if (! entity)
5767
0
            return XML_ERROR_NO_MEMORY;
5768
0
          entity->base = parser->m_curBase;
5769
0
          dtd->paramEntityRead = false;
5770
0
          beforeHandler(parser);
5771
0
          const int status = parser->m_externalEntityRefHandler(
5772
0
              parser->m_externalEntityRefHandlerArg, 0, entity->base,
5773
0
              entity->systemId, entity->publicId);
5774
0
          afterHandler(parser);
5775
0
          if (! status)
5776
0
            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5777
0
          if (dtd->paramEntityRead) {
5778
0
            if (! dtd->standalone && parser->m_notStandaloneHandler) {
5779
0
              beforeHandler(parser);
5780
0
              const int handlerStatus
5781
0
                  = parser->m_notStandaloneHandler(parser->m_handlerArg);
5782
0
              afterHandler(parser);
5783
0
              if (! handlerStatus)
5784
0
                return XML_ERROR_NOT_STANDALONE;
5785
0
            }
5786
0
          }
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
0
          else
5791
0
            dtd->hasParamEntityRefs = hadParamEntityRefs;
5792
          /* end of DTD - no need to update dtd->keepProcessing */
5793
0
        }
5794
0
      }
5795
56.2k
#endif /* XML_DTD */
5796
56.2k
      parser->m_processor = contentProcessor;
5797
56.2k
      return contentProcessor(parser, s, end, nextPtr);
5798
0
    case XML_ROLE_ATTLIST_ELEMENT_NAME:
5799
0
      parser->m_declElementType = getElementType(parser, enc, s, next);
5800
0
      if (! parser->m_declElementType)
5801
0
        return XML_ERROR_NO_MEMORY;
5802
0
      goto checkAttListDeclHandler;
5803
0
    case XML_ROLE_ATTRIBUTE_NAME:
5804
0
      parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
5805
0
      if (! parser->m_declAttributeId)
5806
0
        return XML_ERROR_NO_MEMORY;
5807
0
      parser->m_declAttributeIsCdata = false;
5808
0
      parser->m_declAttributeType = NULL;
5809
0
      parser->m_declAttributeIsId = false;
5810
0
      goto checkAttListDeclHandler;
5811
0
    case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
5812
0
      parser->m_declAttributeIsCdata = true;
5813
0
      parser->m_declAttributeType = atypeCDATA;
5814
0
      goto checkAttListDeclHandler;
5815
0
    case XML_ROLE_ATTRIBUTE_TYPE_ID:
5816
0
      parser->m_declAttributeIsId = true;
5817
0
      parser->m_declAttributeType = atypeID;
5818
0
      goto checkAttListDeclHandler;
5819
0
    case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
5820
0
      parser->m_declAttributeType = atypeIDREF;
5821
0
      goto checkAttListDeclHandler;
5822
0
    case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
5823
0
      parser->m_declAttributeType = atypeIDREFS;
5824
0
      goto checkAttListDeclHandler;
5825
0
    case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
5826
0
      parser->m_declAttributeType = atypeENTITY;
5827
0
      goto checkAttListDeclHandler;
5828
0
    case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
5829
0
      parser->m_declAttributeType = atypeENTITIES;
5830
0
      goto checkAttListDeclHandler;
5831
0
    case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
5832
0
      parser->m_declAttributeType = atypeNMTOKEN;
5833
0
      goto checkAttListDeclHandler;
5834
0
    case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
5835
0
      parser->m_declAttributeType = atypeNMTOKENS;
5836
0
    checkAttListDeclHandler:
5837
0
      if (dtd->keepProcessing && parser->m_attlistDeclHandler)
5838
0
        handleDefault = XML_FALSE;
5839
0
      break;
5840
0
    case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
5841
0
    case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
5842
0
      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
0
      break;
5858
0
    case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
5859
0
    case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
5860
0
      if (dtd->keepProcessing) {
5861
0
        if (! defineAttribute(parser->m_declElementType,
5862
0
                              parser->m_declAttributeId,
5863
0
                              parser->m_declAttributeIsCdata,
5864
0
                              parser->m_declAttributeIsId, 0, parser))
5865
0
          return XML_ERROR_NO_MEMORY;
5866
0
        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
0
      }
5887
0
      poolClear(&parser->m_tempPool);
5888
0
      break;
5889
0
    case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
5890
0
    case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
5891
0
      if (dtd->keepProcessing) {
5892
0
        const XML_Char *attVal;
5893
0
        enum XML_Error result = storeAttributeValue(
5894
0
            parser, enc, parser->m_declAttributeIsCdata,
5895
0
            s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool,
5896
0
            XML_ACCOUNT_NONE);
5897
0
        if (result)
5898
0
          return result;
5899
0
        attVal = poolStart(&dtd->pool);
5900
0
        poolFinish(&dtd->pool);
5901
        /* ID attributes aren't allowed to have a default */
5902
0
        if (! defineAttribute(
5903
0
                parser->m_declElementType, parser->m_declAttributeId,
5904
0
                parser->m_declAttributeIsCdata, false, attVal, parser))
5905
0
          return XML_ERROR_NO_MEMORY;
5906
0
        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
0
      }
5928
0
      break;
5929
0
    case XML_ROLE_ENTITY_VALUE:
5930
0
      if (dtd->keepProcessing) {
5931
0
#if XML_GE == 1
5932
        // This will store the given replacement text in
5933
        // parser->m_declEntity->textPtr.
5934
0
        const enum XML_Error result = callStoreEntityValue(
5935
0
            parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar,
5936
0
            XML_ACCOUNT_NONE);
5937
0
        if (result != XML_ERROR_NONE) {
5938
0
          poolDiscard(&dtd->entityValuePool);
5939
0
          return result;
5940
0
        }
5941
0
        if (parser->m_declEntity) {
5942
          /* Detect and prevent signed integer overflow */
5943
0
          if ((size_t)poolLength(&dtd->entityValuePool) > (size_t)INT_MAX) {
5944
0
            poolDiscard(&dtd->entityValuePool);
5945
0
            return XML_ERROR_NO_MEMORY;
5946
0
          }
5947
0
          parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
5948
0
          parser->m_declEntity->textLen = poolLength(&dtd->entityValuePool);
5949
0
          poolFinish(&dtd->entityValuePool);
5950
0
          if (parser->m_entityDeclHandler) {
5951
0
            *eventEndPP = s;
5952
0
            beforeHandler(parser);
5953
0
            parser->m_entityDeclHandler(
5954
0
                parser->m_handlerArg, parser->m_declEntity->name,
5955
0
                parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
5956
0
                (int)parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
5957
0
            afterHandler(parser);
5958
0
            handleDefault = XML_FALSE;
5959
0
          }
5960
0
        } else
5961
0
          poolDiscard(&dtd->entityValuePool);
5962
#else
5963
        // This will store "&amp;entity123;" in parser->m_declEntity->textPtr
5964
        // to end up as "&entity123;" in the handler.
5965
        if (parser->m_declEntity != NULL) {
5966
          const enum XML_Error result
5967
              = storeSelfEntityValue(parser, parser->m_declEntity);
5968
          if (result != XML_ERROR_NONE)
5969
            return result;
5970
5971
          if (parser->m_entityDeclHandler) {
5972
            *eventEndPP = s;
5973
            beforeHandler(parser);
5974
            parser->m_entityDeclHandler(
5975
                parser->m_handlerArg, parser->m_declEntity->name,
5976
                parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
5977
                (int)parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
5978
            afterHandler(parser);
5979
            handleDefault = XML_FALSE;
5980
          }
5981
        }
5982
#endif
5983
0
      }
5984
0
      break;
5985
0
    case XML_ROLE_DOCTYPE_SYSTEM_ID:
5986
0
#ifdef XML_DTD
5987
0
      parser->m_useForeignDTD = XML_FALSE;
5988
0
#endif /* XML_DTD */
5989
0
      dtd->hasParamEntityRefs = XML_TRUE;
5990
0
      if (parser->m_startDoctypeDeclHandler) {
5991
0
        parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc,
5992
0
                                                 s + enc->minBytesPerChar,
5993
0
                                                 next - enc->minBytesPerChar);
5994
0
        if (parser->m_doctypeSysid == NULL)
5995
0
          return XML_ERROR_NO_MEMORY;
5996
0
        poolFinish(&parser->m_tempPool);
5997
0
        handleDefault = XML_FALSE;
5998
0
      }
5999
0
#ifdef XML_DTD
6000
0
      else
6001
        /* use externalSubsetName to make parser->m_doctypeSysid non-NULL
6002
           for the case where no parser->m_startDoctypeDeclHandler is set */
6003
0
        parser->m_doctypeSysid = externalSubsetName;
6004
0
#endif /* XML_DTD */
6005
0
      if (! dtd->standalone
6006
0
#ifdef XML_DTD
6007
0
          && ! parser->m_paramEntityParsing
6008
0
#endif /* XML_DTD */
6009
0
          && parser->m_notStandaloneHandler) {
6010
0
        beforeHandler(parser);
6011
0
        const int status = parser->m_notStandaloneHandler(parser->m_handlerArg);
6012
0
        afterHandler(parser);
6013
0
        if (! status)
6014
0
          return XML_ERROR_NOT_STANDALONE;
6015
0
      }
6016
#ifndef XML_DTD
6017
      break;
6018
#else  /* XML_DTD */
6019
0
      if (! parser->m_declEntity) {
6020
0
        parser->m_declEntity = (ENTITY *)lookup(
6021
0
            parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
6022
0
        if (! parser->m_declEntity)
6023
0
          return XML_ERROR_NO_MEMORY;
6024
0
        parser->m_declEntity->publicId = NULL;
6025
0
      }
6026
0
#endif /* XML_DTD */
6027
0
      EXPAT_FALLTHROUGH;
6028
0
    case XML_ROLE_ENTITY_SYSTEM_ID:
6029
0
      if (dtd->keepProcessing && parser->m_declEntity) {
6030
0
        parser->m_declEntity->systemId
6031
0
            = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
6032
0
                              next - enc->minBytesPerChar);
6033
0
        if (! parser->m_declEntity->systemId)
6034
0
          return XML_ERROR_NO_MEMORY;
6035
0
        parser->m_declEntity->base = parser->m_curBase;
6036
0
        poolFinish(&dtd->pool);
6037
        /* Don't suppress the default handler if we fell through from
6038
         * the XML_ROLE_DOCTYPE_SYSTEM_ID case.
6039
         */
6040
0
        if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID)
6041
0
          handleDefault = XML_FALSE;
6042
0
      }
6043
0
      break;
6044
0
    case XML_ROLE_ENTITY_COMPLETE:
6045
#if XML_GE == 0
6046
      // This will store "&amp;entity123;" in entity->textPtr
6047
      // to end up as "&entity123;" in the handler.
6048
      if (parser->m_declEntity != NULL) {
6049
        const enum XML_Error result
6050
            = storeSelfEntityValue(parser, parser->m_declEntity);
6051
        if (result != XML_ERROR_NONE)
6052
          return result;
6053
      }
6054
#endif
6055
0
      if (dtd->keepProcessing && parser->m_declEntity
6056
0
          && parser->m_entityDeclHandler) {
6057
0
        *eventEndPP = s;
6058
0
        beforeHandler(parser);
6059
0
        parser->m_entityDeclHandler(
6060
0
            parser->m_handlerArg, parser->m_declEntity->name,
6061
0
            parser->m_declEntity->is_param, 0, 0, parser->m_declEntity->base,
6062
0
            parser->m_declEntity->systemId, parser->m_declEntity->publicId, 0);
6063
0
        afterHandler(parser);
6064
0
        handleDefault = XML_FALSE;
6065
0
      }
6066
0
      break;
6067
0
    case XML_ROLE_ENTITY_NOTATION_NAME:
6068
0
      if (dtd->keepProcessing && parser->m_declEntity) {
6069
0
        parser->m_declEntity->notation
6070
0
            = poolStoreString(&dtd->pool, enc, s, next);
6071
0
        if (! parser->m_declEntity->notation)
6072
0
          return XML_ERROR_NO_MEMORY;
6073
0
        poolFinish(&dtd->pool);
6074
0
        if (parser->m_unparsedEntityDeclHandler) {
6075
0
          *eventEndPP = s;
6076
0
          beforeHandler(parser);
6077
0
          parser->m_unparsedEntityDeclHandler(
6078
0
              parser->m_handlerArg, parser->m_declEntity->name,
6079
0
              parser->m_declEntity->base, parser->m_declEntity->systemId,
6080
0
              parser->m_declEntity->publicId, parser->m_declEntity->notation);
6081
0
          afterHandler(parser);
6082
0
          handleDefault = XML_FALSE;
6083
0
        } else if (parser->m_entityDeclHandler) {
6084
0
          *eventEndPP = s;
6085
0
          beforeHandler(parser);
6086
0
          parser->m_entityDeclHandler(
6087
0
              parser->m_handlerArg, parser->m_declEntity->name, 0, 0, 0,
6088
0
              parser->m_declEntity->base, parser->m_declEntity->systemId,
6089
0
              parser->m_declEntity->publicId, parser->m_declEntity->notation);
6090
0
          afterHandler(parser);
6091
0
          handleDefault = XML_FALSE;
6092
0
        }
6093
0
      }
6094
0
      break;
6095
0
    case XML_ROLE_GENERAL_ENTITY_NAME: {
6096
0
      if (XmlPredefinedEntityName(enc, s, next)) {
6097
0
        parser->m_declEntity = NULL;
6098
0
        break;
6099
0
      }
6100
0
      if (dtd->keepProcessing) {
6101
0
        const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
6102
0
        if (! name)
6103
0
          return XML_ERROR_NO_MEMORY;
6104
0
        parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities,
6105
0
                                                name, sizeof(ENTITY));
6106
0
        if (! parser->m_declEntity)
6107
0
          return XML_ERROR_NO_MEMORY;
6108
0
        if (parser->m_declEntity->name != name) {
6109
0
          poolDiscard(&dtd->pool);
6110
0
          parser->m_declEntity = NULL;
6111
0
        } else {
6112
0
          poolFinish(&dtd->pool);
6113
0
          parser->m_declEntity->publicId = NULL;
6114
0
          parser->m_declEntity->is_param = false;
6115
          /* if we have a parent parser or are reading an internal parameter
6116
             entity, then the entity declaration is not considered "internal"
6117
          */
6118
0
          parser->m_declEntity->is_internal
6119
0
              = ! (parser->m_parentParser || parser->m_openInternalEntities);
6120
0
          if (parser->m_entityDeclHandler)
6121
0
            handleDefault = XML_FALSE;
6122
0
        }
6123
0
      } else {
6124
0
        poolDiscard(&dtd->pool);
6125
0
        parser->m_declEntity = NULL;
6126
0
      }
6127
0
    } break;
6128
0
    case XML_ROLE_PARAM_ENTITY_NAME:
6129
0
#ifdef XML_DTD
6130
0
      if (dtd->keepProcessing) {
6131
0
        const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
6132
0
        if (! name)
6133
0
          return XML_ERROR_NO_MEMORY;
6134
0
        parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
6135
0
                                                name, sizeof(ENTITY));
6136
0
        if (! parser->m_declEntity)
6137
0
          return XML_ERROR_NO_MEMORY;
6138
0
        if (parser->m_declEntity->name != name) {
6139
0
          poolDiscard(&dtd->pool);
6140
0
          parser->m_declEntity = NULL;
6141
0
        } else {
6142
0
          poolFinish(&dtd->pool);
6143
0
          parser->m_declEntity->publicId = NULL;
6144
0
          parser->m_declEntity->is_param = true;
6145
          /* if we have a parent parser or are reading an internal parameter
6146
             entity, then the entity declaration is not considered "internal"
6147
          */
6148
0
          parser->m_declEntity->is_internal
6149
0
              = ! (parser->m_parentParser || parser->m_openInternalEntities);
6150
0
          if (parser->m_entityDeclHandler)
6151
0
            handleDefault = XML_FALSE;
6152
0
        }
6153
0
      } else {
6154
0
        poolDiscard(&dtd->pool);
6155
0
        parser->m_declEntity = NULL;
6156
0
      }
6157
#else  /* not XML_DTD */
6158
      parser->m_declEntity = NULL;
6159
#endif /* XML_DTD */
6160
0
      break;
6161
0
    case XML_ROLE_NOTATION_NAME:
6162
0
      parser->m_declNotationPublicId = NULL;
6163
0
      parser->m_declNotationName = NULL;
6164
0
      if (parser->m_notationDeclHandler) {
6165
0
        parser->m_declNotationName
6166
0
            = poolStoreString(&parser->m_tempPool, enc, s, next);
6167
0
        if (! parser->m_declNotationName)
6168
0
          return XML_ERROR_NO_MEMORY;
6169
0
        poolFinish(&parser->m_tempPool);
6170
0
        handleDefault = XML_FALSE;
6171
0
      }
6172
0
      break;
6173
0
    case XML_ROLE_NOTATION_PUBLIC_ID:
6174
0
      if (! XmlIsPublicId(enc, s, next, eventPP))
6175
0
        return XML_ERROR_PUBLICID;
6176
0
      if (parser
6177
0
              ->m_declNotationName) { /* means m_notationDeclHandler != NULL */
6178
0
        XML_Char *tem = poolStoreString(&parser->m_tempPool, enc,
6179
0
                                        s + enc->minBytesPerChar,
6180
0
                                        next - enc->minBytesPerChar);
6181
0
        if (! tem)
6182
0
          return XML_ERROR_NO_MEMORY;
6183
0
        normalizePublicId(tem);
6184
0
        parser->m_declNotationPublicId = tem;
6185
0
        poolFinish(&parser->m_tempPool);
6186
0
        handleDefault = XML_FALSE;
6187
0
      }
6188
0
      break;
6189
0
    case XML_ROLE_NOTATION_SYSTEM_ID:
6190
0
      if (parser->m_declNotationName && parser->m_notationDeclHandler) {
6191
0
        const XML_Char *systemId = poolStoreString(&parser->m_tempPool, enc,
6192
0
                                                   s + enc->minBytesPerChar,
6193
0
                                                   next - enc->minBytesPerChar);
6194
0
        if (! systemId)
6195
0
          return XML_ERROR_NO_MEMORY;
6196
0
        *eventEndPP = s;
6197
0
        beforeHandler(parser);
6198
0
        parser->m_notationDeclHandler(
6199
0
            parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
6200
0
            systemId, parser->m_declNotationPublicId);
6201
0
        afterHandler(parser);
6202
0
        handleDefault = XML_FALSE;
6203
0
      }
6204
0
      poolClear(&parser->m_tempPool);
6205
0
      break;
6206
0
    case XML_ROLE_NOTATION_NO_SYSTEM_ID:
6207
0
      if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) {
6208
0
        *eventEndPP = s;
6209
0
        beforeHandler(parser);
6210
0
        parser->m_notationDeclHandler(
6211
0
            parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
6212
0
            0, parser->m_declNotationPublicId);
6213
0
        afterHandler(parser);
6214
0
        handleDefault = XML_FALSE;
6215
0
      }
6216
0
      poolClear(&parser->m_tempPool);
6217
0
      break;
6218
11.5k
    case XML_ROLE_ERROR:
6219
11.5k
      switch (tok) {
6220
158
      case XML_TOK_PARAM_ENTITY_REF:
6221
        /* PE references in internal subset are
6222
           not allowed within declarations. */
6223
158
        return XML_ERROR_PARAM_ENTITY_REF;
6224
10
      case XML_TOK_XML_DECL:
6225
10
        return XML_ERROR_MISPLACED_XML_PI;
6226
11.4k
      default:
6227
11.4k
        return XML_ERROR_SYNTAX;
6228
11.5k
      }
6229
0
#ifdef XML_DTD
6230
0
    case XML_ROLE_IGNORE_SECT: {
6231
0
      enum XML_Error result;
6232
0
      if (parser->m_defaultHandler)
6233
0
        reportDefault(parser, enc, s, next);
6234
0
      handleDefault = XML_FALSE;
6235
0
      result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
6236
0
      if (result != XML_ERROR_NONE)
6237
0
        return result;
6238
0
      else if (! next) {
6239
0
        parser->m_processor = ignoreSectionProcessor;
6240
0
        return result;
6241
0
      }
6242
0
    } break;
6243
0
#endif /* XML_DTD */
6244
0
    case XML_ROLE_GROUP_OPEN:
6245
0
      if (parser->m_prologState.level >= parser->m_groupSize) {
6246
0
        if (parser->m_groupSize) {
6247
          /* Detect and prevent integer overflow */
6248
0
          if (parser->m_groupSize > SIZE_MAX / 2) {
6249
0
            return XML_ERROR_NO_MEMORY;
6250
0
          }
6251
6252
0
          char *const new_connector = REALLOC(parser, parser->m_groupConnector,
6253
0
                                              parser->m_groupSize *= 2);
6254
0
          if (new_connector == NULL) {
6255
0
            parser->m_groupSize /= 2;
6256
0
            return XML_ERROR_NO_MEMORY;
6257
0
          }
6258
0
          parser->m_groupConnector = new_connector;
6259
0
        } else {
6260
0
          parser->m_groupConnector = MALLOC(parser, parser->m_groupSize = 32);
6261
0
          if (! parser->m_groupConnector) {
6262
0
            parser->m_groupSize = 0;
6263
0
            return XML_ERROR_NO_MEMORY;
6264
0
          }
6265
0
        }
6266
0
      }
6267
0
      parser->m_groupConnector[parser->m_prologState.level] = 0;
6268
0
      if (dtd->in_eldecl) {
6269
0
        int myindex = nextScaffoldPart(parser);
6270
0
        if (myindex < 0)
6271
0
          return XML_ERROR_NO_MEMORY;
6272
0
        assert(dtd->scaffIndex != NULL);
6273
0
        if ((size_t)dtd->scaffLevel >= dtd->scaffIndexSize) {
6274
          /* Detect and prevent integer overflow */
6275
0
          if (dtd->scaffIndexSize > SIZE_MAX / 2 / sizeof(int)) {
6276
0
            return XML_ERROR_NO_MEMORY;
6277
0
          }
6278
0
          assert(dtd->scaffIndexSize > 0);
6279
0
          const size_t new_size = dtd->scaffIndexSize * 2;
6280
0
          int *const new_scaff_index
6281
0
              = REALLOC(parser, dtd->scaffIndex, new_size * sizeof(int));
6282
0
          if (new_scaff_index == NULL) {
6283
0
            return XML_ERROR_NO_MEMORY;
6284
0
          }
6285
0
          dtd->scaffIndex = new_scaff_index;
6286
0
          dtd->scaffIndexSize = new_size;
6287
0
        }
6288
0
        dtd->scaffIndex[dtd->scaffLevel] = myindex;
6289
0
        dtd->scaffLevel++;
6290
0
        dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
6291
0
        if (parser->m_elementDeclHandler)
6292
0
          handleDefault = XML_FALSE;
6293
0
      }
6294
0
      break;
6295
0
    case XML_ROLE_GROUP_SEQUENCE:
6296
0
      if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE)
6297
0
        return XML_ERROR_SYNTAX;
6298
0
      parser->m_groupConnector[parser->m_prologState.level] = ASCII_COMMA;
6299
0
      if (dtd->in_eldecl && parser->m_elementDeclHandler)
6300
0
        handleDefault = XML_FALSE;
6301
0
      break;
6302
0
    case XML_ROLE_GROUP_CHOICE:
6303
0
      if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
6304
0
        return XML_ERROR_SYNTAX;
6305
0
      if (dtd->in_eldecl
6306
0
          && ! parser->m_groupConnector[parser->m_prologState.level]
6307
0
          && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
6308
0
              != XML_CTYPE_MIXED)) {
6309
0
        dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
6310
0
            = XML_CTYPE_CHOICE;
6311
0
        if (parser->m_elementDeclHandler)
6312
0
          handleDefault = XML_FALSE;
6313
0
      }
6314
0
      parser->m_groupConnector[parser->m_prologState.level] = ASCII_PIPE;
6315
0
      break;
6316
70
    case XML_ROLE_PARAM_ENTITY_REF:
6317
70
#ifdef XML_DTD
6318
70
    case XML_ROLE_INNER_PARAM_ENTITY_REF:
6319
70
      dtd->hasParamEntityRefs = XML_TRUE;
6320
70
      if (! parser->m_paramEntityParsing)
6321
70
        dtd->keepProcessing = dtd->standalone;
6322
0
      else {
6323
0
        const XML_Char *name;
6324
0
        ENTITY *entity;
6325
0
        name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
6326
0
                               next - enc->minBytesPerChar);
6327
0
        if (! name)
6328
0
          return XML_ERROR_NO_MEMORY;
6329
0
        entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
6330
0
        poolDiscard(&dtd->pool);
6331
        /* first, determine if a check for an existing declaration is needed;
6332
           if yes, check that the entity exists, and that it is internal,
6333
           otherwise call the skipped entity handler
6334
        */
6335
0
        if (parser->m_prologState.documentEntity
6336
0
            && (dtd->standalone ? ! parser->m_openInternalEntities
6337
0
                                : ! dtd->hasParamEntityRefs)) {
6338
0
          if (! entity)
6339
0
            return XML_ERROR_UNDEFINED_ENTITY;
6340
0
          else if (! entity->is_internal) {
6341
            /* It's hard to exhaustively search the code to be sure,
6342
             * but there doesn't seem to be a way of executing the
6343
             * following line.  There are two cases:
6344
             *
6345
             * If 'standalone' is false, the DTD must have no
6346
             * parameter entities or we wouldn't have passed the outer
6347
             * 'if' statement.  That means the only entity in the hash
6348
             * table is the external subset name "#" which cannot be
6349
             * given as a parameter entity name in XML syntax, so the
6350
             * lookup must have returned NULL and we don't even reach
6351
             * the test for an internal entity.
6352
             *
6353
             * If 'standalone' is true, it does not seem to be
6354
             * possible to create entities taking this code path that
6355
             * are not internal entities, so fail the test above.
6356
             *
6357
             * Because this analysis is very uncertain, the code is
6358
             * being left in place and merely removed from the
6359
             * coverage test statistics.
6360
             */
6361
0
            return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
6362
0
          }
6363
0
        } else if (! entity) {
6364
0
          dtd->keepProcessing = dtd->standalone;
6365
          /* cannot report skipped entities in declarations */
6366
0
          if ((role == XML_ROLE_PARAM_ENTITY_REF)
6367
0
              && parser->m_skippedEntityHandler) {
6368
0
            beforeHandler(parser);
6369
0
            parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1);
6370
0
            afterHandler(parser);
6371
0
            handleDefault = XML_FALSE;
6372
0
          }
6373
0
          break;
6374
0
        }
6375
0
        if (entity->open)
6376
0
          return XML_ERROR_RECURSIVE_ENTITY_REF;
6377
0
        if (entity->textPtr) {
6378
0
          enum XML_Error result;
6379
0
          bool betweenDecl = (role == XML_ROLE_PARAM_ENTITY_REF);
6380
0
          result = processEntity(parser, entity, betweenDecl, ENTITY_INTERNAL);
6381
0
          if (result != XML_ERROR_NONE)
6382
0
            return result;
6383
0
          handleDefault = XML_FALSE;
6384
0
          break;
6385
0
        }
6386
0
        if (parser->m_externalEntityRefHandler) {
6387
0
          dtd->paramEntityRead = false;
6388
0
          entity->open = true;
6389
0
          entityTrackingOnOpen(parser, entity, __LINE__);
6390
0
          beforeHandler(parser);
6391
0
          const int status = parser->m_externalEntityRefHandler(
6392
0
              parser->m_externalEntityRefHandlerArg, 0, entity->base,
6393
0
              entity->systemId, entity->publicId);
6394
0
          afterHandler(parser);
6395
0
          if (! status) {
6396
0
            entityTrackingOnClose(parser, entity, __LINE__);
6397
0
            entity->open = false;
6398
0
            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
6399
0
          }
6400
0
          entityTrackingOnClose(parser, entity, __LINE__);
6401
0
          entity->open = false;
6402
0
          handleDefault = XML_FALSE;
6403
0
          if (! dtd->paramEntityRead) {
6404
0
            dtd->keepProcessing = dtd->standalone;
6405
0
            break;
6406
0
          }
6407
0
        } else {
6408
0
          dtd->keepProcessing = dtd->standalone;
6409
0
          break;
6410
0
        }
6411
0
      }
6412
70
#endif /* XML_DTD */
6413
70
      if (! dtd->standalone && parser->m_notStandaloneHandler) {
6414
0
        beforeHandler(parser);
6415
0
        const int status = parser->m_notStandaloneHandler(parser->m_handlerArg);
6416
0
        afterHandler(parser);
6417
0
        if (! status)
6418
0
          return XML_ERROR_NOT_STANDALONE;
6419
0
      }
6420
70
      break;
6421
6422
      /* Element declaration stuff */
6423
6424
70
    case XML_ROLE_ELEMENT_NAME:
6425
0
      if (parser->m_elementDeclHandler) {
6426
0
        parser->m_declElementType = getElementType(parser, enc, s, next);
6427
0
        if (! parser->m_declElementType)
6428
0
          return XML_ERROR_NO_MEMORY;
6429
0
        dtd->scaffLevel = 0;
6430
0
        dtd->scaffCount = 0;
6431
0
        dtd->in_eldecl = true;
6432
0
        handleDefault = XML_FALSE;
6433
0
      }
6434
0
      break;
6435
6436
0
    case XML_ROLE_CONTENT_ANY:
6437
0
    case XML_ROLE_CONTENT_EMPTY:
6438
0
      if (dtd->in_eldecl) {
6439
0
        if (parser->m_elementDeclHandler) {
6440
          // NOTE: We are avoiding MALLOC(..) here to so that
6441
          //       applications that are not using XML_FreeContentModel but
6442
          //       plain free(..) or .free_fcn() to free the content model's
6443
          //       memory are safe.
6444
0
          XML_Content *content = parser->m_mem.malloc_fcn(sizeof(XML_Content));
6445
0
          if (! content)
6446
0
            return XML_ERROR_NO_MEMORY;
6447
0
          content->quant = XML_CQUANT_NONE;
6448
0
          content->name = NULL;
6449
0
          content->numchildren = 0;
6450
0
          content->children = NULL;
6451
0
          content->type = ((role == XML_ROLE_CONTENT_ANY) ? XML_CTYPE_ANY
6452
0
                                                          : XML_CTYPE_EMPTY);
6453
0
          *eventEndPP = s;
6454
0
          beforeHandler(parser);
6455
0
          parser->m_elementDeclHandler(
6456
0
              parser->m_handlerArg, parser->m_declElementType->name, content);
6457
0
          afterHandler(parser);
6458
0
          handleDefault = XML_FALSE;
6459
0
        }
6460
0
        dtd->in_eldecl = false;
6461
0
      }
6462
0
      break;
6463
6464
0
    case XML_ROLE_CONTENT_PCDATA:
6465
0
      if (dtd->in_eldecl) {
6466
0
        dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
6467
0
            = XML_CTYPE_MIXED;
6468
0
        if (parser->m_elementDeclHandler)
6469
0
          handleDefault = XML_FALSE;
6470
0
      }
6471
0
      break;
6472
6473
0
    case XML_ROLE_CONTENT_ELEMENT:
6474
0
      quant = XML_CQUANT_NONE;
6475
0
      goto elementContent;
6476
0
    case XML_ROLE_CONTENT_ELEMENT_OPT:
6477
0
      quant = XML_CQUANT_OPT;
6478
0
      goto elementContent;
6479
0
    case XML_ROLE_CONTENT_ELEMENT_REP:
6480
0
      quant = XML_CQUANT_REP;
6481
0
      goto elementContent;
6482
0
    case XML_ROLE_CONTENT_ELEMENT_PLUS:
6483
0
      quant = XML_CQUANT_PLUS;
6484
0
    elementContent:
6485
0
      if (dtd->in_eldecl) {
6486
0
        ELEMENT_TYPE *el;
6487
0
        const XML_Char *name;
6488
0
        size_t nameLen;
6489
0
        const char *nxt
6490
0
            = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
6491
0
        int myindex = nextScaffoldPart(parser);
6492
0
        if (myindex < 0)
6493
0
          return XML_ERROR_NO_MEMORY;
6494
0
        dtd->scaffold[myindex].type = XML_CTYPE_NAME;
6495
0
        dtd->scaffold[myindex].quant = quant;
6496
0
        el = getElementType(parser, enc, s, nxt);
6497
0
        if (! el)
6498
0
          return XML_ERROR_NO_MEMORY;
6499
0
        name = el->name;
6500
0
        dtd->scaffold[myindex].name = name;
6501
0
        nameLen = xcslen(name) + /*null terminator*/ 1;
6502
6503
        /* Detect and prevent integer overflow */
6504
0
        if (nameLen > UINT_MAX - dtd->contentStringLen) {
6505
0
          return XML_ERROR_NO_MEMORY;
6506
0
        }
6507
6508
0
        dtd->contentStringLen += (unsigned)nameLen;
6509
0
        if (parser->m_elementDeclHandler)
6510
0
          handleDefault = XML_FALSE;
6511
0
      }
6512
0
      break;
6513
6514
0
    case XML_ROLE_GROUP_CLOSE:
6515
0
      quant = XML_CQUANT_NONE;
6516
0
      goto closeGroup;
6517
0
    case XML_ROLE_GROUP_CLOSE_OPT:
6518
0
      quant = XML_CQUANT_OPT;
6519
0
      goto closeGroup;
6520
0
    case XML_ROLE_GROUP_CLOSE_REP:
6521
0
      quant = XML_CQUANT_REP;
6522
0
      goto closeGroup;
6523
0
    case XML_ROLE_GROUP_CLOSE_PLUS:
6524
0
      quant = XML_CQUANT_PLUS;
6525
0
    closeGroup:
6526
0
      if (dtd->in_eldecl) {
6527
0
        if (parser->m_elementDeclHandler)
6528
0
          handleDefault = XML_FALSE;
6529
0
        dtd->scaffLevel--;
6530
0
        dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
6531
0
        if (dtd->scaffLevel == 0) {
6532
0
          if (! handleDefault) {
6533
0
            XML_Content *model = build_model(parser);
6534
0
            if (! model)
6535
0
              return XML_ERROR_NO_MEMORY;
6536
0
            *eventEndPP = s;
6537
0
            beforeHandler(parser);
6538
0
            parser->m_elementDeclHandler(
6539
0
                parser->m_handlerArg, parser->m_declElementType->name, model);
6540
0
            afterHandler(parser);
6541
0
          }
6542
0
          dtd->in_eldecl = false;
6543
0
          dtd->contentStringLen = 0;
6544
0
        }
6545
0
      }
6546
0
      break;
6547
      /* End element declaration stuff */
6548
6549
3.58k
    case XML_ROLE_PI:
6550
3.58k
      if (! reportProcessingInstruction(parser, enc, s, next))
6551
0
        return XML_ERROR_NO_MEMORY;
6552
3.58k
      handleDefault = XML_FALSE;
6553
3.58k
      break;
6554
624
    case XML_ROLE_COMMENT:
6555
624
      if (! reportComment(parser, enc, s, next))
6556
0
        return XML_ERROR_NO_MEMORY;
6557
624
      handleDefault = XML_FALSE;
6558
624
      break;
6559
16.4k
    case XML_ROLE_NONE:
6560
16.4k
      switch (tok) {
6561
250
      case XML_TOK_BOM:
6562
250
        handleDefault = XML_FALSE;
6563
250
        break;
6564
16.4k
      }
6565
16.4k
      break;
6566
16.4k
    case XML_ROLE_DOCTYPE_NONE:
6567
11.2k
      if (parser->m_startDoctypeDeclHandler)
6568
11.2k
        handleDefault = XML_FALSE;
6569
11.2k
      break;
6570
0
    case XML_ROLE_ENTITY_NONE:
6571
0
      if (dtd->keepProcessing && parser->m_entityDeclHandler)
6572
0
        handleDefault = XML_FALSE;
6573
0
      break;
6574
0
    case XML_ROLE_NOTATION_NONE:
6575
0
      if (parser->m_notationDeclHandler)
6576
0
        handleDefault = XML_FALSE;
6577
0
      break;
6578
0
    case XML_ROLE_ATTLIST_NONE:
6579
0
      if (dtd->keepProcessing && parser->m_attlistDeclHandler)
6580
0
        handleDefault = XML_FALSE;
6581
0
      break;
6582
0
    case XML_ROLE_ELEMENT_NONE:
6583
0
      if (parser->m_elementDeclHandler)
6584
0
        handleDefault = XML_FALSE;
6585
0
      break;
6586
108k
    } /* end of big switch */
6587
6588
39.8k
    if (handleDefault && parser->m_defaultHandler)
6589
0
      reportDefault(parser, enc, s, next);
6590
6591
39.8k
    switch (parser->m_parsingStatus.parsing) {
6592
0
    case XML_SUSPENDED:
6593
0
      *nextPtr = next;
6594
0
      return XML_ERROR_NONE;
6595
0
    case XML_FINISHED:
6596
0
      return XML_ERROR_ABORTED;
6597
39.8k
    case XML_PARSING:
6598
39.8k
      if (parser->m_reenter) {
6599
0
        *nextPtr = next;
6600
0
        return XML_ERROR_NONE;
6601
0
      }
6602
39.8k
      EXPAT_FALLTHROUGH;
6603
39.8k
    default:
6604
39.8k
      s = next;
6605
39.8k
      tok = XmlPrologTok(enc, s, end, &next);
6606
39.8k
    }
6607
39.8k
  }
6608
  /* not reached */
6609
107k
}
6610
6611
static enum XML_Error
6612
epilogProcessor(XML_Parser parser, const char *s, const char *end,
6613
9.42k
                const char **nextPtr) {
6614
9.42k
  parser->m_processor = epilogProcessor;
6615
9.42k
  parser->m_eventPtr = s;
6616
17.7k
  for (;;) {
6617
17.7k
    const char *next = NULL;
6618
17.7k
    int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
6619
17.7k
#if XML_GE == 1
6620
17.7k
    if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
6621
17.7k
                                  XML_ACCOUNT_DIRECT)) {
6622
0
      accountingOnAbort(parser);
6623
0
      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
6624
0
    }
6625
17.7k
#endif
6626
17.7k
    parser->m_eventEndPtr = next;
6627
17.7k
    switch (tok) {
6628
    /* report partial linebreak - it might be the last token */
6629
385
    case -XML_TOK_PROLOG_S:
6630
385
      if (parser->m_defaultHandler) {
6631
0
        reportDefault(parser, parser->m_encoding, s, next);
6632
0
        if (parser->m_parsingStatus.parsing == XML_FINISHED)
6633
0
          return XML_ERROR_ABORTED;
6634
0
      }
6635
385
      *nextPtr = next;
6636
385
      return XML_ERROR_NONE;
6637
5.73k
    case XML_TOK_NONE:
6638
5.73k
      *nextPtr = s;
6639
5.73k
      return XML_ERROR_NONE;
6640
7.29k
    case XML_TOK_PROLOG_S:
6641
7.29k
      if (parser->m_defaultHandler)
6642
0
        reportDefault(parser, parser->m_encoding, s, next);
6643
7.29k
      break;
6644
509
    case XML_TOK_PI:
6645
509
      if (! reportProcessingInstruction(parser, parser->m_encoding, s, next))
6646
0
        return XML_ERROR_NO_MEMORY;
6647
509
      break;
6648
509
    case XML_TOK_COMMENT:
6649
494
      if (! reportComment(parser, parser->m_encoding, s, next))
6650
0
        return XML_ERROR_NO_MEMORY;
6651
494
      break;
6652
1.31k
    case XML_TOK_INVALID:
6653
1.31k
      parser->m_eventPtr = next;
6654
1.31k
      return XML_ERROR_INVALID_TOKEN;
6655
505
    case XML_TOK_PARTIAL:
6656
505
      if (! parser->m_parsingStatus.finalBuffer) {
6657
0
        *nextPtr = s;
6658
0
        return XML_ERROR_NONE;
6659
0
      }
6660
505
      return XML_ERROR_UNCLOSED_TOKEN;
6661
514
    case XML_TOK_PARTIAL_CHAR:
6662
514
      if (! parser->m_parsingStatus.finalBuffer) {
6663
0
        *nextPtr = s;
6664
0
        return XML_ERROR_NONE;
6665
0
      }
6666
514
      return XML_ERROR_PARTIAL_CHAR;
6667
969
    default:
6668
969
      return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
6669
17.7k
    }
6670
8.29k
    switch (parser->m_parsingStatus.parsing) {
6671
0
    case XML_SUSPENDED:
6672
0
      parser->m_eventPtr = next;
6673
0
      *nextPtr = next;
6674
0
      return XML_ERROR_NONE;
6675
0
    case XML_FINISHED:
6676
0
      parser->m_eventPtr = next;
6677
0
      return XML_ERROR_ABORTED;
6678
8.29k
    case XML_PARSING:
6679
8.29k
      if (parser->m_reenter) {
6680
0
        return XML_ERROR_UNEXPECTED_STATE; // LCOV_EXCL_LINE
6681
0
      }
6682
8.29k
      EXPAT_FALLTHROUGH;
6683
8.29k
    default:;
6684
8.29k
      parser->m_eventPtr = s = next;
6685
8.29k
    }
6686
8.29k
  }
6687
9.42k
}
6688
6689
static enum XML_Error
6690
processEntity(XML_Parser parser, ENTITY *entity, bool betweenDecl,
6691
0
              enum EntityType type) {
6692
0
  OPEN_INTERNAL_ENTITY *openEntity, **openEntityList;
6693
0
  OPEN_INTERNAL_ENTITY **const freeEntityList = &parser->m_freeEntities;
6694
0
  switch (type) {
6695
0
  case ENTITY_INTERNAL:
6696
0
    parser->m_processor = internalEntityProcessor;
6697
0
    openEntityList = &parser->m_openInternalEntities;
6698
0
    break;
6699
0
  case ENTITY_ATTRIBUTE:
6700
0
    openEntityList = &parser->m_openAttributeEntities;
6701
0
    break;
6702
0
  case ENTITY_VALUE:
6703
0
    openEntityList = &parser->m_openValueEntities;
6704
0
    break;
6705
    /* default case serves merely as a safety net in case of a
6706
     * wrong entityType. Therefore we exclude the following lines
6707
     * from the test coverage.
6708
     *
6709
     * LCOV_EXCL_START
6710
     */
6711
0
  default:
6712
    // Should not reach here
6713
0
    assert(0);
6714
    /* LCOV_EXCL_STOP */
6715
0
  }
6716
6717
0
  if (*freeEntityList) {
6718
0
    openEntity = *freeEntityList;
6719
0
    *freeEntityList = openEntity->next;
6720
0
  } else {
6721
0
    openEntity = MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
6722
0
    if (! openEntity)
6723
0
      return XML_ERROR_NO_MEMORY;
6724
0
  }
6725
0
  entity->open = true;
6726
0
  entity->hasMore = true;
6727
0
#if XML_GE == 1
6728
0
  entityTrackingOnOpen(parser, entity, __LINE__);
6729
0
#endif
6730
0
  entity->processed = 0;
6731
0
  openEntity->next = *openEntityList;
6732
0
  *openEntityList = openEntity;
6733
0
  openEntity->entity = entity;
6734
0
  openEntity->type = type;
6735
0
  openEntity->startTagLevel = parser->m_tagLevel;
6736
0
  openEntity->betweenDecl = betweenDecl;
6737
0
  openEntity->internalEventPtr = NULL;
6738
0
  openEntity->internalEventEndPtr = NULL;
6739
6740
  // Only internal entities make use of the reenter flag
6741
  // therefore no need to set it for other entity types
6742
0
  if (type == ENTITY_INTERNAL) {
6743
0
    triggerReenter(parser);
6744
0
  }
6745
0
  return XML_ERROR_NONE;
6746
0
}
6747
6748
static enum XML_Error
6749
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
6750
0
                        const char **nextPtr) {
6751
0
  UNUSED_P(s);
6752
0
  UNUSED_P(end);
6753
0
  UNUSED_P(nextPtr);
6754
0
  ENTITY *entity;
6755
0
  const char *textStart, *textEnd;
6756
0
  const char *next;
6757
0
  enum XML_Error result;
6758
0
  OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
6759
0
  if (! openEntity)
6760
0
    return XML_ERROR_UNEXPECTED_STATE;
6761
6762
0
  entity = openEntity->entity;
6763
6764
  // This will return early
6765
0
  if (entity->hasMore) {
6766
0
    textStart = ((const char *)entity->textPtr) + entity->processed;
6767
0
    textEnd = (const char *)(entity->textPtr + entity->textLen);
6768
    /* Set a safe default value in case 'next' does not get set */
6769
0
    next = textStart;
6770
6771
0
    if (entity->is_param) {
6772
0
      int tok
6773
0
          = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
6774
0
      result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
6775
0
                        tok, next, &next, XML_FALSE, XML_FALSE,
6776
0
                        XML_ACCOUNT_ENTITY_EXPANSION);
6777
0
    } else {
6778
0
      result = doContent(parser, openEntity->startTagLevel,
6779
0
                         parser->m_internalEncoding, textStart, textEnd, &next,
6780
0
                         XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
6781
0
    }
6782
6783
0
    if (result != XML_ERROR_NONE)
6784
0
      return result;
6785
    // Check if entity is complete, if not, mark down how much of it is
6786
    // processed
6787
0
    if (textEnd != next
6788
0
        && (parser->m_parsingStatus.parsing == XML_SUSPENDED
6789
0
            || (parser->m_parsingStatus.parsing == XML_PARSING
6790
0
                && parser->m_reenter))) {
6791
0
      entity->processed = next - (const char *)entity->textPtr;
6792
0
      return result;
6793
0
    }
6794
6795
    // Entity is complete. We cannot close it here since we need to first
6796
    // process its possible inner entities (which are added to the
6797
    // m_openInternalEntities during doProlog or doContent calls above)
6798
0
    entity->hasMore = false;
6799
0
    if (! entity->is_param
6800
0
        && (openEntity->startTagLevel != parser->m_tagLevel)) {
6801
0
      return XML_ERROR_ASYNC_ENTITY;
6802
0
    }
6803
0
    triggerReenter(parser);
6804
0
    return result;
6805
0
  } // End of entity processing, "if" block will return here
6806
6807
  // Remove fully processed openEntity from open entity list.
6808
0
#if XML_GE == 1
6809
0
  entityTrackingOnClose(parser, entity, __LINE__);
6810
0
#endif
6811
  // openEntity is m_openInternalEntities' head, as we set it at the start of
6812
  // this function and we skipped doProlog and doContent calls with hasMore set
6813
  // to false. This means we can directly remove the head of
6814
  // m_openInternalEntities
6815
0
  assert(parser->m_openInternalEntities == openEntity);
6816
0
  entity->open = false;
6817
0
  parser->m_openInternalEntities = parser->m_openInternalEntities->next;
6818
6819
  /* put openEntity back in list of free instances */
6820
0
  openEntity->next = parser->m_freeEntities;
6821
0
  parser->m_freeEntities = openEntity;
6822
6823
0
  if (parser->m_openInternalEntities == NULL) {
6824
0
    parser->m_processor = entity->is_param ? prologProcessor : contentProcessor;
6825
0
  }
6826
0
  triggerReenter(parser);
6827
0
  return XML_ERROR_NONE;
6828
0
}
6829
6830
static enum XML_Error
6831
errorProcessor(XML_Parser parser, const char *s, const char *end,
6832
0
               const char **nextPtr) {
6833
0
  UNUSED_P(s);
6834
0
  UNUSED_P(end);
6835
0
  UNUSED_P(nextPtr);
6836
0
  return parser->m_errorCode;
6837
0
}
6838
6839
static enum XML_Error
6840
storeAttributeValue(XML_Parser parser, const ENCODING *enc, bool isCdata,
6841
                    const char *ptr, const char *end, STRING_POOL *pool,
6842
8.99k
                    enum XML_Account account) {
6843
8.99k
  const char *next = ptr;
6844
8.99k
  enum XML_Error result = XML_ERROR_NONE;
6845
6846
8.99k
  while (1) {
6847
8.99k
    if (! parser->m_openAttributeEntities) {
6848
8.99k
      result = appendAttributeValue(parser, enc, isCdata, next, end, pool,
6849
8.99k
                                    account, &next);
6850
8.99k
    } else {
6851
0
      OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openAttributeEntities;
6852
0
      if (! openEntity)
6853
0
        return XML_ERROR_UNEXPECTED_STATE;
6854
6855
0
      ENTITY *const entity = openEntity->entity;
6856
0
      const char *const textStart
6857
0
          = ((const char *)entity->textPtr) + entity->processed;
6858
0
      const char *const textEnd
6859
0
          = (const char *)(entity->textPtr + entity->textLen);
6860
      /* Set a safe default value in case 'next' does not get set */
6861
0
      const char *nextInEntity = textStart;
6862
0
      if (entity->hasMore) {
6863
0
        result = appendAttributeValue(
6864
0
            parser, parser->m_internalEncoding, isCdata, textStart, textEnd,
6865
0
            pool, XML_ACCOUNT_ENTITY_EXPANSION, &nextInEntity);
6866
0
        if (result != XML_ERROR_NONE)
6867
0
          break;
6868
        // Check if entity is complete, if not, mark down how much of it is
6869
        // processed. A XML_SUSPENDED check here is not required as
6870
        // appendAttributeValue will never suspend the parser.
6871
0
        if (nextInEntity < textEnd) {
6872
0
          entity->processed = nextInEntity - (const char *)entity->textPtr;
6873
0
          continue;
6874
0
        }
6875
0
        assert(nextInEntity == textEnd);
6876
6877
        // Entity is complete. We cannot close it here since we need to first
6878
        // process its possible inner entities (which are added to the
6879
        // m_openAttributeEntities during appendAttributeValue)
6880
0
        entity->hasMore = false;
6881
0
        continue;
6882
0
      } // End of entity processing, "if" block skips the rest
6883
6884
      // Remove fully processed openEntity from open entity list.
6885
0
#if XML_GE == 1
6886
0
      entityTrackingOnClose(parser, entity, __LINE__);
6887
0
#endif
6888
      // openEntity is m_openAttributeEntities' head, since we set it at the
6889
      // start of this function and because we skipped appendAttributeValue call
6890
      // with hasMore set to false. This means we can directly remove the head
6891
      // of m_openAttributeEntities
6892
0
      assert(parser->m_openAttributeEntities == openEntity);
6893
0
      entity->open = false;
6894
0
      parser->m_openAttributeEntities = parser->m_openAttributeEntities->next;
6895
6896
      /* put openEntity back in list of free instances */
6897
0
      openEntity->next = parser->m_freeEntities;
6898
0
      parser->m_freeEntities = openEntity;
6899
0
    }
6900
6901
    // Break if an error occurred or there is nothing left to process
6902
8.99k
    if (result || (parser->m_openAttributeEntities == NULL && end == next)) {
6903
8.99k
      break;
6904
8.99k
    }
6905
8.99k
  }
6906
6907
8.99k
  if (result)
6908
227
    return result;
6909
8.76k
  if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
6910
0
    poolChop(pool);
6911
8.76k
  if (! poolAppendChar(pool, XML_T('\0')))
6912
0
    return XML_ERROR_NO_MEMORY;
6913
8.76k
  return XML_ERROR_NONE;
6914
8.76k
}
6915
6916
static enum XML_Error
6917
appendAttributeValue(XML_Parser parser, const ENCODING *enc, bool isCdata,
6918
                     const char *ptr, const char *end, STRING_POOL *pool,
6919
8.99k
                     enum XML_Account account, const char **nextPtr) {
6920
8.99k
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6921
#ifndef XML_DTD
6922
  UNUSED_P(account);
6923
#endif
6924
6925
672k
  for (;;) {
6926
672k
    const char *next
6927
672k
        = ptr; /* XmlAttributeValueTok doesn't always set the last arg */
6928
672k
    int tok = XmlAttributeValueTok(enc, ptr, end, &next);
6929
672k
#if XML_GE == 1
6930
672k
    if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) {
6931
0
      accountingOnAbort(parser);
6932
0
      return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
6933
0
    }
6934
672k
#endif
6935
672k
    switch (tok) {
6936
8.76k
    case XML_TOK_NONE:
6937
8.76k
      if (nextPtr) {
6938
8.76k
        *nextPtr = next;
6939
8.76k
      }
6940
8.76k
      return XML_ERROR_NONE;
6941
0
    case XML_TOK_INVALID:
6942
0
      if (enc == parser->m_encoding)
6943
0
        parser->m_eventPtr = next;
6944
0
      return XML_ERROR_INVALID_TOKEN;
6945
0
    case XML_TOK_PARTIAL:
6946
0
      if (enc == parser->m_encoding)
6947
0
        parser->m_eventPtr = ptr;
6948
0
      return XML_ERROR_INVALID_TOKEN;
6949
182
    case XML_TOK_CHAR_REF: {
6950
182
      XML_Char buf[XML_ENCODE_MAX];
6951
182
      int n = XmlCharRefNumber(enc, ptr);
6952
182
      if (n < 0) {
6953
41
        if (enc == parser->m_encoding)
6954
41
          parser->m_eventPtr = ptr;
6955
41
        return XML_ERROR_BAD_CHAR_REF;
6956
41
      }
6957
141
      if (! isCdata && n == 0x20 /* space */
6958
0
          && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
6959
0
        break;
6960
141
      n = XmlEncode(n, (ICHAR *)buf);
6961
      /* The XmlEncode() functions can never return 0 here.  That
6962
       * error return happens if the code point passed in is either
6963
       * negative or greater than or equal to 0x110000.  The
6964
       * XmlCharRefNumber() functions will all return a number
6965
       * strictly less than 0x110000 or a negative value if an error
6966
       * occurred.  The negative value is intercepted above, so
6967
       * XmlEncode() is never passed a value it might return an
6968
       * error for.
6969
       */
6970
6971
141
      if (! poolAppendChars(pool, buf, n))
6972
0
        return XML_ERROR_NO_MEMORY;
6973
141
    } break;
6974
26.3k
    case XML_TOK_DATA_CHARS:
6975
26.3k
      if (! poolAppend(pool, enc, ptr, next))
6976
0
        return XML_ERROR_NO_MEMORY;
6977
26.3k
      break;
6978
26.3k
    case XML_TOK_TRAILING_CR:
6979
377
      next = ptr + enc->minBytesPerChar;
6980
377
      EXPAT_FALLTHROUGH;
6981
629k
    case XML_TOK_ATTRIBUTE_VALUE_S:
6982
636k
    case XML_TOK_DATA_NEWLINE:
6983
636k
      if (! isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
6984
0
        break;
6985
636k
      if (! poolAppendChar(pool, 0x20))
6986
0
        return XML_ERROR_NO_MEMORY;
6987
636k
      break;
6988
636k
    case XML_TOK_ENTITY_REF: {
6989
503
      const XML_Char *name;
6990
503
      ENTITY *entity;
6991
503
      bool checkEntityDecl;
6992
503
      XML_Char ch = (XML_Char)XmlPredefinedEntityName(
6993
503
          enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
6994
503
      if (ch) {
6995
317
#if XML_GE == 1
6996
        /* NOTE: We are replacing 4-6 characters original input for 1 character
6997
         *       so there is no amplification and hence recording without
6998
         *       protection. */
6999
317
        accountingDiffTolerated(parser, tok, (char *)&ch,
7000
317
                                ((char *)&ch) + sizeof(XML_Char), __LINE__,
7001
317
                                XML_ACCOUNT_ENTITY_EXPANSION);
7002
317
#endif /* XML_GE == 1 */
7003
317
        if (! poolAppendChar(pool, ch))
7004
0
          return XML_ERROR_NO_MEMORY;
7005
317
        break;
7006
317
      }
7007
186
      name = poolStoreString(&parser->m_temp2Pool, enc,
7008
186
                             ptr + enc->minBytesPerChar,
7009
186
                             next - enc->minBytesPerChar);
7010
186
      if (! name)
7011
0
        return XML_ERROR_NO_MEMORY;
7012
186
      entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
7013
186
      poolDiscard(&parser->m_temp2Pool);
7014
      /* First, determine if a check for an existing declaration is needed;
7015
         if yes, check that the entity exists, and that it is internal.
7016
      */
7017
186
      if (pool == &dtd->pool) /* are we called from prolog? */
7018
0
        checkEntityDecl =
7019
0
#ifdef XML_DTD
7020
0
            parser->m_prologState.documentEntity &&
7021
0
#endif /* XML_DTD */
7022
0
            (dtd->standalone ? ! parser->m_openInternalEntities
7023
0
                             : ! dtd->hasParamEntityRefs);
7024
186
      else /* if (pool == &parser->m_tempPool): we are called from content */
7025
186
        checkEntityDecl = ! dtd->hasParamEntityRefs || dtd->standalone;
7026
186
      if (checkEntityDecl) {
7027
186
        if (! entity)
7028
186
          return XML_ERROR_UNDEFINED_ENTITY;
7029
0
        else if (! entity->is_internal)
7030
0
          return XML_ERROR_ENTITY_DECLARED_IN_PE;
7031
186
      } else if (! entity) {
7032
        /* Cannot report skipped entity here - see comments on
7033
           parser->m_skippedEntityHandler.
7034
        if (parser->m_skippedEntityHandler) {
7035
          beforeHandler(parser);
7036
          parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
7037
          afterHandler(parser);
7038
        }
7039
        */
7040
        /* Cannot call the default handler because this would be
7041
           out of sync with the call to the startElementHandler.
7042
        if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
7043
          reportDefault(parser, enc, ptr, next);
7044
        */
7045
0
        break;
7046
0
      }
7047
0
      if (entity->open) {
7048
0
        if (enc == parser->m_encoding) {
7049
          /* It does not appear that this line can be executed.
7050
           *
7051
           * The "if (entity->open)" check catches recursive entity
7052
           * definitions.  In order to be called with an open
7053
           * entity, it must have gone through this code before and
7054
           * been through the recursive call to
7055
           * appendAttributeValue() some lines below.  That call
7056
           * sets the local encoding ("enc") to the parser's
7057
           * internal encoding (internal_utf8 or internal_utf16),
7058
           * which can never be the same as the principle encoding.
7059
           * It doesn't appear there is another code path that gets
7060
           * here with entity->open being TRUE.
7061
           *
7062
           * Since it is not certain that this logic is watertight,
7063
           * we keep the line and merely exclude it from coverage
7064
           * tests.
7065
           */
7066
0
          parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
7067
0
        }
7068
0
        return XML_ERROR_RECURSIVE_ENTITY_REF;
7069
0
      }
7070
0
      if (entity->notation) {
7071
0
        if (enc == parser->m_encoding)
7072
0
          parser->m_eventPtr = ptr;
7073
0
        return XML_ERROR_BINARY_ENTITY_REF;
7074
0
      }
7075
0
      if (! entity->textPtr) {
7076
0
        if (enc == parser->m_encoding)
7077
0
          parser->m_eventPtr = ptr;
7078
0
        return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
7079
0
      } else {
7080
0
        enum XML_Error result;
7081
0
        result = processEntity(parser, entity, XML_FALSE, ENTITY_ATTRIBUTE);
7082
0
        if ((result == XML_ERROR_NONE) && (nextPtr != NULL)) {
7083
0
          *nextPtr = next;
7084
0
        }
7085
0
        return result;
7086
0
      }
7087
0
    } break;
7088
0
    default:
7089
      /* The only token returned by XmlAttributeValueTok() that does
7090
       * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
7091
       * Getting that would require an entity name to contain an
7092
       * incomplete XML character (e.g. \xE2\x82); however previous
7093
       * tokenisers will have already recognised and rejected such
7094
       * names before XmlAttributeValueTok() gets a look-in.  This
7095
       * default case should be retained as a safety net, but the code
7096
       * excluded from coverage tests.
7097
       *
7098
       * LCOV_EXCL_START
7099
       */
7100
0
      if (enc == parser->m_encoding)
7101
0
        parser->m_eventPtr = ptr;
7102
0
      return XML_ERROR_UNEXPECTED_STATE;
7103
      /* LCOV_EXCL_STOP */
7104
672k
    }
7105
663k
    ptr = next;
7106
663k
  }
7107
  /* not reached */
7108
8.99k
}
7109
7110
#if XML_GE == 1
7111
static enum XML_Error
7112
storeEntityValue(XML_Parser parser, const ENCODING *enc,
7113
                 const char *entityTextPtr, const char *entityTextEnd,
7114
0
                 enum XML_Account account, const char **nextPtr) {
7115
0
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7116
0
  STRING_POOL *pool = &(dtd->entityValuePool);
7117
0
  enum XML_Error result = XML_ERROR_NONE;
7118
0
#  ifdef XML_DTD
7119
0
  int oldInEntityValue = parser->m_prologState.inEntityValue;
7120
0
  parser->m_prologState.inEntityValue = 1;
7121
#  else
7122
  UNUSED_P(account);
7123
#  endif /* XML_DTD */
7124
  /* never return Null for the value argument in EntityDeclHandler,
7125
     since this would indicate an external entity; therefore we
7126
     have to make sure that entityValuePool.start is not null */
7127
0
  if (! pool->blocks) {
7128
0
    if (! poolGrow(pool))
7129
0
      return XML_ERROR_NO_MEMORY;
7130
0
  }
7131
7132
0
  const char *next = entityTextPtr;
7133
7134
  /* Nothing to tokenize. */
7135
0
  if (entityTextPtr >= entityTextEnd) {
7136
0
    result = XML_ERROR_NONE;
7137
0
    goto endEntityValue;
7138
0
  }
7139
7140
0
  for (;;) {
7141
0
    next
7142
0
        = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
7143
0
    int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
7144
7145
0
    if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__,
7146
0
                                  account)) {
7147
0
      accountingOnAbort(parser);
7148
0
      result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
7149
0
      goto endEntityValue;
7150
0
    }
7151
7152
0
    switch (tok) {
7153
0
    case XML_TOK_PARAM_ENTITY_REF:
7154
0
#  ifdef XML_DTD
7155
0
      if (parser->m_isParamEntity || enc != parser->m_encoding) {
7156
0
        const XML_Char *name;
7157
0
        ENTITY *entity;
7158
0
        name = poolStoreString(&parser->m_tempPool, enc,
7159
0
                               entityTextPtr + enc->minBytesPerChar,
7160
0
                               next - enc->minBytesPerChar);
7161
0
        if (! name) {
7162
0
          result = XML_ERROR_NO_MEMORY;
7163
0
          goto endEntityValue;
7164
0
        }
7165
0
        entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
7166
0
        poolDiscard(&parser->m_tempPool);
7167
0
        if (! entity) {
7168
          /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
7169
          /* cannot report skipped entity here - see comments on
7170
             parser->m_skippedEntityHandler
7171
          if (parser->m_skippedEntityHandler) {
7172
            beforeHandler(parser);
7173
            parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
7174
            afterHandler(parser);
7175
          }
7176
          */
7177
0
          dtd->keepProcessing = dtd->standalone;
7178
0
          goto endEntityValue;
7179
0
        }
7180
0
        if (entity->open || (entity == parser->m_declEntity)) {
7181
0
          if (enc == parser->m_encoding)
7182
0
            parser->m_eventPtr = entityTextPtr;
7183
0
          result = XML_ERROR_RECURSIVE_ENTITY_REF;
7184
0
          goto endEntityValue;
7185
0
        }
7186
0
        if (entity->systemId) {
7187
0
          if (parser->m_externalEntityRefHandler) {
7188
0
            dtd->paramEntityRead = false;
7189
0
            entity->open = true;
7190
0
            entityTrackingOnOpen(parser, entity, __LINE__);
7191
0
            beforeHandler(parser);
7192
0
            const int status = parser->m_externalEntityRefHandler(
7193
0
                parser->m_externalEntityRefHandlerArg, 0, entity->base,
7194
0
                entity->systemId, entity->publicId);
7195
0
            afterHandler(parser);
7196
0
            if (! status) {
7197
0
              entityTrackingOnClose(parser, entity, __LINE__);
7198
0
              entity->open = false;
7199
0
              result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
7200
0
              goto endEntityValue;
7201
0
            }
7202
0
            entityTrackingOnClose(parser, entity, __LINE__);
7203
0
            entity->open = false;
7204
0
            if (! dtd->paramEntityRead)
7205
0
              dtd->keepProcessing = dtd->standalone;
7206
0
          } else
7207
0
            dtd->keepProcessing = dtd->standalone;
7208
0
        } else {
7209
0
          result = processEntity(parser, entity, XML_FALSE, ENTITY_VALUE);
7210
0
          goto endEntityValue;
7211
0
        }
7212
0
        break;
7213
0
      }
7214
0
#  endif /* XML_DTD */
7215
      /* In the internal subset, PE references are not legal
7216
         within markup declarations, e.g entity values in this case. */
7217
0
      parser->m_eventPtr = entityTextPtr;
7218
0
      result = XML_ERROR_PARAM_ENTITY_REF;
7219
0
      goto endEntityValue;
7220
0
    case XML_TOK_NONE:
7221
0
      result = XML_ERROR_NONE;
7222
0
      goto endEntityValue;
7223
0
    case XML_TOK_ENTITY_REF:
7224
0
    case XML_TOK_DATA_CHARS:
7225
0
      if (! poolAppend(pool, enc, entityTextPtr, next)) {
7226
0
        result = XML_ERROR_NO_MEMORY;
7227
0
        goto endEntityValue;
7228
0
      }
7229
0
      break;
7230
0
    case XML_TOK_TRAILING_CR:
7231
0
      next = entityTextPtr + enc->minBytesPerChar;
7232
0
      EXPAT_FALLTHROUGH;
7233
0
    case XML_TOK_DATA_NEWLINE:
7234
0
      if (! poolAppendChar(pool, 0xA)) {
7235
0
        result = XML_ERROR_NO_MEMORY;
7236
0
        goto endEntityValue;
7237
0
      }
7238
0
      break;
7239
0
    case XML_TOK_CHAR_REF: {
7240
0
      XML_Char buf[XML_ENCODE_MAX];
7241
0
      int n = XmlCharRefNumber(enc, entityTextPtr);
7242
0
      if (n < 0) {
7243
0
        if (enc == parser->m_encoding)
7244
0
          parser->m_eventPtr = entityTextPtr;
7245
0
        result = XML_ERROR_BAD_CHAR_REF;
7246
0
        goto endEntityValue;
7247
0
      }
7248
0
      n = XmlEncode(n, (ICHAR *)buf);
7249
      /* The XmlEncode() functions can never return 0 here.  That
7250
       * error return happens if the code point passed in is either
7251
       * negative or greater than or equal to 0x110000.  The
7252
       * XmlCharRefNumber() functions will all return a number
7253
       * strictly less than 0x110000 or a negative value if an error
7254
       * occurred.  The negative value is intercepted above, so
7255
       * XmlEncode() is never passed a value it might return an
7256
       * error for.
7257
       */
7258
0
      if (! poolAppendChars(pool, buf, n)) {
7259
0
        result = XML_ERROR_NO_MEMORY;
7260
0
        goto endEntityValue;
7261
0
      }
7262
0
    } break;
7263
0
    case XML_TOK_PARTIAL:
7264
0
      if (enc == parser->m_encoding)
7265
0
        parser->m_eventPtr = entityTextPtr;
7266
0
      result = XML_ERROR_INVALID_TOKEN;
7267
0
      goto endEntityValue;
7268
0
    case XML_TOK_INVALID:
7269
0
      if (enc == parser->m_encoding)
7270
0
        parser->m_eventPtr = next;
7271
0
      result = XML_ERROR_INVALID_TOKEN;
7272
0
      goto endEntityValue;
7273
0
    default:
7274
      /* This default case should be unnecessary -- all the tokens
7275
       * that XmlEntityValueTok() can return have their own explicit
7276
       * cases -- but should be retained for safety.  We do however
7277
       * exclude it from the coverage statistics.
7278
       *
7279
       * LCOV_EXCL_START
7280
       */
7281
0
      if (enc == parser->m_encoding)
7282
0
        parser->m_eventPtr = entityTextPtr;
7283
0
      result = XML_ERROR_UNEXPECTED_STATE;
7284
0
      goto endEntityValue;
7285
      /* LCOV_EXCL_STOP */
7286
0
    }
7287
0
    entityTextPtr = next;
7288
0
  }
7289
0
endEntityValue:
7290
0
#  ifdef XML_DTD
7291
0
  parser->m_prologState.inEntityValue = oldInEntityValue;
7292
0
#  endif /* XML_DTD */
7293
  // If 'nextPtr' is given, it should be updated during the processing
7294
0
  if (nextPtr != NULL) {
7295
0
    *nextPtr = next;
7296
0
  }
7297
0
  return result;
7298
0
}
7299
7300
static enum XML_Error
7301
callStoreEntityValue(XML_Parser parser, const ENCODING *enc,
7302
                     const char *entityTextPtr, const char *entityTextEnd,
7303
0
                     enum XML_Account account) {
7304
0
  const char *next = entityTextPtr;
7305
0
  enum XML_Error result = XML_ERROR_NONE;
7306
0
  while (1) {
7307
0
    if (! parser->m_openValueEntities) {
7308
0
      result
7309
0
          = storeEntityValue(parser, enc, next, entityTextEnd, account, &next);
7310
0
    } else {
7311
0
      OPEN_INTERNAL_ENTITY *const openEntity = parser->m_openValueEntities;
7312
0
      if (! openEntity)
7313
0
        return XML_ERROR_UNEXPECTED_STATE;
7314
7315
0
      ENTITY *const entity = openEntity->entity;
7316
0
      const char *const textStart
7317
0
          = ((const char *)entity->textPtr) + entity->processed;
7318
0
      const char *const textEnd
7319
0
          = (const char *)(entity->textPtr + entity->textLen);
7320
      /* Set a safe default value in case 'next' does not get set */
7321
0
      const char *nextInEntity = textStart;
7322
0
      if (entity->hasMore) {
7323
0
        result = storeEntityValue(parser, parser->m_internalEncoding, textStart,
7324
0
                                  textEnd, XML_ACCOUNT_ENTITY_EXPANSION,
7325
0
                                  &nextInEntity);
7326
0
        if (result != XML_ERROR_NONE)
7327
0
          break;
7328
        // Check if entity is complete, if not, mark down how much of it is
7329
        // processed. A XML_SUSPENDED check here is not required as
7330
        // appendAttributeValue will never suspend the parser.
7331
0
        if (textEnd != nextInEntity) {
7332
0
          entity->processed = nextInEntity - (const char *)entity->textPtr;
7333
0
          continue;
7334
0
        }
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
0
        entity->hasMore = false;
7340
0
        continue;
7341
0
      } // End of entity processing, "if" block skips the rest
7342
7343
      // Remove fully processed openEntity from open entity list.
7344
0
#  if XML_GE == 1
7345
0
      entityTrackingOnClose(parser, entity, __LINE__);
7346
0
#  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
0
      assert(parser->m_openValueEntities == openEntity);
7352
0
      entity->open = false;
7353
0
      parser->m_openValueEntities = parser->m_openValueEntities->next;
7354
7355
      /* put openEntity back in list of free instances */
7356
0
      openEntity->next = parser->m_freeEntities;
7357
0
      parser->m_freeEntities = openEntity;
7358
0
    }
7359
7360
    // Break if an error occurred or there is nothing left to process
7361
0
    if (result
7362
0
        || (parser->m_openValueEntities == NULL && entityTextEnd == next)) {
7363
0
      break;
7364
0
    }
7365
0
  }
7366
7367
0
  return result;
7368
0
}
7369
7370
#else /* XML_GE == 0 */
7371
7372
static enum XML_Error
7373
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
  const char *const entity_start = "&amp;";
7377
  const char *const entity_end = ";";
7378
7379
  STRING_POOL *const pool = &(parser->m_dtd->entityValuePool);
7380
  if (! poolAppendString(pool, entity_start)
7381
      || ! poolAppendString(pool, entity->name)
7382
      || ! poolAppendString(pool, entity_end)) {
7383
    poolDiscard(pool);
7384
    return XML_ERROR_NO_MEMORY;
7385
  }
7386
7387
  /* Detect and prevent signed integer overflow */
7388
  if ((size_t)poolLength(pool) > (size_t)INT_MAX) {
7389
    poolDiscard(pool);
7390
    return XML_ERROR_NO_MEMORY;
7391
  }
7392
  entity->textPtr = poolStart(pool);
7393
  entity->textLen = poolLength(pool);
7394
  poolFinish(pool);
7395
7396
  return XML_ERROR_NONE;
7397
}
7398
7399
#endif /* XML_GE == 0 */
7400
7401
static void
7402
1.58k
normalizeLines(XML_Char *s) {
7403
1.58k
  XML_Char *p;
7404
89.6k
  for (;; s++) {
7405
89.6k
    if (*s == XML_T('\0'))
7406
1.39k
      return;
7407
88.2k
    if (*s == 0xD)
7408
194
      break;
7409
88.2k
  }
7410
194
  p = s;
7411
154k
  do {
7412
154k
    if (*s == 0xD) {
7413
107k
      *p++ = 0xA;
7414
107k
      if (*++s == 0xA)
7415
97
        s++;
7416
107k
    } else
7417
47.2k
      *p++ = *s++;
7418
154k
  } while (*s);
7419
194
  *p = XML_T('\0');
7420
194
}
7421
7422
static int
7423
reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
7424
4.13k
                            const char *start, const char *end) {
7425
4.13k
  const XML_Char *target;
7426
4.13k
  XML_Char *data;
7427
4.13k
  const char *tem;
7428
4.13k
  if (! parser->m_processingInstructionHandler) {
7429
2.75k
    if (parser->m_defaultHandler)
7430
0
      reportDefault(parser, enc, start, end);
7431
2.75k
    return 1;
7432
2.75k
  }
7433
1.38k
  start += enc->minBytesPerChar * 2;
7434
1.38k
  tem = start + XmlNameLength(enc, start);
7435
1.38k
  target = poolStoreString(&parser->m_tempPool, enc, start, tem);
7436
1.38k
  if (! target)
7437
0
    return 0;
7438
1.38k
  poolFinish(&parser->m_tempPool);
7439
1.38k
  data = poolStoreString(&parser->m_tempPool, enc, XmlSkipS(enc, tem),
7440
1.38k
                         end - enc->minBytesPerChar * 2);
7441
1.38k
  if (! data)
7442
0
    return 0;
7443
1.38k
  normalizeLines(data);
7444
1.38k
  beforeHandler(parser);
7445
1.38k
  parser->m_processingInstructionHandler(parser->m_handlerArg, target, data);
7446
1.38k
  afterHandler(parser);
7447
1.38k
  poolClear(&parser->m_tempPool);
7448
1.38k
  return 1;
7449
1.38k
}
7450
7451
static int
7452
reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
7453
1.20k
              const char *end) {
7454
1.20k
  XML_Char *data;
7455
1.20k
  if (! parser->m_commentHandler) {
7456
1.00k
    if (parser->m_defaultHandler)
7457
0
      reportDefault(parser, enc, start, end);
7458
1.00k
    return 1;
7459
1.00k
  }
7460
203
  data = poolStoreString(&parser->m_tempPool, enc,
7461
203
                         start + enc->minBytesPerChar * 4,
7462
203
                         end - enc->minBytesPerChar * 3);
7463
203
  if (! data)
7464
0
    return 0;
7465
203
  normalizeLines(data);
7466
203
  beforeHandler(parser);
7467
203
  parser->m_commentHandler(parser->m_handlerArg, data);
7468
203
  afterHandler(parser);
7469
203
  poolClear(&parser->m_tempPool);
7470
203
  return 1;
7471
203
}
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, bool isCdata,
7527
0
                bool isId, const XML_Char *value, XML_Parser parser) {
7528
0
  DEFAULT_ATTRIBUTE *att;
7529
0
  if (value || isId) {
7530
    /* The handling of default attributes gets messed up if we have
7531
       a default which duplicates a non-default. */
7532
0
    NAMED *const nameFound
7533
0
        = lookup(parser, &(type->defaultAttForName), attId->name, 0);
7534
0
    if (nameFound)
7535
0
      return 1;
7536
0
    if (isId && ! type->idAtt && ! attId->xmlns)
7537
0
      type->idAtt = attId;
7538
0
  }
7539
0
  if (type->nDefaultAtts == type->allocDefaultAtts) {
7540
    /* Detect and prevent integer overflow */
7541
0
    if (type->allocDefaultAtts > SIZE_MAX / 2) {
7542
0
      return 0;
7543
0
    }
7544
7545
0
    size_t count = type->allocDefaultAtts * 2;
7546
0
    if (count == 0) {
7547
0
      count = 8;
7548
0
    }
7549
7550
    /* Detect and prevent integer overflow. */
7551
0
    if (count > SIZE_MAX / sizeof(DEFAULT_ATTRIBUTE)) {
7552
0
      return 0;
7553
0
    }
7554
7555
0
    DEFAULT_ATTRIBUTE *const temp = REALLOC(
7556
0
        parser, type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
7557
0
    if (temp == NULL)
7558
0
      return 0;
7559
0
    type->allocDefaultAtts = count;
7560
0
    type->defaultAtts = temp;
7561
0
  }
7562
0
  att = type->defaultAtts + type->nDefaultAtts;
7563
0
  att->id = attId;
7564
0
  att->value = value;
7565
0
  att->isCdata = isCdata;
7566
0
  if (! isCdata)
7567
0
    attId->maybeTokenized = true;
7568
7569
0
  NAME_AND_DEFAULT_ATTRIBUTE *const nameAndDefaultAttribute
7570
0
      = (NAME_AND_DEFAULT_ATTRIBUTE *)lookup(
7571
0
          parser, &(type->defaultAttForName), attId->name,
7572
0
          sizeof(NAME_AND_DEFAULT_ATTRIBUTE));
7573
0
  if (! nameAndDefaultAttribute)
7574
0
    return 0;
7575
7576
0
  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
0
  if (! nameAndDefaultAttribute->initialized) {
7583
0
    nameAndDefaultAttribute->attIndex = type->nDefaultAtts;
7584
0
    nameAndDefaultAttribute->initialized = true;
7585
0
  }
7586
7587
0
  type->nDefaultAtts += 1;
7588
0
  return 1;
7589
0
}
7590
7591
static int
7592
60.9k
setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) {
7593
60.9k
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7594
60.9k
  const XML_Char *name;
7595
367k
  for (name = elementType->name; *name; name++) {
7596
336k
    if (*name == XML_T(ASCII_COLON)) {
7597
29.9k
      PREFIX *prefix;
7598
29.9k
      const XML_Char *s;
7599
132k
      for (s = elementType->name; s != name; s++) {
7600
102k
        if (! poolAppendChar(&dtd->pool, *s))
7601
0
          return 0;
7602
102k
      }
7603
29.9k
      if (! poolAppendChar(&dtd->pool, XML_T('\0')))
7604
0
        return 0;
7605
29.9k
      prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
7606
29.9k
                                sizeof(PREFIX));
7607
29.9k
      if (! prefix)
7608
0
        return 0;
7609
29.9k
      if (prefix->name == poolStart(&dtd->pool))
7610
8.13k
        poolFinish(&dtd->pool);
7611
21.8k
      else
7612
21.8k
        poolDiscard(&dtd->pool);
7613
29.9k
      elementType->prefix = prefix;
7614
29.9k
      break;
7615
29.9k
    }
7616
336k
  }
7617
60.9k
  return 1;
7618
60.9k
}
7619
7620
static ATTRIBUTE_ID *
7621
getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
7622
95.1k
               const char *end) {
7623
95.1k
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7624
95.1k
  ATTRIBUTE_ID *id;
7625
95.1k
  const XML_Char *name;
7626
95.1k
  if (! poolAppendChar(&dtd->pool, XML_T('\0')))
7627
0
    return NULL;
7628
95.1k
  name = poolStoreString(&dtd->pool, enc, start, end);
7629
95.1k
  if (! name)
7630
0
    return NULL;
7631
  /* skip quotation mark - its storage will be reused (like in name[-1]) */
7632
95.1k
  ++name;
7633
95.1k
  id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name,
7634
95.1k
                              sizeof(ATTRIBUTE_ID));
7635
95.1k
  if (! id)
7636
0
    return NULL;
7637
95.1k
  if (id->name != name)
7638
7.28k
    poolDiscard(&dtd->pool);
7639
87.8k
  else {
7640
87.8k
    poolFinish(&dtd->pool);
7641
87.8k
    if (! parser->m_ns)
7642
2
      ;
7643
87.8k
    else if (name[0] == XML_T(ASCII_x) && name[1] == XML_T(ASCII_m)
7644
35.4k
             && name[2] == XML_T(ASCII_l) && name[3] == XML_T(ASCII_n)
7645
26.5k
             && name[4] == XML_T(ASCII_s)
7646
26.4k
             && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
7647
26.0k
      if (name[5] == XML_T('\0'))
7648
189
        id->prefix = &dtd->defaultPrefix;
7649
25.9k
      else
7650
25.9k
        id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6,
7651
25.9k
                                      sizeof(PREFIX));
7652
26.0k
      id->xmlns = true;
7653
61.7k
    } else {
7654
61.7k
      int i;
7655
379k
      for (i = 0; name[i]; i++) {
7656
        /* Detect and prevent signed integer overflow */
7657
376k
        if (i == INT_MAX) {
7658
0
          return NULL;
7659
0
        }
7660
        /* attributes without prefix are *not* in the default namespace */
7661
376k
        if (name[i] == XML_T(ASCII_COLON)) {
7662
59.2k
          if (! poolAppendChars(&dtd->pool, name, i))
7663
0
            return NULL;
7664
59.2k
          if (! poolAppendChar(&dtd->pool, XML_T('\0')))
7665
0
            return NULL;
7666
59.2k
          id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes,
7667
59.2k
                                        poolStart(&dtd->pool), sizeof(PREFIX));
7668
59.2k
          if (! id->prefix)
7669
0
            return NULL;
7670
59.2k
          if (id->prefix->name == poolStart(&dtd->pool))
7671
1.03k
            poolFinish(&dtd->pool);
7672
58.1k
          else
7673
58.1k
            poolDiscard(&dtd->pool);
7674
59.2k
          break;
7675
59.2k
        }
7676
376k
      }
7677
61.7k
    }
7678
87.8k
  }
7679
95.1k
  return id;
7680
95.1k
}
7681
7682
4.40M
#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
  bool needSep = 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 = 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 = 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 = 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
107k
setContext(XML_Parser parser, const XML_Char *context) {
7772
107k
  if (context == NULL) {
7773
0
    return XML_FALSE;
7774
0
  }
7775
7776
107k
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7777
107k
  const XML_Char *s = context;
7778
7779
536k
  while (*context != XML_T('\0')) {
7780
429k
    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
429k
    } else if (*s == XML_T(ASCII_EQUALS)) {
7793
107k
      PREFIX *prefix;
7794
107k
      if (poolLength(&parser->m_tempPool) == 0)
7795
0
        prefix = &dtd->defaultPrefix;
7796
107k
      else {
7797
107k
        if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
7798
0
          return XML_FALSE;
7799
107k
        const XML_Char *const prefixName = poolCopyStringNoFinish(
7800
107k
            &dtd->pool, poolStart(&parser->m_tempPool));
7801
107k
        if (! prefixName) {
7802
0
          return XML_FALSE;
7803
0
        }
7804
7805
107k
        prefix = (PREFIX *)lookup(parser, &dtd->prefixes, prefixName,
7806
107k
                                  sizeof(PREFIX));
7807
7808
107k
        const bool prefixNameUsed = prefix && prefix->name == prefixName;
7809
107k
        if (prefixNameUsed)
7810
107k
          poolFinish(&dtd->pool);
7811
0
        else
7812
0
          poolDiscard(&dtd->pool);
7813
7814
107k
        if (! prefix)
7815
0
          return XML_FALSE;
7816
7817
107k
        poolDiscard(&parser->m_tempPool);
7818
107k
      }
7819
3.97M
      for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0');
7820
3.86M
           context++)
7821
3.86M
        if (! poolAppendChar(&parser->m_tempPool, *context))
7822
0
          return XML_FALSE;
7823
107k
      if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
7824
0
        return XML_FALSE;
7825
107k
      if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool),
7826
107k
                     &parser->m_inheritedBindings)
7827
107k
          != XML_ERROR_NONE)
7828
0
        return XML_FALSE;
7829
107k
      poolDiscard(&parser->m_tempPool);
7830
107k
      if (*context != XML_T('\0'))
7831
0
        ++context;
7832
107k
      s = context;
7833
322k
    } else {
7834
322k
      if (! poolAppendChar(&parser->m_tempPool, *s))
7835
0
        return XML_FALSE;
7836
322k
      s++;
7837
322k
    }
7838
429k
  }
7839
107k
  return XML_TRUE;
7840
107k
}
7841
7842
static void
7843
0
normalizePublicId(XML_Char *publicId) {
7844
0
  XML_Char *p = publicId;
7845
0
  XML_Char *s;
7846
0
  for (s = publicId; *s; s++) {
7847
0
    switch (*s) {
7848
0
    case 0x20:
7849
0
    case 0xD:
7850
0
    case 0xA:
7851
0
      if (p != publicId && p[-1] != 0x20)
7852
0
        *p++ = 0x20;
7853
0
      break;
7854
0
    default:
7855
0
      *p++ = *s;
7856
0
    }
7857
0
  }
7858
0
  if (p != publicId && p[-1] == 0x20)
7859
0
    --p;
7860
0
  *p = XML_T('\0');
7861
0
}
7862
7863
static DTD *
7864
107k
dtdCreate(XML_Parser parser) {
7865
107k
  DTD *p = MALLOC(parser, sizeof(DTD));
7866
107k
  if (p == NULL)
7867
0
    return p;
7868
107k
  poolInit(&(p->pool), parser);
7869
107k
  poolInit(&(p->entityValuePool), parser);
7870
107k
  hashTableInit(&(p->generalEntities), parser);
7871
107k
  hashTableInit(&(p->elementTypes), parser);
7872
107k
  hashTableInit(&(p->attributeIds), parser);
7873
107k
  hashTableInit(&(p->prefixes), parser);
7874
107k
#ifdef XML_DTD
7875
107k
  p->paramEntityRead = false;
7876
107k
  hashTableInit(&(p->paramEntities), parser);
7877
107k
#endif /* XML_DTD */
7878
107k
  p->defaultPrefix.name = NULL;
7879
107k
  p->defaultPrefix.binding = NULL;
7880
7881
107k
  p->in_eldecl = false;
7882
107k
  p->scaffIndex = NULL;
7883
107k
  p->scaffIndexSize = 0;
7884
107k
  p->scaffold = NULL;
7885
107k
  p->scaffLevel = 0;
7886
107k
  p->scaffSize = 0;
7887
107k
  p->scaffCount = 0;
7888
107k
  p->contentStringLen = 0;
7889
7890
107k
  p->keepProcessing = XML_TRUE;
7891
107k
  p->hasParamEntityRefs = XML_FALSE;
7892
107k
  p->standalone = XML_FALSE;
7893
107k
  return p;
7894
107k
}
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
0
#ifdef XML_DTD
7909
0
  p->paramEntityRead = false;
7910
0
  hashTableClear(&(p->paramEntities));
7911
0
#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
107k
dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser) {
7940
107k
  HASH_TABLE_ITER iter;
7941
107k
  hashTableIterInit(&iter, &(p->elementTypes));
7942
168k
  for (;;) {
7943
168k
    ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
7944
168k
    if (! e)
7945
107k
      break;
7946
60.9k
    hashTableDestroy(&(e->defaultAttForName));
7947
60.9k
    FREE(parser, e->defaultAtts);
7948
60.9k
  }
7949
107k
  hashTableDestroy(&(p->generalEntities));
7950
107k
#ifdef XML_DTD
7951
107k
  hashTableDestroy(&(p->paramEntities));
7952
107k
#endif /* XML_DTD */
7953
107k
  hashTableDestroy(&(p->elementTypes));
7954
107k
  hashTableDestroy(&(p->attributeIds));
7955
107k
  hashTableDestroy(&(p->prefixes));
7956
107k
  poolDestroy(&(p->pool));
7957
107k
  poolDestroy(&(p->entityValuePool));
7958
107k
  if (isDocEntity) {
7959
107k
    FREE(parser, p->scaffIndex);
7960
107k
    FREE(parser, p->scaffold);
7961
107k
  }
7962
107k
  FREE(parser, p);
7963
107k
}
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
0
#ifdef XML_DTD
8098
0
  if (! copyEntityTable(oldParser, &(newDtd->paramEntities), &(newDtd->pool),
8099
0
                        &(oldDtd->paramEntities)))
8100
0
    return 0;
8101
0
  newDtd->paramEntityRead = oldDtd->paramEntityRead;
8102
0
#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
300k
#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
248k
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
248k
  return (strncmp(s1, s2, s1len) == 0 && s2[s1len] == '\0') ? XML_TRUE
8201
248k
                                                            : XML_FALSE;
8202
248k
#endif
8203
248k
}
8204
8205
XML_NONTESTING_STATIC size_t
8206
642k
keylen(KEY s) {
8207
642k
  return xcslen(s);
8208
642k
}
8209
8210
static void
8211
607k
copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
8212
607k
  const XML_Parser rootParser = getRootParserOf(parser, NULL);
8213
607k
  assert(! rootParser->m_parentParser);
8214
8215
607k
  *key = rootParser->m_hash_secret_salt_128;
8216
607k
}
8217
8218
static unsigned long
8219
546k
hash(XML_Parser parser, KEY s, size_t keyLen) {
8220
546k
  struct siphash state;
8221
546k
  struct sipkey key;
8222
546k
  (void)sip24_valid;
8223
546k
  copy_salt_to_sipkey(parser, &key);
8224
546k
  sip24_init(&state, &key);
8225
546k
  sip24_update(&state, s, keyLen * sizeof(XML_Char));
8226
546k
  return (unsigned long)sip24_final(&state);
8227
546k
}
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
525k
                 size_t createSize) {
8251
525k
  size_t i;
8252
525k
  if (table->size == 0) {
8253
185k
    size_t tsize;
8254
185k
    if (! createSize)
8255
35.1k
      return NULL;
8256
150k
    table->power = INIT_POWER;
8257
    /* table->size is a power of 2 */
8258
150k
    table->size = (size_t)1 << INIT_POWER;
8259
150k
    tsize = table->size * sizeof(NAMED *);
8260
150k
    table->v = MALLOC(table->parser, tsize);
8261
150k
    if (! table->v) {
8262
0
      table->size = 0;
8263
0
      return NULL;
8264
0
    }
8265
150k
    memset(table->v, 0, tsize);
8266
150k
    i = hash(parser, name, nameLen) & ((unsigned long)table->size - 1);
8267
340k
  } else {
8268
340k
    unsigned long h = hash(parser, name, nameLen);
8269
340k
    unsigned long mask = (unsigned long)table->size - 1;
8270
340k
    unsigned char step = 0;
8271
340k
    i = h & mask;
8272
409k
    while (table->v[i]) {
8273
248k
      if (keyeq(name, nameLen, table->v[i]->name))
8274
179k
        return table->v[i];
8275
68.8k
      if (! step)
8276
49.9k
        step = PROBE_STEP(h, mask, table->power);
8277
68.8k
      i < step ? (i += table->size - step) : (i -= step);
8278
68.8k
    }
8279
160k
    if (! createSize)
8280
26.7k
      return NULL;
8281
8282
    /* check for overflow (table is half full) */
8283
133k
    if (table->used >> (table->power - 1)) {
8284
1.12k
      unsigned char newPower = table->power + 1;
8285
8286
      /* Detect and prevent invalid shift */
8287
1.12k
      if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
8288
0
        return NULL;
8289
0
      }
8290
8291
1.12k
      size_t newSize = (size_t)1 << newPower;
8292
1.12k
      unsigned long newMask = (unsigned long)newSize - 1;
8293
8294
      /* Detect and prevent integer overflow */
8295
1.12k
      if (newSize > SIZE_MAX / sizeof(NAMED *)) {
8296
0
        return NULL;
8297
0
      }
8298
8299
1.12k
      size_t tsize = newSize * sizeof(NAMED *);
8300
1.12k
      NAMED **newV = MALLOC(table->parser, tsize);
8301
1.12k
      if (! newV)
8302
0
        return NULL;
8303
1.12k
      memset(newV, 0, tsize);
8304
111k
      for (i = 0; i < table->size; i++)
8305
110k
        if (table->v[i]) {
8306
55.4k
          KEY const key = table->v[i]->name;
8307
55.4k
          unsigned long newHash = hash(parser, key, keylen(key));
8308
55.4k
          size_t j = newHash & newMask;
8309
55.4k
          step = 0;
8310
63.5k
          while (newV[j]) {
8311
8.11k
            if (! step)
8312
6.65k
              step = PROBE_STEP(newHash, newMask, newPower);
8313
8.11k
            j < step ? (j += newSize - step) : (j -= step);
8314
8.11k
          }
8315
55.4k
          newV[j] = table->v[i];
8316
55.4k
        }
8317
1.12k
      FREE(table->parser, table->v);
8318
1.12k
      table->v = newV;
8319
1.12k
      table->power = newPower;
8320
1.12k
      table->size = newSize;
8321
1.12k
      i = h & newMask;
8322
1.12k
      step = 0;
8323
1.51k
      while (table->v[i]) {
8324
388
        if (! step)
8325
300
          step = PROBE_STEP(h, newMask, newPower);
8326
388
        i < step ? (i += newSize - step) : (i -= step);
8327
388
      }
8328
1.12k
    }
8329
133k
  }
8330
525k
  assert(createSize >= sizeof(NAMED));
8331
283k
  table->v[i] = MALLOC(table->parser, createSize);
8332
283k
  if (! table->v[i])
8333
0
    return NULL;
8334
283k
  memset(table->v[i], 0, createSize);
8335
283k
  table->v[i]->name = name; // NOTE: This requires and assumes zero termination!
8336
283k
  (table->used)++;
8337
283k
  return table->v[i];
8338
283k
}
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
525k
lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
8357
525k
  return lookupWithLength(parser, table, name, keylen(name), createSize);
8358
525k
}
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
597k
hashTableDestroy(HASH_TABLE *table) {
8372
597k
  size_t i;
8373
10.3M
  for (i = 0; i < table->size; i++)
8374
9.72M
    FREE(table->parser, table->v[i]);
8375
597k
  FREE(table->parser, table->v);
8376
597k
}
8377
8378
XML_NONTESTING_STATIC void
8379
597k
hashTableInit(HASH_TABLE *p, XML_Parser parser) {
8380
597k
  p->power = 0;
8381
597k
  p->size = 0;
8382
597k
  p->used = 0;
8383
597k
  p->v = NULL;
8384
597k
  p->parser = parser;
8385
597k
}
8386
8387
XML_NONTESTING_STATIC void
8388
107k
hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
8389
107k
  iter->p = table->v;
8390
107k
  iter->end = iter->p ? iter->p + table->size : NULL;
8391
107k
}
8392
8393
XML_NONTESTING_STATIC NAMED *
8394
168k
hashTableIterNext(HASH_TABLE_ITER *iter) {
8395
2.29M
  while (iter->p != iter->end) {
8396
2.18M
    NAMED *tem = *(iter->p)++;
8397
2.18M
    if (tem)
8398
60.9k
      return tem;
8399
2.18M
  }
8400
107k
  return NULL;
8401
168k
}
8402
8403
static void
8404
429k
poolInit(STRING_POOL *pool, XML_Parser parser) {
8405
429k
  pool->blocks = NULL;
8406
429k
  pool->freeBlocks = NULL;
8407
429k
  pool->start = NULL;
8408
429k
  pool->ptr = NULL;
8409
429k
  pool->end = NULL;
8410
429k
  pool->parser = parser;
8411
429k
}
8412
8413
static void
8414
87.9k
poolClear(STRING_POOL *pool) {
8415
87.9k
  if (! pool->freeBlocks)
8416
47.0k
    pool->freeBlocks = pool->blocks;
8417
40.8k
  else {
8418
40.8k
    BLOCK *p = pool->blocks;
8419
45.3k
    while (p) {
8420
4.53k
      BLOCK *tem = p->next;
8421
4.53k
      p->next = pool->freeBlocks;
8422
4.53k
      pool->freeBlocks = p;
8423
4.53k
      p = tem;
8424
4.53k
    }
8425
40.8k
  }
8426
87.9k
  pool->blocks = NULL;
8427
87.9k
  pool->start = NULL;
8428
87.9k
  pool->ptr = NULL;
8429
87.9k
  pool->end = NULL;
8430
87.9k
}
8431
8432
static void
8433
429k
poolDestroy(STRING_POOL *pool) {
8434
429k
  BLOCK *p = pool->blocks;
8435
609k
  while (p) {
8436
179k
    BLOCK *tem = p->next;
8437
179k
    FREE(pool->parser, p);
8438
179k
    p = tem;
8439
179k
  }
8440
429k
  p = pool->freeBlocks;
8441
470k
  while (p) {
8442
40.6k
    BLOCK *tem = p->next;
8443
40.6k
    FREE(pool->parser, p);
8444
40.6k
    p = tem;
8445
40.6k
  }
8446
429k
}
8447
8448
static XML_Char *
8449
poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
8450
224k
           const char *end) {
8451
224k
  if (! pool->ptr && ! poolGrow(pool))
8452
0
    return NULL;
8453
226k
  for (;;) {
8454
226k
    const enum XML_Convert_Result convert_res = XmlConvert(
8455
226k
        enc, &ptr, end, (ICHAR **)&(pool->ptr), (const ICHAR *)pool->end);
8456
226k
    if ((convert_res == XML_CONVERT_COMPLETED)
8457
1.46k
        || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
8458
224k
      break;
8459
1.46k
    if (! poolGrow(pool))
8460
0
      return NULL;
8461
1.46k
  }
8462
224k
  return pool->start;
8463
224k
}
8464
8465
static const XML_Char *
8466
60.9k
poolCopyString(STRING_POOL *pool, const XML_Char *s) {
8467
60.9k
  if (! poolAppendChars(pool, s, xcslen(s) + /*null terminator*/ 1))
8468
0
    return NULL;
8469
60.9k
  s = pool->start;
8470
60.9k
  poolFinish(pool);
8471
60.9k
  return s;
8472
60.9k
}
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
107k
poolCopyStringNoFinish(STRING_POOL *pool, const XML_Char *s) {
8478
107k
  const XML_Char *const original = s;
8479
429k
  do {
8480
429k
    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
429k
  } while (*s++);
8488
107k
  return pool->start;
8489
107k
}
8490
8491
static const XML_Char *
8492
0
poolCopyStringN(STRING_POOL *pool, const XML_Char *s, size_t 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
0
poolAppendString(STRING_POOL *pool, const XML_Char *s) {
8516
0
  if (! poolAppendChars(pool, s, xcslen(s)))
8517
0
    return NULL;
8518
0
  return pool->start;
8519
0
}
8520
8521
static XML_Char *
8522
poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
8523
198k
                const char *end) {
8524
198k
  if (! poolAppend(pool, enc, ptr, end))
8525
0
    return NULL;
8526
198k
  if (! poolAppendChar(pool, 0))
8527
0
    return NULL;
8528
198k
  return pool->start;
8529
198k
}
8530
8531
static size_t
8532
221k
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
221k
  const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
8541
8542
221k
  if (blockSize <= 0)
8543
0
    return 0;
8544
8545
221k
  if (blockSize > (int)(INT_MAX / stretch))
8546
0
    return 0;
8547
8548
221k
  {
8549
221k
    const int stretchedBlockSize = blockSize * (int)stretch;
8550
221k
    const int bytesToAllocate
8551
221k
        = (int)(offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
8552
221k
    if (bytesToAllocate < 0)
8553
0
      return 0;
8554
8555
221k
    return (size_t)bytesToAllocate;
8556
221k
  }
8557
221k
}
8558
8559
static XML_Bool
8560
237k
poolGrow(STRING_POOL *pool) {
8561
237k
  if (pool->freeBlocks) {
8562
16.1k
    if (pool->start == NULL) {
8563
15.6k
      pool->blocks = pool->freeBlocks;
8564
15.6k
      pool->freeBlocks = pool->freeBlocks->next;
8565
15.6k
      pool->blocks->next = NULL;
8566
15.6k
      pool->start = pool->blocks->s;
8567
15.6k
      pool->end = pool->start + pool->blocks->size;
8568
15.6k
      pool->ptr = pool->start;
8569
15.6k
      return XML_TRUE;
8570
15.6k
    }
8571
511
    if (pool->end - pool->start < pool->freeBlocks->size) {
8572
392
      BLOCK *tem = pool->freeBlocks->next;
8573
392
      pool->freeBlocks->next = pool->blocks;
8574
392
      pool->blocks = pool->freeBlocks;
8575
392
      pool->freeBlocks = tem;
8576
392
      memcpy(pool->blocks->s, pool->start,
8577
392
             (pool->end - pool->start) * sizeof(XML_Char));
8578
392
      pool->ptr = pool->blocks->s + EXPAT_SAFE_PTR_DIFF(pool->ptr, pool->start);
8579
392
      pool->start = pool->blocks->s;
8580
392
      pool->end = pool->start + pool->blocks->size;
8581
392
      return XML_TRUE;
8582
392
    }
8583
511
  }
8584
221k
  if (pool->blocks && pool->start == pool->blocks->s) {
8585
1.27k
    BLOCK *temp;
8586
1.27k
    int blockSize = (int)((unsigned)(pool->end - pool->start) * 2U);
8587
1.27k
    size_t bytesToAllocate;
8588
8589
    /* NOTE: Needs to be calculated prior to calling `realloc`
8590
             to avoid dangling pointers: */
8591
1.27k
    const ptrdiff_t offsetInsideBlock
8592
1.27k
        = EXPAT_SAFE_PTR_DIFF(pool->ptr, pool->start);
8593
8594
1.27k
    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
1.27k
    bytesToAllocate = poolBytesToAllocateFor(blockSize);
8605
1.27k
    if (bytesToAllocate == 0)
8606
0
      return XML_FALSE;
8607
8608
1.27k
    temp = REALLOC(pool->parser, pool->blocks, bytesToAllocate);
8609
1.27k
    if (temp == NULL)
8610
0
      return XML_FALSE;
8611
1.27k
    pool->blocks = temp;
8612
1.27k
    pool->blocks->size = blockSize;
8613
1.27k
    pool->ptr = pool->blocks->s + offsetInsideBlock;
8614
1.27k
    pool->start = pool->blocks->s;
8615
1.27k
    pool->end = pool->start + blockSize;
8616
220k
  } else {
8617
220k
    BLOCK *tem;
8618
220k
    int blockSize = (int)(pool->end - pool->start);
8619
220k
    size_t bytesToAllocate;
8620
8621
220k
    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
220k
    if (blockSize < INIT_BLOCK_SIZE)
8635
220k
      blockSize = INIT_BLOCK_SIZE;
8636
149
    else {
8637
      /* Detect overflow, avoiding _signed_ overflow undefined behavior */
8638
149
      if ((int)((unsigned)blockSize * 2U) < 0) {
8639
0
        return XML_FALSE;
8640
0
      }
8641
149
      blockSize *= 2;
8642
149
    }
8643
8644
220k
    bytesToAllocate = poolBytesToAllocateFor(blockSize);
8645
220k
    if (bytesToAllocate == 0)
8646
0
      return XML_FALSE;
8647
8648
220k
    tem = MALLOC(pool->parser, bytesToAllocate);
8649
220k
    if (! tem)
8650
0
      return XML_FALSE;
8651
220k
    tem->size = blockSize;
8652
220k
    tem->next = pool->blocks;
8653
220k
    pool->blocks = tem;
8654
220k
    if (pool->ptr != pool->start)
8655
1.97k
      memcpy(tem->s, pool->start,
8656
1.97k
             EXPAT_SAFE_PTR_DIFF(pool->ptr, pool->start) * sizeof(XML_Char));
8657
220k
    pool->ptr = tem->s + EXPAT_SAFE_PTR_DIFF(pool->ptr, pool->start);
8658
220k
    pool->start = tem->s;
8659
220k
    pool->end = tem->s + blockSize;
8660
220k
  }
8661
221k
  return XML_TRUE;
8662
221k
}
8663
8664
static bool
8665
242k
poolGrowUntil(STRING_POOL *pool, size_t needed) {
8666
247k
  for (;;) {
8667
247k
    const size_t available = pool->end - pool->ptr;
8668
247k
    if (available >= needed) {
8669
242k
      return true;
8670
242k
    }
8671
5.37k
    if (! poolGrow(pool)) {
8672
0
      return false;
8673
0
    }
8674
5.37k
  }
8675
242k
}
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
0
               const char *end) {
8889
0
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
8890
0
  const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
8891
0
  ELEMENT_TYPE *ret;
8892
8893
0
  if (! name)
8894
0
    return NULL;
8895
0
  ret = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
8896
0
                               sizeof(ELEMENT_TYPE));
8897
0
  if (! ret)
8898
0
    return NULL;
8899
0
  if (! ret->defaultAttForName.parser)
8900
0
    hashTableInit(&(ret->defaultAttForName), getRootParserOf(parser, NULL));
8901
0
  if (ret->name != name)
8902
0
    poolDiscard(&dtd->pool);
8903
0
  else {
8904
0
    poolFinish(&dtd->pool);
8905
0
    if (! setElementTypePrefix(parser, ret))
8906
0
      return NULL;
8907
0
  }
8908
0
  return ret;
8909
0
}
8910
8911
static XML_Char *
8912
1
copyString(const XML_Char *s, XML_Parser parser) {
8913
  /* First determine how long the string is */
8914
1
  const size_t charsRequired = xcslen(s) + /*null terminator*/ 1;
8915
8916
  /* Detect and prevent integer overflow */
8917
1
  if (charsRequired > SIZE_MAX / sizeof(XML_Char))
8918
0
    return NULL;
8919
8920
1
  const size_t bytesRequired = charsRequired * sizeof(XML_Char);
8921
8922
  /* Now allocate space for the copy */
8923
1
  XML_Char *const result = MALLOC(parser, bytesRequired);
8924
8925
1
  if (result == NULL)
8926
0
    return NULL;
8927
8928
  /* Copy the original into place */
8929
1
  memcpy(result, s, bytesRequired);
8930
8931
1
  return result;
8932
1
}
8933
8934
#if XML_GE == 1
8935
8936
static float
8937
950k
accountingGetCurrentAmplification(XML_Parser rootParser) {
8938
  //                                          1.........1.........12 => 22
8939
950k
  const size_t lenOfShortestInclude = sizeof("<!ENTITY a SYSTEM 'b'>") - 1;
8940
950k
  const XmlBigCount countBytesOutput
8941
950k
      = rootParser->m_accounting.countBytesDirect
8942
950k
        + rootParser->m_accounting.countBytesIndirect;
8943
950k
  const float amplificationFactor
8944
950k
      = rootParser->m_accounting.countBytesDirect
8945
950k
            ? ((float)countBytesOutput
8946
950k
               / (float)(rootParser->m_accounting.countBytesDirect))
8947
950k
            : ((float)(lenOfShortestInclude
8948
0
                       + rootParser->m_accounting.countBytesIndirect)
8949
0
               / (float)lenOfShortestInclude);
8950
950k
  assert(! rootParser->m_parentParser);
8951
950k
  return amplificationFactor;
8952
950k
}
8953
8954
static void
8955
0
accountingReportStats(XML_Parser originParser, const char *epilog) {
8956
0
  const XML_Parser rootParser = getRootParserOf(originParser, NULL);
8957
0
  assert(! rootParser->m_parentParser);
8958
8959
0
  if (rootParser->m_accounting.debugLevel == 0u) {
8960
0
    return;
8961
0
  }
8962
8963
0
  const float amplificationFactor
8964
0
      = accountingGetCurrentAmplification(rootParser);
8965
0
  fprintf(stderr,
8966
0
          "expat: Accounting(%p): Direct " EXPAT_FMT_ULL(
8967
0
              "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s",
8968
0
          (void *)rootParser, rootParser->m_accounting.countBytesDirect,
8969
0
          rootParser->m_accounting.countBytesIndirect,
8970
0
          (double)amplificationFactor, epilog);
8971
0
}
8972
8973
static void
8974
0
accountingOnAbort(XML_Parser originParser) {
8975
0
  accountingReportStats(originParser, " ABORTING\n");
8976
0
}
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
0
                     enum XML_Account account) {
8983
0
  assert(! rootParser->m_parentParser);
8984
8985
0
  fprintf(stderr,
8986
0
          " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%u, xmlparse.c:%d) %*s\"",
8987
0
          bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP",
8988
0
          levelsAwayFromRootParser, source_line, 10, "");
8989
8990
0
  const char ellipis[] = "[..]";
8991
0
  const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1;
8992
0
  const unsigned int contextLength = 10;
8993
8994
  /* Note: Performance is of no concern here */
8995
0
  const char *walker = before;
8996
0
  if ((rootParser->m_accounting.debugLevel >= 3u)
8997
0
      || (after - before)
8998
0
             <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) {
8999
0
    for (; walker < after; walker++) {
9000
0
      fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
9001
0
    }
9002
0
  } else {
9003
0
    for (; walker < before + contextLength; walker++) {
9004
0
      fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
9005
0
    }
9006
0
    fprintf(stderr, ellipis);
9007
0
    walker = after - contextLength;
9008
0
    for (; walker < after; walker++) {
9009
0
      fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
9010
0
    }
9011
0
  }
9012
0
  fprintf(stderr, "\"\n");
9013
0
}
9014
9015
static XML_Bool
9016
accountingDiffTolerated(XML_Parser originParser, int tok, const char *before,
9017
                        const char *after, int source_line,
9018
1.09M
                        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
1.09M
  switch (tok) {
9023
32.1k
  case XML_TOK_INVALID:
9024
38.8k
  case XML_TOK_PARTIAL:
9025
43.2k
  case XML_TOK_PARTIAL_CHAR:
9026
58.6k
  case XML_TOK_NONE:
9027
58.6k
    return XML_TRUE;
9028
1.09M
  }
9029
9030
1.03M
  if (account == XML_ACCOUNT_NONE)
9031
83.8k
    return XML_TRUE; /* because these bytes have been accounted for, already */
9032
9033
950k
  unsigned int levelsAwayFromRootParser;
9034
950k
  const XML_Parser rootParser
9035
950k
      = getRootParserOf(originParser, &levelsAwayFromRootParser);
9036
950k
  assert(! rootParser->m_parentParser);
9037
9038
950k
  const int isDirect
9039
950k
      = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser);
9040
950k
  const ptrdiff_t bytesMore = after - before;
9041
9042
950k
  XmlBigCount *const additionTarget
9043
950k
      = isDirect ? &rootParser->m_accounting.countBytesDirect
9044
950k
                 : &rootParser->m_accounting.countBytesIndirect;
9045
9046
  /* Detect and avoid integer overflow */
9047
950k
  if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore)
9048
0
    return XML_FALSE;
9049
950k
  *additionTarget += bytesMore;
9050
9051
950k
  const XmlBigCount countBytesOutput
9052
950k
      = rootParser->m_accounting.countBytesDirect
9053
950k
        + rootParser->m_accounting.countBytesIndirect;
9054
950k
  const float amplificationFactor
9055
950k
      = accountingGetCurrentAmplification(rootParser);
9056
950k
  const XML_Bool tolerated
9057
950k
      = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes)
9058
459
        || (amplificationFactor
9059
459
            <= rootParser->m_accounting.maximumAmplificationFactor);
9060
9061
950k
  if (rootParser->m_accounting.debugLevel >= 2u) {
9062
0
    accountingReportStats(rootParser, "");
9063
0
    accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after,
9064
0
                         bytesMore, source_line, account);
9065
0
  }
9066
9067
950k
  return tolerated;
9068
950k
}
9069
9070
unsigned long long
9071
0
testingAccountingGetCountBytesDirect(XML_Parser parser) {
9072
0
  if (! parser)
9073
0
    return 0;
9074
0
  return parser->m_accounting.countBytesDirect;
9075
0
}
9076
9077
unsigned long long
9078
0
testingAccountingGetCountBytesIndirect(XML_Parser parser) {
9079
0
  if (! parser)
9080
0
    return 0;
9081
0
  return parser->m_accounting.countBytesIndirect;
9082
0
}
9083
9084
static void
9085
entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
9086
0
                          const char *action, int sourceLine) {
9087
0
  assert(! rootParser->m_parentParser);
9088
0
  if (rootParser->m_entity_stats.debugLevel == 0u)
9089
0
    return;
9090
9091
#  if defined(XML_UNICODE)
9092
  const char *const entityName = "[..]";
9093
#  else
9094
0
  const char *const entityName = entity->name;
9095
0
#  endif
9096
9097
0
  const bool limitingWanted = rootParser->m_entity_stats.debugLevel < 2;
9098
0
  const int maxLimitedDepth = 10; // somewhat arbitrary
9099
0
  const int candidateIndentDepth
9100
0
      = (int)rootParser->m_entity_stats.currentDepth - 1;
9101
0
  const bool limitingNeeded
9102
0
      = limitingWanted && (candidateIndentDepth > maxLimitedDepth);
9103
0
  const char *const ellipisOrEmpty = limitingNeeded ? " [..] " : "";
9104
0
  const int indentDepth
9105
0
      = limitingNeeded ? (maxLimitedDepth - /* make space for ellipis */ 2)
9106
0
                       : candidateIndentDepth;
9107
9108
0
  fprintf(
9109
0
      stderr,
9110
0
      "expat: Entities(%p): Count %9u, depth %2u/%2u %*s%s%s%s; %s length " EXPAT_FMT_SIZE_T(
9111
0
          "") " (xmlparse.c:%d)\n",
9112
0
      (void *)rootParser, rootParser->m_entity_stats.countEverOpened,
9113
0
      rootParser->m_entity_stats.currentDepth,
9114
0
      rootParser->m_entity_stats.maximumDepthSeen, indentDepth * 2, "",
9115
0
      ellipisOrEmpty, entity->is_param ? "%" : "&", entityName, action,
9116
0
      entity->textLen, sourceLine);
9117
0
}
9118
9119
static void
9120
0
entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) {
9121
0
  const XML_Parser rootParser = getRootParserOf(originParser, NULL);
9122
0
  assert(! rootParser->m_parentParser);
9123
9124
0
  rootParser->m_entity_stats.countEverOpened++;
9125
0
  rootParser->m_entity_stats.currentDepth++;
9126
0
  if (rootParser->m_entity_stats.currentDepth
9127
0
      > rootParser->m_entity_stats.maximumDepthSeen) {
9128
0
    rootParser->m_entity_stats.maximumDepthSeen++;
9129
0
  }
9130
9131
0
  entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine);
9132
0
}
9133
9134
static void
9135
0
entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) {
9136
0
  const XML_Parser rootParser = getRootParserOf(originParser, NULL);
9137
0
  assert(! rootParser->m_parentParser);
9138
9139
0
  entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine);
9140
0
  rootParser->m_entity_stats.currentDepth--;
9141
0
}
9142
9143
#endif /* XML_GE == 1 */
9144
9145
static XML_Parser
9146
4.47M
getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {
9147
4.47M
  XML_Parser rootParser = parser;
9148
4.47M
  unsigned int stepsTakenUpwards = 0;
9149
4.47M
  while (rootParser->m_parentParser) {
9150
0
    rootParser = rootParser->m_parentParser;
9151
0
    stepsTakenUpwards++;
9152
0
  }
9153
4.47M
  assert(! rootParser->m_parentParser);
9154
4.47M
  if (outLevelDiff != NULL) {
9155
950k
    *outLevelDiff = stepsTakenUpwards;
9156
950k
  }
9157
4.47M
  return rootParser;
9158
4.47M
}
9159
9160
#if XML_GE == 1
9161
9162
const char *
9163
0
unsignedCharToPrintable(unsigned char c) {
9164
0
  switch (c) {
9165
0
  case 0:
9166
0
    return "\\0";
9167
0
  case 1:
9168
0
    return "\\x1";
9169
0
  case 2:
9170
0
    return "\\x2";
9171
0
  case 3:
9172
0
    return "\\x3";
9173
0
  case 4:
9174
0
    return "\\x4";
9175
0
  case 5:
9176
0
    return "\\x5";
9177
0
  case 6:
9178
0
    return "\\x6";
9179
0
  case 7:
9180
0
    return "\\x7";
9181
0
  case 8:
9182
0
    return "\\x8";
9183
0
  case 9:
9184
0
    return "\\t";
9185
0
  case 10:
9186
0
    return "\\n";
9187
0
  case 11:
9188
0
    return "\\xB";
9189
0
  case 12:
9190
0
    return "\\xC";
9191
0
  case 13:
9192
0
    return "\\r";
9193
0
  case 14:
9194
0
    return "\\xE";
9195
0
  case 15:
9196
0
    return "\\xF";
9197
0
  case 16:
9198
0
    return "\\x10";
9199
0
  case 17:
9200
0
    return "\\x11";
9201
0
  case 18:
9202
0
    return "\\x12";
9203
0
  case 19:
9204
0
    return "\\x13";
9205
0
  case 20:
9206
0
    return "\\x14";
9207
0
  case 21:
9208
0
    return "\\x15";
9209
0
  case 22:
9210
0
    return "\\x16";
9211
0
  case 23:
9212
0
    return "\\x17";
9213
0
  case 24:
9214
0
    return "\\x18";
9215
0
  case 25:
9216
0
    return "\\x19";
9217
0
  case 26:
9218
0
    return "\\x1A";
9219
0
  case 27:
9220
0
    return "\\x1B";
9221
0
  case 28:
9222
0
    return "\\x1C";
9223
0
  case 29:
9224
0
    return "\\x1D";
9225
0
  case 30:
9226
0
    return "\\x1E";
9227
0
  case 31:
9228
0
    return "\\x1F";
9229
0
  case 32:
9230
0
    return " ";
9231
0
  case 33:
9232
0
    return "!";
9233
0
  case 34:
9234
0
    return "\\\"";
9235
0
  case 35:
9236
0
    return "#";
9237
0
  case 36:
9238
0
    return "$";
9239
0
  case 37:
9240
0
    return "%";
9241
0
  case 38:
9242
0
    return "&";
9243
0
  case 39:
9244
0
    return "'";
9245
0
  case 40:
9246
0
    return "(";
9247
0
  case 41:
9248
0
    return ")";
9249
0
  case 42:
9250
0
    return "*";
9251
0
  case 43:
9252
0
    return "+";
9253
0
  case 44:
9254
0
    return ",";
9255
0
  case 45:
9256
0
    return "-";
9257
0
  case 46:
9258
0
    return ".";
9259
0
  case 47:
9260
0
    return "/";
9261
0
  case 48:
9262
0
    return "0";
9263
0
  case 49:
9264
0
    return "1";
9265
0
  case 50:
9266
0
    return "2";
9267
0
  case 51:
9268
0
    return "3";
9269
0
  case 52:
9270
0
    return "4";
9271
0
  case 53:
9272
0
    return "5";
9273
0
  case 54:
9274
0
    return "6";
9275
0
  case 55:
9276
0
    return "7";
9277
0
  case 56:
9278
0
    return "8";
9279
0
  case 57:
9280
0
    return "9";
9281
0
  case 58:
9282
0
    return ":";
9283
0
  case 59:
9284
0
    return ";";
9285
0
  case 60:
9286
0
    return "<";
9287
0
  case 61:
9288
0
    return "=";
9289
0
  case 62:
9290
0
    return ">";
9291
0
  case 63:
9292
0
    return "?";
9293
0
  case 64:
9294
0
    return "@";
9295
0
  case 65:
9296
0
    return "A";
9297
0
  case 66:
9298
0
    return "B";
9299
0
  case 67:
9300
0
    return "C";
9301
0
  case 68:
9302
0
    return "D";
9303
0
  case 69:
9304
0
    return "E";
9305
0
  case 70:
9306
0
    return "F";
9307
0
  case 71:
9308
0
    return "G";
9309
0
  case 72:
9310
0
    return "H";
9311
0
  case 73:
9312
0
    return "I";
9313
0
  case 74:
9314
0
    return "J";
9315
0
  case 75:
9316
0
    return "K";
9317
0
  case 76:
9318
0
    return "L";
9319
0
  case 77:
9320
0
    return "M";
9321
0
  case 78:
9322
0
    return "N";
9323
0
  case 79:
9324
0
    return "O";
9325
0
  case 80:
9326
0
    return "P";
9327
0
  case 81:
9328
0
    return "Q";
9329
0
  case 82:
9330
0
    return "R";
9331
0
  case 83:
9332
0
    return "S";
9333
0
  case 84:
9334
0
    return "T";
9335
0
  case 85:
9336
0
    return "U";
9337
0
  case 86:
9338
0
    return "V";
9339
0
  case 87:
9340
0
    return "W";
9341
0
  case 88:
9342
0
    return "X";
9343
0
  case 89:
9344
0
    return "Y";
9345
0
  case 90:
9346
0
    return "Z";
9347
0
  case 91:
9348
0
    return "[";
9349
0
  case 92:
9350
0
    return "\\\\";
9351
0
  case 93:
9352
0
    return "]";
9353
0
  case 94:
9354
0
    return "^";
9355
0
  case 95:
9356
0
    return "_";
9357
0
  case 96:
9358
0
    return "`";
9359
0
  case 97:
9360
0
    return "a";
9361
0
  case 98:
9362
0
    return "b";
9363
0
  case 99:
9364
0
    return "c";
9365
0
  case 100:
9366
0
    return "d";
9367
0
  case 101:
9368
0
    return "e";
9369
0
  case 102:
9370
0
    return "f";
9371
0
  case 103:
9372
0
    return "g";
9373
0
  case 104:
9374
0
    return "h";
9375
0
  case 105:
9376
0
    return "i";
9377
0
  case 106:
9378
0
    return "j";
9379
0
  case 107:
9380
0
    return "k";
9381
0
  case 108:
9382
0
    return "l";
9383
0
  case 109:
9384
0
    return "m";
9385
0
  case 110:
9386
0
    return "n";
9387
0
  case 111:
9388
0
    return "o";
9389
0
  case 112:
9390
0
    return "p";
9391
0
  case 113:
9392
0
    return "q";
9393
0
  case 114:
9394
0
    return "r";
9395
0
  case 115:
9396
0
    return "s";
9397
0
  case 116:
9398
0
    return "t";
9399
0
  case 117:
9400
0
    return "u";
9401
0
  case 118:
9402
0
    return "v";
9403
0
  case 119:
9404
0
    return "w";
9405
0
  case 120:
9406
0
    return "x";
9407
0
  case 121:
9408
0
    return "y";
9409
0
  case 122:
9410
0
    return "z";
9411
0
  case 123:
9412
0
    return "{";
9413
0
  case 124:
9414
0
    return "|";
9415
0
  case 125:
9416
0
    return "}";
9417
0
  case 126:
9418
0
    return "~";
9419
0
  case 127:
9420
0
    return "\\x7F";
9421
0
  case 128:
9422
0
    return "\\x80";
9423
0
  case 129:
9424
0
    return "\\x81";
9425
0
  case 130:
9426
0
    return "\\x82";
9427
0
  case 131:
9428
0
    return "\\x83";
9429
0
  case 132:
9430
0
    return "\\x84";
9431
0
  case 133:
9432
0
    return "\\x85";
9433
0
  case 134:
9434
0
    return "\\x86";
9435
0
  case 135:
9436
0
    return "\\x87";
9437
0
  case 136:
9438
0
    return "\\x88";
9439
0
  case 137:
9440
0
    return "\\x89";
9441
0
  case 138:
9442
0
    return "\\x8A";
9443
0
  case 139:
9444
0
    return "\\x8B";
9445
0
  case 140:
9446
0
    return "\\x8C";
9447
0
  case 141:
9448
0
    return "\\x8D";
9449
0
  case 142:
9450
0
    return "\\x8E";
9451
0
  case 143:
9452
0
    return "\\x8F";
9453
0
  case 144:
9454
0
    return "\\x90";
9455
0
  case 145:
9456
0
    return "\\x91";
9457
0
  case 146:
9458
0
    return "\\x92";
9459
0
  case 147:
9460
0
    return "\\x93";
9461
0
  case 148:
9462
0
    return "\\x94";
9463
0
  case 149:
9464
0
    return "\\x95";
9465
0
  case 150:
9466
0
    return "\\x96";
9467
0
  case 151:
9468
0
    return "\\x97";
9469
0
  case 152:
9470
0
    return "\\x98";
9471
0
  case 153:
9472
0
    return "\\x99";
9473
0
  case 154:
9474
0
    return "\\x9A";
9475
0
  case 155:
9476
0
    return "\\x9B";
9477
0
  case 156:
9478
0
    return "\\x9C";
9479
0
  case 157:
9480
0
    return "\\x9D";
9481
0
  case 158:
9482
0
    return "\\x9E";
9483
0
  case 159:
9484
0
    return "\\x9F";
9485
0
  case 160:
9486
0
    return "\\xA0";
9487
0
  case 161:
9488
0
    return "\\xA1";
9489
0
  case 162:
9490
0
    return "\\xA2";
9491
0
  case 163:
9492
0
    return "\\xA3";
9493
0
  case 164:
9494
0
    return "\\xA4";
9495
0
  case 165:
9496
0
    return "\\xA5";
9497
0
  case 166:
9498
0
    return "\\xA6";
9499
0
  case 167:
9500
0
    return "\\xA7";
9501
0
  case 168:
9502
0
    return "\\xA8";
9503
0
  case 169:
9504
0
    return "\\xA9";
9505
0
  case 170:
9506
0
    return "\\xAA";
9507
0
  case 171:
9508
0
    return "\\xAB";
9509
0
  case 172:
9510
0
    return "\\xAC";
9511
0
  case 173:
9512
0
    return "\\xAD";
9513
0
  case 174:
9514
0
    return "\\xAE";
9515
0
  case 175:
9516
0
    return "\\xAF";
9517
0
  case 176:
9518
0
    return "\\xB0";
9519
0
  case 177:
9520
0
    return "\\xB1";
9521
0
  case 178:
9522
0
    return "\\xB2";
9523
0
  case 179:
9524
0
    return "\\xB3";
9525
0
  case 180:
9526
0
    return "\\xB4";
9527
0
  case 181:
9528
0
    return "\\xB5";
9529
0
  case 182:
9530
0
    return "\\xB6";
9531
0
  case 183:
9532
0
    return "\\xB7";
9533
0
  case 184:
9534
0
    return "\\xB8";
9535
0
  case 185:
9536
0
    return "\\xB9";
9537
0
  case 186:
9538
0
    return "\\xBA";
9539
0
  case 187:
9540
0
    return "\\xBB";
9541
0
  case 188:
9542
0
    return "\\xBC";
9543
0
  case 189:
9544
0
    return "\\xBD";
9545
0
  case 190:
9546
0
    return "\\xBE";
9547
0
  case 191:
9548
0
    return "\\xBF";
9549
0
  case 192:
9550
0
    return "\\xC0";
9551
0
  case 193:
9552
0
    return "\\xC1";
9553
0
  case 194:
9554
0
    return "\\xC2";
9555
0
  case 195:
9556
0
    return "\\xC3";
9557
0
  case 196:
9558
0
    return "\\xC4";
9559
0
  case 197:
9560
0
    return "\\xC5";
9561
0
  case 198:
9562
0
    return "\\xC6";
9563
0
  case 199:
9564
0
    return "\\xC7";
9565
0
  case 200:
9566
0
    return "\\xC8";
9567
0
  case 201:
9568
0
    return "\\xC9";
9569
0
  case 202:
9570
0
    return "\\xCA";
9571
0
  case 203:
9572
0
    return "\\xCB";
9573
0
  case 204:
9574
0
    return "\\xCC";
9575
0
  case 205:
9576
0
    return "\\xCD";
9577
0
  case 206:
9578
0
    return "\\xCE";
9579
0
  case 207:
9580
0
    return "\\xCF";
9581
0
  case 208:
9582
0
    return "\\xD0";
9583
0
  case 209:
9584
0
    return "\\xD1";
9585
0
  case 210:
9586
0
    return "\\xD2";
9587
0
  case 211:
9588
0
    return "\\xD3";
9589
0
  case 212:
9590
0
    return "\\xD4";
9591
0
  case 213:
9592
0
    return "\\xD5";
9593
0
  case 214:
9594
0
    return "\\xD6";
9595
0
  case 215:
9596
0
    return "\\xD7";
9597
0
  case 216:
9598
0
    return "\\xD8";
9599
0
  case 217:
9600
0
    return "\\xD9";
9601
0
  case 218:
9602
0
    return "\\xDA";
9603
0
  case 219:
9604
0
    return "\\xDB";
9605
0
  case 220:
9606
0
    return "\\xDC";
9607
0
  case 221:
9608
0
    return "\\xDD";
9609
0
  case 222:
9610
0
    return "\\xDE";
9611
0
  case 223:
9612
0
    return "\\xDF";
9613
0
  case 224:
9614
0
    return "\\xE0";
9615
0
  case 225:
9616
0
    return "\\xE1";
9617
0
  case 226:
9618
0
    return "\\xE2";
9619
0
  case 227:
9620
0
    return "\\xE3";
9621
0
  case 228:
9622
0
    return "\\xE4";
9623
0
  case 229:
9624
0
    return "\\xE5";
9625
0
  case 230:
9626
0
    return "\\xE6";
9627
0
  case 231:
9628
0
    return "\\xE7";
9629
0
  case 232:
9630
0
    return "\\xE8";
9631
0
  case 233:
9632
0
    return "\\xE9";
9633
0
  case 234:
9634
0
    return "\\xEA";
9635
0
  case 235:
9636
0
    return "\\xEB";
9637
0
  case 236:
9638
0
    return "\\xEC";
9639
0
  case 237:
9640
0
    return "\\xED";
9641
0
  case 238:
9642
0
    return "\\xEE";
9643
0
  case 239:
9644
0
    return "\\xEF";
9645
0
  case 240:
9646
0
    return "\\xF0";
9647
0
  case 241:
9648
0
    return "\\xF1";
9649
0
  case 242:
9650
0
    return "\\xF2";
9651
0
  case 243:
9652
0
    return "\\xF3";
9653
0
  case 244:
9654
0
    return "\\xF4";
9655
0
  case 245:
9656
0
    return "\\xF5";
9657
0
  case 246:
9658
0
    return "\\xF6";
9659
0
  case 247:
9660
0
    return "\\xF7";
9661
0
  case 248:
9662
0
    return "\\xF8";
9663
0
  case 249:
9664
0
    return "\\xF9";
9665
0
  case 250:
9666
0
    return "\\xFA";
9667
0
  case 251:
9668
0
    return "\\xFB";
9669
0
  case 252:
9670
0
    return "\\xFC";
9671
0
  case 253:
9672
0
    return "\\xFD";
9673
0
  case 254:
9674
0
    return "\\xFE";
9675
0
  case 255:
9676
0
    return "\\xFF";
9677
  // LCOV_EXCL_START
9678
0
  default:
9679
0
    assert(0); /* never gets here */
9680
0
    return "dead code";
9681
0
  }
9682
0
  assert(0); /* never gets here */
9683
  // LCOV_EXCL_STOP
9684
0
}
9685
9686
#endif /* XML_GE == 1 */
9687
9688
static unsigned long
9689
429k
getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {
9690
429k
  const char *const valueOrNull = getenv(variableName);
9691
429k
  if (valueOrNull == NULL) {
9692
429k
    return defaultDebugLevel;
9693
429k
  }
9694
0
  const char *const value = valueOrNull;
9695
9696
0
  errno = 0;
9697
0
  char *afterValue = NULL;
9698
0
  unsigned long debugLevel = strtoul(value, &afterValue, 10);
9699
0
  if ((errno != 0) || (afterValue == value) || (afterValue[0] != '\0')) {
9700
0
    errno = 0;
9701
0
    return defaultDebugLevel;
9702
0
  }
9703
9704
0
  return debugLevel;
9705
0
}