Coverage Report

Created: 2026-07-10 11:04

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