Coverage Report

Created: 2026-04-29 07:00

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