Coverage Report

Created: 2024-07-27 06:44

/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
53.1M
#  define XmlConvert XmlUtf8Convert
157
10.0k
#  define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
158
#  define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
159
64.1k
#  define XmlEncode XmlUtf8Encode
160
781k
#  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
3.75M
#  define XML_T(x) x
187
7.91k
#  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
111k
#define ROUND_UP(n, sz) (((n) + ((sz)-1)) & ~((sz)-1))
193
194
/* Do safe (NULL-aware) pointer arithmetic */
195
50.0k
#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
718k
  ((((hash) & ~(mask)) >> ((power)-1)) & ((mask) >> 2))
229
#define PROBE_STEP(hash, mask, power)                                          \
230
718k
  ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
231
232
typedef struct {
233
  NAMED **p;
234
  NAMED **end;
235
} HASH_TABLE_ITER;
236
237
2.20M
#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
238
10.0k
#define INIT_DATA_BUF_SIZE 1024
239
10.8k
#define INIT_ATTS_SIZE 16
240
0
#define INIT_ATTS_VERSION 0xFFFFFFFF
241
43.4k
#define INIT_BLOCK_SIZE 1024
242
10.0k
#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
48.0k
#define poolStart(pool) ((pool)->start)
592
#define poolEnd(pool) ((pool)->ptr)
593
151k
#define poolLength(pool) ((pool)->ptr - (pool)->start)
594
2.18k
#define poolChop(pool) ((void)--(pool->ptr))
595
104k
#define poolLastChar(pool) (((pool)->ptr)[-1])
596
28.5M
#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
597
352k
#define poolFinish(pool) ((pool)->start = (pool)->ptr)
598
#define poolAppendChar(pool, c)                                                \
599
90.8M
  (((pool)->ptr == (pool)->end && ! poolGrow(pool))                            \
600
90.8M
       ? 0                                                                     \
601
90.8M
       : ((*((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
4.43M
#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
711
3.23k
#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
712
4.48M
#define FREE(parser, p) (parser->m_mem.free_fcn((p)))
713
714
XML_Parser XMLCALL
715
10.0k
XML_ParserCreate(const XML_Char *encodingName) {
716
10.0k
  return XML_ParserCreate_MM(encodingName, NULL, NULL);
717
10.0k
}
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
10.0k
writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
744
10.0k
  int success = 0; /* full count bytes written? */
745
10.0k
  size_t bytesWrittenTotal = 0;
746
10.0k
  const unsigned int getrandomFlags = GRND_NONBLOCK;
747
748
10.0k
  do {
749
10.0k
    void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
750
10.0k
    const size_t bytesToWrite = count - bytesWrittenTotal;
751
752
10.0k
    const int bytesWrittenMore =
753
10.0k
#    if defined(HAVE_GETRANDOM)
754
10.0k
        getrandom(currentTarget, bytesToWrite, getrandomFlags);
755
#    else
756
        syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
757
#    endif
758
759
10.0k
    if (bytesWrittenMore > 0) {
760
10.0k
      bytesWrittenTotal += bytesWrittenMore;
761
10.0k
      if (bytesWrittenTotal >= count)
762
10.0k
        success = 1;
763
10.0k
    }
764
10.0k
  } while (! success && (errno == EINTR));
765
766
10.0k
  return success;
767
10.0k
}
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
10.0k
ENTROPY_DEBUG(const char *label, unsigned long entropy) {
891
10.0k
  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
10.0k
  return entropy;
896
10.0k
}
897
898
static unsigned long
899
10.0k
generate_hash_secret_salt(XML_Parser parser) {
900
10.0k
  unsigned long entropy;
901
10.0k
  (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
10.0k
  if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
918
10.0k
    return ENTROPY_DEBUG("getrandom", entropy);
919
10.0k
  }
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
31.0M
get_hash_secret_salt(XML_Parser parser) {
943
31.0M
  if (parser->m_parentParser != NULL)
944
0
    return get_hash_secret_salt(parser->m_parentParser);
945
31.0M
  return parser->m_hash_secret_salt;
946
31.0M
}
947
948
static XML_Bool /* only valid for root parser */
949
10.0k
startParsing(XML_Parser parser) {
950
  /* hash functions must be initialized before setContext() is called */
951
10.0k
  if (parser->m_hash_secret_salt == 0)
952
10.0k
    parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
953
10.0k
  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
10.0k
  return XML_TRUE;
960
10.0k
}
961
962
XML_Parser XMLCALL
963
XML_ParserCreate_MM(const XML_Char *encodingName,
964
                    const XML_Memory_Handling_Suite *memsuite,
965
10.0k
                    const XML_Char *nameSep) {
966
10.0k
  return parserCreate(encodingName, memsuite, nameSep, NULL);
967
10.0k
}
968
969
static XML_Parser
970
parserCreate(const XML_Char *encodingName,
971
             const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep,
972
10.0k
             DTD *dtd) {
973
10.0k
  XML_Parser parser;
974
975
10.0k
  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
10.0k
  } else {
985
10.0k
    XML_Memory_Handling_Suite *mtemp;
986
10.0k
    parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
987
10.0k
    if (parser != NULL) {
988
10.0k
      mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
989
10.0k
      mtemp->malloc_fcn = malloc;
990
10.0k
      mtemp->realloc_fcn = realloc;
991
10.0k
      mtemp->free_fcn = free;
992
10.0k
    }
993
10.0k
  }
994
995
10.0k
  if (! parser)
996
0
    return parser;
997
998
10.0k
  parser->m_buffer = NULL;
999
10.0k
  parser->m_bufferLim = NULL;
1000
1001
10.0k
  parser->m_attsSize = INIT_ATTS_SIZE;
1002
10.0k
  parser->m_atts
1003
10.0k
      = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
1004
10.0k
  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
10.0k
  parser->m_dataBuf
1018
10.0k
      = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
1019
10.0k
  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
10.0k
  parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
1028
1029
10.0k
  if (dtd)
1030
0
    parser->m_dtd = dtd;
1031
10.0k
  else {
1032
10.0k
    parser->m_dtd = dtdCreate(&parser->m_mem);
1033
10.0k
    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
10.0k
  }
1043
1044
10.0k
  parser->m_freeBindingList = NULL;
1045
10.0k
  parser->m_freeTagList = NULL;
1046
10.0k
  parser->m_freeInternalEntities = NULL;
1047
1048
10.0k
  parser->m_groupSize = 0;
1049
10.0k
  parser->m_groupConnector = NULL;
1050
1051
10.0k
  parser->m_unknownEncodingHandler = NULL;
1052
10.0k
  parser->m_unknownEncodingHandlerData = NULL;
1053
1054
10.0k
  parser->m_namespaceSeparator = ASCII_EXCL;
1055
10.0k
  parser->m_ns = XML_FALSE;
1056
10.0k
  parser->m_ns_triplets = XML_FALSE;
1057
1058
10.0k
  parser->m_nsAtts = NULL;
1059
10.0k
  parser->m_nsAttsVersion = 0;
1060
10.0k
  parser->m_nsAttsPower = 0;
1061
1062
10.0k
  parser->m_protocolEncodingName = NULL;
1063
1064
10.0k
  poolInit(&parser->m_tempPool, &(parser->m_mem));
1065
10.0k
  poolInit(&parser->m_temp2Pool, &(parser->m_mem));
1066
10.0k
  parserInit(parser, encodingName);
1067
1068
10.0k
  if (encodingName && ! parser->m_protocolEncodingName) {
1069
0
    XML_ParserFree(parser);
1070
0
    return NULL;
1071
0
  }
1072
1073
10.0k
  if (nameSep) {
1074
0
    parser->m_ns = XML_TRUE;
1075
0
    parser->m_internalEncoding = XmlGetInternalEncodingNS();
1076
0
    parser->m_namespaceSeparator = *nameSep;
1077
10.0k
  } else {
1078
10.0k
    parser->m_internalEncoding = XmlGetInternalEncoding();
1079
10.0k
  }
1080
1081
10.0k
  return parser;
1082
10.0k
}
1083
1084
static void
1085
10.0k
parserInit(XML_Parser parser, const XML_Char *encodingName) {
1086
10.0k
  parser->m_processor = prologInitProcessor;
1087
10.0k
  XmlPrologStateInit(&parser->m_prologState);
1088
10.0k
  if (encodingName != NULL) {
1089
0
    parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1090
0
  }
1091
10.0k
  parser->m_curBase = NULL;
1092
10.0k
  XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
1093
10.0k
  parser->m_userData = NULL;
1094
10.0k
  parser->m_handlerArg = NULL;
1095
10.0k
  parser->m_startElementHandler = NULL;
1096
10.0k
  parser->m_endElementHandler = NULL;
1097
10.0k
  parser->m_characterDataHandler = NULL;
1098
10.0k
  parser->m_processingInstructionHandler = NULL;
1099
10.0k
  parser->m_commentHandler = NULL;
1100
10.0k
  parser->m_startCdataSectionHandler = NULL;
1101
10.0k
  parser->m_endCdataSectionHandler = NULL;
1102
10.0k
  parser->m_defaultHandler = NULL;
1103
10.0k
  parser->m_startDoctypeDeclHandler = NULL;
1104
10.0k
  parser->m_endDoctypeDeclHandler = NULL;
1105
10.0k
  parser->m_unparsedEntityDeclHandler = NULL;
1106
10.0k
  parser->m_notationDeclHandler = NULL;
1107
10.0k
  parser->m_startNamespaceDeclHandler = NULL;
1108
10.0k
  parser->m_endNamespaceDeclHandler = NULL;
1109
10.0k
  parser->m_notStandaloneHandler = NULL;
1110
10.0k
  parser->m_externalEntityRefHandler = NULL;
1111
10.0k
  parser->m_externalEntityRefHandlerArg = parser;
1112
10.0k
  parser->m_skippedEntityHandler = NULL;
1113
10.0k
  parser->m_elementDeclHandler = NULL;
1114
10.0k
  parser->m_attlistDeclHandler = NULL;
1115
10.0k
  parser->m_entityDeclHandler = NULL;
1116
10.0k
  parser->m_xmlDeclHandler = NULL;
1117
10.0k
  parser->m_bufferPtr = parser->m_buffer;
1118
10.0k
  parser->m_bufferEnd = parser->m_buffer;
1119
10.0k
  parser->m_parseEndByteIndex = 0;
1120
10.0k
  parser->m_parseEndPtr = NULL;
1121
10.0k
  parser->m_declElementType = NULL;
1122
10.0k
  parser->m_declAttributeId = NULL;
1123
10.0k
  parser->m_declEntity = NULL;
1124
10.0k
  parser->m_doctypeName = NULL;
1125
10.0k
  parser->m_doctypeSysid = NULL;
1126
10.0k
  parser->m_doctypePubid = NULL;
1127
10.0k
  parser->m_declAttributeType = NULL;
1128
10.0k
  parser->m_declNotationName = NULL;
1129
10.0k
  parser->m_declNotationPublicId = NULL;
1130
10.0k
  parser->m_declAttributeIsCdata = XML_FALSE;
1131
10.0k
  parser->m_declAttributeIsId = XML_FALSE;
1132
10.0k
  memset(&parser->m_position, 0, sizeof(POSITION));
1133
10.0k
  parser->m_errorCode = XML_ERROR_NONE;
1134
10.0k
  parser->m_eventPtr = NULL;
1135
10.0k
  parser->m_eventEndPtr = NULL;
1136
10.0k
  parser->m_positionPtr = NULL;
1137
10.0k
  parser->m_openInternalEntities = NULL;
1138
10.0k
  parser->m_defaultExpandInternalEntities = XML_TRUE;
1139
10.0k
  parser->m_tagLevel = 0;
1140
10.0k
  parser->m_tagStack = NULL;
1141
10.0k
  parser->m_inheritedBindings = NULL;
1142
10.0k
  parser->m_nSpecifiedAtts = 0;
1143
10.0k
  parser->m_unknownEncodingMem = NULL;
1144
10.0k
  parser->m_unknownEncodingRelease = NULL;
1145
10.0k
  parser->m_unknownEncodingData = NULL;
1146
10.0k
  parser->m_parentParser = NULL;
1147
10.0k
  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
10.0k
  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
10.0k
}
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
2.22M
destroyBindings(BINDING *bindings, XML_Parser parser) {
1417
2.22M
  for (;;) {
1418
2.22M
    BINDING *b = bindings;
1419
2.22M
    if (! b)
1420
2.22M
      break;
1421
0
    bindings = b->nextTagBinding;
1422
0
    FREE(parser, b->uri);
1423
0
    FREE(parser, b);
1424
0
  }
1425
2.22M
}
1426
1427
void XMLCALL
1428
10.0k
XML_ParserFree(XML_Parser parser) {
1429
10.0k
  TAG *tagList;
1430
10.0k
  OPEN_INTERNAL_ENTITY *entityList;
1431
10.0k
  if (parser == NULL)
1432
0
    return;
1433
  /* free m_tagStack and m_freeTagList */
1434
10.0k
  tagList = parser->m_tagStack;
1435
2.21M
  for (;;) {
1436
2.21M
    TAG *p;
1437
2.21M
    if (tagList == NULL) {
1438
11.7k
      if (parser->m_freeTagList == NULL)
1439
10.0k
        break;
1440
1.74k
      tagList = parser->m_freeTagList;
1441
1.74k
      parser->m_freeTagList = NULL;
1442
1.74k
    }
1443
2.20M
    p = tagList;
1444
2.20M
    tagList = tagList->parent;
1445
2.20M
    FREE(parser, p->buf);
1446
2.20M
    destroyBindings(p->bindings, parser);
1447
2.20M
    FREE(parser, p);
1448
2.20M
  }
1449
  /* free m_openInternalEntities and m_freeInternalEntities */
1450
10.0k
  entityList = parser->m_openInternalEntities;
1451
12.3k
  for (;;) {
1452
12.3k
    OPEN_INTERNAL_ENTITY *openEntity;
1453
12.3k
    if (entityList == NULL) {
1454
11.4k
      if (parser->m_freeInternalEntities == NULL)
1455
10.0k
        break;
1456
1.40k
      entityList = parser->m_freeInternalEntities;
1457
1.40k
      parser->m_freeInternalEntities = NULL;
1458
1.40k
    }
1459
2.33k
    openEntity = entityList;
1460
2.33k
    entityList = entityList->next;
1461
2.33k
    FREE(parser, openEntity);
1462
2.33k
  }
1463
1464
10.0k
  destroyBindings(parser->m_freeBindingList, parser);
1465
10.0k
  destroyBindings(parser->m_inheritedBindings, parser);
1466
10.0k
  poolDestroy(&parser->m_tempPool);
1467
10.0k
  poolDestroy(&parser->m_temp2Pool);
1468
10.0k
  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
10.0k
  if (parser->m_dtd)
1476
10.0k
#endif /* XML_DTD */
1477
10.0k
    dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser,
1478
10.0k
               &parser->m_mem);
1479
10.0k
  FREE(parser, (void *)parser->m_atts);
1480
#ifdef XML_ATTR_INFO
1481
  FREE(parser, (void *)parser->m_attInfo);
1482
#endif
1483
10.0k
  FREE(parser, parser->m_groupConnector);
1484
10.0k
  FREE(parser, parser->m_buffer);
1485
10.0k
  FREE(parser, parser->m_dataBuf);
1486
10.0k
  FREE(parser, parser->m_nsAtts);
1487
10.0k
  FREE(parser, parser->m_unknownEncodingMem);
1488
10.0k
  if (parser->m_unknownEncodingRelease)
1489
0
    parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1490
10.0k
  FREE(parser, parser);
1491
10.0k
}
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
10.0k
XML_SetUserData(XML_Parser parser, void *p) {
1529
10.0k
  if (parser == NULL)
1530
0
    return;
1531
10.0k
  if (parser->m_handlerArg == parser->m_userData)
1532
10.0k
    parser->m_handlerArg = parser->m_userData = p;
1533
0
  else
1534
0
    parser->m_userData = p;
1535
10.0k
}
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
10.0k
                      XML_EndElementHandler end) {
1584
10.0k
  if (parser == NULL)
1585
0
    return;
1586
10.0k
  parser->m_startElementHandler = start;
1587
10.0k
  parser->m_endElementHandler = end;
1588
10.0k
}
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
10.0k
                            XML_CharacterDataHandler handler) {
1605
10.0k
  if (parser != NULL)
1606
10.0k
    parser->m_characterDataHandler = handler;
1607
10.0k
}
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
17.0k
XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
1818
17.0k
  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
17.0k
  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
10.0k
  case XML_INITIALIZED:
1831
10.0k
    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
17.0k
  default:
1837
17.0k
    parser->m_parsingStatus.parsing = XML_PARSING;
1838
17.0k
  }
1839
1840
17.0k
  if (len == 0) {
1841
7.03k
    parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
1842
7.03k
    if (! isFinal)
1843
2
      return XML_STATUS_OK;
1844
7.03k
    parser->m_positionPtr = parser->m_bufferPtr;
1845
7.03k
    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
7.03k
    parser->m_errorCode
1852
7.03k
        = parser->m_processor(parser, parser->m_bufferPtr,
1853
7.03k
                              parser->m_parseEndPtr, &parser->m_bufferPtr);
1854
1855
7.03k
    if (parser->m_errorCode == XML_ERROR_NONE) {
1856
2.11k
      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
2.11k
      case XML_PARSING:
1877
2.11k
        parser->m_parsingStatus.parsing = XML_FINISHED;
1878
        /* fall through */
1879
2.11k
      default:
1880
2.11k
        return XML_STATUS_OK;
1881
2.11k
      }
1882
2.11k
    }
1883
4.92k
    parser->m_eventEndPtr = parser->m_eventPtr;
1884
4.92k
    parser->m_processor = errorProcessor;
1885
4.92k
    return XML_STATUS_ERROR;
1886
7.03k
  }
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
10.0k
  else {
1960
10.0k
    void *buff = XML_GetBuffer(parser, len);
1961
10.0k
    if (buff == NULL)
1962
0
      return XML_STATUS_ERROR;
1963
10.0k
    else {
1964
10.0k
      memcpy(buff, s, len);
1965
10.0k
      return XML_ParseBuffer(parser, len, isFinal);
1966
10.0k
    }
1967
10.0k
  }
1968
17.0k
}
1969
1970
enum XML_Status XMLCALL
1971
10.0k
XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
1972
10.0k
  const char *start;
1973
10.0k
  enum XML_Status result = XML_STATUS_OK;
1974
1975
10.0k
  if (parser == NULL)
1976
0
    return XML_STATUS_ERROR;
1977
10.0k
  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
10.0k
  default:
1997
10.0k
    parser->m_parsingStatus.parsing = XML_PARSING;
1998
10.0k
  }
1999
2000
10.0k
  start = parser->m_bufferPtr;
2001
10.0k
  parser->m_positionPtr = start;
2002
10.0k
  parser->m_bufferEnd += len;
2003
10.0k
  parser->m_parseEndPtr = parser->m_bufferEnd;
2004
10.0k
  parser->m_parseEndByteIndex += len;
2005
10.0k
  parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
2006
2007
10.0k
  parser->m_errorCode = parser->m_processor(
2008
10.0k
      parser, start, parser->m_parseEndPtr, &parser->m_bufferPtr);
2009
2010
10.0k
  if (parser->m_errorCode != XML_ERROR_NONE) {
2011
2.98k
    parser->m_eventEndPtr = parser->m_eventPtr;
2012
2.98k
    parser->m_processor = errorProcessor;
2013
2.98k
    return XML_STATUS_ERROR;
2014
7.02k
  } else {
2015
7.02k
    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
7.02k
    case XML_PARSING:
2021
7.02k
      if (isFinal) {
2022
0
        parser->m_parsingStatus.parsing = XML_FINISHED;
2023
0
        return result;
2024
0
      }
2025
7.02k
    default:; /* should not happen */
2026
7.02k
    }
2027
7.02k
  }
2028
2029
7.02k
  XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2030
7.02k
                    parser->m_bufferPtr, &parser->m_position);
2031
7.02k
  parser->m_positionPtr = parser->m_bufferPtr;
2032
7.02k
  return result;
2033
10.0k
}
2034
2035
void *XMLCALL
2036
10.0k
XML_GetBuffer(XML_Parser parser, int len) {
2037
10.0k
  if (parser == NULL)
2038
0
    return NULL;
2039
10.0k
  if (len < 0) {
2040
0
    parser->m_errorCode = XML_ERROR_NO_MEMORY;
2041
0
    return NULL;
2042
0
  }
2043
10.0k
  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
10.0k
  default:;
2051
10.0k
  }
2052
2053
10.0k
  if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)) {
2054
10.0k
#ifdef XML_CONTEXT_BYTES
2055
10.0k
    int keep;
2056
10.0k
#endif /* defined XML_CONTEXT_BYTES */
2057
    /* Do not invoke signed arithmetic overflow: */
2058
10.0k
    int neededSize = (int)((unsigned)len
2059
10.0k
                           + (unsigned)EXPAT_SAFE_PTR_DIFF(
2060
10.0k
                               parser->m_bufferEnd, parser->m_bufferPtr));
2061
10.0k
    if (neededSize < 0) {
2062
0
      parser->m_errorCode = XML_ERROR_NO_MEMORY;
2063
0
      return NULL;
2064
0
    }
2065
10.0k
#ifdef XML_CONTEXT_BYTES
2066
10.0k
    keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
2067
10.0k
    if (keep > XML_CONTEXT_BYTES)
2068
0
      keep = XML_CONTEXT_BYTES;
2069
    /* Detect and prevent integer overflow */
2070
10.0k
    if (keep > INT_MAX - neededSize) {
2071
0
      parser->m_errorCode = XML_ERROR_NO_MEMORY;
2072
0
      return NULL;
2073
0
    }
2074
10.0k
    neededSize += keep;
2075
10.0k
#endif /* defined XML_CONTEXT_BYTES */
2076
10.0k
    if (neededSize
2077
10.0k
        <= 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
10.0k
    } else {
2101
10.0k
      char *newBuf;
2102
10.0k
      int bufferSize
2103
10.0k
          = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferPtr);
2104
10.0k
      if (bufferSize == 0)
2105
10.0k
        bufferSize = INIT_BUFFER_SIZE;
2106
16.6k
      do {
2107
        /* Do not invoke signed arithmetic overflow: */
2108
16.6k
        bufferSize = (int)(2U * (unsigned)bufferSize);
2109
16.6k
      } while (bufferSize < neededSize && bufferSize > 0);
2110
10.0k
      if (bufferSize <= 0) {
2111
0
        parser->m_errorCode = XML_ERROR_NO_MEMORY;
2112
0
        return NULL;
2113
0
      }
2114
10.0k
      newBuf = (char *)MALLOC(parser, bufferSize);
2115
10.0k
      if (newBuf == 0) {
2116
0
        parser->m_errorCode = XML_ERROR_NO_MEMORY;
2117
0
        return NULL;
2118
0
      }
2119
10.0k
      parser->m_bufferLim = newBuf + bufferSize;
2120
10.0k
#ifdef XML_CONTEXT_BYTES
2121
10.0k
      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
10.0k
      } else {
2133
        /* This must be a brand new buffer with no data in it yet */
2134
10.0k
        parser->m_bufferEnd = newBuf;
2135
10.0k
        parser->m_bufferPtr = parser->m_buffer = newBuf;
2136
10.0k
      }
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
10.0k
    }
2152
10.0k
    parser->m_eventPtr = parser->m_eventEndPtr = NULL;
2153
10.0k
    parser->m_positionPtr = NULL;
2154
10.0k
  }
2155
10.0k
  return parser->m_bufferEnd;
2156
10.0k
}
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.91k
XML_GetErrorCode(XML_Parser parser) {
2238
7.91k
  if (parser == NULL)
2239
0
    return XML_ERROR_INVALID_ARGUMENT;
2240
7.91k
  return parser->m_errorCode;
2241
7.91k
}
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.91k
XML_GetCurrentLineNumber(XML_Parser parser) {
2284
7.91k
  if (parser == NULL)
2285
0
    return 0;
2286
7.91k
  if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2287
7.90k
    XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2288
7.90k
                      parser->m_eventPtr, &parser->m_position);
2289
7.90k
    parser->m_positionPtr = parser->m_eventPtr;
2290
7.90k
  }
2291
7.91k
  return parser->m_position.lineNumber + 1;
2292
7.91k
}
2293
2294
XML_Size XMLCALL
2295
7.91k
XML_GetCurrentColumnNumber(XML_Parser parser) {
2296
7.91k
  if (parser == NULL)
2297
0
    return 0;
2298
7.91k
  if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2299
7.90k
    XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
2300
7.90k
                      parser->m_eventPtr, &parser->m_position);
2301
7.90k
    parser->m_positionPtr = parser->m_eventPtr;
2302
7.90k
  }
2303
7.91k
  return parser->m_position.columnNumber;
2304
7.91k
}
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.91k
XML_ErrorString(enum XML_Error code) {
2349
7.91k
  switch (code) {
2350
0
  case XML_ERROR_NONE:
2351
0
    return NULL;
2352
4
  case XML_ERROR_NO_MEMORY:
2353
4
    return XML_L("out of memory");
2354
681
  case XML_ERROR_SYNTAX:
2355
681
    return XML_L("syntax error");
2356
3.23k
  case XML_ERROR_NO_ELEMENTS:
2357
3.23k
    return XML_L("no element found");
2358
1.52k
  case XML_ERROR_INVALID_TOKEN:
2359
1.52k
    return XML_L("not well-formed (invalid token)");
2360
1.12k
  case XML_ERROR_UNCLOSED_TOKEN:
2361
1.12k
    return XML_L("unclosed token");
2362
193
  case XML_ERROR_PARTIAL_CHAR:
2363
193
    return XML_L("partial character");
2364
158
  case XML_ERROR_TAG_MISMATCH:
2365
158
    return XML_L("mismatched tag");
2366
244
  case XML_ERROR_DUPLICATE_ATTRIBUTE:
2367
244
    return XML_L("duplicate attribute");
2368
28
  case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
2369
28
    return XML_L("junk after document element");
2370
3
  case XML_ERROR_PARAM_ENTITY_REF:
2371
3
    return XML_L("illegal parameter entity reference");
2372
119
  case XML_ERROR_UNDEFINED_ENTITY:
2373
119
    return XML_L("undefined entity");
2374
2
  case XML_ERROR_RECURSIVE_ENTITY_REF:
2375
2
    return XML_L("recursive entity reference");
2376
90
  case XML_ERROR_ASYNC_ENTITY:
2377
90
    return XML_L("asynchronous entity");
2378
62
  case XML_ERROR_BAD_CHAR_REF:
2379
62
    return XML_L("reference to invalid character number");
2380
3
  case XML_ERROR_BINARY_ENTITY_REF:
2381
3
    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
45
  case XML_ERROR_UNKNOWN_ENCODING:
2387
45
    return XML_L("unknown encoding");
2388
2
  case XML_ERROR_INCORRECT_ENCODING:
2389
2
    return XML_L("encoding specified in XML declaration is incorrect");
2390
138
  case XML_ERROR_UNCLOSED_CDATA_SECTION:
2391
138
    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
245
  case XML_ERROR_XML_DECL:
2413
245
    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
15
  case XML_ERROR_PUBLICID:
2417
15
    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.91k
        "limit on input amplification factor (from DTD and entities) breached");
2448
7.91k
  }
2449
0
  return NULL;
2450
7.91k
}
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
4.34k
storeRawNames(XML_Parser parser) {
2560
4.34k
  TAG *tag = parser->m_tagStack;
2561
116k
  while (tag) {
2562
111k
    int bufSize;
2563
111k
    int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2564
111k
    size_t rawNameLen;
2565
111k
    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
111k
    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
111k
    rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2577
    /* Detect and prevent integer overflow. */
2578
111k
    if (rawNameLen > (size_t)INT_MAX - nameLen)
2579
0
      return XML_FALSE;
2580
111k
    bufSize = nameLen + (int)rawNameLen;
2581
111k
    if (bufSize > tag->bufEnd - tag->buf) {
2582
366
      char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
2583
366
      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
366
      if (tag->name.str == (XML_Char *)tag->buf)
2589
366
        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
366
      if (tag->name.localPart)
2594
0
        tag->name.localPart
2595
0
            = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf);
2596
366
      tag->buf = temp;
2597
366
      tag->bufEnd = temp + bufSize;
2598
366
      rawNameBuf = temp + nameLen;
2599
366
    }
2600
111k
    memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2601
111k
    tag->rawName = rawNameBuf;
2602
111k
    tag = tag->parent;
2603
111k
  }
2604
4.34k
  return XML_TRUE;
2605
4.34k
}
2606
2607
static enum XML_Error PTRCALL
2608
contentProcessor(XML_Parser parser, const char *start, const char *end,
2609
7.82k
                 const char **endPtr) {
2610
7.82k
  enum XML_Error result = doContent(
2611
7.82k
      parser, 0, parser->m_encoding, start, end, endPtr,
2612
7.82k
      (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
2613
7.82k
  if (result == XML_ERROR_NONE) {
2614
4.34k
    if (! storeRawNames(parser))
2615
0
      return XML_ERROR_NO_MEMORY;
2616
4.34k
  }
2617
7.82k
  return result;
2618
7.82k
}
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
37.6k
          XML_Bool haveMore, enum XML_Account account) {
2740
  /* save one level of indirection */
2741
37.6k
  DTD *const dtd = parser->m_dtd;
2742
2743
37.6k
  const char **eventPP;
2744
37.6k
  const char **eventEndPP;
2745
37.6k
  if (enc == parser->m_encoding) {
2746
7.82k
    eventPP = &parser->m_eventPtr;
2747
7.82k
    eventEndPP = &parser->m_eventEndPtr;
2748
29.8k
  } else {
2749
29.8k
    eventPP = &(parser->m_openInternalEntities->internalEventPtr);
2750
29.8k
    eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
2751
29.8k
  }
2752
37.6k
  *eventPP = s;
2753
2754
7.15M
  for (;;) {
2755
7.15M
    const char *next = s; /* XmlContentTok doesn't always set the last arg */
2756
7.15M
    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
7.15M
    *eventEndPP = next;
2769
7.15M
    switch (tok) {
2770
26
    case XML_TOK_TRAILING_CR:
2771
26
      if (haveMore) {
2772
13
        *nextPtr = s;
2773
13
        return XML_ERROR_NONE;
2774
13
      }
2775
13
      *eventEndPP = end;
2776
13
      if (parser->m_characterDataHandler) {
2777
13
        XML_Char c = 0xA;
2778
13
        parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
2779
13
      } 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
13
      if (startTagLevel == 0)
2785
13
        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
30.7k
    case XML_TOK_NONE:
2791
30.7k
      if (haveMore) {
2792
1.37k
        *nextPtr = s;
2793
1.37k
        return XML_ERROR_NONE;
2794
1.37k
      }
2795
29.3k
      if (startTagLevel > 0) {
2796
27.9k
        if (parser->m_tagLevel != startTagLevel)
2797
50
          return XML_ERROR_ASYNC_ENTITY;
2798
27.9k
        *nextPtr = s;
2799
27.9k
        return XML_ERROR_NONE;
2800
27.9k
      }
2801
1.37k
      return XML_ERROR_NO_ELEMENTS;
2802
592
    case XML_TOK_INVALID:
2803
592
      *eventPP = next;
2804
592
      return XML_ERROR_INVALID_TOKEN;
2805
1.31k
    case XML_TOK_PARTIAL:
2806
1.31k
      if (haveMore) {
2807
631
        *nextPtr = s;
2808
631
        return XML_ERROR_NONE;
2809
631
      }
2810
681
      return XML_ERROR_UNCLOSED_TOKEN;
2811
126
    case XML_TOK_PARTIAL_CHAR:
2812
126
      if (haveMore) {
2813
63
        *nextPtr = s;
2814
63
        return XML_ERROR_NONE;
2815
63
      }
2816
63
      return XML_ERROR_PARTIAL_CHAR;
2817
46.8k
    case XML_TOK_ENTITY_REF: {
2818
46.8k
      const XML_Char *name;
2819
46.8k
      ENTITY *entity;
2820
46.8k
      XML_Char ch = (XML_Char)XmlPredefinedEntityName(
2821
46.8k
          enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
2822
46.8k
      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
1.24k
        if (parser->m_characterDataHandler)
2832
1.24k
          parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
2833
0
        else if (parser->m_defaultHandler)
2834
0
          reportDefault(parser, enc, s, next);
2835
1.24k
        break;
2836
1.24k
      }
2837
45.6k
      name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
2838
45.6k
                             next - enc->minBytesPerChar);
2839
45.6k
      if (! name)
2840
0
        return XML_ERROR_NO_MEMORY;
2841
45.6k
      entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
2842
45.6k
      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
45.6k
      if (! dtd->hasParamEntityRefs || dtd->standalone) {
2848
20.7k
        if (! entity)
2849
79
          return XML_ERROR_UNDEFINED_ENTITY;
2850
20.6k
        else if (! entity->is_internal)
2851
0
          return XML_ERROR_ENTITY_DECLARED_IN_PE;
2852
24.8k
      } else if (! entity) {
2853
15.5k
        if (parser->m_skippedEntityHandler)
2854
0
          parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
2855
15.5k
        else if (parser->m_defaultHandler)
2856
0
          reportDefault(parser, enc, s, next);
2857
15.5k
        break;
2858
15.5k
      }
2859
30.0k
      if (entity->open)
2860
1
        return XML_ERROR_RECURSIVE_ENTITY_REF;
2861
30.0k
      if (entity->notation)
2862
1
        return XML_ERROR_BINARY_ENTITY_REF;
2863
29.9k
      if (entity->textPtr) {
2864
29.8k
        enum XML_Error result;
2865
29.8k
        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
29.8k
        result = processInternalEntity(parser, entity, XML_FALSE);
2874
29.8k
        if (result != XML_ERROR_NONE)
2875
449
          return result;
2876
29.8k
      } 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
194
      } else if (parser->m_defaultHandler)
2889
0
        reportDefault(parser, enc, s, next);
2890
29.5k
      break;
2891
29.9k
    }
2892
2.27M
    case XML_TOK_START_TAG_NO_ATTS:
2893
      /* fall through */
2894
2.28M
    case XML_TOK_START_TAG_WITH_ATTS: {
2895
2.28M
      TAG *tag;
2896
2.28M
      enum XML_Error result;
2897
2.28M
      XML_Char *toPtr;
2898
2.28M
      if (parser->m_freeTagList) {
2899
82.7k
        tag = parser->m_freeTagList;
2900
82.7k
        parser->m_freeTagList = parser->m_freeTagList->parent;
2901
2.20M
      } else {
2902
2.20M
        tag = (TAG *)MALLOC(parser, sizeof(TAG));
2903
2.20M
        if (! tag)
2904
0
          return XML_ERROR_NO_MEMORY;
2905
2.20M
        tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
2906
2.20M
        if (! tag->buf) {
2907
0
          FREE(parser, tag);
2908
0
          return XML_ERROR_NO_MEMORY;
2909
0
        }
2910
2.20M
        tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2911
2.20M
      }
2912
2.28M
      tag->bindings = NULL;
2913
2.28M
      tag->parent = parser->m_tagStack;
2914
2.28M
      parser->m_tagStack = tag;
2915
2.28M
      tag->name.localPart = NULL;
2916
2.28M
      tag->name.prefix = NULL;
2917
2.28M
      tag->rawName = s + enc->minBytesPerChar;
2918
2.28M
      tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2919
2.28M
      ++parser->m_tagLevel;
2920
2.28M
      {
2921
2.28M
        const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2922
2.28M
        const char *fromPtr = tag->rawName;
2923
2.28M
        toPtr = (XML_Char *)tag->buf;
2924
2.28M
        for (;;) {
2925
2.28M
          int bufSize;
2926
2.28M
          int convLen;
2927
2.28M
          const enum XML_Convert_Result convert_res
2928
2.28M
              = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr,
2929
2.28M
                           (ICHAR *)tag->bufEnd - 1);
2930
2.28M
          convLen = (int)(toPtr - (XML_Char *)tag->buf);
2931
2.28M
          if ((fromPtr >= rawNameEnd)
2932
2.28M
              || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
2933
2.28M
            tag->name.strLen = convLen;
2934
2.28M
            break;
2935
2.28M
          }
2936
1.62k
          bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2937
1.62k
          {
2938
1.62k
            char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
2939
1.62k
            if (temp == NULL)
2940
0
              return XML_ERROR_NO_MEMORY;
2941
1.62k
            tag->buf = temp;
2942
1.62k
            tag->bufEnd = temp + bufSize;
2943
1.62k
            toPtr = (XML_Char *)temp + convLen;
2944
1.62k
          }
2945
1.62k
        }
2946
2.28M
      }
2947
2.28M
      tag->name.str = (XML_Char *)tag->buf;
2948
2.28M
      *toPtr = XML_T('\0');
2949
2.28M
      result
2950
2.28M
          = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account);
2951
2.28M
      if (result)
2952
263
        return result;
2953
2.28M
      if (parser->m_startElementHandler)
2954
2.28M
        parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
2955
2.28M
                                      (const XML_Char **)parser->m_atts);
2956
0
      else if (parser->m_defaultHandler)
2957
0
        reportDefault(parser, enc, s, next);
2958
2.28M
      poolClear(&parser->m_tempPool);
2959
2.28M
      break;
2960
2.28M
    }
2961
50.0k
    case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2962
      /* fall through */
2963
93.5k
    case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: {
2964
93.5k
      const char *rawName = s + enc->minBytesPerChar;
2965
93.5k
      enum XML_Error result;
2966
93.5k
      BINDING *bindings = NULL;
2967
93.5k
      XML_Bool noElmHandlers = XML_TRUE;
2968
93.5k
      TAG_NAME name;
2969
93.5k
      name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
2970
93.5k
                                 rawName + XmlNameLength(enc, rawName));
2971
93.5k
      if (! name.str)
2972
0
        return XML_ERROR_NO_MEMORY;
2973
93.5k
      poolFinish(&parser->m_tempPool);
2974
93.5k
      result = storeAtts(parser, enc, s, &name, &bindings,
2975
93.5k
                         XML_ACCOUNT_NONE /* token spans whole start tag */);
2976
93.5k
      if (result != XML_ERROR_NONE) {
2977
33
        freeBindings(parser, bindings);
2978
33
        return result;
2979
33
      }
2980
93.5k
      poolFinish(&parser->m_tempPool);
2981
93.5k
      if (parser->m_startElementHandler) {
2982
93.5k
        parser->m_startElementHandler(parser->m_handlerArg, name.str,
2983
93.5k
                                      (const XML_Char **)parser->m_atts);
2984
93.5k
        noElmHandlers = XML_FALSE;
2985
93.5k
      }
2986
93.5k
      if (parser->m_endElementHandler) {
2987
93.5k
        if (parser->m_startElementHandler)
2988
93.5k
          *eventPP = *eventEndPP;
2989
93.5k
        parser->m_endElementHandler(parser->m_handlerArg, name.str);
2990
93.5k
        noElmHandlers = XML_FALSE;
2991
93.5k
      }
2992
93.5k
      if (noElmHandlers && parser->m_defaultHandler)
2993
0
        reportDefault(parser, enc, s, next);
2994
93.5k
      poolClear(&parser->m_tempPool);
2995
93.5k
      freeBindings(parser, bindings);
2996
93.5k
    }
2997
93.5k
      if ((parser->m_tagLevel == 0)
2998
93.5k
          && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
2999
679
        if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
3000
0
          parser->m_processor = epilogProcessor;
3001
679
        else
3002
679
          return epilogProcessor(parser, next, end, nextPtr);
3003
679
      }
3004
92.8k
      break;
3005
92.8k
    case XML_TOK_END_TAG:
3006
85.7k
      if (parser->m_tagLevel == startTagLevel)
3007
2
        return XML_ERROR_ASYNC_ENTITY;
3008
85.7k
      else {
3009
85.7k
        int len;
3010
85.7k
        const char *rawName;
3011
85.7k
        TAG *tag = parser->m_tagStack;
3012
85.7k
        parser->m_tagStack = tag->parent;
3013
85.7k
        tag->parent = parser->m_freeTagList;
3014
85.7k
        parser->m_freeTagList = tag;
3015
85.7k
        rawName = s + enc->minBytesPerChar * 2;
3016
85.7k
        len = XmlNameLength(enc, rawName);
3017
85.7k
        if (len != tag->rawNameLength
3018
85.7k
            || memcmp(tag->rawName, rawName, len) != 0) {
3019
158
          *eventPP = rawName;
3020
158
          return XML_ERROR_TAG_MISMATCH;
3021
158
        }
3022
85.5k
        --parser->m_tagLevel;
3023
85.5k
        if (parser->m_endElementHandler) {
3024
85.5k
          const XML_Char *localPart;
3025
85.5k
          const XML_Char *prefix;
3026
85.5k
          XML_Char *uri;
3027
85.5k
          localPart = tag->name.localPart;
3028
85.5k
          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
85.5k
          parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
3046
85.5k
        } else if (parser->m_defaultHandler)
3047
0
          reportDefault(parser, enc, s, next);
3048
85.5k
        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
85.5k
        if ((parser->m_tagLevel == 0)
3059
85.5k
            && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
3060
1.47k
          if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
3061
0
            parser->m_processor = epilogProcessor;
3062
1.47k
          else
3063
1.47k
            return epilogProcessor(parser, next, end, nextPtr);
3064
1.47k
        }
3065
85.5k
      }
3066
84.1k
      break;
3067
84.1k
    case XML_TOK_CHAR_REF: {
3068
4.89k
      int n = XmlCharRefNumber(enc, s);
3069
4.89k
      if (n < 0)
3070
48
        return XML_ERROR_BAD_CHAR_REF;
3071
4.84k
      if (parser->m_characterDataHandler) {
3072
4.84k
        XML_Char buf[XML_ENCODE_MAX];
3073
4.84k
        parser->m_characterDataHandler(parser->m_handlerArg, buf,
3074
4.84k
                                       XmlEncode(n, (ICHAR *)buf));
3075
4.84k
      } else if (parser->m_defaultHandler)
3076
0
        reportDefault(parser, enc, s, next);
3077
4.84k
    } break;
3078
1
    case XML_TOK_XML_DECL:
3079
1
      return XML_ERROR_MISPLACED_XML_PI;
3080
4.10M
    case XML_TOK_DATA_NEWLINE:
3081
4.10M
      if (parser->m_characterDataHandler) {
3082
4.10M
        XML_Char c = 0xA;
3083
4.10M
        parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
3084
4.10M
      } else if (parser->m_defaultHandler)
3085
0
        reportDefault(parser, enc, s, next);
3086
4.10M
      break;
3087
1.73k
    case XML_TOK_CDATA_SECT_OPEN: {
3088
1.73k
      enum XML_Error result;
3089
1.73k
      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.73k
      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.73k
      else if (parser->m_defaultHandler)
3109
0
        reportDefault(parser, enc, s, next);
3110
1.73k
      result
3111
1.73k
          = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account);
3112
1.73k
      if (result != XML_ERROR_NONE)
3113
34
        return result;
3114
1.69k
      else if (! next) {
3115
138
        parser->m_processor = cdataSectionProcessor;
3116
138
        return result;
3117
138
      }
3118
1.73k
    } break;
3119
1.56k
    case XML_TOK_TRAILING_RSQB:
3120
1.48k
      if (haveMore) {
3121
15
        *nextPtr = s;
3122
15
        return XML_ERROR_NONE;
3123
15
      }
3124
1.46k
      if (parser->m_characterDataHandler) {
3125
1.46k
        if (MUST_CONVERT(enc, s)) {
3126
1
          ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3127
1
          XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3128
1
          parser->m_characterDataHandler(
3129
1
              parser->m_handlerArg, parser->m_dataBuf,
3130
1
              (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
3131
1
        } else
3132
1.46k
          parser->m_characterDataHandler(
3133
1.46k
              parser->m_handlerArg, (XML_Char *)s,
3134
1.46k
              (int)((XML_Char *)end - (XML_Char *)s));
3135
1.46k
      } 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
1.46k
      if (startTagLevel == 0) {
3141
15
        *eventPP = end;
3142
15
        return XML_ERROR_NO_ELEMENTS;
3143
15
      }
3144
1.45k
      if (parser->m_tagLevel != startTagLevel) {
3145
38
        *eventPP = end;
3146
38
        return XML_ERROR_ASYNC_ENTITY;
3147
38
      }
3148
1.41k
      *nextPtr = end;
3149
1.41k
      return XML_ERROR_NONE;
3150
479k
    case XML_TOK_DATA_CHARS: {
3151
479k
      XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
3152
479k
      if (charDataHandler) {
3153
479k
        if (MUST_CONVERT(enc, s)) {
3154
3.97k
          for (;;) {
3155
3.97k
            ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3156
3.97k
            const enum XML_Convert_Result convert_res = XmlConvert(
3157
3.97k
                enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3158
3.97k
            *eventEndPP = s;
3159
3.97k
            charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3160
3.97k
                            (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
3161
3.97k
            if ((convert_res == XML_CONVERT_COMPLETED)
3162
3.97k
                || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3163
2.14k
              break;
3164
1.82k
            *eventPP = s;
3165
1.82k
          }
3166
2.14k
        } else
3167
477k
          charDataHandler(parser->m_handlerArg, (XML_Char *)s,
3168
477k
                          (int)((XML_Char *)next - (XML_Char *)s));
3169
479k
      } else if (parser->m_defaultHandler)
3170
0
        reportDefault(parser, enc, s, next);
3171
479k
    } break;
3172
11.7k
    case XML_TOK_PI:
3173
11.7k
      if (! reportProcessingInstruction(parser, enc, s, next))
3174
0
        return XML_ERROR_NO_MEMORY;
3175
11.7k
      break;
3176
11.7k
    case XML_TOK_COMMENT:
3177
6.75k
      if (! reportComment(parser, enc, s, next))
3178
0
        return XML_ERROR_NO_MEMORY;
3179
6.75k
      break;
3180
6.75k
    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
7.15M
    }
3193
7.11M
    *eventPP = s = next;
3194
7.11M
    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
7.11M
    default:;
3201
7.11M
    }
3202
7.11M
  }
3203
  /* not reached */
3204
37.6k
}
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
93.5k
freeBindings(XML_Parser parser, BINDING *bindings) {
3212
93.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
93.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
2.37M
          enum XML_Account account) {
3242
2.37M
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
3243
2.37M
  ELEMENT_TYPE *elementType;
3244
2.37M
  int nDefaultAtts;
3245
2.37M
  const XML_Char **appAtts; /* the attribute list for the application */
3246
2.37M
  int attIndex = 0;
3247
2.37M
  int prefixLen;
3248
2.37M
  int i;
3249
2.37M
  int n;
3250
2.37M
  XML_Char *uri;
3251
2.37M
  int nPrefixes = 0;
3252
2.37M
  BINDING *binding;
3253
2.37M
  const XML_Char *localPart;
3254
3255
  /* lookup the element type name */
3256
2.37M
  elementType
3257
2.37M
      = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str, 0);
3258
2.37M
  if (! elementType) {
3259
14.8k
    const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
3260
14.8k
    if (! name)
3261
0
      return XML_ERROR_NO_MEMORY;
3262
14.8k
    elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
3263
14.8k
                                         sizeof(ELEMENT_TYPE));
3264
14.8k
    if (! elementType)
3265
0
      return XML_ERROR_NO_MEMORY;
3266
14.8k
    if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
3267
0
      return XML_ERROR_NO_MEMORY;
3268
14.8k
  }
3269
2.37M
  nDefaultAtts = elementType->nDefaultAtts;
3270
3271
  /* get the attributes from the tokenizer */
3272
2.37M
  n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
3273
3274
  /* Detect and prevent integer overflow */
3275
2.37M
  if (n > INT_MAX - nDefaultAtts) {
3276
0
    return XML_ERROR_NO_MEMORY;
3277
0
  }
3278
3279
2.37M
  if (n + nDefaultAtts > parser->m_attsSize) {
3280
277
    int oldAttsSize = parser->m_attsSize;
3281
277
    ATTRIBUTE *temp;
3282
#ifdef XML_ATTR_INFO
3283
    XML_AttrInfo *temp2;
3284
#endif
3285
3286
    /* Detect and prevent integer overflow */
3287
277
    if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE)
3288
277
        || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
3289
0
      return XML_ERROR_NO_MEMORY;
3290
0
    }
3291
3292
277
    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
277
    temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
3306
277
                                parser->m_attsSize * sizeof(ATTRIBUTE));
3307
277
    if (temp == NULL) {
3308
0
      parser->m_attsSize = oldAttsSize;
3309
0
      return XML_ERROR_NO_MEMORY;
3310
0
    }
3311
277
    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
277
    if (n > oldAttsSize)
3333
237
      XmlGetAttributes(enc, attStr, n, parser->m_atts);
3334
277
  }
3335
3336
2.37M
  appAtts = (const XML_Char **)parser->m_atts;
3337
2.47M
  for (i = 0; i < n; i++) {
3338
95.2k
    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
95.2k
    ATTRIBUTE_ID *attId
3344
95.2k
        = getAttributeId(parser, enc, currAtt->name,
3345
95.2k
                         currAtt->name + XmlNameLength(enc, currAtt->name));
3346
95.2k
    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
95.2k
    if ((attId->name)[-1]) {
3363
244
      if (enc == parser->m_encoding)
3364
241
        parser->m_eventPtr = parser->m_atts[i].name;
3365
244
      return XML_ERROR_DUPLICATE_ATTRIBUTE;
3366
244
    }
3367
95.0k
    (attId->name)[-1] = 1;
3368
95.0k
    appAtts[attIndex++] = attId->name;
3369
95.0k
    if (! parser->m_atts[i].normalized) {
3370
13.1k
      enum XML_Error result;
3371
13.1k
      XML_Bool isCdata = XML_TRUE;
3372
3373
      /* figure out whether declared as other than CDATA */
3374
13.1k
      if (attId->maybeTokenized) {
3375
1.45k
        int j;
3376
93.5k
        for (j = 0; j < nDefaultAtts; j++) {
3377
93.1k
          if (attId == elementType->defaultAtts[j].id) {
3378
994
            isCdata = elementType->defaultAtts[j].isCdata;
3379
994
            break;
3380
994
          }
3381
93.1k
        }
3382
1.45k
      }
3383
3384
      /* normalize the attribute value */
3385
13.1k
      result = storeAttributeValue(
3386
13.1k
          parser, enc, isCdata, parser->m_atts[i].valuePtr,
3387
13.1k
          parser->m_atts[i].valueEnd, &parser->m_tempPool, account);
3388
13.1k
      if (result)
3389
52
        return result;
3390
13.0k
      appAtts[attIndex] = poolStart(&parser->m_tempPool);
3391
13.0k
      poolFinish(&parser->m_tempPool);
3392
81.9k
    } else {
3393
      /* the value did not need normalizing */
3394
81.9k
      appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc,
3395
81.9k
                                          parser->m_atts[i].valuePtr,
3396
81.9k
                                          parser->m_atts[i].valueEnd);
3397
81.9k
      if (appAtts[attIndex] == 0)
3398
0
        return XML_ERROR_NO_MEMORY;
3399
81.9k
      poolFinish(&parser->m_tempPool);
3400
81.9k
    }
3401
    /* handle prefixed attribute names */
3402
94.9k
    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
94.9k
      attIndex++;
3418
94.9k
  }
3419
3420
  /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
3421
2.37M
  parser->m_nSpecifiedAtts = attIndex;
3422
2.37M
  if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
3423
1.03k
    for (i = 0; i < attIndex; i += 2)
3424
1.03k
      if (appAtts[i] == elementType->idAtt->name) {
3425
713
        parser->m_idAttIndex = i;
3426
713
        break;
3427
713
      }
3428
713
  } else
3429
2.37M
    parser->m_idAttIndex = -1;
3430
3431
  /* do attribute defaulting */
3432
3.02M
  for (i = 0; i < nDefaultAtts; i++) {
3433
651k
    const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
3434
651k
    if (! (da->id->name)[-1] && da->value) {
3435
1.92k
      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.92k
      } else {
3448
1.92k
        (da->id->name)[-1] = 1;
3449
1.92k
        appAtts[attIndex++] = da->id->name;
3450
1.92k
        appAtts[attIndex++] = da->value;
3451
1.92k
      }
3452
1.92k
    }
3453
651k
  }
3454
2.37M
  appAtts[attIndex] = 0;
3455
3456
  /* expand prefixed attribute names, check for duplicates,
3457
     and clear flags that say whether attributes were specified */
3458
2.37M
  i = 0;
3459
2.37M
  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
2.47M
  for (; i < attIndex; i += 2)
3627
96.4k
    ((XML_Char *)(appAtts[i]))[-1] = 0;
3628
2.37M
  for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3629
0
    binding->attId->name[-1] = 0;
3630
3631
2.37M
  if (! parser->m_ns)
3632
2.37M
    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
138
                      const char **endPtr) {
3866
138
  enum XML_Error result = doCdataSection(
3867
138
      parser, parser->m_encoding, &start, end, endPtr,
3868
138
      (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
3869
138
  if (result != XML_ERROR_NONE)
3870
138
    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
1.87k
               enum XML_Account account) {
3890
1.87k
  const char *s = *startPtr;
3891
1.87k
  const char **eventPP;
3892
1.87k
  const char **eventEndPP;
3893
1.87k
  if (enc == parser->m_encoding) {
3894
981
    eventPP = &parser->m_eventPtr;
3895
981
    *eventPP = s;
3896
981
    eventEndPP = &parser->m_eventEndPtr;
3897
981
  } else {
3898
890
    eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3899
890
    eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
3900
890
  }
3901
1.87k
  *eventPP = s;
3902
1.87k
  *startPtr = NULL;
3903
3904
1.95M
  for (;;) {
3905
1.95M
    const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
3906
1.95M
    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
1.95M
    UNUSED_P(account);
3914
1.95M
#endif
3915
1.95M
    *eventEndPP = next;
3916
1.95M
    switch (tok) {
3917
1.56k
    case XML_TOK_CDATA_SECT_CLOSE:
3918
1.56k
      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.56k
      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.56k
      else if (parser->m_defaultHandler)
3927
0
        reportDefault(parser, enc, s, next);
3928
1.56k
      *startPtr = next;
3929
1.56k
      *nextPtr = next;
3930
1.56k
      if (parser->m_parsingStatus.parsing == XML_FINISHED)
3931
0
        return XML_ERROR_ABORTED;
3932
1.56k
      else
3933
1.56k
        return XML_ERROR_NONE;
3934
1.64M
    case XML_TOK_DATA_NEWLINE:
3935
1.64M
      if (parser->m_characterDataHandler) {
3936
1.64M
        XML_Char c = 0xA;
3937
1.64M
        parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
3938
1.64M
      } else if (parser->m_defaultHandler)
3939
0
        reportDefault(parser, enc, s, next);
3940
1.64M
      break;
3941
300k
    case XML_TOK_DATA_CHARS: {
3942
300k
      XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
3943
300k
      if (charDataHandler) {
3944
300k
        if (MUST_CONVERT(enc, s)) {
3945
704
          for (;;) {
3946
704
            ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3947
704
            const enum XML_Convert_Result convert_res = XmlConvert(
3948
704
                enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3949
704
            *eventEndPP = next;
3950
704
            charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3951
704
                            (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
3952
704
            if ((convert_res == XML_CONVERT_COMPLETED)
3953
704
                || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3954
510
              break;
3955
194
            *eventPP = s;
3956
194
          }
3957
510
        } else
3958
300k
          charDataHandler(parser->m_handlerArg, (XML_Char *)s,
3959
300k
                          (int)((XML_Char *)next - (XML_Char *)s));
3960
300k
      } else if (parser->m_defaultHandler)
3961
0
        reportDefault(parser, enc, s, next);
3962
300k
    } break;
3963
22
    case XML_TOK_INVALID:
3964
22
      *eventPP = next;
3965
22
      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
48
    case XML_TOK_PARTIAL:
3973
264
    case XML_TOK_NONE:
3974
264
      if (haveMore) {
3975
126
        *nextPtr = s;
3976
126
        return XML_ERROR_NONE;
3977
126
      }
3978
138
      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
1.95M
    }
3991
3992
1.94M
    *eventPP = s = next;
3993
1.94M
    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
1.94M
    default:;
4000
1.94M
    }
4001
1.94M
  }
4002
  /* not reached */
4003
1.87k
}
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
10.0k
initializeEncoding(XML_Parser parser) {
4112
10.0k
  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
10.0k
  s = parser->m_protocolEncodingName;
4133
10.0k
#endif
4134
10.0k
  if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(
4135
10.0k
          &parser->m_initEncoding, &parser->m_encoding, s))
4136
10.0k
    return XML_ERROR_NONE;
4137
0
  return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
4138
10.0k
}
4139
4140
static enum XML_Error
4141
processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
4142
1.78k
               const char *next) {
4143
1.78k
  const char *encodingName = NULL;
4144
1.78k
  const XML_Char *storedEncName = NULL;
4145
1.78k
  const ENCODING *newEncoding = NULL;
4146
1.78k
  const char *version = NULL;
4147
1.78k
  const char *versionend;
4148
1.78k
  const XML_Char *storedversion = NULL;
4149
1.78k
  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.78k
  if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
4160
1.78k
          isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
4161
1.78k
          &version, &versionend, &encodingName, &newEncoding, &standalone)) {
4162
245
    if (isGeneralTextEntity)
4163
0
      return XML_ERROR_TEXT_DECL;
4164
245
    else
4165
245
      return XML_ERROR_XML_DECL;
4166
245
  }
4167
1.54k
  if (! isGeneralTextEntity && standalone == 1) {
4168
34
    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
34
  }
4175
1.54k
  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.54k
  } else if (parser->m_defaultHandler)
4194
0
    reportDefault(parser, parser->m_encoding, s, next);
4195
1.54k
  if (parser->m_protocolEncodingName == NULL) {
4196
1.54k
    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.41k
      if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
4203
1.41k
          || (newEncoding->minBytesPerChar == 2
4204
1.41k
              && newEncoding != parser->m_encoding)) {
4205
2
        parser->m_eventPtr = encodingName;
4206
2
        return XML_ERROR_INCORRECT_ENCODING;
4207
2
      }
4208
1.41k
      parser->m_encoding = newEncoding;
4209
1.41k
    } else if (encodingName) {
4210
45
      enum XML_Error result;
4211
45
      if (! storedEncName) {
4212
45
        storedEncName = poolStoreString(
4213
45
            &parser->m_temp2Pool, parser->m_encoding, encodingName,
4214
45
            encodingName + XmlNameLength(parser->m_encoding, encodingName));
4215
45
        if (! storedEncName)
4216
0
          return XML_ERROR_NO_MEMORY;
4217
45
      }
4218
45
      result = handleUnknownEncoding(parser, storedEncName);
4219
45
      poolClear(&parser->m_temp2Pool);
4220
45
      if (result == XML_ERROR_UNKNOWN_ENCODING)
4221
45
        parser->m_eventPtr = encodingName;
4222
45
      return result;
4223
45
    }
4224
1.54k
  }
4225
4226
1.49k
  if (storedEncName || storedversion)
4227
0
    poolClear(&parser->m_temp2Pool);
4228
4229
1.49k
  return XML_ERROR_NONE;
4230
1.54k
}
4231
4232
static enum XML_Error
4233
45
handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) {
4234
45
  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
45
  return XML_ERROR_UNKNOWN_ENCODING;
4264
45
}
4265
4266
static enum XML_Error PTRCALL
4267
prologInitProcessor(XML_Parser parser, const char *s, const char *end,
4268
10.0k
                    const char **nextPtr) {
4269
10.0k
  enum XML_Error result = initializeEncoding(parser);
4270
10.0k
  if (result != XML_ERROR_NONE)
4271
0
    return result;
4272
10.0k
  parser->m_processor = prologProcessor;
4273
10.0k
  return prologProcessor(parser, s, end, nextPtr);
4274
10.0k
}
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
12.7k
                const char **nextPtr) {
4469
12.7k
  const char *next = s;
4470
12.7k
  int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4471
12.7k
  return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
4472
12.7k
                  (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
4473
12.7k
                  XML_ACCOUNT_DIRECT);
4474
12.7k
}
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
12.7k
         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
12.7k
  static const XML_Char atypeCDATA[]
4484
12.7k
      = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
4485
12.7k
  static const XML_Char atypeID[] = {ASCII_I, ASCII_D, '\0'};
4486
12.7k
  static const XML_Char atypeIDREF[]
4487
12.7k
      = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'};
4488
12.7k
  static const XML_Char atypeIDREFS[]
4489
12.7k
      = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0'};
4490
12.7k
  static const XML_Char atypeENTITY[]
4491
12.7k
      = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0'};
4492
12.7k
  static const XML_Char atypeENTITIES[]
4493
12.7k
      = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T,
4494
12.7k
         ASCII_I, ASCII_E, ASCII_S, '\0'};
4495
12.7k
  static const XML_Char atypeNMTOKEN[]
4496
12.7k
      = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0'};
4497
12.7k
  static const XML_Char atypeNMTOKENS[]
4498
12.7k
      = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K,
4499
12.7k
         ASCII_E, ASCII_N, ASCII_S, '\0'};
4500
12.7k
  static const XML_Char notationPrefix[]
4501
12.7k
      = {ASCII_N, ASCII_O, ASCII_T, ASCII_A,      ASCII_T,
4502
12.7k
         ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0'};
4503
12.7k
  static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
4504
12.7k
  static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
4505
4506
12.7k
#ifndef XML_DTD
4507
12.7k
  UNUSED_P(account);
4508
12.7k
#endif
4509
4510
  /* save one level of indirection */
4511
12.7k
  DTD *const dtd = parser->m_dtd;
4512
4513
12.7k
  const char **eventPP;
4514
12.7k
  const char **eventEndPP;
4515
12.7k
  enum XML_Content_Quant quant;
4516
4517
12.7k
  if (enc == parser->m_encoding) {
4518
12.7k
    eventPP = &parser->m_eventPtr;
4519
12.7k
    eventEndPP = &parser->m_eventEndPtr;
4520
12.7k
  } else {
4521
0
    eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4522
0
    eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
4523
0
  }
4524
4525
7.06M
  for (;;) {
4526
7.06M
    int role;
4527
7.06M
    XML_Bool handleDefault = XML_TRUE;
4528
7.06M
    *eventPP = s;
4529
7.06M
    *eventEndPP = next;
4530
7.06M
    if (tok <= 0) {
4531
7.38k
      if (haveMore && tok != XML_TOK_INVALID) {
4532
2.68k
        *nextPtr = s;
4533
2.68k
        return XML_ERROR_NONE;
4534
2.68k
      }
4535
4.69k
      switch (tok) {
4536
871
      case XML_TOK_INVALID:
4537
871
        *eventPP = next;
4538
871
        return XML_ERROR_INVALID_TOKEN;
4539
438
      case XML_TOK_PARTIAL:
4540
438
        return XML_ERROR_UNCLOSED_TOKEN;
4541
116
      case XML_TOK_PARTIAL_CHAR:
4542
116
        return XML_ERROR_PARTIAL_CHAR;
4543
242
      case -XML_TOK_PROLOG_S:
4544
242
        tok = -tok;
4545
242
        break;
4546
1.83k
      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
1.83k
        return XML_ERROR_NO_ELEMENTS;
4567
1.20k
      default:
4568
1.20k
        tok = -tok;
4569
1.20k
        next = end;
4570
1.20k
        break;
4571
4.69k
      }
4572
4.69k
    }
4573
7.06M
    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
7.06M
    switch (role) {
4588
1.78k
    case XML_ROLE_XML_DECL: {
4589
1.78k
      enum XML_Error result = processXmlDecl(parser, 0, s, next);
4590
1.78k
      if (result != XML_ERROR_NONE)
4591
292
        return result;
4592
1.49k
      enc = parser->m_encoding;
4593
1.49k
      handleDefault = XML_FALSE;
4594
1.49k
    } break;
4595
4.91k
    case XML_ROLE_DOCTYPE_NAME:
4596
4.91k
      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
4.91k
      parser->m_doctypeSysid = NULL; /* always initialize to NULL */
4606
4.91k
      break;
4607
4.56k
    case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
4608
4.56k
      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
4.56k
      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
594
    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
594
      dtd->hasParamEntityRefs = XML_TRUE;
4635
594
      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
2.00k
    case XML_ROLE_ENTITY_PUBLIC_ID:
4652
2.00k
      if (! XmlIsPublicId(enc, s, next, eventPP))
4653
14
        return XML_ERROR_PUBLICID;
4654
1.98k
    alreadyChecked:
4655
1.98k
      if (dtd->keepProcessing && parser->m_declEntity) {
4656
600
        XML_Char *tem
4657
600
            = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
4658
600
                              next - enc->minBytesPerChar);
4659
600
        if (! tem)
4660
0
          return XML_ERROR_NO_MEMORY;
4661
600
        normalizePublicId(tem);
4662
600
        parser->m_declEntity->publicId = tem;
4663
600
        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
600
        if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID)
4668
0
          handleDefault = XML_FALSE;
4669
600
      }
4670
1.98k
      break;
4671
2.62k
    case XML_ROLE_DOCTYPE_CLOSE:
4672
2.62k
      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
2.62k
      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
2.62k
      if (parser->m_endDoctypeDeclHandler) {
4727
0
        parser->m_endDoctypeDeclHandler(parser->m_handlerArg);
4728
0
        handleDefault = XML_FALSE;
4729
0
      }
4730
2.62k
      break;
4731
5.73k
    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
5.73k
      parser->m_processor = contentProcessor;
4766
5.73k
      return contentProcessor(parser, s, end, nextPtr);
4767
23.3k
    case XML_ROLE_ATTLIST_ELEMENT_NAME:
4768
23.3k
      parser->m_declElementType = getElementType(parser, enc, s, next);
4769
23.3k
      if (! parser->m_declElementType)
4770
0
        return XML_ERROR_NO_MEMORY;
4771
23.3k
      goto checkAttListDeclHandler;
4772
91.1k
    case XML_ROLE_ATTRIBUTE_NAME:
4773
91.1k
      parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
4774
91.1k
      if (! parser->m_declAttributeId)
4775
0
        return XML_ERROR_NO_MEMORY;
4776
91.1k
      parser->m_declAttributeIsCdata = XML_FALSE;
4777
91.1k
      parser->m_declAttributeType = NULL;
4778
91.1k
      parser->m_declAttributeIsId = XML_FALSE;
4779
91.1k
      goto checkAttListDeclHandler;
4780
21.3k
    case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
4781
21.3k
      parser->m_declAttributeIsCdata = XML_TRUE;
4782
21.3k
      parser->m_declAttributeType = atypeCDATA;
4783
21.3k
      goto checkAttListDeclHandler;
4784
10.1k
    case XML_ROLE_ATTRIBUTE_TYPE_ID:
4785
10.1k
      parser->m_declAttributeIsId = XML_TRUE;
4786
10.1k
      parser->m_declAttributeType = atypeID;
4787
10.1k
      goto checkAttListDeclHandler;
4788
195
    case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
4789
195
      parser->m_declAttributeType = atypeIDREF;
4790
195
      goto checkAttListDeclHandler;
4791
251
    case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
4792
251
      parser->m_declAttributeType = atypeIDREFS;
4793
251
      goto checkAttListDeclHandler;
4794
195
    case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
4795
195
      parser->m_declAttributeType = atypeENTITY;
4796
195
      goto checkAttListDeclHandler;
4797
242
    case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
4798
242
      parser->m_declAttributeType = atypeENTITIES;
4799
242
      goto checkAttListDeclHandler;
4800
223
    case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
4801
223
      parser->m_declAttributeType = atypeNMTOKEN;
4802
223
      goto checkAttListDeclHandler;
4803
92
    case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
4804
92
      parser->m_declAttributeType = atypeNMTOKENS;
4805
147k
    checkAttListDeclHandler:
4806
147k
      if (dtd->keepProcessing && parser->m_attlistDeclHandler)
4807
0
        handleDefault = XML_FALSE;
4808
147k
      break;
4809
60.0k
    case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4810
61.2k
    case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
4811
61.2k
      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
61.2k
      break;
4827
61.2k
    case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4828
71.6k
    case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4829
71.6k
      if (dtd->keepProcessing) {
4830
71.6k
        if (! defineAttribute(parser->m_declElementType,
4831
71.6k
                              parser->m_declAttributeId,
4832
71.6k
                              parser->m_declAttributeIsCdata,
4833
71.6k
                              parser->m_declAttributeIsId, 0, parser))
4834
0
          return XML_ERROR_NO_MEMORY;
4835
71.6k
        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
71.6k
      }
4855
71.6k
      break;
4856
71.6k
    case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4857
19.1k
    case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4858
19.1k
      if (dtd->keepProcessing) {
4859
19.1k
        const XML_Char *attVal;
4860
19.1k
        enum XML_Error result = storeAttributeValue(
4861
19.1k
            parser, enc, parser->m_declAttributeIsCdata,
4862
19.1k
            s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool,
4863
19.1k
            XML_ACCOUNT_NONE);
4864
19.1k
        if (result)
4865
19
          return result;
4866
19.1k
        attVal = poolStart(&dtd->pool);
4867
19.1k
        poolFinish(&dtd->pool);
4868
        /* ID attributes aren't allowed to have a default */
4869
19.1k
        if (! defineAttribute(
4870
19.1k
                parser->m_declElementType, parser->m_declAttributeId,
4871
19.1k
                parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
4872
0
          return XML_ERROR_NO_MEMORY;
4873
19.1k
        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
19.1k
      }
4893
19.1k
      break;
4894
19.1k
    case XML_ROLE_ENTITY_VALUE:
4895
10.0k
      if (dtd->keepProcessing) {
4896
10.0k
        enum XML_Error result
4897
10.0k
            = storeEntityValue(parser, enc, s + enc->minBytesPerChar,
4898
10.0k
                               next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
4899
10.0k
        if (parser->m_declEntity) {
4900
6.22k
          parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
4901
6.22k
          parser->m_declEntity->textLen
4902
6.22k
              = (int)(poolLength(&dtd->entityValuePool));
4903
6.22k
          poolFinish(&dtd->entityValuePool);
4904
6.22k
          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
6.22k
        } else
4913
3.86k
          poolDiscard(&dtd->entityValuePool);
4914
10.0k
        if (result != XML_ERROR_NONE)
4915
24
          return result;
4916
10.0k
      }
4917
10.0k
      break;
4918
10.0k
    case XML_ROLE_DOCTYPE_SYSTEM_ID:
4919
#ifdef XML_DTD
4920
      parser->m_useForeignDTD = XML_FALSE;
4921
#endif /* XML_DTD */
4922
434
      dtd->hasParamEntityRefs = XML_TRUE;
4923
434
      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
434
      if (! dtd->standalone
4939
#ifdef XML_DTD
4940
          && ! parser->m_paramEntityParsing
4941
#endif /* XML_DTD */
4942
434
          && parser->m_notStandaloneHandler
4943
434
          && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
4944
0
        return XML_ERROR_NOT_STANDALONE;
4945
434
#ifndef XML_DTD
4946
434
      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
3.13k
    case XML_ROLE_ENTITY_SYSTEM_ID:
4958
3.13k
      if (dtd->keepProcessing && parser->m_declEntity) {
4959
627
        parser->m_declEntity->systemId
4960
627
            = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
4961
627
                              next - enc->minBytesPerChar);
4962
627
        if (! parser->m_declEntity->systemId)
4963
0
          return XML_ERROR_NO_MEMORY;
4964
627
        parser->m_declEntity->base = parser->m_curBase;
4965
627
        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
627
        if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID)
4970
0
          handleDefault = XML_FALSE;
4971
627
      }
4972
3.13k
      break;
4973
3.13k
    case XML_ROLE_ENTITY_COMPLETE:
4974
2.65k
      if (dtd->keepProcessing && parser->m_declEntity
4975
2.65k
          && 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.65k
      break;
4984
432
    case XML_ROLE_ENTITY_NOTATION_NAME:
4985
432
      if (dtd->keepProcessing && parser->m_declEntity) {
4986
69
        parser->m_declEntity->notation
4987
69
            = poolStoreString(&dtd->pool, enc, s, next);
4988
69
        if (! parser->m_declEntity->notation)
4989
0
          return XML_ERROR_NO_MEMORY;
4990
69
        poolFinish(&dtd->pool);
4991
69
        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
69
        } 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
69
      }
5007
432
      break;
5008
11.6k
    case XML_ROLE_GENERAL_ENTITY_NAME: {
5009
11.6k
      if (XmlPredefinedEntityName(enc, s, next)) {
5010
207
        parser->m_declEntity = NULL;
5011
207
        break;
5012
207
      }
5013
11.4k
      if (dtd->keepProcessing) {
5014
11.4k
        const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
5015
11.4k
        if (! name)
5016
0
          return XML_ERROR_NO_MEMORY;
5017
11.4k
        parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities,
5018
11.4k
                                                name, sizeof(ENTITY));
5019
11.4k
        if (! parser->m_declEntity)
5020
0
          return XML_ERROR_NO_MEMORY;
5021
11.4k
        if (parser->m_declEntity->name != name) {
5022
4.46k
          poolDiscard(&dtd->pool);
5023
4.46k
          parser->m_declEntity = NULL;
5024
6.95k
        } else {
5025
6.95k
          poolFinish(&dtd->pool);
5026
6.95k
          parser->m_declEntity->publicId = NULL;
5027
6.95k
          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
6.95k
          parser->m_declEntity->is_internal
5032
6.95k
              = ! (parser->m_parentParser || parser->m_openInternalEntities);
5033
6.95k
          if (parser->m_entityDeclHandler)
5034
0
            handleDefault = XML_FALSE;
5035
6.95k
        }
5036
11.4k
      } else {
5037
0
        poolDiscard(&dtd->pool);
5038
0
        parser->m_declEntity = NULL;
5039
0
      }
5040
11.4k
    } break;
5041
11.4k
    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
1.83k
      parser->m_declEntity = NULL;
5072
1.83k
#endif /* XML_DTD */
5073
1.83k
      break;
5074
1.40k
    case XML_ROLE_NOTATION_NAME:
5075
1.40k
      parser->m_declNotationPublicId = NULL;
5076
1.40k
      parser->m_declNotationName = NULL;
5077
1.40k
      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.40k
      break;
5086
1.40k
    case XML_ROLE_NOTATION_PUBLIC_ID:
5087
706
      if (! XmlIsPublicId(enc, s, next, eventPP))
5088
1
        return XML_ERROR_PUBLICID;
5089
705
      if (parser
5090
705
              ->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
705
      break;
5102
722
    case XML_ROLE_NOTATION_SYSTEM_ID:
5103
722
      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
722
      poolClear(&parser->m_tempPool);
5116
722
      break;
5117
614
    case XML_ROLE_NOTATION_NO_SYSTEM_ID:
5118
614
      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
614
      poolClear(&parser->m_tempPool);
5126
614
      break;
5127
682
    case XML_ROLE_ERROR:
5128
682
      switch (tok) {
5129
2
      case XML_TOK_PARAM_ENTITY_REF:
5130
        /* PE references in internal subset are
5131
           not allowed within declarations. */
5132
2
        return XML_ERROR_PARAM_ENTITY_REF;
5133
1
      case XML_TOK_XML_DECL:
5134
1
        return XML_ERROR_MISPLACED_XML_PI;
5135
679
      default:
5136
679
        return XML_ERROR_SYNTAX;
5137
682
      }
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
5.72M
    case XML_ROLE_GROUP_OPEN:
5154
5.72M
      if (parser->m_prologState.level >= parser->m_groupSize) {
5155
1.05k
        if (parser->m_groupSize) {
5156
533
          {
5157
            /* Detect and prevent integer overflow */
5158
533
            if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
5159
0
              return XML_ERROR_NO_MEMORY;
5160
0
            }
5161
5162
533
            char *const new_connector = (char *)REALLOC(
5163
533
                parser, parser->m_groupConnector, parser->m_groupSize *= 2);
5164
533
            if (new_connector == NULL) {
5165
0
              parser->m_groupSize /= 2;
5166
0
              return XML_ERROR_NO_MEMORY;
5167
0
            }
5168
533
            parser->m_groupConnector = new_connector;
5169
533
          }
5170
5171
533
          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
533
        } else {
5189
521
          parser->m_groupConnector
5190
521
              = (char *)MALLOC(parser, parser->m_groupSize = 32);
5191
521
          if (! parser->m_groupConnector) {
5192
0
            parser->m_groupSize = 0;
5193
0
            return XML_ERROR_NO_MEMORY;
5194
0
          }
5195
521
        }
5196
1.05k
      }
5197
5.72M
      parser->m_groupConnector[parser->m_prologState.level] = 0;
5198
5.72M
      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
5.72M
      break;
5210
5.72M
    case XML_ROLE_GROUP_SEQUENCE:
5211
46.0k
      if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE)
5212
1
        return XML_ERROR_SYNTAX;
5213
46.0k
      parser->m_groupConnector[parser->m_prologState.level] = ASCII_COMMA;
5214
46.0k
      if (dtd->in_eldecl && parser->m_elementDeclHandler)
5215
0
        handleDefault = XML_FALSE;
5216
46.0k
      break;
5217
52.3k
    case XML_ROLE_GROUP_CHOICE:
5218
52.3k
      if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
5219
1
        return XML_ERROR_SYNTAX;
5220
52.3k
      if (dtd->in_eldecl
5221
52.3k
          && ! parser->m_groupConnector[parser->m_prologState.level]
5222
52.3k
          && (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
52.3k
      parser->m_groupConnector[parser->m_prologState.level] = ASCII_PIPE;
5230
52.3k
      break;
5231
1.32k
    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.32k
      if (! dtd->standalone && parser->m_notStandaloneHandler
5325
1.32k
          && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
5326
0
        return XML_ERROR_NOT_STANDALONE;
5327
1.32k
      break;
5328
5329
      /* Element declaration stuff */
5330
5331
4.26k
    case XML_ROLE_ELEMENT_NAME:
5332
4.26k
      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
4.26k
      break;
5342
5343
4.26k
    case XML_ROLE_CONTENT_ANY:
5344
556
    case XML_ROLE_CONTENT_EMPTY:
5345
556
      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
556
      break;
5365
5366
1.26k
    case XML_ROLE_CONTENT_PCDATA:
5367
1.26k
      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
1.26k
      break;
5374
5375
81.9k
    case XML_ROLE_CONTENT_ELEMENT:
5376
81.9k
      quant = XML_CQUANT_NONE;
5377
81.9k
      goto elementContent;
5378
492
    case XML_ROLE_CONTENT_ELEMENT_OPT:
5379
492
      quant = XML_CQUANT_OPT;
5380
492
      goto elementContent;
5381
3.26k
    case XML_ROLE_CONTENT_ELEMENT_REP:
5382
3.26k
      quant = XML_CQUANT_REP;
5383
3.26k
      goto elementContent;
5384
16.3k
    case XML_ROLE_CONTENT_ELEMENT_PLUS:
5385
16.3k
      quant = XML_CQUANT_PLUS;
5386
102k
    elementContent:
5387
102k
      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
102k
      break;
5417
5418
102k
    case XML_ROLE_GROUP_CLOSE:
5419
63.9k
      quant = XML_CQUANT_NONE;
5420
63.9k
      goto closeGroup;
5421
34.8k
    case XML_ROLE_GROUP_CLOSE_OPT:
5422
34.8k
      quant = XML_CQUANT_OPT;
5423
34.8k
      goto closeGroup;
5424
9.18k
    case XML_ROLE_GROUP_CLOSE_REP:
5425
9.18k
      quant = XML_CQUANT_REP;
5426
9.18k
      goto closeGroup;
5427
31.0k
    case XML_ROLE_GROUP_CLOSE_PLUS:
5428
31.0k
      quant = XML_CQUANT_PLUS;
5429
138k
    closeGroup:
5430
138k
      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
138k
      break;
5449
      /* End element declaration stuff */
5450
5451
138k
    case XML_ROLE_PI:
5452
1.86k
      if (! reportProcessingInstruction(parser, enc, s, next))
5453
0
        return XML_ERROR_NO_MEMORY;
5454
1.86k
      handleDefault = XML_FALSE;
5455
1.86k
      break;
5456
801
    case XML_ROLE_COMMENT:
5457
801
      if (! reportComment(parser, enc, s, next))
5458
0
        return XML_ERROR_NO_MEMORY;
5459
801
      handleDefault = XML_FALSE;
5460
801
      break;
5461
5.92k
    case XML_ROLE_NONE:
5462
5.92k
      switch (tok) {
5463
351
      case XML_TOK_BOM:
5464
351
        handleDefault = XML_FALSE;
5465
351
        break;
5466
5.92k
      }
5467
5.92k
      break;
5468
14.7k
    case XML_ROLE_DOCTYPE_NONE:
5469
14.7k
      if (parser->m_startDoctypeDeclHandler)
5470
0
        handleDefault = XML_FALSE;
5471
14.7k
      break;
5472
65.2k
    case XML_ROLE_ENTITY_NONE:
5473
65.2k
      if (dtd->keepProcessing && parser->m_entityDeclHandler)
5474
0
        handleDefault = XML_FALSE;
5475
65.2k
      break;
5476
8.13k
    case XML_ROLE_NOTATION_NONE:
5477
8.13k
      if (parser->m_notationDeclHandler)
5478
0
        handleDefault = XML_FALSE;
5479
8.13k
      break;
5480
466k
    case XML_ROLE_ATTLIST_NONE:
5481
466k
      if (dtd->keepProcessing && parser->m_attlistDeclHandler)
5482
0
        handleDefault = XML_FALSE;
5483
466k
      break;
5484
77.1k
    case XML_ROLE_ELEMENT_NONE:
5485
77.1k
      if (parser->m_elementDeclHandler)
5486
0
        handleDefault = XML_FALSE;
5487
77.1k
      break;
5488
7.06M
    } /* end of big switch */
5489
5490
7.05M
    if (handleDefault && parser->m_defaultHandler)
5491
0
      reportDefault(parser, enc, s, next);
5492
5493
7.05M
    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
7.05M
    default:
5500
7.05M
      s = next;
5501
7.05M
      tok = XmlPrologTok(enc, s, end, &next);
5502
7.05M
    }
5503
7.05M
  }
5504
  /* not reached */
5505
12.7k
}
5506
5507
static enum XML_Error PTRCALL
5508
epilogProcessor(XML_Parser parser, const char *s, const char *end,
5509
4.26k
                const char **nextPtr) {
5510
4.26k
  parser->m_processor = epilogProcessor;
5511
4.26k
  parser->m_eventPtr = s;
5512
5.39k
  for (;;) {
5513
5.39k
    const char *next = NULL;
5514
5.39k
    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
5.39k
    parser->m_eventEndPtr = next;
5523
5.39k
    switch (tok) {
5524
    /* report partial linebreak - it might be the last token */
5525
5
    case -XML_TOK_PROLOG_S:
5526
5
      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
5
      *nextPtr = next;
5532
5
      return XML_ERROR_NONE;
5533
4.21k
    case XML_TOK_NONE:
5534
4.21k
      *nextPtr = s;
5535
4.21k
      return XML_ERROR_NONE;
5536
420
    case XML_TOK_PROLOG_S:
5537
420
      if (parser->m_defaultHandler)
5538
0
        reportDefault(parser, parser->m_encoding, s, next);
5539
420
      break;
5540
520
    case XML_TOK_PI:
5541
520
      if (! reportProcessingInstruction(parser, parser->m_encoding, s, next))
5542
0
        return XML_ERROR_NO_MEMORY;
5543
520
      break;
5544
520
    case XML_TOK_COMMENT:
5545
194
      if (! reportComment(parser, parser->m_encoding, s, next))
5546
0
        return XML_ERROR_NO_MEMORY;
5547
194
      break;
5548
194
    case XML_TOK_INVALID:
5549
6
      parser->m_eventPtr = next;
5550
6
      return XML_ERROR_INVALID_TOKEN;
5551
6
    case XML_TOK_PARTIAL:
5552
6
      if (! parser->m_parsingStatus.finalBuffer) {
5553
3
        *nextPtr = s;
5554
3
        return XML_ERROR_NONE;
5555
3
      }
5556
3
      return XML_ERROR_UNCLOSED_TOKEN;
5557
4
    case XML_TOK_PARTIAL_CHAR:
5558
4
      if (! parser->m_parsingStatus.finalBuffer) {
5559
2
        *nextPtr = s;
5560
2
        return XML_ERROR_NONE;
5561
2
      }
5562
2
      return XML_ERROR_PARTIAL_CHAR;
5563
28
    default:
5564
28
      return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
5565
5.39k
    }
5566
1.13k
    parser->m_eventPtr = s = next;
5567
1.13k
    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
1.13k
    default:;
5574
1.13k
    }
5575
1.13k
  }
5576
4.26k
}
5577
5578
static enum XML_Error
5579
29.8k
processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
5580
29.8k
  const char *textStart, *textEnd;
5581
29.8k
  const char *next;
5582
29.8k
  enum XML_Error result;
5583
29.8k
  OPEN_INTERNAL_ENTITY *openEntity;
5584
5585
29.8k
  if (parser->m_freeInternalEntities) {
5586
27.4k
    openEntity = parser->m_freeInternalEntities;
5587
27.4k
    parser->m_freeInternalEntities = openEntity->next;
5588
27.4k
  } else {
5589
2.33k
    openEntity
5590
2.33k
        = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
5591
2.33k
    if (! openEntity)
5592
0
      return XML_ERROR_NO_MEMORY;
5593
2.33k
  }
5594
29.8k
  entity->open = XML_TRUE;
5595
#ifdef XML_DTD
5596
  entityTrackingOnOpen(parser, entity, __LINE__);
5597
#endif
5598
29.8k
  entity->processed = 0;
5599
29.8k
  openEntity->next = parser->m_openInternalEntities;
5600
29.8k
  parser->m_openInternalEntities = openEntity;
5601
29.8k
  openEntity->entity = entity;
5602
29.8k
  openEntity->startTagLevel = parser->m_tagLevel;
5603
29.8k
  openEntity->betweenDecl = betweenDecl;
5604
29.8k
  openEntity->internalEventPtr = NULL;
5605
29.8k
  openEntity->internalEventEndPtr = NULL;
5606
29.8k
  textStart = (const char *)entity->textPtr;
5607
29.8k
  textEnd = (const char *)(entity->textPtr + entity->textLen);
5608
  /* Set a safe default value in case 'next' does not get set */
5609
29.8k
  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
29.8k
    result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
5621
29.8k
                       textStart, textEnd, &next, XML_FALSE,
5622
29.8k
                       XML_ACCOUNT_ENTITY_EXPANSION);
5623
5624
29.8k
  if (result == XML_ERROR_NONE) {
5625
29.3k
    if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
5626
0
      entity->processed = (int)(next - textStart);
5627
0
      parser->m_processor = internalEntityProcessor;
5628
29.3k
    } else {
5629
#ifdef XML_DTD
5630
      entityTrackingOnClose(parser, entity, __LINE__);
5631
#endif /* XML_DTD */
5632
29.3k
      entity->open = XML_FALSE;
5633
29.3k
      parser->m_openInternalEntities = openEntity->next;
5634
      /* put openEntity back in list of free instances */
5635
29.3k
      openEntity->next = parser->m_freeInternalEntities;
5636
29.3k
      parser->m_freeInternalEntities = openEntity;
5637
29.3k
    }
5638
29.3k
  }
5639
29.8k
  return result;
5640
29.8k
}
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
32.3k
                    enum XML_Account account) {
5722
32.3k
  enum XML_Error result
5723
32.3k
      = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
5724
32.3k
  if (result)
5725
71
    return result;
5726
32.2k
  if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
5727
2.18k
    poolChop(pool);
5728
32.2k
  if (! poolAppendChar(pool, XML_T('\0')))
5729
0
    return XML_ERROR_NO_MEMORY;
5730
32.2k
  return XML_ERROR_NONE;
5731
32.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
28.1M
                     enum XML_Account account) {
5737
28.1M
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5738
28.1M
#ifndef XML_DTD
5739
28.1M
  UNUSED_P(account);
5740
28.1M
#endif
5741
5742
159M
  for (;;) {
5743
159M
    const char *next
5744
159M
        = ptr; /* XmlAttributeValueTok doesn't always set the last arg */
5745
159M
    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
159M
    switch (tok) {
5753
28.1M
    case XML_TOK_NONE:
5754
28.1M
      return XML_ERROR_NONE;
5755
7
    case XML_TOK_INVALID:
5756
7
      if (enc == parser->m_encoding)
5757
6
        parser->m_eventPtr = next;
5758
7
      return XML_ERROR_INVALID_TOKEN;
5759
4
    case XML_TOK_PARTIAL:
5760
4
      if (enc == parser->m_encoding)
5761
3
        parser->m_eventPtr = ptr;
5762
4
      return XML_ERROR_INVALID_TOKEN;
5763
30.4k
    case XML_TOK_CHAR_REF: {
5764
30.4k
      XML_Char buf[XML_ENCODE_MAX];
5765
30.4k
      int i;
5766
30.4k
      int n = XmlCharRefNumber(enc, ptr);
5767
30.4k
      if (n < 0) {
5768
11
        if (enc == parser->m_encoding)
5769
7
          parser->m_eventPtr = ptr;
5770
11
        return XML_ERROR_BAD_CHAR_REF;
5771
11
      }
5772
30.4k
      if (! isCdata && n == 0x20 /* space */
5773
30.4k
          && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5774
420
        break;
5775
30.0k
      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
145k
      for (i = 0; i < n; i++) {
5786
115k
        if (! poolAppendChar(pool, buf[i]))
5787
0
          return XML_ERROR_NO_MEMORY;
5788
115k
      }
5789
30.0k
    } break;
5790
21.7M
    case XML_TOK_DATA_CHARS:
5791
21.7M
      if (! poolAppend(pool, enc, ptr, next))
5792
4
        return XML_ERROR_NO_MEMORY;
5793
21.7M
      break;
5794
21.7M
    case XML_TOK_TRAILING_CR:
5795
695
      next = ptr + enc->minBytesPerChar;
5796
      /* fall through */
5797
6.24M
    case XML_TOK_ATTRIBUTE_VALUE_S:
5798
81.3M
    case XML_TOK_DATA_NEWLINE:
5799
81.3M
      if (! isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5800
37.5k
        break;
5801
81.2M
      if (! poolAppendChar(pool, 0x20))
5802
0
        return XML_ERROR_NO_MEMORY;
5803
81.2M
      break;
5804
81.2M
    case XML_TOK_ENTITY_REF: {
5805
28.3M
      const XML_Char *name;
5806
28.3M
      ENTITY *entity;
5807
28.3M
      char checkEntityDecl;
5808
28.3M
      XML_Char ch = (XML_Char)XmlPredefinedEntityName(
5809
28.3M
          enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
5810
28.3M
      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
2.56k
        if (! poolAppendChar(pool, ch))
5820
0
          return XML_ERROR_NO_MEMORY;
5821
2.56k
        break;
5822
2.56k
      }
5823
28.3M
      name = poolStoreString(&parser->m_temp2Pool, enc,
5824
28.3M
                             ptr + enc->minBytesPerChar,
5825
28.3M
                             next - enc->minBytesPerChar);
5826
28.3M
      if (! name)
5827
0
        return XML_ERROR_NO_MEMORY;
5828
28.3M
      entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
5829
28.3M
      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
28.3M
      if (pool == &dtd->pool) /* are we called from prolog? */
5834
69.7k
        checkEntityDecl =
5835
#ifdef XML_DTD
5836
            parser->m_prologState.documentEntity &&
5837
#endif /* XML_DTD */
5838
69.7k
            (dtd->standalone ? ! parser->m_openInternalEntities
5839
69.7k
                             : ! dtd->hasParamEntityRefs);
5840
28.2M
      else /* if (pool == &parser->m_tempPool): we are called from content */
5841
28.2M
        checkEntityDecl = ! dtd->hasParamEntityRefs || dtd->standalone;
5842
28.3M
      if (checkEntityDecl) {
5843
27.9M
        if (! entity)
5844
40
          return XML_ERROR_UNDEFINED_ENTITY;
5845
27.9M
        else if (! entity->is_internal)
5846
0
          return XML_ERROR_ENTITY_DECLARED_IN_PE;
5847
27.9M
      } 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
211k
        break;
5859
211k
      }
5860
28.1M
      if (entity->open) {
5861
1
        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
1
        return XML_ERROR_RECURSIVE_ENTITY_REF;
5882
1
      }
5883
28.1M
      if (entity->notation) {
5884
2
        if (enc == parser->m_encoding)
5885
1
          parser->m_eventPtr = ptr;
5886
2
        return XML_ERROR_BINARY_ENTITY_REF;
5887
2
      }
5888
28.1M
      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
28.1M
      } else {
5893
28.1M
        enum XML_Error result;
5894
28.1M
        const XML_Char *textEnd = entity->textPtr + entity->textLen;
5895
28.1M
        entity->open = XML_TRUE;
5896
#ifdef XML_DTD
5897
        entityTrackingOnOpen(parser, entity, __LINE__);
5898
#endif
5899
28.1M
        result = appendAttributeValue(parser, parser->m_internalEncoding,
5900
28.1M
                                      isCdata, (const char *)entity->textPtr,
5901
28.1M
                                      (const char *)textEnd, pool,
5902
28.1M
                                      XML_ACCOUNT_ENTITY_EXPANSION);
5903
#ifdef XML_DTD
5904
        entityTrackingOnClose(parser, entity, __LINE__);
5905
#endif
5906
28.1M
        entity->open = XML_FALSE;
5907
28.1M
        if (result)
5908
60
          return result;
5909
28.1M
      }
5910
28.1M
    } break;
5911
28.1M
    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
159M
    }
5928
131M
    ptr = next;
5929
131M
  }
5930
  /* not reached */
5931
28.1M
}
5932
5933
static enum XML_Error
5934
storeEntityValue(XML_Parser parser, const ENCODING *enc,
5935
                 const char *entityTextPtr, const char *entityTextEnd,
5936
10.0k
                 enum XML_Account account) {
5937
10.0k
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
5938
10.0k
  STRING_POOL *pool = &(dtd->entityValuePool);
5939
10.0k
  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
10.0k
  UNUSED_P(account);
5945
10.0k
#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
10.0k
  if (! pool->blocks) {
5950
2.73k
    if (! poolGrow(pool))
5951
0
      return XML_ERROR_NO_MEMORY;
5952
2.73k
  }
5953
5954
1.32M
  for (;;) {
5955
1.32M
    const char *next
5956
1.32M
        = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */
5957
1.32M
    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
1.32M
    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
10.0k
    case XML_TOK_NONE:
6039
10.0k
      result = XML_ERROR_NONE;
6040
10.0k
      goto endEntityValue;
6041
21.9k
    case XML_TOK_ENTITY_REF:
6042
290k
    case XML_TOK_DATA_CHARS:
6043
290k
      if (! poolAppend(pool, enc, entityTextPtr, next)) {
6044
0
        result = XML_ERROR_NO_MEMORY;
6045
0
        goto endEntityValue;
6046
0
      }
6047
290k
      break;
6048
290k
    case XML_TOK_TRAILING_CR:
6049
306
      next = entityTextPtr + enc->minBytesPerChar;
6050
      /* fall through */
6051
990k
    case XML_TOK_DATA_NEWLINE:
6052
990k
      if (pool->end == pool->ptr && ! poolGrow(pool)) {
6053
0
        result = XML_ERROR_NO_MEMORY;
6054
0
        goto endEntityValue;
6055
0
      }
6056
990k
      *(pool->ptr)++ = 0xA;
6057
990k
      break;
6058
29.3k
    case XML_TOK_CHAR_REF: {
6059
29.3k
      XML_Char buf[XML_ENCODE_MAX];
6060
29.3k
      int i;
6061
29.3k
      int n = XmlCharRefNumber(enc, entityTextPtr);
6062
29.3k
      if (n < 0) {
6063
3
        if (enc == parser->m_encoding)
6064
3
          parser->m_eventPtr = entityTextPtr;
6065
3
        result = XML_ERROR_BAD_CHAR_REF;
6066
3
        goto endEntityValue;
6067
3
      }
6068
29.3k
      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
108k
      for (i = 0; i < n; i++) {
6079
79.1k
        if (pool->end == pool->ptr && ! poolGrow(pool)) {
6080
0
          result = XML_ERROR_NO_MEMORY;
6081
0
          goto endEntityValue;
6082
0
        }
6083
79.1k
        *(pool->ptr)++ = buf[i];
6084
79.1k
      }
6085
29.3k
    } break;
6086
29.3k
    case XML_TOK_PARTIAL:
6087
16
      if (enc == parser->m_encoding)
6088
16
        parser->m_eventPtr = entityTextPtr;
6089
16
      result = XML_ERROR_INVALID_TOKEN;
6090
16
      goto endEntityValue;
6091
4
    case XML_TOK_INVALID:
6092
4
      if (enc == parser->m_encoding)
6093
4
        parser->m_eventPtr = next;
6094
4
      result = XML_ERROR_INVALID_TOKEN;
6095
4
      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
1.32M
    }
6110
1.31M
    entityTextPtr = next;
6111
1.31M
  }
6112
10.0k
endEntityValue:
6113
#ifdef XML_DTD
6114
  parser->m_prologState.inEntityValue = oldInEntityValue;
6115
#endif /* XML_DTD */
6116
10.0k
  return result;
6117
10.0k
}
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
14.1k
                            const char *start, const char *end) {
6143
14.1k
  const XML_Char *target;
6144
14.1k
  XML_Char *data;
6145
14.1k
  const char *tem;
6146
14.1k
  if (! parser->m_processingInstructionHandler) {
6147
14.1k
    if (parser->m_defaultHandler)
6148
0
      reportDefault(parser, enc, start, end);
6149
14.1k
    return 1;
6150
14.1k
  }
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
7.74k
              const char *end) {
6170
7.74k
  XML_Char *data;
6171
7.74k
  if (! parser->m_commentHandler) {
6172
7.74k
    if (parser->m_defaultHandler)
6173
0
      reportDefault(parser, enc, start, end);
6174
7.74k
    return 1;
6175
7.74k
  }
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
90.7k
                XML_Bool isId, const XML_Char *value, XML_Parser parser) {
6236
90.7k
  DEFAULT_ATTRIBUTE *att;
6237
90.7k
  if (value || isId) {
6238
    /* The handling of default attributes gets messed up if we have
6239
       a default which duplicates a non-default. */
6240
21.7k
    int i;
6241
111k
    for (i = 0; i < type->nDefaultAtts; i++)
6242
106k
      if (attId == type->defaultAtts[i].id)
6243
17.5k
        return 1;
6244
4.16k
    if (isId && ! type->idAtt && ! attId->xmlns)
6245
580
      type->idAtt = attId;
6246
4.16k
  }
6247
73.2k
  if (type->nDefaultAtts == type->allocDefaultAtts) {
6248
2.17k
    if (type->allocDefaultAtts == 0) {
6249
1.74k
      type->allocDefaultAtts = 8;
6250
1.74k
      type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(
6251
1.74k
          parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6252
1.74k
      if (! type->defaultAtts) {
6253
0
        type->allocDefaultAtts = 0;
6254
0
        return 0;
6255
0
      }
6256
1.74k
    } else {
6257
435
      DEFAULT_ATTRIBUTE *temp;
6258
6259
      /* Detect and prevent integer overflow */
6260
435
      if (type->allocDefaultAtts > INT_MAX / 2) {
6261
0
        return 0;
6262
0
      }
6263
6264
435
      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
435
      temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
6277
435
                                          (count * sizeof(DEFAULT_ATTRIBUTE)));
6278
435
      if (temp == NULL)
6279
0
        return 0;
6280
435
      type->allocDefaultAtts = count;
6281
435
      type->defaultAtts = temp;
6282
435
    }
6283
2.17k
  }
6284
73.2k
  att = type->defaultAtts + type->nDefaultAtts;
6285
73.2k
  att->id = attId;
6286
73.2k
  att->value = value;
6287
73.2k
  att->isCdata = isCdata;
6288
73.2k
  if (! isCdata)
6289
52.0k
    attId->maybeTokenized = XML_TRUE;
6290
73.2k
  type->nDefaultAtts += 1;
6291
73.2k
  return 1;
6292
73.2k
}
6293
6294
static int
6295
7.80k
setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) {
6296
7.80k
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6297
7.80k
  const XML_Char *name;
6298
1.47M
  for (name = elementType->name; *name; name++) {
6299
1.47M
    if (*name == XML_T(ASCII_COLON)) {
6300
4.78k
      PREFIX *prefix;
6301
4.78k
      const XML_Char *s;
6302
1.22M
      for (s = elementType->name; s != name; s++) {
6303
1.22M
        if (! poolAppendChar(&dtd->pool, *s))
6304
0
          return 0;
6305
1.22M
      }
6306
4.78k
      if (! poolAppendChar(&dtd->pool, XML_T('\0')))
6307
0
        return 0;
6308
4.78k
      prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
6309
4.78k
                                sizeof(PREFIX));
6310
4.78k
      if (! prefix)
6311
0
        return 0;
6312
4.78k
      if (prefix->name == poolStart(&dtd->pool))
6313
3.99k
        poolFinish(&dtd->pool);
6314
790
      else
6315
790
        poolDiscard(&dtd->pool);
6316
4.78k
      elementType->prefix = prefix;
6317
4.78k
      break;
6318
4.78k
    }
6319
1.47M
  }
6320
7.80k
  return 1;
6321
7.80k
}
6322
6323
static ATTRIBUTE_ID *
6324
getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
6325
186k
               const char *end) {
6326
186k
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
6327
186k
  ATTRIBUTE_ID *id;
6328
186k
  const XML_Char *name;
6329
186k
  if (! poolAppendChar(&dtd->pool, XML_T('\0')))
6330
0
    return NULL;
6331
186k
  name = poolStoreString(&dtd->pool, enc, start, end);
6332
186k
  if (! name)
6333
0
    return NULL;
6334
  /* skip quotation mark - its storage will be re-used (like in name[-1]) */
6335
186k
  ++name;
6336
186k
  id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name,
6337
186k
                              sizeof(ATTRIBUTE_ID));
6338
186k
  if (! id)
6339
0
    return NULL;
6340
186k
  if (id->name != name)
6341
176k
    poolDiscard(&dtd->pool);
6342
9.74k
  else {
6343
9.74k
    poolFinish(&dtd->pool);
6344
9.74k
    if (! parser->m_ns)
6345
9.74k
      ;
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
9.74k
  }
6381
186k
  return id;
6382
186k
}
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
600
normalizePublicId(XML_Char *publicId) {
6544
600
  XML_Char *p = publicId;
6545
600
  XML_Char *s;
6546
12.6k
  for (s = publicId; *s; s++) {
6547
12.0k
    switch (*s) {
6548
661
    case 0x20:
6549
1.49k
    case 0xD:
6550
4.37k
    case 0xA:
6551
4.37k
      if (p != publicId && p[-1] != 0x20)
6552
656
        *p++ = 0x20;
6553
4.37k
      break;
6554
7.63k
    default:
6555
7.63k
      *p++ = *s;
6556
12.0k
    }
6557
12.0k
  }
6558
600
  if (p != publicId && p[-1] == 0x20)
6559
194
    --p;
6560
600
  *p = XML_T('\0');
6561
600
}
6562
6563
static DTD *
6564
10.0k
dtdCreate(const XML_Memory_Handling_Suite *ms) {
6565
10.0k
  DTD *p = ms->malloc_fcn(sizeof(DTD));
6566
10.0k
  if (p == NULL)
6567
0
    return p;
6568
10.0k
  poolInit(&(p->pool), ms);
6569
10.0k
  poolInit(&(p->entityValuePool), ms);
6570
10.0k
  hashTableInit(&(p->generalEntities), ms);
6571
10.0k
  hashTableInit(&(p->elementTypes), ms);
6572
10.0k
  hashTableInit(&(p->attributeIds), ms);
6573
10.0k
  hashTableInit(&(p->prefixes), ms);
6574
#ifdef XML_DTD
6575
  p->paramEntityRead = XML_FALSE;
6576
  hashTableInit(&(p->paramEntities), ms);
6577
#endif /* XML_DTD */
6578
10.0k
  p->defaultPrefix.name = NULL;
6579
10.0k
  p->defaultPrefix.binding = NULL;
6580
6581
10.0k
  p->in_eldecl = XML_FALSE;
6582
10.0k
  p->scaffIndex = NULL;
6583
10.0k
  p->scaffold = NULL;
6584
10.0k
  p->scaffLevel = 0;
6585
10.0k
  p->scaffSize = 0;
6586
10.0k
  p->scaffCount = 0;
6587
10.0k
  p->contentStringLen = 0;
6588
6589
10.0k
  p->keepProcessing = XML_TRUE;
6590
10.0k
  p->hasParamEntityRefs = XML_FALSE;
6591
10.0k
  p->standalone = XML_FALSE;
6592
10.0k
  return p;
6593
10.0k
}
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
10.0k
dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
6638
10.0k
  HASH_TABLE_ITER iter;
6639
10.0k
  hashTableIterInit(&iter, &(p->elementTypes));
6640
32.6k
  for (;;) {
6641
32.6k
    ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6642
32.6k
    if (! e)
6643
10.0k
      break;
6644
22.6k
    if (e->allocDefaultAtts != 0)
6645
1.74k
      ms->free_fcn(e->defaultAtts);
6646
22.6k
  }
6647
10.0k
  hashTableDestroy(&(p->generalEntities));
6648
#ifdef XML_DTD
6649
  hashTableDestroy(&(p->paramEntities));
6650
#endif /* XML_DTD */
6651
10.0k
  hashTableDestroy(&(p->elementTypes));
6652
10.0k
  hashTableDestroy(&(p->attributeIds));
6653
10.0k
  hashTableDestroy(&(p->prefixes));
6654
10.0k
  poolDestroy(&(p->pool));
6655
10.0k
  poolDestroy(&(p->entityValuePool));
6656
10.0k
  if (isDocEntity) {
6657
10.0k
    ms->free_fcn(p->scaffIndex);
6658
10.0k
    ms->free_fcn(p->scaffold);
6659
10.0k
  }
6660
10.0k
  ms->free_fcn(p);
6661
10.0k
}
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
23.2k
#define INIT_POWER 6
6856
6857
static XML_Bool FASTCALL
6858
31.7M
keyeq(KEY s1, KEY s2) {
6859
213M
  for (; *s1 == *s2; s1++, s2++)
6860
212M
    if (*s1 == 0)
6861
30.7M
      return XML_TRUE;
6862
985k
  return XML_FALSE;
6863
31.7M
}
6864
6865
static size_t
6866
31.0M
keylen(KEY s) {
6867
31.0M
  size_t len = 0;
6868
228M
  for (; *s; s++, len++)
6869
197M
    ;
6870
31.0M
  return len;
6871
31.0M
}
6872
6873
static void
6874
31.0M
copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
6875
31.0M
  key->k[0] = 0;
6876
31.0M
  key->k[1] = get_hash_secret_salt(parser);
6877
31.0M
}
6878
6879
static unsigned long FASTCALL
6880
31.0M
hash(XML_Parser parser, KEY s) {
6881
31.0M
  struct siphash state;
6882
31.0M
  struct sipkey key;
6883
31.0M
  (void)sip24_valid;
6884
31.0M
  copy_salt_to_sipkey(parser, &key);
6885
31.0M
  sip24_init(&state, &key);
6886
31.0M
  sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
6887
31.0M
  return (unsigned long)sip24_final(&state);
6888
31.0M
}
6889
6890
static NAMED *
6891
31.0M
lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
6892
31.0M
  size_t i;
6893
31.0M
  if (table->size == 0) {
6894
17.1k
    size_t tsize;
6895
17.1k
    if (! createSize)
6896
5.54k
      return NULL;
6897
11.6k
    table->power = INIT_POWER;
6898
    /* table->size is a power of 2 */
6899
11.6k
    table->size = (size_t)1 << INIT_POWER;
6900
11.6k
    tsize = table->size * sizeof(NAMED *);
6901
11.6k
    table->v = table->mem->malloc_fcn(tsize);
6902
11.6k
    if (! table->v) {
6903
0
      table->size = 0;
6904
0
      return NULL;
6905
0
    }
6906
11.6k
    memset(table->v, 0, tsize);
6907
11.6k
    i = hash(parser, name) & ((unsigned long)table->size - 1);
6908
30.9M
  } else {
6909
30.9M
    unsigned long h = hash(parser, name);
6910
30.9M
    unsigned long mask = (unsigned long)table->size - 1;
6911
30.9M
    unsigned char step = 0;
6912
30.9M
    i = h & mask;
6913
31.9M
    while (table->v[i]) {
6914
31.7M
      if (keyeq(name, table->v[i]->name))
6915
30.7M
        return table->v[i];
6916
985k
      if (! step)
6917
714k
        step = PROBE_STEP(h, mask, table->power);
6918
985k
      i < step ? (i += table->size - step) : (i -= step);
6919
985k
    }
6920
267k
    if (! createSize)
6921
236k
      return NULL;
6922
6923
    /* check for overflow (table is half full) */
6924
31.7k
    if (table->used >> (table->power - 1)) {
6925
451
      unsigned char newPower = table->power + 1;
6926
6927
      /* Detect and prevent invalid shift */
6928
451
      if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
6929
0
        return NULL;
6930
0
      }
6931
6932
451
      size_t newSize = (size_t)1 << newPower;
6933
451
      unsigned long newMask = (unsigned long)newSize - 1;
6934
6935
      /* Detect and prevent integer overflow */
6936
451
      if (newSize > (size_t)(-1) / sizeof(NAMED *)) {
6937
0
        return NULL;
6938
0
      }
6939
6940
451
      size_t tsize = newSize * sizeof(NAMED *);
6941
451
      NAMED **newV = table->mem->malloc_fcn(tsize);
6942
451
      if (! newV)
6943
0
        return NULL;
6944
451
      memset(newV, 0, tsize);
6945
61.6k
      for (i = 0; i < table->size; i++)
6946
61.2k
        if (table->v[i]) {
6947
30.6k
          unsigned long newHash = hash(parser, table->v[i]->name);
6948
30.6k
          size_t j = newHash & newMask;
6949
30.6k
          step = 0;
6950
35.1k
          while (newV[j]) {
6951
4.50k
            if (! step)
6952
3.68k
              step = PROBE_STEP(newHash, newMask, newPower);
6953
4.50k
            j < step ? (j += newSize - step) : (j -= step);
6954
4.50k
          }
6955
30.6k
          newV[j] = table->v[i];
6956
30.6k
        }
6957
451
      table->mem->free_fcn(table->v);
6958
451
      table->v = newV;
6959
451
      table->power = newPower;
6960
451
      table->size = newSize;
6961
451
      i = h & newMask;
6962
451
      step = 0;
6963
624
      while (table->v[i]) {
6964
173
        if (! step)
6965
115
          step = PROBE_STEP(h, newMask, newPower);
6966
173
        i < step ? (i += newSize - step) : (i -= step);
6967
173
      }
6968
451
    }
6969
31.7k
  }
6970
43.3k
  table->v[i] = table->mem->malloc_fcn(createSize);
6971
43.3k
  if (! table->v[i])
6972
0
    return NULL;
6973
43.3k
  memset(table->v[i], 0, createSize);
6974
43.3k
  table->v[i]->name = name;
6975
43.3k
  (table->used)++;
6976
43.3k
  return table->v[i];
6977
43.3k
}
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
40.0k
hashTableDestroy(HASH_TABLE *table) {
6991
40.0k
  size_t i;
6992
844k
  for (i = 0; i < table->size; i++)
6993
803k
    table->mem->free_fcn(table->v[i]);
6994
40.0k
  table->mem->free_fcn(table->v);
6995
40.0k
}
6996
6997
static void FASTCALL
6998
40.0k
hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) {
6999
40.0k
  p->power = 0;
7000
40.0k
  p->size = 0;
7001
40.0k
  p->used = 0;
7002
40.0k
  p->v = NULL;
7003
40.0k
  p->mem = ms;
7004
40.0k
}
7005
7006
static void FASTCALL
7007
10.0k
hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
7008
10.0k
  iter->p = table->v;
7009
10.0k
  iter->end = iter->p ? iter->p + table->size : NULL;
7010
10.0k
}
7011
7012
static NAMED *FASTCALL
7013
32.6k
hashTableIterNext(HASH_TABLE_ITER *iter) {
7014
432k
  while (iter->p != iter->end) {
7015
422k
    NAMED *tem = *(iter->p)++;
7016
422k
    if (tem)
7017
22.6k
      return tem;
7018
422k
  }
7019
10.0k
  return NULL;
7020
32.6k
}
7021
7022
static void FASTCALL
7023
40.0k
poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) {
7024
40.0k
  pool->blocks = NULL;
7025
40.0k
  pool->freeBlocks = NULL;
7026
40.0k
  pool->start = NULL;
7027
40.0k
  pool->ptr = NULL;
7028
40.0k
  pool->end = NULL;
7029
40.0k
  pool->mem = ms;
7030
40.0k
}
7031
7032
static void FASTCALL
7033
2.37M
poolClear(STRING_POOL *pool) {
7034
2.37M
  if (! pool->freeBlocks)
7035
1.49M
    pool->freeBlocks = pool->blocks;
7036
884k
  else {
7037
884k
    BLOCK *p = pool->blocks;
7038
894k
    while (p) {
7039
10.2k
      BLOCK *tem = p->next;
7040
10.2k
      p->next = pool->freeBlocks;
7041
10.2k
      pool->freeBlocks = p;
7042
10.2k
      p = tem;
7043
10.2k
    }
7044
884k
  }
7045
2.37M
  pool->blocks = NULL;
7046
2.37M
  pool->start = NULL;
7047
2.37M
  pool->ptr = NULL;
7048
2.37M
  pool->end = NULL;
7049
2.37M
}
7050
7051
static void FASTCALL
7052
40.0k
poolDestroy(STRING_POOL *pool) {
7053
40.0k
  BLOCK *p = pool->blocks;
7054
59.4k
  while (p) {
7055
19.3k
    BLOCK *tem = p->next;
7056
19.3k
    pool->mem->free_fcn(p);
7057
19.3k
    p = tem;
7058
19.3k
  }
7059
40.0k
  p = pool->freeBlocks;
7060
42.5k
  while (p) {
7061
2.51k
    BLOCK *tem = p->next;
7062
2.51k
    pool->mem->free_fcn(p);
7063
2.51k
    p = tem;
7064
2.51k
  }
7065
40.0k
}
7066
7067
static XML_Char *
7068
poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
7069
50.8M
           const char *end) {
7070
50.8M
  if (! pool->ptr && ! poolGrow(pool))
7071
0
    return NULL;
7072
50.8M
  for (;;) {
7073
50.8M
    const enum XML_Convert_Result convert_res = XmlConvert(
7074
50.8M
        enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
7075
50.8M
    if ((convert_res == XML_CONVERT_COMPLETED)
7076
50.8M
        || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
7077
50.8M
      break;
7078
17.3k
    if (! poolGrow(pool))
7079
4
      return NULL;
7080
17.3k
  }
7081
50.8M
  return pool->start;
7082
50.8M
}
7083
7084
static const XML_Char *FASTCALL
7085
14.8k
poolCopyString(STRING_POOL *pool, const XML_Char *s) {
7086
7.97M
  do {
7087
7.97M
    if (! poolAppendChar(pool, *s))
7088
0
      return NULL;
7089
7.97M
  } while (*s++);
7090
14.8k
  s = pool->start;
7091
14.8k
  poolFinish(pool);
7092
14.8k
  return s;
7093
14.8k
}
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
28.7M
                const char *end) {
7133
28.7M
  if (! poolAppend(pool, enc, ptr, end))
7134
0
    return NULL;
7135
28.7M
  if (pool->ptr == pool->end && ! poolGrow(pool))
7136
0
    return NULL;
7137
28.7M
  *(pool->ptr)++ = 0;
7138
28.7M
  return pool->start;
7139
28.7M
}
7140
7141
static size_t
7142
31.4k
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
31.4k
  const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
7151
7152
31.4k
  if (blockSize <= 0)
7153
0
    return 0;
7154
7155
31.4k
  if (blockSize > (int)(INT_MAX / stretch))
7156
0
    return 0;
7157
7158
31.4k
  {
7159
31.4k
    const int stretchedBlockSize = blockSize * (int)stretch;
7160
31.4k
    const int bytesToAllocate
7161
31.4k
        = (int)(offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
7162
31.4k
    if (bytesToAllocate < 0)
7163
3
      return 0;
7164
7165
31.4k
    return (size_t)bytesToAllocate;
7166
31.4k
  }
7167
31.4k
}
7168
7169
static XML_Bool FASTCALL
7170
132k
poolGrow(STRING_POOL *pool) {
7171
132k
  if (pool->freeBlocks) {
7172
101k
    if (pool->start == 0) {
7173
98.1k
      pool->blocks = pool->freeBlocks;
7174
98.1k
      pool->freeBlocks = pool->freeBlocks->next;
7175
98.1k
      pool->blocks->next = NULL;
7176
98.1k
      pool->start = pool->blocks->s;
7177
98.1k
      pool->end = pool->start + pool->blocks->size;
7178
98.1k
      pool->ptr = pool->start;
7179
98.1k
      return XML_TRUE;
7180
98.1k
    }
7181
2.93k
    if (pool->end - pool->start < pool->freeBlocks->size) {
7182
2.68k
      BLOCK *tem = pool->freeBlocks->next;
7183
2.68k
      pool->freeBlocks->next = pool->blocks;
7184
2.68k
      pool->blocks = pool->freeBlocks;
7185
2.68k
      pool->freeBlocks = tem;
7186
2.68k
      memcpy(pool->blocks->s, pool->start,
7187
2.68k
             (pool->end - pool->start) * sizeof(XML_Char));
7188
2.68k
      pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
7189
2.68k
      pool->start = pool->blocks->s;
7190
2.68k
      pool->end = pool->start + pool->blocks->size;
7191
2.68k
      return XML_TRUE;
7192
2.68k
    }
7193
2.93k
  }
7194
31.4k
  if (pool->blocks && pool->start == pool->blocks->s) {
7195
9.53k
    BLOCK *temp;
7196
9.53k
    int blockSize = (int)((unsigned)(pool->end - pool->start) * 2U);
7197
9.53k
    size_t bytesToAllocate;
7198
7199
    /* NOTE: Needs to be calculated prior to calling `realloc`
7200
             to avoid dangling pointers: */
7201
9.53k
    const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
7202
7203
9.53k
    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
1
      return XML_FALSE; /* LCOV_EXCL_LINE */
7211
1
    }
7212
7213
9.53k
    bytesToAllocate = poolBytesToAllocateFor(blockSize);
7214
9.53k
    if (bytesToAllocate == 0)
7215
2
      return XML_FALSE;
7216
7217
9.53k
    temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks,
7218
9.53k
                                           (unsigned)bytesToAllocate);
7219
9.53k
    if (temp == NULL)
7220
0
      return XML_FALSE;
7221
9.53k
    pool->blocks = temp;
7222
9.53k
    pool->blocks->size = blockSize;
7223
9.53k
    pool->ptr = pool->blocks->s + offsetInsideBlock;
7224
9.53k
    pool->start = pool->blocks->s;
7225
9.53k
    pool->end = pool->start + blockSize;
7226
21.9k
  } else {
7227
21.9k
    BLOCK *tem;
7228
21.9k
    int blockSize = (int)(pool->end - pool->start);
7229
21.9k
    size_t bytesToAllocate;
7230
7231
21.9k
    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
21.9k
    if (blockSize < INIT_BLOCK_SIZE)
7245
21.5k
      blockSize = INIT_BLOCK_SIZE;
7246
413
    else {
7247
      /* Detect overflow, avoiding _signed_ overflow undefined behavior */
7248
413
      if ((int)((unsigned)blockSize * 2U) < 0) {
7249
0
        return XML_FALSE;
7250
0
      }
7251
413
      blockSize *= 2;
7252
413
    }
7253
7254
21.9k
    bytesToAllocate = poolBytesToAllocateFor(blockSize);
7255
21.9k
    if (bytesToAllocate == 0)
7256
1
      return XML_FALSE;
7257
7258
21.9k
    tem = pool->mem->malloc_fcn(bytesToAllocate);
7259
21.9k
    if (! tem)
7260
0
      return XML_FALSE;
7261
21.9k
    tem->size = blockSize;
7262
21.9k
    tem->next = pool->blocks;
7263
21.9k
    pool->blocks = tem;
7264
21.9k
    if (pool->ptr != pool->start)
7265
8.81k
      memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
7266
21.9k
    pool->ptr = tem->s + (pool->ptr - pool->start);
7267
21.9k
    pool->start = tem->s;
7268
21.9k
    pool->end = tem->s + blockSize;
7269
21.9k
  }
7270
31.4k
  return XML_TRUE;
7271
31.4k
}
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
23.3k
               const char *end) {
7464
23.3k
  DTD *const dtd = parser->m_dtd; /* save one level of indirection */
7465
23.3k
  const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
7466
23.3k
  ELEMENT_TYPE *ret;
7467
7468
23.3k
  if (! name)
7469
0
    return NULL;
7470
23.3k
  ret = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
7471
23.3k
                               sizeof(ELEMENT_TYPE));
7472
23.3k
  if (! ret)
7473
0
    return NULL;
7474
23.3k
  if (ret->name != name)
7475
15.5k
    poolDiscard(&dtd->pool);
7476
7.80k
  else {
7477
7.80k
    poolFinish(&dtd->pool);
7478
7.80k
    if (! setElementTypePrefix(parser, ret))
7479
0
      return NULL;
7480
7.80k
  }
7481
23.3k
  return ret;
7482
23.3k
}
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
10.0k
getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {
8240
10.0k
  const char *const valueOrNull = getenv(variableName);
8241
10.0k
  if (valueOrNull == NULL) {
8242
10.0k
    return defaultDebugLevel;
8243
10.0k
  }
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
}