Coverage Report

Created: 2026-04-09 11:41

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