Coverage Report

Created: 2026-01-25 07:18

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