Coverage Report

Created: 2026-03-12 07:14

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