Coverage Report

Created: 2026-05-31 06:50

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