Coverage Report

Created: 2025-12-31 10:39

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