Coverage Report

Created: 2025-07-07 10:01

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