Bug Summary

File:root/firefox-clang/parser/expat/expat/lib/xmlparse.c
Warning:line 2496, column 25
Subtraction of a null pointer and a probably non-null pointer (from variable 'end') may result in undefined behavior

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name moz_xmlparse.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/parser/expat -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/parser/expat -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D HAVE_EXPAT_CONFIG_H -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/parser/expat -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/parser/expat -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/rlbox -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -Wno-unreachable-code-fallthrough -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c /root/firefox-clang/parser/expat/expat/lib/moz_xmlparse.c

/root/firefox-clang/parser/expat/expat/lib/moz_xmlparse.c

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "moz_expat.h"
6#include "xmlparse.c"
7
8void
9MOZ_XML_SetXmlDeclHandler(XML_Parser parser,
10 XML_XmlDeclHandler xmldecl) {
11 return XML_SetXmlDeclHandler(parser, xmldecl);
12}
13
14XML_Parser
15MOZ_XML_ParserCreate_MM(const XML_Char *encoding,
16 const XML_Memory_Handling_Suite *memsuite,
17 const XML_Char *namespaceSeparator) {
18 return XML_ParserCreate_MM(encoding, memsuite, namespaceSeparator);
19}
20
21void
22MOZ_XML_SetElementHandler(XML_Parser parser,
23 XML_StartElementHandler start,
24 XML_EndElementHandler end) {
25 XML_SetElementHandler(parser, start, end);
26}
27
28void
29MOZ_XML_SetCharacterDataHandler(XML_Parser parser,
30 XML_CharacterDataHandler handler) {
31 return XML_SetCharacterDataHandler(parser, handler);
32}
33
34void
35MOZ_XML_SetProcessingInstructionHandler(XML_Parser parser,
36 XML_ProcessingInstructionHandler handler) {
37 return XML_SetProcessingInstructionHandler(parser, handler);
38}
39
40void
41MOZ_XML_SetCommentHandler(XML_Parser parser,
42 XML_CommentHandler handler) {
43 XML_SetCommentHandler(parser, handler);
44}
45
46void
47MOZ_XML_SetCdataSectionHandler(XML_Parser parser,
48 XML_StartCdataSectionHandler start,
49 XML_EndCdataSectionHandler end) {
50 XML_SetCdataSectionHandler(parser, start, end);
51}
52
53void
54MOZ_XML_SetDefaultHandlerExpand(XML_Parser parser,
55 XML_DefaultHandler handler) {
56 XML_SetDefaultHandlerExpand(parser, handler);
57}
58
59void
60MOZ_XML_SetDoctypeDeclHandler(XML_Parser parser,
61 XML_StartDoctypeDeclHandler start,
62 XML_EndDoctypeDeclHandler end) {
63 XML_SetDoctypeDeclHandler(parser, start, end);
64}
65
66void
67MOZ_XML_SetExternalEntityRefHandler(XML_Parser parser,
68 XML_ExternalEntityRefHandler handler) {
69 XML_SetExternalEntityRefHandler(parser, handler);
70}
71
72void
73MOZ_XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
74 XML_SetReturnNSTriplet(parser, do_nst);
75}
76
77void
78MOZ_XML_SetBase(XML_Parser parser, const XML_Char *base) {
79 XML_SetBase(parser, base);
80}
81
82const XML_Char *
83MOZ_XML_GetBase(XML_Parser parser) {
84 return XML_GetBase(parser);
85}
86
87int
88MOZ_XML_GetSpecifiedAttributeCount(XML_Parser parser) {
89 return XML_GetSpecifiedAttributeCount(parser);
90}
91
92int
93MOZ_XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
94 return XML_Parse(parser, s, len, isFinal);
1
Passing value via 2nd parameter 's'
2
Calling 'XML_Parse'
95}
96
97void
98MOZ_XML_StopParser(XML_Parser parser, int resumable) {
99 XML_StopParser(parser, resumable);
100}
101
102int
103MOZ_XML_ResumeParser(XML_Parser parser) {
104 return XML_ResumeParser(parser);
105}
106
107XML_Parser
108MOZ_XML_ExternalEntityParserCreate(XML_Parser parser,
109 const XML_Char *context,
110 const XML_Char *encoding) {
111 return XML_ExternalEntityParserCreate(parser, context, encoding);
112}
113
114int
115MOZ_XML_SetParamEntityParsing(XML_Parser parser,
116 enum XML_ParamEntityParsing parsing) {
117 return XML_SetParamEntityParsing(parser, parsing);
118}
119
120XML_Bool
121MOZ_XML_SetHashSalt16Bytes(XML_Parser parser, const char entropy[16]) {
122 return XML_SetHashSalt16Bytes(parser, (const uint8_t *)entropy);
123}
124
125int
126MOZ_XML_GetErrorCode(XML_Parser parser)
127{
128 return XML_GetErrorCode(parser);
129}
130
131XML_Size MOZ_XML_GetCurrentLineNumber(XML_Parser parser) {
132 return XML_GetCurrentLineNumber(parser);
133}
134
135XML_Size MOZ_XML_GetCurrentColumnNumber(XML_Parser parser) {
136 return XML_GetCurrentColumnNumber(parser);
137}
138
139XML_Index MOZ_XML_GetCurrentByteIndex(XML_Parser parser) {
140 return XML_GetCurrentByteIndex(parser);
141}
142
143void
144MOZ_XML_ParserFree(XML_Parser parser) {
145 return XML_ParserFree(parser);
146}
147
148XML_Bool MOZ_XML_SetReparseDeferralEnabled(XML_Parser parser, int enabled) {
149 return XML_SetReparseDeferralEnabled(parser, enabled);
150}
151
152const XML_Char * XMLCALL
153MOZ_XML_GetMismatchedTag(XML_Parser parser)
154{
155 return parser->m_mismatch;
156}
157
158XML_Bool XMLCALL
159MOZ_XML_ProcessingEntityValue(XML_Parser parser) {
160 return parser->m_openInternalEntities != NULL((void*)0);
161}

/root/firefox-clang/parser/expat/expat/lib/xmlparse.c

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