Coverage Report

Created: 2026-02-14 09:37

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