Coverage Report

Created: 2026-02-09 06:05

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