Coverage Report

Created: 2024-05-20 06:20

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