Coverage Report

Created: 2026-03-31 11:00

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