blob: 9c0987f4f6d8749d2d3a0885219e366c1ac67393 [file] [log] [blame]
Haibo Huangfd5e81a2019-06-20 12:09:36 -07001/* 69df5be70289a11fb834869ce4a91c23c1d9dd04baffcbd10e86742d149a080c (2.2.7+)
Elliott Hughes72472942018-01-10 08:36:10 -08002 __ __ _
3 ___\ \/ /_ __ __ _| |_
4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
7 |_| XML parser
8
9 Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10 Copyright (c) 2000-2017 Expat development team
11 Licensed under the MIT license:
12
13 Permission is hereby granted, free of charge, to any person obtaining
14 a copy of this software and associated documentation files (the
15 "Software"), to deal in the Software without restriction, including
16 without limitation the rights to use, copy, modify, merge, publish,
17 distribute, sublicense, and/or sell copies of the Software, and to permit
18 persons to whom the Software is furnished to do so, subject to the
19 following conditions:
20
21 The above copyright notice and this permission notice shall be included
22 in all copies or substantial portions of the Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
29 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30 USE OR OTHER DEALINGS IN THE SOFTWARE.
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080031*/
32
Elliott Hughes72472942018-01-10 08:36:10 -080033#if !defined(_GNU_SOURCE)
34# define _GNU_SOURCE 1 /* syscall prototype */
35#endif
36
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080037#include <stddef.h>
38#include <string.h> /* memset(), memcpy() */
39#include <assert.h>
Elliott Hughes35e432d2012-09-09 14:23:38 -070040#include <limits.h> /* UINT_MAX */
Elliott Hughes72472942018-01-10 08:36:10 -080041#include <stdio.h> /* fprintf */
42#include <stdlib.h> /* getenv */
Paul Duffin3c2f09e2016-06-07 15:53:38 +010043
Elliott Hughes72472942018-01-10 08:36:10 -080044#ifdef _WIN32
Paul Duffin3c2f09e2016-06-07 15:53:38 +010045#define getpid GetCurrentProcessId
46#else
47#include <sys/time.h> /* gettimeofday() */
48#include <sys/types.h> /* getpid() */
49#include <unistd.h> /* getpid() */
Elliott Hughes72472942018-01-10 08:36:10 -080050#include <fcntl.h> /* O_RDONLY */
51#include <errno.h>
Paul Duffin3c2f09e2016-06-07 15:53:38 +010052#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080053
54#define XML_BUILDING_EXPAT 1
55
Elliott Hughes72472942018-01-10 08:36:10 -080056#ifdef _WIN32
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080057#include "winconfig.h"
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080058#elif defined(HAVE_EXPAT_CONFIG_H)
59#include <expat_config.h>
Elliott Hughes72472942018-01-10 08:36:10 -080060#endif /* ndef _WIN32 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080061
Elliott Hughesd07d5a72009-09-25 16:04:37 -070062#include "ascii.h"
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080063#include "expat.h"
Elliott Hughes72472942018-01-10 08:36:10 -080064#include "siphash.h"
65
66#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
67# if defined(HAVE_GETRANDOM)
68# include <sys/random.h> /* getrandom */
69# else
70# include <unistd.h> /* syscall */
71# include <sys/syscall.h> /* SYS_getrandom */
72# endif
73# if ! defined(GRND_NONBLOCK)
74# define GRND_NONBLOCK 0x0001
75# endif /* defined(GRND_NONBLOCK) */
76#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
77
78#if defined(HAVE_LIBBSD) \
79 && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
80# include <bsd/stdlib.h>
81#endif
82
83#if defined(_WIN32) && !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
84# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
85#endif
86
87#if !defined(HAVE_GETRANDOM) && !defined(HAVE_SYSCALL_GETRANDOM) \
88 && !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM) \
89 && !defined(XML_DEV_URANDOM) \
90 && !defined(_WIN32) \
91 && !defined(XML_POOR_ENTROPY)
92# error \
93 You do not have support for any sources of high quality entropy \
94 enabled. For end user security, that is probably not what you want. \
95 \
96 Your options include: \
97 * Linux + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \
98 * Linux + glibc <2.25 (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \
99 * BSD / macOS >=10.7 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \
100 * BSD / macOS <10.7 (arc4random): HAVE_ARC4RANDOM, \
101 * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
102 * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
103 * Linux / BSD / macOS (/dev/urandom): XML_DEV_URANDOM \
104 * Windows (RtlGenRandom): _WIN32. \
105 \
106 If insist on not using any of these, bypass this error by defining \
107 XML_POOR_ENTROPY; you have been warned. \
108 \
109 If you have reasons to patch this detection code away or need changes \
110 to the build system, please open a bug. Thank you!
111#endif
112
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800113
114#ifdef XML_UNICODE
115#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
116#define XmlConvert XmlUtf16Convert
117#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
118#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
119#define XmlEncode XmlUtf16Encode
Elliott Hughesd07d5a72009-09-25 16:04:37 -0700120/* Using pointer subtraction to convert to integer type. */
121#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800122typedef unsigned short ICHAR;
123#else
124#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
125#define XmlConvert XmlUtf8Convert
126#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
127#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
128#define XmlEncode XmlUtf8Encode
129#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
130typedef char ICHAR;
131#endif
132
133
134#ifndef XML_NS
135
136#define XmlInitEncodingNS XmlInitEncoding
137#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
138#undef XmlGetInternalEncodingNS
139#define XmlGetInternalEncodingNS XmlGetInternalEncoding
140#define XmlParseXmlDeclNS XmlParseXmlDecl
141
142#endif
143
144#ifdef XML_UNICODE
145
146#ifdef XML_UNICODE_WCHAR_T
147#define XML_T(x) (const wchar_t)x
148#define XML_L(x) L ## x
149#else
150#define XML_T(x) (const unsigned short)x
151#define XML_L(x) x
152#endif
153
154#else
155
156#define XML_T(x) x
157#define XML_L(x) x
158
159#endif
160
161/* Round up n to be a multiple of sz, where sz is a power of 2. */
162#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
163
Elliott Hughesaaec48e2018-08-16 16:29:01 -0700164/* Do safe (NULL-aware) pointer arithmetic */
165#define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
166
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800167#include "internal.h"
168#include "xmltok.h"
169#include "xmlrole.h"
170
171typedef const XML_Char *KEY;
172
173typedef struct {
174 KEY name;
175} NAMED;
176
177typedef struct {
178 NAMED **v;
179 unsigned char power;
180 size_t size;
181 size_t used;
182 const XML_Memory_Handling_Suite *mem;
183} HASH_TABLE;
184
Elliott Hughes72472942018-01-10 08:36:10 -0800185static size_t
186keylen(KEY s);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800187
Elliott Hughes72472942018-01-10 08:36:10 -0800188static void
189copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800190
191/* For probing (after a collision) we need a step size relative prime
192 to the hash table size, which is a power of 2. We use double-hashing,
193 since we can calculate a second hash value cheaply by taking those bits
194 of the first hash value that were discarded (masked out) when the table
195 index was calculated: index = hash & mask, where mask = table->size - 1.
196 We limit the maximum step size to table->size / 4 (mask >> 2) and make
197 it odd, since odd numbers are always relative prime to a power of 2.
198*/
199#define SECOND_HASH(hash, mask, power) \
200 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
201#define PROBE_STEP(hash, mask, power) \
202 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
203
204typedef struct {
205 NAMED **p;
206 NAMED **end;
207} HASH_TABLE_ITER;
208
209#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
210#define INIT_DATA_BUF_SIZE 1024
211#define INIT_ATTS_SIZE 16
212#define INIT_ATTS_VERSION 0xFFFFFFFF
213#define INIT_BLOCK_SIZE 1024
214#define INIT_BUFFER_SIZE 1024
215
216#define EXPAND_SPARE 24
217
218typedef struct binding {
219 struct prefix *prefix;
220 struct binding *nextTagBinding;
221 struct binding *prevPrefixBinding;
222 const struct attribute_id *attId;
223 XML_Char *uri;
224 int uriLen;
225 int uriAlloc;
226} BINDING;
227
228typedef struct prefix {
229 const XML_Char *name;
230 BINDING *binding;
231} PREFIX;
232
233typedef struct {
234 const XML_Char *str;
235 const XML_Char *localPart;
236 const XML_Char *prefix;
237 int strLen;
238 int uriLen;
239 int prefixLen;
240} TAG_NAME;
241
242/* TAG represents an open element.
243 The name of the element is stored in both the document and API
244 encodings. The memory buffer 'buf' is a separately-allocated
245 memory area which stores the name. During the XML_Parse()/
246 XMLParseBuffer() when the element is open, the memory for the 'raw'
247 version of the name (in the document encoding) is shared with the
248 document buffer. If the element is open across calls to
249 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
250 contain the 'raw' name as well.
251
252 A parser re-uses these structures, maintaining a list of allocated
253 TAG objects in a free list.
254*/
255typedef struct tag {
256 struct tag *parent; /* parent of this element */
257 const char *rawName; /* tagName in the original encoding */
258 int rawNameLength;
259 TAG_NAME name; /* tagName in the API encoding */
260 char *buf; /* buffer for name components */
261 char *bufEnd; /* end of the buffer */
262 BINDING *bindings;
263} TAG;
264
265typedef struct {
266 const XML_Char *name;
267 const XML_Char *textPtr;
268 int textLen; /* length in XML_Chars */
269 int processed; /* # of processed bytes - when suspended */
270 const XML_Char *systemId;
271 const XML_Char *base;
272 const XML_Char *publicId;
273 const XML_Char *notation;
274 XML_Bool open;
275 XML_Bool is_param;
276 XML_Bool is_internal; /* true if declared in internal subset outside PE */
277} ENTITY;
278
279typedef struct {
280 enum XML_Content_Type type;
281 enum XML_Content_Quant quant;
282 const XML_Char * name;
283 int firstchild;
284 int lastchild;
285 int childcnt;
286 int nextsib;
287} CONTENT_SCAFFOLD;
288
289#define INIT_SCAFFOLD_ELEMENTS 32
290
291typedef struct block {
292 struct block *next;
293 int size;
294 XML_Char s[1];
295} BLOCK;
296
297typedef struct {
298 BLOCK *blocks;
299 BLOCK *freeBlocks;
300 const XML_Char *end;
301 XML_Char *ptr;
302 XML_Char *start;
303 const XML_Memory_Handling_Suite *mem;
304} STRING_POOL;
305
306/* The XML_Char before the name is used to determine whether
307 an attribute has been specified. */
308typedef struct attribute_id {
309 XML_Char *name;
310 PREFIX *prefix;
311 XML_Bool maybeTokenized;
312 XML_Bool xmlns;
313} ATTRIBUTE_ID;
314
315typedef struct {
316 const ATTRIBUTE_ID *id;
317 XML_Bool isCdata;
318 const XML_Char *value;
319} DEFAULT_ATTRIBUTE;
320
321typedef struct {
322 unsigned long version;
323 unsigned long hash;
324 const XML_Char *uriName;
325} NS_ATT;
326
327typedef struct {
328 const XML_Char *name;
329 PREFIX *prefix;
330 const ATTRIBUTE_ID *idAtt;
331 int nDefaultAtts;
332 int allocDefaultAtts;
333 DEFAULT_ATTRIBUTE *defaultAtts;
334} ELEMENT_TYPE;
335
336typedef struct {
337 HASH_TABLE generalEntities;
338 HASH_TABLE elementTypes;
339 HASH_TABLE attributeIds;
340 HASH_TABLE prefixes;
341 STRING_POOL pool;
342 STRING_POOL entityValuePool;
343 /* false once a parameter entity reference has been skipped */
344 XML_Bool keepProcessing;
345 /* true once an internal or external PE reference has been encountered;
346 this includes the reference to an external subset */
347 XML_Bool hasParamEntityRefs;
348 XML_Bool standalone;
349#ifdef XML_DTD
350 /* indicates if external PE has been read */
351 XML_Bool paramEntityRead;
352 HASH_TABLE paramEntities;
353#endif /* XML_DTD */
354 PREFIX defaultPrefix;
355 /* === scaffolding for building content model === */
356 XML_Bool in_eldecl;
357 CONTENT_SCAFFOLD *scaffold;
358 unsigned contentStringLen;
359 unsigned scaffSize;
360 unsigned scaffCount;
361 int scaffLevel;
362 int *scaffIndex;
363} DTD;
364
365typedef struct open_internal_entity {
366 const char *internalEventPtr;
367 const char *internalEventEndPtr;
368 struct open_internal_entity *next;
369 ENTITY *entity;
370 int startTagLevel;
371 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
372} OPEN_INTERNAL_ENTITY;
373
374typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
375 const char *start,
376 const char *end,
377 const char **endPtr);
378
379static Processor prologProcessor;
380static Processor prologInitProcessor;
381static Processor contentProcessor;
382static Processor cdataSectionProcessor;
383#ifdef XML_DTD
384static Processor ignoreSectionProcessor;
385static Processor externalParEntProcessor;
386static Processor externalParEntInitProcessor;
387static Processor entityValueProcessor;
388static Processor entityValueInitProcessor;
389#endif /* XML_DTD */
390static Processor epilogProcessor;
391static Processor errorProcessor;
392static Processor externalEntityInitProcessor;
393static Processor externalEntityInitProcessor2;
394static Processor externalEntityInitProcessor3;
395static Processor externalEntityContentProcessor;
396static Processor internalEntityProcessor;
397
398static enum XML_Error
399handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
400static enum XML_Error
401processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
402 const char *s, const char *next);
403static enum XML_Error
404initializeEncoding(XML_Parser parser);
405static enum XML_Error
Elliott Hughes35e432d2012-09-09 14:23:38 -0700406doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
407 const char *end, int tok, const char *next, const char **nextPtr,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800408 XML_Bool haveMore);
409static enum XML_Error
Elliott Hughes35e432d2012-09-09 14:23:38 -0700410processInternalEntity(XML_Parser parser, ENTITY *entity,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800411 XML_Bool betweenDecl);
412static enum XML_Error
413doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
Elliott Hughes35e432d2012-09-09 14:23:38 -0700414 const char *start, const char *end, const char **endPtr,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800415 XML_Bool haveMore);
416static enum XML_Error
417doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
418 const char *end, const char **nextPtr, XML_Bool haveMore);
419#ifdef XML_DTD
420static enum XML_Error
421doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
422 const char *end, const char **nextPtr, XML_Bool haveMore);
423#endif /* XML_DTD */
424
Elliott Hughes72472942018-01-10 08:36:10 -0800425static void
426freeBindings(XML_Parser parser, BINDING *bindings);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800427static enum XML_Error
428storeAtts(XML_Parser parser, const ENCODING *, const char *s,
429 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
430static enum XML_Error
431addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
432 const XML_Char *uri, BINDING **bindingsPtr);
433static int
Elliott Hughes35e432d2012-09-09 14:23:38 -0700434defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800435 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
436static enum XML_Error
437storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
438 const char *, const char *, STRING_POOL *);
439static enum XML_Error
440appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
441 const char *, const char *, STRING_POOL *);
442static ATTRIBUTE_ID *
443getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
444 const char *end);
445static int
446setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
447static enum XML_Error
448storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
449 const char *end);
450static int
451reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
452 const char *start, const char *end);
453static int
454reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
455 const char *end);
456static void
457reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
458 const char *end);
459
460static const XML_Char * getContext(XML_Parser parser);
461static XML_Bool
462setContext(XML_Parser parser, const XML_Char *context);
463
464static void FASTCALL normalizePublicId(XML_Char *s);
465
466static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
Elliott Hughes72472942018-01-10 08:36:10 -0800467/* do not call if m_parentParser != NULL */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800468static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
469static void
470dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
471static int
Elliott Hughes35e432d2012-09-09 14:23:38 -0700472dtdCopy(XML_Parser oldParser,
473 DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800474static int
Elliott Hughes35e432d2012-09-09 14:23:38 -0700475copyEntityTable(XML_Parser oldParser,
476 HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800477static NAMED *
Elliott Hughes35e432d2012-09-09 14:23:38 -0700478lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800479static void FASTCALL
480hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
481static void FASTCALL hashTableClear(HASH_TABLE *);
482static void FASTCALL hashTableDestroy(HASH_TABLE *);
483static void FASTCALL
484hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
485static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
486
487static void FASTCALL
488poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
489static void FASTCALL poolClear(STRING_POOL *);
490static void FASTCALL poolDestroy(STRING_POOL *);
491static XML_Char *
492poolAppend(STRING_POOL *pool, const ENCODING *enc,
493 const char *ptr, const char *end);
494static XML_Char *
495poolStoreString(STRING_POOL *pool, const ENCODING *enc,
496 const char *ptr, const char *end);
497static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
498static const XML_Char * FASTCALL
499poolCopyString(STRING_POOL *pool, const XML_Char *s);
500static const XML_Char *
501poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
502static const XML_Char * FASTCALL
503poolAppendString(STRING_POOL *pool, const XML_Char *s);
504
505static int FASTCALL nextScaffoldPart(XML_Parser parser);
506static XML_Content * build_model(XML_Parser parser);
507static ELEMENT_TYPE *
508getElementType(XML_Parser parser, const ENCODING *enc,
509 const char *ptr, const char *end);
510
Elliott Hughes72472942018-01-10 08:36:10 -0800511static XML_Char *copyString(const XML_Char *s,
512 const XML_Memory_Handling_Suite *memsuite);
513
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100514static unsigned long generate_hash_secret_salt(XML_Parser parser);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700515static XML_Bool startParsing(XML_Parser parser);
516
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800517static XML_Parser
518parserCreate(const XML_Char *encodingName,
519 const XML_Memory_Handling_Suite *memsuite,
520 const XML_Char *nameSep,
521 DTD *dtd);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700522
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800523static void
524parserInit(XML_Parser parser, const XML_Char *encodingName);
525
526#define poolStart(pool) ((pool)->start)
527#define poolEnd(pool) ((pool)->ptr)
528#define poolLength(pool) ((pool)->ptr - (pool)->start)
529#define poolChop(pool) ((void)--(pool->ptr))
530#define poolLastChar(pool) (((pool)->ptr)[-1])
531#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
532#define poolFinish(pool) ((pool)->start = (pool)->ptr)
533#define poolAppendChar(pool, c) \
534 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
535 ? 0 \
536 : ((*((pool)->ptr)++ = c), 1))
537
538struct XML_ParserStruct {
Elliott Hughes72472942018-01-10 08:36:10 -0800539 /* The first member must be m_userData so that the XML_GetUserData
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800540 macro works. */
541 void *m_userData;
542 void *m_handlerArg;
543 char *m_buffer;
544 const XML_Memory_Handling_Suite m_mem;
545 /* first character to be parsed */
546 const char *m_bufferPtr;
547 /* past last character to be parsed */
548 char *m_bufferEnd;
Elliott Hughes72472942018-01-10 08:36:10 -0800549 /* allocated end of m_buffer */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800550 const char *m_bufferLim;
551 XML_Index m_parseEndByteIndex;
552 const char *m_parseEndPtr;
553 XML_Char *m_dataBuf;
554 XML_Char *m_dataBufEnd;
555 XML_StartElementHandler m_startElementHandler;
556 XML_EndElementHandler m_endElementHandler;
557 XML_CharacterDataHandler m_characterDataHandler;
558 XML_ProcessingInstructionHandler m_processingInstructionHandler;
559 XML_CommentHandler m_commentHandler;
560 XML_StartCdataSectionHandler m_startCdataSectionHandler;
561 XML_EndCdataSectionHandler m_endCdataSectionHandler;
562 XML_DefaultHandler m_defaultHandler;
563 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
564 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
565 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
566 XML_NotationDeclHandler m_notationDeclHandler;
567 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
568 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
569 XML_NotStandaloneHandler m_notStandaloneHandler;
570 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
571 XML_Parser m_externalEntityRefHandlerArg;
572 XML_SkippedEntityHandler m_skippedEntityHandler;
573 XML_UnknownEncodingHandler m_unknownEncodingHandler;
574 XML_ElementDeclHandler m_elementDeclHandler;
575 XML_AttlistDeclHandler m_attlistDeclHandler;
576 XML_EntityDeclHandler m_entityDeclHandler;
577 XML_XmlDeclHandler m_xmlDeclHandler;
578 const ENCODING *m_encoding;
579 INIT_ENCODING m_initEncoding;
580 const ENCODING *m_internalEncoding;
581 const XML_Char *m_protocolEncodingName;
582 XML_Bool m_ns;
583 XML_Bool m_ns_triplets;
584 void *m_unknownEncodingMem;
585 void *m_unknownEncodingData;
586 void *m_unknownEncodingHandlerData;
587 void (XMLCALL *m_unknownEncodingRelease)(void *);
588 PROLOG_STATE m_prologState;
589 Processor *m_processor;
590 enum XML_Error m_errorCode;
591 const char *m_eventPtr;
592 const char *m_eventEndPtr;
593 const char *m_positionPtr;
594 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
595 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
596 XML_Bool m_defaultExpandInternalEntities;
597 int m_tagLevel;
598 ENTITY *m_declEntity;
599 const XML_Char *m_doctypeName;
600 const XML_Char *m_doctypeSysid;
601 const XML_Char *m_doctypePubid;
602 const XML_Char *m_declAttributeType;
603 const XML_Char *m_declNotationName;
604 const XML_Char *m_declNotationPublicId;
605 ELEMENT_TYPE *m_declElementType;
606 ATTRIBUTE_ID *m_declAttributeId;
607 XML_Bool m_declAttributeIsCdata;
608 XML_Bool m_declAttributeIsId;
609 DTD *m_dtd;
610 const XML_Char *m_curBase;
611 TAG *m_tagStack;
612 TAG *m_freeTagList;
613 BINDING *m_inheritedBindings;
614 BINDING *m_freeBindingList;
615 int m_attsSize;
616 int m_nSpecifiedAtts;
617 int m_idAttIndex;
618 ATTRIBUTE *m_atts;
619 NS_ATT *m_nsAtts;
620 unsigned long m_nsAttsVersion;
621 unsigned char m_nsAttsPower;
Elliott Hughes35e432d2012-09-09 14:23:38 -0700622#ifdef XML_ATTR_INFO
623 XML_AttrInfo *m_attInfo;
624#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800625 POSITION m_position;
626 STRING_POOL m_tempPool;
627 STRING_POOL m_temp2Pool;
628 char *m_groupConnector;
629 unsigned int m_groupSize;
630 XML_Char m_namespaceSeparator;
631 XML_Parser m_parentParser;
632 XML_ParsingStatus m_parsingStatus;
633#ifdef XML_DTD
634 XML_Bool m_isParamEntity;
635 XML_Bool m_useForeignDTD;
636 enum XML_ParamEntityParsing m_paramEntityParsing;
637#endif
Elliott Hughes35e432d2012-09-09 14:23:38 -0700638 unsigned long m_hash_secret_salt;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800639};
640
Elliott Hughes72472942018-01-10 08:36:10 -0800641#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
642#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p),(s)))
643#define FREE(parser, p) (parser->m_mem.free_fcn((p)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800644
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800645
646XML_Parser XMLCALL
647XML_ParserCreate(const XML_Char *encodingName)
648{
649 return XML_ParserCreate_MM(encodingName, NULL, NULL);
650}
651
652XML_Parser XMLCALL
653XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
654{
655 XML_Char tmp[2];
656 *tmp = nsSep;
657 return XML_ParserCreate_MM(encodingName, NULL, tmp);
658}
659
660static const XML_Char implicitContext[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -0700661 ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
Elliott Hughes35e432d2012-09-09 14:23:38 -0700662 ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
Elliott Hughesd07d5a72009-09-25 16:04:37 -0700663 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
664 ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
665 ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
666 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800667};
668
Elliott Hughes72472942018-01-10 08:36:10 -0800669
670/* To avoid warnings about unused functions: */
671#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
672
673#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
674
675/* Obtain entropy on Linux 3.17+ */
676static int
677writeRandomBytes_getrandom_nonblock(void * target, size_t count) {
678 int success = 0; /* full count bytes written? */
679 size_t bytesWrittenTotal = 0;
680 const unsigned int getrandomFlags = GRND_NONBLOCK;
681
682 do {
683 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
684 const size_t bytesToWrite = count - bytesWrittenTotal;
685
686 const int bytesWrittenMore =
687#if defined(HAVE_GETRANDOM)
688 getrandom(currentTarget, bytesToWrite, getrandomFlags);
689#else
690 syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
691#endif
692
693 if (bytesWrittenMore > 0) {
694 bytesWrittenTotal += bytesWrittenMore;
695 if (bytesWrittenTotal >= count)
696 success = 1;
697 }
698 } while (! success && (errno == EINTR));
699
700 return success;
701}
702
703#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
704
705
706#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
707
708/* Extract entropy from /dev/urandom */
709static int
710writeRandomBytes_dev_urandom(void * target, size_t count) {
711 int success = 0; /* full count bytes written? */
712 size_t bytesWrittenTotal = 0;
713
714 const int fd = open("/dev/urandom", O_RDONLY);
715 if (fd < 0) {
716 return 0;
717 }
718
719 do {
720 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
721 const size_t bytesToWrite = count - bytesWrittenTotal;
722
723 const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
724
725 if (bytesWrittenMore > 0) {
726 bytesWrittenTotal += bytesWrittenMore;
727 if (bytesWrittenTotal >= count)
728 success = 1;
729 }
730 } while (! success && (errno == EINTR));
731
732 close(fd);
733 return success;
734}
735
736#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
737
738#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
739
740
Haibo Huangfd5e81a2019-06-20 12:09:36 -0700741#if defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF)
Elliott Hughes72472942018-01-10 08:36:10 -0800742
743static void
744writeRandomBytes_arc4random(void * target, size_t count) {
745 size_t bytesWrittenTotal = 0;
746
747 while (bytesWrittenTotal < count) {
748 const uint32_t random32 = arc4random();
749 size_t i = 0;
750
751 for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
752 i++, bytesWrittenTotal++) {
753 const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
754 ((uint8_t *)target)[bytesWrittenTotal] = random8;
755 }
756 }
757}
758
Haibo Huangfd5e81a2019-06-20 12:09:36 -0700759#endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */
Elliott Hughes72472942018-01-10 08:36:10 -0800760
761
762#ifdef _WIN32
763
764typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
765HMODULE _Expat_LoadLibrary(LPCTSTR filename); /* see loadlibrary.c */
766
767/* Obtain entropy on Windows XP / Windows Server 2003 and later.
768 * Hint on RtlGenRandom and the following article from libsodium.
769 *
770 * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
771 * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
772 */
773static int
774writeRandomBytes_RtlGenRandom(void * target, size_t count) {
775 int success = 0; /* full count bytes written? */
776 const HMODULE advapi32 = _Expat_LoadLibrary(TEXT("ADVAPI32.DLL"));
777
778 if (advapi32) {
779 const RTLGENRANDOM_FUNC RtlGenRandom
780 = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
781 if (RtlGenRandom) {
782 if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
783 success = 1;
784 }
785 }
786 FreeLibrary(advapi32);
787 }
788
789 return success;
790}
791
792#endif /* _WIN32 */
793
794
795#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
796
Elliott Hughes35e432d2012-09-09 14:23:38 -0700797static unsigned long
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100798gather_time_entropy(void)
Elliott Hughes35e432d2012-09-09 14:23:38 -0700799{
Elliott Hughes72472942018-01-10 08:36:10 -0800800#ifdef _WIN32
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100801 FILETIME ft;
802 GetSystemTimeAsFileTime(&ft); /* never fails */
803 return ft.dwHighDateTime ^ ft.dwLowDateTime;
804#else
805 struct timeval tv;
806 int gettimeofday_res;
807
808 gettimeofday_res = gettimeofday(&tv, NULL);
Elliott Hughes72472942018-01-10 08:36:10 -0800809
810#if defined(NDEBUG)
811 (void)gettimeofday_res;
812#else
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100813 assert (gettimeofday_res == 0);
Elliott Hughes72472942018-01-10 08:36:10 -0800814#endif /* defined(NDEBUG) */
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100815
816 /* Microseconds time is <20 bits entropy */
817 return tv.tv_usec;
818#endif
819}
820
Elliott Hughes72472942018-01-10 08:36:10 -0800821#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
822
823
824static unsigned long
825ENTROPY_DEBUG(const char * label, unsigned long entropy) {
826 const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
827 if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
828 fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
829 label,
830 (int)sizeof(entropy) * 2, entropy,
831 (unsigned long)sizeof(entropy));
832 }
833 return entropy;
834}
835
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100836static unsigned long
837generate_hash_secret_salt(XML_Parser parser)
838{
Elliott Hughes72472942018-01-10 08:36:10 -0800839 unsigned long entropy;
840 (void)parser;
841
842 /* "Failproof" high quality providers: */
843#if defined(HAVE_ARC4RANDOM_BUF)
844 arc4random_buf(&entropy, sizeof(entropy));
845 return ENTROPY_DEBUG("arc4random_buf", entropy);
846#elif defined(HAVE_ARC4RANDOM)
847 writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
848 return ENTROPY_DEBUG("arc4random", entropy);
849#else
850 /* Try high quality providers first .. */
851#ifdef _WIN32
852 if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
853 return ENTROPY_DEBUG("RtlGenRandom", entropy);
854 }
855#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
856 if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
857 return ENTROPY_DEBUG("getrandom", entropy);
858 }
859#endif
860#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
861 if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
862 return ENTROPY_DEBUG("/dev/urandom", entropy);
863 }
864#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
865 /* .. and self-made low quality for backup: */
866
867 /* Process ID is 0 bits entropy if attacker has local access */
868 entropy = gather_time_entropy() ^ getpid();
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100869
870 /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
871 if (sizeof(unsigned long) == 4) {
Elliott Hughes72472942018-01-10 08:36:10 -0800872 return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100873 } else {
Elliott Hughes72472942018-01-10 08:36:10 -0800874 return ENTROPY_DEBUG("fallback(8)",
875 entropy * (unsigned long)2305843009213693951ULL);
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100876 }
Elliott Hughes72472942018-01-10 08:36:10 -0800877#endif
878}
879
880static unsigned long
881get_hash_secret_salt(XML_Parser parser) {
882 if (parser->m_parentParser != NULL)
883 return get_hash_secret_salt(parser->m_parentParser);
884 return parser->m_hash_secret_salt;
Elliott Hughes35e432d2012-09-09 14:23:38 -0700885}
886
887static XML_Bool /* only valid for root parser */
888startParsing(XML_Parser parser)
889{
890 /* hash functions must be initialized before setContext() is called */
Elliott Hughes72472942018-01-10 08:36:10 -0800891 if (parser->m_hash_secret_salt == 0)
892 parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
893 if (parser->m_ns) {
Elliott Hughes35e432d2012-09-09 14:23:38 -0700894 /* implicit context only set for root parser, since child
895 parsers (i.e. external entity parsers) will inherit it
896 */
897 return setContext(parser, implicitContext);
898 }
899 return XML_TRUE;
900}
901
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800902XML_Parser XMLCALL
903XML_ParserCreate_MM(const XML_Char *encodingName,
904 const XML_Memory_Handling_Suite *memsuite,
905 const XML_Char *nameSep)
906{
Elliott Hughes35e432d2012-09-09 14:23:38 -0700907 return parserCreate(encodingName, memsuite, nameSep, NULL);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800908}
909
910static XML_Parser
911parserCreate(const XML_Char *encodingName,
912 const XML_Memory_Handling_Suite *memsuite,
913 const XML_Char *nameSep,
914 DTD *dtd)
915{
916 XML_Parser parser;
917
918 if (memsuite) {
919 XML_Memory_Handling_Suite *mtemp;
920 parser = (XML_Parser)
921 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
922 if (parser != NULL) {
923 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
924 mtemp->malloc_fcn = memsuite->malloc_fcn;
925 mtemp->realloc_fcn = memsuite->realloc_fcn;
926 mtemp->free_fcn = memsuite->free_fcn;
927 }
928 }
929 else {
930 XML_Memory_Handling_Suite *mtemp;
931 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
932 if (parser != NULL) {
933 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
934 mtemp->malloc_fcn = malloc;
935 mtemp->realloc_fcn = realloc;
936 mtemp->free_fcn = free;
937 }
938 }
939
940 if (!parser)
941 return parser;
942
Elliott Hughes72472942018-01-10 08:36:10 -0800943 parser->m_buffer = NULL;
944 parser->m_bufferLim = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800945
Elliott Hughes72472942018-01-10 08:36:10 -0800946 parser->m_attsSize = INIT_ATTS_SIZE;
947 parser->m_atts = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
948 if (parser->m_atts == NULL) {
949 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800950 return NULL;
951 }
Elliott Hughes35e432d2012-09-09 14:23:38 -0700952#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -0800953 parser->m_attInfo = (XML_AttrInfo*)MALLOC(parser, parser->m_attsSize * sizeof(XML_AttrInfo));
954 if (parser->m_attInfo == NULL) {
955 FREE(parser, parser->m_atts);
956 FREE(parser, parser);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700957 return NULL;
958 }
959#endif
Elliott Hughes72472942018-01-10 08:36:10 -0800960 parser->m_dataBuf = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
961 if (parser->m_dataBuf == NULL) {
962 FREE(parser, parser->m_atts);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700963#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -0800964 FREE(parser, parser->m_attInfo);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700965#endif
Elliott Hughes72472942018-01-10 08:36:10 -0800966 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800967 return NULL;
968 }
Elliott Hughes72472942018-01-10 08:36:10 -0800969 parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800970
971 if (dtd)
Elliott Hughes72472942018-01-10 08:36:10 -0800972 parser->m_dtd = dtd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800973 else {
Elliott Hughes72472942018-01-10 08:36:10 -0800974 parser->m_dtd = dtdCreate(&parser->m_mem);
975 if (parser->m_dtd == NULL) {
976 FREE(parser, parser->m_dataBuf);
977 FREE(parser, parser->m_atts);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700978#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -0800979 FREE(parser, parser->m_attInfo);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700980#endif
Elliott Hughes72472942018-01-10 08:36:10 -0800981 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800982 return NULL;
983 }
984 }
985
Elliott Hughes72472942018-01-10 08:36:10 -0800986 parser->m_freeBindingList = NULL;
987 parser->m_freeTagList = NULL;
988 parser->m_freeInternalEntities = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800989
Elliott Hughes72472942018-01-10 08:36:10 -0800990 parser->m_groupSize = 0;
991 parser->m_groupConnector = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800992
Elliott Hughes72472942018-01-10 08:36:10 -0800993 parser->m_unknownEncodingHandler = NULL;
994 parser->m_unknownEncodingHandlerData = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800995
Elliott Hughes72472942018-01-10 08:36:10 -0800996 parser->m_namespaceSeparator = ASCII_EXCL;
997 parser->m_ns = XML_FALSE;
998 parser->m_ns_triplets = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800999
Elliott Hughes72472942018-01-10 08:36:10 -08001000 parser->m_nsAtts = NULL;
1001 parser->m_nsAttsVersion = 0;
1002 parser->m_nsAttsPower = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001003
Elliott Hughes72472942018-01-10 08:36:10 -08001004 parser->m_protocolEncodingName = NULL;
1005
1006 poolInit(&parser->m_tempPool, &(parser->m_mem));
1007 poolInit(&parser->m_temp2Pool, &(parser->m_mem));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001008 parserInit(parser, encodingName);
1009
Elliott Hughes72472942018-01-10 08:36:10 -08001010 if (encodingName && !parser->m_protocolEncodingName) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001011 XML_ParserFree(parser);
1012 return NULL;
1013 }
1014
1015 if (nameSep) {
Elliott Hughes72472942018-01-10 08:36:10 -08001016 parser->m_ns = XML_TRUE;
1017 parser->m_internalEncoding = XmlGetInternalEncodingNS();
1018 parser->m_namespaceSeparator = *nameSep;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001019 }
1020 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001021 parser->m_internalEncoding = XmlGetInternalEncoding();
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001022 }
1023
1024 return parser;
1025}
1026
1027static void
1028parserInit(XML_Parser parser, const XML_Char *encodingName)
1029{
Elliott Hughes72472942018-01-10 08:36:10 -08001030 parser->m_processor = prologInitProcessor;
1031 XmlPrologStateInit(&parser->m_prologState);
1032 if (encodingName != NULL) {
1033 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1034 }
1035 parser->m_curBase = NULL;
1036 XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
1037 parser->m_userData = NULL;
1038 parser->m_handlerArg = NULL;
1039 parser->m_startElementHandler = NULL;
1040 parser->m_endElementHandler = NULL;
1041 parser->m_characterDataHandler = NULL;
1042 parser->m_processingInstructionHandler = NULL;
1043 parser->m_commentHandler = NULL;
1044 parser->m_startCdataSectionHandler = NULL;
1045 parser->m_endCdataSectionHandler = NULL;
1046 parser->m_defaultHandler = NULL;
1047 parser->m_startDoctypeDeclHandler = NULL;
1048 parser->m_endDoctypeDeclHandler = NULL;
1049 parser->m_unparsedEntityDeclHandler = NULL;
1050 parser->m_notationDeclHandler = NULL;
1051 parser->m_startNamespaceDeclHandler = NULL;
1052 parser->m_endNamespaceDeclHandler = NULL;
1053 parser->m_notStandaloneHandler = NULL;
1054 parser->m_externalEntityRefHandler = NULL;
1055 parser->m_externalEntityRefHandlerArg = parser;
1056 parser->m_skippedEntityHandler = NULL;
1057 parser->m_elementDeclHandler = NULL;
1058 parser->m_attlistDeclHandler = NULL;
1059 parser->m_entityDeclHandler = NULL;
1060 parser->m_xmlDeclHandler = NULL;
1061 parser->m_bufferPtr = parser->m_buffer;
1062 parser->m_bufferEnd = parser->m_buffer;
1063 parser->m_parseEndByteIndex = 0;
1064 parser->m_parseEndPtr = NULL;
1065 parser->m_declElementType = NULL;
1066 parser->m_declAttributeId = NULL;
1067 parser->m_declEntity = NULL;
1068 parser->m_doctypeName = NULL;
1069 parser->m_doctypeSysid = NULL;
1070 parser->m_doctypePubid = NULL;
1071 parser->m_declAttributeType = NULL;
1072 parser->m_declNotationName = NULL;
1073 parser->m_declNotationPublicId = NULL;
1074 parser->m_declAttributeIsCdata = XML_FALSE;
1075 parser->m_declAttributeIsId = XML_FALSE;
1076 memset(&parser->m_position, 0, sizeof(POSITION));
1077 parser->m_errorCode = XML_ERROR_NONE;
1078 parser->m_eventPtr = NULL;
1079 parser->m_eventEndPtr = NULL;
1080 parser->m_positionPtr = NULL;
1081 parser->m_openInternalEntities = NULL;
1082 parser->m_defaultExpandInternalEntities = XML_TRUE;
1083 parser->m_tagLevel = 0;
1084 parser->m_tagStack = NULL;
1085 parser->m_inheritedBindings = NULL;
1086 parser->m_nSpecifiedAtts = 0;
1087 parser->m_unknownEncodingMem = NULL;
1088 parser->m_unknownEncodingRelease = NULL;
1089 parser->m_unknownEncodingData = NULL;
1090 parser->m_parentParser = NULL;
1091 parser->m_parsingStatus.parsing = XML_INITIALIZED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001092#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001093 parser->m_isParamEntity = XML_FALSE;
1094 parser->m_useForeignDTD = XML_FALSE;
1095 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001096#endif
Elliott Hughes72472942018-01-10 08:36:10 -08001097 parser->m_hash_secret_salt = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001098}
1099
Elliott Hughes72472942018-01-10 08:36:10 -08001100/* moves list of bindings to m_freeBindingList */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001101static void FASTCALL
1102moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
1103{
1104 while (bindings) {
1105 BINDING *b = bindings;
1106 bindings = bindings->nextTagBinding;
Elliott Hughes72472942018-01-10 08:36:10 -08001107 b->nextTagBinding = parser->m_freeBindingList;
1108 parser->m_freeBindingList = b;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001109 }
1110}
1111
1112XML_Bool XMLCALL
1113XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
1114{
1115 TAG *tStk;
1116 OPEN_INTERNAL_ENTITY *openEntityList;
Elliott Hughes72472942018-01-10 08:36:10 -08001117
1118 if (parser == NULL)
1119 return XML_FALSE;
1120
1121 if (parser->m_parentParser)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001122 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08001123 /* move m_tagStack to m_freeTagList */
1124 tStk = parser->m_tagStack;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001125 while (tStk) {
1126 TAG *tag = tStk;
1127 tStk = tStk->parent;
Elliott Hughes72472942018-01-10 08:36:10 -08001128 tag->parent = parser->m_freeTagList;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001129 moveToFreeBindingList(parser, tag->bindings);
1130 tag->bindings = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08001131 parser->m_freeTagList = tag;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001132 }
Elliott Hughes72472942018-01-10 08:36:10 -08001133 /* move m_openInternalEntities to m_freeInternalEntities */
1134 openEntityList = parser->m_openInternalEntities;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001135 while (openEntityList) {
1136 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
1137 openEntityList = openEntity->next;
Elliott Hughes72472942018-01-10 08:36:10 -08001138 openEntity->next = parser->m_freeInternalEntities;
1139 parser->m_freeInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001140 }
Elliott Hughes72472942018-01-10 08:36:10 -08001141 moveToFreeBindingList(parser, parser->m_inheritedBindings);
1142 FREE(parser, parser->m_unknownEncodingMem);
1143 if (parser->m_unknownEncodingRelease)
1144 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1145 poolClear(&parser->m_tempPool);
1146 poolClear(&parser->m_temp2Pool);
1147 FREE(parser, (void *)parser->m_protocolEncodingName);
1148 parser->m_protocolEncodingName = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001149 parserInit(parser, encodingName);
Elliott Hughes72472942018-01-10 08:36:10 -08001150 dtdReset(parser->m_dtd, &parser->m_mem);
Elliott Hughes35e432d2012-09-09 14:23:38 -07001151 return XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001152}
1153
1154enum XML_Status XMLCALL
1155XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
1156{
Elliott Hughes72472942018-01-10 08:36:10 -08001157 if (parser == NULL)
1158 return XML_STATUS_ERROR;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001159 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
1160 XXX There's no way for the caller to determine which of the
1161 XXX possible error cases caused the XML_STATUS_ERROR return.
1162 */
Elliott Hughes72472942018-01-10 08:36:10 -08001163 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001164 return XML_STATUS_ERROR;
Elliott Hughes72472942018-01-10 08:36:10 -08001165
1166 /* Get rid of any previous encoding name */
1167 FREE(parser, (void *)parser->m_protocolEncodingName);
1168
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001169 if (encodingName == NULL)
Elliott Hughes72472942018-01-10 08:36:10 -08001170 /* No new encoding name */
1171 parser->m_protocolEncodingName = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001172 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001173 /* Copy the new encoding name into allocated memory */
1174 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1175 if (!parser->m_protocolEncodingName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001176 return XML_STATUS_ERROR;
1177 }
1178 return XML_STATUS_OK;
1179}
1180
1181XML_Parser XMLCALL
1182XML_ExternalEntityParserCreate(XML_Parser oldParser,
1183 const XML_Char *context,
1184 const XML_Char *encodingName)
1185{
1186 XML_Parser parser = oldParser;
1187 DTD *newDtd = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08001188 DTD *oldDtd;
1189 XML_StartElementHandler oldStartElementHandler;
1190 XML_EndElementHandler oldEndElementHandler;
1191 XML_CharacterDataHandler oldCharacterDataHandler;
1192 XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
1193 XML_CommentHandler oldCommentHandler;
1194 XML_StartCdataSectionHandler oldStartCdataSectionHandler;
1195 XML_EndCdataSectionHandler oldEndCdataSectionHandler;
1196 XML_DefaultHandler oldDefaultHandler;
1197 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
1198 XML_NotationDeclHandler oldNotationDeclHandler;
1199 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
1200 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
1201 XML_NotStandaloneHandler oldNotStandaloneHandler;
1202 XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
1203 XML_SkippedEntityHandler oldSkippedEntityHandler;
1204 XML_UnknownEncodingHandler oldUnknownEncodingHandler;
1205 XML_ElementDeclHandler oldElementDeclHandler;
1206 XML_AttlistDeclHandler oldAttlistDeclHandler;
1207 XML_EntityDeclHandler oldEntityDeclHandler;
1208 XML_XmlDeclHandler oldXmlDeclHandler;
1209 ELEMENT_TYPE * oldDeclElementType;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001210
Elliott Hughes72472942018-01-10 08:36:10 -08001211 void *oldUserData;
1212 void *oldHandlerArg;
1213 XML_Bool oldDefaultExpandInternalEntities;
1214 XML_Parser oldExternalEntityRefHandlerArg;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001215#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001216 enum XML_ParamEntityParsing oldParamEntityParsing;
1217 int oldInEntityValue;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001218#endif
Elliott Hughes72472942018-01-10 08:36:10 -08001219 XML_Bool oldns_triplets;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001220 /* Note that the new parser shares the same hash secret as the old
1221 parser, so that dtdCopy and copyEntityTable can lookup values
1222 from hash tables associated with either parser without us having
1223 to worry which hash secrets each table has.
1224 */
Elliott Hughes72472942018-01-10 08:36:10 -08001225 unsigned long oldhash_secret_salt;
1226
1227 /* Validate the oldParser parameter before we pull everything out of it */
1228 if (oldParser == NULL)
1229 return NULL;
1230
1231 /* Stash the original parser contents on the stack */
1232 oldDtd = parser->m_dtd;
1233 oldStartElementHandler = parser->m_startElementHandler;
1234 oldEndElementHandler = parser->m_endElementHandler;
1235 oldCharacterDataHandler = parser->m_characterDataHandler;
1236 oldProcessingInstructionHandler = parser->m_processingInstructionHandler;
1237 oldCommentHandler = parser->m_commentHandler;
1238 oldStartCdataSectionHandler = parser->m_startCdataSectionHandler;
1239 oldEndCdataSectionHandler = parser->m_endCdataSectionHandler;
1240 oldDefaultHandler = parser->m_defaultHandler;
1241 oldUnparsedEntityDeclHandler = parser->m_unparsedEntityDeclHandler;
1242 oldNotationDeclHandler = parser->m_notationDeclHandler;
1243 oldStartNamespaceDeclHandler = parser->m_startNamespaceDeclHandler;
1244 oldEndNamespaceDeclHandler = parser->m_endNamespaceDeclHandler;
1245 oldNotStandaloneHandler = parser->m_notStandaloneHandler;
1246 oldExternalEntityRefHandler = parser->m_externalEntityRefHandler;
1247 oldSkippedEntityHandler = parser->m_skippedEntityHandler;
1248 oldUnknownEncodingHandler = parser->m_unknownEncodingHandler;
1249 oldElementDeclHandler = parser->m_elementDeclHandler;
1250 oldAttlistDeclHandler = parser->m_attlistDeclHandler;
1251 oldEntityDeclHandler = parser->m_entityDeclHandler;
1252 oldXmlDeclHandler = parser->m_xmlDeclHandler;
1253 oldDeclElementType = parser->m_declElementType;
1254
1255 oldUserData = parser->m_userData;
1256 oldHandlerArg = parser->m_handlerArg;
1257 oldDefaultExpandInternalEntities = parser->m_defaultExpandInternalEntities;
1258 oldExternalEntityRefHandlerArg = parser->m_externalEntityRefHandlerArg;
1259#ifdef XML_DTD
1260 oldParamEntityParsing = parser->m_paramEntityParsing;
1261 oldInEntityValue = parser->m_prologState.inEntityValue;
1262#endif
1263 oldns_triplets = parser->m_ns_triplets;
1264 /* Note that the new parser shares the same hash secret as the old
1265 parser, so that dtdCopy and copyEntityTable can lookup values
1266 from hash tables associated with either parser without us having
1267 to worry which hash secrets each table has.
1268 */
1269 oldhash_secret_salt = parser->m_hash_secret_salt;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001270
1271#ifdef XML_DTD
1272 if (!context)
1273 newDtd = oldDtd;
1274#endif /* XML_DTD */
1275
1276 /* Note that the magical uses of the pre-processor to make field
1277 access look more like C++ require that `parser' be overwritten
1278 here. This makes this function more painful to follow than it
1279 would be otherwise.
1280 */
Elliott Hughes72472942018-01-10 08:36:10 -08001281 if (parser->m_ns) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001282 XML_Char tmp[2];
Elliott Hughes72472942018-01-10 08:36:10 -08001283 *tmp = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001284 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1285 }
1286 else {
1287 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1288 }
1289
1290 if (!parser)
1291 return NULL;
1292
Elliott Hughes72472942018-01-10 08:36:10 -08001293 parser->m_startElementHandler = oldStartElementHandler;
1294 parser->m_endElementHandler = oldEndElementHandler;
1295 parser->m_characterDataHandler = oldCharacterDataHandler;
1296 parser->m_processingInstructionHandler = oldProcessingInstructionHandler;
1297 parser->m_commentHandler = oldCommentHandler;
1298 parser->m_startCdataSectionHandler = oldStartCdataSectionHandler;
1299 parser->m_endCdataSectionHandler = oldEndCdataSectionHandler;
1300 parser->m_defaultHandler = oldDefaultHandler;
1301 parser->m_unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1302 parser->m_notationDeclHandler = oldNotationDeclHandler;
1303 parser->m_startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1304 parser->m_endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1305 parser->m_notStandaloneHandler = oldNotStandaloneHandler;
1306 parser->m_externalEntityRefHandler = oldExternalEntityRefHandler;
1307 parser->m_skippedEntityHandler = oldSkippedEntityHandler;
1308 parser->m_unknownEncodingHandler = oldUnknownEncodingHandler;
1309 parser->m_elementDeclHandler = oldElementDeclHandler;
1310 parser->m_attlistDeclHandler = oldAttlistDeclHandler;
1311 parser->m_entityDeclHandler = oldEntityDeclHandler;
1312 parser->m_xmlDeclHandler = oldXmlDeclHandler;
1313 parser->m_declElementType = oldDeclElementType;
1314 parser->m_userData = oldUserData;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001315 if (oldUserData == oldHandlerArg)
Elliott Hughes72472942018-01-10 08:36:10 -08001316 parser->m_handlerArg = parser->m_userData;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001317 else
Elliott Hughes72472942018-01-10 08:36:10 -08001318 parser->m_handlerArg = parser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001319 if (oldExternalEntityRefHandlerArg != oldParser)
Elliott Hughes72472942018-01-10 08:36:10 -08001320 parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1321 parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1322 parser->m_ns_triplets = oldns_triplets;
1323 parser->m_hash_secret_salt = oldhash_secret_salt;
1324 parser->m_parentParser = oldParser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001325#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001326 parser->m_paramEntityParsing = oldParamEntityParsing;
1327 parser->m_prologState.inEntityValue = oldInEntityValue;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001328 if (context) {
1329#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08001330 if (!dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001331 || !setContext(parser, context)) {
1332 XML_ParserFree(parser);
1333 return NULL;
1334 }
Elliott Hughes72472942018-01-10 08:36:10 -08001335 parser->m_processor = externalEntityInitProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001336#ifdef XML_DTD
1337 }
1338 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001339 /* The DTD instance referenced by parser->m_dtd is shared between the document's
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001340 root parser and external PE parsers, therefore one does not need to
1341 call setContext. In addition, one also *must* not call setContext,
1342 because this would overwrite existing prefix->binding pointers in
Elliott Hughes72472942018-01-10 08:36:10 -08001343 parser->m_dtd with ones that get destroyed with the external PE parser.
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001344 This would leave those prefixes with dangling pointers.
1345 */
Elliott Hughes72472942018-01-10 08:36:10 -08001346 parser->m_isParamEntity = XML_TRUE;
1347 XmlPrologStateInitExternalEntity(&parser->m_prologState);
1348 parser->m_processor = externalParEntInitProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001349 }
1350#endif /* XML_DTD */
1351 return parser;
1352}
1353
1354static void FASTCALL
1355destroyBindings(BINDING *bindings, XML_Parser parser)
1356{
1357 for (;;) {
1358 BINDING *b = bindings;
1359 if (!b)
1360 break;
1361 bindings = b->nextTagBinding;
Elliott Hughes72472942018-01-10 08:36:10 -08001362 FREE(parser, b->uri);
1363 FREE(parser, b);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001364 }
1365}
1366
1367void XMLCALL
1368XML_ParserFree(XML_Parser parser)
1369{
1370 TAG *tagList;
1371 OPEN_INTERNAL_ENTITY *entityList;
1372 if (parser == NULL)
1373 return;
Elliott Hughes72472942018-01-10 08:36:10 -08001374 /* free m_tagStack and m_freeTagList */
1375 tagList = parser->m_tagStack;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001376 for (;;) {
1377 TAG *p;
1378 if (tagList == NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08001379 if (parser->m_freeTagList == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001380 break;
Elliott Hughes72472942018-01-10 08:36:10 -08001381 tagList = parser->m_freeTagList;
1382 parser->m_freeTagList = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001383 }
1384 p = tagList;
1385 tagList = tagList->parent;
Elliott Hughes72472942018-01-10 08:36:10 -08001386 FREE(parser, p->buf);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001387 destroyBindings(p->bindings, parser);
Elliott Hughes72472942018-01-10 08:36:10 -08001388 FREE(parser, p);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001389 }
Elliott Hughes72472942018-01-10 08:36:10 -08001390 /* free m_openInternalEntities and m_freeInternalEntities */
1391 entityList = parser->m_openInternalEntities;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001392 for (;;) {
1393 OPEN_INTERNAL_ENTITY *openEntity;
1394 if (entityList == NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08001395 if (parser->m_freeInternalEntities == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001396 break;
Elliott Hughes72472942018-01-10 08:36:10 -08001397 entityList = parser->m_freeInternalEntities;
1398 parser->m_freeInternalEntities = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001399 }
1400 openEntity = entityList;
1401 entityList = entityList->next;
Elliott Hughes72472942018-01-10 08:36:10 -08001402 FREE(parser, openEntity);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001403 }
1404
Elliott Hughes72472942018-01-10 08:36:10 -08001405 destroyBindings(parser->m_freeBindingList, parser);
1406 destroyBindings(parser->m_inheritedBindings, parser);
1407 poolDestroy(&parser->m_tempPool);
1408 poolDestroy(&parser->m_temp2Pool);
1409 FREE(parser, (void *)parser->m_protocolEncodingName);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001410#ifdef XML_DTD
1411 /* external parameter entity parsers share the DTD structure
1412 parser->m_dtd with the root parser, so we must not destroy it
1413 */
Elliott Hughes72472942018-01-10 08:36:10 -08001414 if (!parser->m_isParamEntity && parser->m_dtd)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001415#else
Elliott Hughes72472942018-01-10 08:36:10 -08001416 if (parser->m_dtd)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001417#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08001418 dtdDestroy(parser->m_dtd, (XML_Bool)!parser->m_parentParser, &parser->m_mem);
1419 FREE(parser, (void *)parser->m_atts);
Elliott Hughes35e432d2012-09-09 14:23:38 -07001420#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08001421 FREE(parser, (void *)parser->m_attInfo);
Elliott Hughes35e432d2012-09-09 14:23:38 -07001422#endif
Elliott Hughes72472942018-01-10 08:36:10 -08001423 FREE(parser, parser->m_groupConnector);
1424 FREE(parser, parser->m_buffer);
1425 FREE(parser, parser->m_dataBuf);
1426 FREE(parser, parser->m_nsAtts);
1427 FREE(parser, parser->m_unknownEncodingMem);
1428 if (parser->m_unknownEncodingRelease)
1429 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1430 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001431}
1432
1433void XMLCALL
1434XML_UseParserAsHandlerArg(XML_Parser parser)
1435{
Elliott Hughes72472942018-01-10 08:36:10 -08001436 if (parser != NULL)
1437 parser->m_handlerArg = parser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001438}
1439
1440enum XML_Error XMLCALL
1441XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1442{
Elliott Hughes72472942018-01-10 08:36:10 -08001443 if (parser == NULL)
1444 return XML_ERROR_INVALID_ARGUMENT;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001445#ifdef XML_DTD
1446 /* block after XML_Parse()/XML_ParseBuffer() has been called */
Elliott Hughes72472942018-01-10 08:36:10 -08001447 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001448 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
Elliott Hughes72472942018-01-10 08:36:10 -08001449 parser->m_useForeignDTD = useDTD;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001450 return XML_ERROR_NONE;
1451#else
1452 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1453#endif
1454}
1455
1456void XMLCALL
1457XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1458{
Elliott Hughes72472942018-01-10 08:36:10 -08001459 if (parser == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001460 return;
Elliott Hughes72472942018-01-10 08:36:10 -08001461 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1462 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1463 return;
1464 parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001465}
1466
1467void XMLCALL
1468XML_SetUserData(XML_Parser parser, void *p)
1469{
Elliott Hughes72472942018-01-10 08:36:10 -08001470 if (parser == NULL)
1471 return;
1472 if (parser->m_handlerArg == parser->m_userData)
1473 parser->m_handlerArg = parser->m_userData = p;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001474 else
Elliott Hughes72472942018-01-10 08:36:10 -08001475 parser->m_userData = p;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001476}
1477
1478enum XML_Status XMLCALL
1479XML_SetBase(XML_Parser parser, const XML_Char *p)
1480{
Elliott Hughes72472942018-01-10 08:36:10 -08001481 if (parser == NULL)
1482 return XML_STATUS_ERROR;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001483 if (p) {
Elliott Hughes72472942018-01-10 08:36:10 -08001484 p = poolCopyString(&parser->m_dtd->pool, p);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001485 if (!p)
1486 return XML_STATUS_ERROR;
Elliott Hughes72472942018-01-10 08:36:10 -08001487 parser->m_curBase = p;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001488 }
1489 else
Elliott Hughes72472942018-01-10 08:36:10 -08001490 parser->m_curBase = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001491 return XML_STATUS_OK;
1492}
1493
1494const XML_Char * XMLCALL
1495XML_GetBase(XML_Parser parser)
1496{
Elliott Hughes72472942018-01-10 08:36:10 -08001497 if (parser == NULL)
1498 return NULL;
1499 return parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001500}
1501
1502int XMLCALL
1503XML_GetSpecifiedAttributeCount(XML_Parser parser)
1504{
Elliott Hughes72472942018-01-10 08:36:10 -08001505 if (parser == NULL)
1506 return -1;
1507 return parser->m_nSpecifiedAtts;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001508}
1509
1510int XMLCALL
1511XML_GetIdAttributeIndex(XML_Parser parser)
1512{
Elliott Hughes72472942018-01-10 08:36:10 -08001513 if (parser == NULL)
1514 return -1;
1515 return parser->m_idAttIndex;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001516}
1517
Elliott Hughes35e432d2012-09-09 14:23:38 -07001518#ifdef XML_ATTR_INFO
1519const XML_AttrInfo * XMLCALL
1520XML_GetAttributeInfo(XML_Parser parser)
1521{
Elliott Hughes72472942018-01-10 08:36:10 -08001522 if (parser == NULL)
1523 return NULL;
1524 return parser->m_attInfo;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001525}
1526#endif
1527
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001528void XMLCALL
1529XML_SetElementHandler(XML_Parser parser,
1530 XML_StartElementHandler start,
1531 XML_EndElementHandler end)
1532{
Elliott Hughes72472942018-01-10 08:36:10 -08001533 if (parser == NULL)
1534 return;
1535 parser->m_startElementHandler = start;
1536 parser->m_endElementHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001537}
1538
1539void XMLCALL
1540XML_SetStartElementHandler(XML_Parser parser,
1541 XML_StartElementHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001542 if (parser != NULL)
1543 parser->m_startElementHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001544}
1545
1546void XMLCALL
1547XML_SetEndElementHandler(XML_Parser parser,
1548 XML_EndElementHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001549 if (parser != NULL)
1550 parser->m_endElementHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001551}
1552
1553void XMLCALL
1554XML_SetCharacterDataHandler(XML_Parser parser,
1555 XML_CharacterDataHandler handler)
1556{
Elliott Hughes72472942018-01-10 08:36:10 -08001557 if (parser != NULL)
1558 parser->m_characterDataHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001559}
1560
1561void XMLCALL
1562XML_SetProcessingInstructionHandler(XML_Parser parser,
1563 XML_ProcessingInstructionHandler handler)
1564{
Elliott Hughes72472942018-01-10 08:36:10 -08001565 if (parser != NULL)
1566 parser->m_processingInstructionHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001567}
1568
1569void XMLCALL
1570XML_SetCommentHandler(XML_Parser parser,
1571 XML_CommentHandler handler)
1572{
Elliott Hughes72472942018-01-10 08:36:10 -08001573 if (parser != NULL)
1574 parser->m_commentHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001575}
1576
1577void XMLCALL
1578XML_SetCdataSectionHandler(XML_Parser parser,
1579 XML_StartCdataSectionHandler start,
1580 XML_EndCdataSectionHandler end)
1581{
Elliott Hughes72472942018-01-10 08:36:10 -08001582 if (parser == NULL)
1583 return;
1584 parser->m_startCdataSectionHandler = start;
1585 parser->m_endCdataSectionHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001586}
1587
1588void XMLCALL
1589XML_SetStartCdataSectionHandler(XML_Parser parser,
1590 XML_StartCdataSectionHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001591 if (parser != NULL)
1592 parser->m_startCdataSectionHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001593}
1594
1595void XMLCALL
1596XML_SetEndCdataSectionHandler(XML_Parser parser,
1597 XML_EndCdataSectionHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001598 if (parser != NULL)
1599 parser->m_endCdataSectionHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001600}
1601
1602void XMLCALL
1603XML_SetDefaultHandler(XML_Parser parser,
1604 XML_DefaultHandler handler)
1605{
Elliott Hughes72472942018-01-10 08:36:10 -08001606 if (parser == NULL)
1607 return;
1608 parser->m_defaultHandler = handler;
1609 parser->m_defaultExpandInternalEntities = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001610}
1611
1612void XMLCALL
1613XML_SetDefaultHandlerExpand(XML_Parser parser,
1614 XML_DefaultHandler handler)
1615{
Elliott Hughes72472942018-01-10 08:36:10 -08001616 if (parser == NULL)
1617 return;
1618 parser->m_defaultHandler = handler;
1619 parser->m_defaultExpandInternalEntities = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001620}
1621
1622void XMLCALL
1623XML_SetDoctypeDeclHandler(XML_Parser parser,
1624 XML_StartDoctypeDeclHandler start,
1625 XML_EndDoctypeDeclHandler end)
1626{
Elliott Hughes72472942018-01-10 08:36:10 -08001627 if (parser == NULL)
1628 return;
1629 parser->m_startDoctypeDeclHandler = start;
1630 parser->m_endDoctypeDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001631}
1632
1633void XMLCALL
1634XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1635 XML_StartDoctypeDeclHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001636 if (parser != NULL)
1637 parser->m_startDoctypeDeclHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001638}
1639
1640void XMLCALL
1641XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1642 XML_EndDoctypeDeclHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001643 if (parser != NULL)
1644 parser->m_endDoctypeDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001645}
1646
1647void XMLCALL
1648XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1649 XML_UnparsedEntityDeclHandler handler)
1650{
Elliott Hughes72472942018-01-10 08:36:10 -08001651 if (parser != NULL)
1652 parser->m_unparsedEntityDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001653}
1654
1655void XMLCALL
1656XML_SetNotationDeclHandler(XML_Parser parser,
1657 XML_NotationDeclHandler handler)
1658{
Elliott Hughes72472942018-01-10 08:36:10 -08001659 if (parser != NULL)
1660 parser->m_notationDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001661}
1662
1663void XMLCALL
1664XML_SetNamespaceDeclHandler(XML_Parser parser,
1665 XML_StartNamespaceDeclHandler start,
1666 XML_EndNamespaceDeclHandler end)
1667{
Elliott Hughes72472942018-01-10 08:36:10 -08001668 if (parser == NULL)
1669 return;
1670 parser->m_startNamespaceDeclHandler = start;
1671 parser->m_endNamespaceDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001672}
1673
1674void XMLCALL
1675XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1676 XML_StartNamespaceDeclHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001677 if (parser != NULL)
1678 parser->m_startNamespaceDeclHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001679}
1680
1681void XMLCALL
1682XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1683 XML_EndNamespaceDeclHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001684 if (parser != NULL)
1685 parser->m_endNamespaceDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001686}
1687
1688void XMLCALL
1689XML_SetNotStandaloneHandler(XML_Parser parser,
1690 XML_NotStandaloneHandler handler)
1691{
Elliott Hughes72472942018-01-10 08:36:10 -08001692 if (parser != NULL)
1693 parser->m_notStandaloneHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001694}
1695
1696void XMLCALL
1697XML_SetExternalEntityRefHandler(XML_Parser parser,
1698 XML_ExternalEntityRefHandler handler)
1699{
Elliott Hughes72472942018-01-10 08:36:10 -08001700 if (parser != NULL)
1701 parser->m_externalEntityRefHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001702}
1703
1704void XMLCALL
1705XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1706{
Elliott Hughes72472942018-01-10 08:36:10 -08001707 if (parser == NULL)
1708 return;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001709 if (arg)
Elliott Hughes72472942018-01-10 08:36:10 -08001710 parser->m_externalEntityRefHandlerArg = (XML_Parser)arg;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001711 else
Elliott Hughes72472942018-01-10 08:36:10 -08001712 parser->m_externalEntityRefHandlerArg = parser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001713}
1714
1715void XMLCALL
1716XML_SetSkippedEntityHandler(XML_Parser parser,
1717 XML_SkippedEntityHandler handler)
1718{
Elliott Hughes72472942018-01-10 08:36:10 -08001719 if (parser != NULL)
1720 parser->m_skippedEntityHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001721}
1722
1723void XMLCALL
1724XML_SetUnknownEncodingHandler(XML_Parser parser,
1725 XML_UnknownEncodingHandler handler,
1726 void *data)
1727{
Elliott Hughes72472942018-01-10 08:36:10 -08001728 if (parser == NULL)
1729 return;
1730 parser->m_unknownEncodingHandler = handler;
1731 parser->m_unknownEncodingHandlerData = data;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001732}
1733
1734void XMLCALL
1735XML_SetElementDeclHandler(XML_Parser parser,
1736 XML_ElementDeclHandler eldecl)
1737{
Elliott Hughes72472942018-01-10 08:36:10 -08001738 if (parser != NULL)
1739 parser->m_elementDeclHandler = eldecl;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001740}
1741
1742void XMLCALL
1743XML_SetAttlistDeclHandler(XML_Parser parser,
1744 XML_AttlistDeclHandler attdecl)
1745{
Elliott Hughes72472942018-01-10 08:36:10 -08001746 if (parser != NULL)
1747 parser->m_attlistDeclHandler = attdecl;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001748}
1749
1750void XMLCALL
1751XML_SetEntityDeclHandler(XML_Parser parser,
1752 XML_EntityDeclHandler handler)
1753{
Elliott Hughes72472942018-01-10 08:36:10 -08001754 if (parser != NULL)
1755 parser->m_entityDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001756}
1757
1758void XMLCALL
1759XML_SetXmlDeclHandler(XML_Parser parser,
1760 XML_XmlDeclHandler handler) {
Elliott Hughes72472942018-01-10 08:36:10 -08001761 if (parser != NULL)
1762 parser->m_xmlDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001763}
1764
1765int XMLCALL
1766XML_SetParamEntityParsing(XML_Parser parser,
1767 enum XML_ParamEntityParsing peParsing)
1768{
Elliott Hughes72472942018-01-10 08:36:10 -08001769 if (parser == NULL)
1770 return 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001771 /* block after XML_Parse()/XML_ParseBuffer() has been called */
Elliott Hughes72472942018-01-10 08:36:10 -08001772 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001773 return 0;
1774#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001775 parser->m_paramEntityParsing = peParsing;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001776 return 1;
1777#else
1778 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1779#endif
1780}
1781
Elliott Hughes35e432d2012-09-09 14:23:38 -07001782int XMLCALL
1783XML_SetHashSalt(XML_Parser parser,
1784 unsigned long hash_salt)
1785{
Elliott Hughes72472942018-01-10 08:36:10 -08001786 if (parser == NULL)
Elliott Hughes35e432d2012-09-09 14:23:38 -07001787 return 0;
Elliott Hughes72472942018-01-10 08:36:10 -08001788 if (parser->m_parentParser)
1789 return XML_SetHashSalt(parser->m_parentParser, hash_salt);
1790 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1791 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1792 return 0;
1793 parser->m_hash_secret_salt = hash_salt;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001794 return 1;
1795}
1796
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001797enum XML_Status XMLCALL
1798XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1799{
Elliott Hughes72472942018-01-10 08:36:10 -08001800 if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
1801 if (parser != NULL)
1802 parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
1803 return XML_STATUS_ERROR;
1804 }
1805 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001806 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08001807 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001808 return XML_STATUS_ERROR;
1809 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08001810 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001811 return XML_STATUS_ERROR;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001812 case XML_INITIALIZED:
Elliott Hughes72472942018-01-10 08:36:10 -08001813 if (parser->m_parentParser == NULL && !startParsing(parser)) {
1814 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001815 return XML_STATUS_ERROR;
1816 }
Elliott Hughesaaec48e2018-08-16 16:29:01 -07001817 /* fall through */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001818 default:
Elliott Hughes72472942018-01-10 08:36:10 -08001819 parser->m_parsingStatus.parsing = XML_PARSING;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001820 }
1821
1822 if (len == 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08001823 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001824 if (!isFinal)
1825 return XML_STATUS_OK;
Elliott Hughes72472942018-01-10 08:36:10 -08001826 parser->m_positionPtr = parser->m_bufferPtr;
1827 parser->m_parseEndPtr = parser->m_bufferEnd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001828
1829 /* If data are left over from last buffer, and we now know that these
1830 data are the final chunk of input, then we have to check them again
1831 to detect errors based on that fact.
1832 */
Elliott Hughes72472942018-01-10 08:36:10 -08001833 parser->m_errorCode = parser->m_processor(parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001834
Elliott Hughes72472942018-01-10 08:36:10 -08001835 if (parser->m_errorCode == XML_ERROR_NONE) {
1836 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001837 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08001838 /* It is hard to be certain, but it seems that this case
1839 * cannot occur. This code is cleaning up a previous parse
1840 * with no new data (since len == 0). Changing the parsing
1841 * state requires getting to execute a handler function, and
1842 * there doesn't seem to be an opportunity for that while in
1843 * this circumstance.
1844 *
1845 * Given the uncertainty, we retain the code but exclude it
1846 * from coverage tests.
1847 *
1848 * LCOV_EXCL_START
1849 */
1850 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
1851 parser->m_positionPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001852 return XML_STATUS_SUSPENDED;
Elliott Hughes72472942018-01-10 08:36:10 -08001853 /* LCOV_EXCL_STOP */
Elliott Hughes35e432d2012-09-09 14:23:38 -07001854 case XML_INITIALIZED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001855 case XML_PARSING:
Elliott Hughes72472942018-01-10 08:36:10 -08001856 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001857 /* fall through */
1858 default:
1859 return XML_STATUS_OK;
1860 }
1861 }
Elliott Hughes72472942018-01-10 08:36:10 -08001862 parser->m_eventEndPtr = parser->m_eventPtr;
1863 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001864 return XML_STATUS_ERROR;
1865 }
1866#ifndef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08001867 else if (parser->m_bufferPtr == parser->m_bufferEnd) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001868 const char *end;
1869 int nLeftOver;
Paul Duffinc05e0322016-05-04 10:42:31 +01001870 enum XML_Status result;
Elliott Hughes72472942018-01-10 08:36:10 -08001871 /* Detect overflow (a+b > MAX <==> b > MAX-a) */
1872 if (len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) {
1873 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1874 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1875 parser->m_processor = errorProcessor;
1876 return XML_STATUS_ERROR;
1877 }
1878 parser->m_parseEndByteIndex += len;
1879 parser->m_positionPtr = s;
1880 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001881
Elliott Hughes72472942018-01-10 08:36:10 -08001882 parser->m_errorCode = parser->m_processor(parser, s, parser->m_parseEndPtr = s + len, &end);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001883
Elliott Hughes72472942018-01-10 08:36:10 -08001884 if (parser->m_errorCode != XML_ERROR_NONE) {
1885 parser->m_eventEndPtr = parser->m_eventPtr;
1886 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001887 return XML_STATUS_ERROR;
1888 }
1889 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001890 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001891 case XML_SUSPENDED:
1892 result = XML_STATUS_SUSPENDED;
1893 break;
1894 case XML_INITIALIZED:
1895 case XML_PARSING:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001896 if (isFinal) {
Elliott Hughes72472942018-01-10 08:36:10 -08001897 parser->m_parsingStatus.parsing = XML_FINISHED;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001898 return XML_STATUS_OK;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001899 }
Elliott Hughes35e432d2012-09-09 14:23:38 -07001900 /* fall through */
1901 default:
1902 result = XML_STATUS_OK;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001903 }
1904 }
1905
Elliott Hughes72472942018-01-10 08:36:10 -08001906 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end, &parser->m_position);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001907 nLeftOver = s + len - end;
1908 if (nLeftOver) {
Elliott Hughes72472942018-01-10 08:36:10 -08001909 if (parser->m_buffer == NULL || nLeftOver > parser->m_bufferLim - parser->m_buffer) {
1910 /* avoid _signed_ integer overflow */
1911 char *temp = NULL;
1912 const int bytesToAllocate = (int)((unsigned)len * 2U);
1913 if (bytesToAllocate > 0) {
1914 temp = (char *)REALLOC(parser, parser->m_buffer, bytesToAllocate);
1915 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001916 if (temp == NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08001917 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1918 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1919 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001920 return XML_STATUS_ERROR;
1921 }
Elliott Hughes72472942018-01-10 08:36:10 -08001922 parser->m_buffer = temp;
1923 parser->m_bufferLim = parser->m_buffer + bytesToAllocate;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001924 }
Elliott Hughes72472942018-01-10 08:36:10 -08001925 memcpy(parser->m_buffer, end, nLeftOver);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001926 }
Elliott Hughes72472942018-01-10 08:36:10 -08001927 parser->m_bufferPtr = parser->m_buffer;
1928 parser->m_bufferEnd = parser->m_buffer + nLeftOver;
1929 parser->m_positionPtr = parser->m_bufferPtr;
1930 parser->m_parseEndPtr = parser->m_bufferEnd;
1931 parser->m_eventPtr = parser->m_bufferPtr;
1932 parser->m_eventEndPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001933 return result;
1934 }
1935#endif /* not defined XML_CONTEXT_BYTES */
1936 else {
1937 void *buff = XML_GetBuffer(parser, len);
1938 if (buff == NULL)
1939 return XML_STATUS_ERROR;
1940 else {
1941 memcpy(buff, s, len);
1942 return XML_ParseBuffer(parser, len, isFinal);
1943 }
1944 }
1945}
1946
1947enum XML_Status XMLCALL
1948XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1949{
1950 const char *start;
1951 enum XML_Status result = XML_STATUS_OK;
1952
Elliott Hughes72472942018-01-10 08:36:10 -08001953 if (parser == NULL)
1954 return XML_STATUS_ERROR;
1955 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001956 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08001957 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001958 return XML_STATUS_ERROR;
1959 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08001960 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001961 return XML_STATUS_ERROR;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001962 case XML_INITIALIZED:
Elliott Hughes72472942018-01-10 08:36:10 -08001963 if (parser->m_parentParser == NULL && !startParsing(parser)) {
1964 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001965 return XML_STATUS_ERROR;
1966 }
Elliott Hughesaaec48e2018-08-16 16:29:01 -07001967 /* fall through */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001968 default:
Elliott Hughes72472942018-01-10 08:36:10 -08001969 parser->m_parsingStatus.parsing = XML_PARSING;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001970 }
1971
Elliott Hughes72472942018-01-10 08:36:10 -08001972 start = parser->m_bufferPtr;
1973 parser->m_positionPtr = start;
1974 parser->m_bufferEnd += len;
1975 parser->m_parseEndPtr = parser->m_bufferEnd;
1976 parser->m_parseEndByteIndex += len;
1977 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001978
Elliott Hughes72472942018-01-10 08:36:10 -08001979 parser->m_errorCode = parser->m_processor(parser, start, parser->m_parseEndPtr, &parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001980
Elliott Hughes72472942018-01-10 08:36:10 -08001981 if (parser->m_errorCode != XML_ERROR_NONE) {
1982 parser->m_eventEndPtr = parser->m_eventPtr;
1983 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001984 return XML_STATUS_ERROR;
1985 }
1986 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001987 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001988 case XML_SUSPENDED:
1989 result = XML_STATUS_SUSPENDED;
1990 break;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001991 case XML_INITIALIZED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001992 case XML_PARSING:
1993 if (isFinal) {
Elliott Hughes72472942018-01-10 08:36:10 -08001994 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001995 return result;
1996 }
1997 default: ; /* should not happen */
1998 }
1999 }
2000
Elliott Hughes72472942018-01-10 08:36:10 -08002001 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
2002 parser->m_positionPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002003 return result;
2004}
2005
2006void * XMLCALL
2007XML_GetBuffer(XML_Parser parser, int len)
2008{
Elliott Hughes72472942018-01-10 08:36:10 -08002009 if (parser == NULL)
2010 return NULL;
Paul Duffinc05e0322016-05-04 10:42:31 +01002011 if (len < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002012 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Paul Duffinc05e0322016-05-04 10:42:31 +01002013 return NULL;
2014 }
Elliott Hughes72472942018-01-10 08:36:10 -08002015 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002016 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08002017 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002018 return NULL;
2019 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08002020 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002021 return NULL;
2022 default: ;
2023 }
2024
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002025 if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)) {
Paul Duffinba34a0c2017-02-27 14:40:16 +00002026#ifdef XML_CONTEXT_BYTES
2027 int keep;
2028#endif /* defined XML_CONTEXT_BYTES */
2029 /* Do not invoke signed arithmetic overflow: */
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002030 int neededSize = (int) ((unsigned)len +
2031 (unsigned)EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd,
2032 parser->m_bufferPtr));
Paul Duffinc05e0322016-05-04 10:42:31 +01002033 if (neededSize < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002034 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Paul Duffinc05e0322016-05-04 10:42:31 +01002035 return NULL;
2036 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002037#ifdef XML_CONTEXT_BYTES
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002038 keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002039 if (keep > XML_CONTEXT_BYTES)
2040 keep = XML_CONTEXT_BYTES;
2041 neededSize += keep;
2042#endif /* defined XML_CONTEXT_BYTES */
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002043 if (neededSize <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002044#ifdef XML_CONTEXT_BYTES
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002045 if (keep < EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)) {
2046 int offset = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer) - keep;
2047 /* The buffer pointers cannot be NULL here; we have at least some bytes in the buffer */
Elliott Hughes72472942018-01-10 08:36:10 -08002048 memmove(parser->m_buffer, &parser->m_buffer[offset], parser->m_bufferEnd - parser->m_bufferPtr + keep);
2049 parser->m_bufferEnd -= offset;
2050 parser->m_bufferPtr -= offset;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002051 }
2052#else
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002053 if (parser->m_buffer && parser->m_bufferPtr) {
2054 memmove(parser->m_buffer, parser->m_bufferPtr,
2055 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
2056 parser->m_bufferEnd = parser->m_buffer +
2057 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
2058 parser->m_bufferPtr = parser->m_buffer;
2059 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002060#endif /* not defined XML_CONTEXT_BYTES */
2061 }
2062 else {
2063 char *newBuf;
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002064 int bufferSize = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002065 if (bufferSize == 0)
2066 bufferSize = INIT_BUFFER_SIZE;
2067 do {
Paul Duffinba34a0c2017-02-27 14:40:16 +00002068 /* Do not invoke signed arithmetic overflow: */
2069 bufferSize = (int) (2U * (unsigned) bufferSize);
Paul Duffinc05e0322016-05-04 10:42:31 +01002070 } while (bufferSize < neededSize && bufferSize > 0);
2071 if (bufferSize <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002072 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Paul Duffinc05e0322016-05-04 10:42:31 +01002073 return NULL;
2074 }
Elliott Hughes72472942018-01-10 08:36:10 -08002075 newBuf = (char *)MALLOC(parser, bufferSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002076 if (newBuf == 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002077 parser->m_errorCode = XML_ERROR_NO_MEMORY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002078 return NULL;
2079 }
Elliott Hughes72472942018-01-10 08:36:10 -08002080 parser->m_bufferLim = newBuf + bufferSize;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002081#ifdef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08002082 if (parser->m_bufferPtr) {
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002083 int keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002084 if (keep > XML_CONTEXT_BYTES)
2085 keep = XML_CONTEXT_BYTES;
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002086 memcpy(newBuf, &parser->m_bufferPtr[-keep],
2087 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) + keep);
Elliott Hughes72472942018-01-10 08:36:10 -08002088 FREE(parser, parser->m_buffer);
2089 parser->m_buffer = newBuf;
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002090 parser->m_bufferEnd = parser->m_buffer +
2091 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) + keep;
Elliott Hughes72472942018-01-10 08:36:10 -08002092 parser->m_bufferPtr = parser->m_buffer + keep;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002093 }
2094 else {
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002095 /* This must be a brand new buffer with no data in it yet */
2096 parser->m_bufferEnd = newBuf;
Elliott Hughes72472942018-01-10 08:36:10 -08002097 parser->m_bufferPtr = parser->m_buffer = newBuf;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002098 }
2099#else
Elliott Hughes72472942018-01-10 08:36:10 -08002100 if (parser->m_bufferPtr) {
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002101 memcpy(newBuf, parser->m_bufferPtr,
2102 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
Elliott Hughes72472942018-01-10 08:36:10 -08002103 FREE(parser, parser->m_buffer);
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002104 parser->m_bufferEnd = newBuf +
2105 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002106 }
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002107 else {
2108 /* This must be a brand new buffer with no data in it yet */
2109 parser->m_bufferEnd = newBuf;
2110 }
Elliott Hughes72472942018-01-10 08:36:10 -08002111 parser->m_bufferPtr = parser->m_buffer = newBuf;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002112#endif /* not defined XML_CONTEXT_BYTES */
2113 }
Elliott Hughes72472942018-01-10 08:36:10 -08002114 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
2115 parser->m_positionPtr = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002116 }
Elliott Hughes72472942018-01-10 08:36:10 -08002117 return parser->m_bufferEnd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002118}
2119
2120enum XML_Status XMLCALL
2121XML_StopParser(XML_Parser parser, XML_Bool resumable)
2122{
Elliott Hughes72472942018-01-10 08:36:10 -08002123 if (parser == NULL)
2124 return XML_STATUS_ERROR;
2125 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002126 case XML_SUSPENDED:
2127 if (resumable) {
Elliott Hughes72472942018-01-10 08:36:10 -08002128 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002129 return XML_STATUS_ERROR;
2130 }
Elliott Hughes72472942018-01-10 08:36:10 -08002131 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002132 break;
2133 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08002134 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002135 return XML_STATUS_ERROR;
2136 default:
2137 if (resumable) {
2138#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08002139 if (parser->m_isParamEntity) {
2140 parser->m_errorCode = XML_ERROR_SUSPEND_PE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002141 return XML_STATUS_ERROR;
2142 }
2143#endif
Elliott Hughes72472942018-01-10 08:36:10 -08002144 parser->m_parsingStatus.parsing = XML_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002145 }
2146 else
Elliott Hughes72472942018-01-10 08:36:10 -08002147 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002148 }
2149 return XML_STATUS_OK;
2150}
2151
2152enum XML_Status XMLCALL
2153XML_ResumeParser(XML_Parser parser)
2154{
2155 enum XML_Status result = XML_STATUS_OK;
2156
Elliott Hughes72472942018-01-10 08:36:10 -08002157 if (parser == NULL)
2158 return XML_STATUS_ERROR;
2159 if (parser->m_parsingStatus.parsing != XML_SUSPENDED) {
2160 parser->m_errorCode = XML_ERROR_NOT_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002161 return XML_STATUS_ERROR;
2162 }
Elliott Hughes72472942018-01-10 08:36:10 -08002163 parser->m_parsingStatus.parsing = XML_PARSING;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002164
Elliott Hughes72472942018-01-10 08:36:10 -08002165 parser->m_errorCode = parser->m_processor(parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002166
Elliott Hughes72472942018-01-10 08:36:10 -08002167 if (parser->m_errorCode != XML_ERROR_NONE) {
2168 parser->m_eventEndPtr = parser->m_eventPtr;
2169 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002170 return XML_STATUS_ERROR;
2171 }
2172 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002173 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002174 case XML_SUSPENDED:
2175 result = XML_STATUS_SUSPENDED;
2176 break;
Elliott Hughes35e432d2012-09-09 14:23:38 -07002177 case XML_INITIALIZED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002178 case XML_PARSING:
Elliott Hughes72472942018-01-10 08:36:10 -08002179 if (parser->m_parsingStatus.finalBuffer) {
2180 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002181 return result;
2182 }
2183 default: ;
2184 }
2185 }
2186
Elliott Hughes72472942018-01-10 08:36:10 -08002187 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
2188 parser->m_positionPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002189 return result;
2190}
2191
2192void XMLCALL
2193XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
2194{
Elliott Hughes72472942018-01-10 08:36:10 -08002195 if (parser == NULL)
2196 return;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002197 assert(status != NULL);
2198 *status = parser->m_parsingStatus;
2199}
2200
2201enum XML_Error XMLCALL
2202XML_GetErrorCode(XML_Parser parser)
2203{
Elliott Hughes72472942018-01-10 08:36:10 -08002204 if (parser == NULL)
2205 return XML_ERROR_INVALID_ARGUMENT;
2206 return parser->m_errorCode;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002207}
2208
2209XML_Index XMLCALL
2210XML_GetCurrentByteIndex(XML_Parser parser)
2211{
Elliott Hughes72472942018-01-10 08:36:10 -08002212 if (parser == NULL)
2213 return -1;
2214 if (parser->m_eventPtr)
2215 return (XML_Index)(parser->m_parseEndByteIndex - (parser->m_parseEndPtr - parser->m_eventPtr));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002216 return -1;
2217}
2218
2219int XMLCALL
2220XML_GetCurrentByteCount(XML_Parser parser)
2221{
Elliott Hughes72472942018-01-10 08:36:10 -08002222 if (parser == NULL)
2223 return 0;
2224 if (parser->m_eventEndPtr && parser->m_eventPtr)
2225 return (int)(parser->m_eventEndPtr - parser->m_eventPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002226 return 0;
2227}
2228
2229const char * XMLCALL
2230XML_GetInputContext(XML_Parser parser, int *offset, int *size)
2231{
2232#ifdef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08002233 if (parser == NULL)
2234 return NULL;
2235 if (parser->m_eventPtr && parser->m_buffer) {
2236 if (offset != NULL)
2237 *offset = (int)(parser->m_eventPtr - parser->m_buffer);
2238 if (size != NULL)
2239 *size = (int)(parser->m_bufferEnd - parser->m_buffer);
2240 return parser->m_buffer;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002241 }
Elliott Hughes72472942018-01-10 08:36:10 -08002242#else
2243 (void)parser;
2244 (void)offset;
2245 (void)size;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002246#endif /* defined XML_CONTEXT_BYTES */
2247 return (char *) 0;
2248}
2249
2250XML_Size XMLCALL
2251XML_GetCurrentLineNumber(XML_Parser parser)
2252{
Elliott Hughes72472942018-01-10 08:36:10 -08002253 if (parser == NULL)
2254 return 0;
2255 if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2256 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_eventPtr, &parser->m_position);
2257 parser->m_positionPtr = parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002258 }
Elliott Hughes72472942018-01-10 08:36:10 -08002259 return parser->m_position.lineNumber + 1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002260}
2261
2262XML_Size XMLCALL
2263XML_GetCurrentColumnNumber(XML_Parser parser)
2264{
Elliott Hughes72472942018-01-10 08:36:10 -08002265 if (parser == NULL)
2266 return 0;
2267 if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2268 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_eventPtr, &parser->m_position);
2269 parser->m_positionPtr = parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002270 }
Elliott Hughes72472942018-01-10 08:36:10 -08002271 return parser->m_position.columnNumber;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002272}
2273
2274void XMLCALL
2275XML_FreeContentModel(XML_Parser parser, XML_Content *model)
2276{
Elliott Hughes72472942018-01-10 08:36:10 -08002277 if (parser != NULL)
2278 FREE(parser, model);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002279}
2280
2281void * XMLCALL
2282XML_MemMalloc(XML_Parser parser, size_t size)
2283{
Elliott Hughes72472942018-01-10 08:36:10 -08002284 if (parser == NULL)
2285 return NULL;
2286 return MALLOC(parser, size);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002287}
2288
2289void * XMLCALL
2290XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
2291{
Elliott Hughes72472942018-01-10 08:36:10 -08002292 if (parser == NULL)
2293 return NULL;
2294 return REALLOC(parser, ptr, size);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002295}
2296
2297void XMLCALL
2298XML_MemFree(XML_Parser parser, void *ptr)
2299{
Elliott Hughes72472942018-01-10 08:36:10 -08002300 if (parser != NULL)
2301 FREE(parser, ptr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002302}
2303
2304void XMLCALL
2305XML_DefaultCurrent(XML_Parser parser)
2306{
Elliott Hughes72472942018-01-10 08:36:10 -08002307 if (parser == NULL)
2308 return;
2309 if (parser->m_defaultHandler) {
2310 if (parser->m_openInternalEntities)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002311 reportDefault(parser,
Elliott Hughes72472942018-01-10 08:36:10 -08002312 parser->m_internalEncoding,
2313 parser->m_openInternalEntities->internalEventPtr,
2314 parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002315 else
Elliott Hughes72472942018-01-10 08:36:10 -08002316 reportDefault(parser, parser->m_encoding, parser->m_eventPtr, parser->m_eventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002317 }
2318}
2319
2320const XML_LChar * XMLCALL
2321XML_ErrorString(enum XML_Error code)
2322{
Elliott Hughes72472942018-01-10 08:36:10 -08002323 switch (code) {
2324 case XML_ERROR_NONE:
2325 return NULL;
2326 case XML_ERROR_NO_MEMORY:
2327 return XML_L("out of memory");
2328 case XML_ERROR_SYNTAX:
2329 return XML_L("syntax error");
2330 case XML_ERROR_NO_ELEMENTS:
2331 return XML_L("no element found");
2332 case XML_ERROR_INVALID_TOKEN:
2333 return XML_L("not well-formed (invalid token)");
2334 case XML_ERROR_UNCLOSED_TOKEN:
2335 return XML_L("unclosed token");
2336 case XML_ERROR_PARTIAL_CHAR:
2337 return XML_L("partial character");
2338 case XML_ERROR_TAG_MISMATCH:
2339 return XML_L("mismatched tag");
2340 case XML_ERROR_DUPLICATE_ATTRIBUTE:
2341 return XML_L("duplicate attribute");
2342 case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
2343 return XML_L("junk after document element");
2344 case XML_ERROR_PARAM_ENTITY_REF:
2345 return XML_L("illegal parameter entity reference");
2346 case XML_ERROR_UNDEFINED_ENTITY:
2347 return XML_L("undefined entity");
2348 case XML_ERROR_RECURSIVE_ENTITY_REF:
2349 return XML_L("recursive entity reference");
2350 case XML_ERROR_ASYNC_ENTITY:
2351 return XML_L("asynchronous entity");
2352 case XML_ERROR_BAD_CHAR_REF:
2353 return XML_L("reference to invalid character number");
2354 case XML_ERROR_BINARY_ENTITY_REF:
2355 return XML_L("reference to binary entity");
2356 case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
2357 return XML_L("reference to external entity in attribute");
2358 case XML_ERROR_MISPLACED_XML_PI:
2359 return XML_L("XML or text declaration not at start of entity");
2360 case XML_ERROR_UNKNOWN_ENCODING:
2361 return XML_L("unknown encoding");
2362 case XML_ERROR_INCORRECT_ENCODING:
2363 return XML_L("encoding specified in XML declaration is incorrect");
2364 case XML_ERROR_UNCLOSED_CDATA_SECTION:
2365 return XML_L("unclosed CDATA section");
2366 case XML_ERROR_EXTERNAL_ENTITY_HANDLING:
2367 return XML_L("error in processing external entity reference");
2368 case XML_ERROR_NOT_STANDALONE:
2369 return XML_L("document is not standalone");
2370 case XML_ERROR_UNEXPECTED_STATE:
2371 return XML_L("unexpected parser state - please send a bug report");
2372 case XML_ERROR_ENTITY_DECLARED_IN_PE:
2373 return XML_L("entity declared in parameter entity");
2374 case XML_ERROR_FEATURE_REQUIRES_XML_DTD:
2375 return XML_L("requested feature requires XML_DTD support in Expat");
2376 case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:
2377 return XML_L("cannot change setting once parsing has begun");
2378 /* Added in 1.95.7. */
2379 case XML_ERROR_UNBOUND_PREFIX:
2380 return XML_L("unbound prefix");
2381 /* Added in 1.95.8. */
2382 case XML_ERROR_UNDECLARING_PREFIX:
2383 return XML_L("must not undeclare prefix");
2384 case XML_ERROR_INCOMPLETE_PE:
2385 return XML_L("incomplete markup in parameter entity");
2386 case XML_ERROR_XML_DECL:
2387 return XML_L("XML declaration not well-formed");
2388 case XML_ERROR_TEXT_DECL:
2389 return XML_L("text declaration not well-formed");
2390 case XML_ERROR_PUBLICID:
2391 return XML_L("illegal character(s) in public id");
2392 case XML_ERROR_SUSPENDED:
2393 return XML_L("parser suspended");
2394 case XML_ERROR_NOT_SUSPENDED:
2395 return XML_L("parser not suspended");
2396 case XML_ERROR_ABORTED:
2397 return XML_L("parsing aborted");
2398 case XML_ERROR_FINISHED:
2399 return XML_L("parsing finished");
2400 case XML_ERROR_SUSPEND_PE:
2401 return XML_L("cannot suspend in external parameter entity");
2402 /* Added in 2.0.0. */
2403 case XML_ERROR_RESERVED_PREFIX_XML:
2404 return XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name");
2405 case XML_ERROR_RESERVED_PREFIX_XMLNS:
2406 return XML_L("reserved prefix (xmlns) must not be declared or undeclared");
2407 case XML_ERROR_RESERVED_NAMESPACE_URI:
2408 return XML_L("prefix must not be bound to one of the reserved namespace names");
2409 /* Added in 2.2.5. */
2410 case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
2411 return XML_L("invalid argument");
2412 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002413 return NULL;
2414}
2415
2416const XML_LChar * XMLCALL
2417XML_ExpatVersion(void) {
2418
2419 /* V1 is used to string-ize the version number. However, it would
2420 string-ize the actual version macro *names* unless we get them
2421 substituted before being passed to V1. CPP is defined to expand
2422 a macro, then rescan for more expansions. Thus, we use V2 to expand
2423 the version macros, then CPP will expand the resulting V1() macro
2424 with the correct numerals. */
2425 /* ### I'm assuming cpp is portable in this respect... */
2426
2427#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
2428#define V2(a,b,c) XML_L("expat_")V1(a,b,c)
2429
2430 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
2431
2432#undef V1
2433#undef V2
2434}
2435
2436XML_Expat_Version XMLCALL
2437XML_ExpatVersionInfo(void)
2438{
2439 XML_Expat_Version version;
2440
2441 version.major = XML_MAJOR_VERSION;
2442 version.minor = XML_MINOR_VERSION;
2443 version.micro = XML_MICRO_VERSION;
2444
2445 return version;
2446}
2447
2448const XML_Feature * XMLCALL
2449XML_GetFeatureList(void)
2450{
2451 static const XML_Feature features[] = {
2452 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2453 sizeof(XML_Char)},
2454 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2455 sizeof(XML_LChar)},
2456#ifdef XML_UNICODE
2457 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2458#endif
2459#ifdef XML_UNICODE_WCHAR_T
2460 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2461#endif
2462#ifdef XML_DTD
2463 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2464#endif
2465#ifdef XML_CONTEXT_BYTES
2466 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2467 XML_CONTEXT_BYTES},
2468#endif
2469#ifdef XML_MIN_SIZE
2470 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2471#endif
2472#ifdef XML_NS
2473 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2474#endif
Elliott Hughesd07d5a72009-09-25 16:04:37 -07002475#ifdef XML_LARGE_SIZE
2476 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
Elliott Hughes35e432d2012-09-09 14:23:38 -07002477#endif
2478#ifdef XML_ATTR_INFO
2479 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2480#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002481 {XML_FEATURE_END, NULL, 0}
2482 };
2483
2484 return features;
2485}
2486
2487/* Initially tag->rawName always points into the parse buffer;
2488 for those TAG instances opened while the current parse buffer was
2489 processed, and not yet closed, we need to store tag->rawName in a more
2490 permanent location, since the parse buffer is about to be discarded.
2491*/
2492static XML_Bool
2493storeRawNames(XML_Parser parser)
2494{
Elliott Hughes72472942018-01-10 08:36:10 -08002495 TAG *tag = parser->m_tagStack;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002496 while (tag) {
2497 int bufSize;
2498 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2499 char *rawNameBuf = tag->buf + nameLen;
Elliott Hughes72472942018-01-10 08:36:10 -08002500 /* Stop if already stored. Since m_tagStack is a stack, we can stop
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002501 at the first entry that has already been copied; everything
2502 below it in the stack is already been accounted for in a
2503 previous call to this function.
2504 */
2505 if (tag->rawName == rawNameBuf)
2506 break;
2507 /* For re-use purposes we need to ensure that the
2508 size of tag->buf is a multiple of sizeof(XML_Char).
2509 */
2510 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2511 if (bufSize > tag->bufEnd - tag->buf) {
Elliott Hughes72472942018-01-10 08:36:10 -08002512 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002513 if (temp == NULL)
2514 return XML_FALSE;
2515 /* if tag->name.str points to tag->buf (only when namespace
2516 processing is off) then we have to update it
2517 */
2518 if (tag->name.str == (XML_Char *)tag->buf)
2519 tag->name.str = (XML_Char *)temp;
2520 /* if tag->name.localPart is set (when namespace processing is on)
2521 then update it as well, since it will always point into tag->buf
2522 */
2523 if (tag->name.localPart)
2524 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2525 (XML_Char *)tag->buf);
2526 tag->buf = temp;
2527 tag->bufEnd = temp + bufSize;
2528 rawNameBuf = temp + nameLen;
2529 }
2530 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2531 tag->rawName = rawNameBuf;
2532 tag = tag->parent;
2533 }
2534 return XML_TRUE;
2535}
2536
2537static enum XML_Error PTRCALL
2538contentProcessor(XML_Parser parser,
2539 const char *start,
2540 const char *end,
2541 const char **endPtr)
2542{
Elliott Hughes72472942018-01-10 08:36:10 -08002543 enum XML_Error result = doContent(parser, 0, parser->m_encoding, start, end,
2544 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002545 if (result == XML_ERROR_NONE) {
2546 if (!storeRawNames(parser))
2547 return XML_ERROR_NO_MEMORY;
2548 }
2549 return result;
2550}
2551
2552static enum XML_Error PTRCALL
2553externalEntityInitProcessor(XML_Parser parser,
2554 const char *start,
2555 const char *end,
2556 const char **endPtr)
2557{
2558 enum XML_Error result = initializeEncoding(parser);
2559 if (result != XML_ERROR_NONE)
2560 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002561 parser->m_processor = externalEntityInitProcessor2;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002562 return externalEntityInitProcessor2(parser, start, end, endPtr);
2563}
2564
2565static enum XML_Error PTRCALL
2566externalEntityInitProcessor2(XML_Parser parser,
2567 const char *start,
2568 const char *end,
2569 const char **endPtr)
2570{
2571 const char *next = start; /* XmlContentTok doesn't always set the last arg */
Elliott Hughes72472942018-01-10 08:36:10 -08002572 int tok = XmlContentTok(parser->m_encoding, start, end, &next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002573 switch (tok) {
2574 case XML_TOK_BOM:
2575 /* If we are at the end of the buffer, this would cause the next stage,
2576 i.e. externalEntityInitProcessor3, to pass control directly to
2577 doContent (by detecting XML_TOK_NONE) without processing any xml text
2578 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2579 */
Elliott Hughes72472942018-01-10 08:36:10 -08002580 if (next == end && !parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002581 *endPtr = next;
2582 return XML_ERROR_NONE;
2583 }
2584 start = next;
2585 break;
2586 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08002587 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002588 *endPtr = start;
2589 return XML_ERROR_NONE;
2590 }
Elliott Hughes72472942018-01-10 08:36:10 -08002591 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002592 return XML_ERROR_UNCLOSED_TOKEN;
2593 case XML_TOK_PARTIAL_CHAR:
Elliott Hughes72472942018-01-10 08:36:10 -08002594 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002595 *endPtr = start;
2596 return XML_ERROR_NONE;
2597 }
Elliott Hughes72472942018-01-10 08:36:10 -08002598 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002599 return XML_ERROR_PARTIAL_CHAR;
2600 }
Elliott Hughes72472942018-01-10 08:36:10 -08002601 parser->m_processor = externalEntityInitProcessor3;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002602 return externalEntityInitProcessor3(parser, start, end, endPtr);
2603}
2604
2605static enum XML_Error PTRCALL
2606externalEntityInitProcessor3(XML_Parser parser,
2607 const char *start,
2608 const char *end,
2609 const char **endPtr)
2610{
2611 int tok;
2612 const char *next = start; /* XmlContentTok doesn't always set the last arg */
Elliott Hughes72472942018-01-10 08:36:10 -08002613 parser->m_eventPtr = start;
2614 tok = XmlContentTok(parser->m_encoding, start, end, &next);
2615 parser->m_eventEndPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002616
2617 switch (tok) {
2618 case XML_TOK_XML_DECL:
2619 {
2620 enum XML_Error result;
2621 result = processXmlDecl(parser, 1, start, next);
2622 if (result != XML_ERROR_NONE)
2623 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002624 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07002625 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002626 *endPtr = next;
2627 return XML_ERROR_NONE;
2628 case XML_FINISHED:
2629 return XML_ERROR_ABORTED;
2630 default:
2631 start = next;
2632 }
2633 }
2634 break;
2635 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08002636 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002637 *endPtr = start;
2638 return XML_ERROR_NONE;
2639 }
2640 return XML_ERROR_UNCLOSED_TOKEN;
2641 case XML_TOK_PARTIAL_CHAR:
Elliott Hughes72472942018-01-10 08:36:10 -08002642 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002643 *endPtr = start;
2644 return XML_ERROR_NONE;
2645 }
2646 return XML_ERROR_PARTIAL_CHAR;
2647 }
Elliott Hughes72472942018-01-10 08:36:10 -08002648 parser->m_processor = externalEntityContentProcessor;
2649 parser->m_tagLevel = 1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002650 return externalEntityContentProcessor(parser, start, end, endPtr);
2651}
2652
2653static enum XML_Error PTRCALL
2654externalEntityContentProcessor(XML_Parser parser,
2655 const char *start,
2656 const char *end,
2657 const char **endPtr)
2658{
Elliott Hughes72472942018-01-10 08:36:10 -08002659 enum XML_Error result = doContent(parser, 1, parser->m_encoding, start, end,
2660 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002661 if (result == XML_ERROR_NONE) {
2662 if (!storeRawNames(parser))
2663 return XML_ERROR_NO_MEMORY;
2664 }
2665 return result;
2666}
2667
2668static enum XML_Error
2669doContent(XML_Parser parser,
2670 int startTagLevel,
2671 const ENCODING *enc,
2672 const char *s,
2673 const char *end,
2674 const char **nextPtr,
2675 XML_Bool haveMore)
2676{
2677 /* save one level of indirection */
Elliott Hughes72472942018-01-10 08:36:10 -08002678 DTD * const dtd = parser->m_dtd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002679
2680 const char **eventPP;
2681 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08002682 if (enc == parser->m_encoding) {
2683 eventPP = &parser->m_eventPtr;
2684 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002685 }
2686 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002687 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
2688 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002689 }
2690 *eventPP = s;
2691
2692 for (;;) {
2693 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2694 int tok = XmlContentTok(enc, s, end, &next);
2695 *eventEndPP = next;
2696 switch (tok) {
2697 case XML_TOK_TRAILING_CR:
2698 if (haveMore) {
2699 *nextPtr = s;
2700 return XML_ERROR_NONE;
2701 }
2702 *eventEndPP = end;
Elliott Hughes72472942018-01-10 08:36:10 -08002703 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002704 XML_Char c = 0xA;
Elliott Hughes72472942018-01-10 08:36:10 -08002705 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002706 }
Elliott Hughes72472942018-01-10 08:36:10 -08002707 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002708 reportDefault(parser, enc, s, end);
Elliott Hughes35e432d2012-09-09 14:23:38 -07002709 /* We are at the end of the final buffer, should we check for
2710 XML_SUSPENDED, XML_FINISHED?
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002711 */
2712 if (startTagLevel == 0)
2713 return XML_ERROR_NO_ELEMENTS;
Elliott Hughes72472942018-01-10 08:36:10 -08002714 if (parser->m_tagLevel != startTagLevel)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002715 return XML_ERROR_ASYNC_ENTITY;
2716 *nextPtr = end;
2717 return XML_ERROR_NONE;
2718 case XML_TOK_NONE:
2719 if (haveMore) {
2720 *nextPtr = s;
2721 return XML_ERROR_NONE;
2722 }
2723 if (startTagLevel > 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002724 if (parser->m_tagLevel != startTagLevel)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002725 return XML_ERROR_ASYNC_ENTITY;
2726 *nextPtr = s;
2727 return XML_ERROR_NONE;
2728 }
2729 return XML_ERROR_NO_ELEMENTS;
2730 case XML_TOK_INVALID:
2731 *eventPP = next;
2732 return XML_ERROR_INVALID_TOKEN;
2733 case XML_TOK_PARTIAL:
2734 if (haveMore) {
2735 *nextPtr = s;
2736 return XML_ERROR_NONE;
2737 }
2738 return XML_ERROR_UNCLOSED_TOKEN;
2739 case XML_TOK_PARTIAL_CHAR:
2740 if (haveMore) {
2741 *nextPtr = s;
2742 return XML_ERROR_NONE;
2743 }
2744 return XML_ERROR_PARTIAL_CHAR;
2745 case XML_TOK_ENTITY_REF:
2746 {
2747 const XML_Char *name;
2748 ENTITY *entity;
2749 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2750 s + enc->minBytesPerChar,
2751 next - enc->minBytesPerChar);
2752 if (ch) {
Elliott Hughes72472942018-01-10 08:36:10 -08002753 if (parser->m_characterDataHandler)
2754 parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
2755 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002756 reportDefault(parser, enc, s, next);
2757 break;
2758 }
2759 name = poolStoreString(&dtd->pool, enc,
2760 s + enc->minBytesPerChar,
2761 next - enc->minBytesPerChar);
2762 if (!name)
2763 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07002764 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002765 poolDiscard(&dtd->pool);
2766 /* First, determine if a check for an existing declaration is needed;
2767 if yes, check that the entity exists, and that it is internal,
2768 otherwise call the skipped entity or default handler.
2769 */
2770 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2771 if (!entity)
2772 return XML_ERROR_UNDEFINED_ENTITY;
2773 else if (!entity->is_internal)
2774 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2775 }
2776 else if (!entity) {
Elliott Hughes72472942018-01-10 08:36:10 -08002777 if (parser->m_skippedEntityHandler)
2778 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
2779 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002780 reportDefault(parser, enc, s, next);
2781 break;
2782 }
2783 if (entity->open)
2784 return XML_ERROR_RECURSIVE_ENTITY_REF;
2785 if (entity->notation)
2786 return XML_ERROR_BINARY_ENTITY_REF;
2787 if (entity->textPtr) {
2788 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08002789 if (!parser->m_defaultExpandInternalEntities) {
2790 if (parser->m_skippedEntityHandler)
2791 parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name, 0);
2792 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002793 reportDefault(parser, enc, s, next);
2794 break;
2795 }
2796 result = processInternalEntity(parser, entity, XML_FALSE);
2797 if (result != XML_ERROR_NONE)
2798 return result;
2799 }
Elliott Hughes72472942018-01-10 08:36:10 -08002800 else if (parser->m_externalEntityRefHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002801 const XML_Char *context;
2802 entity->open = XML_TRUE;
2803 context = getContext(parser);
2804 entity->open = XML_FALSE;
2805 if (!context)
2806 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08002807 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002808 context,
2809 entity->base,
2810 entity->systemId,
2811 entity->publicId))
2812 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
Elliott Hughes72472942018-01-10 08:36:10 -08002813 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002814 }
Elliott Hughes72472942018-01-10 08:36:10 -08002815 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002816 reportDefault(parser, enc, s, next);
2817 break;
2818 }
2819 case XML_TOK_START_TAG_NO_ATTS:
2820 /* fall through */
2821 case XML_TOK_START_TAG_WITH_ATTS:
2822 {
2823 TAG *tag;
2824 enum XML_Error result;
2825 XML_Char *toPtr;
Elliott Hughes72472942018-01-10 08:36:10 -08002826 if (parser->m_freeTagList) {
2827 tag = parser->m_freeTagList;
2828 parser->m_freeTagList = parser->m_freeTagList->parent;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002829 }
2830 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002831 tag = (TAG *)MALLOC(parser, sizeof(TAG));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002832 if (!tag)
2833 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08002834 tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002835 if (!tag->buf) {
Elliott Hughes72472942018-01-10 08:36:10 -08002836 FREE(parser, tag);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002837 return XML_ERROR_NO_MEMORY;
2838 }
2839 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2840 }
2841 tag->bindings = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08002842 tag->parent = parser->m_tagStack;
2843 parser->m_tagStack = tag;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002844 tag->name.localPart = NULL;
2845 tag->name.prefix = NULL;
2846 tag->rawName = s + enc->minBytesPerChar;
2847 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
Elliott Hughes72472942018-01-10 08:36:10 -08002848 ++parser->m_tagLevel;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002849 {
2850 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2851 const char *fromPtr = tag->rawName;
2852 toPtr = (XML_Char *)tag->buf;
2853 for (;;) {
2854 int bufSize;
2855 int convLen;
Paul Duffin4bf8f122016-05-13 12:35:25 +01002856 const enum XML_Convert_Result convert_res = XmlConvert(enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002857 &fromPtr, rawNameEnd,
2858 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2859 convLen = (int)(toPtr - (XML_Char *)tag->buf);
Elliott Hughes72472942018-01-10 08:36:10 -08002860 if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002861 tag->name.strLen = convLen;
2862 break;
2863 }
2864 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2865 {
Elliott Hughes72472942018-01-10 08:36:10 -08002866 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002867 if (temp == NULL)
2868 return XML_ERROR_NO_MEMORY;
2869 tag->buf = temp;
2870 tag->bufEnd = temp + bufSize;
2871 toPtr = (XML_Char *)temp + convLen;
2872 }
2873 }
2874 }
2875 tag->name.str = (XML_Char *)tag->buf;
2876 *toPtr = XML_T('\0');
2877 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2878 if (result)
2879 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002880 if (parser->m_startElementHandler)
2881 parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
2882 (const XML_Char **)parser->m_atts);
2883 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002884 reportDefault(parser, enc, s, next);
Elliott Hughes72472942018-01-10 08:36:10 -08002885 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002886 break;
2887 }
2888 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2889 /* fall through */
2890 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2891 {
2892 const char *rawName = s + enc->minBytesPerChar;
2893 enum XML_Error result;
2894 BINDING *bindings = NULL;
2895 XML_Bool noElmHandlers = XML_TRUE;
2896 TAG_NAME name;
Elliott Hughes72472942018-01-10 08:36:10 -08002897 name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002898 rawName + XmlNameLength(enc, rawName));
2899 if (!name.str)
2900 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08002901 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002902 result = storeAtts(parser, enc, s, &name, &bindings);
Elliott Hughes72472942018-01-10 08:36:10 -08002903 if (result != XML_ERROR_NONE) {
2904 freeBindings(parser, bindings);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002905 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002906 }
2907 poolFinish(&parser->m_tempPool);
2908 if (parser->m_startElementHandler) {
2909 parser->m_startElementHandler(parser->m_handlerArg, name.str, (const XML_Char **)parser->m_atts);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002910 noElmHandlers = XML_FALSE;
2911 }
Elliott Hughes72472942018-01-10 08:36:10 -08002912 if (parser->m_endElementHandler) {
2913 if (parser->m_startElementHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002914 *eventPP = *eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08002915 parser->m_endElementHandler(parser->m_handlerArg, name.str);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002916 noElmHandlers = XML_FALSE;
2917 }
Elliott Hughes72472942018-01-10 08:36:10 -08002918 if (noElmHandlers && parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002919 reportDefault(parser, enc, s, next);
Elliott Hughes72472942018-01-10 08:36:10 -08002920 poolClear(&parser->m_tempPool);
2921 freeBindings(parser, bindings);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002922 }
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002923 if ((parser->m_tagLevel == 0) && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
2924 if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
2925 parser->m_processor = epilogProcessor;
2926 else
2927 return epilogProcessor(parser, next, end, nextPtr);
Elliott Hughes72472942018-01-10 08:36:10 -08002928 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002929 break;
2930 case XML_TOK_END_TAG:
Elliott Hughes72472942018-01-10 08:36:10 -08002931 if (parser->m_tagLevel == startTagLevel)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002932 return XML_ERROR_ASYNC_ENTITY;
2933 else {
2934 int len;
2935 const char *rawName;
Elliott Hughes72472942018-01-10 08:36:10 -08002936 TAG *tag = parser->m_tagStack;
2937 parser->m_tagStack = tag->parent;
2938 tag->parent = parser->m_freeTagList;
2939 parser->m_freeTagList = tag;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002940 rawName = s + enc->minBytesPerChar*2;
2941 len = XmlNameLength(enc, rawName);
2942 if (len != tag->rawNameLength
2943 || memcmp(tag->rawName, rawName, len) != 0) {
2944 *eventPP = rawName;
2945 return XML_ERROR_TAG_MISMATCH;
2946 }
Elliott Hughes72472942018-01-10 08:36:10 -08002947 --parser->m_tagLevel;
2948 if (parser->m_endElementHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002949 const XML_Char *localPart;
2950 const XML_Char *prefix;
2951 XML_Char *uri;
2952 localPart = tag->name.localPart;
Elliott Hughes72472942018-01-10 08:36:10 -08002953 if (parser->m_ns && localPart) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002954 /* localPart and prefix may have been overwritten in
2955 tag->name.str, since this points to the binding->uri
2956 buffer which gets re-used; so we have to add them again
2957 */
2958 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2959 /* don't need to check for space - already done in storeAtts() */
2960 while (*localPart) *uri++ = *localPart++;
2961 prefix = (XML_Char *)tag->name.prefix;
Elliott Hughes72472942018-01-10 08:36:10 -08002962 if (parser->m_ns_triplets && prefix) {
2963 *uri++ = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002964 while (*prefix) *uri++ = *prefix++;
2965 }
2966 *uri = XML_T('\0');
2967 }
Elliott Hughes72472942018-01-10 08:36:10 -08002968 parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002969 }
Elliott Hughes72472942018-01-10 08:36:10 -08002970 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002971 reportDefault(parser, enc, s, next);
2972 while (tag->bindings) {
2973 BINDING *b = tag->bindings;
Elliott Hughes72472942018-01-10 08:36:10 -08002974 if (parser->m_endNamespaceDeclHandler)
2975 parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002976 tag->bindings = tag->bindings->nextTagBinding;
Elliott Hughes72472942018-01-10 08:36:10 -08002977 b->nextTagBinding = parser->m_freeBindingList;
2978 parser->m_freeBindingList = b;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002979 b->prefix->binding = b->prevPrefixBinding;
2980 }
Elliott Hughes72472942018-01-10 08:36:10 -08002981 if (parser->m_tagLevel == 0)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002982 return epilogProcessor(parser, next, end, nextPtr);
2983 }
2984 break;
2985 case XML_TOK_CHAR_REF:
2986 {
2987 int n = XmlCharRefNumber(enc, s);
2988 if (n < 0)
2989 return XML_ERROR_BAD_CHAR_REF;
Elliott Hughes72472942018-01-10 08:36:10 -08002990 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002991 XML_Char buf[XML_ENCODE_MAX];
Elliott Hughes72472942018-01-10 08:36:10 -08002992 parser->m_characterDataHandler(parser->m_handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002993 }
Elliott Hughes72472942018-01-10 08:36:10 -08002994 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002995 reportDefault(parser, enc, s, next);
2996 }
2997 break;
2998 case XML_TOK_XML_DECL:
2999 return XML_ERROR_MISPLACED_XML_PI;
3000 case XML_TOK_DATA_NEWLINE:
Elliott Hughes72472942018-01-10 08:36:10 -08003001 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003002 XML_Char c = 0xA;
Elliott Hughes72472942018-01-10 08:36:10 -08003003 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003004 }
Elliott Hughes72472942018-01-10 08:36:10 -08003005 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003006 reportDefault(parser, enc, s, next);
3007 break;
3008 case XML_TOK_CDATA_SECT_OPEN:
3009 {
3010 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08003011 if (parser->m_startCdataSectionHandler)
3012 parser->m_startCdataSectionHandler(parser->m_handlerArg);
Haibo Huangfd5e81a2019-06-20 12:09:36 -07003013/* BEGIN disabled code */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003014 /* Suppose you doing a transformation on a document that involves
3015 changing only the character data. You set up a defaultHandler
3016 and a characterDataHandler. The defaultHandler simply copies
3017 characters through. The characterDataHandler does the
3018 transformation and writes the characters out escaping them as
3019 necessary. This case will fail to work if we leave out the
3020 following two lines (because & and < inside CDATA sections will
3021 be incorrectly escaped).
3022
3023 However, now we have a start/endCdataSectionHandler, so it seems
3024 easier to let the user deal with this.
3025 */
Haibo Huangfd5e81a2019-06-20 12:09:36 -07003026 else if (0 && parser->m_characterDataHandler)
Elliott Hughes72472942018-01-10 08:36:10 -08003027 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0);
Haibo Huangfd5e81a2019-06-20 12:09:36 -07003028/* END disabled code */
Elliott Hughes72472942018-01-10 08:36:10 -08003029 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003030 reportDefault(parser, enc, s, next);
3031 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
3032 if (result != XML_ERROR_NONE)
3033 return result;
3034 else if (!next) {
Elliott Hughes72472942018-01-10 08:36:10 -08003035 parser->m_processor = cdataSectionProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003036 return result;
3037 }
3038 }
3039 break;
3040 case XML_TOK_TRAILING_RSQB:
3041 if (haveMore) {
3042 *nextPtr = s;
3043 return XML_ERROR_NONE;
3044 }
Elliott Hughes72472942018-01-10 08:36:10 -08003045 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003046 if (MUST_CONVERT(enc, s)) {
Elliott Hughes72472942018-01-10 08:36:10 -08003047 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3048 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3049 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3050 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003051 }
3052 else
Elliott Hughes72472942018-01-10 08:36:10 -08003053 parser->m_characterDataHandler(parser->m_handlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003054 (XML_Char *)s,
3055 (int)((XML_Char *)end - (XML_Char *)s));
3056 }
Elliott Hughes72472942018-01-10 08:36:10 -08003057 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003058 reportDefault(parser, enc, s, end);
Elliott Hughes35e432d2012-09-09 14:23:38 -07003059 /* We are at the end of the final buffer, should we check for
3060 XML_SUSPENDED, XML_FINISHED?
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003061 */
3062 if (startTagLevel == 0) {
3063 *eventPP = end;
3064 return XML_ERROR_NO_ELEMENTS;
3065 }
Elliott Hughes72472942018-01-10 08:36:10 -08003066 if (parser->m_tagLevel != startTagLevel) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003067 *eventPP = end;
3068 return XML_ERROR_ASYNC_ENTITY;
3069 }
3070 *nextPtr = end;
3071 return XML_ERROR_NONE;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003072 case XML_TOK_DATA_CHARS:
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003073 {
Elliott Hughes72472942018-01-10 08:36:10 -08003074 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003075 if (charDataHandler) {
3076 if (MUST_CONVERT(enc, s)) {
3077 for (;;) {
Elliott Hughes72472942018-01-10 08:36:10 -08003078 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3079 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003080 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08003081 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3082 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
Paul Duffin4bf8f122016-05-13 12:35:25 +01003083 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003084 break;
3085 *eventPP = s;
3086 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003087 }
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003088 else
Elliott Hughes72472942018-01-10 08:36:10 -08003089 charDataHandler(parser->m_handlerArg,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003090 (XML_Char *)s,
3091 (int)((XML_Char *)next - (XML_Char *)s));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003092 }
Elliott Hughes72472942018-01-10 08:36:10 -08003093 else if (parser->m_defaultHandler)
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003094 reportDefault(parser, enc, s, next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003095 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003096 break;
3097 case XML_TOK_PI:
3098 if (!reportProcessingInstruction(parser, enc, s, next))
3099 return XML_ERROR_NO_MEMORY;
3100 break;
3101 case XML_TOK_COMMENT:
3102 if (!reportComment(parser, enc, s, next))
3103 return XML_ERROR_NO_MEMORY;
3104 break;
3105 default:
Elliott Hughes72472942018-01-10 08:36:10 -08003106 /* All of the tokens produced by XmlContentTok() have their own
3107 * explicit cases, so this default is not strictly necessary.
3108 * However it is a useful safety net, so we retain the code and
3109 * simply exclude it from the coverage tests.
3110 *
3111 * LCOV_EXCL_START
3112 */
3113 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003114 reportDefault(parser, enc, s, next);
3115 break;
Elliott Hughes72472942018-01-10 08:36:10 -08003116 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003117 }
3118 *eventPP = s = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003119 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07003120 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003121 *nextPtr = next;
3122 return XML_ERROR_NONE;
3123 case XML_FINISHED:
3124 return XML_ERROR_ABORTED;
3125 default: ;
3126 }
3127 }
3128 /* not reached */
3129}
3130
Elliott Hughes72472942018-01-10 08:36:10 -08003131/* This function does not call free() on the allocated memory, merely
3132 * moving it to the parser's m_freeBindingList where it can be freed or
3133 * reused as appropriate.
3134 */
3135static void
3136freeBindings(XML_Parser parser, BINDING *bindings)
3137{
3138 while (bindings) {
3139 BINDING *b = bindings;
3140
3141 /* m_startNamespaceDeclHandler will have been called for this
3142 * binding in addBindings(), so call the end handler now.
3143 */
3144 if (parser->m_endNamespaceDeclHandler)
3145 parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
3146
3147 bindings = bindings->nextTagBinding;
3148 b->nextTagBinding = parser->m_freeBindingList;
3149 parser->m_freeBindingList = b;
3150 b->prefix->binding = b->prevPrefixBinding;
3151 }
3152}
3153
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003154/* Precondition: all arguments must be non-NULL;
3155 Purpose:
3156 - normalize attributes
3157 - check attributes for well-formedness
3158 - generate namespace aware attribute names (URI, prefix)
3159 - build list of attributes for startElementHandler
3160 - default attributes
3161 - process namespace declarations (check and report them)
3162 - generate namespace aware element name (URI, prefix)
3163*/
3164static enum XML_Error
3165storeAtts(XML_Parser parser, const ENCODING *enc,
3166 const char *attStr, TAG_NAME *tagNamePtr,
3167 BINDING **bindingsPtr)
3168{
Elliott Hughes72472942018-01-10 08:36:10 -08003169 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003170 ELEMENT_TYPE *elementType;
3171 int nDefaultAtts;
3172 const XML_Char **appAtts; /* the attribute list for the application */
3173 int attIndex = 0;
3174 int prefixLen;
3175 int i;
3176 int n;
3177 XML_Char *uri;
3178 int nPrefixes = 0;
3179 BINDING *binding;
3180 const XML_Char *localPart;
3181
3182 /* lookup the element type name */
Elliott Hughes35e432d2012-09-09 14:23:38 -07003183 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003184 if (!elementType) {
3185 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
3186 if (!name)
3187 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003188 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003189 sizeof(ELEMENT_TYPE));
3190 if (!elementType)
3191 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003192 if (parser->m_ns && !setElementTypePrefix(parser, elementType))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003193 return XML_ERROR_NO_MEMORY;
3194 }
3195 nDefaultAtts = elementType->nDefaultAtts;
3196
3197 /* get the attributes from the tokenizer */
Elliott Hughes72472942018-01-10 08:36:10 -08003198 n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
3199 if (n + nDefaultAtts > parser->m_attsSize) {
3200 int oldAttsSize = parser->m_attsSize;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003201 ATTRIBUTE *temp;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003202#ifdef XML_ATTR_INFO
3203 XML_AttrInfo *temp2;
3204#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003205 parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
3206 temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, parser->m_attsSize * sizeof(ATTRIBUTE));
3207 if (temp == NULL) {
3208 parser->m_attsSize = oldAttsSize;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003209 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003210 }
3211 parser->m_atts = temp;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003212#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08003213 temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, parser->m_attsSize * sizeof(XML_AttrInfo));
3214 if (temp2 == NULL) {
3215 parser->m_attsSize = oldAttsSize;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003216 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003217 }
3218 parser->m_attInfo = temp2;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003219#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003220 if (n > oldAttsSize)
Elliott Hughes72472942018-01-10 08:36:10 -08003221 XmlGetAttributes(enc, attStr, n, parser->m_atts);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003222 }
3223
Elliott Hughes72472942018-01-10 08:36:10 -08003224 appAtts = (const XML_Char **)parser->m_atts;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003225 for (i = 0; i < n; i++) {
Elliott Hughes72472942018-01-10 08:36:10 -08003226 ATTRIBUTE *currAtt = &parser->m_atts[i];
Elliott Hughes35e432d2012-09-09 14:23:38 -07003227#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08003228 XML_AttrInfo *currAttInfo = &parser->m_attInfo[i];
Elliott Hughes35e432d2012-09-09 14:23:38 -07003229#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003230 /* add the name and value to the attribute list */
Elliott Hughes35e432d2012-09-09 14:23:38 -07003231 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
3232 currAtt->name
3233 + XmlNameLength(enc, currAtt->name));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003234 if (!attId)
3235 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003236#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08003237 currAttInfo->nameStart = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name);
Elliott Hughes35e432d2012-09-09 14:23:38 -07003238 currAttInfo->nameEnd = currAttInfo->nameStart +
3239 XmlNameLength(enc, currAtt->name);
Elliott Hughes72472942018-01-10 08:36:10 -08003240 currAttInfo->valueStart = parser->m_parseEndByteIndex -
3241 (parser->m_parseEndPtr - currAtt->valuePtr);
3242 currAttInfo->valueEnd = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->valueEnd);
Elliott Hughes35e432d2012-09-09 14:23:38 -07003243#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003244 /* Detect duplicate attributes by their QNames. This does not work when
3245 namespace processing is turned on and different prefixes for the same
3246 namespace are used. For this case we have a check further down.
3247 */
3248 if ((attId->name)[-1]) {
Elliott Hughes72472942018-01-10 08:36:10 -08003249 if (enc == parser->m_encoding)
3250 parser->m_eventPtr = parser->m_atts[i].name;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003251 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3252 }
3253 (attId->name)[-1] = 1;
3254 appAtts[attIndex++] = attId->name;
Elliott Hughes72472942018-01-10 08:36:10 -08003255 if (!parser->m_atts[i].normalized) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003256 enum XML_Error result;
3257 XML_Bool isCdata = XML_TRUE;
3258
3259 /* figure out whether declared as other than CDATA */
3260 if (attId->maybeTokenized) {
3261 int j;
3262 for (j = 0; j < nDefaultAtts; j++) {
3263 if (attId == elementType->defaultAtts[j].id) {
3264 isCdata = elementType->defaultAtts[j].isCdata;
3265 break;
3266 }
3267 }
3268 }
3269
3270 /* normalize the attribute value */
3271 result = storeAttributeValue(parser, enc, isCdata,
Elliott Hughes72472942018-01-10 08:36:10 -08003272 parser->m_atts[i].valuePtr, parser->m_atts[i].valueEnd,
3273 &parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003274 if (result)
3275 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08003276 appAtts[attIndex] = poolStart(&parser->m_tempPool);
3277 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003278 }
3279 else {
3280 /* the value did not need normalizing */
Elliott Hughes72472942018-01-10 08:36:10 -08003281 appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc, parser->m_atts[i].valuePtr,
3282 parser->m_atts[i].valueEnd);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003283 if (appAtts[attIndex] == 0)
3284 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003285 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003286 }
3287 /* handle prefixed attribute names */
3288 if (attId->prefix) {
3289 if (attId->xmlns) {
3290 /* deal with namespace declarations here */
3291 enum XML_Error result = addBinding(parser, attId->prefix, attId,
3292 appAtts[attIndex], bindingsPtr);
3293 if (result)
3294 return result;
3295 --attIndex;
3296 }
3297 else {
3298 /* deal with other prefixed names later */
3299 attIndex++;
3300 nPrefixes++;
3301 (attId->name)[-1] = 2;
3302 }
3303 }
3304 else
3305 attIndex++;
3306 }
3307
3308 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
Elliott Hughes72472942018-01-10 08:36:10 -08003309 parser->m_nSpecifiedAtts = attIndex;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003310 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
3311 for (i = 0; i < attIndex; i += 2)
3312 if (appAtts[i] == elementType->idAtt->name) {
Elliott Hughes72472942018-01-10 08:36:10 -08003313 parser->m_idAttIndex = i;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003314 break;
3315 }
3316 }
3317 else
Elliott Hughes72472942018-01-10 08:36:10 -08003318 parser->m_idAttIndex = -1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003319
3320 /* do attribute defaulting */
3321 for (i = 0; i < nDefaultAtts; i++) {
3322 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
3323 if (!(da->id->name)[-1] && da->value) {
3324 if (da->id->prefix) {
3325 if (da->id->xmlns) {
3326 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
3327 da->value, bindingsPtr);
3328 if (result)
3329 return result;
3330 }
3331 else {
3332 (da->id->name)[-1] = 2;
3333 nPrefixes++;
3334 appAtts[attIndex++] = da->id->name;
3335 appAtts[attIndex++] = da->value;
3336 }
3337 }
3338 else {
3339 (da->id->name)[-1] = 1;
3340 appAtts[attIndex++] = da->id->name;
3341 appAtts[attIndex++] = da->value;
3342 }
3343 }
3344 }
3345 appAtts[attIndex] = 0;
3346
3347 /* expand prefixed attribute names, check for duplicates,
3348 and clear flags that say whether attributes were specified */
3349 i = 0;
3350 if (nPrefixes) {
3351 int j; /* hash table index */
Elliott Hughes72472942018-01-10 08:36:10 -08003352 unsigned long version = parser->m_nsAttsVersion;
3353 int nsAttsSize = (int)1 << parser->m_nsAttsPower;
3354 unsigned char oldNsAttsPower = parser->m_nsAttsPower;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003355 /* size of hash table must be at least 2 * (# of prefixed attributes) */
Elliott Hughes72472942018-01-10 08:36:10 -08003356 if ((nPrefixes << 1) >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003357 NS_ATT *temp;
3358 /* hash table size must also be a power of 2 and >= 8 */
Elliott Hughes72472942018-01-10 08:36:10 -08003359 while (nPrefixes >> parser->m_nsAttsPower++);
3360 if (parser->m_nsAttsPower < 3)
3361 parser->m_nsAttsPower = 3;
3362 nsAttsSize = (int)1 << parser->m_nsAttsPower;
3363 temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, nsAttsSize * sizeof(NS_ATT));
3364 if (!temp) {
3365 /* Restore actual size of memory in m_nsAtts */
3366 parser->m_nsAttsPower = oldNsAttsPower;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003367 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003368 }
3369 parser->m_nsAtts = temp;
3370 version = 0; /* force re-initialization of m_nsAtts hash table */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003371 }
Elliott Hughes72472942018-01-10 08:36:10 -08003372 /* using a version flag saves us from initializing m_nsAtts every time */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003373 if (!version) { /* initialize version flags when version wraps around */
3374 version = INIT_ATTS_VERSION;
3375 for (j = nsAttsSize; j != 0; )
Elliott Hughes72472942018-01-10 08:36:10 -08003376 parser->m_nsAtts[--j].version = version;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003377 }
Elliott Hughes72472942018-01-10 08:36:10 -08003378 parser->m_nsAttsVersion = --version;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003379
3380 /* expand prefixed names and check for duplicates */
3381 for (; i < attIndex; i += 2) {
3382 const XML_Char *s = appAtts[i];
3383 if (s[-1] == 2) { /* prefixed */
3384 ATTRIBUTE_ID *id;
3385 const BINDING *b;
Elliott Hughes72472942018-01-10 08:36:10 -08003386 unsigned long uriHash;
3387 struct siphash sip_state;
3388 struct sipkey sip_key;
3389
3390 copy_salt_to_sipkey(parser, &sip_key);
3391 sip24_init(&sip_state, &sip_key);
3392
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003393 ((XML_Char *)s)[-1] = 0; /* clear flag */
Elliott Hughes35e432d2012-09-09 14:23:38 -07003394 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
Elliott Hughes72472942018-01-10 08:36:10 -08003395 if (!id || !id->prefix) {
3396 /* This code is walking through the appAtts array, dealing
3397 * with (in this case) a prefixed attribute name. To be in
3398 * the array, the attribute must have already been bound, so
3399 * has to have passed through the hash table lookup once
3400 * already. That implies that an entry for it already
3401 * exists, so the lookup above will return a pointer to
3402 * already allocated memory. There is no opportunaity for
3403 * the allocator to fail, so the condition above cannot be
3404 * fulfilled.
3405 *
3406 * Since it is difficult to be certain that the above
3407 * analysis is complete, we retain the test and merely
3408 * remove the code from coverage tests.
3409 */
3410 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
3411 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003412 b = id->prefix->binding;
3413 if (!b)
3414 return XML_ERROR_UNBOUND_PREFIX;
3415
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003416 for (j = 0; j < b->uriLen; j++) {
3417 const XML_Char c = b->uri[j];
Elliott Hughes72472942018-01-10 08:36:10 -08003418 if (!poolAppendChar(&parser->m_tempPool, c))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003419 return XML_ERROR_NO_MEMORY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003420 }
Elliott Hughes72472942018-01-10 08:36:10 -08003421
3422 sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
3423
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003424 while (*s++ != XML_T(ASCII_COLON))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003425 ;
Elliott Hughes72472942018-01-10 08:36:10 -08003426
3427 sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
3428
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003429 do { /* copies null terminator */
Elliott Hughes72472942018-01-10 08:36:10 -08003430 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003431 return XML_ERROR_NO_MEMORY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003432 } while (*s++);
3433
Elliott Hughes72472942018-01-10 08:36:10 -08003434 uriHash = (unsigned long)sip24_final(&sip_state);
3435
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003436 { /* Check hash table for duplicate of expanded name (uriName).
Elliott Hughes35e432d2012-09-09 14:23:38 -07003437 Derived from code in lookup(parser, HASH_TABLE *table, ...).
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003438 */
3439 unsigned char step = 0;
3440 unsigned long mask = nsAttsSize - 1;
3441 j = uriHash & mask; /* index into hash table */
Elliott Hughes72472942018-01-10 08:36:10 -08003442 while (parser->m_nsAtts[j].version == version) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003443 /* for speed we compare stored hash values first */
Elliott Hughes72472942018-01-10 08:36:10 -08003444 if (uriHash == parser->m_nsAtts[j].hash) {
3445 const XML_Char *s1 = poolStart(&parser->m_tempPool);
3446 const XML_Char *s2 = parser->m_nsAtts[j].uriName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003447 /* s1 is null terminated, but not s2 */
3448 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
3449 if (*s1 == 0)
3450 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3451 }
3452 if (!step)
Elliott Hughes72472942018-01-10 08:36:10 -08003453 step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003454 j < step ? (j += nsAttsSize - step) : (j -= step);
3455 }
3456 }
3457
Elliott Hughes72472942018-01-10 08:36:10 -08003458 if (parser->m_ns_triplets) { /* append namespace separator and prefix */
3459 parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003460 s = b->prefix->name;
3461 do {
Elliott Hughes72472942018-01-10 08:36:10 -08003462 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003463 return XML_ERROR_NO_MEMORY;
3464 } while (*s++);
3465 }
3466
3467 /* store expanded name in attribute list */
Elliott Hughes72472942018-01-10 08:36:10 -08003468 s = poolStart(&parser->m_tempPool);
3469 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003470 appAtts[i] = s;
3471
3472 /* fill empty slot with new version, uriName and hash value */
Elliott Hughes72472942018-01-10 08:36:10 -08003473 parser->m_nsAtts[j].version = version;
3474 parser->m_nsAtts[j].hash = uriHash;
3475 parser->m_nsAtts[j].uriName = s;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003476
3477 if (!--nPrefixes) {
3478 i += 2;
3479 break;
3480 }
3481 }
3482 else /* not prefixed */
3483 ((XML_Char *)s)[-1] = 0; /* clear flag */
3484 }
3485 }
3486 /* clear flags for the remaining attributes */
3487 for (; i < attIndex; i += 2)
3488 ((XML_Char *)(appAtts[i]))[-1] = 0;
3489 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3490 binding->attId->name[-1] = 0;
3491
Elliott Hughes72472942018-01-10 08:36:10 -08003492 if (!parser->m_ns)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003493 return XML_ERROR_NONE;
3494
3495 /* expand the element type name */
3496 if (elementType->prefix) {
3497 binding = elementType->prefix->binding;
3498 if (!binding)
3499 return XML_ERROR_UNBOUND_PREFIX;
3500 localPart = tagNamePtr->str;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003501 while (*localPart++ != XML_T(ASCII_COLON))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003502 ;
3503 }
3504 else if (dtd->defaultPrefix.binding) {
3505 binding = dtd->defaultPrefix.binding;
3506 localPart = tagNamePtr->str;
3507 }
3508 else
3509 return XML_ERROR_NONE;
3510 prefixLen = 0;
Elliott Hughes72472942018-01-10 08:36:10 -08003511 if (parser->m_ns_triplets && binding->prefix->name) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003512 for (; binding->prefix->name[prefixLen++];)
3513 ; /* prefixLen includes null terminator */
3514 }
3515 tagNamePtr->localPart = localPart;
3516 tagNamePtr->uriLen = binding->uriLen;
3517 tagNamePtr->prefix = binding->prefix->name;
3518 tagNamePtr->prefixLen = prefixLen;
3519 for (i = 0; localPart[i++];)
3520 ; /* i includes null terminator */
3521 n = i + binding->uriLen + prefixLen;
3522 if (n > binding->uriAlloc) {
3523 TAG *p;
Elliott Hughes72472942018-01-10 08:36:10 -08003524 uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003525 if (!uri)
3526 return XML_ERROR_NO_MEMORY;
3527 binding->uriAlloc = n + EXPAND_SPARE;
3528 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
Elliott Hughes72472942018-01-10 08:36:10 -08003529 for (p = parser->m_tagStack; p; p = p->parent)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003530 if (p->name.str == binding->uri)
3531 p->name.str = uri;
Elliott Hughes72472942018-01-10 08:36:10 -08003532 FREE(parser, binding->uri);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003533 binding->uri = uri;
3534 }
Elliott Hughes72472942018-01-10 08:36:10 -08003535 /* if m_namespaceSeparator != '\0' then uri includes it already */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003536 uri = binding->uri + binding->uriLen;
3537 memcpy(uri, localPart, i * sizeof(XML_Char));
3538 /* we always have a namespace separator between localPart and prefix */
3539 if (prefixLen) {
3540 uri += i - 1;
Elliott Hughes72472942018-01-10 08:36:10 -08003541 *uri = parser->m_namespaceSeparator; /* replace null terminator */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003542 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3543 }
3544 tagNamePtr->str = binding->uri;
3545 return XML_ERROR_NONE;
3546}
3547
3548/* addBinding() overwrites the value of prefix->binding without checking.
3549 Therefore one must keep track of the old value outside of addBinding().
3550*/
3551static enum XML_Error
3552addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3553 const XML_Char *uri, BINDING **bindingsPtr)
3554{
3555 static const XML_Char xmlNamespace[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003556 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3557 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
Elliott Hughes35e432d2012-09-09 14:23:38 -07003558 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003559 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
3560 ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
3561 ASCII_e, '\0'
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003562 };
Elliott Hughes35e432d2012-09-09 14:23:38 -07003563 static const int xmlLen =
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003564 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
3565 static const XML_Char xmlnsNamespace[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003566 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3567 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
Elliott Hughes35e432d2012-09-09 14:23:38 -07003568 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
3569 ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003570 ASCII_SLASH, '\0'
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003571 };
Elliott Hughes35e432d2012-09-09 14:23:38 -07003572 static const int xmlnsLen =
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003573 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
3574
3575 XML_Bool mustBeXML = XML_FALSE;
3576 XML_Bool isXML = XML_TRUE;
3577 XML_Bool isXMLNS = XML_TRUE;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003578
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003579 BINDING *b;
3580 int len;
3581
3582 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3583 if (*uri == XML_T('\0') && prefix->name)
3584 return XML_ERROR_UNDECLARING_PREFIX;
3585
3586 if (prefix->name
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003587 && prefix->name[0] == XML_T(ASCII_x)
3588 && prefix->name[1] == XML_T(ASCII_m)
3589 && prefix->name[2] == XML_T(ASCII_l)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003590
3591 /* Not allowed to bind xmlns */
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003592 if (prefix->name[3] == XML_T(ASCII_n)
3593 && prefix->name[4] == XML_T(ASCII_s)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003594 && prefix->name[5] == XML_T('\0'))
3595 return XML_ERROR_RESERVED_PREFIX_XMLNS;
3596
3597 if (prefix->name[3] == XML_T('\0'))
3598 mustBeXML = XML_TRUE;
3599 }
3600
3601 for (len = 0; uri[len]; len++) {
3602 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3603 isXML = XML_FALSE;
3604
Elliott Hughes35e432d2012-09-09 14:23:38 -07003605 if (!mustBeXML && isXMLNS
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003606 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3607 isXMLNS = XML_FALSE;
3608 }
3609 isXML = isXML && len == xmlLen;
3610 isXMLNS = isXMLNS && len == xmlnsLen;
3611
3612 if (mustBeXML != isXML)
3613 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3614 : XML_ERROR_RESERVED_NAMESPACE_URI;
3615
3616 if (isXMLNS)
3617 return XML_ERROR_RESERVED_NAMESPACE_URI;
3618
Elliott Hughes72472942018-01-10 08:36:10 -08003619 if (parser->m_namespaceSeparator)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003620 len++;
Elliott Hughes72472942018-01-10 08:36:10 -08003621 if (parser->m_freeBindingList) {
3622 b = parser->m_freeBindingList;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003623 if (len > b->uriAlloc) {
Elliott Hughes72472942018-01-10 08:36:10 -08003624 XML_Char *temp = (XML_Char *)REALLOC(parser, b->uri,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003625 sizeof(XML_Char) * (len + EXPAND_SPARE));
3626 if (temp == NULL)
3627 return XML_ERROR_NO_MEMORY;
3628 b->uri = temp;
3629 b->uriAlloc = len + EXPAND_SPARE;
3630 }
Elliott Hughes72472942018-01-10 08:36:10 -08003631 parser->m_freeBindingList = b->nextTagBinding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003632 }
3633 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003634 b = (BINDING *)MALLOC(parser, sizeof(BINDING));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003635 if (!b)
3636 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003637 b->uri = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003638 if (!b->uri) {
Elliott Hughes72472942018-01-10 08:36:10 -08003639 FREE(parser, b);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003640 return XML_ERROR_NO_MEMORY;
3641 }
3642 b->uriAlloc = len + EXPAND_SPARE;
3643 }
3644 b->uriLen = len;
3645 memcpy(b->uri, uri, len * sizeof(XML_Char));
Elliott Hughes72472942018-01-10 08:36:10 -08003646 if (parser->m_namespaceSeparator)
3647 b->uri[len - 1] = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003648 b->prefix = prefix;
3649 b->attId = attId;
3650 b->prevPrefixBinding = prefix->binding;
3651 /* NULL binding when default namespace undeclared */
Elliott Hughes72472942018-01-10 08:36:10 -08003652 if (*uri == XML_T('\0') && prefix == &parser->m_dtd->defaultPrefix)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003653 prefix->binding = NULL;
3654 else
3655 prefix->binding = b;
3656 b->nextTagBinding = *bindingsPtr;
3657 *bindingsPtr = b;
3658 /* if attId == NULL then we are not starting a namespace scope */
Elliott Hughes72472942018-01-10 08:36:10 -08003659 if (attId && parser->m_startNamespaceDeclHandler)
3660 parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003661 prefix->binding ? uri : 0);
3662 return XML_ERROR_NONE;
3663}
3664
3665/* The idea here is to avoid using stack for each CDATA section when
3666 the whole file is parsed with one call.
3667*/
3668static enum XML_Error PTRCALL
3669cdataSectionProcessor(XML_Parser parser,
3670 const char *start,
3671 const char *end,
3672 const char **endPtr)
3673{
Elliott Hughes72472942018-01-10 08:36:10 -08003674 enum XML_Error result = doCdataSection(parser, parser->m_encoding, &start, end,
3675 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003676 if (result != XML_ERROR_NONE)
3677 return result;
3678 if (start) {
Elliott Hughes72472942018-01-10 08:36:10 -08003679 if (parser->m_parentParser) { /* we are parsing an external entity */
3680 parser->m_processor = externalEntityContentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003681 return externalEntityContentProcessor(parser, start, end, endPtr);
3682 }
3683 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003684 parser->m_processor = contentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003685 return contentProcessor(parser, start, end, endPtr);
3686 }
3687 }
3688 return result;
3689}
3690
3691/* startPtr gets set to non-null if the section is closed, and to null if
3692 the section is not yet closed.
3693*/
3694static enum XML_Error
3695doCdataSection(XML_Parser parser,
3696 const ENCODING *enc,
3697 const char **startPtr,
3698 const char *end,
3699 const char **nextPtr,
3700 XML_Bool haveMore)
3701{
3702 const char *s = *startPtr;
3703 const char **eventPP;
3704 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08003705 if (enc == parser->m_encoding) {
3706 eventPP = &parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003707 *eventPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08003708 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003709 }
3710 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003711 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3712 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003713 }
3714 *eventPP = s;
3715 *startPtr = NULL;
3716
3717 for (;;) {
3718 const char *next;
3719 int tok = XmlCdataSectionTok(enc, s, end, &next);
3720 *eventEndPP = next;
3721 switch (tok) {
3722 case XML_TOK_CDATA_SECT_CLOSE:
Elliott Hughes72472942018-01-10 08:36:10 -08003723 if (parser->m_endCdataSectionHandler)
3724 parser->m_endCdataSectionHandler(parser->m_handlerArg);
Haibo Huangfd5e81a2019-06-20 12:09:36 -07003725/* BEGIN disabled code */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003726 /* see comment under XML_TOK_CDATA_SECT_OPEN */
Haibo Huangfd5e81a2019-06-20 12:09:36 -07003727 else if (0 && parser->m_characterDataHandler)
Elliott Hughes72472942018-01-10 08:36:10 -08003728 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0);
Haibo Huangfd5e81a2019-06-20 12:09:36 -07003729/* END disabled code */
Elliott Hughes72472942018-01-10 08:36:10 -08003730 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003731 reportDefault(parser, enc, s, next);
3732 *startPtr = next;
3733 *nextPtr = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003734 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003735 return XML_ERROR_ABORTED;
3736 else
3737 return XML_ERROR_NONE;
3738 case XML_TOK_DATA_NEWLINE:
Elliott Hughes72472942018-01-10 08:36:10 -08003739 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003740 XML_Char c = 0xA;
Elliott Hughes72472942018-01-10 08:36:10 -08003741 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003742 }
Elliott Hughes72472942018-01-10 08:36:10 -08003743 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003744 reportDefault(parser, enc, s, next);
3745 break;
3746 case XML_TOK_DATA_CHARS:
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003747 {
Elliott Hughes72472942018-01-10 08:36:10 -08003748 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003749 if (charDataHandler) {
3750 if (MUST_CONVERT(enc, s)) {
3751 for (;;) {
Elliott Hughes72472942018-01-10 08:36:10 -08003752 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3753 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003754 *eventEndPP = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003755 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3756 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
Paul Duffin4bf8f122016-05-13 12:35:25 +01003757 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003758 break;
3759 *eventPP = s;
3760 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003761 }
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003762 else
Elliott Hughes72472942018-01-10 08:36:10 -08003763 charDataHandler(parser->m_handlerArg,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003764 (XML_Char *)s,
3765 (int)((XML_Char *)next - (XML_Char *)s));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003766 }
Elliott Hughes72472942018-01-10 08:36:10 -08003767 else if (parser->m_defaultHandler)
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003768 reportDefault(parser, enc, s, next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003769 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003770 break;
3771 case XML_TOK_INVALID:
3772 *eventPP = next;
3773 return XML_ERROR_INVALID_TOKEN;
3774 case XML_TOK_PARTIAL_CHAR:
3775 if (haveMore) {
3776 *nextPtr = s;
3777 return XML_ERROR_NONE;
3778 }
3779 return XML_ERROR_PARTIAL_CHAR;
3780 case XML_TOK_PARTIAL:
3781 case XML_TOK_NONE:
3782 if (haveMore) {
3783 *nextPtr = s;
3784 return XML_ERROR_NONE;
3785 }
3786 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3787 default:
Elliott Hughes72472942018-01-10 08:36:10 -08003788 /* Every token returned by XmlCdataSectionTok() has its own
3789 * explicit case, so this default case will never be executed.
3790 * We retain it as a safety net and exclude it from the coverage
3791 * statistics.
3792 *
3793 * LCOV_EXCL_START
3794 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003795 *eventPP = next;
3796 return XML_ERROR_UNEXPECTED_STATE;
Elliott Hughes72472942018-01-10 08:36:10 -08003797 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003798 }
3799
3800 *eventPP = s = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003801 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003802 case XML_SUSPENDED:
3803 *nextPtr = next;
3804 return XML_ERROR_NONE;
3805 case XML_FINISHED:
3806 return XML_ERROR_ABORTED;
3807 default: ;
3808 }
3809 }
3810 /* not reached */
3811}
3812
3813#ifdef XML_DTD
3814
3815/* The idea here is to avoid using stack for each IGNORE section when
3816 the whole file is parsed with one call.
3817*/
3818static enum XML_Error PTRCALL
3819ignoreSectionProcessor(XML_Parser parser,
3820 const char *start,
3821 const char *end,
3822 const char **endPtr)
3823{
Elliott Hughes72472942018-01-10 08:36:10 -08003824 enum XML_Error result = doIgnoreSection(parser, parser->m_encoding, &start, end,
3825 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003826 if (result != XML_ERROR_NONE)
3827 return result;
3828 if (start) {
Elliott Hughes72472942018-01-10 08:36:10 -08003829 parser->m_processor = prologProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003830 return prologProcessor(parser, start, end, endPtr);
3831 }
3832 return result;
3833}
3834
3835/* startPtr gets set to non-null is the section is closed, and to null
3836 if the section is not yet closed.
3837*/
3838static enum XML_Error
3839doIgnoreSection(XML_Parser parser,
3840 const ENCODING *enc,
3841 const char **startPtr,
3842 const char *end,
3843 const char **nextPtr,
3844 XML_Bool haveMore)
3845{
3846 const char *next;
3847 int tok;
3848 const char *s = *startPtr;
3849 const char **eventPP;
3850 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08003851 if (enc == parser->m_encoding) {
3852 eventPP = &parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003853 *eventPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08003854 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003855 }
3856 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003857 /* It's not entirely clear, but it seems the following two lines
3858 * of code cannot be executed. The only occasions on which 'enc'
3859 * is not 'encoding' are when this function is called
3860 * from the internal entity processing, and IGNORE sections are an
3861 * error in internal entities.
3862 *
3863 * Since it really isn't clear that this is true, we keep the code
3864 * and just remove it from our coverage tests.
3865 *
3866 * LCOV_EXCL_START
3867 */
3868 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3869 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
3870 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003871 }
3872 *eventPP = s;
3873 *startPtr = NULL;
3874 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3875 *eventEndPP = next;
3876 switch (tok) {
3877 case XML_TOK_IGNORE_SECT:
Elliott Hughes72472942018-01-10 08:36:10 -08003878 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003879 reportDefault(parser, enc, s, next);
3880 *startPtr = next;
3881 *nextPtr = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003882 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003883 return XML_ERROR_ABORTED;
3884 else
3885 return XML_ERROR_NONE;
3886 case XML_TOK_INVALID:
3887 *eventPP = next;
3888 return XML_ERROR_INVALID_TOKEN;
3889 case XML_TOK_PARTIAL_CHAR:
3890 if (haveMore) {
3891 *nextPtr = s;
3892 return XML_ERROR_NONE;
3893 }
3894 return XML_ERROR_PARTIAL_CHAR;
3895 case XML_TOK_PARTIAL:
3896 case XML_TOK_NONE:
3897 if (haveMore) {
3898 *nextPtr = s;
3899 return XML_ERROR_NONE;
3900 }
3901 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3902 default:
Elliott Hughes72472942018-01-10 08:36:10 -08003903 /* All of the tokens that XmlIgnoreSectionTok() returns have
3904 * explicit cases to handle them, so this default case is never
3905 * executed. We keep it as a safety net anyway, and remove it
3906 * from our test coverage statistics.
3907 *
3908 * LCOV_EXCL_START
3909 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003910 *eventPP = next;
3911 return XML_ERROR_UNEXPECTED_STATE;
Elliott Hughes72472942018-01-10 08:36:10 -08003912 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003913 }
3914 /* not reached */
3915}
3916
3917#endif /* XML_DTD */
3918
3919static enum XML_Error
3920initializeEncoding(XML_Parser parser)
3921{
3922 const char *s;
3923#ifdef XML_UNICODE
3924 char encodingBuf[128];
Elliott Hughes72472942018-01-10 08:36:10 -08003925 /* See comments abount `protoclEncodingName` in parserInit() */
3926 if (!parser->m_protocolEncodingName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003927 s = NULL;
3928 else {
3929 int i;
Elliott Hughes72472942018-01-10 08:36:10 -08003930 for (i = 0; parser->m_protocolEncodingName[i]; i++) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003931 if (i == sizeof(encodingBuf) - 1
Elliott Hughes72472942018-01-10 08:36:10 -08003932 || (parser->m_protocolEncodingName[i] & ~0x7f) != 0) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003933 encodingBuf[0] = '\0';
3934 break;
3935 }
Elliott Hughes72472942018-01-10 08:36:10 -08003936 encodingBuf[i] = (char)parser->m_protocolEncodingName[i];
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003937 }
3938 encodingBuf[i] = '\0';
3939 s = encodingBuf;
3940 }
3941#else
Elliott Hughes72472942018-01-10 08:36:10 -08003942 s = parser->m_protocolEncodingName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003943#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003944 if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(&parser->m_initEncoding, &parser->m_encoding, s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003945 return XML_ERROR_NONE;
Elliott Hughes72472942018-01-10 08:36:10 -08003946 return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003947}
3948
3949static enum XML_Error
3950processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3951 const char *s, const char *next)
3952{
3953 const char *encodingName = NULL;
3954 const XML_Char *storedEncName = NULL;
3955 const ENCODING *newEncoding = NULL;
3956 const char *version = NULL;
3957 const char *versionend;
3958 const XML_Char *storedversion = NULL;
3959 int standalone = -1;
Elliott Hughes72472942018-01-10 08:36:10 -08003960 if (!(parser->m_ns
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003961 ? XmlParseXmlDeclNS
3962 : XmlParseXmlDecl)(isGeneralTextEntity,
Elliott Hughes72472942018-01-10 08:36:10 -08003963 parser->m_encoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003964 s,
3965 next,
Elliott Hughes72472942018-01-10 08:36:10 -08003966 &parser->m_eventPtr,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003967 &version,
3968 &versionend,
3969 &encodingName,
3970 &newEncoding,
3971 &standalone)) {
3972 if (isGeneralTextEntity)
3973 return XML_ERROR_TEXT_DECL;
3974 else
3975 return XML_ERROR_XML_DECL;
3976 }
3977 if (!isGeneralTextEntity && standalone == 1) {
Elliott Hughes72472942018-01-10 08:36:10 -08003978 parser->m_dtd->standalone = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003979#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08003980 if (parser->m_paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3981 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003982#endif /* XML_DTD */
3983 }
Elliott Hughes72472942018-01-10 08:36:10 -08003984 if (parser->m_xmlDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003985 if (encodingName != NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08003986 storedEncName = poolStoreString(&parser->m_temp2Pool,
3987 parser->m_encoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003988 encodingName,
3989 encodingName
Elliott Hughes72472942018-01-10 08:36:10 -08003990 + XmlNameLength(parser->m_encoding, encodingName));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003991 if (!storedEncName)
3992 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003993 poolFinish(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003994 }
3995 if (version) {
Elliott Hughes72472942018-01-10 08:36:10 -08003996 storedversion = poolStoreString(&parser->m_temp2Pool,
3997 parser->m_encoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003998 version,
Elliott Hughes72472942018-01-10 08:36:10 -08003999 versionend - parser->m_encoding->minBytesPerChar);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004000 if (!storedversion)
4001 return XML_ERROR_NO_MEMORY;
4002 }
Elliott Hughes72472942018-01-10 08:36:10 -08004003 parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName, standalone);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004004 }
Elliott Hughes72472942018-01-10 08:36:10 -08004005 else if (parser->m_defaultHandler)
4006 reportDefault(parser, parser->m_encoding, s, next);
4007 if (parser->m_protocolEncodingName == NULL) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004008 if (newEncoding) {
Elliott Hughes72472942018-01-10 08:36:10 -08004009 /* Check that the specified encoding does not conflict with what
4010 * the parser has already deduced. Do we have the same number
4011 * of bytes in the smallest representation of a character? If
4012 * this is UTF-16, is it the same endianness?
4013 */
4014 if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
4015 || (newEncoding->minBytesPerChar == 2 &&
4016 newEncoding != parser->m_encoding)) {
4017 parser->m_eventPtr = encodingName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004018 return XML_ERROR_INCORRECT_ENCODING;
4019 }
Elliott Hughes72472942018-01-10 08:36:10 -08004020 parser->m_encoding = newEncoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004021 }
4022 else if (encodingName) {
4023 enum XML_Error result;
4024 if (!storedEncName) {
4025 storedEncName = poolStoreString(
Elliott Hughes72472942018-01-10 08:36:10 -08004026 &parser->m_temp2Pool, parser->m_encoding, encodingName,
4027 encodingName + XmlNameLength(parser->m_encoding, encodingName));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004028 if (!storedEncName)
4029 return XML_ERROR_NO_MEMORY;
4030 }
4031 result = handleUnknownEncoding(parser, storedEncName);
Elliott Hughes72472942018-01-10 08:36:10 -08004032 poolClear(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004033 if (result == XML_ERROR_UNKNOWN_ENCODING)
Elliott Hughes72472942018-01-10 08:36:10 -08004034 parser->m_eventPtr = encodingName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004035 return result;
4036 }
4037 }
4038
4039 if (storedEncName || storedversion)
Elliott Hughes72472942018-01-10 08:36:10 -08004040 poolClear(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004041
4042 return XML_ERROR_NONE;
4043}
4044
4045static enum XML_Error
4046handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
4047{
Elliott Hughes72472942018-01-10 08:36:10 -08004048 if (parser->m_unknownEncodingHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004049 XML_Encoding info;
4050 int i;
4051 for (i = 0; i < 256; i++)
4052 info.map[i] = -1;
4053 info.convert = NULL;
4054 info.data = NULL;
4055 info.release = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08004056 if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData, encodingName,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004057 &info)) {
4058 ENCODING *enc;
Elliott Hughes72472942018-01-10 08:36:10 -08004059 parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding());
4060 if (!parser->m_unknownEncodingMem) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004061 if (info.release)
4062 info.release(info.data);
4063 return XML_ERROR_NO_MEMORY;
4064 }
Elliott Hughes72472942018-01-10 08:36:10 -08004065 enc = (parser->m_ns
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004066 ? XmlInitUnknownEncodingNS
Elliott Hughes72472942018-01-10 08:36:10 -08004067 : XmlInitUnknownEncoding)(parser->m_unknownEncodingMem,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004068 info.map,
4069 info.convert,
4070 info.data);
4071 if (enc) {
Elliott Hughes72472942018-01-10 08:36:10 -08004072 parser->m_unknownEncodingData = info.data;
4073 parser->m_unknownEncodingRelease = info.release;
4074 parser->m_encoding = enc;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004075 return XML_ERROR_NONE;
4076 }
4077 }
4078 if (info.release != NULL)
4079 info.release(info.data);
4080 }
4081 return XML_ERROR_UNKNOWN_ENCODING;
4082}
4083
4084static enum XML_Error PTRCALL
4085prologInitProcessor(XML_Parser parser,
4086 const char *s,
4087 const char *end,
4088 const char **nextPtr)
4089{
4090 enum XML_Error result = initializeEncoding(parser);
4091 if (result != XML_ERROR_NONE)
4092 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004093 parser->m_processor = prologProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004094 return prologProcessor(parser, s, end, nextPtr);
4095}
4096
4097#ifdef XML_DTD
4098
4099static enum XML_Error PTRCALL
4100externalParEntInitProcessor(XML_Parser parser,
4101 const char *s,
4102 const char *end,
4103 const char **nextPtr)
4104{
4105 enum XML_Error result = initializeEncoding(parser);
4106 if (result != XML_ERROR_NONE)
4107 return result;
4108
4109 /* we know now that XML_Parse(Buffer) has been called,
4110 so we consider the external parameter entity read */
Elliott Hughes72472942018-01-10 08:36:10 -08004111 parser->m_dtd->paramEntityRead = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004112
Elliott Hughes72472942018-01-10 08:36:10 -08004113 if (parser->m_prologState.inEntityValue) {
4114 parser->m_processor = entityValueInitProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004115 return entityValueInitProcessor(parser, s, end, nextPtr);
4116 }
4117 else {
Elliott Hughes72472942018-01-10 08:36:10 -08004118 parser->m_processor = externalParEntProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004119 return externalParEntProcessor(parser, s, end, nextPtr);
4120 }
4121}
4122
4123static enum XML_Error PTRCALL
4124entityValueInitProcessor(XML_Parser parser,
4125 const char *s,
4126 const char *end,
4127 const char **nextPtr)
4128{
4129 int tok;
4130 const char *start = s;
4131 const char *next = start;
Elliott Hughes72472942018-01-10 08:36:10 -08004132 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004133
Elliott Hughes35e432d2012-09-09 14:23:38 -07004134 for (;;) {
Elliott Hughes72472942018-01-10 08:36:10 -08004135 tok = XmlPrologTok(parser->m_encoding, start, end, &next);
4136 parser->m_eventEndPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004137 if (tok <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08004138 if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004139 *nextPtr = s;
4140 return XML_ERROR_NONE;
4141 }
4142 switch (tok) {
4143 case XML_TOK_INVALID:
4144 return XML_ERROR_INVALID_TOKEN;
4145 case XML_TOK_PARTIAL:
4146 return XML_ERROR_UNCLOSED_TOKEN;
4147 case XML_TOK_PARTIAL_CHAR:
4148 return XML_ERROR_PARTIAL_CHAR;
4149 case XML_TOK_NONE: /* start == end */
4150 default:
4151 break;
4152 }
4153 /* found end of entity value - can store it now */
Elliott Hughes72472942018-01-10 08:36:10 -08004154 return storeEntityValue(parser, parser->m_encoding, s, end);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004155 }
4156 else if (tok == XML_TOK_XML_DECL) {
4157 enum XML_Error result;
4158 result = processXmlDecl(parser, 0, start, next);
4159 if (result != XML_ERROR_NONE)
4160 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004161 /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED. For that
4162 * to happen, a parameter entity parsing handler must have
4163 * attempted to suspend the parser, which fails and raises an
4164 * error. The parser can be aborted, but can't be suspended.
4165 */
4166 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004167 return XML_ERROR_ABORTED;
Elliott Hughes72472942018-01-10 08:36:10 -08004168 *nextPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004169 /* stop scanning for text declaration - we found one */
Elliott Hughes72472942018-01-10 08:36:10 -08004170 parser->m_processor = entityValueProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004171 return entityValueProcessor(parser, next, end, nextPtr);
4172 }
4173 /* If we are at the end of the buffer, this would cause XmlPrologTok to
4174 return XML_TOK_NONE on the next call, which would then cause the
4175 function to exit with *nextPtr set to s - that is what we want for other
4176 tokens, but not for the BOM - we would rather like to skip it;
4177 then, when this routine is entered the next time, XmlPrologTok will
4178 return XML_TOK_INVALID, since the BOM is still in the buffer
4179 */
Elliott Hughes72472942018-01-10 08:36:10 -08004180 else if (tok == XML_TOK_BOM && next == end && !parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004181 *nextPtr = next;
4182 return XML_ERROR_NONE;
4183 }
Elliott Hughes72472942018-01-10 08:36:10 -08004184 /* If we get this token, we have the start of what might be a
4185 normal tag, but not a declaration (i.e. it doesn't begin with
4186 "<!"). In a DTD context, that isn't legal.
4187 */
4188 else if (tok == XML_TOK_INSTANCE_START) {
4189 *nextPtr = next;
4190 return XML_ERROR_SYNTAX;
4191 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004192 start = next;
Elliott Hughes72472942018-01-10 08:36:10 -08004193 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004194 }
4195}
4196
4197static enum XML_Error PTRCALL
4198externalParEntProcessor(XML_Parser parser,
4199 const char *s,
4200 const char *end,
4201 const char **nextPtr)
4202{
4203 const char *next = s;
4204 int tok;
4205
Elliott Hughes72472942018-01-10 08:36:10 -08004206 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004207 if (tok <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08004208 if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004209 *nextPtr = s;
4210 return XML_ERROR_NONE;
4211 }
4212 switch (tok) {
4213 case XML_TOK_INVALID:
4214 return XML_ERROR_INVALID_TOKEN;
4215 case XML_TOK_PARTIAL:
4216 return XML_ERROR_UNCLOSED_TOKEN;
4217 case XML_TOK_PARTIAL_CHAR:
4218 return XML_ERROR_PARTIAL_CHAR;
4219 case XML_TOK_NONE: /* start == end */
4220 default:
4221 break;
4222 }
4223 }
4224 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
4225 However, when parsing an external subset, doProlog will not accept a BOM
4226 as valid, and report a syntax error, so we have to skip the BOM
4227 */
4228 else if (tok == XML_TOK_BOM) {
4229 s = next;
Elliott Hughes72472942018-01-10 08:36:10 -08004230 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004231 }
4232
Elliott Hughes72472942018-01-10 08:36:10 -08004233 parser->m_processor = prologProcessor;
4234 return doProlog(parser, parser->m_encoding, s, end, tok, next,
4235 nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004236}
4237
4238static enum XML_Error PTRCALL
4239entityValueProcessor(XML_Parser parser,
4240 const char *s,
4241 const char *end,
4242 const char **nextPtr)
4243{
4244 const char *start = s;
4245 const char *next = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004246 const ENCODING *enc = parser->m_encoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004247 int tok;
4248
4249 for (;;) {
4250 tok = XmlPrologTok(enc, start, end, &next);
4251 if (tok <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08004252 if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004253 *nextPtr = s;
4254 return XML_ERROR_NONE;
4255 }
4256 switch (tok) {
4257 case XML_TOK_INVALID:
4258 return XML_ERROR_INVALID_TOKEN;
4259 case XML_TOK_PARTIAL:
4260 return XML_ERROR_UNCLOSED_TOKEN;
4261 case XML_TOK_PARTIAL_CHAR:
4262 return XML_ERROR_PARTIAL_CHAR;
4263 case XML_TOK_NONE: /* start == end */
4264 default:
4265 break;
4266 }
4267 /* found end of entity value - can store it now */
4268 return storeEntityValue(parser, enc, s, end);
4269 }
4270 start = next;
4271 }
4272}
4273
4274#endif /* XML_DTD */
4275
4276static enum XML_Error PTRCALL
4277prologProcessor(XML_Parser parser,
4278 const char *s,
4279 const char *end,
4280 const char **nextPtr)
4281{
4282 const char *next = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004283 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4284 return doProlog(parser, parser->m_encoding, s, end, tok, next,
4285 nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004286}
4287
4288static enum XML_Error
4289doProlog(XML_Parser parser,
4290 const ENCODING *enc,
4291 const char *s,
4292 const char *end,
4293 int tok,
4294 const char *next,
4295 const char **nextPtr,
4296 XML_Bool haveMore)
4297{
4298#ifdef XML_DTD
Elliott Hughesd07d5a72009-09-25 16:04:37 -07004299 static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004300#endif /* XML_DTD */
Elliott Hughes35e432d2012-09-09 14:23:38 -07004301 static const XML_Char atypeCDATA[] =
Elliott Hughesd07d5a72009-09-25 16:04:37 -07004302 { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
4303 static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
4304 static const XML_Char atypeIDREF[] =
4305 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
4306 static const XML_Char atypeIDREFS[] =
4307 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
4308 static const XML_Char atypeENTITY[] =
4309 { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
4310 static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
4311 ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004312 static const XML_Char atypeNMTOKEN[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07004313 ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
4314 static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
4315 ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
4316 static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
4317 ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
4318 static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
4319 static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004320
4321 /* save one level of indirection */
Elliott Hughes72472942018-01-10 08:36:10 -08004322 DTD * const dtd = parser->m_dtd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004323
4324 const char **eventPP;
4325 const char **eventEndPP;
4326 enum XML_Content_Quant quant;
4327
Elliott Hughes72472942018-01-10 08:36:10 -08004328 if (enc == parser->m_encoding) {
4329 eventPP = &parser->m_eventPtr;
4330 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004331 }
4332 else {
Elliott Hughes72472942018-01-10 08:36:10 -08004333 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4334 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004335 }
4336
4337 for (;;) {
4338 int role;
4339 XML_Bool handleDefault = XML_TRUE;
4340 *eventPP = s;
4341 *eventEndPP = next;
4342 if (tok <= 0) {
4343 if (haveMore && tok != XML_TOK_INVALID) {
4344 *nextPtr = s;
4345 return XML_ERROR_NONE;
4346 }
4347 switch (tok) {
4348 case XML_TOK_INVALID:
4349 *eventPP = next;
4350 return XML_ERROR_INVALID_TOKEN;
4351 case XML_TOK_PARTIAL:
4352 return XML_ERROR_UNCLOSED_TOKEN;
4353 case XML_TOK_PARTIAL_CHAR:
4354 return XML_ERROR_PARTIAL_CHAR;
Elliott Hughes35e432d2012-09-09 14:23:38 -07004355 case -XML_TOK_PROLOG_S:
4356 tok = -tok;
4357 break;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004358 case XML_TOK_NONE:
4359#ifdef XML_DTD
4360 /* for internal PE NOT referenced between declarations */
Elliott Hughes72472942018-01-10 08:36:10 -08004361 if (enc != parser->m_encoding && !parser->m_openInternalEntities->betweenDecl) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004362 *nextPtr = s;
4363 return XML_ERROR_NONE;
4364 }
4365 /* WFC: PE Between Declarations - must check that PE contains
4366 complete markup, not only for external PEs, but also for
4367 internal PEs if the reference occurs between declarations.
4368 */
Elliott Hughes72472942018-01-10 08:36:10 -08004369 if (parser->m_isParamEntity || enc != parser->m_encoding) {
4370 if (XmlTokenRole(&parser->m_prologState, XML_TOK_NONE, end, end, enc)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004371 == XML_ROLE_ERROR)
4372 return XML_ERROR_INCOMPLETE_PE;
4373 *nextPtr = s;
4374 return XML_ERROR_NONE;
4375 }
4376#endif /* XML_DTD */
4377 return XML_ERROR_NO_ELEMENTS;
4378 default:
4379 tok = -tok;
4380 next = end;
4381 break;
4382 }
4383 }
Elliott Hughes72472942018-01-10 08:36:10 -08004384 role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004385 switch (role) {
4386 case XML_ROLE_XML_DECL:
4387 {
4388 enum XML_Error result = processXmlDecl(parser, 0, s, next);
4389 if (result != XML_ERROR_NONE)
4390 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004391 enc = parser->m_encoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004392 handleDefault = XML_FALSE;
4393 }
4394 break;
4395 case XML_ROLE_DOCTYPE_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004396 if (parser->m_startDoctypeDeclHandler) {
4397 parser->m_doctypeName = poolStoreString(&parser->m_tempPool, enc, s, next);
4398 if (!parser->m_doctypeName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004399 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004400 poolFinish(&parser->m_tempPool);
4401 parser->m_doctypePubid = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004402 handleDefault = XML_FALSE;
4403 }
Elliott Hughes72472942018-01-10 08:36:10 -08004404 parser->m_doctypeSysid = NULL; /* always initialize to NULL */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004405 break;
4406 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
Elliott Hughes72472942018-01-10 08:36:10 -08004407 if (parser->m_startDoctypeDeclHandler) {
4408 parser->m_startDoctypeDeclHandler(parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
4409 parser->m_doctypePubid, 1);
4410 parser->m_doctypeName = NULL;
4411 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004412 handleDefault = XML_FALSE;
4413 }
4414 break;
4415#ifdef XML_DTD
4416 case XML_ROLE_TEXT_DECL:
4417 {
4418 enum XML_Error result = processXmlDecl(parser, 1, s, next);
4419 if (result != XML_ERROR_NONE)
4420 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004421 enc = parser->m_encoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004422 handleDefault = XML_FALSE;
4423 }
4424 break;
4425#endif /* XML_DTD */
4426 case XML_ROLE_DOCTYPE_PUBLIC_ID:
4427#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004428 parser->m_useForeignDTD = XML_FALSE;
4429 parser->m_declEntity = (ENTITY *)lookup(parser,
Elliott Hughes35e432d2012-09-09 14:23:38 -07004430 &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004431 externalSubsetName,
4432 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004433 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004434 return XML_ERROR_NO_MEMORY;
4435#endif /* XML_DTD */
4436 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004437 if (parser->m_startDoctypeDeclHandler) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004438 XML_Char *pubId;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004439 if (!XmlIsPublicId(enc, s, next, eventPP))
4440 return XML_ERROR_PUBLICID;
Elliott Hughes72472942018-01-10 08:36:10 -08004441 pubId = poolStoreString(&parser->m_tempPool, enc,
Elliott Hughes35e432d2012-09-09 14:23:38 -07004442 s + enc->minBytesPerChar,
4443 next - enc->minBytesPerChar);
4444 if (!pubId)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004445 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07004446 normalizePublicId(pubId);
Elliott Hughes72472942018-01-10 08:36:10 -08004447 poolFinish(&parser->m_tempPool);
4448 parser->m_doctypePubid = pubId;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004449 handleDefault = XML_FALSE;
4450 goto alreadyChecked;
4451 }
4452 /* fall through */
4453 case XML_ROLE_ENTITY_PUBLIC_ID:
4454 if (!XmlIsPublicId(enc, s, next, eventPP))
4455 return XML_ERROR_PUBLICID;
4456 alreadyChecked:
Elliott Hughes72472942018-01-10 08:36:10 -08004457 if (dtd->keepProcessing && parser->m_declEntity) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004458 XML_Char *tem = poolStoreString(&dtd->pool,
4459 enc,
4460 s + enc->minBytesPerChar,
4461 next - enc->minBytesPerChar);
4462 if (!tem)
4463 return XML_ERROR_NO_MEMORY;
4464 normalizePublicId(tem);
Elliott Hughes72472942018-01-10 08:36:10 -08004465 parser->m_declEntity->publicId = tem;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004466 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004467 /* Don't suppress the default handler if we fell through from
4468 * the XML_ROLE_DOCTYPE_PUBLIC_ID case.
4469 */
4470 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004471 handleDefault = XML_FALSE;
4472 }
4473 break;
4474 case XML_ROLE_DOCTYPE_CLOSE:
Elliott Hughes72472942018-01-10 08:36:10 -08004475 if (parser->m_doctypeName) {
4476 parser->m_startDoctypeDeclHandler(parser->m_handlerArg, parser->m_doctypeName,
4477 parser->m_doctypeSysid, parser->m_doctypePubid, 0);
4478 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004479 handleDefault = XML_FALSE;
4480 }
Elliott Hughes72472942018-01-10 08:36:10 -08004481 /* parser->m_doctypeSysid will be non-NULL in the case of a previous
4482 XML_ROLE_DOCTYPE_SYSTEM_ID, even if parser->m_startDoctypeDeclHandler
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004483 was not set, indicating an external subset
4484 */
4485#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004486 if (parser->m_doctypeSysid || parser->m_useForeignDTD) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004487 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4488 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004489 if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004490 ENTITY *entity = (ENTITY *)lookup(parser,
4491 &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004492 externalSubsetName,
4493 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004494 if (!entity) {
4495 /* The external subset name "#" will have already been
4496 * inserted into the hash table at the start of the
4497 * external entity parsing, so no allocation will happen
4498 * and lookup() cannot fail.
4499 */
4500 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
4501 }
4502 if (parser->m_useForeignDTD)
4503 entity->base = parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004504 dtd->paramEntityRead = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08004505 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004506 0,
4507 entity->base,
4508 entity->systemId,
4509 entity->publicId))
4510 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4511 if (dtd->paramEntityRead) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004512 if (!dtd->standalone &&
Elliott Hughes72472942018-01-10 08:36:10 -08004513 parser->m_notStandaloneHandler &&
4514 !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004515 return XML_ERROR_NOT_STANDALONE;
4516 }
4517 /* if we didn't read the foreign DTD then this means that there
4518 is no external subset and we must reset dtd->hasParamEntityRefs
4519 */
Elliott Hughes72472942018-01-10 08:36:10 -08004520 else if (!parser->m_doctypeSysid)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004521 dtd->hasParamEntityRefs = hadParamEntityRefs;
4522 /* end of DTD - no need to update dtd->keepProcessing */
4523 }
Elliott Hughes72472942018-01-10 08:36:10 -08004524 parser->m_useForeignDTD = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004525 }
4526#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004527 if (parser->m_endDoctypeDeclHandler) {
4528 parser->m_endDoctypeDeclHandler(parser->m_handlerArg);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004529 handleDefault = XML_FALSE;
4530 }
4531 break;
4532 case XML_ROLE_INSTANCE_START:
4533#ifdef XML_DTD
4534 /* if there is no DOCTYPE declaration then now is the
4535 last chance to read the foreign DTD
4536 */
Elliott Hughes72472942018-01-10 08:36:10 -08004537 if (parser->m_useForeignDTD) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004538 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4539 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004540 if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004541 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004542 externalSubsetName,
4543 sizeof(ENTITY));
4544 if (!entity)
4545 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004546 entity->base = parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004547 dtd->paramEntityRead = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08004548 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004549 0,
4550 entity->base,
4551 entity->systemId,
4552 entity->publicId))
4553 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4554 if (dtd->paramEntityRead) {
4555 if (!dtd->standalone &&
Elliott Hughes72472942018-01-10 08:36:10 -08004556 parser->m_notStandaloneHandler &&
4557 !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004558 return XML_ERROR_NOT_STANDALONE;
4559 }
4560 /* if we didn't read the foreign DTD then this means that there
4561 is no external subset and we must reset dtd->hasParamEntityRefs
4562 */
4563 else
4564 dtd->hasParamEntityRefs = hadParamEntityRefs;
4565 /* end of DTD - no need to update dtd->keepProcessing */
4566 }
4567 }
4568#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004569 parser->m_processor = contentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004570 return contentProcessor(parser, s, end, nextPtr);
4571 case XML_ROLE_ATTLIST_ELEMENT_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004572 parser->m_declElementType = getElementType(parser, enc, s, next);
4573 if (!parser->m_declElementType)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004574 return XML_ERROR_NO_MEMORY;
4575 goto checkAttListDeclHandler;
4576 case XML_ROLE_ATTRIBUTE_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004577 parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
4578 if (!parser->m_declAttributeId)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004579 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004580 parser->m_declAttributeIsCdata = XML_FALSE;
4581 parser->m_declAttributeType = NULL;
4582 parser->m_declAttributeIsId = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004583 goto checkAttListDeclHandler;
4584 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
Elliott Hughes72472942018-01-10 08:36:10 -08004585 parser->m_declAttributeIsCdata = XML_TRUE;
4586 parser->m_declAttributeType = atypeCDATA;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004587 goto checkAttListDeclHandler;
4588 case XML_ROLE_ATTRIBUTE_TYPE_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004589 parser->m_declAttributeIsId = XML_TRUE;
4590 parser->m_declAttributeType = atypeID;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004591 goto checkAttListDeclHandler;
4592 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
Elliott Hughes72472942018-01-10 08:36:10 -08004593 parser->m_declAttributeType = atypeIDREF;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004594 goto checkAttListDeclHandler;
4595 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
Elliott Hughes72472942018-01-10 08:36:10 -08004596 parser->m_declAttributeType = atypeIDREFS;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004597 goto checkAttListDeclHandler;
4598 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
Elliott Hughes72472942018-01-10 08:36:10 -08004599 parser->m_declAttributeType = atypeENTITY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004600 goto checkAttListDeclHandler;
4601 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
Elliott Hughes72472942018-01-10 08:36:10 -08004602 parser->m_declAttributeType = atypeENTITIES;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004603 goto checkAttListDeclHandler;
4604 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
Elliott Hughes72472942018-01-10 08:36:10 -08004605 parser->m_declAttributeType = atypeNMTOKEN;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004606 goto checkAttListDeclHandler;
4607 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
Elliott Hughes72472942018-01-10 08:36:10 -08004608 parser->m_declAttributeType = atypeNMTOKENS;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004609 checkAttListDeclHandler:
Elliott Hughes72472942018-01-10 08:36:10 -08004610 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004611 handleDefault = XML_FALSE;
4612 break;
4613 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4614 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
Elliott Hughes72472942018-01-10 08:36:10 -08004615 if (dtd->keepProcessing && parser->m_attlistDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004616 const XML_Char *prefix;
Elliott Hughes72472942018-01-10 08:36:10 -08004617 if (parser->m_declAttributeType) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004618 prefix = enumValueSep;
4619 }
4620 else {
4621 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
4622 ? notationPrefix
4623 : enumValueStart);
4624 }
Elliott Hughes72472942018-01-10 08:36:10 -08004625 if (!poolAppendString(&parser->m_tempPool, prefix))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004626 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004627 if (!poolAppend(&parser->m_tempPool, enc, s, next))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004628 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004629 parser->m_declAttributeType = parser->m_tempPool.start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004630 handleDefault = XML_FALSE;
4631 }
4632 break;
4633 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4634 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4635 if (dtd->keepProcessing) {
Elliott Hughes72472942018-01-10 08:36:10 -08004636 if (!defineAttribute(parser->m_declElementType, parser->m_declAttributeId,
4637 parser->m_declAttributeIsCdata, parser->m_declAttributeIsId,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004638 0, parser))
4639 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004640 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
4641 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
4642 || (*parser->m_declAttributeType == XML_T(ASCII_N)
4643 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004644 /* Enumerated or Notation type */
Elliott Hughes72472942018-01-10 08:36:10 -08004645 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
4646 || !poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004647 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004648 parser->m_declAttributeType = parser->m_tempPool.start;
4649 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004650 }
4651 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004652 parser->m_attlistDeclHandler(parser->m_handlerArg, parser->m_declElementType->name,
4653 parser->m_declAttributeId->name, parser->m_declAttributeType,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004654 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
Elliott Hughes72472942018-01-10 08:36:10 -08004655 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004656 handleDefault = XML_FALSE;
4657 }
4658 }
4659 break;
4660 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4661 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4662 if (dtd->keepProcessing) {
4663 const XML_Char *attVal;
4664 enum XML_Error result =
Elliott Hughes72472942018-01-10 08:36:10 -08004665 storeAttributeValue(parser, enc, parser->m_declAttributeIsCdata,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004666 s + enc->minBytesPerChar,
4667 next - enc->minBytesPerChar,
4668 &dtd->pool);
4669 if (result)
4670 return result;
4671 attVal = poolStart(&dtd->pool);
4672 poolFinish(&dtd->pool);
4673 /* ID attributes aren't allowed to have a default */
Elliott Hughes72472942018-01-10 08:36:10 -08004674 if (!defineAttribute(parser->m_declElementType, parser->m_declAttributeId,
4675 parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004676 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004677 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
4678 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
4679 || (*parser->m_declAttributeType == XML_T(ASCII_N)
4680 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004681 /* Enumerated or Notation type */
Elliott Hughes72472942018-01-10 08:36:10 -08004682 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
4683 || !poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004684 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004685 parser->m_declAttributeType = parser->m_tempPool.start;
4686 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004687 }
4688 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004689 parser->m_attlistDeclHandler(parser->m_handlerArg, parser->m_declElementType->name,
4690 parser->m_declAttributeId->name, parser->m_declAttributeType,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004691 attVal,
4692 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
Elliott Hughes72472942018-01-10 08:36:10 -08004693 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004694 handleDefault = XML_FALSE;
4695 }
4696 }
4697 break;
4698 case XML_ROLE_ENTITY_VALUE:
4699 if (dtd->keepProcessing) {
4700 enum XML_Error result = storeEntityValue(parser, enc,
4701 s + enc->minBytesPerChar,
4702 next - enc->minBytesPerChar);
Elliott Hughes72472942018-01-10 08:36:10 -08004703 if (parser->m_declEntity) {
4704 parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
4705 parser->m_declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004706 poolFinish(&dtd->entityValuePool);
Elliott Hughes72472942018-01-10 08:36:10 -08004707 if (parser->m_entityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004708 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004709 parser->m_entityDeclHandler(parser->m_handlerArg,
4710 parser->m_declEntity->name,
4711 parser->m_declEntity->is_param,
4712 parser->m_declEntity->textPtr,
4713 parser->m_declEntity->textLen,
4714 parser->m_curBase, 0, 0, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004715 handleDefault = XML_FALSE;
4716 }
4717 }
4718 else
4719 poolDiscard(&dtd->entityValuePool);
4720 if (result != XML_ERROR_NONE)
4721 return result;
4722 }
4723 break;
4724 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4725#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004726 parser->m_useForeignDTD = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004727#endif /* XML_DTD */
4728 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004729 if (parser->m_startDoctypeDeclHandler) {
4730 parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004731 s + enc->minBytesPerChar,
4732 next - enc->minBytesPerChar);
Elliott Hughes72472942018-01-10 08:36:10 -08004733 if (parser->m_doctypeSysid == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004734 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004735 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004736 handleDefault = XML_FALSE;
4737 }
4738#ifdef XML_DTD
4739 else
Elliott Hughes72472942018-01-10 08:36:10 -08004740 /* use externalSubsetName to make parser->m_doctypeSysid non-NULL
4741 for the case where no parser->m_startDoctypeDeclHandler is set */
4742 parser->m_doctypeSysid = externalSubsetName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004743#endif /* XML_DTD */
4744 if (!dtd->standalone
4745#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004746 && !parser->m_paramEntityParsing
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004747#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004748 && parser->m_notStandaloneHandler
4749 && !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004750 return XML_ERROR_NOT_STANDALONE;
4751#ifndef XML_DTD
4752 break;
4753#else /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004754 if (!parser->m_declEntity) {
4755 parser->m_declEntity = (ENTITY *)lookup(parser,
Elliott Hughes35e432d2012-09-09 14:23:38 -07004756 &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004757 externalSubsetName,
4758 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004759 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004760 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004761 parser->m_declEntity->publicId = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004762 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004763#endif /* XML_DTD */
Elliott Hughesaaec48e2018-08-16 16:29:01 -07004764 /* fall through */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004765 case XML_ROLE_ENTITY_SYSTEM_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004766 if (dtd->keepProcessing && parser->m_declEntity) {
4767 parser->m_declEntity->systemId = poolStoreString(&dtd->pool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004768 s + enc->minBytesPerChar,
4769 next - enc->minBytesPerChar);
Elliott Hughes72472942018-01-10 08:36:10 -08004770 if (!parser->m_declEntity->systemId)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004771 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004772 parser->m_declEntity->base = parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004773 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004774 /* Don't suppress the default handler if we fell through from
4775 * the XML_ROLE_DOCTYPE_SYSTEM_ID case.
4776 */
4777 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004778 handleDefault = XML_FALSE;
4779 }
4780 break;
4781 case XML_ROLE_ENTITY_COMPLETE:
Elliott Hughes72472942018-01-10 08:36:10 -08004782 if (dtd->keepProcessing && parser->m_declEntity && parser->m_entityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004783 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004784 parser->m_entityDeclHandler(parser->m_handlerArg,
4785 parser->m_declEntity->name,
4786 parser->m_declEntity->is_param,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004787 0,0,
Elliott Hughes72472942018-01-10 08:36:10 -08004788 parser->m_declEntity->base,
4789 parser->m_declEntity->systemId,
4790 parser->m_declEntity->publicId,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004791 0);
4792 handleDefault = XML_FALSE;
4793 }
4794 break;
4795 case XML_ROLE_ENTITY_NOTATION_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004796 if (dtd->keepProcessing && parser->m_declEntity) {
4797 parser->m_declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4798 if (!parser->m_declEntity->notation)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004799 return XML_ERROR_NO_MEMORY;
4800 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004801 if (parser->m_unparsedEntityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004802 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004803 parser->m_unparsedEntityDeclHandler(parser->m_handlerArg,
4804 parser->m_declEntity->name,
4805 parser->m_declEntity->base,
4806 parser->m_declEntity->systemId,
4807 parser->m_declEntity->publicId,
4808 parser->m_declEntity->notation);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004809 handleDefault = XML_FALSE;
4810 }
Elliott Hughes72472942018-01-10 08:36:10 -08004811 else if (parser->m_entityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004812 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004813 parser->m_entityDeclHandler(parser->m_handlerArg,
4814 parser->m_declEntity->name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004815 0,0,0,
Elliott Hughes72472942018-01-10 08:36:10 -08004816 parser->m_declEntity->base,
4817 parser->m_declEntity->systemId,
4818 parser->m_declEntity->publicId,
4819 parser->m_declEntity->notation);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004820 handleDefault = XML_FALSE;
4821 }
4822 }
4823 break;
4824 case XML_ROLE_GENERAL_ENTITY_NAME:
4825 {
4826 if (XmlPredefinedEntityName(enc, s, next)) {
Elliott Hughes72472942018-01-10 08:36:10 -08004827 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004828 break;
4829 }
4830 if (dtd->keepProcessing) {
4831 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4832 if (!name)
4833 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004834 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004835 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004836 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004837 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004838 if (parser->m_declEntity->name != name) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004839 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004840 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004841 }
4842 else {
4843 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004844 parser->m_declEntity->publicId = NULL;
4845 parser->m_declEntity->is_param = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004846 /* if we have a parent parser or are reading an internal parameter
4847 entity, then the entity declaration is not considered "internal"
4848 */
Elliott Hughes72472942018-01-10 08:36:10 -08004849 parser->m_declEntity->is_internal = !(parser->m_parentParser || parser->m_openInternalEntities);
4850 if (parser->m_entityDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004851 handleDefault = XML_FALSE;
4852 }
4853 }
4854 else {
4855 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004856 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004857 }
4858 }
4859 break;
4860 case XML_ROLE_PARAM_ENTITY_NAME:
4861#ifdef XML_DTD
4862 if (dtd->keepProcessing) {
4863 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4864 if (!name)
4865 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004866 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004867 name, sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004868 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004869 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004870 if (parser->m_declEntity->name != name) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004871 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004872 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004873 }
4874 else {
4875 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004876 parser->m_declEntity->publicId = NULL;
4877 parser->m_declEntity->is_param = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004878 /* if we have a parent parser or are reading an internal parameter
4879 entity, then the entity declaration is not considered "internal"
4880 */
Elliott Hughes72472942018-01-10 08:36:10 -08004881 parser->m_declEntity->is_internal = !(parser->m_parentParser || parser->m_openInternalEntities);
4882 if (parser->m_entityDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004883 handleDefault = XML_FALSE;
4884 }
4885 }
4886 else {
4887 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004888 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004889 }
4890#else /* not XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004891 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004892#endif /* XML_DTD */
4893 break;
4894 case XML_ROLE_NOTATION_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004895 parser->m_declNotationPublicId = NULL;
4896 parser->m_declNotationName = NULL;
4897 if (parser->m_notationDeclHandler) {
4898 parser->m_declNotationName = poolStoreString(&parser->m_tempPool, enc, s, next);
4899 if (!parser->m_declNotationName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004900 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004901 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004902 handleDefault = XML_FALSE;
4903 }
4904 break;
4905 case XML_ROLE_NOTATION_PUBLIC_ID:
4906 if (!XmlIsPublicId(enc, s, next, eventPP))
4907 return XML_ERROR_PUBLICID;
Elliott Hughes72472942018-01-10 08:36:10 -08004908 if (parser->m_declNotationName) { /* means m_notationDeclHandler != NULL */
4909 XML_Char *tem = poolStoreString(&parser->m_tempPool,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004910 enc,
4911 s + enc->minBytesPerChar,
4912 next - enc->minBytesPerChar);
4913 if (!tem)
4914 return XML_ERROR_NO_MEMORY;
4915 normalizePublicId(tem);
Elliott Hughes72472942018-01-10 08:36:10 -08004916 parser->m_declNotationPublicId = tem;
4917 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004918 handleDefault = XML_FALSE;
4919 }
4920 break;
4921 case XML_ROLE_NOTATION_SYSTEM_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004922 if (parser->m_declNotationName && parser->m_notationDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004923 const XML_Char *systemId
Elliott Hughes72472942018-01-10 08:36:10 -08004924 = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004925 s + enc->minBytesPerChar,
4926 next - enc->minBytesPerChar);
4927 if (!systemId)
4928 return XML_ERROR_NO_MEMORY;
4929 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004930 parser->m_notationDeclHandler(parser->m_handlerArg,
4931 parser->m_declNotationName,
4932 parser->m_curBase,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004933 systemId,
Elliott Hughes72472942018-01-10 08:36:10 -08004934 parser->m_declNotationPublicId);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004935 handleDefault = XML_FALSE;
4936 }
Elliott Hughes72472942018-01-10 08:36:10 -08004937 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004938 break;
4939 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004940 if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004941 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004942 parser->m_notationDeclHandler(parser->m_handlerArg,
4943 parser->m_declNotationName,
4944 parser->m_curBase,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004945 0,
Elliott Hughes72472942018-01-10 08:36:10 -08004946 parser->m_declNotationPublicId);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004947 handleDefault = XML_FALSE;
4948 }
Elliott Hughes72472942018-01-10 08:36:10 -08004949 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004950 break;
4951 case XML_ROLE_ERROR:
4952 switch (tok) {
4953 case XML_TOK_PARAM_ENTITY_REF:
4954 /* PE references in internal subset are
Elliott Hughes35e432d2012-09-09 14:23:38 -07004955 not allowed within declarations. */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004956 return XML_ERROR_PARAM_ENTITY_REF;
4957 case XML_TOK_XML_DECL:
4958 return XML_ERROR_MISPLACED_XML_PI;
4959 default:
4960 return XML_ERROR_SYNTAX;
4961 }
4962#ifdef XML_DTD
4963 case XML_ROLE_IGNORE_SECT:
4964 {
4965 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08004966 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004967 reportDefault(parser, enc, s, next);
4968 handleDefault = XML_FALSE;
4969 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4970 if (result != XML_ERROR_NONE)
4971 return result;
4972 else if (!next) {
Elliott Hughes72472942018-01-10 08:36:10 -08004973 parser->m_processor = ignoreSectionProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004974 return result;
4975 }
4976 }
4977 break;
4978#endif /* XML_DTD */
4979 case XML_ROLE_GROUP_OPEN:
Elliott Hughes72472942018-01-10 08:36:10 -08004980 if (parser->m_prologState.level >= parser->m_groupSize) {
4981 if (parser->m_groupSize) {
4982 char *temp = (char *)REALLOC(parser, parser->m_groupConnector, parser->m_groupSize *= 2);
4983 if (temp == NULL) {
4984 parser->m_groupSize /= 2;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004985 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004986 }
4987 parser->m_groupConnector = temp;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004988 if (dtd->scaffIndex) {
Elliott Hughes72472942018-01-10 08:36:10 -08004989 int *temp = (int *)REALLOC(parser, dtd->scaffIndex,
4990 parser->m_groupSize * sizeof(int));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004991 if (temp == NULL)
4992 return XML_ERROR_NO_MEMORY;
4993 dtd->scaffIndex = temp;
4994 }
4995 }
4996 else {
Elliott Hughes72472942018-01-10 08:36:10 -08004997 parser->m_groupConnector = (char *)MALLOC(parser, parser->m_groupSize = 32);
4998 if (!parser->m_groupConnector) {
4999 parser->m_groupSize = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005000 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08005001 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005002 }
5003 }
Elliott Hughes72472942018-01-10 08:36:10 -08005004 parser->m_groupConnector[parser->m_prologState.level] = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005005 if (dtd->in_eldecl) {
5006 int myindex = nextScaffoldPart(parser);
5007 if (myindex < 0)
5008 return XML_ERROR_NO_MEMORY;
5009 dtd->scaffIndex[dtd->scaffLevel] = myindex;
5010 dtd->scaffLevel++;
5011 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
Elliott Hughes72472942018-01-10 08:36:10 -08005012 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005013 handleDefault = XML_FALSE;
5014 }
5015 break;
5016 case XML_ROLE_GROUP_SEQUENCE:
Elliott Hughes72472942018-01-10 08:36:10 -08005017 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005018 return XML_ERROR_SYNTAX;
Elliott Hughes72472942018-01-10 08:36:10 -08005019 parser->m_groupConnector[parser->m_prologState.level] = ASCII_COMMA;
5020 if (dtd->in_eldecl && parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005021 handleDefault = XML_FALSE;
5022 break;
5023 case XML_ROLE_GROUP_CHOICE:
Elliott Hughes72472942018-01-10 08:36:10 -08005024 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005025 return XML_ERROR_SYNTAX;
5026 if (dtd->in_eldecl
Elliott Hughes72472942018-01-10 08:36:10 -08005027 && !parser->m_groupConnector[parser->m_prologState.level]
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005028 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5029 != XML_CTYPE_MIXED)
5030 ) {
5031 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5032 = XML_CTYPE_CHOICE;
Elliott Hughes72472942018-01-10 08:36:10 -08005033 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005034 handleDefault = XML_FALSE;
5035 }
Elliott Hughes72472942018-01-10 08:36:10 -08005036 parser->m_groupConnector[parser->m_prologState.level] = ASCII_PIPE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005037 break;
5038 case XML_ROLE_PARAM_ENTITY_REF:
5039#ifdef XML_DTD
5040 case XML_ROLE_INNER_PARAM_ENTITY_REF:
5041 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005042 if (!parser->m_paramEntityParsing)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005043 dtd->keepProcessing = dtd->standalone;
5044 else {
5045 const XML_Char *name;
5046 ENTITY *entity;
5047 name = poolStoreString(&dtd->pool, enc,
5048 s + enc->minBytesPerChar,
5049 next - enc->minBytesPerChar);
5050 if (!name)
5051 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005052 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005053 poolDiscard(&dtd->pool);
5054 /* first, determine if a check for an existing declaration is needed;
5055 if yes, check that the entity exists, and that it is internal,
5056 otherwise call the skipped entity handler
5057 */
Elliott Hughes72472942018-01-10 08:36:10 -08005058 if (parser->m_prologState.documentEntity &&
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005059 (dtd->standalone
Elliott Hughes72472942018-01-10 08:36:10 -08005060 ? !parser->m_openInternalEntities
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005061 : !dtd->hasParamEntityRefs)) {
5062 if (!entity)
5063 return XML_ERROR_UNDEFINED_ENTITY;
Elliott Hughes72472942018-01-10 08:36:10 -08005064 else if (!entity->is_internal) {
5065 /* It's hard to exhaustively search the code to be sure,
5066 * but there doesn't seem to be a way of executing the
5067 * following line. There are two cases:
5068 *
5069 * If 'standalone' is false, the DTD must have no
5070 * parameter entities or we wouldn't have passed the outer
5071 * 'if' statement. That measn the only entity in the hash
5072 * table is the external subset name "#" which cannot be
5073 * given as a parameter entity name in XML syntax, so the
5074 * lookup must have returned NULL and we don't even reach
5075 * the test for an internal entity.
5076 *
5077 * If 'standalone' is true, it does not seem to be
5078 * possible to create entities taking this code path that
5079 * are not internal entities, so fail the test above.
5080 *
5081 * Because this analysis is very uncertain, the code is
5082 * being left in place and merely removed from the
5083 * coverage test statistics.
5084 */
5085 return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
5086 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005087 }
5088 else if (!entity) {
5089 dtd->keepProcessing = dtd->standalone;
5090 /* cannot report skipped entities in declarations */
Elliott Hughes72472942018-01-10 08:36:10 -08005091 if ((role == XML_ROLE_PARAM_ENTITY_REF) && parser->m_skippedEntityHandler) {
5092 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005093 handleDefault = XML_FALSE;
5094 }
5095 break;
5096 }
5097 if (entity->open)
5098 return XML_ERROR_RECURSIVE_ENTITY_REF;
5099 if (entity->textPtr) {
5100 enum XML_Error result;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005101 XML_Bool betweenDecl =
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005102 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
5103 result = processInternalEntity(parser, entity, betweenDecl);
5104 if (result != XML_ERROR_NONE)
5105 return result;
5106 handleDefault = XML_FALSE;
5107 break;
5108 }
Elliott Hughes72472942018-01-10 08:36:10 -08005109 if (parser->m_externalEntityRefHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005110 dtd->paramEntityRead = XML_FALSE;
5111 entity->open = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005112 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005113 0,
5114 entity->base,
5115 entity->systemId,
5116 entity->publicId)) {
5117 entity->open = XML_FALSE;
5118 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5119 }
5120 entity->open = XML_FALSE;
5121 handleDefault = XML_FALSE;
5122 if (!dtd->paramEntityRead) {
5123 dtd->keepProcessing = dtd->standalone;
5124 break;
5125 }
5126 }
5127 else {
5128 dtd->keepProcessing = dtd->standalone;
5129 break;
5130 }
5131 }
5132#endif /* XML_DTD */
5133 if (!dtd->standalone &&
Elliott Hughes72472942018-01-10 08:36:10 -08005134 parser->m_notStandaloneHandler &&
5135 !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005136 return XML_ERROR_NOT_STANDALONE;
5137 break;
5138
5139 /* Element declaration stuff */
5140
5141 case XML_ROLE_ELEMENT_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08005142 if (parser->m_elementDeclHandler) {
5143 parser->m_declElementType = getElementType(parser, enc, s, next);
5144 if (!parser->m_declElementType)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005145 return XML_ERROR_NO_MEMORY;
5146 dtd->scaffLevel = 0;
5147 dtd->scaffCount = 0;
5148 dtd->in_eldecl = XML_TRUE;
5149 handleDefault = XML_FALSE;
5150 }
5151 break;
5152
5153 case XML_ROLE_CONTENT_ANY:
5154 case XML_ROLE_CONTENT_EMPTY:
5155 if (dtd->in_eldecl) {
Elliott Hughes72472942018-01-10 08:36:10 -08005156 if (parser->m_elementDeclHandler) {
5157 XML_Content * content = (XML_Content *) MALLOC(parser, sizeof(XML_Content));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005158 if (!content)
5159 return XML_ERROR_NO_MEMORY;
5160 content->quant = XML_CQUANT_NONE;
5161 content->name = NULL;
5162 content->numchildren = 0;
5163 content->children = NULL;
5164 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
5165 XML_CTYPE_ANY :
5166 XML_CTYPE_EMPTY);
5167 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08005168 parser->m_elementDeclHandler(parser->m_handlerArg, parser->m_declElementType->name, content);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005169 handleDefault = XML_FALSE;
5170 }
5171 dtd->in_eldecl = XML_FALSE;
5172 }
5173 break;
5174
5175 case XML_ROLE_CONTENT_PCDATA:
5176 if (dtd->in_eldecl) {
5177 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5178 = XML_CTYPE_MIXED;
Elliott Hughes72472942018-01-10 08:36:10 -08005179 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005180 handleDefault = XML_FALSE;
5181 }
5182 break;
5183
5184 case XML_ROLE_CONTENT_ELEMENT:
5185 quant = XML_CQUANT_NONE;
5186 goto elementContent;
5187 case XML_ROLE_CONTENT_ELEMENT_OPT:
5188 quant = XML_CQUANT_OPT;
5189 goto elementContent;
5190 case XML_ROLE_CONTENT_ELEMENT_REP:
5191 quant = XML_CQUANT_REP;
5192 goto elementContent;
5193 case XML_ROLE_CONTENT_ELEMENT_PLUS:
5194 quant = XML_CQUANT_PLUS;
5195 elementContent:
5196 if (dtd->in_eldecl) {
5197 ELEMENT_TYPE *el;
5198 const XML_Char *name;
5199 int nameLen;
5200 const char *nxt = (quant == XML_CQUANT_NONE
5201 ? next
5202 : next - enc->minBytesPerChar);
5203 int myindex = nextScaffoldPart(parser);
5204 if (myindex < 0)
5205 return XML_ERROR_NO_MEMORY;
5206 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
5207 dtd->scaffold[myindex].quant = quant;
5208 el = getElementType(parser, enc, s, nxt);
5209 if (!el)
5210 return XML_ERROR_NO_MEMORY;
5211 name = el->name;
5212 dtd->scaffold[myindex].name = name;
5213 nameLen = 0;
5214 for (; name[nameLen++]; );
5215 dtd->contentStringLen += nameLen;
Elliott Hughes72472942018-01-10 08:36:10 -08005216 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005217 handleDefault = XML_FALSE;
5218 }
5219 break;
5220
5221 case XML_ROLE_GROUP_CLOSE:
5222 quant = XML_CQUANT_NONE;
5223 goto closeGroup;
5224 case XML_ROLE_GROUP_CLOSE_OPT:
5225 quant = XML_CQUANT_OPT;
5226 goto closeGroup;
5227 case XML_ROLE_GROUP_CLOSE_REP:
5228 quant = XML_CQUANT_REP;
5229 goto closeGroup;
5230 case XML_ROLE_GROUP_CLOSE_PLUS:
5231 quant = XML_CQUANT_PLUS;
5232 closeGroup:
5233 if (dtd->in_eldecl) {
Elliott Hughes72472942018-01-10 08:36:10 -08005234 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005235 handleDefault = XML_FALSE;
5236 dtd->scaffLevel--;
5237 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
5238 if (dtd->scaffLevel == 0) {
5239 if (!handleDefault) {
5240 XML_Content *model = build_model(parser);
5241 if (!model)
5242 return XML_ERROR_NO_MEMORY;
5243 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08005244 parser->m_elementDeclHandler(parser->m_handlerArg, parser->m_declElementType->name, model);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005245 }
5246 dtd->in_eldecl = XML_FALSE;
5247 dtd->contentStringLen = 0;
5248 }
5249 }
5250 break;
5251 /* End element declaration stuff */
5252
5253 case XML_ROLE_PI:
5254 if (!reportProcessingInstruction(parser, enc, s, next))
5255 return XML_ERROR_NO_MEMORY;
5256 handleDefault = XML_FALSE;
5257 break;
5258 case XML_ROLE_COMMENT:
5259 if (!reportComment(parser, enc, s, next))
5260 return XML_ERROR_NO_MEMORY;
5261 handleDefault = XML_FALSE;
5262 break;
5263 case XML_ROLE_NONE:
5264 switch (tok) {
5265 case XML_TOK_BOM:
5266 handleDefault = XML_FALSE;
5267 break;
5268 }
5269 break;
5270 case XML_ROLE_DOCTYPE_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005271 if (parser->m_startDoctypeDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005272 handleDefault = XML_FALSE;
5273 break;
5274 case XML_ROLE_ENTITY_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005275 if (dtd->keepProcessing && parser->m_entityDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005276 handleDefault = XML_FALSE;
5277 break;
5278 case XML_ROLE_NOTATION_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005279 if (parser->m_notationDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005280 handleDefault = XML_FALSE;
5281 break;
5282 case XML_ROLE_ATTLIST_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005283 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005284 handleDefault = XML_FALSE;
5285 break;
5286 case XML_ROLE_ELEMENT_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005287 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005288 handleDefault = XML_FALSE;
5289 break;
5290 } /* end of big switch */
5291
Elliott Hughes72472942018-01-10 08:36:10 -08005292 if (handleDefault && parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005293 reportDefault(parser, enc, s, next);
5294
Elliott Hughes72472942018-01-10 08:36:10 -08005295 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07005296 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005297 *nextPtr = next;
5298 return XML_ERROR_NONE;
5299 case XML_FINISHED:
5300 return XML_ERROR_ABORTED;
5301 default:
5302 s = next;
5303 tok = XmlPrologTok(enc, s, end, &next);
5304 }
5305 }
5306 /* not reached */
5307}
5308
5309static enum XML_Error PTRCALL
5310epilogProcessor(XML_Parser parser,
5311 const char *s,
5312 const char *end,
5313 const char **nextPtr)
5314{
Elliott Hughes72472942018-01-10 08:36:10 -08005315 parser->m_processor = epilogProcessor;
5316 parser->m_eventPtr = s;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005317 for (;;) {
5318 const char *next = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08005319 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5320 parser->m_eventEndPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005321 switch (tok) {
5322 /* report partial linebreak - it might be the last token */
5323 case -XML_TOK_PROLOG_S:
Elliott Hughes72472942018-01-10 08:36:10 -08005324 if (parser->m_defaultHandler) {
5325 reportDefault(parser, parser->m_encoding, s, next);
5326 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005327 return XML_ERROR_ABORTED;
5328 }
5329 *nextPtr = next;
5330 return XML_ERROR_NONE;
5331 case XML_TOK_NONE:
5332 *nextPtr = s;
5333 return XML_ERROR_NONE;
5334 case XML_TOK_PROLOG_S:
Elliott Hughes72472942018-01-10 08:36:10 -08005335 if (parser->m_defaultHandler)
5336 reportDefault(parser, parser->m_encoding, s, next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005337 break;
5338 case XML_TOK_PI:
Elliott Hughes72472942018-01-10 08:36:10 -08005339 if (!reportProcessingInstruction(parser, parser->m_encoding, s, next))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005340 return XML_ERROR_NO_MEMORY;
5341 break;
5342 case XML_TOK_COMMENT:
Elliott Hughes72472942018-01-10 08:36:10 -08005343 if (!reportComment(parser, parser->m_encoding, s, next))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005344 return XML_ERROR_NO_MEMORY;
5345 break;
5346 case XML_TOK_INVALID:
Elliott Hughes72472942018-01-10 08:36:10 -08005347 parser->m_eventPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005348 return XML_ERROR_INVALID_TOKEN;
5349 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08005350 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005351 *nextPtr = s;
5352 return XML_ERROR_NONE;
5353 }
5354 return XML_ERROR_UNCLOSED_TOKEN;
5355 case XML_TOK_PARTIAL_CHAR:
Elliott Hughes72472942018-01-10 08:36:10 -08005356 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005357 *nextPtr = s;
5358 return XML_ERROR_NONE;
5359 }
5360 return XML_ERROR_PARTIAL_CHAR;
5361 default:
5362 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
5363 }
Elliott Hughes72472942018-01-10 08:36:10 -08005364 parser->m_eventPtr = s = next;
5365 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07005366 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005367 *nextPtr = next;
5368 return XML_ERROR_NONE;
5369 case XML_FINISHED:
5370 return XML_ERROR_ABORTED;
5371 default: ;
5372 }
5373 }
5374}
5375
5376static enum XML_Error
5377processInternalEntity(XML_Parser parser, ENTITY *entity,
5378 XML_Bool betweenDecl)
5379{
5380 const char *textStart, *textEnd;
5381 const char *next;
5382 enum XML_Error result;
5383 OPEN_INTERNAL_ENTITY *openEntity;
5384
Elliott Hughes72472942018-01-10 08:36:10 -08005385 if (parser->m_freeInternalEntities) {
5386 openEntity = parser->m_freeInternalEntities;
5387 parser->m_freeInternalEntities = openEntity->next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005388 }
5389 else {
Elliott Hughes72472942018-01-10 08:36:10 -08005390 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005391 if (!openEntity)
5392 return XML_ERROR_NO_MEMORY;
5393 }
5394 entity->open = XML_TRUE;
5395 entity->processed = 0;
Elliott Hughes72472942018-01-10 08:36:10 -08005396 openEntity->next = parser->m_openInternalEntities;
5397 parser->m_openInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005398 openEntity->entity = entity;
Elliott Hughes72472942018-01-10 08:36:10 -08005399 openEntity->startTagLevel = parser->m_tagLevel;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005400 openEntity->betweenDecl = betweenDecl;
5401 openEntity->internalEventPtr = NULL;
5402 openEntity->internalEventEndPtr = NULL;
5403 textStart = (char *)entity->textPtr;
5404 textEnd = (char *)(entity->textPtr + entity->textLen);
Elliott Hughes72472942018-01-10 08:36:10 -08005405 /* Set a safe default value in case 'next' does not get set */
5406 next = textStart;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005407
5408#ifdef XML_DTD
5409 if (entity->is_param) {
Elliott Hughes72472942018-01-10 08:36:10 -08005410 int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5411 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005412 next, &next, XML_FALSE);
5413 }
Elliott Hughes35e432d2012-09-09 14:23:38 -07005414 else
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005415#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08005416 result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding, textStart,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005417 textEnd, &next, XML_FALSE);
5418
5419 if (result == XML_ERROR_NONE) {
Elliott Hughes72472942018-01-10 08:36:10 -08005420 if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005421 entity->processed = (int)(next - textStart);
Elliott Hughes72472942018-01-10 08:36:10 -08005422 parser->m_processor = internalEntityProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005423 }
5424 else {
5425 entity->open = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08005426 parser->m_openInternalEntities = openEntity->next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005427 /* put openEntity back in list of free instances */
Elliott Hughes72472942018-01-10 08:36:10 -08005428 openEntity->next = parser->m_freeInternalEntities;
5429 parser->m_freeInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005430 }
5431 }
5432 return result;
5433}
5434
5435static enum XML_Error PTRCALL
5436internalEntityProcessor(XML_Parser parser,
5437 const char *s,
5438 const char *end,
5439 const char **nextPtr)
5440{
5441 ENTITY *entity;
5442 const char *textStart, *textEnd;
5443 const char *next;
5444 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08005445 OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005446 if (!openEntity)
5447 return XML_ERROR_UNEXPECTED_STATE;
5448
5449 entity = openEntity->entity;
5450 textStart = ((char *)entity->textPtr) + entity->processed;
5451 textEnd = (char *)(entity->textPtr + entity->textLen);
Elliott Hughes72472942018-01-10 08:36:10 -08005452 /* Set a safe default value in case 'next' does not get set */
5453 next = textStart;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005454
5455#ifdef XML_DTD
5456 if (entity->is_param) {
Elliott Hughes72472942018-01-10 08:36:10 -08005457 int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5458 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005459 next, &next, XML_FALSE);
5460 }
5461 else
5462#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08005463 result = doContent(parser, openEntity->startTagLevel, parser->m_internalEncoding,
Elliott Hughes35e432d2012-09-09 14:23:38 -07005464 textStart, textEnd, &next, XML_FALSE);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005465
5466 if (result != XML_ERROR_NONE)
5467 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08005468 else if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005469 entity->processed = (int)(next - (char *)entity->textPtr);
5470 return result;
5471 }
5472 else {
5473 entity->open = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08005474 parser->m_openInternalEntities = openEntity->next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005475 /* put openEntity back in list of free instances */
Elliott Hughes72472942018-01-10 08:36:10 -08005476 openEntity->next = parser->m_freeInternalEntities;
5477 parser->m_freeInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005478 }
5479
5480#ifdef XML_DTD
5481 if (entity->is_param) {
5482 int tok;
Elliott Hughes72472942018-01-10 08:36:10 -08005483 parser->m_processor = prologProcessor;
5484 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5485 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
5486 (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005487 }
5488 else
5489#endif /* XML_DTD */
5490 {
Elliott Hughes72472942018-01-10 08:36:10 -08005491 parser->m_processor = contentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005492 /* see externalEntityContentProcessor vs contentProcessor */
Elliott Hughes72472942018-01-10 08:36:10 -08005493 return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, s, end,
5494 nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
Elliott Hughes35e432d2012-09-09 14:23:38 -07005495 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005496}
5497
5498static enum XML_Error PTRCALL
5499errorProcessor(XML_Parser parser,
Paul Duffinba34a0c2017-02-27 14:40:16 +00005500 const char *UNUSED_P(s),
5501 const char *UNUSED_P(end),
5502 const char **UNUSED_P(nextPtr))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005503{
Elliott Hughes72472942018-01-10 08:36:10 -08005504 return parser->m_errorCode;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005505}
5506
5507static enum XML_Error
5508storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5509 const char *ptr, const char *end,
5510 STRING_POOL *pool)
5511{
5512 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
5513 end, pool);
5514 if (result)
5515 return result;
5516 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
5517 poolChop(pool);
5518 if (!poolAppendChar(pool, XML_T('\0')))
5519 return XML_ERROR_NO_MEMORY;
5520 return XML_ERROR_NONE;
5521}
5522
5523static enum XML_Error
5524appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5525 const char *ptr, const char *end,
5526 STRING_POOL *pool)
5527{
Elliott Hughes72472942018-01-10 08:36:10 -08005528 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005529 for (;;) {
5530 const char *next;
5531 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
5532 switch (tok) {
5533 case XML_TOK_NONE:
5534 return XML_ERROR_NONE;
5535 case XML_TOK_INVALID:
Elliott Hughes72472942018-01-10 08:36:10 -08005536 if (enc == parser->m_encoding)
5537 parser->m_eventPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005538 return XML_ERROR_INVALID_TOKEN;
5539 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08005540 if (enc == parser->m_encoding)
5541 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005542 return XML_ERROR_INVALID_TOKEN;
5543 case XML_TOK_CHAR_REF:
5544 {
5545 XML_Char buf[XML_ENCODE_MAX];
5546 int i;
5547 int n = XmlCharRefNumber(enc, ptr);
5548 if (n < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08005549 if (enc == parser->m_encoding)
5550 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005551 return XML_ERROR_BAD_CHAR_REF;
5552 }
5553 if (!isCdata
5554 && n == 0x20 /* space */
5555 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5556 break;
5557 n = XmlEncode(n, (ICHAR *)buf);
Elliott Hughes72472942018-01-10 08:36:10 -08005558 /* The XmlEncode() functions can never return 0 here. That
5559 * error return happens if the code point passed in is either
5560 * negative or greater than or equal to 0x110000. The
5561 * XmlCharRefNumber() functions will all return a number
5562 * strictly less than 0x110000 or a negative value if an error
5563 * occurred. The negative value is intercepted above, so
5564 * XmlEncode() is never passed a value it might return an
5565 * error for.
5566 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005567 for (i = 0; i < n; i++) {
5568 if (!poolAppendChar(pool, buf[i]))
5569 return XML_ERROR_NO_MEMORY;
5570 }
5571 }
5572 break;
5573 case XML_TOK_DATA_CHARS:
5574 if (!poolAppend(pool, enc, ptr, next))
5575 return XML_ERROR_NO_MEMORY;
5576 break;
5577 case XML_TOK_TRAILING_CR:
5578 next = ptr + enc->minBytesPerChar;
5579 /* fall through */
5580 case XML_TOK_ATTRIBUTE_VALUE_S:
5581 case XML_TOK_DATA_NEWLINE:
5582 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5583 break;
5584 if (!poolAppendChar(pool, 0x20))
5585 return XML_ERROR_NO_MEMORY;
5586 break;
5587 case XML_TOK_ENTITY_REF:
5588 {
5589 const XML_Char *name;
5590 ENTITY *entity;
5591 char checkEntityDecl;
5592 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
5593 ptr + enc->minBytesPerChar,
5594 next - enc->minBytesPerChar);
5595 if (ch) {
5596 if (!poolAppendChar(pool, ch))
5597 return XML_ERROR_NO_MEMORY;
5598 break;
5599 }
Elliott Hughes72472942018-01-10 08:36:10 -08005600 name = poolStoreString(&parser->m_temp2Pool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005601 ptr + enc->minBytesPerChar,
5602 next - enc->minBytesPerChar);
5603 if (!name)
5604 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005605 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
Elliott Hughes72472942018-01-10 08:36:10 -08005606 poolDiscard(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005607 /* First, determine if a check for an existing declaration is needed;
5608 if yes, check that the entity exists, and that it is internal.
5609 */
5610 if (pool == &dtd->pool) /* are we called from prolog? */
5611 checkEntityDecl =
5612#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005613 parser->m_prologState.documentEntity &&
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005614#endif /* XML_DTD */
5615 (dtd->standalone
Elliott Hughes72472942018-01-10 08:36:10 -08005616 ? !parser->m_openInternalEntities
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005617 : !dtd->hasParamEntityRefs);
Elliott Hughes72472942018-01-10 08:36:10 -08005618 else /* if (pool == &parser->m_tempPool): we are called from content */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005619 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
5620 if (checkEntityDecl) {
5621 if (!entity)
5622 return XML_ERROR_UNDEFINED_ENTITY;
5623 else if (!entity->is_internal)
5624 return XML_ERROR_ENTITY_DECLARED_IN_PE;
5625 }
5626 else if (!entity) {
5627 /* Cannot report skipped entity here - see comments on
Elliott Hughes72472942018-01-10 08:36:10 -08005628 parser->m_skippedEntityHandler.
5629 if (parser->m_skippedEntityHandler)
5630 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005631 */
5632 /* Cannot call the default handler because this would be
5633 out of sync with the call to the startElementHandler.
Elliott Hughes72472942018-01-10 08:36:10 -08005634 if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005635 reportDefault(parser, enc, ptr, next);
5636 */
5637 break;
5638 }
5639 if (entity->open) {
Elliott Hughes72472942018-01-10 08:36:10 -08005640 if (enc == parser->m_encoding) {
5641 /* It does not appear that this line can be executed.
5642 *
5643 * The "if (entity->open)" check catches recursive entity
5644 * definitions. In order to be called with an open
5645 * entity, it must have gone through this code before and
5646 * been through the recursive call to
5647 * appendAttributeValue() some lines below. That call
5648 * sets the local encoding ("enc") to the parser's
5649 * internal encoding (internal_utf8 or internal_utf16),
5650 * which can never be the same as the principle encoding.
5651 * It doesn't appear there is another code path that gets
5652 * here with entity->open being TRUE.
5653 *
5654 * Since it is not certain that this logic is watertight,
5655 * we keep the line and merely exclude it from coverage
5656 * tests.
5657 */
5658 parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
5659 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005660 return XML_ERROR_RECURSIVE_ENTITY_REF;
5661 }
5662 if (entity->notation) {
Elliott Hughes72472942018-01-10 08:36:10 -08005663 if (enc == parser->m_encoding)
5664 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005665 return XML_ERROR_BINARY_ENTITY_REF;
5666 }
5667 if (!entity->textPtr) {
Elliott Hughes72472942018-01-10 08:36:10 -08005668 if (enc == parser->m_encoding)
5669 parser->m_eventPtr = ptr;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005670 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005671 }
5672 else {
5673 enum XML_Error result;
5674 const XML_Char *textEnd = entity->textPtr + entity->textLen;
5675 entity->open = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005676 result = appendAttributeValue(parser, parser->m_internalEncoding, isCdata,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005677 (char *)entity->textPtr,
5678 (char *)textEnd, pool);
5679 entity->open = XML_FALSE;
5680 if (result)
5681 return result;
5682 }
5683 }
5684 break;
5685 default:
Elliott Hughes72472942018-01-10 08:36:10 -08005686 /* The only token returned by XmlAttributeValueTok() that does
5687 * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
5688 * Getting that would require an entity name to contain an
5689 * incomplete XML character (e.g. \xE2\x82); however previous
5690 * tokenisers will have already recognised and rejected such
5691 * names before XmlAttributeValueTok() gets a look-in. This
5692 * default case should be retained as a safety net, but the code
5693 * excluded from coverage tests.
5694 *
5695 * LCOV_EXCL_START
5696 */
5697 if (enc == parser->m_encoding)
5698 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005699 return XML_ERROR_UNEXPECTED_STATE;
Elliott Hughes72472942018-01-10 08:36:10 -08005700 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005701 }
5702 ptr = next;
5703 }
5704 /* not reached */
5705}
5706
5707static enum XML_Error
5708storeEntityValue(XML_Parser parser,
5709 const ENCODING *enc,
5710 const char *entityTextPtr,
5711 const char *entityTextEnd)
5712{
Elliott Hughes72472942018-01-10 08:36:10 -08005713 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005714 STRING_POOL *pool = &(dtd->entityValuePool);
5715 enum XML_Error result = XML_ERROR_NONE;
5716#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005717 int oldInEntityValue = parser->m_prologState.inEntityValue;
5718 parser->m_prologState.inEntityValue = 1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005719#endif /* XML_DTD */
5720 /* never return Null for the value argument in EntityDeclHandler,
5721 since this would indicate an external entity; therefore we
5722 have to make sure that entityValuePool.start is not null */
5723 if (!pool->blocks) {
5724 if (!poolGrow(pool))
5725 return XML_ERROR_NO_MEMORY;
5726 }
5727
5728 for (;;) {
5729 const char *next;
5730 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5731 switch (tok) {
5732 case XML_TOK_PARAM_ENTITY_REF:
5733#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005734 if (parser->m_isParamEntity || enc != parser->m_encoding) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005735 const XML_Char *name;
5736 ENTITY *entity;
Elliott Hughes72472942018-01-10 08:36:10 -08005737 name = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005738 entityTextPtr + enc->minBytesPerChar,
5739 next - enc->minBytesPerChar);
5740 if (!name) {
5741 result = XML_ERROR_NO_MEMORY;
5742 goto endEntityValue;
5743 }
Elliott Hughes35e432d2012-09-09 14:23:38 -07005744 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
Elliott Hughes72472942018-01-10 08:36:10 -08005745 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005746 if (!entity) {
5747 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5748 /* cannot report skipped entity here - see comments on
Elliott Hughes72472942018-01-10 08:36:10 -08005749 parser->m_skippedEntityHandler
5750 if (parser->m_skippedEntityHandler)
5751 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005752 */
5753 dtd->keepProcessing = dtd->standalone;
5754 goto endEntityValue;
5755 }
5756 if (entity->open) {
Elliott Hughes72472942018-01-10 08:36:10 -08005757 if (enc == parser->m_encoding)
5758 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005759 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5760 goto endEntityValue;
5761 }
5762 if (entity->systemId) {
Elliott Hughes72472942018-01-10 08:36:10 -08005763 if (parser->m_externalEntityRefHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005764 dtd->paramEntityRead = XML_FALSE;
5765 entity->open = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005766 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005767 0,
5768 entity->base,
5769 entity->systemId,
5770 entity->publicId)) {
5771 entity->open = XML_FALSE;
5772 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5773 goto endEntityValue;
5774 }
5775 entity->open = XML_FALSE;
5776 if (!dtd->paramEntityRead)
5777 dtd->keepProcessing = dtd->standalone;
5778 }
5779 else
5780 dtd->keepProcessing = dtd->standalone;
5781 }
5782 else {
5783 entity->open = XML_TRUE;
5784 result = storeEntityValue(parser,
Elliott Hughes72472942018-01-10 08:36:10 -08005785 parser->m_internalEncoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005786 (char *)entity->textPtr,
5787 (char *)(entity->textPtr
5788 + entity->textLen));
5789 entity->open = XML_FALSE;
5790 if (result)
5791 goto endEntityValue;
5792 }
5793 break;
5794 }
5795#endif /* XML_DTD */
5796 /* In the internal subset, PE references are not legal
5797 within markup declarations, e.g entity values in this case. */
Elliott Hughes72472942018-01-10 08:36:10 -08005798 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005799 result = XML_ERROR_PARAM_ENTITY_REF;
5800 goto endEntityValue;
5801 case XML_TOK_NONE:
5802 result = XML_ERROR_NONE;
5803 goto endEntityValue;
5804 case XML_TOK_ENTITY_REF:
5805 case XML_TOK_DATA_CHARS:
5806 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5807 result = XML_ERROR_NO_MEMORY;
5808 goto endEntityValue;
5809 }
5810 break;
5811 case XML_TOK_TRAILING_CR:
5812 next = entityTextPtr + enc->minBytesPerChar;
5813 /* fall through */
5814 case XML_TOK_DATA_NEWLINE:
5815 if (pool->end == pool->ptr && !poolGrow(pool)) {
5816 result = XML_ERROR_NO_MEMORY;
5817 goto endEntityValue;
5818 }
5819 *(pool->ptr)++ = 0xA;
5820 break;
5821 case XML_TOK_CHAR_REF:
5822 {
5823 XML_Char buf[XML_ENCODE_MAX];
5824 int i;
5825 int n = XmlCharRefNumber(enc, entityTextPtr);
5826 if (n < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08005827 if (enc == parser->m_encoding)
5828 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005829 result = XML_ERROR_BAD_CHAR_REF;
5830 goto endEntityValue;
5831 }
5832 n = XmlEncode(n, (ICHAR *)buf);
Elliott Hughes72472942018-01-10 08:36:10 -08005833 /* The XmlEncode() functions can never return 0 here. That
5834 * error return happens if the code point passed in is either
5835 * negative or greater than or equal to 0x110000. The
5836 * XmlCharRefNumber() functions will all return a number
5837 * strictly less than 0x110000 or a negative value if an error
5838 * occurred. The negative value is intercepted above, so
5839 * XmlEncode() is never passed a value it might return an
5840 * error for.
5841 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005842 for (i = 0; i < n; i++) {
5843 if (pool->end == pool->ptr && !poolGrow(pool)) {
5844 result = XML_ERROR_NO_MEMORY;
5845 goto endEntityValue;
5846 }
5847 *(pool->ptr)++ = buf[i];
5848 }
5849 }
5850 break;
5851 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08005852 if (enc == parser->m_encoding)
5853 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005854 result = XML_ERROR_INVALID_TOKEN;
5855 goto endEntityValue;
5856 case XML_TOK_INVALID:
Elliott Hughes72472942018-01-10 08:36:10 -08005857 if (enc == parser->m_encoding)
5858 parser->m_eventPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005859 result = XML_ERROR_INVALID_TOKEN;
5860 goto endEntityValue;
5861 default:
Elliott Hughes72472942018-01-10 08:36:10 -08005862 /* This default case should be unnecessary -- all the tokens
5863 * that XmlEntityValueTok() can return have their own explicit
5864 * cases -- but should be retained for safety. We do however
5865 * exclude it from the coverage statistics.
5866 *
5867 * LCOV_EXCL_START
5868 */
5869 if (enc == parser->m_encoding)
5870 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005871 result = XML_ERROR_UNEXPECTED_STATE;
5872 goto endEntityValue;
Elliott Hughes72472942018-01-10 08:36:10 -08005873 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005874 }
5875 entityTextPtr = next;
5876 }
5877endEntityValue:
5878#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005879 parser->m_prologState.inEntityValue = oldInEntityValue;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005880#endif /* XML_DTD */
5881 return result;
5882}
5883
5884static void FASTCALL
5885normalizeLines(XML_Char *s)
5886{
5887 XML_Char *p;
5888 for (;; s++) {
5889 if (*s == XML_T('\0'))
5890 return;
5891 if (*s == 0xD)
5892 break;
5893 }
5894 p = s;
5895 do {
5896 if (*s == 0xD) {
5897 *p++ = 0xA;
5898 if (*++s == 0xA)
5899 s++;
5900 }
5901 else
5902 *p++ = *s++;
5903 } while (*s);
5904 *p = XML_T('\0');
5905}
5906
5907static int
5908reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5909 const char *start, const char *end)
5910{
5911 const XML_Char *target;
5912 XML_Char *data;
5913 const char *tem;
Elliott Hughes72472942018-01-10 08:36:10 -08005914 if (!parser->m_processingInstructionHandler) {
5915 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005916 reportDefault(parser, enc, start, end);
5917 return 1;
5918 }
5919 start += enc->minBytesPerChar * 2;
5920 tem = start + XmlNameLength(enc, start);
Elliott Hughes72472942018-01-10 08:36:10 -08005921 target = poolStoreString(&parser->m_tempPool, enc, start, tem);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005922 if (!target)
5923 return 0;
Elliott Hughes72472942018-01-10 08:36:10 -08005924 poolFinish(&parser->m_tempPool);
5925 data = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005926 XmlSkipS(enc, tem),
5927 end - enc->minBytesPerChar*2);
5928 if (!data)
5929 return 0;
5930 normalizeLines(data);
Elliott Hughes72472942018-01-10 08:36:10 -08005931 parser->m_processingInstructionHandler(parser->m_handlerArg, target, data);
5932 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005933 return 1;
5934}
5935
5936static int
5937reportComment(XML_Parser parser, const ENCODING *enc,
5938 const char *start, const char *end)
5939{
5940 XML_Char *data;
Elliott Hughes72472942018-01-10 08:36:10 -08005941 if (!parser->m_commentHandler) {
5942 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005943 reportDefault(parser, enc, start, end);
5944 return 1;
5945 }
Elliott Hughes72472942018-01-10 08:36:10 -08005946 data = poolStoreString(&parser->m_tempPool,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005947 enc,
5948 start + enc->minBytesPerChar * 4,
5949 end - enc->minBytesPerChar * 3);
5950 if (!data)
5951 return 0;
5952 normalizeLines(data);
Elliott Hughes72472942018-01-10 08:36:10 -08005953 parser->m_commentHandler(parser->m_handlerArg, data);
5954 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005955 return 1;
5956}
5957
5958static void
5959reportDefault(XML_Parser parser, const ENCODING *enc,
5960 const char *s, const char *end)
5961{
5962 if (MUST_CONVERT(enc, s)) {
Paul Duffin4bf8f122016-05-13 12:35:25 +01005963 enum XML_Convert_Result convert_res;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005964 const char **eventPP;
5965 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08005966 if (enc == parser->m_encoding) {
5967 eventPP = &parser->m_eventPtr;
5968 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005969 }
5970 else {
Elliott Hughes72472942018-01-10 08:36:10 -08005971 /* To get here, two things must be true; the parser must be
5972 * using a character encoding that is not the same as the
5973 * encoding passed in, and the encoding passed in must need
5974 * conversion to the internal format (UTF-8 unless XML_UNICODE
5975 * is defined). The only occasions on which the encoding passed
5976 * in is not the same as the parser's encoding are when it is
5977 * the internal encoding (e.g. a previously defined parameter
5978 * entity, already converted to internal format). This by
5979 * definition doesn't need conversion, so the whole branch never
5980 * gets executed.
5981 *
5982 * For safety's sake we don't delete these lines and merely
5983 * exclude them from coverage statistics.
5984 *
5985 * LCOV_EXCL_START
5986 */
5987 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
5988 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
5989 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005990 }
5991 do {
Elliott Hughes72472942018-01-10 08:36:10 -08005992 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
5993 convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005994 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08005995 parser->m_defaultHandler(parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005996 *eventPP = s;
Paul Duffin4bf8f122016-05-13 12:35:25 +01005997 } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005998 }
5999 else
Elliott Hughes72472942018-01-10 08:36:10 -08006000 parser->m_defaultHandler(parser->m_handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006001}
6002
6003
6004static int
6005defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
6006 XML_Bool isId, const XML_Char *value, XML_Parser parser)
6007{
6008 DEFAULT_ATTRIBUTE *att;
6009 if (value || isId) {
6010 /* The handling of default attributes gets messed up if we have
6011 a default which duplicates a non-default. */
6012 int i;
6013 for (i = 0; i < type->nDefaultAtts; i++)
6014 if (attId == type->defaultAtts[i].id)
6015 return 1;
6016 if (isId && !type->idAtt && !attId->xmlns)
6017 type->idAtt = attId;
6018 }
6019 if (type->nDefaultAtts == type->allocDefaultAtts) {
6020 if (type->allocDefaultAtts == 0) {
6021 type->allocDefaultAtts = 8;
Elliott Hughes72472942018-01-10 08:36:10 -08006022 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(parser, type->allocDefaultAtts
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006023 * sizeof(DEFAULT_ATTRIBUTE));
Elliott Hughes72472942018-01-10 08:36:10 -08006024 if (!type->defaultAtts) {
6025 type->allocDefaultAtts = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006026 return 0;
Elliott Hughes72472942018-01-10 08:36:10 -08006027 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006028 }
6029 else {
6030 DEFAULT_ATTRIBUTE *temp;
6031 int count = type->allocDefaultAtts * 2;
6032 temp = (DEFAULT_ATTRIBUTE *)
Elliott Hughes72472942018-01-10 08:36:10 -08006033 REALLOC(parser, type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006034 if (temp == NULL)
6035 return 0;
6036 type->allocDefaultAtts = count;
6037 type->defaultAtts = temp;
6038 }
6039 }
6040 att = type->defaultAtts + type->nDefaultAtts;
6041 att->id = attId;
6042 att->value = value;
6043 att->isCdata = isCdata;
6044 if (!isCdata)
6045 attId->maybeTokenized = XML_TRUE;
6046 type->nDefaultAtts += 1;
6047 return 1;
6048}
6049
6050static int
6051setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
6052{
Elliott Hughes72472942018-01-10 08:36:10 -08006053 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006054 const XML_Char *name;
6055 for (name = elementType->name; *name; name++) {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006056 if (*name == XML_T(ASCII_COLON)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006057 PREFIX *prefix;
6058 const XML_Char *s;
6059 for (s = elementType->name; s != name; s++) {
6060 if (!poolAppendChar(&dtd->pool, *s))
6061 return 0;
6062 }
6063 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6064 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006065 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006066 sizeof(PREFIX));
6067 if (!prefix)
6068 return 0;
6069 if (prefix->name == poolStart(&dtd->pool))
6070 poolFinish(&dtd->pool);
6071 else
6072 poolDiscard(&dtd->pool);
6073 elementType->prefix = prefix;
Haibo Huangfd5e81a2019-06-20 12:09:36 -07006074 break;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006075 }
6076 }
6077 return 1;
6078}
6079
6080static ATTRIBUTE_ID *
6081getAttributeId(XML_Parser parser, const ENCODING *enc,
6082 const char *start, const char *end)
6083{
Elliott Hughes72472942018-01-10 08:36:10 -08006084 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006085 ATTRIBUTE_ID *id;
6086 const XML_Char *name;
6087 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6088 return NULL;
6089 name = poolStoreString(&dtd->pool, enc, start, end);
6090 if (!name)
6091 return NULL;
6092 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
6093 ++name;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006094 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006095 if (!id)
6096 return NULL;
6097 if (id->name != name)
6098 poolDiscard(&dtd->pool);
6099 else {
6100 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08006101 if (!parser->m_ns)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006102 ;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006103 else if (name[0] == XML_T(ASCII_x)
6104 && name[1] == XML_T(ASCII_m)
6105 && name[2] == XML_T(ASCII_l)
6106 && name[3] == XML_T(ASCII_n)
6107 && name[4] == XML_T(ASCII_s)
6108 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006109 if (name[5] == XML_T('\0'))
6110 id->prefix = &dtd->defaultPrefix;
6111 else
Elliott Hughes35e432d2012-09-09 14:23:38 -07006112 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006113 id->xmlns = XML_TRUE;
6114 }
6115 else {
6116 int i;
6117 for (i = 0; name[i]; i++) {
6118 /* attributes without prefix are *not* in the default namespace */
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006119 if (name[i] == XML_T(ASCII_COLON)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006120 int j;
6121 for (j = 0; j < i; j++) {
6122 if (!poolAppendChar(&dtd->pool, name[j]))
6123 return NULL;
6124 }
6125 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6126 return NULL;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006127 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006128 sizeof(PREFIX));
Paul Duffinc05e0322016-05-04 10:42:31 +01006129 if (!id->prefix)
6130 return NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006131 if (id->prefix->name == poolStart(&dtd->pool))
6132 poolFinish(&dtd->pool);
6133 else
6134 poolDiscard(&dtd->pool);
6135 break;
6136 }
6137 }
6138 }
6139 }
6140 return id;
6141}
6142
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006143#define CONTEXT_SEP XML_T(ASCII_FF)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006144
6145static const XML_Char *
6146getContext(XML_Parser parser)
6147{
Elliott Hughes72472942018-01-10 08:36:10 -08006148 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006149 HASH_TABLE_ITER iter;
6150 XML_Bool needSep = XML_FALSE;
6151
6152 if (dtd->defaultPrefix.binding) {
6153 int i;
6154 int len;
Elliott Hughes72472942018-01-10 08:36:10 -08006155 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006156 return NULL;
6157 len = dtd->defaultPrefix.binding->uriLen;
Elliott Hughes72472942018-01-10 08:36:10 -08006158 if (parser->m_namespaceSeparator)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006159 len--;
Elliott Hughes72472942018-01-10 08:36:10 -08006160 for (i = 0; i < len; i++) {
6161 if (!poolAppendChar(&parser->m_tempPool, dtd->defaultPrefix.binding->uri[i])) {
6162 /* Because of memory caching, I don't believe this line can be
6163 * executed.
6164 *
6165 * This is part of a loop copying the default prefix binding
6166 * URI into the parser's temporary string pool. Previously,
6167 * that URI was copied into the same string pool, with a
6168 * terminating NUL character, as part of setContext(). When
6169 * the pool was cleared, that leaves a block definitely big
6170 * enough to hold the URI on the free block list of the pool.
6171 * The URI copy in getContext() therefore cannot run out of
6172 * memory.
6173 *
6174 * If the pool is used between the setContext() and
6175 * getContext() calls, the worst it can do is leave a bigger
6176 * block on the front of the free list. Given that this is
6177 * all somewhat inobvious and program logic can be changed, we
6178 * don't delete the line but we do exclude it from the test
6179 * coverage statistics.
6180 */
6181 return NULL; /* LCOV_EXCL_LINE */
6182 }
6183 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006184 needSep = XML_TRUE;
6185 }
6186
6187 hashTableIterInit(&iter, &(dtd->prefixes));
6188 for (;;) {
6189 int i;
6190 int len;
6191 const XML_Char *s;
6192 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
6193 if (!prefix)
6194 break;
Elliott Hughes72472942018-01-10 08:36:10 -08006195 if (!prefix->binding) {
6196 /* This test appears to be (justifiable) paranoia. There does
6197 * not seem to be a way of injecting a prefix without a binding
6198 * that doesn't get errored long before this function is called.
6199 * The test should remain for safety's sake, so we instead
6200 * exclude the following line from the coverage statistics.
6201 */
6202 continue; /* LCOV_EXCL_LINE */
6203 }
6204 if (needSep && !poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006205 return NULL;
6206 for (s = prefix->name; *s; s++)
Elliott Hughes72472942018-01-10 08:36:10 -08006207 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006208 return NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08006209 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006210 return NULL;
6211 len = prefix->binding->uriLen;
Elliott Hughes72472942018-01-10 08:36:10 -08006212 if (parser->m_namespaceSeparator)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006213 len--;
6214 for (i = 0; i < len; i++)
Elliott Hughes72472942018-01-10 08:36:10 -08006215 if (!poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i]))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006216 return NULL;
6217 needSep = XML_TRUE;
6218 }
6219
6220
6221 hashTableIterInit(&iter, &(dtd->generalEntities));
6222 for (;;) {
6223 const XML_Char *s;
6224 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
6225 if (!e)
6226 break;
6227 if (!e->open)
6228 continue;
Elliott Hughes72472942018-01-10 08:36:10 -08006229 if (needSep && !poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006230 return NULL;
6231 for (s = e->name; *s; s++)
Elliott Hughes72472942018-01-10 08:36:10 -08006232 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006233 return 0;
6234 needSep = XML_TRUE;
6235 }
6236
Elliott Hughes72472942018-01-10 08:36:10 -08006237 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006238 return NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08006239 return parser->m_tempPool.start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006240}
6241
6242static XML_Bool
6243setContext(XML_Parser parser, const XML_Char *context)
6244{
Elliott Hughes72472942018-01-10 08:36:10 -08006245 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006246 const XML_Char *s = context;
6247
6248 while (*context != XML_T('\0')) {
6249 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
6250 ENTITY *e;
Elliott Hughes72472942018-01-10 08:36:10 -08006251 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006252 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006253 e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&parser->m_tempPool), 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006254 if (e)
6255 e->open = XML_TRUE;
6256 if (*s != XML_T('\0'))
6257 s++;
6258 context = s;
Elliott Hughes72472942018-01-10 08:36:10 -08006259 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006260 }
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006261 else if (*s == XML_T(ASCII_EQUALS)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006262 PREFIX *prefix;
Elliott Hughes72472942018-01-10 08:36:10 -08006263 if (poolLength(&parser->m_tempPool) == 0)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006264 prefix = &dtd->defaultPrefix;
6265 else {
Elliott Hughes72472942018-01-10 08:36:10 -08006266 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006267 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006268 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&parser->m_tempPool),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006269 sizeof(PREFIX));
6270 if (!prefix)
6271 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006272 if (prefix->name == poolStart(&parser->m_tempPool)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006273 prefix->name = poolCopyString(&dtd->pool, prefix->name);
6274 if (!prefix->name)
6275 return XML_FALSE;
6276 }
Elliott Hughes72472942018-01-10 08:36:10 -08006277 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006278 }
6279 for (context = s + 1;
6280 *context != CONTEXT_SEP && *context != XML_T('\0');
6281 context++)
Elliott Hughes72472942018-01-10 08:36:10 -08006282 if (!poolAppendChar(&parser->m_tempPool, *context))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006283 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006284 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006285 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006286 if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool),
6287 &parser->m_inheritedBindings) != XML_ERROR_NONE)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006288 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006289 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006290 if (*context != XML_T('\0'))
6291 ++context;
6292 s = context;
6293 }
6294 else {
Elliott Hughes72472942018-01-10 08:36:10 -08006295 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006296 return XML_FALSE;
6297 s++;
6298 }
6299 }
6300 return XML_TRUE;
6301}
6302
6303static void FASTCALL
6304normalizePublicId(XML_Char *publicId)
6305{
6306 XML_Char *p = publicId;
6307 XML_Char *s;
6308 for (s = publicId; *s; s++) {
6309 switch (*s) {
6310 case 0x20:
6311 case 0xD:
6312 case 0xA:
6313 if (p != publicId && p[-1] != 0x20)
6314 *p++ = 0x20;
6315 break;
6316 default:
6317 *p++ = *s;
6318 }
6319 }
6320 if (p != publicId && p[-1] == 0x20)
6321 --p;
6322 *p = XML_T('\0');
6323}
6324
6325static DTD *
6326dtdCreate(const XML_Memory_Handling_Suite *ms)
6327{
6328 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
6329 if (p == NULL)
6330 return p;
6331 poolInit(&(p->pool), ms);
6332 poolInit(&(p->entityValuePool), ms);
6333 hashTableInit(&(p->generalEntities), ms);
6334 hashTableInit(&(p->elementTypes), ms);
6335 hashTableInit(&(p->attributeIds), ms);
6336 hashTableInit(&(p->prefixes), ms);
6337#ifdef XML_DTD
6338 p->paramEntityRead = XML_FALSE;
6339 hashTableInit(&(p->paramEntities), ms);
6340#endif /* XML_DTD */
6341 p->defaultPrefix.name = NULL;
6342 p->defaultPrefix.binding = NULL;
6343
6344 p->in_eldecl = XML_FALSE;
6345 p->scaffIndex = NULL;
6346 p->scaffold = NULL;
6347 p->scaffLevel = 0;
6348 p->scaffSize = 0;
6349 p->scaffCount = 0;
6350 p->contentStringLen = 0;
6351
6352 p->keepProcessing = XML_TRUE;
6353 p->hasParamEntityRefs = XML_FALSE;
6354 p->standalone = XML_FALSE;
6355 return p;
6356}
6357
6358static void
6359dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
6360{
6361 HASH_TABLE_ITER iter;
6362 hashTableIterInit(&iter, &(p->elementTypes));
6363 for (;;) {
6364 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6365 if (!e)
6366 break;
6367 if (e->allocDefaultAtts != 0)
6368 ms->free_fcn(e->defaultAtts);
6369 }
6370 hashTableClear(&(p->generalEntities));
6371#ifdef XML_DTD
6372 p->paramEntityRead = XML_FALSE;
6373 hashTableClear(&(p->paramEntities));
6374#endif /* XML_DTD */
6375 hashTableClear(&(p->elementTypes));
6376 hashTableClear(&(p->attributeIds));
6377 hashTableClear(&(p->prefixes));
6378 poolClear(&(p->pool));
6379 poolClear(&(p->entityValuePool));
6380 p->defaultPrefix.name = NULL;
6381 p->defaultPrefix.binding = NULL;
6382
6383 p->in_eldecl = XML_FALSE;
6384
6385 ms->free_fcn(p->scaffIndex);
6386 p->scaffIndex = NULL;
6387 ms->free_fcn(p->scaffold);
6388 p->scaffold = NULL;
6389
6390 p->scaffLevel = 0;
6391 p->scaffSize = 0;
6392 p->scaffCount = 0;
6393 p->contentStringLen = 0;
6394
6395 p->keepProcessing = XML_TRUE;
6396 p->hasParamEntityRefs = XML_FALSE;
6397 p->standalone = XML_FALSE;
6398}
6399
6400static void
6401dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
6402{
6403 HASH_TABLE_ITER iter;
6404 hashTableIterInit(&iter, &(p->elementTypes));
6405 for (;;) {
6406 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6407 if (!e)
6408 break;
6409 if (e->allocDefaultAtts != 0)
6410 ms->free_fcn(e->defaultAtts);
6411 }
6412 hashTableDestroy(&(p->generalEntities));
6413#ifdef XML_DTD
6414 hashTableDestroy(&(p->paramEntities));
6415#endif /* XML_DTD */
6416 hashTableDestroy(&(p->elementTypes));
6417 hashTableDestroy(&(p->attributeIds));
6418 hashTableDestroy(&(p->prefixes));
6419 poolDestroy(&(p->pool));
6420 poolDestroy(&(p->entityValuePool));
6421 if (isDocEntity) {
6422 ms->free_fcn(p->scaffIndex);
6423 ms->free_fcn(p->scaffold);
6424 }
6425 ms->free_fcn(p);
6426}
6427
6428/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
6429 The new DTD has already been initialized.
6430*/
6431static int
Elliott Hughes35e432d2012-09-09 14:23:38 -07006432dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006433{
6434 HASH_TABLE_ITER iter;
6435
6436 /* Copy the prefix table. */
6437
6438 hashTableIterInit(&iter, &(oldDtd->prefixes));
6439 for (;;) {
6440 const XML_Char *name;
6441 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
6442 if (!oldP)
6443 break;
6444 name = poolCopyString(&(newDtd->pool), oldP->name);
6445 if (!name)
6446 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006447 if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006448 return 0;
6449 }
6450
6451 hashTableIterInit(&iter, &(oldDtd->attributeIds));
6452
6453 /* Copy the attribute id table. */
6454
6455 for (;;) {
6456 ATTRIBUTE_ID *newA;
6457 const XML_Char *name;
6458 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
6459
6460 if (!oldA)
6461 break;
6462 /* Remember to allocate the scratch byte before the name. */
6463 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
6464 return 0;
6465 name = poolCopyString(&(newDtd->pool), oldA->name);
6466 if (!name)
6467 return 0;
6468 ++name;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006469 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006470 sizeof(ATTRIBUTE_ID));
6471 if (!newA)
6472 return 0;
6473 newA->maybeTokenized = oldA->maybeTokenized;
6474 if (oldA->prefix) {
6475 newA->xmlns = oldA->xmlns;
6476 if (oldA->prefix == &oldDtd->defaultPrefix)
6477 newA->prefix = &newDtd->defaultPrefix;
6478 else
Elliott Hughes35e432d2012-09-09 14:23:38 -07006479 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006480 oldA->prefix->name, 0);
6481 }
6482 }
6483
6484 /* Copy the element type table. */
6485
6486 hashTableIterInit(&iter, &(oldDtd->elementTypes));
6487
6488 for (;;) {
6489 int i;
6490 ELEMENT_TYPE *newE;
6491 const XML_Char *name;
6492 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6493 if (!oldE)
6494 break;
6495 name = poolCopyString(&(newDtd->pool), oldE->name);
6496 if (!name)
6497 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006498 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006499 sizeof(ELEMENT_TYPE));
6500 if (!newE)
6501 return 0;
6502 if (oldE->nDefaultAtts) {
6503 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
6504 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6505 if (!newE->defaultAtts) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006506 return 0;
6507 }
6508 }
6509 if (oldE->idAtt)
6510 newE->idAtt = (ATTRIBUTE_ID *)
Elliott Hughes35e432d2012-09-09 14:23:38 -07006511 lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006512 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
6513 if (oldE->prefix)
Elliott Hughes35e432d2012-09-09 14:23:38 -07006514 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006515 oldE->prefix->name, 0);
6516 for (i = 0; i < newE->nDefaultAtts; i++) {
6517 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
Elliott Hughes35e432d2012-09-09 14:23:38 -07006518 lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006519 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
6520 if (oldE->defaultAtts[i].value) {
6521 newE->defaultAtts[i].value
6522 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
6523 if (!newE->defaultAtts[i].value)
6524 return 0;
6525 }
6526 else
6527 newE->defaultAtts[i].value = NULL;
6528 }
6529 }
6530
6531 /* Copy the entity tables. */
Elliott Hughes35e432d2012-09-09 14:23:38 -07006532 if (!copyEntityTable(oldParser,
6533 &(newDtd->generalEntities),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006534 &(newDtd->pool),
6535 &(oldDtd->generalEntities)))
6536 return 0;
6537
6538#ifdef XML_DTD
Elliott Hughes35e432d2012-09-09 14:23:38 -07006539 if (!copyEntityTable(oldParser,
6540 &(newDtd->paramEntities),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006541 &(newDtd->pool),
6542 &(oldDtd->paramEntities)))
6543 return 0;
6544 newDtd->paramEntityRead = oldDtd->paramEntityRead;
6545#endif /* XML_DTD */
6546
6547 newDtd->keepProcessing = oldDtd->keepProcessing;
6548 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
6549 newDtd->standalone = oldDtd->standalone;
6550
6551 /* Don't want deep copying for scaffolding */
6552 newDtd->in_eldecl = oldDtd->in_eldecl;
6553 newDtd->scaffold = oldDtd->scaffold;
6554 newDtd->contentStringLen = oldDtd->contentStringLen;
6555 newDtd->scaffSize = oldDtd->scaffSize;
6556 newDtd->scaffLevel = oldDtd->scaffLevel;
6557 newDtd->scaffIndex = oldDtd->scaffIndex;
6558
6559 return 1;
6560} /* End dtdCopy */
6561
6562static int
Elliott Hughes35e432d2012-09-09 14:23:38 -07006563copyEntityTable(XML_Parser oldParser,
6564 HASH_TABLE *newTable,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006565 STRING_POOL *newPool,
6566 const HASH_TABLE *oldTable)
6567{
6568 HASH_TABLE_ITER iter;
6569 const XML_Char *cachedOldBase = NULL;
6570 const XML_Char *cachedNewBase = NULL;
6571
6572 hashTableIterInit(&iter, oldTable);
6573
6574 for (;;) {
6575 ENTITY *newE;
6576 const XML_Char *name;
6577 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
6578 if (!oldE)
6579 break;
6580 name = poolCopyString(newPool, oldE->name);
6581 if (!name)
6582 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006583 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006584 if (!newE)
6585 return 0;
6586 if (oldE->systemId) {
6587 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
6588 if (!tem)
6589 return 0;
6590 newE->systemId = tem;
6591 if (oldE->base) {
6592 if (oldE->base == cachedOldBase)
6593 newE->base = cachedNewBase;
6594 else {
6595 cachedOldBase = oldE->base;
6596 tem = poolCopyString(newPool, cachedOldBase);
6597 if (!tem)
6598 return 0;
6599 cachedNewBase = newE->base = tem;
6600 }
6601 }
6602 if (oldE->publicId) {
6603 tem = poolCopyString(newPool, oldE->publicId);
6604 if (!tem)
6605 return 0;
6606 newE->publicId = tem;
6607 }
6608 }
6609 else {
6610 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
6611 oldE->textLen);
6612 if (!tem)
6613 return 0;
6614 newE->textPtr = tem;
6615 newE->textLen = oldE->textLen;
6616 }
6617 if (oldE->notation) {
6618 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
6619 if (!tem)
6620 return 0;
6621 newE->notation = tem;
6622 }
6623 newE->is_param = oldE->is_param;
6624 newE->is_internal = oldE->is_internal;
6625 }
6626 return 1;
6627}
6628
6629#define INIT_POWER 6
6630
6631static XML_Bool FASTCALL
6632keyeq(KEY s1, KEY s2)
6633{
6634 for (; *s1 == *s2; s1++, s2++)
6635 if (*s1 == 0)
6636 return XML_TRUE;
6637 return XML_FALSE;
6638}
6639
Elliott Hughes72472942018-01-10 08:36:10 -08006640static size_t
6641keylen(KEY s)
6642{
6643 size_t len = 0;
6644 for (; *s; s++, len++);
6645 return len;
6646}
6647
6648static void
6649copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key)
6650{
6651 key->k[0] = 0;
6652 key->k[1] = get_hash_secret_salt(parser);
6653}
6654
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006655static unsigned long FASTCALL
Elliott Hughes35e432d2012-09-09 14:23:38 -07006656hash(XML_Parser parser, KEY s)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006657{
Elliott Hughes72472942018-01-10 08:36:10 -08006658 struct siphash state;
6659 struct sipkey key;
Elliott Hughes72472942018-01-10 08:36:10 -08006660 (void)sip24_valid;
6661 copy_salt_to_sipkey(parser, &key);
6662 sip24_init(&state, &key);
6663 sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
6664 return (unsigned long)sip24_final(&state);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006665}
6666
6667static NAMED *
Elliott Hughes35e432d2012-09-09 14:23:38 -07006668lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006669{
6670 size_t i;
6671 if (table->size == 0) {
6672 size_t tsize;
6673 if (!createSize)
6674 return NULL;
6675 table->power = INIT_POWER;
6676 /* table->size is a power of 2 */
6677 table->size = (size_t)1 << INIT_POWER;
6678 tsize = table->size * sizeof(NAMED *);
6679 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
6680 if (!table->v) {
6681 table->size = 0;
6682 return NULL;
6683 }
6684 memset(table->v, 0, tsize);
Elliott Hughes35e432d2012-09-09 14:23:38 -07006685 i = hash(parser, name) & ((unsigned long)table->size - 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006686 }
6687 else {
Elliott Hughes35e432d2012-09-09 14:23:38 -07006688 unsigned long h = hash(parser, name);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006689 unsigned long mask = (unsigned long)table->size - 1;
6690 unsigned char step = 0;
6691 i = h & mask;
6692 while (table->v[i]) {
6693 if (keyeq(name, table->v[i]->name))
6694 return table->v[i];
6695 if (!step)
6696 step = PROBE_STEP(h, mask, table->power);
6697 i < step ? (i += table->size - step) : (i -= step);
6698 }
6699 if (!createSize)
6700 return NULL;
6701
6702 /* check for overflow (table is half full) */
6703 if (table->used >> (table->power - 1)) {
6704 unsigned char newPower = table->power + 1;
6705 size_t newSize = (size_t)1 << newPower;
6706 unsigned long newMask = (unsigned long)newSize - 1;
6707 size_t tsize = newSize * sizeof(NAMED *);
6708 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
6709 if (!newV)
6710 return NULL;
6711 memset(newV, 0, tsize);
6712 for (i = 0; i < table->size; i++)
6713 if (table->v[i]) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07006714 unsigned long newHash = hash(parser, table->v[i]->name);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006715 size_t j = newHash & newMask;
6716 step = 0;
6717 while (newV[j]) {
6718 if (!step)
6719 step = PROBE_STEP(newHash, newMask, newPower);
6720 j < step ? (j += newSize - step) : (j -= step);
6721 }
6722 newV[j] = table->v[i];
6723 }
6724 table->mem->free_fcn(table->v);
6725 table->v = newV;
6726 table->power = newPower;
6727 table->size = newSize;
6728 i = h & newMask;
6729 step = 0;
6730 while (table->v[i]) {
6731 if (!step)
6732 step = PROBE_STEP(h, newMask, newPower);
6733 i < step ? (i += newSize - step) : (i -= step);
6734 }
6735 }
6736 }
6737 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
6738 if (!table->v[i])
6739 return NULL;
6740 memset(table->v[i], 0, createSize);
6741 table->v[i]->name = name;
6742 (table->used)++;
6743 return table->v[i];
6744}
6745
6746static void FASTCALL
6747hashTableClear(HASH_TABLE *table)
6748{
6749 size_t i;
6750 for (i = 0; i < table->size; i++) {
6751 table->mem->free_fcn(table->v[i]);
6752 table->v[i] = NULL;
6753 }
6754 table->used = 0;
6755}
6756
6757static void FASTCALL
6758hashTableDestroy(HASH_TABLE *table)
6759{
6760 size_t i;
6761 for (i = 0; i < table->size; i++)
6762 table->mem->free_fcn(table->v[i]);
6763 table->mem->free_fcn(table->v);
6764}
6765
6766static void FASTCALL
6767hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
6768{
6769 p->power = 0;
6770 p->size = 0;
6771 p->used = 0;
6772 p->v = NULL;
6773 p->mem = ms;
6774}
6775
6776static void FASTCALL
6777hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
6778{
6779 iter->p = table->v;
6780 iter->end = iter->p + table->size;
6781}
6782
6783static NAMED * FASTCALL
6784hashTableIterNext(HASH_TABLE_ITER *iter)
6785{
6786 while (iter->p != iter->end) {
6787 NAMED *tem = *(iter->p)++;
6788 if (tem)
6789 return tem;
6790 }
6791 return NULL;
6792}
6793
6794static void FASTCALL
6795poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
6796{
6797 pool->blocks = NULL;
6798 pool->freeBlocks = NULL;
6799 pool->start = NULL;
6800 pool->ptr = NULL;
6801 pool->end = NULL;
6802 pool->mem = ms;
6803}
6804
6805static void FASTCALL
6806poolClear(STRING_POOL *pool)
6807{
6808 if (!pool->freeBlocks)
6809 pool->freeBlocks = pool->blocks;
6810 else {
6811 BLOCK *p = pool->blocks;
6812 while (p) {
6813 BLOCK *tem = p->next;
6814 p->next = pool->freeBlocks;
6815 pool->freeBlocks = p;
6816 p = tem;
6817 }
6818 }
6819 pool->blocks = NULL;
6820 pool->start = NULL;
6821 pool->ptr = NULL;
6822 pool->end = NULL;
6823}
6824
6825static void FASTCALL
6826poolDestroy(STRING_POOL *pool)
6827{
6828 BLOCK *p = pool->blocks;
6829 while (p) {
6830 BLOCK *tem = p->next;
6831 pool->mem->free_fcn(p);
6832 p = tem;
6833 }
6834 p = pool->freeBlocks;
6835 while (p) {
6836 BLOCK *tem = p->next;
6837 pool->mem->free_fcn(p);
6838 p = tem;
6839 }
6840}
6841
6842static XML_Char *
6843poolAppend(STRING_POOL *pool, const ENCODING *enc,
6844 const char *ptr, const char *end)
6845{
6846 if (!pool->ptr && !poolGrow(pool))
6847 return NULL;
6848 for (;;) {
Paul Duffin4bf8f122016-05-13 12:35:25 +01006849 const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6850 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006851 break;
6852 if (!poolGrow(pool))
6853 return NULL;
6854 }
6855 return pool->start;
6856}
6857
6858static const XML_Char * FASTCALL
6859poolCopyString(STRING_POOL *pool, const XML_Char *s)
6860{
6861 do {
6862 if (!poolAppendChar(pool, *s))
6863 return NULL;
6864 } while (*s++);
6865 s = pool->start;
6866 poolFinish(pool);
6867 return s;
6868}
6869
6870static const XML_Char *
6871poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6872{
Elliott Hughes72472942018-01-10 08:36:10 -08006873 if (!pool->ptr && !poolGrow(pool)) {
6874 /* The following line is unreachable given the current usage of
6875 * poolCopyStringN(). Currently it is called from exactly one
6876 * place to copy the text of a simple general entity. By that
6877 * point, the name of the entity is already stored in the pool, so
6878 * pool->ptr cannot be NULL.
6879 *
6880 * If poolCopyStringN() is used elsewhere as it well might be,
6881 * this line may well become executable again. Regardless, this
6882 * sort of check shouldn't be removed lightly, so we just exclude
6883 * it from the coverage statistics.
6884 */
6885 return NULL; /* LCOV_EXCL_LINE */
6886 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006887 for (; n > 0; --n, s++) {
6888 if (!poolAppendChar(pool, *s))
6889 return NULL;
6890 }
6891 s = pool->start;
6892 poolFinish(pool);
6893 return s;
6894}
6895
6896static const XML_Char * FASTCALL
6897poolAppendString(STRING_POOL *pool, const XML_Char *s)
6898{
6899 while (*s) {
6900 if (!poolAppendChar(pool, *s))
6901 return NULL;
6902 s++;
6903 }
6904 return pool->start;
6905}
6906
6907static XML_Char *
6908poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6909 const char *ptr, const char *end)
6910{
6911 if (!poolAppend(pool, enc, ptr, end))
6912 return NULL;
6913 if (pool->ptr == pool->end && !poolGrow(pool))
6914 return NULL;
6915 *(pool->ptr)++ = 0;
6916 return pool->start;
6917}
6918
Elliott Hughes72472942018-01-10 08:36:10 -08006919static size_t
6920poolBytesToAllocateFor(int blockSize)
6921{
6922 /* Unprotected math would be:
6923 ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
6924 **
6925 ** Detect overflow, avoiding _signed_ overflow undefined behavior
6926 ** For a + b * c we check b * c in isolation first, so that addition of a
6927 ** on top has no chance of making us accept a small non-negative number
6928 */
6929 const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
6930
6931 if (blockSize <= 0)
6932 return 0;
6933
6934 if (blockSize > (int)(INT_MAX / stretch))
6935 return 0;
6936
6937 {
6938 const int stretchedBlockSize = blockSize * (int)stretch;
6939 const int bytesToAllocate = (int)(
6940 offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
6941 if (bytesToAllocate < 0)
6942 return 0;
6943
6944 return (size_t)bytesToAllocate;
6945 }
6946}
6947
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006948static XML_Bool FASTCALL
6949poolGrow(STRING_POOL *pool)
6950{
6951 if (pool->freeBlocks) {
6952 if (pool->start == 0) {
6953 pool->blocks = pool->freeBlocks;
6954 pool->freeBlocks = pool->freeBlocks->next;
6955 pool->blocks->next = NULL;
6956 pool->start = pool->blocks->s;
6957 pool->end = pool->start + pool->blocks->size;
6958 pool->ptr = pool->start;
6959 return XML_TRUE;
6960 }
6961 if (pool->end - pool->start < pool->freeBlocks->size) {
6962 BLOCK *tem = pool->freeBlocks->next;
6963 pool->freeBlocks->next = pool->blocks;
6964 pool->blocks = pool->freeBlocks;
6965 pool->freeBlocks = tem;
6966 memcpy(pool->blocks->s, pool->start,
6967 (pool->end - pool->start) * sizeof(XML_Char));
6968 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6969 pool->start = pool->blocks->s;
6970 pool->end = pool->start + pool->blocks->size;
6971 return XML_TRUE;
6972 }
6973 }
6974 if (pool->blocks && pool->start == pool->blocks->s) {
Paul Duffin4bf8f122016-05-13 12:35:25 +01006975 BLOCK *temp;
Paul Duffinba34a0c2017-02-27 14:40:16 +00006976 int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
Elliott Hughes72472942018-01-10 08:36:10 -08006977 size_t bytesToAllocate;
Paul Duffin4bf8f122016-05-13 12:35:25 +01006978
Elliott Hughes72472942018-01-10 08:36:10 -08006979 /* NOTE: Needs to be calculated prior to calling `realloc`
6980 to avoid dangling pointers: */
6981 const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
6982
6983 if (blockSize < 0) {
6984 /* This condition traps a situation where either more than
6985 * INT_MAX/2 bytes have already been allocated. This isn't
6986 * readily testable, since it is unlikely that an average
6987 * machine will have that much memory, so we exclude it from the
6988 * coverage statistics.
6989 */
6990 return XML_FALSE; /* LCOV_EXCL_LINE */
6991 }
6992
6993 bytesToAllocate = poolBytesToAllocateFor(blockSize);
6994 if (bytesToAllocate == 0)
Paul Duffin4bf8f122016-05-13 12:35:25 +01006995 return XML_FALSE;
6996
6997 temp = (BLOCK *)
Elliott Hughes72472942018-01-10 08:36:10 -08006998 pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate);
Elliott Hughes35e432d2012-09-09 14:23:38 -07006999 if (temp == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007000 return XML_FALSE;
Elliott Hughes35e432d2012-09-09 14:23:38 -07007001 pool->blocks = temp;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007002 pool->blocks->size = blockSize;
Elliott Hughes72472942018-01-10 08:36:10 -08007003 pool->ptr = pool->blocks->s + offsetInsideBlock;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007004 pool->start = pool->blocks->s;
7005 pool->end = pool->start + blockSize;
7006 }
7007 else {
7008 BLOCK *tem;
7009 int blockSize = (int)(pool->end - pool->start);
Elliott Hughes72472942018-01-10 08:36:10 -08007010 size_t bytesToAllocate;
Paul Duffin4bf8f122016-05-13 12:35:25 +01007011
Elliott Hughes72472942018-01-10 08:36:10 -08007012 if (blockSize < 0) {
7013 /* This condition traps a situation where either more than
7014 * INT_MAX bytes have already been allocated (which is prevented
7015 * by various pieces of program logic, not least this one, never
7016 * mind the unlikelihood of actually having that much memory) or
7017 * the pool control fields have been corrupted (which could
7018 * conceivably happen in an extremely buggy user handler
7019 * function). Either way it isn't readily testable, so we
7020 * exclude it from the coverage statistics.
7021 */
7022 return XML_FALSE; /* LCOV_EXCL_LINE */
7023 }
Paul Duffin4bf8f122016-05-13 12:35:25 +01007024
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007025 if (blockSize < INIT_BLOCK_SIZE)
7026 blockSize = INIT_BLOCK_SIZE;
Elliott Hughes72472942018-01-10 08:36:10 -08007027 else {
7028 /* Detect overflow, avoiding _signed_ overflow undefined behavior */
7029 if ((int)((unsigned)blockSize * 2U) < 0) {
7030 return XML_FALSE;
7031 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007032 blockSize *= 2;
Elliott Hughes72472942018-01-10 08:36:10 -08007033 }
7034
7035 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7036 if (bytesToAllocate == 0)
7037 return XML_FALSE;
7038
7039 tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007040 if (!tem)
7041 return XML_FALSE;
7042 tem->size = blockSize;
7043 tem->next = pool->blocks;
7044 pool->blocks = tem;
7045 if (pool->ptr != pool->start)
7046 memcpy(tem->s, pool->start,
7047 (pool->ptr - pool->start) * sizeof(XML_Char));
7048 pool->ptr = tem->s + (pool->ptr - pool->start);
7049 pool->start = tem->s;
7050 pool->end = tem->s + blockSize;
7051 }
7052 return XML_TRUE;
7053}
7054
7055static int FASTCALL
7056nextScaffoldPart(XML_Parser parser)
7057{
Elliott Hughes72472942018-01-10 08:36:10 -08007058 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007059 CONTENT_SCAFFOLD * me;
7060 int next;
7061
7062 if (!dtd->scaffIndex) {
Elliott Hughes72472942018-01-10 08:36:10 -08007063 dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007064 if (!dtd->scaffIndex)
7065 return -1;
7066 dtd->scaffIndex[0] = 0;
7067 }
7068
7069 if (dtd->scaffCount >= dtd->scaffSize) {
7070 CONTENT_SCAFFOLD *temp;
7071 if (dtd->scaffold) {
7072 temp = (CONTENT_SCAFFOLD *)
Elliott Hughes72472942018-01-10 08:36:10 -08007073 REALLOC(parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007074 if (temp == NULL)
7075 return -1;
7076 dtd->scaffSize *= 2;
7077 }
7078 else {
Elliott Hughes72472942018-01-10 08:36:10 -08007079 temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007080 * sizeof(CONTENT_SCAFFOLD));
7081 if (temp == NULL)
7082 return -1;
7083 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
7084 }
7085 dtd->scaffold = temp;
7086 }
7087 next = dtd->scaffCount++;
7088 me = &dtd->scaffold[next];
7089 if (dtd->scaffLevel) {
7090 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
7091 if (parent->lastchild) {
7092 dtd->scaffold[parent->lastchild].nextsib = next;
7093 }
7094 if (!parent->childcnt)
7095 parent->firstchild = next;
7096 parent->lastchild = next;
7097 parent->childcnt++;
7098 }
7099 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
7100 return next;
7101}
7102
7103static void
7104build_node(XML_Parser parser,
7105 int src_node,
7106 XML_Content *dest,
7107 XML_Content **contpos,
7108 XML_Char **strpos)
7109{
Elliott Hughes72472942018-01-10 08:36:10 -08007110 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007111 dest->type = dtd->scaffold[src_node].type;
7112 dest->quant = dtd->scaffold[src_node].quant;
7113 if (dest->type == XML_CTYPE_NAME) {
7114 const XML_Char *src;
7115 dest->name = *strpos;
7116 src = dtd->scaffold[src_node].name;
7117 for (;;) {
7118 *(*strpos)++ = *src;
7119 if (!*src)
7120 break;
7121 src++;
7122 }
7123 dest->numchildren = 0;
7124 dest->children = NULL;
7125 }
7126 else {
7127 unsigned int i;
7128 int cn;
7129 dest->numchildren = dtd->scaffold[src_node].childcnt;
7130 dest->children = *contpos;
7131 *contpos += dest->numchildren;
7132 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
7133 i < dest->numchildren;
7134 i++, cn = dtd->scaffold[cn].nextsib) {
7135 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
7136 }
7137 dest->name = NULL;
7138 }
7139}
7140
7141static XML_Content *
7142build_model (XML_Parser parser)
7143{
Elliott Hughes72472942018-01-10 08:36:10 -08007144 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007145 XML_Content *ret;
7146 XML_Content *cpos;
7147 XML_Char * str;
7148 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
7149 + (dtd->contentStringLen * sizeof(XML_Char)));
7150
Elliott Hughes72472942018-01-10 08:36:10 -08007151 ret = (XML_Content *)MALLOC(parser, allocsize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007152 if (!ret)
7153 return NULL;
7154
7155 str = (XML_Char *) (&ret[dtd->scaffCount]);
7156 cpos = &ret[1];
7157
7158 build_node(parser, 0, ret, &cpos, &str);
7159 return ret;
7160}
7161
7162static ELEMENT_TYPE *
7163getElementType(XML_Parser parser,
7164 const ENCODING *enc,
7165 const char *ptr,
7166 const char *end)
7167{
Elliott Hughes72472942018-01-10 08:36:10 -08007168 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007169 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
7170 ELEMENT_TYPE *ret;
7171
7172 if (!name)
7173 return NULL;
Elliott Hughes35e432d2012-09-09 14:23:38 -07007174 ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007175 if (!ret)
7176 return NULL;
7177 if (ret->name != name)
7178 poolDiscard(&dtd->pool);
7179 else {
7180 poolFinish(&dtd->pool);
7181 if (!setElementTypePrefix(parser, ret))
7182 return NULL;
7183 }
7184 return ret;
7185}
Elliott Hughes72472942018-01-10 08:36:10 -08007186
7187static XML_Char *
7188copyString(const XML_Char *s,
7189 const XML_Memory_Handling_Suite *memsuite)
7190{
7191 int charsRequired = 0;
7192 XML_Char *result;
7193
7194 /* First determine how long the string is */
7195 while (s[charsRequired] != 0) {
7196 charsRequired++;
7197 }
7198 /* Include the terminator */
7199 charsRequired++;
7200
7201 /* Now allocate space for the copy */
7202 result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
7203 if (result == NULL)
7204 return NULL;
7205 /* Copy the original into place */
7206 memcpy(result, s, charsRequired * sizeof(XML_Char));
7207 return result;
7208}