Coverage Report

Created: 2023-06-07 06:17

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