Coverage Report

Created: 2026-05-16 09:25

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