Coverage Report

Created: 2025-11-16 09:57

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