blob: 90a237f30eb8cdcee92874d2cdc4b3d5e42e757c [file] [log] [blame]
Elliott Hughes72472942018-01-10 08:36:10 -08001/* 4b74aa710b4ed5ce464b0ce544852cb47bf905c85a49c7bae2749f5885cb966d (2.2.5+)
2 __ __ _
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
164/* Handle the case where memmove() doesn't exist. */
165#ifndef HAVE_MEMMOVE
166#ifdef HAVE_BCOPY
167#define memmove(d,s,l) bcopy((s),(d),(l))
168#else
169#error memmove does not exist on this platform, nor is a substitute available
170#endif /* HAVE_BCOPY */
171#endif /* HAVE_MEMMOVE */
172
173#include "internal.h"
174#include "xmltok.h"
175#include "xmlrole.h"
176
177typedef const XML_Char *KEY;
178
179typedef struct {
180 KEY name;
181} NAMED;
182
183typedef struct {
184 NAMED **v;
185 unsigned char power;
186 size_t size;
187 size_t used;
188 const XML_Memory_Handling_Suite *mem;
189} HASH_TABLE;
190
Elliott Hughes72472942018-01-10 08:36:10 -0800191static size_t
192keylen(KEY s);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800193
Elliott Hughes72472942018-01-10 08:36:10 -0800194static void
195copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800196
197/* For probing (after a collision) we need a step size relative prime
198 to the hash table size, which is a power of 2. We use double-hashing,
199 since we can calculate a second hash value cheaply by taking those bits
200 of the first hash value that were discarded (masked out) when the table
201 index was calculated: index = hash & mask, where mask = table->size - 1.
202 We limit the maximum step size to table->size / 4 (mask >> 2) and make
203 it odd, since odd numbers are always relative prime to a power of 2.
204*/
205#define SECOND_HASH(hash, mask, power) \
206 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
207#define PROBE_STEP(hash, mask, power) \
208 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
209
210typedef struct {
211 NAMED **p;
212 NAMED **end;
213} HASH_TABLE_ITER;
214
215#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
216#define INIT_DATA_BUF_SIZE 1024
217#define INIT_ATTS_SIZE 16
218#define INIT_ATTS_VERSION 0xFFFFFFFF
219#define INIT_BLOCK_SIZE 1024
220#define INIT_BUFFER_SIZE 1024
221
222#define EXPAND_SPARE 24
223
224typedef struct binding {
225 struct prefix *prefix;
226 struct binding *nextTagBinding;
227 struct binding *prevPrefixBinding;
228 const struct attribute_id *attId;
229 XML_Char *uri;
230 int uriLen;
231 int uriAlloc;
232} BINDING;
233
234typedef struct prefix {
235 const XML_Char *name;
236 BINDING *binding;
237} PREFIX;
238
239typedef struct {
240 const XML_Char *str;
241 const XML_Char *localPart;
242 const XML_Char *prefix;
243 int strLen;
244 int uriLen;
245 int prefixLen;
246} TAG_NAME;
247
248/* TAG represents an open element.
249 The name of the element is stored in both the document and API
250 encodings. The memory buffer 'buf' is a separately-allocated
251 memory area which stores the name. During the XML_Parse()/
252 XMLParseBuffer() when the element is open, the memory for the 'raw'
253 version of the name (in the document encoding) is shared with the
254 document buffer. If the element is open across calls to
255 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
256 contain the 'raw' name as well.
257
258 A parser re-uses these structures, maintaining a list of allocated
259 TAG objects in a free list.
260*/
261typedef struct tag {
262 struct tag *parent; /* parent of this element */
263 const char *rawName; /* tagName in the original encoding */
264 int rawNameLength;
265 TAG_NAME name; /* tagName in the API encoding */
266 char *buf; /* buffer for name components */
267 char *bufEnd; /* end of the buffer */
268 BINDING *bindings;
269} TAG;
270
271typedef struct {
272 const XML_Char *name;
273 const XML_Char *textPtr;
274 int textLen; /* length in XML_Chars */
275 int processed; /* # of processed bytes - when suspended */
276 const XML_Char *systemId;
277 const XML_Char *base;
278 const XML_Char *publicId;
279 const XML_Char *notation;
280 XML_Bool open;
281 XML_Bool is_param;
282 XML_Bool is_internal; /* true if declared in internal subset outside PE */
283} ENTITY;
284
285typedef struct {
286 enum XML_Content_Type type;
287 enum XML_Content_Quant quant;
288 const XML_Char * name;
289 int firstchild;
290 int lastchild;
291 int childcnt;
292 int nextsib;
293} CONTENT_SCAFFOLD;
294
295#define INIT_SCAFFOLD_ELEMENTS 32
296
297typedef struct block {
298 struct block *next;
299 int size;
300 XML_Char s[1];
301} BLOCK;
302
303typedef struct {
304 BLOCK *blocks;
305 BLOCK *freeBlocks;
306 const XML_Char *end;
307 XML_Char *ptr;
308 XML_Char *start;
309 const XML_Memory_Handling_Suite *mem;
310} STRING_POOL;
311
312/* The XML_Char before the name is used to determine whether
313 an attribute has been specified. */
314typedef struct attribute_id {
315 XML_Char *name;
316 PREFIX *prefix;
317 XML_Bool maybeTokenized;
318 XML_Bool xmlns;
319} ATTRIBUTE_ID;
320
321typedef struct {
322 const ATTRIBUTE_ID *id;
323 XML_Bool isCdata;
324 const XML_Char *value;
325} DEFAULT_ATTRIBUTE;
326
327typedef struct {
328 unsigned long version;
329 unsigned long hash;
330 const XML_Char *uriName;
331} NS_ATT;
332
333typedef struct {
334 const XML_Char *name;
335 PREFIX *prefix;
336 const ATTRIBUTE_ID *idAtt;
337 int nDefaultAtts;
338 int allocDefaultAtts;
339 DEFAULT_ATTRIBUTE *defaultAtts;
340} ELEMENT_TYPE;
341
342typedef struct {
343 HASH_TABLE generalEntities;
344 HASH_TABLE elementTypes;
345 HASH_TABLE attributeIds;
346 HASH_TABLE prefixes;
347 STRING_POOL pool;
348 STRING_POOL entityValuePool;
349 /* false once a parameter entity reference has been skipped */
350 XML_Bool keepProcessing;
351 /* true once an internal or external PE reference has been encountered;
352 this includes the reference to an external subset */
353 XML_Bool hasParamEntityRefs;
354 XML_Bool standalone;
355#ifdef XML_DTD
356 /* indicates if external PE has been read */
357 XML_Bool paramEntityRead;
358 HASH_TABLE paramEntities;
359#endif /* XML_DTD */
360 PREFIX defaultPrefix;
361 /* === scaffolding for building content model === */
362 XML_Bool in_eldecl;
363 CONTENT_SCAFFOLD *scaffold;
364 unsigned contentStringLen;
365 unsigned scaffSize;
366 unsigned scaffCount;
367 int scaffLevel;
368 int *scaffIndex;
369} DTD;
370
371typedef struct open_internal_entity {
372 const char *internalEventPtr;
373 const char *internalEventEndPtr;
374 struct open_internal_entity *next;
375 ENTITY *entity;
376 int startTagLevel;
377 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
378} OPEN_INTERNAL_ENTITY;
379
380typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
381 const char *start,
382 const char *end,
383 const char **endPtr);
384
385static Processor prologProcessor;
386static Processor prologInitProcessor;
387static Processor contentProcessor;
388static Processor cdataSectionProcessor;
389#ifdef XML_DTD
390static Processor ignoreSectionProcessor;
391static Processor externalParEntProcessor;
392static Processor externalParEntInitProcessor;
393static Processor entityValueProcessor;
394static Processor entityValueInitProcessor;
395#endif /* XML_DTD */
396static Processor epilogProcessor;
397static Processor errorProcessor;
398static Processor externalEntityInitProcessor;
399static Processor externalEntityInitProcessor2;
400static Processor externalEntityInitProcessor3;
401static Processor externalEntityContentProcessor;
402static Processor internalEntityProcessor;
403
404static enum XML_Error
405handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
406static enum XML_Error
407processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
408 const char *s, const char *next);
409static enum XML_Error
410initializeEncoding(XML_Parser parser);
411static enum XML_Error
Elliott Hughes35e432d2012-09-09 14:23:38 -0700412doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
413 const char *end, int tok, const char *next, const char **nextPtr,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800414 XML_Bool haveMore);
415static enum XML_Error
Elliott Hughes35e432d2012-09-09 14:23:38 -0700416processInternalEntity(XML_Parser parser, ENTITY *entity,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800417 XML_Bool betweenDecl);
418static enum XML_Error
419doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
Elliott Hughes35e432d2012-09-09 14:23:38 -0700420 const char *start, const char *end, const char **endPtr,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800421 XML_Bool haveMore);
422static enum XML_Error
423doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
424 const char *end, const char **nextPtr, XML_Bool haveMore);
425#ifdef XML_DTD
426static enum XML_Error
427doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
428 const char *end, const char **nextPtr, XML_Bool haveMore);
429#endif /* XML_DTD */
430
Elliott Hughes72472942018-01-10 08:36:10 -0800431static void
432freeBindings(XML_Parser parser, BINDING *bindings);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800433static enum XML_Error
434storeAtts(XML_Parser parser, const ENCODING *, const char *s,
435 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
436static enum XML_Error
437addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
438 const XML_Char *uri, BINDING **bindingsPtr);
439static int
Elliott Hughes35e432d2012-09-09 14:23:38 -0700440defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800441 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
442static enum XML_Error
443storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
444 const char *, const char *, STRING_POOL *);
445static enum XML_Error
446appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
447 const char *, const char *, STRING_POOL *);
448static ATTRIBUTE_ID *
449getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
450 const char *end);
451static int
452setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
453static enum XML_Error
454storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
455 const char *end);
456static int
457reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
458 const char *start, const char *end);
459static int
460reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
461 const char *end);
462static void
463reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
464 const char *end);
465
466static const XML_Char * getContext(XML_Parser parser);
467static XML_Bool
468setContext(XML_Parser parser, const XML_Char *context);
469
470static void FASTCALL normalizePublicId(XML_Char *s);
471
472static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
Elliott Hughes72472942018-01-10 08:36:10 -0800473/* do not call if m_parentParser != NULL */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800474static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
475static void
476dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
477static int
Elliott Hughes35e432d2012-09-09 14:23:38 -0700478dtdCopy(XML_Parser oldParser,
479 DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800480static int
Elliott Hughes35e432d2012-09-09 14:23:38 -0700481copyEntityTable(XML_Parser oldParser,
482 HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800483static NAMED *
Elliott Hughes35e432d2012-09-09 14:23:38 -0700484lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800485static void FASTCALL
486hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
487static void FASTCALL hashTableClear(HASH_TABLE *);
488static void FASTCALL hashTableDestroy(HASH_TABLE *);
489static void FASTCALL
490hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
491static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
492
493static void FASTCALL
494poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
495static void FASTCALL poolClear(STRING_POOL *);
496static void FASTCALL poolDestroy(STRING_POOL *);
497static XML_Char *
498poolAppend(STRING_POOL *pool, const ENCODING *enc,
499 const char *ptr, const char *end);
500static XML_Char *
501poolStoreString(STRING_POOL *pool, const ENCODING *enc,
502 const char *ptr, const char *end);
503static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
504static const XML_Char * FASTCALL
505poolCopyString(STRING_POOL *pool, const XML_Char *s);
506static const XML_Char *
507poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
508static const XML_Char * FASTCALL
509poolAppendString(STRING_POOL *pool, const XML_Char *s);
510
511static int FASTCALL nextScaffoldPart(XML_Parser parser);
512static XML_Content * build_model(XML_Parser parser);
513static ELEMENT_TYPE *
514getElementType(XML_Parser parser, const ENCODING *enc,
515 const char *ptr, const char *end);
516
Elliott Hughes72472942018-01-10 08:36:10 -0800517static XML_Char *copyString(const XML_Char *s,
518 const XML_Memory_Handling_Suite *memsuite);
519
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100520static unsigned long generate_hash_secret_salt(XML_Parser parser);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700521static XML_Bool startParsing(XML_Parser parser);
522
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800523static XML_Parser
524parserCreate(const XML_Char *encodingName,
525 const XML_Memory_Handling_Suite *memsuite,
526 const XML_Char *nameSep,
527 DTD *dtd);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700528
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800529static void
530parserInit(XML_Parser parser, const XML_Char *encodingName);
531
532#define poolStart(pool) ((pool)->start)
533#define poolEnd(pool) ((pool)->ptr)
534#define poolLength(pool) ((pool)->ptr - (pool)->start)
535#define poolChop(pool) ((void)--(pool->ptr))
536#define poolLastChar(pool) (((pool)->ptr)[-1])
537#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
538#define poolFinish(pool) ((pool)->start = (pool)->ptr)
539#define poolAppendChar(pool, c) \
540 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
541 ? 0 \
542 : ((*((pool)->ptr)++ = c), 1))
543
544struct XML_ParserStruct {
Elliott Hughes72472942018-01-10 08:36:10 -0800545 /* The first member must be m_userData so that the XML_GetUserData
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800546 macro works. */
547 void *m_userData;
548 void *m_handlerArg;
549 char *m_buffer;
550 const XML_Memory_Handling_Suite m_mem;
551 /* first character to be parsed */
552 const char *m_bufferPtr;
553 /* past last character to be parsed */
554 char *m_bufferEnd;
Elliott Hughes72472942018-01-10 08:36:10 -0800555 /* allocated end of m_buffer */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800556 const char *m_bufferLim;
557 XML_Index m_parseEndByteIndex;
558 const char *m_parseEndPtr;
559 XML_Char *m_dataBuf;
560 XML_Char *m_dataBufEnd;
561 XML_StartElementHandler m_startElementHandler;
562 XML_EndElementHandler m_endElementHandler;
563 XML_CharacterDataHandler m_characterDataHandler;
564 XML_ProcessingInstructionHandler m_processingInstructionHandler;
565 XML_CommentHandler m_commentHandler;
566 XML_StartCdataSectionHandler m_startCdataSectionHandler;
567 XML_EndCdataSectionHandler m_endCdataSectionHandler;
568 XML_DefaultHandler m_defaultHandler;
569 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
570 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
571 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
572 XML_NotationDeclHandler m_notationDeclHandler;
573 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
574 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
575 XML_NotStandaloneHandler m_notStandaloneHandler;
576 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
577 XML_Parser m_externalEntityRefHandlerArg;
578 XML_SkippedEntityHandler m_skippedEntityHandler;
579 XML_UnknownEncodingHandler m_unknownEncodingHandler;
580 XML_ElementDeclHandler m_elementDeclHandler;
581 XML_AttlistDeclHandler m_attlistDeclHandler;
582 XML_EntityDeclHandler m_entityDeclHandler;
583 XML_XmlDeclHandler m_xmlDeclHandler;
584 const ENCODING *m_encoding;
585 INIT_ENCODING m_initEncoding;
586 const ENCODING *m_internalEncoding;
587 const XML_Char *m_protocolEncodingName;
588 XML_Bool m_ns;
589 XML_Bool m_ns_triplets;
590 void *m_unknownEncodingMem;
591 void *m_unknownEncodingData;
592 void *m_unknownEncodingHandlerData;
593 void (XMLCALL *m_unknownEncodingRelease)(void *);
594 PROLOG_STATE m_prologState;
595 Processor *m_processor;
596 enum XML_Error m_errorCode;
597 const char *m_eventPtr;
598 const char *m_eventEndPtr;
599 const char *m_positionPtr;
600 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
601 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
602 XML_Bool m_defaultExpandInternalEntities;
603 int m_tagLevel;
604 ENTITY *m_declEntity;
605 const XML_Char *m_doctypeName;
606 const XML_Char *m_doctypeSysid;
607 const XML_Char *m_doctypePubid;
608 const XML_Char *m_declAttributeType;
609 const XML_Char *m_declNotationName;
610 const XML_Char *m_declNotationPublicId;
611 ELEMENT_TYPE *m_declElementType;
612 ATTRIBUTE_ID *m_declAttributeId;
613 XML_Bool m_declAttributeIsCdata;
614 XML_Bool m_declAttributeIsId;
615 DTD *m_dtd;
616 const XML_Char *m_curBase;
617 TAG *m_tagStack;
618 TAG *m_freeTagList;
619 BINDING *m_inheritedBindings;
620 BINDING *m_freeBindingList;
621 int m_attsSize;
622 int m_nSpecifiedAtts;
623 int m_idAttIndex;
624 ATTRIBUTE *m_atts;
625 NS_ATT *m_nsAtts;
626 unsigned long m_nsAttsVersion;
627 unsigned char m_nsAttsPower;
Elliott Hughes35e432d2012-09-09 14:23:38 -0700628#ifdef XML_ATTR_INFO
629 XML_AttrInfo *m_attInfo;
630#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800631 POSITION m_position;
632 STRING_POOL m_tempPool;
633 STRING_POOL m_temp2Pool;
634 char *m_groupConnector;
635 unsigned int m_groupSize;
636 XML_Char m_namespaceSeparator;
637 XML_Parser m_parentParser;
638 XML_ParsingStatus m_parsingStatus;
639#ifdef XML_DTD
640 XML_Bool m_isParamEntity;
641 XML_Bool m_useForeignDTD;
642 enum XML_ParamEntityParsing m_paramEntityParsing;
643#endif
Elliott Hughes35e432d2012-09-09 14:23:38 -0700644 unsigned long m_hash_secret_salt;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800645};
646
Elliott Hughes72472942018-01-10 08:36:10 -0800647#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
648#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p),(s)))
649#define FREE(parser, p) (parser->m_mem.free_fcn((p)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800650
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800651
652XML_Parser XMLCALL
653XML_ParserCreate(const XML_Char *encodingName)
654{
655 return XML_ParserCreate_MM(encodingName, NULL, NULL);
656}
657
658XML_Parser XMLCALL
659XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
660{
661 XML_Char tmp[2];
662 *tmp = nsSep;
663 return XML_ParserCreate_MM(encodingName, NULL, tmp);
664}
665
666static const XML_Char implicitContext[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -0700667 ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
Elliott Hughes35e432d2012-09-09 14:23:38 -0700668 ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
Elliott Hughesd07d5a72009-09-25 16:04:37 -0700669 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
670 ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
671 ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
672 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800673};
674
Elliott Hughes72472942018-01-10 08:36:10 -0800675
676/* To avoid warnings about unused functions: */
677#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
678
679#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
680
681/* Obtain entropy on Linux 3.17+ */
682static int
683writeRandomBytes_getrandom_nonblock(void * target, size_t count) {
684 int success = 0; /* full count bytes written? */
685 size_t bytesWrittenTotal = 0;
686 const unsigned int getrandomFlags = GRND_NONBLOCK;
687
688 do {
689 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
690 const size_t bytesToWrite = count - bytesWrittenTotal;
691
692 const int bytesWrittenMore =
693#if defined(HAVE_GETRANDOM)
694 getrandom(currentTarget, bytesToWrite, getrandomFlags);
695#else
696 syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
697#endif
698
699 if (bytesWrittenMore > 0) {
700 bytesWrittenTotal += bytesWrittenMore;
701 if (bytesWrittenTotal >= count)
702 success = 1;
703 }
704 } while (! success && (errno == EINTR));
705
706 return success;
707}
708
709#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
710
711
712#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
713
714/* Extract entropy from /dev/urandom */
715static int
716writeRandomBytes_dev_urandom(void * target, size_t count) {
717 int success = 0; /* full count bytes written? */
718 size_t bytesWrittenTotal = 0;
719
720 const int fd = open("/dev/urandom", O_RDONLY);
721 if (fd < 0) {
722 return 0;
723 }
724
725 do {
726 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
727 const size_t bytesToWrite = count - bytesWrittenTotal;
728
729 const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
730
731 if (bytesWrittenMore > 0) {
732 bytesWrittenTotal += bytesWrittenMore;
733 if (bytesWrittenTotal >= count)
734 success = 1;
735 }
736 } while (! success && (errno == EINTR));
737
738 close(fd);
739 return success;
740}
741
742#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
743
744#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
745
746
747#if defined(HAVE_ARC4RANDOM)
748
749static void
750writeRandomBytes_arc4random(void * target, size_t count) {
751 size_t bytesWrittenTotal = 0;
752
753 while (bytesWrittenTotal < count) {
754 const uint32_t random32 = arc4random();
755 size_t i = 0;
756
757 for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
758 i++, bytesWrittenTotal++) {
759 const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
760 ((uint8_t *)target)[bytesWrittenTotal] = random8;
761 }
762 }
763}
764
765#endif /* defined(HAVE_ARC4RANDOM) */
766
767
768#ifdef _WIN32
769
770typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
771HMODULE _Expat_LoadLibrary(LPCTSTR filename); /* see loadlibrary.c */
772
773/* Obtain entropy on Windows XP / Windows Server 2003 and later.
774 * Hint on RtlGenRandom and the following article from libsodium.
775 *
776 * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
777 * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
778 */
779static int
780writeRandomBytes_RtlGenRandom(void * target, size_t count) {
781 int success = 0; /* full count bytes written? */
782 const HMODULE advapi32 = _Expat_LoadLibrary(TEXT("ADVAPI32.DLL"));
783
784 if (advapi32) {
785 const RTLGENRANDOM_FUNC RtlGenRandom
786 = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
787 if (RtlGenRandom) {
788 if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
789 success = 1;
790 }
791 }
792 FreeLibrary(advapi32);
793 }
794
795 return success;
796}
797
798#endif /* _WIN32 */
799
800
801#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
802
Elliott Hughes35e432d2012-09-09 14:23:38 -0700803static unsigned long
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100804gather_time_entropy(void)
Elliott Hughes35e432d2012-09-09 14:23:38 -0700805{
Elliott Hughes72472942018-01-10 08:36:10 -0800806#ifdef _WIN32
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100807 FILETIME ft;
808 GetSystemTimeAsFileTime(&ft); /* never fails */
809 return ft.dwHighDateTime ^ ft.dwLowDateTime;
810#else
811 struct timeval tv;
812 int gettimeofday_res;
813
814 gettimeofday_res = gettimeofday(&tv, NULL);
Elliott Hughes72472942018-01-10 08:36:10 -0800815
816#if defined(NDEBUG)
817 (void)gettimeofday_res;
818#else
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100819 assert (gettimeofday_res == 0);
Elliott Hughes72472942018-01-10 08:36:10 -0800820#endif /* defined(NDEBUG) */
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100821
822 /* Microseconds time is <20 bits entropy */
823 return tv.tv_usec;
824#endif
825}
826
Elliott Hughes72472942018-01-10 08:36:10 -0800827#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
828
829
830static unsigned long
831ENTROPY_DEBUG(const char * label, unsigned long entropy) {
832 const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
833 if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
834 fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
835 label,
836 (int)sizeof(entropy) * 2, entropy,
837 (unsigned long)sizeof(entropy));
838 }
839 return entropy;
840}
841
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100842static unsigned long
843generate_hash_secret_salt(XML_Parser parser)
844{
Elliott Hughes72472942018-01-10 08:36:10 -0800845 unsigned long entropy;
846 (void)parser;
847
848 /* "Failproof" high quality providers: */
849#if defined(HAVE_ARC4RANDOM_BUF)
850 arc4random_buf(&entropy, sizeof(entropy));
851 return ENTROPY_DEBUG("arc4random_buf", entropy);
852#elif defined(HAVE_ARC4RANDOM)
853 writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
854 return ENTROPY_DEBUG("arc4random", entropy);
855#else
856 /* Try high quality providers first .. */
857#ifdef _WIN32
858 if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
859 return ENTROPY_DEBUG("RtlGenRandom", entropy);
860 }
861#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
862 if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
863 return ENTROPY_DEBUG("getrandom", entropy);
864 }
865#endif
866#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
867 if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
868 return ENTROPY_DEBUG("/dev/urandom", entropy);
869 }
870#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
871 /* .. and self-made low quality for backup: */
872
873 /* Process ID is 0 bits entropy if attacker has local access */
874 entropy = gather_time_entropy() ^ getpid();
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100875
876 /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
877 if (sizeof(unsigned long) == 4) {
Elliott Hughes72472942018-01-10 08:36:10 -0800878 return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100879 } else {
Elliott Hughes72472942018-01-10 08:36:10 -0800880 return ENTROPY_DEBUG("fallback(8)",
881 entropy * (unsigned long)2305843009213693951ULL);
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100882 }
Elliott Hughes72472942018-01-10 08:36:10 -0800883#endif
884}
885
886static unsigned long
887get_hash_secret_salt(XML_Parser parser) {
888 if (parser->m_parentParser != NULL)
889 return get_hash_secret_salt(parser->m_parentParser);
890 return parser->m_hash_secret_salt;
Elliott Hughes35e432d2012-09-09 14:23:38 -0700891}
892
893static XML_Bool /* only valid for root parser */
894startParsing(XML_Parser parser)
895{
896 /* hash functions must be initialized before setContext() is called */
Elliott Hughes72472942018-01-10 08:36:10 -0800897 if (parser->m_hash_secret_salt == 0)
898 parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
899 if (parser->m_ns) {
Elliott Hughes35e432d2012-09-09 14:23:38 -0700900 /* implicit context only set for root parser, since child
901 parsers (i.e. external entity parsers) will inherit it
902 */
903 return setContext(parser, implicitContext);
904 }
905 return XML_TRUE;
906}
907
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800908XML_Parser XMLCALL
909XML_ParserCreate_MM(const XML_Char *encodingName,
910 const XML_Memory_Handling_Suite *memsuite,
911 const XML_Char *nameSep)
912{
Elliott Hughes35e432d2012-09-09 14:23:38 -0700913 return parserCreate(encodingName, memsuite, nameSep, NULL);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800914}
915
916static XML_Parser
917parserCreate(const XML_Char *encodingName,
918 const XML_Memory_Handling_Suite *memsuite,
919 const XML_Char *nameSep,
920 DTD *dtd)
921{
922 XML_Parser parser;
923
924 if (memsuite) {
925 XML_Memory_Handling_Suite *mtemp;
926 parser = (XML_Parser)
927 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
928 if (parser != NULL) {
929 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
930 mtemp->malloc_fcn = memsuite->malloc_fcn;
931 mtemp->realloc_fcn = memsuite->realloc_fcn;
932 mtemp->free_fcn = memsuite->free_fcn;
933 }
934 }
935 else {
936 XML_Memory_Handling_Suite *mtemp;
937 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
938 if (parser != NULL) {
939 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
940 mtemp->malloc_fcn = malloc;
941 mtemp->realloc_fcn = realloc;
942 mtemp->free_fcn = free;
943 }
944 }
945
946 if (!parser)
947 return parser;
948
Elliott Hughes72472942018-01-10 08:36:10 -0800949 parser->m_buffer = NULL;
950 parser->m_bufferLim = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800951
Elliott Hughes72472942018-01-10 08:36:10 -0800952 parser->m_attsSize = INIT_ATTS_SIZE;
953 parser->m_atts = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
954 if (parser->m_atts == NULL) {
955 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800956 return NULL;
957 }
Elliott Hughes35e432d2012-09-09 14:23:38 -0700958#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -0800959 parser->m_attInfo = (XML_AttrInfo*)MALLOC(parser, parser->m_attsSize * sizeof(XML_AttrInfo));
960 if (parser->m_attInfo == NULL) {
961 FREE(parser, parser->m_atts);
962 FREE(parser, parser);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700963 return NULL;
964 }
965#endif
Elliott Hughes72472942018-01-10 08:36:10 -0800966 parser->m_dataBuf = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
967 if (parser->m_dataBuf == NULL) {
968 FREE(parser, parser->m_atts);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700969#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -0800970 FREE(parser, parser->m_attInfo);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700971#endif
Elliott Hughes72472942018-01-10 08:36:10 -0800972 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800973 return NULL;
974 }
Elliott Hughes72472942018-01-10 08:36:10 -0800975 parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800976
977 if (dtd)
Elliott Hughes72472942018-01-10 08:36:10 -0800978 parser->m_dtd = dtd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800979 else {
Elliott Hughes72472942018-01-10 08:36:10 -0800980 parser->m_dtd = dtdCreate(&parser->m_mem);
981 if (parser->m_dtd == NULL) {
982 FREE(parser, parser->m_dataBuf);
983 FREE(parser, parser->m_atts);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700984#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -0800985 FREE(parser, parser->m_attInfo);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700986#endif
Elliott Hughes72472942018-01-10 08:36:10 -0800987 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800988 return NULL;
989 }
990 }
991
Elliott Hughes72472942018-01-10 08:36:10 -0800992 parser->m_freeBindingList = NULL;
993 parser->m_freeTagList = NULL;
994 parser->m_freeInternalEntities = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800995
Elliott Hughes72472942018-01-10 08:36:10 -0800996 parser->m_groupSize = 0;
997 parser->m_groupConnector = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800998
Elliott Hughes72472942018-01-10 08:36:10 -0800999 parser->m_unknownEncodingHandler = NULL;
1000 parser->m_unknownEncodingHandlerData = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001001
Elliott Hughes72472942018-01-10 08:36:10 -08001002 parser->m_namespaceSeparator = ASCII_EXCL;
1003 parser->m_ns = XML_FALSE;
1004 parser->m_ns_triplets = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001005
Elliott Hughes72472942018-01-10 08:36:10 -08001006 parser->m_nsAtts = NULL;
1007 parser->m_nsAttsVersion = 0;
1008 parser->m_nsAttsPower = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001009
Elliott Hughes72472942018-01-10 08:36:10 -08001010 parser->m_protocolEncodingName = NULL;
1011
1012 poolInit(&parser->m_tempPool, &(parser->m_mem));
1013 poolInit(&parser->m_temp2Pool, &(parser->m_mem));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001014 parserInit(parser, encodingName);
1015
Elliott Hughes72472942018-01-10 08:36:10 -08001016 if (encodingName && !parser->m_protocolEncodingName) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001017 XML_ParserFree(parser);
1018 return NULL;
1019 }
1020
1021 if (nameSep) {
Elliott Hughes72472942018-01-10 08:36:10 -08001022 parser->m_ns = XML_TRUE;
1023 parser->m_internalEncoding = XmlGetInternalEncodingNS();
1024 parser->m_namespaceSeparator = *nameSep;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001025 }
1026 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001027 parser->m_internalEncoding = XmlGetInternalEncoding();
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001028 }
1029
1030 return parser;
1031}
1032
1033static void
1034parserInit(XML_Parser parser, const XML_Char *encodingName)
1035{
Elliott Hughes72472942018-01-10 08:36:10 -08001036 parser->m_processor = prologInitProcessor;
1037 XmlPrologStateInit(&parser->m_prologState);
1038 if (encodingName != NULL) {
1039 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1040 }
1041 parser->m_curBase = NULL;
1042 XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
1043 parser->m_userData = NULL;
1044 parser->m_handlerArg = NULL;
1045 parser->m_startElementHandler = NULL;
1046 parser->m_endElementHandler = NULL;
1047 parser->m_characterDataHandler = NULL;
1048 parser->m_processingInstructionHandler = NULL;
1049 parser->m_commentHandler = NULL;
1050 parser->m_startCdataSectionHandler = NULL;
1051 parser->m_endCdataSectionHandler = NULL;
1052 parser->m_defaultHandler = NULL;
1053 parser->m_startDoctypeDeclHandler = NULL;
1054 parser->m_endDoctypeDeclHandler = NULL;
1055 parser->m_unparsedEntityDeclHandler = NULL;
1056 parser->m_notationDeclHandler = NULL;
1057 parser->m_startNamespaceDeclHandler = NULL;
1058 parser->m_endNamespaceDeclHandler = NULL;
1059 parser->m_notStandaloneHandler = NULL;
1060 parser->m_externalEntityRefHandler = NULL;
1061 parser->m_externalEntityRefHandlerArg = parser;
1062 parser->m_skippedEntityHandler = NULL;
1063 parser->m_elementDeclHandler = NULL;
1064 parser->m_attlistDeclHandler = NULL;
1065 parser->m_entityDeclHandler = NULL;
1066 parser->m_xmlDeclHandler = NULL;
1067 parser->m_bufferPtr = parser->m_buffer;
1068 parser->m_bufferEnd = parser->m_buffer;
1069 parser->m_parseEndByteIndex = 0;
1070 parser->m_parseEndPtr = NULL;
1071 parser->m_declElementType = NULL;
1072 parser->m_declAttributeId = NULL;
1073 parser->m_declEntity = NULL;
1074 parser->m_doctypeName = NULL;
1075 parser->m_doctypeSysid = NULL;
1076 parser->m_doctypePubid = NULL;
1077 parser->m_declAttributeType = NULL;
1078 parser->m_declNotationName = NULL;
1079 parser->m_declNotationPublicId = NULL;
1080 parser->m_declAttributeIsCdata = XML_FALSE;
1081 parser->m_declAttributeIsId = XML_FALSE;
1082 memset(&parser->m_position, 0, sizeof(POSITION));
1083 parser->m_errorCode = XML_ERROR_NONE;
1084 parser->m_eventPtr = NULL;
1085 parser->m_eventEndPtr = NULL;
1086 parser->m_positionPtr = NULL;
1087 parser->m_openInternalEntities = NULL;
1088 parser->m_defaultExpandInternalEntities = XML_TRUE;
1089 parser->m_tagLevel = 0;
1090 parser->m_tagStack = NULL;
1091 parser->m_inheritedBindings = NULL;
1092 parser->m_nSpecifiedAtts = 0;
1093 parser->m_unknownEncodingMem = NULL;
1094 parser->m_unknownEncodingRelease = NULL;
1095 parser->m_unknownEncodingData = NULL;
1096 parser->m_parentParser = NULL;
1097 parser->m_parsingStatus.parsing = XML_INITIALIZED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001098#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001099 parser->m_isParamEntity = XML_FALSE;
1100 parser->m_useForeignDTD = XML_FALSE;
1101 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001102#endif
Elliott Hughes72472942018-01-10 08:36:10 -08001103 parser->m_hash_secret_salt = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001104}
1105
Elliott Hughes72472942018-01-10 08:36:10 -08001106/* moves list of bindings to m_freeBindingList */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001107static void FASTCALL
1108moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
1109{
1110 while (bindings) {
1111 BINDING *b = bindings;
1112 bindings = bindings->nextTagBinding;
Elliott Hughes72472942018-01-10 08:36:10 -08001113 b->nextTagBinding = parser->m_freeBindingList;
1114 parser->m_freeBindingList = b;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001115 }
1116}
1117
1118XML_Bool XMLCALL
1119XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
1120{
1121 TAG *tStk;
1122 OPEN_INTERNAL_ENTITY *openEntityList;
Elliott Hughes72472942018-01-10 08:36:10 -08001123
1124 if (parser == NULL)
1125 return XML_FALSE;
1126
1127 if (parser->m_parentParser)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001128 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08001129 /* move m_tagStack to m_freeTagList */
1130 tStk = parser->m_tagStack;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001131 while (tStk) {
1132 TAG *tag = tStk;
1133 tStk = tStk->parent;
Elliott Hughes72472942018-01-10 08:36:10 -08001134 tag->parent = parser->m_freeTagList;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001135 moveToFreeBindingList(parser, tag->bindings);
1136 tag->bindings = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08001137 parser->m_freeTagList = tag;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001138 }
Elliott Hughes72472942018-01-10 08:36:10 -08001139 /* move m_openInternalEntities to m_freeInternalEntities */
1140 openEntityList = parser->m_openInternalEntities;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001141 while (openEntityList) {
1142 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
1143 openEntityList = openEntity->next;
Elliott Hughes72472942018-01-10 08:36:10 -08001144 openEntity->next = parser->m_freeInternalEntities;
1145 parser->m_freeInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001146 }
Elliott Hughes72472942018-01-10 08:36:10 -08001147 moveToFreeBindingList(parser, parser->m_inheritedBindings);
1148 FREE(parser, parser->m_unknownEncodingMem);
1149 if (parser->m_unknownEncodingRelease)
1150 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1151 poolClear(&parser->m_tempPool);
1152 poolClear(&parser->m_temp2Pool);
1153 FREE(parser, (void *)parser->m_protocolEncodingName);
1154 parser->m_protocolEncodingName = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001155 parserInit(parser, encodingName);
Elliott Hughes72472942018-01-10 08:36:10 -08001156 dtdReset(parser->m_dtd, &parser->m_mem);
Elliott Hughes35e432d2012-09-09 14:23:38 -07001157 return XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001158}
1159
1160enum XML_Status XMLCALL
1161XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
1162{
Elliott Hughes72472942018-01-10 08:36:10 -08001163 if (parser == NULL)
1164 return XML_STATUS_ERROR;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001165 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
1166 XXX There's no way for the caller to determine which of the
1167 XXX possible error cases caused the XML_STATUS_ERROR return.
1168 */
Elliott Hughes72472942018-01-10 08:36:10 -08001169 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001170 return XML_STATUS_ERROR;
Elliott Hughes72472942018-01-10 08:36:10 -08001171
1172 /* Get rid of any previous encoding name */
1173 FREE(parser, (void *)parser->m_protocolEncodingName);
1174
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001175 if (encodingName == NULL)
Elliott Hughes72472942018-01-10 08:36:10 -08001176 /* No new encoding name */
1177 parser->m_protocolEncodingName = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001178 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001179 /* Copy the new encoding name into allocated memory */
1180 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1181 if (!parser->m_protocolEncodingName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001182 return XML_STATUS_ERROR;
1183 }
1184 return XML_STATUS_OK;
1185}
1186
1187XML_Parser XMLCALL
1188XML_ExternalEntityParserCreate(XML_Parser oldParser,
1189 const XML_Char *context,
1190 const XML_Char *encodingName)
1191{
1192 XML_Parser parser = oldParser;
1193 DTD *newDtd = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08001194 DTD *oldDtd;
1195 XML_StartElementHandler oldStartElementHandler;
1196 XML_EndElementHandler oldEndElementHandler;
1197 XML_CharacterDataHandler oldCharacterDataHandler;
1198 XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
1199 XML_CommentHandler oldCommentHandler;
1200 XML_StartCdataSectionHandler oldStartCdataSectionHandler;
1201 XML_EndCdataSectionHandler oldEndCdataSectionHandler;
1202 XML_DefaultHandler oldDefaultHandler;
1203 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
1204 XML_NotationDeclHandler oldNotationDeclHandler;
1205 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
1206 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
1207 XML_NotStandaloneHandler oldNotStandaloneHandler;
1208 XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
1209 XML_SkippedEntityHandler oldSkippedEntityHandler;
1210 XML_UnknownEncodingHandler oldUnknownEncodingHandler;
1211 XML_ElementDeclHandler oldElementDeclHandler;
1212 XML_AttlistDeclHandler oldAttlistDeclHandler;
1213 XML_EntityDeclHandler oldEntityDeclHandler;
1214 XML_XmlDeclHandler oldXmlDeclHandler;
1215 ELEMENT_TYPE * oldDeclElementType;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001216
Elliott Hughes72472942018-01-10 08:36:10 -08001217 void *oldUserData;
1218 void *oldHandlerArg;
1219 XML_Bool oldDefaultExpandInternalEntities;
1220 XML_Parser oldExternalEntityRefHandlerArg;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001221#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001222 enum XML_ParamEntityParsing oldParamEntityParsing;
1223 int oldInEntityValue;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001224#endif
Elliott Hughes72472942018-01-10 08:36:10 -08001225 XML_Bool oldns_triplets;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001226 /* Note that the new parser shares the same hash secret as the old
1227 parser, so that dtdCopy and copyEntityTable can lookup values
1228 from hash tables associated with either parser without us having
1229 to worry which hash secrets each table has.
1230 */
Elliott Hughes72472942018-01-10 08:36:10 -08001231 unsigned long oldhash_secret_salt;
1232
1233 /* Validate the oldParser parameter before we pull everything out of it */
1234 if (oldParser == NULL)
1235 return NULL;
1236
1237 /* Stash the original parser contents on the stack */
1238 oldDtd = parser->m_dtd;
1239 oldStartElementHandler = parser->m_startElementHandler;
1240 oldEndElementHandler = parser->m_endElementHandler;
1241 oldCharacterDataHandler = parser->m_characterDataHandler;
1242 oldProcessingInstructionHandler = parser->m_processingInstructionHandler;
1243 oldCommentHandler = parser->m_commentHandler;
1244 oldStartCdataSectionHandler = parser->m_startCdataSectionHandler;
1245 oldEndCdataSectionHandler = parser->m_endCdataSectionHandler;
1246 oldDefaultHandler = parser->m_defaultHandler;
1247 oldUnparsedEntityDeclHandler = parser->m_unparsedEntityDeclHandler;
1248 oldNotationDeclHandler = parser->m_notationDeclHandler;
1249 oldStartNamespaceDeclHandler = parser->m_startNamespaceDeclHandler;
1250 oldEndNamespaceDeclHandler = parser->m_endNamespaceDeclHandler;
1251 oldNotStandaloneHandler = parser->m_notStandaloneHandler;
1252 oldExternalEntityRefHandler = parser->m_externalEntityRefHandler;
1253 oldSkippedEntityHandler = parser->m_skippedEntityHandler;
1254 oldUnknownEncodingHandler = parser->m_unknownEncodingHandler;
1255 oldElementDeclHandler = parser->m_elementDeclHandler;
1256 oldAttlistDeclHandler = parser->m_attlistDeclHandler;
1257 oldEntityDeclHandler = parser->m_entityDeclHandler;
1258 oldXmlDeclHandler = parser->m_xmlDeclHandler;
1259 oldDeclElementType = parser->m_declElementType;
1260
1261 oldUserData = parser->m_userData;
1262 oldHandlerArg = parser->m_handlerArg;
1263 oldDefaultExpandInternalEntities = parser->m_defaultExpandInternalEntities;
1264 oldExternalEntityRefHandlerArg = parser->m_externalEntityRefHandlerArg;
1265#ifdef XML_DTD
1266 oldParamEntityParsing = parser->m_paramEntityParsing;
1267 oldInEntityValue = parser->m_prologState.inEntityValue;
1268#endif
1269 oldns_triplets = parser->m_ns_triplets;
1270 /* Note that the new parser shares the same hash secret as the old
1271 parser, so that dtdCopy and copyEntityTable can lookup values
1272 from hash tables associated with either parser without us having
1273 to worry which hash secrets each table has.
1274 */
1275 oldhash_secret_salt = parser->m_hash_secret_salt;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001276
1277#ifdef XML_DTD
1278 if (!context)
1279 newDtd = oldDtd;
1280#endif /* XML_DTD */
1281
1282 /* Note that the magical uses of the pre-processor to make field
1283 access look more like C++ require that `parser' be overwritten
1284 here. This makes this function more painful to follow than it
1285 would be otherwise.
1286 */
Elliott Hughes72472942018-01-10 08:36:10 -08001287 if (parser->m_ns) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001288 XML_Char tmp[2];
Elliott Hughes72472942018-01-10 08:36:10 -08001289 *tmp = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001290 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1291 }
1292 else {
1293 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1294 }
1295
1296 if (!parser)
1297 return NULL;
1298
Elliott Hughes72472942018-01-10 08:36:10 -08001299 parser->m_startElementHandler = oldStartElementHandler;
1300 parser->m_endElementHandler = oldEndElementHandler;
1301 parser->m_characterDataHandler = oldCharacterDataHandler;
1302 parser->m_processingInstructionHandler = oldProcessingInstructionHandler;
1303 parser->m_commentHandler = oldCommentHandler;
1304 parser->m_startCdataSectionHandler = oldStartCdataSectionHandler;
1305 parser->m_endCdataSectionHandler = oldEndCdataSectionHandler;
1306 parser->m_defaultHandler = oldDefaultHandler;
1307 parser->m_unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1308 parser->m_notationDeclHandler = oldNotationDeclHandler;
1309 parser->m_startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1310 parser->m_endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1311 parser->m_notStandaloneHandler = oldNotStandaloneHandler;
1312 parser->m_externalEntityRefHandler = oldExternalEntityRefHandler;
1313 parser->m_skippedEntityHandler = oldSkippedEntityHandler;
1314 parser->m_unknownEncodingHandler = oldUnknownEncodingHandler;
1315 parser->m_elementDeclHandler = oldElementDeclHandler;
1316 parser->m_attlistDeclHandler = oldAttlistDeclHandler;
1317 parser->m_entityDeclHandler = oldEntityDeclHandler;
1318 parser->m_xmlDeclHandler = oldXmlDeclHandler;
1319 parser->m_declElementType = oldDeclElementType;
1320 parser->m_userData = oldUserData;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001321 if (oldUserData == oldHandlerArg)
Elliott Hughes72472942018-01-10 08:36:10 -08001322 parser->m_handlerArg = parser->m_userData;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001323 else
Elliott Hughes72472942018-01-10 08:36:10 -08001324 parser->m_handlerArg = parser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001325 if (oldExternalEntityRefHandlerArg != oldParser)
Elliott Hughes72472942018-01-10 08:36:10 -08001326 parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1327 parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1328 parser->m_ns_triplets = oldns_triplets;
1329 parser->m_hash_secret_salt = oldhash_secret_salt;
1330 parser->m_parentParser = oldParser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001331#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001332 parser->m_paramEntityParsing = oldParamEntityParsing;
1333 parser->m_prologState.inEntityValue = oldInEntityValue;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001334 if (context) {
1335#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08001336 if (!dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001337 || !setContext(parser, context)) {
1338 XML_ParserFree(parser);
1339 return NULL;
1340 }
Elliott Hughes72472942018-01-10 08:36:10 -08001341 parser->m_processor = externalEntityInitProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001342#ifdef XML_DTD
1343 }
1344 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001345 /* The DTD instance referenced by parser->m_dtd is shared between the document's
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001346 root parser and external PE parsers, therefore one does not need to
1347 call setContext. In addition, one also *must* not call setContext,
1348 because this would overwrite existing prefix->binding pointers in
Elliott Hughes72472942018-01-10 08:36:10 -08001349 parser->m_dtd with ones that get destroyed with the external PE parser.
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001350 This would leave those prefixes with dangling pointers.
1351 */
Elliott Hughes72472942018-01-10 08:36:10 -08001352 parser->m_isParamEntity = XML_TRUE;
1353 XmlPrologStateInitExternalEntity(&parser->m_prologState);
1354 parser->m_processor = externalParEntInitProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001355 }
1356#endif /* XML_DTD */
1357 return parser;
1358}
1359
1360static void FASTCALL
1361destroyBindings(BINDING *bindings, XML_Parser parser)
1362{
1363 for (;;) {
1364 BINDING *b = bindings;
1365 if (!b)
1366 break;
1367 bindings = b->nextTagBinding;
Elliott Hughes72472942018-01-10 08:36:10 -08001368 FREE(parser, b->uri);
1369 FREE(parser, b);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001370 }
1371}
1372
1373void XMLCALL
1374XML_ParserFree(XML_Parser parser)
1375{
1376 TAG *tagList;
1377 OPEN_INTERNAL_ENTITY *entityList;
1378 if (parser == NULL)
1379 return;
Elliott Hughes72472942018-01-10 08:36:10 -08001380 /* free m_tagStack and m_freeTagList */
1381 tagList = parser->m_tagStack;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001382 for (;;) {
1383 TAG *p;
1384 if (tagList == NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08001385 if (parser->m_freeTagList == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001386 break;
Elliott Hughes72472942018-01-10 08:36:10 -08001387 tagList = parser->m_freeTagList;
1388 parser->m_freeTagList = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001389 }
1390 p = tagList;
1391 tagList = tagList->parent;
Elliott Hughes72472942018-01-10 08:36:10 -08001392 FREE(parser, p->buf);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001393 destroyBindings(p->bindings, parser);
Elliott Hughes72472942018-01-10 08:36:10 -08001394 FREE(parser, p);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001395 }
Elliott Hughes72472942018-01-10 08:36:10 -08001396 /* free m_openInternalEntities and m_freeInternalEntities */
1397 entityList = parser->m_openInternalEntities;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001398 for (;;) {
1399 OPEN_INTERNAL_ENTITY *openEntity;
1400 if (entityList == NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08001401 if (parser->m_freeInternalEntities == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001402 break;
Elliott Hughes72472942018-01-10 08:36:10 -08001403 entityList = parser->m_freeInternalEntities;
1404 parser->m_freeInternalEntities = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001405 }
1406 openEntity = entityList;
1407 entityList = entityList->next;
Elliott Hughes72472942018-01-10 08:36:10 -08001408 FREE(parser, openEntity);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001409 }
1410
Elliott Hughes72472942018-01-10 08:36:10 -08001411 destroyBindings(parser->m_freeBindingList, parser);
1412 destroyBindings(parser->m_inheritedBindings, parser);
1413 poolDestroy(&parser->m_tempPool);
1414 poolDestroy(&parser->m_temp2Pool);
1415 FREE(parser, (void *)parser->m_protocolEncodingName);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001416#ifdef XML_DTD
1417 /* external parameter entity parsers share the DTD structure
1418 parser->m_dtd with the root parser, so we must not destroy it
1419 */
Elliott Hughes72472942018-01-10 08:36:10 -08001420 if (!parser->m_isParamEntity && parser->m_dtd)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001421#else
Elliott Hughes72472942018-01-10 08:36:10 -08001422 if (parser->m_dtd)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001423#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08001424 dtdDestroy(parser->m_dtd, (XML_Bool)!parser->m_parentParser, &parser->m_mem);
1425 FREE(parser, (void *)parser->m_atts);
Elliott Hughes35e432d2012-09-09 14:23:38 -07001426#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08001427 FREE(parser, (void *)parser->m_attInfo);
Elliott Hughes35e432d2012-09-09 14:23:38 -07001428#endif
Elliott Hughes72472942018-01-10 08:36:10 -08001429 FREE(parser, parser->m_groupConnector);
1430 FREE(parser, parser->m_buffer);
1431 FREE(parser, parser->m_dataBuf);
1432 FREE(parser, parser->m_nsAtts);
1433 FREE(parser, parser->m_unknownEncodingMem);
1434 if (parser->m_unknownEncodingRelease)
1435 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1436 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001437}
1438
1439void XMLCALL
1440XML_UseParserAsHandlerArg(XML_Parser parser)
1441{
Elliott Hughes72472942018-01-10 08:36:10 -08001442 if (parser != NULL)
1443 parser->m_handlerArg = parser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001444}
1445
1446enum XML_Error XMLCALL
1447XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1448{
Elliott Hughes72472942018-01-10 08:36:10 -08001449 if (parser == NULL)
1450 return XML_ERROR_INVALID_ARGUMENT;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001451#ifdef XML_DTD
1452 /* block after XML_Parse()/XML_ParseBuffer() has been called */
Elliott Hughes72472942018-01-10 08:36:10 -08001453 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001454 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
Elliott Hughes72472942018-01-10 08:36:10 -08001455 parser->m_useForeignDTD = useDTD;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001456 return XML_ERROR_NONE;
1457#else
1458 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1459#endif
1460}
1461
1462void XMLCALL
1463XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1464{
Elliott Hughes72472942018-01-10 08:36:10 -08001465 if (parser == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001466 return;
Elliott Hughes72472942018-01-10 08:36:10 -08001467 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1468 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1469 return;
1470 parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001471}
1472
1473void XMLCALL
1474XML_SetUserData(XML_Parser parser, void *p)
1475{
Elliott Hughes72472942018-01-10 08:36:10 -08001476 if (parser == NULL)
1477 return;
1478 if (parser->m_handlerArg == parser->m_userData)
1479 parser->m_handlerArg = parser->m_userData = p;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001480 else
Elliott Hughes72472942018-01-10 08:36:10 -08001481 parser->m_userData = p;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001482}
1483
1484enum XML_Status XMLCALL
1485XML_SetBase(XML_Parser parser, const XML_Char *p)
1486{
Elliott Hughes72472942018-01-10 08:36:10 -08001487 if (parser == NULL)
1488 return XML_STATUS_ERROR;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001489 if (p) {
Elliott Hughes72472942018-01-10 08:36:10 -08001490 p = poolCopyString(&parser->m_dtd->pool, p);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001491 if (!p)
1492 return XML_STATUS_ERROR;
Elliott Hughes72472942018-01-10 08:36:10 -08001493 parser->m_curBase = p;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001494 }
1495 else
Elliott Hughes72472942018-01-10 08:36:10 -08001496 parser->m_curBase = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001497 return XML_STATUS_OK;
1498}
1499
1500const XML_Char * XMLCALL
1501XML_GetBase(XML_Parser parser)
1502{
Elliott Hughes72472942018-01-10 08:36:10 -08001503 if (parser == NULL)
1504 return NULL;
1505 return parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001506}
1507
1508int XMLCALL
1509XML_GetSpecifiedAttributeCount(XML_Parser parser)
1510{
Elliott Hughes72472942018-01-10 08:36:10 -08001511 if (parser == NULL)
1512 return -1;
1513 return parser->m_nSpecifiedAtts;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001514}
1515
1516int XMLCALL
1517XML_GetIdAttributeIndex(XML_Parser parser)
1518{
Elliott Hughes72472942018-01-10 08:36:10 -08001519 if (parser == NULL)
1520 return -1;
1521 return parser->m_idAttIndex;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001522}
1523
Elliott Hughes35e432d2012-09-09 14:23:38 -07001524#ifdef XML_ATTR_INFO
1525const XML_AttrInfo * XMLCALL
1526XML_GetAttributeInfo(XML_Parser parser)
1527{
Elliott Hughes72472942018-01-10 08:36:10 -08001528 if (parser == NULL)
1529 return NULL;
1530 return parser->m_attInfo;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001531}
1532#endif
1533
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001534void XMLCALL
1535XML_SetElementHandler(XML_Parser parser,
1536 XML_StartElementHandler start,
1537 XML_EndElementHandler end)
1538{
Elliott Hughes72472942018-01-10 08:36:10 -08001539 if (parser == NULL)
1540 return;
1541 parser->m_startElementHandler = start;
1542 parser->m_endElementHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001543}
1544
1545void XMLCALL
1546XML_SetStartElementHandler(XML_Parser parser,
1547 XML_StartElementHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001548 if (parser != NULL)
1549 parser->m_startElementHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001550}
1551
1552void XMLCALL
1553XML_SetEndElementHandler(XML_Parser parser,
1554 XML_EndElementHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001555 if (parser != NULL)
1556 parser->m_endElementHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001557}
1558
1559void XMLCALL
1560XML_SetCharacterDataHandler(XML_Parser parser,
1561 XML_CharacterDataHandler handler)
1562{
Elliott Hughes72472942018-01-10 08:36:10 -08001563 if (parser != NULL)
1564 parser->m_characterDataHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001565}
1566
1567void XMLCALL
1568XML_SetProcessingInstructionHandler(XML_Parser parser,
1569 XML_ProcessingInstructionHandler handler)
1570{
Elliott Hughes72472942018-01-10 08:36:10 -08001571 if (parser != NULL)
1572 parser->m_processingInstructionHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001573}
1574
1575void XMLCALL
1576XML_SetCommentHandler(XML_Parser parser,
1577 XML_CommentHandler handler)
1578{
Elliott Hughes72472942018-01-10 08:36:10 -08001579 if (parser != NULL)
1580 parser->m_commentHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001581}
1582
1583void XMLCALL
1584XML_SetCdataSectionHandler(XML_Parser parser,
1585 XML_StartCdataSectionHandler start,
1586 XML_EndCdataSectionHandler end)
1587{
Elliott Hughes72472942018-01-10 08:36:10 -08001588 if (parser == NULL)
1589 return;
1590 parser->m_startCdataSectionHandler = start;
1591 parser->m_endCdataSectionHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001592}
1593
1594void XMLCALL
1595XML_SetStartCdataSectionHandler(XML_Parser parser,
1596 XML_StartCdataSectionHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001597 if (parser != NULL)
1598 parser->m_startCdataSectionHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001599}
1600
1601void XMLCALL
1602XML_SetEndCdataSectionHandler(XML_Parser parser,
1603 XML_EndCdataSectionHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001604 if (parser != NULL)
1605 parser->m_endCdataSectionHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001606}
1607
1608void XMLCALL
1609XML_SetDefaultHandler(XML_Parser parser,
1610 XML_DefaultHandler handler)
1611{
Elliott Hughes72472942018-01-10 08:36:10 -08001612 if (parser == NULL)
1613 return;
1614 parser->m_defaultHandler = handler;
1615 parser->m_defaultExpandInternalEntities = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001616}
1617
1618void XMLCALL
1619XML_SetDefaultHandlerExpand(XML_Parser parser,
1620 XML_DefaultHandler handler)
1621{
Elliott Hughes72472942018-01-10 08:36:10 -08001622 if (parser == NULL)
1623 return;
1624 parser->m_defaultHandler = handler;
1625 parser->m_defaultExpandInternalEntities = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001626}
1627
1628void XMLCALL
1629XML_SetDoctypeDeclHandler(XML_Parser parser,
1630 XML_StartDoctypeDeclHandler start,
1631 XML_EndDoctypeDeclHandler end)
1632{
Elliott Hughes72472942018-01-10 08:36:10 -08001633 if (parser == NULL)
1634 return;
1635 parser->m_startDoctypeDeclHandler = start;
1636 parser->m_endDoctypeDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001637}
1638
1639void XMLCALL
1640XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1641 XML_StartDoctypeDeclHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001642 if (parser != NULL)
1643 parser->m_startDoctypeDeclHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001644}
1645
1646void XMLCALL
1647XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1648 XML_EndDoctypeDeclHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001649 if (parser != NULL)
1650 parser->m_endDoctypeDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001651}
1652
1653void XMLCALL
1654XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1655 XML_UnparsedEntityDeclHandler handler)
1656{
Elliott Hughes72472942018-01-10 08:36:10 -08001657 if (parser != NULL)
1658 parser->m_unparsedEntityDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001659}
1660
1661void XMLCALL
1662XML_SetNotationDeclHandler(XML_Parser parser,
1663 XML_NotationDeclHandler handler)
1664{
Elliott Hughes72472942018-01-10 08:36:10 -08001665 if (parser != NULL)
1666 parser->m_notationDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001667}
1668
1669void XMLCALL
1670XML_SetNamespaceDeclHandler(XML_Parser parser,
1671 XML_StartNamespaceDeclHandler start,
1672 XML_EndNamespaceDeclHandler end)
1673{
Elliott Hughes72472942018-01-10 08:36:10 -08001674 if (parser == NULL)
1675 return;
1676 parser->m_startNamespaceDeclHandler = start;
1677 parser->m_endNamespaceDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001678}
1679
1680void XMLCALL
1681XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1682 XML_StartNamespaceDeclHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001683 if (parser != NULL)
1684 parser->m_startNamespaceDeclHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001685}
1686
1687void XMLCALL
1688XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1689 XML_EndNamespaceDeclHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001690 if (parser != NULL)
1691 parser->m_endNamespaceDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001692}
1693
1694void XMLCALL
1695XML_SetNotStandaloneHandler(XML_Parser parser,
1696 XML_NotStandaloneHandler handler)
1697{
Elliott Hughes72472942018-01-10 08:36:10 -08001698 if (parser != NULL)
1699 parser->m_notStandaloneHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001700}
1701
1702void XMLCALL
1703XML_SetExternalEntityRefHandler(XML_Parser parser,
1704 XML_ExternalEntityRefHandler handler)
1705{
Elliott Hughes72472942018-01-10 08:36:10 -08001706 if (parser != NULL)
1707 parser->m_externalEntityRefHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001708}
1709
1710void XMLCALL
1711XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1712{
Elliott Hughes72472942018-01-10 08:36:10 -08001713 if (parser == NULL)
1714 return;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001715 if (arg)
Elliott Hughes72472942018-01-10 08:36:10 -08001716 parser->m_externalEntityRefHandlerArg = (XML_Parser)arg;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001717 else
Elliott Hughes72472942018-01-10 08:36:10 -08001718 parser->m_externalEntityRefHandlerArg = parser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001719}
1720
1721void XMLCALL
1722XML_SetSkippedEntityHandler(XML_Parser parser,
1723 XML_SkippedEntityHandler handler)
1724{
Elliott Hughes72472942018-01-10 08:36:10 -08001725 if (parser != NULL)
1726 parser->m_skippedEntityHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001727}
1728
1729void XMLCALL
1730XML_SetUnknownEncodingHandler(XML_Parser parser,
1731 XML_UnknownEncodingHandler handler,
1732 void *data)
1733{
Elliott Hughes72472942018-01-10 08:36:10 -08001734 if (parser == NULL)
1735 return;
1736 parser->m_unknownEncodingHandler = handler;
1737 parser->m_unknownEncodingHandlerData = data;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001738}
1739
1740void XMLCALL
1741XML_SetElementDeclHandler(XML_Parser parser,
1742 XML_ElementDeclHandler eldecl)
1743{
Elliott Hughes72472942018-01-10 08:36:10 -08001744 if (parser != NULL)
1745 parser->m_elementDeclHandler = eldecl;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001746}
1747
1748void XMLCALL
1749XML_SetAttlistDeclHandler(XML_Parser parser,
1750 XML_AttlistDeclHandler attdecl)
1751{
Elliott Hughes72472942018-01-10 08:36:10 -08001752 if (parser != NULL)
1753 parser->m_attlistDeclHandler = attdecl;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001754}
1755
1756void XMLCALL
1757XML_SetEntityDeclHandler(XML_Parser parser,
1758 XML_EntityDeclHandler handler)
1759{
Elliott Hughes72472942018-01-10 08:36:10 -08001760 if (parser != NULL)
1761 parser->m_entityDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001762}
1763
1764void XMLCALL
1765XML_SetXmlDeclHandler(XML_Parser parser,
1766 XML_XmlDeclHandler handler) {
Elliott Hughes72472942018-01-10 08:36:10 -08001767 if (parser != NULL)
1768 parser->m_xmlDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001769}
1770
1771int XMLCALL
1772XML_SetParamEntityParsing(XML_Parser parser,
1773 enum XML_ParamEntityParsing peParsing)
1774{
Elliott Hughes72472942018-01-10 08:36:10 -08001775 if (parser == NULL)
1776 return 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001777 /* block after XML_Parse()/XML_ParseBuffer() has been called */
Elliott Hughes72472942018-01-10 08:36:10 -08001778 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001779 return 0;
1780#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001781 parser->m_paramEntityParsing = peParsing;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001782 return 1;
1783#else
1784 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1785#endif
1786}
1787
Elliott Hughes35e432d2012-09-09 14:23:38 -07001788int XMLCALL
1789XML_SetHashSalt(XML_Parser parser,
1790 unsigned long hash_salt)
1791{
Elliott Hughes72472942018-01-10 08:36:10 -08001792 if (parser == NULL)
Elliott Hughes35e432d2012-09-09 14:23:38 -07001793 return 0;
Elliott Hughes72472942018-01-10 08:36:10 -08001794 if (parser->m_parentParser)
1795 return XML_SetHashSalt(parser->m_parentParser, hash_salt);
1796 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1797 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1798 return 0;
1799 parser->m_hash_secret_salt = hash_salt;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001800 return 1;
1801}
1802
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001803enum XML_Status XMLCALL
1804XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1805{
Elliott Hughes72472942018-01-10 08:36:10 -08001806 if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
1807 if (parser != NULL)
1808 parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
1809 return XML_STATUS_ERROR;
1810 }
1811 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001812 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08001813 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001814 return XML_STATUS_ERROR;
1815 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08001816 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001817 return XML_STATUS_ERROR;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001818 case XML_INITIALIZED:
Elliott Hughes72472942018-01-10 08:36:10 -08001819 if (parser->m_parentParser == NULL && !startParsing(parser)) {
1820 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001821 return XML_STATUS_ERROR;
1822 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001823 default:
Elliott Hughes72472942018-01-10 08:36:10 -08001824 parser->m_parsingStatus.parsing = XML_PARSING;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001825 }
1826
1827 if (len == 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08001828 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001829 if (!isFinal)
1830 return XML_STATUS_OK;
Elliott Hughes72472942018-01-10 08:36:10 -08001831 parser->m_positionPtr = parser->m_bufferPtr;
1832 parser->m_parseEndPtr = parser->m_bufferEnd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001833
1834 /* If data are left over from last buffer, and we now know that these
1835 data are the final chunk of input, then we have to check them again
1836 to detect errors based on that fact.
1837 */
Elliott Hughes72472942018-01-10 08:36:10 -08001838 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 -08001839
Elliott Hughes72472942018-01-10 08:36:10 -08001840 if (parser->m_errorCode == XML_ERROR_NONE) {
1841 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001842 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08001843 /* It is hard to be certain, but it seems that this case
1844 * cannot occur. This code is cleaning up a previous parse
1845 * with no new data (since len == 0). Changing the parsing
1846 * state requires getting to execute a handler function, and
1847 * there doesn't seem to be an opportunity for that while in
1848 * this circumstance.
1849 *
1850 * Given the uncertainty, we retain the code but exclude it
1851 * from coverage tests.
1852 *
1853 * LCOV_EXCL_START
1854 */
1855 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
1856 parser->m_positionPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001857 return XML_STATUS_SUSPENDED;
Elliott Hughes72472942018-01-10 08:36:10 -08001858 /* LCOV_EXCL_STOP */
Elliott Hughes35e432d2012-09-09 14:23:38 -07001859 case XML_INITIALIZED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001860 case XML_PARSING:
Elliott Hughes72472942018-01-10 08:36:10 -08001861 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001862 /* fall through */
1863 default:
1864 return XML_STATUS_OK;
1865 }
1866 }
Elliott Hughes72472942018-01-10 08:36:10 -08001867 parser->m_eventEndPtr = parser->m_eventPtr;
1868 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001869 return XML_STATUS_ERROR;
1870 }
1871#ifndef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08001872 else if (parser->m_bufferPtr == parser->m_bufferEnd) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001873 const char *end;
1874 int nLeftOver;
Paul Duffinc05e0322016-05-04 10:42:31 +01001875 enum XML_Status result;
Elliott Hughes72472942018-01-10 08:36:10 -08001876 /* Detect overflow (a+b > MAX <==> b > MAX-a) */
1877 if (len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) {
1878 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1879 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1880 parser->m_processor = errorProcessor;
1881 return XML_STATUS_ERROR;
1882 }
1883 parser->m_parseEndByteIndex += len;
1884 parser->m_positionPtr = s;
1885 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001886
Elliott Hughes72472942018-01-10 08:36:10 -08001887 parser->m_errorCode = parser->m_processor(parser, s, parser->m_parseEndPtr = s + len, &end);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001888
Elliott Hughes72472942018-01-10 08:36:10 -08001889 if (parser->m_errorCode != XML_ERROR_NONE) {
1890 parser->m_eventEndPtr = parser->m_eventPtr;
1891 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001892 return XML_STATUS_ERROR;
1893 }
1894 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001895 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001896 case XML_SUSPENDED:
1897 result = XML_STATUS_SUSPENDED;
1898 break;
1899 case XML_INITIALIZED:
1900 case XML_PARSING:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001901 if (isFinal) {
Elliott Hughes72472942018-01-10 08:36:10 -08001902 parser->m_parsingStatus.parsing = XML_FINISHED;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001903 return XML_STATUS_OK;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001904 }
Elliott Hughes35e432d2012-09-09 14:23:38 -07001905 /* fall through */
1906 default:
1907 result = XML_STATUS_OK;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001908 }
1909 }
1910
Elliott Hughes72472942018-01-10 08:36:10 -08001911 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end, &parser->m_position);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001912 nLeftOver = s + len - end;
1913 if (nLeftOver) {
Elliott Hughes72472942018-01-10 08:36:10 -08001914 if (parser->m_buffer == NULL || nLeftOver > parser->m_bufferLim - parser->m_buffer) {
1915 /* avoid _signed_ integer overflow */
1916 char *temp = NULL;
1917 const int bytesToAllocate = (int)((unsigned)len * 2U);
1918 if (bytesToAllocate > 0) {
1919 temp = (char *)REALLOC(parser, parser->m_buffer, bytesToAllocate);
1920 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001921 if (temp == NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08001922 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1923 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1924 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001925 return XML_STATUS_ERROR;
1926 }
Elliott Hughes72472942018-01-10 08:36:10 -08001927 parser->m_buffer = temp;
1928 parser->m_bufferLim = parser->m_buffer + bytesToAllocate;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001929 }
Elliott Hughes72472942018-01-10 08:36:10 -08001930 memcpy(parser->m_buffer, end, nLeftOver);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001931 }
Elliott Hughes72472942018-01-10 08:36:10 -08001932 parser->m_bufferPtr = parser->m_buffer;
1933 parser->m_bufferEnd = parser->m_buffer + nLeftOver;
1934 parser->m_positionPtr = parser->m_bufferPtr;
1935 parser->m_parseEndPtr = parser->m_bufferEnd;
1936 parser->m_eventPtr = parser->m_bufferPtr;
1937 parser->m_eventEndPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001938 return result;
1939 }
1940#endif /* not defined XML_CONTEXT_BYTES */
1941 else {
1942 void *buff = XML_GetBuffer(parser, len);
1943 if (buff == NULL)
1944 return XML_STATUS_ERROR;
1945 else {
1946 memcpy(buff, s, len);
1947 return XML_ParseBuffer(parser, len, isFinal);
1948 }
1949 }
1950}
1951
1952enum XML_Status XMLCALL
1953XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1954{
1955 const char *start;
1956 enum XML_Status result = XML_STATUS_OK;
1957
Elliott Hughes72472942018-01-10 08:36:10 -08001958 if (parser == NULL)
1959 return XML_STATUS_ERROR;
1960 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001961 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08001962 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001963 return XML_STATUS_ERROR;
1964 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08001965 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001966 return XML_STATUS_ERROR;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001967 case XML_INITIALIZED:
Elliott Hughes72472942018-01-10 08:36:10 -08001968 if (parser->m_parentParser == NULL && !startParsing(parser)) {
1969 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001970 return XML_STATUS_ERROR;
1971 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001972 default:
Elliott Hughes72472942018-01-10 08:36:10 -08001973 parser->m_parsingStatus.parsing = XML_PARSING;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001974 }
1975
Elliott Hughes72472942018-01-10 08:36:10 -08001976 start = parser->m_bufferPtr;
1977 parser->m_positionPtr = start;
1978 parser->m_bufferEnd += len;
1979 parser->m_parseEndPtr = parser->m_bufferEnd;
1980 parser->m_parseEndByteIndex += len;
1981 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001982
Elliott Hughes72472942018-01-10 08:36:10 -08001983 parser->m_errorCode = parser->m_processor(parser, start, parser->m_parseEndPtr, &parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001984
Elliott Hughes72472942018-01-10 08:36:10 -08001985 if (parser->m_errorCode != XML_ERROR_NONE) {
1986 parser->m_eventEndPtr = parser->m_eventPtr;
1987 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001988 return XML_STATUS_ERROR;
1989 }
1990 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001991 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001992 case XML_SUSPENDED:
1993 result = XML_STATUS_SUSPENDED;
1994 break;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001995 case XML_INITIALIZED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001996 case XML_PARSING:
1997 if (isFinal) {
Elliott Hughes72472942018-01-10 08:36:10 -08001998 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001999 return result;
2000 }
2001 default: ; /* should not happen */
2002 }
2003 }
2004
Elliott Hughes72472942018-01-10 08:36:10 -08002005 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
2006 parser->m_positionPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002007 return result;
2008}
2009
2010void * XMLCALL
2011XML_GetBuffer(XML_Parser parser, int len)
2012{
Elliott Hughes72472942018-01-10 08:36:10 -08002013 if (parser == NULL)
2014 return NULL;
Paul Duffinc05e0322016-05-04 10:42:31 +01002015 if (len < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002016 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Paul Duffinc05e0322016-05-04 10:42:31 +01002017 return NULL;
2018 }
Elliott Hughes72472942018-01-10 08:36:10 -08002019 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002020 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08002021 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002022 return NULL;
2023 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08002024 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002025 return NULL;
2026 default: ;
2027 }
2028
Elliott Hughes72472942018-01-10 08:36:10 -08002029 if (len > parser->m_bufferLim - parser->m_bufferEnd) {
Paul Duffinba34a0c2017-02-27 14:40:16 +00002030#ifdef XML_CONTEXT_BYTES
2031 int keep;
2032#endif /* defined XML_CONTEXT_BYTES */
2033 /* Do not invoke signed arithmetic overflow: */
Elliott Hughes72472942018-01-10 08:36:10 -08002034 int neededSize = (int) ((unsigned)len + (unsigned)(parser->m_bufferEnd - parser->m_bufferPtr));
Paul Duffinc05e0322016-05-04 10:42:31 +01002035 if (neededSize < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002036 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Paul Duffinc05e0322016-05-04 10:42:31 +01002037 return NULL;
2038 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002039#ifdef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08002040 keep = (int)(parser->m_bufferPtr - parser->m_buffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002041 if (keep > XML_CONTEXT_BYTES)
2042 keep = XML_CONTEXT_BYTES;
2043 neededSize += keep;
2044#endif /* defined XML_CONTEXT_BYTES */
Elliott Hughes72472942018-01-10 08:36:10 -08002045 if (neededSize <= parser->m_bufferLim - parser->m_buffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002046#ifdef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08002047 if (keep < parser->m_bufferPtr - parser->m_buffer) {
2048 int offset = (int)(parser->m_bufferPtr - parser->m_buffer) - keep;
2049 memmove(parser->m_buffer, &parser->m_buffer[offset], parser->m_bufferEnd - parser->m_bufferPtr + keep);
2050 parser->m_bufferEnd -= offset;
2051 parser->m_bufferPtr -= offset;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002052 }
2053#else
Elliott Hughes72472942018-01-10 08:36:10 -08002054 memmove(parser->m_buffer, parser->m_bufferPtr, parser->m_bufferEnd - parser->m_bufferPtr);
2055 parser->m_bufferEnd = parser->m_buffer + (parser->m_bufferEnd - parser->m_bufferPtr);
2056 parser->m_bufferPtr = parser->m_buffer;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002057#endif /* not defined XML_CONTEXT_BYTES */
2058 }
2059 else {
2060 char *newBuf;
Elliott Hughes72472942018-01-10 08:36:10 -08002061 int bufferSize = (int)(parser->m_bufferLim - parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002062 if (bufferSize == 0)
2063 bufferSize = INIT_BUFFER_SIZE;
2064 do {
Paul Duffinba34a0c2017-02-27 14:40:16 +00002065 /* Do not invoke signed arithmetic overflow: */
2066 bufferSize = (int) (2U * (unsigned) bufferSize);
Paul Duffinc05e0322016-05-04 10:42:31 +01002067 } while (bufferSize < neededSize && bufferSize > 0);
2068 if (bufferSize <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002069 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Paul Duffinc05e0322016-05-04 10:42:31 +01002070 return NULL;
2071 }
Elliott Hughes72472942018-01-10 08:36:10 -08002072 newBuf = (char *)MALLOC(parser, bufferSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002073 if (newBuf == 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002074 parser->m_errorCode = XML_ERROR_NO_MEMORY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002075 return NULL;
2076 }
Elliott Hughes72472942018-01-10 08:36:10 -08002077 parser->m_bufferLim = newBuf + bufferSize;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002078#ifdef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08002079 if (parser->m_bufferPtr) {
2080 int keep = (int)(parser->m_bufferPtr - parser->m_buffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002081 if (keep > XML_CONTEXT_BYTES)
2082 keep = XML_CONTEXT_BYTES;
Elliott Hughes72472942018-01-10 08:36:10 -08002083 memcpy(newBuf, &parser->m_bufferPtr[-keep], parser->m_bufferEnd - parser->m_bufferPtr + keep);
2084 FREE(parser, parser->m_buffer);
2085 parser->m_buffer = newBuf;
2086 parser->m_bufferEnd = parser->m_buffer + (parser->m_bufferEnd - parser->m_bufferPtr) + keep;
2087 parser->m_bufferPtr = parser->m_buffer + keep;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002088 }
2089 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002090 parser->m_bufferEnd = newBuf + (parser->m_bufferEnd - parser->m_bufferPtr);
2091 parser->m_bufferPtr = parser->m_buffer = newBuf;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002092 }
2093#else
Elliott Hughes72472942018-01-10 08:36:10 -08002094 if (parser->m_bufferPtr) {
2095 memcpy(newBuf, parser->m_bufferPtr, parser->m_bufferEnd - parser->m_bufferPtr);
2096 FREE(parser, parser->m_buffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002097 }
Elliott Hughes72472942018-01-10 08:36:10 -08002098 parser->m_bufferEnd = newBuf + (parser->m_bufferEnd - parser->m_bufferPtr);
2099 parser->m_bufferPtr = parser->m_buffer = newBuf;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002100#endif /* not defined XML_CONTEXT_BYTES */
2101 }
Elliott Hughes72472942018-01-10 08:36:10 -08002102 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
2103 parser->m_positionPtr = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002104 }
Elliott Hughes72472942018-01-10 08:36:10 -08002105 return parser->m_bufferEnd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002106}
2107
2108enum XML_Status XMLCALL
2109XML_StopParser(XML_Parser parser, XML_Bool resumable)
2110{
Elliott Hughes72472942018-01-10 08:36:10 -08002111 if (parser == NULL)
2112 return XML_STATUS_ERROR;
2113 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002114 case XML_SUSPENDED:
2115 if (resumable) {
Elliott Hughes72472942018-01-10 08:36:10 -08002116 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002117 return XML_STATUS_ERROR;
2118 }
Elliott Hughes72472942018-01-10 08:36:10 -08002119 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002120 break;
2121 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08002122 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002123 return XML_STATUS_ERROR;
2124 default:
2125 if (resumable) {
2126#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08002127 if (parser->m_isParamEntity) {
2128 parser->m_errorCode = XML_ERROR_SUSPEND_PE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002129 return XML_STATUS_ERROR;
2130 }
2131#endif
Elliott Hughes72472942018-01-10 08:36:10 -08002132 parser->m_parsingStatus.parsing = XML_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002133 }
2134 else
Elliott Hughes72472942018-01-10 08:36:10 -08002135 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002136 }
2137 return XML_STATUS_OK;
2138}
2139
2140enum XML_Status XMLCALL
2141XML_ResumeParser(XML_Parser parser)
2142{
2143 enum XML_Status result = XML_STATUS_OK;
2144
Elliott Hughes72472942018-01-10 08:36:10 -08002145 if (parser == NULL)
2146 return XML_STATUS_ERROR;
2147 if (parser->m_parsingStatus.parsing != XML_SUSPENDED) {
2148 parser->m_errorCode = XML_ERROR_NOT_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002149 return XML_STATUS_ERROR;
2150 }
Elliott Hughes72472942018-01-10 08:36:10 -08002151 parser->m_parsingStatus.parsing = XML_PARSING;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002152
Elliott Hughes72472942018-01-10 08:36:10 -08002153 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 -08002154
Elliott Hughes72472942018-01-10 08:36:10 -08002155 if (parser->m_errorCode != XML_ERROR_NONE) {
2156 parser->m_eventEndPtr = parser->m_eventPtr;
2157 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002158 return XML_STATUS_ERROR;
2159 }
2160 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002161 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002162 case XML_SUSPENDED:
2163 result = XML_STATUS_SUSPENDED;
2164 break;
Elliott Hughes35e432d2012-09-09 14:23:38 -07002165 case XML_INITIALIZED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002166 case XML_PARSING:
Elliott Hughes72472942018-01-10 08:36:10 -08002167 if (parser->m_parsingStatus.finalBuffer) {
2168 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002169 return result;
2170 }
2171 default: ;
2172 }
2173 }
2174
Elliott Hughes72472942018-01-10 08:36:10 -08002175 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
2176 parser->m_positionPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002177 return result;
2178}
2179
2180void XMLCALL
2181XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
2182{
Elliott Hughes72472942018-01-10 08:36:10 -08002183 if (parser == NULL)
2184 return;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002185 assert(status != NULL);
2186 *status = parser->m_parsingStatus;
2187}
2188
2189enum XML_Error XMLCALL
2190XML_GetErrorCode(XML_Parser parser)
2191{
Elliott Hughes72472942018-01-10 08:36:10 -08002192 if (parser == NULL)
2193 return XML_ERROR_INVALID_ARGUMENT;
2194 return parser->m_errorCode;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002195}
2196
2197XML_Index XMLCALL
2198XML_GetCurrentByteIndex(XML_Parser parser)
2199{
Elliott Hughes72472942018-01-10 08:36:10 -08002200 if (parser == NULL)
2201 return -1;
2202 if (parser->m_eventPtr)
2203 return (XML_Index)(parser->m_parseEndByteIndex - (parser->m_parseEndPtr - parser->m_eventPtr));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002204 return -1;
2205}
2206
2207int XMLCALL
2208XML_GetCurrentByteCount(XML_Parser parser)
2209{
Elliott Hughes72472942018-01-10 08:36:10 -08002210 if (parser == NULL)
2211 return 0;
2212 if (parser->m_eventEndPtr && parser->m_eventPtr)
2213 return (int)(parser->m_eventEndPtr - parser->m_eventPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002214 return 0;
2215}
2216
2217const char * XMLCALL
2218XML_GetInputContext(XML_Parser parser, int *offset, int *size)
2219{
2220#ifdef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08002221 if (parser == NULL)
2222 return NULL;
2223 if (parser->m_eventPtr && parser->m_buffer) {
2224 if (offset != NULL)
2225 *offset = (int)(parser->m_eventPtr - parser->m_buffer);
2226 if (size != NULL)
2227 *size = (int)(parser->m_bufferEnd - parser->m_buffer);
2228 return parser->m_buffer;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002229 }
Elliott Hughes72472942018-01-10 08:36:10 -08002230#else
2231 (void)parser;
2232 (void)offset;
2233 (void)size;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002234#endif /* defined XML_CONTEXT_BYTES */
2235 return (char *) 0;
2236}
2237
2238XML_Size XMLCALL
2239XML_GetCurrentLineNumber(XML_Parser parser)
2240{
Elliott Hughes72472942018-01-10 08:36:10 -08002241 if (parser == NULL)
2242 return 0;
2243 if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2244 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_eventPtr, &parser->m_position);
2245 parser->m_positionPtr = parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002246 }
Elliott Hughes72472942018-01-10 08:36:10 -08002247 return parser->m_position.lineNumber + 1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002248}
2249
2250XML_Size XMLCALL
2251XML_GetCurrentColumnNumber(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.columnNumber;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002260}
2261
2262void XMLCALL
2263XML_FreeContentModel(XML_Parser parser, XML_Content *model)
2264{
Elliott Hughes72472942018-01-10 08:36:10 -08002265 if (parser != NULL)
2266 FREE(parser, model);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002267}
2268
2269void * XMLCALL
2270XML_MemMalloc(XML_Parser parser, size_t size)
2271{
Elliott Hughes72472942018-01-10 08:36:10 -08002272 if (parser == NULL)
2273 return NULL;
2274 return MALLOC(parser, size);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002275}
2276
2277void * XMLCALL
2278XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
2279{
Elliott Hughes72472942018-01-10 08:36:10 -08002280 if (parser == NULL)
2281 return NULL;
2282 return REALLOC(parser, ptr, size);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002283}
2284
2285void XMLCALL
2286XML_MemFree(XML_Parser parser, void *ptr)
2287{
Elliott Hughes72472942018-01-10 08:36:10 -08002288 if (parser != NULL)
2289 FREE(parser, ptr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002290}
2291
2292void XMLCALL
2293XML_DefaultCurrent(XML_Parser parser)
2294{
Elliott Hughes72472942018-01-10 08:36:10 -08002295 if (parser == NULL)
2296 return;
2297 if (parser->m_defaultHandler) {
2298 if (parser->m_openInternalEntities)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002299 reportDefault(parser,
Elliott Hughes72472942018-01-10 08:36:10 -08002300 parser->m_internalEncoding,
2301 parser->m_openInternalEntities->internalEventPtr,
2302 parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002303 else
Elliott Hughes72472942018-01-10 08:36:10 -08002304 reportDefault(parser, parser->m_encoding, parser->m_eventPtr, parser->m_eventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002305 }
2306}
2307
2308const XML_LChar * XMLCALL
2309XML_ErrorString(enum XML_Error code)
2310{
Elliott Hughes72472942018-01-10 08:36:10 -08002311 switch (code) {
2312 case XML_ERROR_NONE:
2313 return NULL;
2314 case XML_ERROR_NO_MEMORY:
2315 return XML_L("out of memory");
2316 case XML_ERROR_SYNTAX:
2317 return XML_L("syntax error");
2318 case XML_ERROR_NO_ELEMENTS:
2319 return XML_L("no element found");
2320 case XML_ERROR_INVALID_TOKEN:
2321 return XML_L("not well-formed (invalid token)");
2322 case XML_ERROR_UNCLOSED_TOKEN:
2323 return XML_L("unclosed token");
2324 case XML_ERROR_PARTIAL_CHAR:
2325 return XML_L("partial character");
2326 case XML_ERROR_TAG_MISMATCH:
2327 return XML_L("mismatched tag");
2328 case XML_ERROR_DUPLICATE_ATTRIBUTE:
2329 return XML_L("duplicate attribute");
2330 case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
2331 return XML_L("junk after document element");
2332 case XML_ERROR_PARAM_ENTITY_REF:
2333 return XML_L("illegal parameter entity reference");
2334 case XML_ERROR_UNDEFINED_ENTITY:
2335 return XML_L("undefined entity");
2336 case XML_ERROR_RECURSIVE_ENTITY_REF:
2337 return XML_L("recursive entity reference");
2338 case XML_ERROR_ASYNC_ENTITY:
2339 return XML_L("asynchronous entity");
2340 case XML_ERROR_BAD_CHAR_REF:
2341 return XML_L("reference to invalid character number");
2342 case XML_ERROR_BINARY_ENTITY_REF:
2343 return XML_L("reference to binary entity");
2344 case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
2345 return XML_L("reference to external entity in attribute");
2346 case XML_ERROR_MISPLACED_XML_PI:
2347 return XML_L("XML or text declaration not at start of entity");
2348 case XML_ERROR_UNKNOWN_ENCODING:
2349 return XML_L("unknown encoding");
2350 case XML_ERROR_INCORRECT_ENCODING:
2351 return XML_L("encoding specified in XML declaration is incorrect");
2352 case XML_ERROR_UNCLOSED_CDATA_SECTION:
2353 return XML_L("unclosed CDATA section");
2354 case XML_ERROR_EXTERNAL_ENTITY_HANDLING:
2355 return XML_L("error in processing external entity reference");
2356 case XML_ERROR_NOT_STANDALONE:
2357 return XML_L("document is not standalone");
2358 case XML_ERROR_UNEXPECTED_STATE:
2359 return XML_L("unexpected parser state - please send a bug report");
2360 case XML_ERROR_ENTITY_DECLARED_IN_PE:
2361 return XML_L("entity declared in parameter entity");
2362 case XML_ERROR_FEATURE_REQUIRES_XML_DTD:
2363 return XML_L("requested feature requires XML_DTD support in Expat");
2364 case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:
2365 return XML_L("cannot change setting once parsing has begun");
2366 /* Added in 1.95.7. */
2367 case XML_ERROR_UNBOUND_PREFIX:
2368 return XML_L("unbound prefix");
2369 /* Added in 1.95.8. */
2370 case XML_ERROR_UNDECLARING_PREFIX:
2371 return XML_L("must not undeclare prefix");
2372 case XML_ERROR_INCOMPLETE_PE:
2373 return XML_L("incomplete markup in parameter entity");
2374 case XML_ERROR_XML_DECL:
2375 return XML_L("XML declaration not well-formed");
2376 case XML_ERROR_TEXT_DECL:
2377 return XML_L("text declaration not well-formed");
2378 case XML_ERROR_PUBLICID:
2379 return XML_L("illegal character(s) in public id");
2380 case XML_ERROR_SUSPENDED:
2381 return XML_L("parser suspended");
2382 case XML_ERROR_NOT_SUSPENDED:
2383 return XML_L("parser not suspended");
2384 case XML_ERROR_ABORTED:
2385 return XML_L("parsing aborted");
2386 case XML_ERROR_FINISHED:
2387 return XML_L("parsing finished");
2388 case XML_ERROR_SUSPEND_PE:
2389 return XML_L("cannot suspend in external parameter entity");
2390 /* Added in 2.0.0. */
2391 case XML_ERROR_RESERVED_PREFIX_XML:
2392 return XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name");
2393 case XML_ERROR_RESERVED_PREFIX_XMLNS:
2394 return XML_L("reserved prefix (xmlns) must not be declared or undeclared");
2395 case XML_ERROR_RESERVED_NAMESPACE_URI:
2396 return XML_L("prefix must not be bound to one of the reserved namespace names");
2397 /* Added in 2.2.5. */
2398 case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
2399 return XML_L("invalid argument");
2400 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002401 return NULL;
2402}
2403
2404const XML_LChar * XMLCALL
2405XML_ExpatVersion(void) {
2406
2407 /* V1 is used to string-ize the version number. However, it would
2408 string-ize the actual version macro *names* unless we get them
2409 substituted before being passed to V1. CPP is defined to expand
2410 a macro, then rescan for more expansions. Thus, we use V2 to expand
2411 the version macros, then CPP will expand the resulting V1() macro
2412 with the correct numerals. */
2413 /* ### I'm assuming cpp is portable in this respect... */
2414
2415#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
2416#define V2(a,b,c) XML_L("expat_")V1(a,b,c)
2417
2418 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
2419
2420#undef V1
2421#undef V2
2422}
2423
2424XML_Expat_Version XMLCALL
2425XML_ExpatVersionInfo(void)
2426{
2427 XML_Expat_Version version;
2428
2429 version.major = XML_MAJOR_VERSION;
2430 version.minor = XML_MINOR_VERSION;
2431 version.micro = XML_MICRO_VERSION;
2432
2433 return version;
2434}
2435
2436const XML_Feature * XMLCALL
2437XML_GetFeatureList(void)
2438{
2439 static const XML_Feature features[] = {
2440 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2441 sizeof(XML_Char)},
2442 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2443 sizeof(XML_LChar)},
2444#ifdef XML_UNICODE
2445 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2446#endif
2447#ifdef XML_UNICODE_WCHAR_T
2448 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2449#endif
2450#ifdef XML_DTD
2451 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2452#endif
2453#ifdef XML_CONTEXT_BYTES
2454 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2455 XML_CONTEXT_BYTES},
2456#endif
2457#ifdef XML_MIN_SIZE
2458 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2459#endif
2460#ifdef XML_NS
2461 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2462#endif
Elliott Hughesd07d5a72009-09-25 16:04:37 -07002463#ifdef XML_LARGE_SIZE
2464 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
Elliott Hughes35e432d2012-09-09 14:23:38 -07002465#endif
2466#ifdef XML_ATTR_INFO
2467 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2468#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002469 {XML_FEATURE_END, NULL, 0}
2470 };
2471
2472 return features;
2473}
2474
2475/* Initially tag->rawName always points into the parse buffer;
2476 for those TAG instances opened while the current parse buffer was
2477 processed, and not yet closed, we need to store tag->rawName in a more
2478 permanent location, since the parse buffer is about to be discarded.
2479*/
2480static XML_Bool
2481storeRawNames(XML_Parser parser)
2482{
Elliott Hughes72472942018-01-10 08:36:10 -08002483 TAG *tag = parser->m_tagStack;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002484 while (tag) {
2485 int bufSize;
2486 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2487 char *rawNameBuf = tag->buf + nameLen;
Elliott Hughes72472942018-01-10 08:36:10 -08002488 /* Stop if already stored. Since m_tagStack is a stack, we can stop
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002489 at the first entry that has already been copied; everything
2490 below it in the stack is already been accounted for in a
2491 previous call to this function.
2492 */
2493 if (tag->rawName == rawNameBuf)
2494 break;
2495 /* For re-use purposes we need to ensure that the
2496 size of tag->buf is a multiple of sizeof(XML_Char).
2497 */
2498 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2499 if (bufSize > tag->bufEnd - tag->buf) {
Elliott Hughes72472942018-01-10 08:36:10 -08002500 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002501 if (temp == NULL)
2502 return XML_FALSE;
2503 /* if tag->name.str points to tag->buf (only when namespace
2504 processing is off) then we have to update it
2505 */
2506 if (tag->name.str == (XML_Char *)tag->buf)
2507 tag->name.str = (XML_Char *)temp;
2508 /* if tag->name.localPart is set (when namespace processing is on)
2509 then update it as well, since it will always point into tag->buf
2510 */
2511 if (tag->name.localPart)
2512 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2513 (XML_Char *)tag->buf);
2514 tag->buf = temp;
2515 tag->bufEnd = temp + bufSize;
2516 rawNameBuf = temp + nameLen;
2517 }
2518 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2519 tag->rawName = rawNameBuf;
2520 tag = tag->parent;
2521 }
2522 return XML_TRUE;
2523}
2524
2525static enum XML_Error PTRCALL
2526contentProcessor(XML_Parser parser,
2527 const char *start,
2528 const char *end,
2529 const char **endPtr)
2530{
Elliott Hughes72472942018-01-10 08:36:10 -08002531 enum XML_Error result = doContent(parser, 0, parser->m_encoding, start, end,
2532 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002533 if (result == XML_ERROR_NONE) {
2534 if (!storeRawNames(parser))
2535 return XML_ERROR_NO_MEMORY;
2536 }
2537 return result;
2538}
2539
2540static enum XML_Error PTRCALL
2541externalEntityInitProcessor(XML_Parser parser,
2542 const char *start,
2543 const char *end,
2544 const char **endPtr)
2545{
2546 enum XML_Error result = initializeEncoding(parser);
2547 if (result != XML_ERROR_NONE)
2548 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002549 parser->m_processor = externalEntityInitProcessor2;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002550 return externalEntityInitProcessor2(parser, start, end, endPtr);
2551}
2552
2553static enum XML_Error PTRCALL
2554externalEntityInitProcessor2(XML_Parser parser,
2555 const char *start,
2556 const char *end,
2557 const char **endPtr)
2558{
2559 const char *next = start; /* XmlContentTok doesn't always set the last arg */
Elliott Hughes72472942018-01-10 08:36:10 -08002560 int tok = XmlContentTok(parser->m_encoding, start, end, &next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002561 switch (tok) {
2562 case XML_TOK_BOM:
2563 /* If we are at the end of the buffer, this would cause the next stage,
2564 i.e. externalEntityInitProcessor3, to pass control directly to
2565 doContent (by detecting XML_TOK_NONE) without processing any xml text
2566 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2567 */
Elliott Hughes72472942018-01-10 08:36:10 -08002568 if (next == end && !parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002569 *endPtr = next;
2570 return XML_ERROR_NONE;
2571 }
2572 start = next;
2573 break;
2574 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08002575 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002576 *endPtr = start;
2577 return XML_ERROR_NONE;
2578 }
Elliott Hughes72472942018-01-10 08:36:10 -08002579 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002580 return XML_ERROR_UNCLOSED_TOKEN;
2581 case XML_TOK_PARTIAL_CHAR:
Elliott Hughes72472942018-01-10 08:36:10 -08002582 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002583 *endPtr = start;
2584 return XML_ERROR_NONE;
2585 }
Elliott Hughes72472942018-01-10 08:36:10 -08002586 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002587 return XML_ERROR_PARTIAL_CHAR;
2588 }
Elliott Hughes72472942018-01-10 08:36:10 -08002589 parser->m_processor = externalEntityInitProcessor3;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002590 return externalEntityInitProcessor3(parser, start, end, endPtr);
2591}
2592
2593static enum XML_Error PTRCALL
2594externalEntityInitProcessor3(XML_Parser parser,
2595 const char *start,
2596 const char *end,
2597 const char **endPtr)
2598{
2599 int tok;
2600 const char *next = start; /* XmlContentTok doesn't always set the last arg */
Elliott Hughes72472942018-01-10 08:36:10 -08002601 parser->m_eventPtr = start;
2602 tok = XmlContentTok(parser->m_encoding, start, end, &next);
2603 parser->m_eventEndPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002604
2605 switch (tok) {
2606 case XML_TOK_XML_DECL:
2607 {
2608 enum XML_Error result;
2609 result = processXmlDecl(parser, 1, start, next);
2610 if (result != XML_ERROR_NONE)
2611 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002612 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07002613 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002614 *endPtr = next;
2615 return XML_ERROR_NONE;
2616 case XML_FINISHED:
2617 return XML_ERROR_ABORTED;
2618 default:
2619 start = next;
2620 }
2621 }
2622 break;
2623 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08002624 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002625 *endPtr = start;
2626 return XML_ERROR_NONE;
2627 }
2628 return XML_ERROR_UNCLOSED_TOKEN;
2629 case XML_TOK_PARTIAL_CHAR:
Elliott Hughes72472942018-01-10 08:36:10 -08002630 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002631 *endPtr = start;
2632 return XML_ERROR_NONE;
2633 }
2634 return XML_ERROR_PARTIAL_CHAR;
2635 }
Elliott Hughes72472942018-01-10 08:36:10 -08002636 parser->m_processor = externalEntityContentProcessor;
2637 parser->m_tagLevel = 1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002638 return externalEntityContentProcessor(parser, start, end, endPtr);
2639}
2640
2641static enum XML_Error PTRCALL
2642externalEntityContentProcessor(XML_Parser parser,
2643 const char *start,
2644 const char *end,
2645 const char **endPtr)
2646{
Elliott Hughes72472942018-01-10 08:36:10 -08002647 enum XML_Error result = doContent(parser, 1, parser->m_encoding, start, end,
2648 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002649 if (result == XML_ERROR_NONE) {
2650 if (!storeRawNames(parser))
2651 return XML_ERROR_NO_MEMORY;
2652 }
2653 return result;
2654}
2655
2656static enum XML_Error
2657doContent(XML_Parser parser,
2658 int startTagLevel,
2659 const ENCODING *enc,
2660 const char *s,
2661 const char *end,
2662 const char **nextPtr,
2663 XML_Bool haveMore)
2664{
2665 /* save one level of indirection */
Elliott Hughes72472942018-01-10 08:36:10 -08002666 DTD * const dtd = parser->m_dtd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002667
2668 const char **eventPP;
2669 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08002670 if (enc == parser->m_encoding) {
2671 eventPP = &parser->m_eventPtr;
2672 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002673 }
2674 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002675 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
2676 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002677 }
2678 *eventPP = s;
2679
2680 for (;;) {
2681 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2682 int tok = XmlContentTok(enc, s, end, &next);
2683 *eventEndPP = next;
2684 switch (tok) {
2685 case XML_TOK_TRAILING_CR:
2686 if (haveMore) {
2687 *nextPtr = s;
2688 return XML_ERROR_NONE;
2689 }
2690 *eventEndPP = end;
Elliott Hughes72472942018-01-10 08:36:10 -08002691 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002692 XML_Char c = 0xA;
Elliott Hughes72472942018-01-10 08:36:10 -08002693 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002694 }
Elliott Hughes72472942018-01-10 08:36:10 -08002695 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002696 reportDefault(parser, enc, s, end);
Elliott Hughes35e432d2012-09-09 14:23:38 -07002697 /* We are at the end of the final buffer, should we check for
2698 XML_SUSPENDED, XML_FINISHED?
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002699 */
2700 if (startTagLevel == 0)
2701 return XML_ERROR_NO_ELEMENTS;
Elliott Hughes72472942018-01-10 08:36:10 -08002702 if (parser->m_tagLevel != startTagLevel)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002703 return XML_ERROR_ASYNC_ENTITY;
2704 *nextPtr = end;
2705 return XML_ERROR_NONE;
2706 case XML_TOK_NONE:
2707 if (haveMore) {
2708 *nextPtr = s;
2709 return XML_ERROR_NONE;
2710 }
2711 if (startTagLevel > 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002712 if (parser->m_tagLevel != startTagLevel)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002713 return XML_ERROR_ASYNC_ENTITY;
2714 *nextPtr = s;
2715 return XML_ERROR_NONE;
2716 }
2717 return XML_ERROR_NO_ELEMENTS;
2718 case XML_TOK_INVALID:
2719 *eventPP = next;
2720 return XML_ERROR_INVALID_TOKEN;
2721 case XML_TOK_PARTIAL:
2722 if (haveMore) {
2723 *nextPtr = s;
2724 return XML_ERROR_NONE;
2725 }
2726 return XML_ERROR_UNCLOSED_TOKEN;
2727 case XML_TOK_PARTIAL_CHAR:
2728 if (haveMore) {
2729 *nextPtr = s;
2730 return XML_ERROR_NONE;
2731 }
2732 return XML_ERROR_PARTIAL_CHAR;
2733 case XML_TOK_ENTITY_REF:
2734 {
2735 const XML_Char *name;
2736 ENTITY *entity;
2737 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2738 s + enc->minBytesPerChar,
2739 next - enc->minBytesPerChar);
2740 if (ch) {
Elliott Hughes72472942018-01-10 08:36:10 -08002741 if (parser->m_characterDataHandler)
2742 parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
2743 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002744 reportDefault(parser, enc, s, next);
2745 break;
2746 }
2747 name = poolStoreString(&dtd->pool, enc,
2748 s + enc->minBytesPerChar,
2749 next - enc->minBytesPerChar);
2750 if (!name)
2751 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07002752 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002753 poolDiscard(&dtd->pool);
2754 /* First, determine if a check for an existing declaration is needed;
2755 if yes, check that the entity exists, and that it is internal,
2756 otherwise call the skipped entity or default handler.
2757 */
2758 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2759 if (!entity)
2760 return XML_ERROR_UNDEFINED_ENTITY;
2761 else if (!entity->is_internal)
2762 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2763 }
2764 else if (!entity) {
Elliott Hughes72472942018-01-10 08:36:10 -08002765 if (parser->m_skippedEntityHandler)
2766 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
2767 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002768 reportDefault(parser, enc, s, next);
2769 break;
2770 }
2771 if (entity->open)
2772 return XML_ERROR_RECURSIVE_ENTITY_REF;
2773 if (entity->notation)
2774 return XML_ERROR_BINARY_ENTITY_REF;
2775 if (entity->textPtr) {
2776 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08002777 if (!parser->m_defaultExpandInternalEntities) {
2778 if (parser->m_skippedEntityHandler)
2779 parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name, 0);
2780 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002781 reportDefault(parser, enc, s, next);
2782 break;
2783 }
2784 result = processInternalEntity(parser, entity, XML_FALSE);
2785 if (result != XML_ERROR_NONE)
2786 return result;
2787 }
Elliott Hughes72472942018-01-10 08:36:10 -08002788 else if (parser->m_externalEntityRefHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002789 const XML_Char *context;
2790 entity->open = XML_TRUE;
2791 context = getContext(parser);
2792 entity->open = XML_FALSE;
2793 if (!context)
2794 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08002795 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002796 context,
2797 entity->base,
2798 entity->systemId,
2799 entity->publicId))
2800 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
Elliott Hughes72472942018-01-10 08:36:10 -08002801 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002802 }
Elliott Hughes72472942018-01-10 08:36:10 -08002803 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002804 reportDefault(parser, enc, s, next);
2805 break;
2806 }
2807 case XML_TOK_START_TAG_NO_ATTS:
2808 /* fall through */
2809 case XML_TOK_START_TAG_WITH_ATTS:
2810 {
2811 TAG *tag;
2812 enum XML_Error result;
2813 XML_Char *toPtr;
Elliott Hughes72472942018-01-10 08:36:10 -08002814 if (parser->m_freeTagList) {
2815 tag = parser->m_freeTagList;
2816 parser->m_freeTagList = parser->m_freeTagList->parent;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002817 }
2818 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002819 tag = (TAG *)MALLOC(parser, sizeof(TAG));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002820 if (!tag)
2821 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08002822 tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002823 if (!tag->buf) {
Elliott Hughes72472942018-01-10 08:36:10 -08002824 FREE(parser, tag);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002825 return XML_ERROR_NO_MEMORY;
2826 }
2827 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2828 }
2829 tag->bindings = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08002830 tag->parent = parser->m_tagStack;
2831 parser->m_tagStack = tag;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002832 tag->name.localPart = NULL;
2833 tag->name.prefix = NULL;
2834 tag->rawName = s + enc->minBytesPerChar;
2835 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
Elliott Hughes72472942018-01-10 08:36:10 -08002836 ++parser->m_tagLevel;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002837 {
2838 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2839 const char *fromPtr = tag->rawName;
2840 toPtr = (XML_Char *)tag->buf;
2841 for (;;) {
2842 int bufSize;
2843 int convLen;
Paul Duffin4bf8f122016-05-13 12:35:25 +01002844 const enum XML_Convert_Result convert_res = XmlConvert(enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002845 &fromPtr, rawNameEnd,
2846 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2847 convLen = (int)(toPtr - (XML_Char *)tag->buf);
Elliott Hughes72472942018-01-10 08:36:10 -08002848 if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002849 tag->name.strLen = convLen;
2850 break;
2851 }
2852 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2853 {
Elliott Hughes72472942018-01-10 08:36:10 -08002854 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002855 if (temp == NULL)
2856 return XML_ERROR_NO_MEMORY;
2857 tag->buf = temp;
2858 tag->bufEnd = temp + bufSize;
2859 toPtr = (XML_Char *)temp + convLen;
2860 }
2861 }
2862 }
2863 tag->name.str = (XML_Char *)tag->buf;
2864 *toPtr = XML_T('\0');
2865 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2866 if (result)
2867 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002868 if (parser->m_startElementHandler)
2869 parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
2870 (const XML_Char **)parser->m_atts);
2871 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002872 reportDefault(parser, enc, s, next);
Elliott Hughes72472942018-01-10 08:36:10 -08002873 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002874 break;
2875 }
2876 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2877 /* fall through */
2878 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2879 {
2880 const char *rawName = s + enc->minBytesPerChar;
2881 enum XML_Error result;
2882 BINDING *bindings = NULL;
2883 XML_Bool noElmHandlers = XML_TRUE;
2884 TAG_NAME name;
Elliott Hughes72472942018-01-10 08:36:10 -08002885 name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002886 rawName + XmlNameLength(enc, rawName));
2887 if (!name.str)
2888 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08002889 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002890 result = storeAtts(parser, enc, s, &name, &bindings);
Elliott Hughes72472942018-01-10 08:36:10 -08002891 if (result != XML_ERROR_NONE) {
2892 freeBindings(parser, bindings);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002893 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002894 }
2895 poolFinish(&parser->m_tempPool);
2896 if (parser->m_startElementHandler) {
2897 parser->m_startElementHandler(parser->m_handlerArg, name.str, (const XML_Char **)parser->m_atts);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002898 noElmHandlers = XML_FALSE;
2899 }
Elliott Hughes72472942018-01-10 08:36:10 -08002900 if (parser->m_endElementHandler) {
2901 if (parser->m_startElementHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002902 *eventPP = *eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08002903 parser->m_endElementHandler(parser->m_handlerArg, name.str);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002904 noElmHandlers = XML_FALSE;
2905 }
Elliott Hughes72472942018-01-10 08:36:10 -08002906 if (noElmHandlers && parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002907 reportDefault(parser, enc, s, next);
Elliott Hughes72472942018-01-10 08:36:10 -08002908 poolClear(&parser->m_tempPool);
2909 freeBindings(parser, bindings);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002910 }
Elliott Hughes72472942018-01-10 08:36:10 -08002911 if ((parser->m_tagLevel == 0) &&
2912 !((parser->m_parsingStatus.parsing == XML_FINISHED) || (parser->m_parsingStatus.parsing == XML_SUSPENDED))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002913 return epilogProcessor(parser, next, end, nextPtr);
Elliott Hughes72472942018-01-10 08:36:10 -08002914 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002915 break;
2916 case XML_TOK_END_TAG:
Elliott Hughes72472942018-01-10 08:36:10 -08002917 if (parser->m_tagLevel == startTagLevel)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002918 return XML_ERROR_ASYNC_ENTITY;
2919 else {
2920 int len;
2921 const char *rawName;
Elliott Hughes72472942018-01-10 08:36:10 -08002922 TAG *tag = parser->m_tagStack;
2923 parser->m_tagStack = tag->parent;
2924 tag->parent = parser->m_freeTagList;
2925 parser->m_freeTagList = tag;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002926 rawName = s + enc->minBytesPerChar*2;
2927 len = XmlNameLength(enc, rawName);
2928 if (len != tag->rawNameLength
2929 || memcmp(tag->rawName, rawName, len) != 0) {
2930 *eventPP = rawName;
2931 return XML_ERROR_TAG_MISMATCH;
2932 }
Elliott Hughes72472942018-01-10 08:36:10 -08002933 --parser->m_tagLevel;
2934 if (parser->m_endElementHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002935 const XML_Char *localPart;
2936 const XML_Char *prefix;
2937 XML_Char *uri;
2938 localPart = tag->name.localPart;
Elliott Hughes72472942018-01-10 08:36:10 -08002939 if (parser->m_ns && localPart) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002940 /* localPart and prefix may have been overwritten in
2941 tag->name.str, since this points to the binding->uri
2942 buffer which gets re-used; so we have to add them again
2943 */
2944 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2945 /* don't need to check for space - already done in storeAtts() */
2946 while (*localPart) *uri++ = *localPart++;
2947 prefix = (XML_Char *)tag->name.prefix;
Elliott Hughes72472942018-01-10 08:36:10 -08002948 if (parser->m_ns_triplets && prefix) {
2949 *uri++ = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002950 while (*prefix) *uri++ = *prefix++;
2951 }
2952 *uri = XML_T('\0');
2953 }
Elliott Hughes72472942018-01-10 08:36:10 -08002954 parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002955 }
Elliott Hughes72472942018-01-10 08:36:10 -08002956 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002957 reportDefault(parser, enc, s, next);
2958 while (tag->bindings) {
2959 BINDING *b = tag->bindings;
Elliott Hughes72472942018-01-10 08:36:10 -08002960 if (parser->m_endNamespaceDeclHandler)
2961 parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002962 tag->bindings = tag->bindings->nextTagBinding;
Elliott Hughes72472942018-01-10 08:36:10 -08002963 b->nextTagBinding = parser->m_freeBindingList;
2964 parser->m_freeBindingList = b;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002965 b->prefix->binding = b->prevPrefixBinding;
2966 }
Elliott Hughes72472942018-01-10 08:36:10 -08002967 if (parser->m_tagLevel == 0)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002968 return epilogProcessor(parser, next, end, nextPtr);
2969 }
2970 break;
2971 case XML_TOK_CHAR_REF:
2972 {
2973 int n = XmlCharRefNumber(enc, s);
2974 if (n < 0)
2975 return XML_ERROR_BAD_CHAR_REF;
Elliott Hughes72472942018-01-10 08:36:10 -08002976 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002977 XML_Char buf[XML_ENCODE_MAX];
Elliott Hughes72472942018-01-10 08:36:10 -08002978 parser->m_characterDataHandler(parser->m_handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002979 }
Elliott Hughes72472942018-01-10 08:36:10 -08002980 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002981 reportDefault(parser, enc, s, next);
2982 }
2983 break;
2984 case XML_TOK_XML_DECL:
2985 return XML_ERROR_MISPLACED_XML_PI;
2986 case XML_TOK_DATA_NEWLINE:
Elliott Hughes72472942018-01-10 08:36:10 -08002987 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002988 XML_Char c = 0xA;
Elliott Hughes72472942018-01-10 08:36:10 -08002989 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002990 }
Elliott Hughes72472942018-01-10 08:36:10 -08002991 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002992 reportDefault(parser, enc, s, next);
2993 break;
2994 case XML_TOK_CDATA_SECT_OPEN:
2995 {
2996 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08002997 if (parser->m_startCdataSectionHandler)
2998 parser->m_startCdataSectionHandler(parser->m_handlerArg);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002999#if 0
3000 /* Suppose you doing a transformation on a document that involves
3001 changing only the character data. You set up a defaultHandler
3002 and a characterDataHandler. The defaultHandler simply copies
3003 characters through. The characterDataHandler does the
3004 transformation and writes the characters out escaping them as
3005 necessary. This case will fail to work if we leave out the
3006 following two lines (because & and < inside CDATA sections will
3007 be incorrectly escaped).
3008
3009 However, now we have a start/endCdataSectionHandler, so it seems
3010 easier to let the user deal with this.
3011 */
Elliott Hughes72472942018-01-10 08:36:10 -08003012 else if (parser->m_characterDataHandler)
3013 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003014#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003015 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003016 reportDefault(parser, enc, s, next);
3017 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
3018 if (result != XML_ERROR_NONE)
3019 return result;
3020 else if (!next) {
Elliott Hughes72472942018-01-10 08:36:10 -08003021 parser->m_processor = cdataSectionProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003022 return result;
3023 }
3024 }
3025 break;
3026 case XML_TOK_TRAILING_RSQB:
3027 if (haveMore) {
3028 *nextPtr = s;
3029 return XML_ERROR_NONE;
3030 }
Elliott Hughes72472942018-01-10 08:36:10 -08003031 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003032 if (MUST_CONVERT(enc, s)) {
Elliott Hughes72472942018-01-10 08:36:10 -08003033 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3034 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3035 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3036 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003037 }
3038 else
Elliott Hughes72472942018-01-10 08:36:10 -08003039 parser->m_characterDataHandler(parser->m_handlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003040 (XML_Char *)s,
3041 (int)((XML_Char *)end - (XML_Char *)s));
3042 }
Elliott Hughes72472942018-01-10 08:36:10 -08003043 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003044 reportDefault(parser, enc, s, end);
Elliott Hughes35e432d2012-09-09 14:23:38 -07003045 /* We are at the end of the final buffer, should we check for
3046 XML_SUSPENDED, XML_FINISHED?
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003047 */
3048 if (startTagLevel == 0) {
3049 *eventPP = end;
3050 return XML_ERROR_NO_ELEMENTS;
3051 }
Elliott Hughes72472942018-01-10 08:36:10 -08003052 if (parser->m_tagLevel != startTagLevel) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003053 *eventPP = end;
3054 return XML_ERROR_ASYNC_ENTITY;
3055 }
3056 *nextPtr = end;
3057 return XML_ERROR_NONE;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003058 case XML_TOK_DATA_CHARS:
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003059 {
Elliott Hughes72472942018-01-10 08:36:10 -08003060 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003061 if (charDataHandler) {
3062 if (MUST_CONVERT(enc, s)) {
3063 for (;;) {
Elliott Hughes72472942018-01-10 08:36:10 -08003064 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3065 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003066 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08003067 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3068 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
Paul Duffin4bf8f122016-05-13 12:35:25 +01003069 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003070 break;
3071 *eventPP = s;
3072 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003073 }
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003074 else
Elliott Hughes72472942018-01-10 08:36:10 -08003075 charDataHandler(parser->m_handlerArg,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003076 (XML_Char *)s,
3077 (int)((XML_Char *)next - (XML_Char *)s));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003078 }
Elliott Hughes72472942018-01-10 08:36:10 -08003079 else if (parser->m_defaultHandler)
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003080 reportDefault(parser, enc, s, next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003081 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003082 break;
3083 case XML_TOK_PI:
3084 if (!reportProcessingInstruction(parser, enc, s, next))
3085 return XML_ERROR_NO_MEMORY;
3086 break;
3087 case XML_TOK_COMMENT:
3088 if (!reportComment(parser, enc, s, next))
3089 return XML_ERROR_NO_MEMORY;
3090 break;
3091 default:
Elliott Hughes72472942018-01-10 08:36:10 -08003092 /* All of the tokens produced by XmlContentTok() have their own
3093 * explicit cases, so this default is not strictly necessary.
3094 * However it is a useful safety net, so we retain the code and
3095 * simply exclude it from the coverage tests.
3096 *
3097 * LCOV_EXCL_START
3098 */
3099 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003100 reportDefault(parser, enc, s, next);
3101 break;
Elliott Hughes72472942018-01-10 08:36:10 -08003102 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003103 }
3104 *eventPP = s = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003105 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07003106 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003107 *nextPtr = next;
3108 return XML_ERROR_NONE;
3109 case XML_FINISHED:
3110 return XML_ERROR_ABORTED;
3111 default: ;
3112 }
3113 }
3114 /* not reached */
3115}
3116
Elliott Hughes72472942018-01-10 08:36:10 -08003117/* This function does not call free() on the allocated memory, merely
3118 * moving it to the parser's m_freeBindingList where it can be freed or
3119 * reused as appropriate.
3120 */
3121static void
3122freeBindings(XML_Parser parser, BINDING *bindings)
3123{
3124 while (bindings) {
3125 BINDING *b = bindings;
3126
3127 /* m_startNamespaceDeclHandler will have been called for this
3128 * binding in addBindings(), so call the end handler now.
3129 */
3130 if (parser->m_endNamespaceDeclHandler)
3131 parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
3132
3133 bindings = bindings->nextTagBinding;
3134 b->nextTagBinding = parser->m_freeBindingList;
3135 parser->m_freeBindingList = b;
3136 b->prefix->binding = b->prevPrefixBinding;
3137 }
3138}
3139
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003140/* Precondition: all arguments must be non-NULL;
3141 Purpose:
3142 - normalize attributes
3143 - check attributes for well-formedness
3144 - generate namespace aware attribute names (URI, prefix)
3145 - build list of attributes for startElementHandler
3146 - default attributes
3147 - process namespace declarations (check and report them)
3148 - generate namespace aware element name (URI, prefix)
3149*/
3150static enum XML_Error
3151storeAtts(XML_Parser parser, const ENCODING *enc,
3152 const char *attStr, TAG_NAME *tagNamePtr,
3153 BINDING **bindingsPtr)
3154{
Elliott Hughes72472942018-01-10 08:36:10 -08003155 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003156 ELEMENT_TYPE *elementType;
3157 int nDefaultAtts;
3158 const XML_Char **appAtts; /* the attribute list for the application */
3159 int attIndex = 0;
3160 int prefixLen;
3161 int i;
3162 int n;
3163 XML_Char *uri;
3164 int nPrefixes = 0;
3165 BINDING *binding;
3166 const XML_Char *localPart;
3167
3168 /* lookup the element type name */
Elliott Hughes35e432d2012-09-09 14:23:38 -07003169 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003170 if (!elementType) {
3171 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
3172 if (!name)
3173 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003174 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003175 sizeof(ELEMENT_TYPE));
3176 if (!elementType)
3177 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003178 if (parser->m_ns && !setElementTypePrefix(parser, elementType))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003179 return XML_ERROR_NO_MEMORY;
3180 }
3181 nDefaultAtts = elementType->nDefaultAtts;
3182
3183 /* get the attributes from the tokenizer */
Elliott Hughes72472942018-01-10 08:36:10 -08003184 n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
3185 if (n + nDefaultAtts > parser->m_attsSize) {
3186 int oldAttsSize = parser->m_attsSize;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003187 ATTRIBUTE *temp;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003188#ifdef XML_ATTR_INFO
3189 XML_AttrInfo *temp2;
3190#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003191 parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
3192 temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, parser->m_attsSize * sizeof(ATTRIBUTE));
3193 if (temp == NULL) {
3194 parser->m_attsSize = oldAttsSize;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003195 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003196 }
3197 parser->m_atts = temp;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003198#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08003199 temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, parser->m_attsSize * sizeof(XML_AttrInfo));
3200 if (temp2 == NULL) {
3201 parser->m_attsSize = oldAttsSize;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003202 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003203 }
3204 parser->m_attInfo = temp2;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003205#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003206 if (n > oldAttsSize)
Elliott Hughes72472942018-01-10 08:36:10 -08003207 XmlGetAttributes(enc, attStr, n, parser->m_atts);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003208 }
3209
Elliott Hughes72472942018-01-10 08:36:10 -08003210 appAtts = (const XML_Char **)parser->m_atts;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003211 for (i = 0; i < n; i++) {
Elliott Hughes72472942018-01-10 08:36:10 -08003212 ATTRIBUTE *currAtt = &parser->m_atts[i];
Elliott Hughes35e432d2012-09-09 14:23:38 -07003213#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08003214 XML_AttrInfo *currAttInfo = &parser->m_attInfo[i];
Elliott Hughes35e432d2012-09-09 14:23:38 -07003215#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003216 /* add the name and value to the attribute list */
Elliott Hughes35e432d2012-09-09 14:23:38 -07003217 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
3218 currAtt->name
3219 + XmlNameLength(enc, currAtt->name));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003220 if (!attId)
3221 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003222#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08003223 currAttInfo->nameStart = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name);
Elliott Hughes35e432d2012-09-09 14:23:38 -07003224 currAttInfo->nameEnd = currAttInfo->nameStart +
3225 XmlNameLength(enc, currAtt->name);
Elliott Hughes72472942018-01-10 08:36:10 -08003226 currAttInfo->valueStart = parser->m_parseEndByteIndex -
3227 (parser->m_parseEndPtr - currAtt->valuePtr);
3228 currAttInfo->valueEnd = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->valueEnd);
Elliott Hughes35e432d2012-09-09 14:23:38 -07003229#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003230 /* Detect duplicate attributes by their QNames. This does not work when
3231 namespace processing is turned on and different prefixes for the same
3232 namespace are used. For this case we have a check further down.
3233 */
3234 if ((attId->name)[-1]) {
Elliott Hughes72472942018-01-10 08:36:10 -08003235 if (enc == parser->m_encoding)
3236 parser->m_eventPtr = parser->m_atts[i].name;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003237 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3238 }
3239 (attId->name)[-1] = 1;
3240 appAtts[attIndex++] = attId->name;
Elliott Hughes72472942018-01-10 08:36:10 -08003241 if (!parser->m_atts[i].normalized) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003242 enum XML_Error result;
3243 XML_Bool isCdata = XML_TRUE;
3244
3245 /* figure out whether declared as other than CDATA */
3246 if (attId->maybeTokenized) {
3247 int j;
3248 for (j = 0; j < nDefaultAtts; j++) {
3249 if (attId == elementType->defaultAtts[j].id) {
3250 isCdata = elementType->defaultAtts[j].isCdata;
3251 break;
3252 }
3253 }
3254 }
3255
3256 /* normalize the attribute value */
3257 result = storeAttributeValue(parser, enc, isCdata,
Elliott Hughes72472942018-01-10 08:36:10 -08003258 parser->m_atts[i].valuePtr, parser->m_atts[i].valueEnd,
3259 &parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003260 if (result)
3261 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08003262 appAtts[attIndex] = poolStart(&parser->m_tempPool);
3263 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003264 }
3265 else {
3266 /* the value did not need normalizing */
Elliott Hughes72472942018-01-10 08:36:10 -08003267 appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc, parser->m_atts[i].valuePtr,
3268 parser->m_atts[i].valueEnd);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003269 if (appAtts[attIndex] == 0)
3270 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003271 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003272 }
3273 /* handle prefixed attribute names */
3274 if (attId->prefix) {
3275 if (attId->xmlns) {
3276 /* deal with namespace declarations here */
3277 enum XML_Error result = addBinding(parser, attId->prefix, attId,
3278 appAtts[attIndex], bindingsPtr);
3279 if (result)
3280 return result;
3281 --attIndex;
3282 }
3283 else {
3284 /* deal with other prefixed names later */
3285 attIndex++;
3286 nPrefixes++;
3287 (attId->name)[-1] = 2;
3288 }
3289 }
3290 else
3291 attIndex++;
3292 }
3293
3294 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
Elliott Hughes72472942018-01-10 08:36:10 -08003295 parser->m_nSpecifiedAtts = attIndex;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003296 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
3297 for (i = 0; i < attIndex; i += 2)
3298 if (appAtts[i] == elementType->idAtt->name) {
Elliott Hughes72472942018-01-10 08:36:10 -08003299 parser->m_idAttIndex = i;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003300 break;
3301 }
3302 }
3303 else
Elliott Hughes72472942018-01-10 08:36:10 -08003304 parser->m_idAttIndex = -1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003305
3306 /* do attribute defaulting */
3307 for (i = 0; i < nDefaultAtts; i++) {
3308 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
3309 if (!(da->id->name)[-1] && da->value) {
3310 if (da->id->prefix) {
3311 if (da->id->xmlns) {
3312 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
3313 da->value, bindingsPtr);
3314 if (result)
3315 return result;
3316 }
3317 else {
3318 (da->id->name)[-1] = 2;
3319 nPrefixes++;
3320 appAtts[attIndex++] = da->id->name;
3321 appAtts[attIndex++] = da->value;
3322 }
3323 }
3324 else {
3325 (da->id->name)[-1] = 1;
3326 appAtts[attIndex++] = da->id->name;
3327 appAtts[attIndex++] = da->value;
3328 }
3329 }
3330 }
3331 appAtts[attIndex] = 0;
3332
3333 /* expand prefixed attribute names, check for duplicates,
3334 and clear flags that say whether attributes were specified */
3335 i = 0;
3336 if (nPrefixes) {
3337 int j; /* hash table index */
Elliott Hughes72472942018-01-10 08:36:10 -08003338 unsigned long version = parser->m_nsAttsVersion;
3339 int nsAttsSize = (int)1 << parser->m_nsAttsPower;
3340 unsigned char oldNsAttsPower = parser->m_nsAttsPower;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003341 /* size of hash table must be at least 2 * (# of prefixed attributes) */
Elliott Hughes72472942018-01-10 08:36:10 -08003342 if ((nPrefixes << 1) >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003343 NS_ATT *temp;
3344 /* hash table size must also be a power of 2 and >= 8 */
Elliott Hughes72472942018-01-10 08:36:10 -08003345 while (nPrefixes >> parser->m_nsAttsPower++);
3346 if (parser->m_nsAttsPower < 3)
3347 parser->m_nsAttsPower = 3;
3348 nsAttsSize = (int)1 << parser->m_nsAttsPower;
3349 temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, nsAttsSize * sizeof(NS_ATT));
3350 if (!temp) {
3351 /* Restore actual size of memory in m_nsAtts */
3352 parser->m_nsAttsPower = oldNsAttsPower;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003353 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003354 }
3355 parser->m_nsAtts = temp;
3356 version = 0; /* force re-initialization of m_nsAtts hash table */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003357 }
Elliott Hughes72472942018-01-10 08:36:10 -08003358 /* using a version flag saves us from initializing m_nsAtts every time */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003359 if (!version) { /* initialize version flags when version wraps around */
3360 version = INIT_ATTS_VERSION;
3361 for (j = nsAttsSize; j != 0; )
Elliott Hughes72472942018-01-10 08:36:10 -08003362 parser->m_nsAtts[--j].version = version;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003363 }
Elliott Hughes72472942018-01-10 08:36:10 -08003364 parser->m_nsAttsVersion = --version;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003365
3366 /* expand prefixed names and check for duplicates */
3367 for (; i < attIndex; i += 2) {
3368 const XML_Char *s = appAtts[i];
3369 if (s[-1] == 2) { /* prefixed */
3370 ATTRIBUTE_ID *id;
3371 const BINDING *b;
Elliott Hughes72472942018-01-10 08:36:10 -08003372 unsigned long uriHash;
3373 struct siphash sip_state;
3374 struct sipkey sip_key;
3375
3376 copy_salt_to_sipkey(parser, &sip_key);
3377 sip24_init(&sip_state, &sip_key);
3378
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003379 ((XML_Char *)s)[-1] = 0; /* clear flag */
Elliott Hughes35e432d2012-09-09 14:23:38 -07003380 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
Elliott Hughes72472942018-01-10 08:36:10 -08003381 if (!id || !id->prefix) {
3382 /* This code is walking through the appAtts array, dealing
3383 * with (in this case) a prefixed attribute name. To be in
3384 * the array, the attribute must have already been bound, so
3385 * has to have passed through the hash table lookup once
3386 * already. That implies that an entry for it already
3387 * exists, so the lookup above will return a pointer to
3388 * already allocated memory. There is no opportunaity for
3389 * the allocator to fail, so the condition above cannot be
3390 * fulfilled.
3391 *
3392 * Since it is difficult to be certain that the above
3393 * analysis is complete, we retain the test and merely
3394 * remove the code from coverage tests.
3395 */
3396 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
3397 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003398 b = id->prefix->binding;
3399 if (!b)
3400 return XML_ERROR_UNBOUND_PREFIX;
3401
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003402 for (j = 0; j < b->uriLen; j++) {
3403 const XML_Char c = b->uri[j];
Elliott Hughes72472942018-01-10 08:36:10 -08003404 if (!poolAppendChar(&parser->m_tempPool, c))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003405 return XML_ERROR_NO_MEMORY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003406 }
Elliott Hughes72472942018-01-10 08:36:10 -08003407
3408 sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
3409
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003410 while (*s++ != XML_T(ASCII_COLON))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003411 ;
Elliott Hughes72472942018-01-10 08:36:10 -08003412
3413 sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
3414
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003415 do { /* copies null terminator */
Elliott Hughes72472942018-01-10 08:36:10 -08003416 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003417 return XML_ERROR_NO_MEMORY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003418 } while (*s++);
3419
Elliott Hughes72472942018-01-10 08:36:10 -08003420 uriHash = (unsigned long)sip24_final(&sip_state);
3421
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003422 { /* Check hash table for duplicate of expanded name (uriName).
Elliott Hughes35e432d2012-09-09 14:23:38 -07003423 Derived from code in lookup(parser, HASH_TABLE *table, ...).
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003424 */
3425 unsigned char step = 0;
3426 unsigned long mask = nsAttsSize - 1;
3427 j = uriHash & mask; /* index into hash table */
Elliott Hughes72472942018-01-10 08:36:10 -08003428 while (parser->m_nsAtts[j].version == version) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003429 /* for speed we compare stored hash values first */
Elliott Hughes72472942018-01-10 08:36:10 -08003430 if (uriHash == parser->m_nsAtts[j].hash) {
3431 const XML_Char *s1 = poolStart(&parser->m_tempPool);
3432 const XML_Char *s2 = parser->m_nsAtts[j].uriName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003433 /* s1 is null terminated, but not s2 */
3434 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
3435 if (*s1 == 0)
3436 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3437 }
3438 if (!step)
Elliott Hughes72472942018-01-10 08:36:10 -08003439 step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003440 j < step ? (j += nsAttsSize - step) : (j -= step);
3441 }
3442 }
3443
Elliott Hughes72472942018-01-10 08:36:10 -08003444 if (parser->m_ns_triplets) { /* append namespace separator and prefix */
3445 parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003446 s = b->prefix->name;
3447 do {
Elliott Hughes72472942018-01-10 08:36:10 -08003448 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003449 return XML_ERROR_NO_MEMORY;
3450 } while (*s++);
3451 }
3452
3453 /* store expanded name in attribute list */
Elliott Hughes72472942018-01-10 08:36:10 -08003454 s = poolStart(&parser->m_tempPool);
3455 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003456 appAtts[i] = s;
3457
3458 /* fill empty slot with new version, uriName and hash value */
Elliott Hughes72472942018-01-10 08:36:10 -08003459 parser->m_nsAtts[j].version = version;
3460 parser->m_nsAtts[j].hash = uriHash;
3461 parser->m_nsAtts[j].uriName = s;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003462
3463 if (!--nPrefixes) {
3464 i += 2;
3465 break;
3466 }
3467 }
3468 else /* not prefixed */
3469 ((XML_Char *)s)[-1] = 0; /* clear flag */
3470 }
3471 }
3472 /* clear flags for the remaining attributes */
3473 for (; i < attIndex; i += 2)
3474 ((XML_Char *)(appAtts[i]))[-1] = 0;
3475 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3476 binding->attId->name[-1] = 0;
3477
Elliott Hughes72472942018-01-10 08:36:10 -08003478 if (!parser->m_ns)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003479 return XML_ERROR_NONE;
3480
3481 /* expand the element type name */
3482 if (elementType->prefix) {
3483 binding = elementType->prefix->binding;
3484 if (!binding)
3485 return XML_ERROR_UNBOUND_PREFIX;
3486 localPart = tagNamePtr->str;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003487 while (*localPart++ != XML_T(ASCII_COLON))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003488 ;
3489 }
3490 else if (dtd->defaultPrefix.binding) {
3491 binding = dtd->defaultPrefix.binding;
3492 localPart = tagNamePtr->str;
3493 }
3494 else
3495 return XML_ERROR_NONE;
3496 prefixLen = 0;
Elliott Hughes72472942018-01-10 08:36:10 -08003497 if (parser->m_ns_triplets && binding->prefix->name) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003498 for (; binding->prefix->name[prefixLen++];)
3499 ; /* prefixLen includes null terminator */
3500 }
3501 tagNamePtr->localPart = localPart;
3502 tagNamePtr->uriLen = binding->uriLen;
3503 tagNamePtr->prefix = binding->prefix->name;
3504 tagNamePtr->prefixLen = prefixLen;
3505 for (i = 0; localPart[i++];)
3506 ; /* i includes null terminator */
3507 n = i + binding->uriLen + prefixLen;
3508 if (n > binding->uriAlloc) {
3509 TAG *p;
Elliott Hughes72472942018-01-10 08:36:10 -08003510 uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003511 if (!uri)
3512 return XML_ERROR_NO_MEMORY;
3513 binding->uriAlloc = n + EXPAND_SPARE;
3514 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
Elliott Hughes72472942018-01-10 08:36:10 -08003515 for (p = parser->m_tagStack; p; p = p->parent)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003516 if (p->name.str == binding->uri)
3517 p->name.str = uri;
Elliott Hughes72472942018-01-10 08:36:10 -08003518 FREE(parser, binding->uri);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003519 binding->uri = uri;
3520 }
Elliott Hughes72472942018-01-10 08:36:10 -08003521 /* if m_namespaceSeparator != '\0' then uri includes it already */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003522 uri = binding->uri + binding->uriLen;
3523 memcpy(uri, localPart, i * sizeof(XML_Char));
3524 /* we always have a namespace separator between localPart and prefix */
3525 if (prefixLen) {
3526 uri += i - 1;
Elliott Hughes72472942018-01-10 08:36:10 -08003527 *uri = parser->m_namespaceSeparator; /* replace null terminator */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003528 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3529 }
3530 tagNamePtr->str = binding->uri;
3531 return XML_ERROR_NONE;
3532}
3533
3534/* addBinding() overwrites the value of prefix->binding without checking.
3535 Therefore one must keep track of the old value outside of addBinding().
3536*/
3537static enum XML_Error
3538addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3539 const XML_Char *uri, BINDING **bindingsPtr)
3540{
3541 static const XML_Char xmlNamespace[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003542 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3543 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
Elliott Hughes35e432d2012-09-09 14:23:38 -07003544 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003545 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
3546 ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
3547 ASCII_e, '\0'
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003548 };
Elliott Hughes35e432d2012-09-09 14:23:38 -07003549 static const int xmlLen =
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003550 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
3551 static const XML_Char xmlnsNamespace[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003552 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3553 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
Elliott Hughes35e432d2012-09-09 14:23:38 -07003554 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
3555 ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003556 ASCII_SLASH, '\0'
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003557 };
Elliott Hughes35e432d2012-09-09 14:23:38 -07003558 static const int xmlnsLen =
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003559 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
3560
3561 XML_Bool mustBeXML = XML_FALSE;
3562 XML_Bool isXML = XML_TRUE;
3563 XML_Bool isXMLNS = XML_TRUE;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003564
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003565 BINDING *b;
3566 int len;
3567
3568 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3569 if (*uri == XML_T('\0') && prefix->name)
3570 return XML_ERROR_UNDECLARING_PREFIX;
3571
3572 if (prefix->name
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003573 && prefix->name[0] == XML_T(ASCII_x)
3574 && prefix->name[1] == XML_T(ASCII_m)
3575 && prefix->name[2] == XML_T(ASCII_l)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003576
3577 /* Not allowed to bind xmlns */
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003578 if (prefix->name[3] == XML_T(ASCII_n)
3579 && prefix->name[4] == XML_T(ASCII_s)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003580 && prefix->name[5] == XML_T('\0'))
3581 return XML_ERROR_RESERVED_PREFIX_XMLNS;
3582
3583 if (prefix->name[3] == XML_T('\0'))
3584 mustBeXML = XML_TRUE;
3585 }
3586
3587 for (len = 0; uri[len]; len++) {
3588 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3589 isXML = XML_FALSE;
3590
Elliott Hughes35e432d2012-09-09 14:23:38 -07003591 if (!mustBeXML && isXMLNS
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003592 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3593 isXMLNS = XML_FALSE;
3594 }
3595 isXML = isXML && len == xmlLen;
3596 isXMLNS = isXMLNS && len == xmlnsLen;
3597
3598 if (mustBeXML != isXML)
3599 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3600 : XML_ERROR_RESERVED_NAMESPACE_URI;
3601
3602 if (isXMLNS)
3603 return XML_ERROR_RESERVED_NAMESPACE_URI;
3604
Elliott Hughes72472942018-01-10 08:36:10 -08003605 if (parser->m_namespaceSeparator)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003606 len++;
Elliott Hughes72472942018-01-10 08:36:10 -08003607 if (parser->m_freeBindingList) {
3608 b = parser->m_freeBindingList;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003609 if (len > b->uriAlloc) {
Elliott Hughes72472942018-01-10 08:36:10 -08003610 XML_Char *temp = (XML_Char *)REALLOC(parser, b->uri,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003611 sizeof(XML_Char) * (len + EXPAND_SPARE));
3612 if (temp == NULL)
3613 return XML_ERROR_NO_MEMORY;
3614 b->uri = temp;
3615 b->uriAlloc = len + EXPAND_SPARE;
3616 }
Elliott Hughes72472942018-01-10 08:36:10 -08003617 parser->m_freeBindingList = b->nextTagBinding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003618 }
3619 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003620 b = (BINDING *)MALLOC(parser, sizeof(BINDING));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003621 if (!b)
3622 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003623 b->uri = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003624 if (!b->uri) {
Elliott Hughes72472942018-01-10 08:36:10 -08003625 FREE(parser, b);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003626 return XML_ERROR_NO_MEMORY;
3627 }
3628 b->uriAlloc = len + EXPAND_SPARE;
3629 }
3630 b->uriLen = len;
3631 memcpy(b->uri, uri, len * sizeof(XML_Char));
Elliott Hughes72472942018-01-10 08:36:10 -08003632 if (parser->m_namespaceSeparator)
3633 b->uri[len - 1] = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003634 b->prefix = prefix;
3635 b->attId = attId;
3636 b->prevPrefixBinding = prefix->binding;
3637 /* NULL binding when default namespace undeclared */
Elliott Hughes72472942018-01-10 08:36:10 -08003638 if (*uri == XML_T('\0') && prefix == &parser->m_dtd->defaultPrefix)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003639 prefix->binding = NULL;
3640 else
3641 prefix->binding = b;
3642 b->nextTagBinding = *bindingsPtr;
3643 *bindingsPtr = b;
3644 /* if attId == NULL then we are not starting a namespace scope */
Elliott Hughes72472942018-01-10 08:36:10 -08003645 if (attId && parser->m_startNamespaceDeclHandler)
3646 parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003647 prefix->binding ? uri : 0);
3648 return XML_ERROR_NONE;
3649}
3650
3651/* The idea here is to avoid using stack for each CDATA section when
3652 the whole file is parsed with one call.
3653*/
3654static enum XML_Error PTRCALL
3655cdataSectionProcessor(XML_Parser parser,
3656 const char *start,
3657 const char *end,
3658 const char **endPtr)
3659{
Elliott Hughes72472942018-01-10 08:36:10 -08003660 enum XML_Error result = doCdataSection(parser, parser->m_encoding, &start, end,
3661 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003662 if (result != XML_ERROR_NONE)
3663 return result;
3664 if (start) {
Elliott Hughes72472942018-01-10 08:36:10 -08003665 if (parser->m_parentParser) { /* we are parsing an external entity */
3666 parser->m_processor = externalEntityContentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003667 return externalEntityContentProcessor(parser, start, end, endPtr);
3668 }
3669 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003670 parser->m_processor = contentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003671 return contentProcessor(parser, start, end, endPtr);
3672 }
3673 }
3674 return result;
3675}
3676
3677/* startPtr gets set to non-null if the section is closed, and to null if
3678 the section is not yet closed.
3679*/
3680static enum XML_Error
3681doCdataSection(XML_Parser parser,
3682 const ENCODING *enc,
3683 const char **startPtr,
3684 const char *end,
3685 const char **nextPtr,
3686 XML_Bool haveMore)
3687{
3688 const char *s = *startPtr;
3689 const char **eventPP;
3690 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08003691 if (enc == parser->m_encoding) {
3692 eventPP = &parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003693 *eventPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08003694 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003695 }
3696 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003697 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3698 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003699 }
3700 *eventPP = s;
3701 *startPtr = NULL;
3702
3703 for (;;) {
3704 const char *next;
3705 int tok = XmlCdataSectionTok(enc, s, end, &next);
3706 *eventEndPP = next;
3707 switch (tok) {
3708 case XML_TOK_CDATA_SECT_CLOSE:
Elliott Hughes72472942018-01-10 08:36:10 -08003709 if (parser->m_endCdataSectionHandler)
3710 parser->m_endCdataSectionHandler(parser->m_handlerArg);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003711#if 0
3712 /* see comment under XML_TOK_CDATA_SECT_OPEN */
Elliott Hughes72472942018-01-10 08:36:10 -08003713 else if (parser->m_characterDataHandler)
3714 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003715#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003716 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003717 reportDefault(parser, enc, s, next);
3718 *startPtr = next;
3719 *nextPtr = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003720 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003721 return XML_ERROR_ABORTED;
3722 else
3723 return XML_ERROR_NONE;
3724 case XML_TOK_DATA_NEWLINE:
Elliott Hughes72472942018-01-10 08:36:10 -08003725 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003726 XML_Char c = 0xA;
Elliott Hughes72472942018-01-10 08:36:10 -08003727 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003728 }
Elliott Hughes72472942018-01-10 08:36:10 -08003729 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003730 reportDefault(parser, enc, s, next);
3731 break;
3732 case XML_TOK_DATA_CHARS:
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003733 {
Elliott Hughes72472942018-01-10 08:36:10 -08003734 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003735 if (charDataHandler) {
3736 if (MUST_CONVERT(enc, s)) {
3737 for (;;) {
Elliott Hughes72472942018-01-10 08:36:10 -08003738 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3739 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003740 *eventEndPP = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003741 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3742 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
Paul Duffin4bf8f122016-05-13 12:35:25 +01003743 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003744 break;
3745 *eventPP = s;
3746 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003747 }
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003748 else
Elliott Hughes72472942018-01-10 08:36:10 -08003749 charDataHandler(parser->m_handlerArg,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003750 (XML_Char *)s,
3751 (int)((XML_Char *)next - (XML_Char *)s));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003752 }
Elliott Hughes72472942018-01-10 08:36:10 -08003753 else if (parser->m_defaultHandler)
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003754 reportDefault(parser, enc, s, next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003755 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003756 break;
3757 case XML_TOK_INVALID:
3758 *eventPP = next;
3759 return XML_ERROR_INVALID_TOKEN;
3760 case XML_TOK_PARTIAL_CHAR:
3761 if (haveMore) {
3762 *nextPtr = s;
3763 return XML_ERROR_NONE;
3764 }
3765 return XML_ERROR_PARTIAL_CHAR;
3766 case XML_TOK_PARTIAL:
3767 case XML_TOK_NONE:
3768 if (haveMore) {
3769 *nextPtr = s;
3770 return XML_ERROR_NONE;
3771 }
3772 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3773 default:
Elliott Hughes72472942018-01-10 08:36:10 -08003774 /* Every token returned by XmlCdataSectionTok() has its own
3775 * explicit case, so this default case will never be executed.
3776 * We retain it as a safety net and exclude it from the coverage
3777 * statistics.
3778 *
3779 * LCOV_EXCL_START
3780 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003781 *eventPP = next;
3782 return XML_ERROR_UNEXPECTED_STATE;
Elliott Hughes72472942018-01-10 08:36:10 -08003783 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003784 }
3785
3786 *eventPP = s = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003787 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003788 case XML_SUSPENDED:
3789 *nextPtr = next;
3790 return XML_ERROR_NONE;
3791 case XML_FINISHED:
3792 return XML_ERROR_ABORTED;
3793 default: ;
3794 }
3795 }
3796 /* not reached */
3797}
3798
3799#ifdef XML_DTD
3800
3801/* The idea here is to avoid using stack for each IGNORE section when
3802 the whole file is parsed with one call.
3803*/
3804static enum XML_Error PTRCALL
3805ignoreSectionProcessor(XML_Parser parser,
3806 const char *start,
3807 const char *end,
3808 const char **endPtr)
3809{
Elliott Hughes72472942018-01-10 08:36:10 -08003810 enum XML_Error result = doIgnoreSection(parser, parser->m_encoding, &start, end,
3811 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003812 if (result != XML_ERROR_NONE)
3813 return result;
3814 if (start) {
Elliott Hughes72472942018-01-10 08:36:10 -08003815 parser->m_processor = prologProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003816 return prologProcessor(parser, start, end, endPtr);
3817 }
3818 return result;
3819}
3820
3821/* startPtr gets set to non-null is the section is closed, and to null
3822 if the section is not yet closed.
3823*/
3824static enum XML_Error
3825doIgnoreSection(XML_Parser parser,
3826 const ENCODING *enc,
3827 const char **startPtr,
3828 const char *end,
3829 const char **nextPtr,
3830 XML_Bool haveMore)
3831{
3832 const char *next;
3833 int tok;
3834 const char *s = *startPtr;
3835 const char **eventPP;
3836 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08003837 if (enc == parser->m_encoding) {
3838 eventPP = &parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003839 *eventPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08003840 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003841 }
3842 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003843 /* It's not entirely clear, but it seems the following two lines
3844 * of code cannot be executed. The only occasions on which 'enc'
3845 * is not 'encoding' are when this function is called
3846 * from the internal entity processing, and IGNORE sections are an
3847 * error in internal entities.
3848 *
3849 * Since it really isn't clear that this is true, we keep the code
3850 * and just remove it from our coverage tests.
3851 *
3852 * LCOV_EXCL_START
3853 */
3854 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3855 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
3856 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003857 }
3858 *eventPP = s;
3859 *startPtr = NULL;
3860 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3861 *eventEndPP = next;
3862 switch (tok) {
3863 case XML_TOK_IGNORE_SECT:
Elliott Hughes72472942018-01-10 08:36:10 -08003864 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003865 reportDefault(parser, enc, s, next);
3866 *startPtr = next;
3867 *nextPtr = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003868 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003869 return XML_ERROR_ABORTED;
3870 else
3871 return XML_ERROR_NONE;
3872 case XML_TOK_INVALID:
3873 *eventPP = next;
3874 return XML_ERROR_INVALID_TOKEN;
3875 case XML_TOK_PARTIAL_CHAR:
3876 if (haveMore) {
3877 *nextPtr = s;
3878 return XML_ERROR_NONE;
3879 }
3880 return XML_ERROR_PARTIAL_CHAR;
3881 case XML_TOK_PARTIAL:
3882 case XML_TOK_NONE:
3883 if (haveMore) {
3884 *nextPtr = s;
3885 return XML_ERROR_NONE;
3886 }
3887 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3888 default:
Elliott Hughes72472942018-01-10 08:36:10 -08003889 /* All of the tokens that XmlIgnoreSectionTok() returns have
3890 * explicit cases to handle them, so this default case is never
3891 * executed. We keep it as a safety net anyway, and remove it
3892 * from our test coverage statistics.
3893 *
3894 * LCOV_EXCL_START
3895 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003896 *eventPP = next;
3897 return XML_ERROR_UNEXPECTED_STATE;
Elliott Hughes72472942018-01-10 08:36:10 -08003898 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003899 }
3900 /* not reached */
3901}
3902
3903#endif /* XML_DTD */
3904
3905static enum XML_Error
3906initializeEncoding(XML_Parser parser)
3907{
3908 const char *s;
3909#ifdef XML_UNICODE
3910 char encodingBuf[128];
Elliott Hughes72472942018-01-10 08:36:10 -08003911 /* See comments abount `protoclEncodingName` in parserInit() */
3912 if (!parser->m_protocolEncodingName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003913 s = NULL;
3914 else {
3915 int i;
Elliott Hughes72472942018-01-10 08:36:10 -08003916 for (i = 0; parser->m_protocolEncodingName[i]; i++) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003917 if (i == sizeof(encodingBuf) - 1
Elliott Hughes72472942018-01-10 08:36:10 -08003918 || (parser->m_protocolEncodingName[i] & ~0x7f) != 0) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003919 encodingBuf[0] = '\0';
3920 break;
3921 }
Elliott Hughes72472942018-01-10 08:36:10 -08003922 encodingBuf[i] = (char)parser->m_protocolEncodingName[i];
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003923 }
3924 encodingBuf[i] = '\0';
3925 s = encodingBuf;
3926 }
3927#else
Elliott Hughes72472942018-01-10 08:36:10 -08003928 s = parser->m_protocolEncodingName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003929#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003930 if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(&parser->m_initEncoding, &parser->m_encoding, s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003931 return XML_ERROR_NONE;
Elliott Hughes72472942018-01-10 08:36:10 -08003932 return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003933}
3934
3935static enum XML_Error
3936processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3937 const char *s, const char *next)
3938{
3939 const char *encodingName = NULL;
3940 const XML_Char *storedEncName = NULL;
3941 const ENCODING *newEncoding = NULL;
3942 const char *version = NULL;
3943 const char *versionend;
3944 const XML_Char *storedversion = NULL;
3945 int standalone = -1;
Elliott Hughes72472942018-01-10 08:36:10 -08003946 if (!(parser->m_ns
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003947 ? XmlParseXmlDeclNS
3948 : XmlParseXmlDecl)(isGeneralTextEntity,
Elliott Hughes72472942018-01-10 08:36:10 -08003949 parser->m_encoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003950 s,
3951 next,
Elliott Hughes72472942018-01-10 08:36:10 -08003952 &parser->m_eventPtr,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003953 &version,
3954 &versionend,
3955 &encodingName,
3956 &newEncoding,
3957 &standalone)) {
3958 if (isGeneralTextEntity)
3959 return XML_ERROR_TEXT_DECL;
3960 else
3961 return XML_ERROR_XML_DECL;
3962 }
3963 if (!isGeneralTextEntity && standalone == 1) {
Elliott Hughes72472942018-01-10 08:36:10 -08003964 parser->m_dtd->standalone = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003965#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08003966 if (parser->m_paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3967 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003968#endif /* XML_DTD */
3969 }
Elliott Hughes72472942018-01-10 08:36:10 -08003970 if (parser->m_xmlDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003971 if (encodingName != NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08003972 storedEncName = poolStoreString(&parser->m_temp2Pool,
3973 parser->m_encoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003974 encodingName,
3975 encodingName
Elliott Hughes72472942018-01-10 08:36:10 -08003976 + XmlNameLength(parser->m_encoding, encodingName));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003977 if (!storedEncName)
3978 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003979 poolFinish(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003980 }
3981 if (version) {
Elliott Hughes72472942018-01-10 08:36:10 -08003982 storedversion = poolStoreString(&parser->m_temp2Pool,
3983 parser->m_encoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003984 version,
Elliott Hughes72472942018-01-10 08:36:10 -08003985 versionend - parser->m_encoding->minBytesPerChar);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003986 if (!storedversion)
3987 return XML_ERROR_NO_MEMORY;
3988 }
Elliott Hughes72472942018-01-10 08:36:10 -08003989 parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName, standalone);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003990 }
Elliott Hughes72472942018-01-10 08:36:10 -08003991 else if (parser->m_defaultHandler)
3992 reportDefault(parser, parser->m_encoding, s, next);
3993 if (parser->m_protocolEncodingName == NULL) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003994 if (newEncoding) {
Elliott Hughes72472942018-01-10 08:36:10 -08003995 /* Check that the specified encoding does not conflict with what
3996 * the parser has already deduced. Do we have the same number
3997 * of bytes in the smallest representation of a character? If
3998 * this is UTF-16, is it the same endianness?
3999 */
4000 if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
4001 || (newEncoding->minBytesPerChar == 2 &&
4002 newEncoding != parser->m_encoding)) {
4003 parser->m_eventPtr = encodingName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004004 return XML_ERROR_INCORRECT_ENCODING;
4005 }
Elliott Hughes72472942018-01-10 08:36:10 -08004006 parser->m_encoding = newEncoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004007 }
4008 else if (encodingName) {
4009 enum XML_Error result;
4010 if (!storedEncName) {
4011 storedEncName = poolStoreString(
Elliott Hughes72472942018-01-10 08:36:10 -08004012 &parser->m_temp2Pool, parser->m_encoding, encodingName,
4013 encodingName + XmlNameLength(parser->m_encoding, encodingName));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004014 if (!storedEncName)
4015 return XML_ERROR_NO_MEMORY;
4016 }
4017 result = handleUnknownEncoding(parser, storedEncName);
Elliott Hughes72472942018-01-10 08:36:10 -08004018 poolClear(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004019 if (result == XML_ERROR_UNKNOWN_ENCODING)
Elliott Hughes72472942018-01-10 08:36:10 -08004020 parser->m_eventPtr = encodingName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004021 return result;
4022 }
4023 }
4024
4025 if (storedEncName || storedversion)
Elliott Hughes72472942018-01-10 08:36:10 -08004026 poolClear(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004027
4028 return XML_ERROR_NONE;
4029}
4030
4031static enum XML_Error
4032handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
4033{
Elliott Hughes72472942018-01-10 08:36:10 -08004034 if (parser->m_unknownEncodingHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004035 XML_Encoding info;
4036 int i;
4037 for (i = 0; i < 256; i++)
4038 info.map[i] = -1;
4039 info.convert = NULL;
4040 info.data = NULL;
4041 info.release = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08004042 if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData, encodingName,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004043 &info)) {
4044 ENCODING *enc;
Elliott Hughes72472942018-01-10 08:36:10 -08004045 parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding());
4046 if (!parser->m_unknownEncodingMem) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004047 if (info.release)
4048 info.release(info.data);
4049 return XML_ERROR_NO_MEMORY;
4050 }
Elliott Hughes72472942018-01-10 08:36:10 -08004051 enc = (parser->m_ns
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004052 ? XmlInitUnknownEncodingNS
Elliott Hughes72472942018-01-10 08:36:10 -08004053 : XmlInitUnknownEncoding)(parser->m_unknownEncodingMem,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004054 info.map,
4055 info.convert,
4056 info.data);
4057 if (enc) {
Elliott Hughes72472942018-01-10 08:36:10 -08004058 parser->m_unknownEncodingData = info.data;
4059 parser->m_unknownEncodingRelease = info.release;
4060 parser->m_encoding = enc;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004061 return XML_ERROR_NONE;
4062 }
4063 }
4064 if (info.release != NULL)
4065 info.release(info.data);
4066 }
4067 return XML_ERROR_UNKNOWN_ENCODING;
4068}
4069
4070static enum XML_Error PTRCALL
4071prologInitProcessor(XML_Parser parser,
4072 const char *s,
4073 const char *end,
4074 const char **nextPtr)
4075{
4076 enum XML_Error result = initializeEncoding(parser);
4077 if (result != XML_ERROR_NONE)
4078 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004079 parser->m_processor = prologProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004080 return prologProcessor(parser, s, end, nextPtr);
4081}
4082
4083#ifdef XML_DTD
4084
4085static enum XML_Error PTRCALL
4086externalParEntInitProcessor(XML_Parser parser,
4087 const char *s,
4088 const char *end,
4089 const char **nextPtr)
4090{
4091 enum XML_Error result = initializeEncoding(parser);
4092 if (result != XML_ERROR_NONE)
4093 return result;
4094
4095 /* we know now that XML_Parse(Buffer) has been called,
4096 so we consider the external parameter entity read */
Elliott Hughes72472942018-01-10 08:36:10 -08004097 parser->m_dtd->paramEntityRead = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004098
Elliott Hughes72472942018-01-10 08:36:10 -08004099 if (parser->m_prologState.inEntityValue) {
4100 parser->m_processor = entityValueInitProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004101 return entityValueInitProcessor(parser, s, end, nextPtr);
4102 }
4103 else {
Elliott Hughes72472942018-01-10 08:36:10 -08004104 parser->m_processor = externalParEntProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004105 return externalParEntProcessor(parser, s, end, nextPtr);
4106 }
4107}
4108
4109static enum XML_Error PTRCALL
4110entityValueInitProcessor(XML_Parser parser,
4111 const char *s,
4112 const char *end,
4113 const char **nextPtr)
4114{
4115 int tok;
4116 const char *start = s;
4117 const char *next = start;
Elliott Hughes72472942018-01-10 08:36:10 -08004118 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004119
Elliott Hughes35e432d2012-09-09 14:23:38 -07004120 for (;;) {
Elliott Hughes72472942018-01-10 08:36:10 -08004121 tok = XmlPrologTok(parser->m_encoding, start, end, &next);
4122 parser->m_eventEndPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004123 if (tok <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08004124 if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004125 *nextPtr = s;
4126 return XML_ERROR_NONE;
4127 }
4128 switch (tok) {
4129 case XML_TOK_INVALID:
4130 return XML_ERROR_INVALID_TOKEN;
4131 case XML_TOK_PARTIAL:
4132 return XML_ERROR_UNCLOSED_TOKEN;
4133 case XML_TOK_PARTIAL_CHAR:
4134 return XML_ERROR_PARTIAL_CHAR;
4135 case XML_TOK_NONE: /* start == end */
4136 default:
4137 break;
4138 }
4139 /* found end of entity value - can store it now */
Elliott Hughes72472942018-01-10 08:36:10 -08004140 return storeEntityValue(parser, parser->m_encoding, s, end);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004141 }
4142 else if (tok == XML_TOK_XML_DECL) {
4143 enum XML_Error result;
4144 result = processXmlDecl(parser, 0, start, next);
4145 if (result != XML_ERROR_NONE)
4146 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004147 /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED. For that
4148 * to happen, a parameter entity parsing handler must have
4149 * attempted to suspend the parser, which fails and raises an
4150 * error. The parser can be aborted, but can't be suspended.
4151 */
4152 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004153 return XML_ERROR_ABORTED;
Elliott Hughes72472942018-01-10 08:36:10 -08004154 *nextPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004155 /* stop scanning for text declaration - we found one */
Elliott Hughes72472942018-01-10 08:36:10 -08004156 parser->m_processor = entityValueProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004157 return entityValueProcessor(parser, next, end, nextPtr);
4158 }
4159 /* If we are at the end of the buffer, this would cause XmlPrologTok to
4160 return XML_TOK_NONE on the next call, which would then cause the
4161 function to exit with *nextPtr set to s - that is what we want for other
4162 tokens, but not for the BOM - we would rather like to skip it;
4163 then, when this routine is entered the next time, XmlPrologTok will
4164 return XML_TOK_INVALID, since the BOM is still in the buffer
4165 */
Elliott Hughes72472942018-01-10 08:36:10 -08004166 else if (tok == XML_TOK_BOM && next == end && !parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004167 *nextPtr = next;
4168 return XML_ERROR_NONE;
4169 }
Elliott Hughes72472942018-01-10 08:36:10 -08004170 /* If we get this token, we have the start of what might be a
4171 normal tag, but not a declaration (i.e. it doesn't begin with
4172 "<!"). In a DTD context, that isn't legal.
4173 */
4174 else if (tok == XML_TOK_INSTANCE_START) {
4175 *nextPtr = next;
4176 return XML_ERROR_SYNTAX;
4177 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004178 start = next;
Elliott Hughes72472942018-01-10 08:36:10 -08004179 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004180 }
4181}
4182
4183static enum XML_Error PTRCALL
4184externalParEntProcessor(XML_Parser parser,
4185 const char *s,
4186 const char *end,
4187 const char **nextPtr)
4188{
4189 const char *next = s;
4190 int tok;
4191
Elliott Hughes72472942018-01-10 08:36:10 -08004192 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004193 if (tok <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08004194 if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004195 *nextPtr = s;
4196 return XML_ERROR_NONE;
4197 }
4198 switch (tok) {
4199 case XML_TOK_INVALID:
4200 return XML_ERROR_INVALID_TOKEN;
4201 case XML_TOK_PARTIAL:
4202 return XML_ERROR_UNCLOSED_TOKEN;
4203 case XML_TOK_PARTIAL_CHAR:
4204 return XML_ERROR_PARTIAL_CHAR;
4205 case XML_TOK_NONE: /* start == end */
4206 default:
4207 break;
4208 }
4209 }
4210 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
4211 However, when parsing an external subset, doProlog will not accept a BOM
4212 as valid, and report a syntax error, so we have to skip the BOM
4213 */
4214 else if (tok == XML_TOK_BOM) {
4215 s = next;
Elliott Hughes72472942018-01-10 08:36:10 -08004216 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004217 }
4218
Elliott Hughes72472942018-01-10 08:36:10 -08004219 parser->m_processor = prologProcessor;
4220 return doProlog(parser, parser->m_encoding, s, end, tok, next,
4221 nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004222}
4223
4224static enum XML_Error PTRCALL
4225entityValueProcessor(XML_Parser parser,
4226 const char *s,
4227 const char *end,
4228 const char **nextPtr)
4229{
4230 const char *start = s;
4231 const char *next = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004232 const ENCODING *enc = parser->m_encoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004233 int tok;
4234
4235 for (;;) {
4236 tok = XmlPrologTok(enc, start, end, &next);
4237 if (tok <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08004238 if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004239 *nextPtr = s;
4240 return XML_ERROR_NONE;
4241 }
4242 switch (tok) {
4243 case XML_TOK_INVALID:
4244 return XML_ERROR_INVALID_TOKEN;
4245 case XML_TOK_PARTIAL:
4246 return XML_ERROR_UNCLOSED_TOKEN;
4247 case XML_TOK_PARTIAL_CHAR:
4248 return XML_ERROR_PARTIAL_CHAR;
4249 case XML_TOK_NONE: /* start == end */
4250 default:
4251 break;
4252 }
4253 /* found end of entity value - can store it now */
4254 return storeEntityValue(parser, enc, s, end);
4255 }
4256 start = next;
4257 }
4258}
4259
4260#endif /* XML_DTD */
4261
4262static enum XML_Error PTRCALL
4263prologProcessor(XML_Parser parser,
4264 const char *s,
4265 const char *end,
4266 const char **nextPtr)
4267{
4268 const char *next = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004269 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4270 return doProlog(parser, parser->m_encoding, s, end, tok, next,
4271 nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004272}
4273
4274static enum XML_Error
4275doProlog(XML_Parser parser,
4276 const ENCODING *enc,
4277 const char *s,
4278 const char *end,
4279 int tok,
4280 const char *next,
4281 const char **nextPtr,
4282 XML_Bool haveMore)
4283{
4284#ifdef XML_DTD
Elliott Hughesd07d5a72009-09-25 16:04:37 -07004285 static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004286#endif /* XML_DTD */
Elliott Hughes35e432d2012-09-09 14:23:38 -07004287 static const XML_Char atypeCDATA[] =
Elliott Hughesd07d5a72009-09-25 16:04:37 -07004288 { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
4289 static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
4290 static const XML_Char atypeIDREF[] =
4291 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
4292 static const XML_Char atypeIDREFS[] =
4293 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
4294 static const XML_Char atypeENTITY[] =
4295 { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
4296 static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
4297 ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004298 static const XML_Char atypeNMTOKEN[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07004299 ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
4300 static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
4301 ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
4302 static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
4303 ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
4304 static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
4305 static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004306
4307 /* save one level of indirection */
Elliott Hughes72472942018-01-10 08:36:10 -08004308 DTD * const dtd = parser->m_dtd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004309
4310 const char **eventPP;
4311 const char **eventEndPP;
4312 enum XML_Content_Quant quant;
4313
Elliott Hughes72472942018-01-10 08:36:10 -08004314 if (enc == parser->m_encoding) {
4315 eventPP = &parser->m_eventPtr;
4316 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004317 }
4318 else {
Elliott Hughes72472942018-01-10 08:36:10 -08004319 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4320 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004321 }
4322
4323 for (;;) {
4324 int role;
4325 XML_Bool handleDefault = XML_TRUE;
4326 *eventPP = s;
4327 *eventEndPP = next;
4328 if (tok <= 0) {
4329 if (haveMore && tok != XML_TOK_INVALID) {
4330 *nextPtr = s;
4331 return XML_ERROR_NONE;
4332 }
4333 switch (tok) {
4334 case XML_TOK_INVALID:
4335 *eventPP = next;
4336 return XML_ERROR_INVALID_TOKEN;
4337 case XML_TOK_PARTIAL:
4338 return XML_ERROR_UNCLOSED_TOKEN;
4339 case XML_TOK_PARTIAL_CHAR:
4340 return XML_ERROR_PARTIAL_CHAR;
Elliott Hughes35e432d2012-09-09 14:23:38 -07004341 case -XML_TOK_PROLOG_S:
4342 tok = -tok;
4343 break;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004344 case XML_TOK_NONE:
4345#ifdef XML_DTD
4346 /* for internal PE NOT referenced between declarations */
Elliott Hughes72472942018-01-10 08:36:10 -08004347 if (enc != parser->m_encoding && !parser->m_openInternalEntities->betweenDecl) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004348 *nextPtr = s;
4349 return XML_ERROR_NONE;
4350 }
4351 /* WFC: PE Between Declarations - must check that PE contains
4352 complete markup, not only for external PEs, but also for
4353 internal PEs if the reference occurs between declarations.
4354 */
Elliott Hughes72472942018-01-10 08:36:10 -08004355 if (parser->m_isParamEntity || enc != parser->m_encoding) {
4356 if (XmlTokenRole(&parser->m_prologState, XML_TOK_NONE, end, end, enc)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004357 == XML_ROLE_ERROR)
4358 return XML_ERROR_INCOMPLETE_PE;
4359 *nextPtr = s;
4360 return XML_ERROR_NONE;
4361 }
4362#endif /* XML_DTD */
4363 return XML_ERROR_NO_ELEMENTS;
4364 default:
4365 tok = -tok;
4366 next = end;
4367 break;
4368 }
4369 }
Elliott Hughes72472942018-01-10 08:36:10 -08004370 role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004371 switch (role) {
4372 case XML_ROLE_XML_DECL:
4373 {
4374 enum XML_Error result = processXmlDecl(parser, 0, s, next);
4375 if (result != XML_ERROR_NONE)
4376 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004377 enc = parser->m_encoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004378 handleDefault = XML_FALSE;
4379 }
4380 break;
4381 case XML_ROLE_DOCTYPE_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004382 if (parser->m_startDoctypeDeclHandler) {
4383 parser->m_doctypeName = poolStoreString(&parser->m_tempPool, enc, s, next);
4384 if (!parser->m_doctypeName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004385 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004386 poolFinish(&parser->m_tempPool);
4387 parser->m_doctypePubid = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004388 handleDefault = XML_FALSE;
4389 }
Elliott Hughes72472942018-01-10 08:36:10 -08004390 parser->m_doctypeSysid = NULL; /* always initialize to NULL */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004391 break;
4392 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
Elliott Hughes72472942018-01-10 08:36:10 -08004393 if (parser->m_startDoctypeDeclHandler) {
4394 parser->m_startDoctypeDeclHandler(parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
4395 parser->m_doctypePubid, 1);
4396 parser->m_doctypeName = NULL;
4397 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004398 handleDefault = XML_FALSE;
4399 }
4400 break;
4401#ifdef XML_DTD
4402 case XML_ROLE_TEXT_DECL:
4403 {
4404 enum XML_Error result = processXmlDecl(parser, 1, s, next);
4405 if (result != XML_ERROR_NONE)
4406 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004407 enc = parser->m_encoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004408 handleDefault = XML_FALSE;
4409 }
4410 break;
4411#endif /* XML_DTD */
4412 case XML_ROLE_DOCTYPE_PUBLIC_ID:
4413#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004414 parser->m_useForeignDTD = XML_FALSE;
4415 parser->m_declEntity = (ENTITY *)lookup(parser,
Elliott Hughes35e432d2012-09-09 14:23:38 -07004416 &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004417 externalSubsetName,
4418 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004419 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004420 return XML_ERROR_NO_MEMORY;
4421#endif /* XML_DTD */
4422 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004423 if (parser->m_startDoctypeDeclHandler) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004424 XML_Char *pubId;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004425 if (!XmlIsPublicId(enc, s, next, eventPP))
4426 return XML_ERROR_PUBLICID;
Elliott Hughes72472942018-01-10 08:36:10 -08004427 pubId = poolStoreString(&parser->m_tempPool, enc,
Elliott Hughes35e432d2012-09-09 14:23:38 -07004428 s + enc->minBytesPerChar,
4429 next - enc->minBytesPerChar);
4430 if (!pubId)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004431 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07004432 normalizePublicId(pubId);
Elliott Hughes72472942018-01-10 08:36:10 -08004433 poolFinish(&parser->m_tempPool);
4434 parser->m_doctypePubid = pubId;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004435 handleDefault = XML_FALSE;
4436 goto alreadyChecked;
4437 }
4438 /* fall through */
4439 case XML_ROLE_ENTITY_PUBLIC_ID:
4440 if (!XmlIsPublicId(enc, s, next, eventPP))
4441 return XML_ERROR_PUBLICID;
4442 alreadyChecked:
Elliott Hughes72472942018-01-10 08:36:10 -08004443 if (dtd->keepProcessing && parser->m_declEntity) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004444 XML_Char *tem = poolStoreString(&dtd->pool,
4445 enc,
4446 s + enc->minBytesPerChar,
4447 next - enc->minBytesPerChar);
4448 if (!tem)
4449 return XML_ERROR_NO_MEMORY;
4450 normalizePublicId(tem);
Elliott Hughes72472942018-01-10 08:36:10 -08004451 parser->m_declEntity->publicId = tem;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004452 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004453 /* Don't suppress the default handler if we fell through from
4454 * the XML_ROLE_DOCTYPE_PUBLIC_ID case.
4455 */
4456 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004457 handleDefault = XML_FALSE;
4458 }
4459 break;
4460 case XML_ROLE_DOCTYPE_CLOSE:
Elliott Hughes72472942018-01-10 08:36:10 -08004461 if (parser->m_doctypeName) {
4462 parser->m_startDoctypeDeclHandler(parser->m_handlerArg, parser->m_doctypeName,
4463 parser->m_doctypeSysid, parser->m_doctypePubid, 0);
4464 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004465 handleDefault = XML_FALSE;
4466 }
Elliott Hughes72472942018-01-10 08:36:10 -08004467 /* parser->m_doctypeSysid will be non-NULL in the case of a previous
4468 XML_ROLE_DOCTYPE_SYSTEM_ID, even if parser->m_startDoctypeDeclHandler
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004469 was not set, indicating an external subset
4470 */
4471#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004472 if (parser->m_doctypeSysid || parser->m_useForeignDTD) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004473 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4474 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004475 if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004476 ENTITY *entity = (ENTITY *)lookup(parser,
4477 &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004478 externalSubsetName,
4479 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004480 if (!entity) {
4481 /* The external subset name "#" will have already been
4482 * inserted into the hash table at the start of the
4483 * external entity parsing, so no allocation will happen
4484 * and lookup() cannot fail.
4485 */
4486 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
4487 }
4488 if (parser->m_useForeignDTD)
4489 entity->base = parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004490 dtd->paramEntityRead = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08004491 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004492 0,
4493 entity->base,
4494 entity->systemId,
4495 entity->publicId))
4496 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4497 if (dtd->paramEntityRead) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004498 if (!dtd->standalone &&
Elliott Hughes72472942018-01-10 08:36:10 -08004499 parser->m_notStandaloneHandler &&
4500 !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004501 return XML_ERROR_NOT_STANDALONE;
4502 }
4503 /* if we didn't read the foreign DTD then this means that there
4504 is no external subset and we must reset dtd->hasParamEntityRefs
4505 */
Elliott Hughes72472942018-01-10 08:36:10 -08004506 else if (!parser->m_doctypeSysid)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004507 dtd->hasParamEntityRefs = hadParamEntityRefs;
4508 /* end of DTD - no need to update dtd->keepProcessing */
4509 }
Elliott Hughes72472942018-01-10 08:36:10 -08004510 parser->m_useForeignDTD = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004511 }
4512#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004513 if (parser->m_endDoctypeDeclHandler) {
4514 parser->m_endDoctypeDeclHandler(parser->m_handlerArg);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004515 handleDefault = XML_FALSE;
4516 }
4517 break;
4518 case XML_ROLE_INSTANCE_START:
4519#ifdef XML_DTD
4520 /* if there is no DOCTYPE declaration then now is the
4521 last chance to read the foreign DTD
4522 */
Elliott Hughes72472942018-01-10 08:36:10 -08004523 if (parser->m_useForeignDTD) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004524 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4525 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004526 if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004527 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004528 externalSubsetName,
4529 sizeof(ENTITY));
4530 if (!entity)
4531 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004532 entity->base = parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004533 dtd->paramEntityRead = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08004534 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004535 0,
4536 entity->base,
4537 entity->systemId,
4538 entity->publicId))
4539 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4540 if (dtd->paramEntityRead) {
4541 if (!dtd->standalone &&
Elliott Hughes72472942018-01-10 08:36:10 -08004542 parser->m_notStandaloneHandler &&
4543 !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004544 return XML_ERROR_NOT_STANDALONE;
4545 }
4546 /* if we didn't read the foreign DTD then this means that there
4547 is no external subset and we must reset dtd->hasParamEntityRefs
4548 */
4549 else
4550 dtd->hasParamEntityRefs = hadParamEntityRefs;
4551 /* end of DTD - no need to update dtd->keepProcessing */
4552 }
4553 }
4554#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004555 parser->m_processor = contentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004556 return contentProcessor(parser, s, end, nextPtr);
4557 case XML_ROLE_ATTLIST_ELEMENT_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004558 parser->m_declElementType = getElementType(parser, enc, s, next);
4559 if (!parser->m_declElementType)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004560 return XML_ERROR_NO_MEMORY;
4561 goto checkAttListDeclHandler;
4562 case XML_ROLE_ATTRIBUTE_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004563 parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
4564 if (!parser->m_declAttributeId)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004565 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004566 parser->m_declAttributeIsCdata = XML_FALSE;
4567 parser->m_declAttributeType = NULL;
4568 parser->m_declAttributeIsId = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004569 goto checkAttListDeclHandler;
4570 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
Elliott Hughes72472942018-01-10 08:36:10 -08004571 parser->m_declAttributeIsCdata = XML_TRUE;
4572 parser->m_declAttributeType = atypeCDATA;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004573 goto checkAttListDeclHandler;
4574 case XML_ROLE_ATTRIBUTE_TYPE_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004575 parser->m_declAttributeIsId = XML_TRUE;
4576 parser->m_declAttributeType = atypeID;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004577 goto checkAttListDeclHandler;
4578 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
Elliott Hughes72472942018-01-10 08:36:10 -08004579 parser->m_declAttributeType = atypeIDREF;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004580 goto checkAttListDeclHandler;
4581 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
Elliott Hughes72472942018-01-10 08:36:10 -08004582 parser->m_declAttributeType = atypeIDREFS;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004583 goto checkAttListDeclHandler;
4584 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
Elliott Hughes72472942018-01-10 08:36:10 -08004585 parser->m_declAttributeType = atypeENTITY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004586 goto checkAttListDeclHandler;
4587 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
Elliott Hughes72472942018-01-10 08:36:10 -08004588 parser->m_declAttributeType = atypeENTITIES;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004589 goto checkAttListDeclHandler;
4590 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
Elliott Hughes72472942018-01-10 08:36:10 -08004591 parser->m_declAttributeType = atypeNMTOKEN;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004592 goto checkAttListDeclHandler;
4593 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
Elliott Hughes72472942018-01-10 08:36:10 -08004594 parser->m_declAttributeType = atypeNMTOKENS;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004595 checkAttListDeclHandler:
Elliott Hughes72472942018-01-10 08:36:10 -08004596 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004597 handleDefault = XML_FALSE;
4598 break;
4599 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4600 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
Elliott Hughes72472942018-01-10 08:36:10 -08004601 if (dtd->keepProcessing && parser->m_attlistDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004602 const XML_Char *prefix;
Elliott Hughes72472942018-01-10 08:36:10 -08004603 if (parser->m_declAttributeType) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004604 prefix = enumValueSep;
4605 }
4606 else {
4607 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
4608 ? notationPrefix
4609 : enumValueStart);
4610 }
Elliott Hughes72472942018-01-10 08:36:10 -08004611 if (!poolAppendString(&parser->m_tempPool, prefix))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004612 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004613 if (!poolAppend(&parser->m_tempPool, enc, s, next))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004614 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004615 parser->m_declAttributeType = parser->m_tempPool.start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004616 handleDefault = XML_FALSE;
4617 }
4618 break;
4619 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4620 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4621 if (dtd->keepProcessing) {
Elliott Hughes72472942018-01-10 08:36:10 -08004622 if (!defineAttribute(parser->m_declElementType, parser->m_declAttributeId,
4623 parser->m_declAttributeIsCdata, parser->m_declAttributeIsId,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004624 0, parser))
4625 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004626 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
4627 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
4628 || (*parser->m_declAttributeType == XML_T(ASCII_N)
4629 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004630 /* Enumerated or Notation type */
Elliott Hughes72472942018-01-10 08:36:10 -08004631 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
4632 || !poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004633 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004634 parser->m_declAttributeType = parser->m_tempPool.start;
4635 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004636 }
4637 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004638 parser->m_attlistDeclHandler(parser->m_handlerArg, parser->m_declElementType->name,
4639 parser->m_declAttributeId->name, parser->m_declAttributeType,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004640 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
Elliott Hughes72472942018-01-10 08:36:10 -08004641 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004642 handleDefault = XML_FALSE;
4643 }
4644 }
4645 break;
4646 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4647 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4648 if (dtd->keepProcessing) {
4649 const XML_Char *attVal;
4650 enum XML_Error result =
Elliott Hughes72472942018-01-10 08:36:10 -08004651 storeAttributeValue(parser, enc, parser->m_declAttributeIsCdata,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004652 s + enc->minBytesPerChar,
4653 next - enc->minBytesPerChar,
4654 &dtd->pool);
4655 if (result)
4656 return result;
4657 attVal = poolStart(&dtd->pool);
4658 poolFinish(&dtd->pool);
4659 /* ID attributes aren't allowed to have a default */
Elliott Hughes72472942018-01-10 08:36:10 -08004660 if (!defineAttribute(parser->m_declElementType, parser->m_declAttributeId,
4661 parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004662 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004663 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
4664 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
4665 || (*parser->m_declAttributeType == XML_T(ASCII_N)
4666 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004667 /* Enumerated or Notation type */
Elliott Hughes72472942018-01-10 08:36:10 -08004668 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
4669 || !poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004670 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004671 parser->m_declAttributeType = parser->m_tempPool.start;
4672 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004673 }
4674 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004675 parser->m_attlistDeclHandler(parser->m_handlerArg, parser->m_declElementType->name,
4676 parser->m_declAttributeId->name, parser->m_declAttributeType,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004677 attVal,
4678 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
Elliott Hughes72472942018-01-10 08:36:10 -08004679 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004680 handleDefault = XML_FALSE;
4681 }
4682 }
4683 break;
4684 case XML_ROLE_ENTITY_VALUE:
4685 if (dtd->keepProcessing) {
4686 enum XML_Error result = storeEntityValue(parser, enc,
4687 s + enc->minBytesPerChar,
4688 next - enc->minBytesPerChar);
Elliott Hughes72472942018-01-10 08:36:10 -08004689 if (parser->m_declEntity) {
4690 parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
4691 parser->m_declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004692 poolFinish(&dtd->entityValuePool);
Elliott Hughes72472942018-01-10 08:36:10 -08004693 if (parser->m_entityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004694 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004695 parser->m_entityDeclHandler(parser->m_handlerArg,
4696 parser->m_declEntity->name,
4697 parser->m_declEntity->is_param,
4698 parser->m_declEntity->textPtr,
4699 parser->m_declEntity->textLen,
4700 parser->m_curBase, 0, 0, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004701 handleDefault = XML_FALSE;
4702 }
4703 }
4704 else
4705 poolDiscard(&dtd->entityValuePool);
4706 if (result != XML_ERROR_NONE)
4707 return result;
4708 }
4709 break;
4710 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4711#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004712 parser->m_useForeignDTD = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004713#endif /* XML_DTD */
4714 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004715 if (parser->m_startDoctypeDeclHandler) {
4716 parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004717 s + enc->minBytesPerChar,
4718 next - enc->minBytesPerChar);
Elliott Hughes72472942018-01-10 08:36:10 -08004719 if (parser->m_doctypeSysid == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004720 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004721 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004722 handleDefault = XML_FALSE;
4723 }
4724#ifdef XML_DTD
4725 else
Elliott Hughes72472942018-01-10 08:36:10 -08004726 /* use externalSubsetName to make parser->m_doctypeSysid non-NULL
4727 for the case where no parser->m_startDoctypeDeclHandler is set */
4728 parser->m_doctypeSysid = externalSubsetName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004729#endif /* XML_DTD */
4730 if (!dtd->standalone
4731#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004732 && !parser->m_paramEntityParsing
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004733#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004734 && parser->m_notStandaloneHandler
4735 && !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004736 return XML_ERROR_NOT_STANDALONE;
4737#ifndef XML_DTD
4738 break;
4739#else /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004740 if (!parser->m_declEntity) {
4741 parser->m_declEntity = (ENTITY *)lookup(parser,
Elliott Hughes35e432d2012-09-09 14:23:38 -07004742 &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004743 externalSubsetName,
4744 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004745 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004746 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004747 parser->m_declEntity->publicId = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004748 }
4749 /* fall through */
4750#endif /* XML_DTD */
4751 case XML_ROLE_ENTITY_SYSTEM_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004752 if (dtd->keepProcessing && parser->m_declEntity) {
4753 parser->m_declEntity->systemId = poolStoreString(&dtd->pool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004754 s + enc->minBytesPerChar,
4755 next - enc->minBytesPerChar);
Elliott Hughes72472942018-01-10 08:36:10 -08004756 if (!parser->m_declEntity->systemId)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004757 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004758 parser->m_declEntity->base = parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004759 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004760 /* Don't suppress the default handler if we fell through from
4761 * the XML_ROLE_DOCTYPE_SYSTEM_ID case.
4762 */
4763 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004764 handleDefault = XML_FALSE;
4765 }
4766 break;
4767 case XML_ROLE_ENTITY_COMPLETE:
Elliott Hughes72472942018-01-10 08:36:10 -08004768 if (dtd->keepProcessing && parser->m_declEntity && parser->m_entityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004769 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004770 parser->m_entityDeclHandler(parser->m_handlerArg,
4771 parser->m_declEntity->name,
4772 parser->m_declEntity->is_param,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004773 0,0,
Elliott Hughes72472942018-01-10 08:36:10 -08004774 parser->m_declEntity->base,
4775 parser->m_declEntity->systemId,
4776 parser->m_declEntity->publicId,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004777 0);
4778 handleDefault = XML_FALSE;
4779 }
4780 break;
4781 case XML_ROLE_ENTITY_NOTATION_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004782 if (dtd->keepProcessing && parser->m_declEntity) {
4783 parser->m_declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4784 if (!parser->m_declEntity->notation)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004785 return XML_ERROR_NO_MEMORY;
4786 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004787 if (parser->m_unparsedEntityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004788 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004789 parser->m_unparsedEntityDeclHandler(parser->m_handlerArg,
4790 parser->m_declEntity->name,
4791 parser->m_declEntity->base,
4792 parser->m_declEntity->systemId,
4793 parser->m_declEntity->publicId,
4794 parser->m_declEntity->notation);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004795 handleDefault = XML_FALSE;
4796 }
Elliott Hughes72472942018-01-10 08:36:10 -08004797 else if (parser->m_entityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004798 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004799 parser->m_entityDeclHandler(parser->m_handlerArg,
4800 parser->m_declEntity->name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004801 0,0,0,
Elliott Hughes72472942018-01-10 08:36:10 -08004802 parser->m_declEntity->base,
4803 parser->m_declEntity->systemId,
4804 parser->m_declEntity->publicId,
4805 parser->m_declEntity->notation);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004806 handleDefault = XML_FALSE;
4807 }
4808 }
4809 break;
4810 case XML_ROLE_GENERAL_ENTITY_NAME:
4811 {
4812 if (XmlPredefinedEntityName(enc, s, next)) {
Elliott Hughes72472942018-01-10 08:36:10 -08004813 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004814 break;
4815 }
4816 if (dtd->keepProcessing) {
4817 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4818 if (!name)
4819 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004820 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004821 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004822 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004823 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004824 if (parser->m_declEntity->name != name) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004825 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004826 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004827 }
4828 else {
4829 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004830 parser->m_declEntity->publicId = NULL;
4831 parser->m_declEntity->is_param = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004832 /* if we have a parent parser or are reading an internal parameter
4833 entity, then the entity declaration is not considered "internal"
4834 */
Elliott Hughes72472942018-01-10 08:36:10 -08004835 parser->m_declEntity->is_internal = !(parser->m_parentParser || parser->m_openInternalEntities);
4836 if (parser->m_entityDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004837 handleDefault = XML_FALSE;
4838 }
4839 }
4840 else {
4841 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004842 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004843 }
4844 }
4845 break;
4846 case XML_ROLE_PARAM_ENTITY_NAME:
4847#ifdef XML_DTD
4848 if (dtd->keepProcessing) {
4849 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4850 if (!name)
4851 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004852 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004853 name, sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004854 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004855 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004856 if (parser->m_declEntity->name != name) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004857 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004858 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004859 }
4860 else {
4861 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004862 parser->m_declEntity->publicId = NULL;
4863 parser->m_declEntity->is_param = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004864 /* if we have a parent parser or are reading an internal parameter
4865 entity, then the entity declaration is not considered "internal"
4866 */
Elliott Hughes72472942018-01-10 08:36:10 -08004867 parser->m_declEntity->is_internal = !(parser->m_parentParser || parser->m_openInternalEntities);
4868 if (parser->m_entityDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004869 handleDefault = XML_FALSE;
4870 }
4871 }
4872 else {
4873 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004874 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004875 }
4876#else /* not XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004877 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004878#endif /* XML_DTD */
4879 break;
4880 case XML_ROLE_NOTATION_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004881 parser->m_declNotationPublicId = NULL;
4882 parser->m_declNotationName = NULL;
4883 if (parser->m_notationDeclHandler) {
4884 parser->m_declNotationName = poolStoreString(&parser->m_tempPool, enc, s, next);
4885 if (!parser->m_declNotationName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004886 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004887 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004888 handleDefault = XML_FALSE;
4889 }
4890 break;
4891 case XML_ROLE_NOTATION_PUBLIC_ID:
4892 if (!XmlIsPublicId(enc, s, next, eventPP))
4893 return XML_ERROR_PUBLICID;
Elliott Hughes72472942018-01-10 08:36:10 -08004894 if (parser->m_declNotationName) { /* means m_notationDeclHandler != NULL */
4895 XML_Char *tem = poolStoreString(&parser->m_tempPool,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004896 enc,
4897 s + enc->minBytesPerChar,
4898 next - enc->minBytesPerChar);
4899 if (!tem)
4900 return XML_ERROR_NO_MEMORY;
4901 normalizePublicId(tem);
Elliott Hughes72472942018-01-10 08:36:10 -08004902 parser->m_declNotationPublicId = tem;
4903 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004904 handleDefault = XML_FALSE;
4905 }
4906 break;
4907 case XML_ROLE_NOTATION_SYSTEM_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004908 if (parser->m_declNotationName && parser->m_notationDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004909 const XML_Char *systemId
Elliott Hughes72472942018-01-10 08:36:10 -08004910 = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004911 s + enc->minBytesPerChar,
4912 next - enc->minBytesPerChar);
4913 if (!systemId)
4914 return XML_ERROR_NO_MEMORY;
4915 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004916 parser->m_notationDeclHandler(parser->m_handlerArg,
4917 parser->m_declNotationName,
4918 parser->m_curBase,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004919 systemId,
Elliott Hughes72472942018-01-10 08:36:10 -08004920 parser->m_declNotationPublicId);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004921 handleDefault = XML_FALSE;
4922 }
Elliott Hughes72472942018-01-10 08:36:10 -08004923 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004924 break;
4925 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004926 if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004927 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004928 parser->m_notationDeclHandler(parser->m_handlerArg,
4929 parser->m_declNotationName,
4930 parser->m_curBase,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004931 0,
Elliott Hughes72472942018-01-10 08:36:10 -08004932 parser->m_declNotationPublicId);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004933 handleDefault = XML_FALSE;
4934 }
Elliott Hughes72472942018-01-10 08:36:10 -08004935 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004936 break;
4937 case XML_ROLE_ERROR:
4938 switch (tok) {
4939 case XML_TOK_PARAM_ENTITY_REF:
4940 /* PE references in internal subset are
Elliott Hughes35e432d2012-09-09 14:23:38 -07004941 not allowed within declarations. */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004942 return XML_ERROR_PARAM_ENTITY_REF;
4943 case XML_TOK_XML_DECL:
4944 return XML_ERROR_MISPLACED_XML_PI;
4945 default:
4946 return XML_ERROR_SYNTAX;
4947 }
4948#ifdef XML_DTD
4949 case XML_ROLE_IGNORE_SECT:
4950 {
4951 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08004952 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004953 reportDefault(parser, enc, s, next);
4954 handleDefault = XML_FALSE;
4955 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4956 if (result != XML_ERROR_NONE)
4957 return result;
4958 else if (!next) {
Elliott Hughes72472942018-01-10 08:36:10 -08004959 parser->m_processor = ignoreSectionProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004960 return result;
4961 }
4962 }
4963 break;
4964#endif /* XML_DTD */
4965 case XML_ROLE_GROUP_OPEN:
Elliott Hughes72472942018-01-10 08:36:10 -08004966 if (parser->m_prologState.level >= parser->m_groupSize) {
4967 if (parser->m_groupSize) {
4968 char *temp = (char *)REALLOC(parser, parser->m_groupConnector, parser->m_groupSize *= 2);
4969 if (temp == NULL) {
4970 parser->m_groupSize /= 2;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004971 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004972 }
4973 parser->m_groupConnector = temp;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004974 if (dtd->scaffIndex) {
Elliott Hughes72472942018-01-10 08:36:10 -08004975 int *temp = (int *)REALLOC(parser, dtd->scaffIndex,
4976 parser->m_groupSize * sizeof(int));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004977 if (temp == NULL)
4978 return XML_ERROR_NO_MEMORY;
4979 dtd->scaffIndex = temp;
4980 }
4981 }
4982 else {
Elliott Hughes72472942018-01-10 08:36:10 -08004983 parser->m_groupConnector = (char *)MALLOC(parser, parser->m_groupSize = 32);
4984 if (!parser->m_groupConnector) {
4985 parser->m_groupSize = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004986 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004987 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004988 }
4989 }
Elliott Hughes72472942018-01-10 08:36:10 -08004990 parser->m_groupConnector[parser->m_prologState.level] = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004991 if (dtd->in_eldecl) {
4992 int myindex = nextScaffoldPart(parser);
4993 if (myindex < 0)
4994 return XML_ERROR_NO_MEMORY;
4995 dtd->scaffIndex[dtd->scaffLevel] = myindex;
4996 dtd->scaffLevel++;
4997 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
Elliott Hughes72472942018-01-10 08:36:10 -08004998 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004999 handleDefault = XML_FALSE;
5000 }
5001 break;
5002 case XML_ROLE_GROUP_SEQUENCE:
Elliott Hughes72472942018-01-10 08:36:10 -08005003 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005004 return XML_ERROR_SYNTAX;
Elliott Hughes72472942018-01-10 08:36:10 -08005005 parser->m_groupConnector[parser->m_prologState.level] = ASCII_COMMA;
5006 if (dtd->in_eldecl && parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005007 handleDefault = XML_FALSE;
5008 break;
5009 case XML_ROLE_GROUP_CHOICE:
Elliott Hughes72472942018-01-10 08:36:10 -08005010 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005011 return XML_ERROR_SYNTAX;
5012 if (dtd->in_eldecl
Elliott Hughes72472942018-01-10 08:36:10 -08005013 && !parser->m_groupConnector[parser->m_prologState.level]
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005014 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5015 != XML_CTYPE_MIXED)
5016 ) {
5017 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5018 = XML_CTYPE_CHOICE;
Elliott Hughes72472942018-01-10 08:36:10 -08005019 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005020 handleDefault = XML_FALSE;
5021 }
Elliott Hughes72472942018-01-10 08:36:10 -08005022 parser->m_groupConnector[parser->m_prologState.level] = ASCII_PIPE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005023 break;
5024 case XML_ROLE_PARAM_ENTITY_REF:
5025#ifdef XML_DTD
5026 case XML_ROLE_INNER_PARAM_ENTITY_REF:
5027 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005028 if (!parser->m_paramEntityParsing)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005029 dtd->keepProcessing = dtd->standalone;
5030 else {
5031 const XML_Char *name;
5032 ENTITY *entity;
5033 name = poolStoreString(&dtd->pool, enc,
5034 s + enc->minBytesPerChar,
5035 next - enc->minBytesPerChar);
5036 if (!name)
5037 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005038 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005039 poolDiscard(&dtd->pool);
5040 /* first, determine if a check for an existing declaration is needed;
5041 if yes, check that the entity exists, and that it is internal,
5042 otherwise call the skipped entity handler
5043 */
Elliott Hughes72472942018-01-10 08:36:10 -08005044 if (parser->m_prologState.documentEntity &&
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005045 (dtd->standalone
Elliott Hughes72472942018-01-10 08:36:10 -08005046 ? !parser->m_openInternalEntities
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005047 : !dtd->hasParamEntityRefs)) {
5048 if (!entity)
5049 return XML_ERROR_UNDEFINED_ENTITY;
Elliott Hughes72472942018-01-10 08:36:10 -08005050 else if (!entity->is_internal) {
5051 /* It's hard to exhaustively search the code to be sure,
5052 * but there doesn't seem to be a way of executing the
5053 * following line. There are two cases:
5054 *
5055 * If 'standalone' is false, the DTD must have no
5056 * parameter entities or we wouldn't have passed the outer
5057 * 'if' statement. That measn the only entity in the hash
5058 * table is the external subset name "#" which cannot be
5059 * given as a parameter entity name in XML syntax, so the
5060 * lookup must have returned NULL and we don't even reach
5061 * the test for an internal entity.
5062 *
5063 * If 'standalone' is true, it does not seem to be
5064 * possible to create entities taking this code path that
5065 * are not internal entities, so fail the test above.
5066 *
5067 * Because this analysis is very uncertain, the code is
5068 * being left in place and merely removed from the
5069 * coverage test statistics.
5070 */
5071 return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
5072 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005073 }
5074 else if (!entity) {
5075 dtd->keepProcessing = dtd->standalone;
5076 /* cannot report skipped entities in declarations */
Elliott Hughes72472942018-01-10 08:36:10 -08005077 if ((role == XML_ROLE_PARAM_ENTITY_REF) && parser->m_skippedEntityHandler) {
5078 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005079 handleDefault = XML_FALSE;
5080 }
5081 break;
5082 }
5083 if (entity->open)
5084 return XML_ERROR_RECURSIVE_ENTITY_REF;
5085 if (entity->textPtr) {
5086 enum XML_Error result;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005087 XML_Bool betweenDecl =
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005088 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
5089 result = processInternalEntity(parser, entity, betweenDecl);
5090 if (result != XML_ERROR_NONE)
5091 return result;
5092 handleDefault = XML_FALSE;
5093 break;
5094 }
Elliott Hughes72472942018-01-10 08:36:10 -08005095 if (parser->m_externalEntityRefHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005096 dtd->paramEntityRead = XML_FALSE;
5097 entity->open = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005098 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005099 0,
5100 entity->base,
5101 entity->systemId,
5102 entity->publicId)) {
5103 entity->open = XML_FALSE;
5104 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5105 }
5106 entity->open = XML_FALSE;
5107 handleDefault = XML_FALSE;
5108 if (!dtd->paramEntityRead) {
5109 dtd->keepProcessing = dtd->standalone;
5110 break;
5111 }
5112 }
5113 else {
5114 dtd->keepProcessing = dtd->standalone;
5115 break;
5116 }
5117 }
5118#endif /* XML_DTD */
5119 if (!dtd->standalone &&
Elliott Hughes72472942018-01-10 08:36:10 -08005120 parser->m_notStandaloneHandler &&
5121 !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005122 return XML_ERROR_NOT_STANDALONE;
5123 break;
5124
5125 /* Element declaration stuff */
5126
5127 case XML_ROLE_ELEMENT_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08005128 if (parser->m_elementDeclHandler) {
5129 parser->m_declElementType = getElementType(parser, enc, s, next);
5130 if (!parser->m_declElementType)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005131 return XML_ERROR_NO_MEMORY;
5132 dtd->scaffLevel = 0;
5133 dtd->scaffCount = 0;
5134 dtd->in_eldecl = XML_TRUE;
5135 handleDefault = XML_FALSE;
5136 }
5137 break;
5138
5139 case XML_ROLE_CONTENT_ANY:
5140 case XML_ROLE_CONTENT_EMPTY:
5141 if (dtd->in_eldecl) {
Elliott Hughes72472942018-01-10 08:36:10 -08005142 if (parser->m_elementDeclHandler) {
5143 XML_Content * content = (XML_Content *) MALLOC(parser, sizeof(XML_Content));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005144 if (!content)
5145 return XML_ERROR_NO_MEMORY;
5146 content->quant = XML_CQUANT_NONE;
5147 content->name = NULL;
5148 content->numchildren = 0;
5149 content->children = NULL;
5150 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
5151 XML_CTYPE_ANY :
5152 XML_CTYPE_EMPTY);
5153 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08005154 parser->m_elementDeclHandler(parser->m_handlerArg, parser->m_declElementType->name, content);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005155 handleDefault = XML_FALSE;
5156 }
5157 dtd->in_eldecl = XML_FALSE;
5158 }
5159 break;
5160
5161 case XML_ROLE_CONTENT_PCDATA:
5162 if (dtd->in_eldecl) {
5163 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5164 = XML_CTYPE_MIXED;
Elliott Hughes72472942018-01-10 08:36:10 -08005165 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005166 handleDefault = XML_FALSE;
5167 }
5168 break;
5169
5170 case XML_ROLE_CONTENT_ELEMENT:
5171 quant = XML_CQUANT_NONE;
5172 goto elementContent;
5173 case XML_ROLE_CONTENT_ELEMENT_OPT:
5174 quant = XML_CQUANT_OPT;
5175 goto elementContent;
5176 case XML_ROLE_CONTENT_ELEMENT_REP:
5177 quant = XML_CQUANT_REP;
5178 goto elementContent;
5179 case XML_ROLE_CONTENT_ELEMENT_PLUS:
5180 quant = XML_CQUANT_PLUS;
5181 elementContent:
5182 if (dtd->in_eldecl) {
5183 ELEMENT_TYPE *el;
5184 const XML_Char *name;
5185 int nameLen;
5186 const char *nxt = (quant == XML_CQUANT_NONE
5187 ? next
5188 : next - enc->minBytesPerChar);
5189 int myindex = nextScaffoldPart(parser);
5190 if (myindex < 0)
5191 return XML_ERROR_NO_MEMORY;
5192 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
5193 dtd->scaffold[myindex].quant = quant;
5194 el = getElementType(parser, enc, s, nxt);
5195 if (!el)
5196 return XML_ERROR_NO_MEMORY;
5197 name = el->name;
5198 dtd->scaffold[myindex].name = name;
5199 nameLen = 0;
5200 for (; name[nameLen++]; );
5201 dtd->contentStringLen += nameLen;
Elliott Hughes72472942018-01-10 08:36:10 -08005202 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005203 handleDefault = XML_FALSE;
5204 }
5205 break;
5206
5207 case XML_ROLE_GROUP_CLOSE:
5208 quant = XML_CQUANT_NONE;
5209 goto closeGroup;
5210 case XML_ROLE_GROUP_CLOSE_OPT:
5211 quant = XML_CQUANT_OPT;
5212 goto closeGroup;
5213 case XML_ROLE_GROUP_CLOSE_REP:
5214 quant = XML_CQUANT_REP;
5215 goto closeGroup;
5216 case XML_ROLE_GROUP_CLOSE_PLUS:
5217 quant = XML_CQUANT_PLUS;
5218 closeGroup:
5219 if (dtd->in_eldecl) {
Elliott Hughes72472942018-01-10 08:36:10 -08005220 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005221 handleDefault = XML_FALSE;
5222 dtd->scaffLevel--;
5223 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
5224 if (dtd->scaffLevel == 0) {
5225 if (!handleDefault) {
5226 XML_Content *model = build_model(parser);
5227 if (!model)
5228 return XML_ERROR_NO_MEMORY;
5229 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08005230 parser->m_elementDeclHandler(parser->m_handlerArg, parser->m_declElementType->name, model);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005231 }
5232 dtd->in_eldecl = XML_FALSE;
5233 dtd->contentStringLen = 0;
5234 }
5235 }
5236 break;
5237 /* End element declaration stuff */
5238
5239 case XML_ROLE_PI:
5240 if (!reportProcessingInstruction(parser, enc, s, next))
5241 return XML_ERROR_NO_MEMORY;
5242 handleDefault = XML_FALSE;
5243 break;
5244 case XML_ROLE_COMMENT:
5245 if (!reportComment(parser, enc, s, next))
5246 return XML_ERROR_NO_MEMORY;
5247 handleDefault = XML_FALSE;
5248 break;
5249 case XML_ROLE_NONE:
5250 switch (tok) {
5251 case XML_TOK_BOM:
5252 handleDefault = XML_FALSE;
5253 break;
5254 }
5255 break;
5256 case XML_ROLE_DOCTYPE_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005257 if (parser->m_startDoctypeDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005258 handleDefault = XML_FALSE;
5259 break;
5260 case XML_ROLE_ENTITY_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005261 if (dtd->keepProcessing && parser->m_entityDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005262 handleDefault = XML_FALSE;
5263 break;
5264 case XML_ROLE_NOTATION_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005265 if (parser->m_notationDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005266 handleDefault = XML_FALSE;
5267 break;
5268 case XML_ROLE_ATTLIST_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005269 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005270 handleDefault = XML_FALSE;
5271 break;
5272 case XML_ROLE_ELEMENT_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005273 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005274 handleDefault = XML_FALSE;
5275 break;
5276 } /* end of big switch */
5277
Elliott Hughes72472942018-01-10 08:36:10 -08005278 if (handleDefault && parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005279 reportDefault(parser, enc, s, next);
5280
Elliott Hughes72472942018-01-10 08:36:10 -08005281 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07005282 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005283 *nextPtr = next;
5284 return XML_ERROR_NONE;
5285 case XML_FINISHED:
5286 return XML_ERROR_ABORTED;
5287 default:
5288 s = next;
5289 tok = XmlPrologTok(enc, s, end, &next);
5290 }
5291 }
5292 /* not reached */
5293}
5294
5295static enum XML_Error PTRCALL
5296epilogProcessor(XML_Parser parser,
5297 const char *s,
5298 const char *end,
5299 const char **nextPtr)
5300{
Elliott Hughes72472942018-01-10 08:36:10 -08005301 parser->m_processor = epilogProcessor;
5302 parser->m_eventPtr = s;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005303 for (;;) {
5304 const char *next = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08005305 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5306 parser->m_eventEndPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005307 switch (tok) {
5308 /* report partial linebreak - it might be the last token */
5309 case -XML_TOK_PROLOG_S:
Elliott Hughes72472942018-01-10 08:36:10 -08005310 if (parser->m_defaultHandler) {
5311 reportDefault(parser, parser->m_encoding, s, next);
5312 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005313 return XML_ERROR_ABORTED;
5314 }
5315 *nextPtr = next;
5316 return XML_ERROR_NONE;
5317 case XML_TOK_NONE:
5318 *nextPtr = s;
5319 return XML_ERROR_NONE;
5320 case XML_TOK_PROLOG_S:
Elliott Hughes72472942018-01-10 08:36:10 -08005321 if (parser->m_defaultHandler)
5322 reportDefault(parser, parser->m_encoding, s, next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005323 break;
5324 case XML_TOK_PI:
Elliott Hughes72472942018-01-10 08:36:10 -08005325 if (!reportProcessingInstruction(parser, parser->m_encoding, s, next))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005326 return XML_ERROR_NO_MEMORY;
5327 break;
5328 case XML_TOK_COMMENT:
Elliott Hughes72472942018-01-10 08:36:10 -08005329 if (!reportComment(parser, parser->m_encoding, s, next))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005330 return XML_ERROR_NO_MEMORY;
5331 break;
5332 case XML_TOK_INVALID:
Elliott Hughes72472942018-01-10 08:36:10 -08005333 parser->m_eventPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005334 return XML_ERROR_INVALID_TOKEN;
5335 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08005336 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005337 *nextPtr = s;
5338 return XML_ERROR_NONE;
5339 }
5340 return XML_ERROR_UNCLOSED_TOKEN;
5341 case XML_TOK_PARTIAL_CHAR:
Elliott Hughes72472942018-01-10 08:36:10 -08005342 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005343 *nextPtr = s;
5344 return XML_ERROR_NONE;
5345 }
5346 return XML_ERROR_PARTIAL_CHAR;
5347 default:
5348 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
5349 }
Elliott Hughes72472942018-01-10 08:36:10 -08005350 parser->m_eventPtr = s = next;
5351 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07005352 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005353 *nextPtr = next;
5354 return XML_ERROR_NONE;
5355 case XML_FINISHED:
5356 return XML_ERROR_ABORTED;
5357 default: ;
5358 }
5359 }
5360}
5361
5362static enum XML_Error
5363processInternalEntity(XML_Parser parser, ENTITY *entity,
5364 XML_Bool betweenDecl)
5365{
5366 const char *textStart, *textEnd;
5367 const char *next;
5368 enum XML_Error result;
5369 OPEN_INTERNAL_ENTITY *openEntity;
5370
Elliott Hughes72472942018-01-10 08:36:10 -08005371 if (parser->m_freeInternalEntities) {
5372 openEntity = parser->m_freeInternalEntities;
5373 parser->m_freeInternalEntities = openEntity->next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005374 }
5375 else {
Elliott Hughes72472942018-01-10 08:36:10 -08005376 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005377 if (!openEntity)
5378 return XML_ERROR_NO_MEMORY;
5379 }
5380 entity->open = XML_TRUE;
5381 entity->processed = 0;
Elliott Hughes72472942018-01-10 08:36:10 -08005382 openEntity->next = parser->m_openInternalEntities;
5383 parser->m_openInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005384 openEntity->entity = entity;
Elliott Hughes72472942018-01-10 08:36:10 -08005385 openEntity->startTagLevel = parser->m_tagLevel;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005386 openEntity->betweenDecl = betweenDecl;
5387 openEntity->internalEventPtr = NULL;
5388 openEntity->internalEventEndPtr = NULL;
5389 textStart = (char *)entity->textPtr;
5390 textEnd = (char *)(entity->textPtr + entity->textLen);
Elliott Hughes72472942018-01-10 08:36:10 -08005391 /* Set a safe default value in case 'next' does not get set */
5392 next = textStart;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005393
5394#ifdef XML_DTD
5395 if (entity->is_param) {
Elliott Hughes72472942018-01-10 08:36:10 -08005396 int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5397 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005398 next, &next, XML_FALSE);
5399 }
Elliott Hughes35e432d2012-09-09 14:23:38 -07005400 else
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005401#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08005402 result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding, textStart,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005403 textEnd, &next, XML_FALSE);
5404
5405 if (result == XML_ERROR_NONE) {
Elliott Hughes72472942018-01-10 08:36:10 -08005406 if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005407 entity->processed = (int)(next - textStart);
Elliott Hughes72472942018-01-10 08:36:10 -08005408 parser->m_processor = internalEntityProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005409 }
5410 else {
5411 entity->open = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08005412 parser->m_openInternalEntities = openEntity->next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005413 /* put openEntity back in list of free instances */
Elliott Hughes72472942018-01-10 08:36:10 -08005414 openEntity->next = parser->m_freeInternalEntities;
5415 parser->m_freeInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005416 }
5417 }
5418 return result;
5419}
5420
5421static enum XML_Error PTRCALL
5422internalEntityProcessor(XML_Parser parser,
5423 const char *s,
5424 const char *end,
5425 const char **nextPtr)
5426{
5427 ENTITY *entity;
5428 const char *textStart, *textEnd;
5429 const char *next;
5430 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08005431 OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005432 if (!openEntity)
5433 return XML_ERROR_UNEXPECTED_STATE;
5434
5435 entity = openEntity->entity;
5436 textStart = ((char *)entity->textPtr) + entity->processed;
5437 textEnd = (char *)(entity->textPtr + entity->textLen);
Elliott Hughes72472942018-01-10 08:36:10 -08005438 /* Set a safe default value in case 'next' does not get set */
5439 next = textStart;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005440
5441#ifdef XML_DTD
5442 if (entity->is_param) {
Elliott Hughes72472942018-01-10 08:36:10 -08005443 int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5444 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005445 next, &next, XML_FALSE);
5446 }
5447 else
5448#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08005449 result = doContent(parser, openEntity->startTagLevel, parser->m_internalEncoding,
Elliott Hughes35e432d2012-09-09 14:23:38 -07005450 textStart, textEnd, &next, XML_FALSE);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005451
5452 if (result != XML_ERROR_NONE)
5453 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08005454 else if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005455 entity->processed = (int)(next - (char *)entity->textPtr);
5456 return result;
5457 }
5458 else {
5459 entity->open = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08005460 parser->m_openInternalEntities = openEntity->next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005461 /* put openEntity back in list of free instances */
Elliott Hughes72472942018-01-10 08:36:10 -08005462 openEntity->next = parser->m_freeInternalEntities;
5463 parser->m_freeInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005464 }
5465
5466#ifdef XML_DTD
5467 if (entity->is_param) {
5468 int tok;
Elliott Hughes72472942018-01-10 08:36:10 -08005469 parser->m_processor = prologProcessor;
5470 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5471 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
5472 (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005473 }
5474 else
5475#endif /* XML_DTD */
5476 {
Elliott Hughes72472942018-01-10 08:36:10 -08005477 parser->m_processor = contentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005478 /* see externalEntityContentProcessor vs contentProcessor */
Elliott Hughes72472942018-01-10 08:36:10 -08005479 return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, s, end,
5480 nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
Elliott Hughes35e432d2012-09-09 14:23:38 -07005481 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005482}
5483
5484static enum XML_Error PTRCALL
5485errorProcessor(XML_Parser parser,
Paul Duffinba34a0c2017-02-27 14:40:16 +00005486 const char *UNUSED_P(s),
5487 const char *UNUSED_P(end),
5488 const char **UNUSED_P(nextPtr))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005489{
Elliott Hughes72472942018-01-10 08:36:10 -08005490 return parser->m_errorCode;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005491}
5492
5493static enum XML_Error
5494storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5495 const char *ptr, const char *end,
5496 STRING_POOL *pool)
5497{
5498 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
5499 end, pool);
5500 if (result)
5501 return result;
5502 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
5503 poolChop(pool);
5504 if (!poolAppendChar(pool, XML_T('\0')))
5505 return XML_ERROR_NO_MEMORY;
5506 return XML_ERROR_NONE;
5507}
5508
5509static enum XML_Error
5510appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5511 const char *ptr, const char *end,
5512 STRING_POOL *pool)
5513{
Elliott Hughes72472942018-01-10 08:36:10 -08005514 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005515 for (;;) {
5516 const char *next;
5517 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
5518 switch (tok) {
5519 case XML_TOK_NONE:
5520 return XML_ERROR_NONE;
5521 case XML_TOK_INVALID:
Elliott Hughes72472942018-01-10 08:36:10 -08005522 if (enc == parser->m_encoding)
5523 parser->m_eventPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005524 return XML_ERROR_INVALID_TOKEN;
5525 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08005526 if (enc == parser->m_encoding)
5527 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005528 return XML_ERROR_INVALID_TOKEN;
5529 case XML_TOK_CHAR_REF:
5530 {
5531 XML_Char buf[XML_ENCODE_MAX];
5532 int i;
5533 int n = XmlCharRefNumber(enc, ptr);
5534 if (n < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08005535 if (enc == parser->m_encoding)
5536 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005537 return XML_ERROR_BAD_CHAR_REF;
5538 }
5539 if (!isCdata
5540 && n == 0x20 /* space */
5541 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5542 break;
5543 n = XmlEncode(n, (ICHAR *)buf);
Elliott Hughes72472942018-01-10 08:36:10 -08005544 /* The XmlEncode() functions can never return 0 here. That
5545 * error return happens if the code point passed in is either
5546 * negative or greater than or equal to 0x110000. The
5547 * XmlCharRefNumber() functions will all return a number
5548 * strictly less than 0x110000 or a negative value if an error
5549 * occurred. The negative value is intercepted above, so
5550 * XmlEncode() is never passed a value it might return an
5551 * error for.
5552 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005553 for (i = 0; i < n; i++) {
5554 if (!poolAppendChar(pool, buf[i]))
5555 return XML_ERROR_NO_MEMORY;
5556 }
5557 }
5558 break;
5559 case XML_TOK_DATA_CHARS:
5560 if (!poolAppend(pool, enc, ptr, next))
5561 return XML_ERROR_NO_MEMORY;
5562 break;
5563 case XML_TOK_TRAILING_CR:
5564 next = ptr + enc->minBytesPerChar;
5565 /* fall through */
5566 case XML_TOK_ATTRIBUTE_VALUE_S:
5567 case XML_TOK_DATA_NEWLINE:
5568 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5569 break;
5570 if (!poolAppendChar(pool, 0x20))
5571 return XML_ERROR_NO_MEMORY;
5572 break;
5573 case XML_TOK_ENTITY_REF:
5574 {
5575 const XML_Char *name;
5576 ENTITY *entity;
5577 char checkEntityDecl;
5578 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
5579 ptr + enc->minBytesPerChar,
5580 next - enc->minBytesPerChar);
5581 if (ch) {
5582 if (!poolAppendChar(pool, ch))
5583 return XML_ERROR_NO_MEMORY;
5584 break;
5585 }
Elliott Hughes72472942018-01-10 08:36:10 -08005586 name = poolStoreString(&parser->m_temp2Pool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005587 ptr + enc->minBytesPerChar,
5588 next - enc->minBytesPerChar);
5589 if (!name)
5590 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005591 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
Elliott Hughes72472942018-01-10 08:36:10 -08005592 poolDiscard(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005593 /* First, determine if a check for an existing declaration is needed;
5594 if yes, check that the entity exists, and that it is internal.
5595 */
5596 if (pool == &dtd->pool) /* are we called from prolog? */
5597 checkEntityDecl =
5598#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005599 parser->m_prologState.documentEntity &&
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005600#endif /* XML_DTD */
5601 (dtd->standalone
Elliott Hughes72472942018-01-10 08:36:10 -08005602 ? !parser->m_openInternalEntities
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005603 : !dtd->hasParamEntityRefs);
Elliott Hughes72472942018-01-10 08:36:10 -08005604 else /* if (pool == &parser->m_tempPool): we are called from content */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005605 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
5606 if (checkEntityDecl) {
5607 if (!entity)
5608 return XML_ERROR_UNDEFINED_ENTITY;
5609 else if (!entity->is_internal)
5610 return XML_ERROR_ENTITY_DECLARED_IN_PE;
5611 }
5612 else if (!entity) {
5613 /* Cannot report skipped entity here - see comments on
Elliott Hughes72472942018-01-10 08:36:10 -08005614 parser->m_skippedEntityHandler.
5615 if (parser->m_skippedEntityHandler)
5616 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005617 */
5618 /* Cannot call the default handler because this would be
5619 out of sync with the call to the startElementHandler.
Elliott Hughes72472942018-01-10 08:36:10 -08005620 if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005621 reportDefault(parser, enc, ptr, next);
5622 */
5623 break;
5624 }
5625 if (entity->open) {
Elliott Hughes72472942018-01-10 08:36:10 -08005626 if (enc == parser->m_encoding) {
5627 /* It does not appear that this line can be executed.
5628 *
5629 * The "if (entity->open)" check catches recursive entity
5630 * definitions. In order to be called with an open
5631 * entity, it must have gone through this code before and
5632 * been through the recursive call to
5633 * appendAttributeValue() some lines below. That call
5634 * sets the local encoding ("enc") to the parser's
5635 * internal encoding (internal_utf8 or internal_utf16),
5636 * which can never be the same as the principle encoding.
5637 * It doesn't appear there is another code path that gets
5638 * here with entity->open being TRUE.
5639 *
5640 * Since it is not certain that this logic is watertight,
5641 * we keep the line and merely exclude it from coverage
5642 * tests.
5643 */
5644 parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
5645 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005646 return XML_ERROR_RECURSIVE_ENTITY_REF;
5647 }
5648 if (entity->notation) {
Elliott Hughes72472942018-01-10 08:36:10 -08005649 if (enc == parser->m_encoding)
5650 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005651 return XML_ERROR_BINARY_ENTITY_REF;
5652 }
5653 if (!entity->textPtr) {
Elliott Hughes72472942018-01-10 08:36:10 -08005654 if (enc == parser->m_encoding)
5655 parser->m_eventPtr = ptr;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005656 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005657 }
5658 else {
5659 enum XML_Error result;
5660 const XML_Char *textEnd = entity->textPtr + entity->textLen;
5661 entity->open = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005662 result = appendAttributeValue(parser, parser->m_internalEncoding, isCdata,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005663 (char *)entity->textPtr,
5664 (char *)textEnd, pool);
5665 entity->open = XML_FALSE;
5666 if (result)
5667 return result;
5668 }
5669 }
5670 break;
5671 default:
Elliott Hughes72472942018-01-10 08:36:10 -08005672 /* The only token returned by XmlAttributeValueTok() that does
5673 * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
5674 * Getting that would require an entity name to contain an
5675 * incomplete XML character (e.g. \xE2\x82); however previous
5676 * tokenisers will have already recognised and rejected such
5677 * names before XmlAttributeValueTok() gets a look-in. This
5678 * default case should be retained as a safety net, but the code
5679 * excluded from coverage tests.
5680 *
5681 * LCOV_EXCL_START
5682 */
5683 if (enc == parser->m_encoding)
5684 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005685 return XML_ERROR_UNEXPECTED_STATE;
Elliott Hughes72472942018-01-10 08:36:10 -08005686 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005687 }
5688 ptr = next;
5689 }
5690 /* not reached */
5691}
5692
5693static enum XML_Error
5694storeEntityValue(XML_Parser parser,
5695 const ENCODING *enc,
5696 const char *entityTextPtr,
5697 const char *entityTextEnd)
5698{
Elliott Hughes72472942018-01-10 08:36:10 -08005699 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005700 STRING_POOL *pool = &(dtd->entityValuePool);
5701 enum XML_Error result = XML_ERROR_NONE;
5702#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005703 int oldInEntityValue = parser->m_prologState.inEntityValue;
5704 parser->m_prologState.inEntityValue = 1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005705#endif /* XML_DTD */
5706 /* never return Null for the value argument in EntityDeclHandler,
5707 since this would indicate an external entity; therefore we
5708 have to make sure that entityValuePool.start is not null */
5709 if (!pool->blocks) {
5710 if (!poolGrow(pool))
5711 return XML_ERROR_NO_MEMORY;
5712 }
5713
5714 for (;;) {
5715 const char *next;
5716 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5717 switch (tok) {
5718 case XML_TOK_PARAM_ENTITY_REF:
5719#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005720 if (parser->m_isParamEntity || enc != parser->m_encoding) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005721 const XML_Char *name;
5722 ENTITY *entity;
Elliott Hughes72472942018-01-10 08:36:10 -08005723 name = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005724 entityTextPtr + enc->minBytesPerChar,
5725 next - enc->minBytesPerChar);
5726 if (!name) {
5727 result = XML_ERROR_NO_MEMORY;
5728 goto endEntityValue;
5729 }
Elliott Hughes35e432d2012-09-09 14:23:38 -07005730 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
Elliott Hughes72472942018-01-10 08:36:10 -08005731 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005732 if (!entity) {
5733 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5734 /* cannot report skipped entity here - see comments on
Elliott Hughes72472942018-01-10 08:36:10 -08005735 parser->m_skippedEntityHandler
5736 if (parser->m_skippedEntityHandler)
5737 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005738 */
5739 dtd->keepProcessing = dtd->standalone;
5740 goto endEntityValue;
5741 }
5742 if (entity->open) {
Elliott Hughes72472942018-01-10 08:36:10 -08005743 if (enc == parser->m_encoding)
5744 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005745 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5746 goto endEntityValue;
5747 }
5748 if (entity->systemId) {
Elliott Hughes72472942018-01-10 08:36:10 -08005749 if (parser->m_externalEntityRefHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005750 dtd->paramEntityRead = XML_FALSE;
5751 entity->open = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005752 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005753 0,
5754 entity->base,
5755 entity->systemId,
5756 entity->publicId)) {
5757 entity->open = XML_FALSE;
5758 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5759 goto endEntityValue;
5760 }
5761 entity->open = XML_FALSE;
5762 if (!dtd->paramEntityRead)
5763 dtd->keepProcessing = dtd->standalone;
5764 }
5765 else
5766 dtd->keepProcessing = dtd->standalone;
5767 }
5768 else {
5769 entity->open = XML_TRUE;
5770 result = storeEntityValue(parser,
Elliott Hughes72472942018-01-10 08:36:10 -08005771 parser->m_internalEncoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005772 (char *)entity->textPtr,
5773 (char *)(entity->textPtr
5774 + entity->textLen));
5775 entity->open = XML_FALSE;
5776 if (result)
5777 goto endEntityValue;
5778 }
5779 break;
5780 }
5781#endif /* XML_DTD */
5782 /* In the internal subset, PE references are not legal
5783 within markup declarations, e.g entity values in this case. */
Elliott Hughes72472942018-01-10 08:36:10 -08005784 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005785 result = XML_ERROR_PARAM_ENTITY_REF;
5786 goto endEntityValue;
5787 case XML_TOK_NONE:
5788 result = XML_ERROR_NONE;
5789 goto endEntityValue;
5790 case XML_TOK_ENTITY_REF:
5791 case XML_TOK_DATA_CHARS:
5792 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5793 result = XML_ERROR_NO_MEMORY;
5794 goto endEntityValue;
5795 }
5796 break;
5797 case XML_TOK_TRAILING_CR:
5798 next = entityTextPtr + enc->minBytesPerChar;
5799 /* fall through */
5800 case XML_TOK_DATA_NEWLINE:
5801 if (pool->end == pool->ptr && !poolGrow(pool)) {
5802 result = XML_ERROR_NO_MEMORY;
5803 goto endEntityValue;
5804 }
5805 *(pool->ptr)++ = 0xA;
5806 break;
5807 case XML_TOK_CHAR_REF:
5808 {
5809 XML_Char buf[XML_ENCODE_MAX];
5810 int i;
5811 int n = XmlCharRefNumber(enc, entityTextPtr);
5812 if (n < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08005813 if (enc == parser->m_encoding)
5814 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005815 result = XML_ERROR_BAD_CHAR_REF;
5816 goto endEntityValue;
5817 }
5818 n = XmlEncode(n, (ICHAR *)buf);
Elliott Hughes72472942018-01-10 08:36:10 -08005819 /* The XmlEncode() functions can never return 0 here. That
5820 * error return happens if the code point passed in is either
5821 * negative or greater than or equal to 0x110000. The
5822 * XmlCharRefNumber() functions will all return a number
5823 * strictly less than 0x110000 or a negative value if an error
5824 * occurred. The negative value is intercepted above, so
5825 * XmlEncode() is never passed a value it might return an
5826 * error for.
5827 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005828 for (i = 0; i < n; i++) {
5829 if (pool->end == pool->ptr && !poolGrow(pool)) {
5830 result = XML_ERROR_NO_MEMORY;
5831 goto endEntityValue;
5832 }
5833 *(pool->ptr)++ = buf[i];
5834 }
5835 }
5836 break;
5837 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08005838 if (enc == parser->m_encoding)
5839 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005840 result = XML_ERROR_INVALID_TOKEN;
5841 goto endEntityValue;
5842 case XML_TOK_INVALID:
Elliott Hughes72472942018-01-10 08:36:10 -08005843 if (enc == parser->m_encoding)
5844 parser->m_eventPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005845 result = XML_ERROR_INVALID_TOKEN;
5846 goto endEntityValue;
5847 default:
Elliott Hughes72472942018-01-10 08:36:10 -08005848 /* This default case should be unnecessary -- all the tokens
5849 * that XmlEntityValueTok() can return have their own explicit
5850 * cases -- but should be retained for safety. We do however
5851 * exclude it from the coverage statistics.
5852 *
5853 * LCOV_EXCL_START
5854 */
5855 if (enc == parser->m_encoding)
5856 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005857 result = XML_ERROR_UNEXPECTED_STATE;
5858 goto endEntityValue;
Elliott Hughes72472942018-01-10 08:36:10 -08005859 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005860 }
5861 entityTextPtr = next;
5862 }
5863endEntityValue:
5864#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005865 parser->m_prologState.inEntityValue = oldInEntityValue;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005866#endif /* XML_DTD */
5867 return result;
5868}
5869
5870static void FASTCALL
5871normalizeLines(XML_Char *s)
5872{
5873 XML_Char *p;
5874 for (;; s++) {
5875 if (*s == XML_T('\0'))
5876 return;
5877 if (*s == 0xD)
5878 break;
5879 }
5880 p = s;
5881 do {
5882 if (*s == 0xD) {
5883 *p++ = 0xA;
5884 if (*++s == 0xA)
5885 s++;
5886 }
5887 else
5888 *p++ = *s++;
5889 } while (*s);
5890 *p = XML_T('\0');
5891}
5892
5893static int
5894reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5895 const char *start, const char *end)
5896{
5897 const XML_Char *target;
5898 XML_Char *data;
5899 const char *tem;
Elliott Hughes72472942018-01-10 08:36:10 -08005900 if (!parser->m_processingInstructionHandler) {
5901 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005902 reportDefault(parser, enc, start, end);
5903 return 1;
5904 }
5905 start += enc->minBytesPerChar * 2;
5906 tem = start + XmlNameLength(enc, start);
Elliott Hughes72472942018-01-10 08:36:10 -08005907 target = poolStoreString(&parser->m_tempPool, enc, start, tem);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005908 if (!target)
5909 return 0;
Elliott Hughes72472942018-01-10 08:36:10 -08005910 poolFinish(&parser->m_tempPool);
5911 data = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005912 XmlSkipS(enc, tem),
5913 end - enc->minBytesPerChar*2);
5914 if (!data)
5915 return 0;
5916 normalizeLines(data);
Elliott Hughes72472942018-01-10 08:36:10 -08005917 parser->m_processingInstructionHandler(parser->m_handlerArg, target, data);
5918 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005919 return 1;
5920}
5921
5922static int
5923reportComment(XML_Parser parser, const ENCODING *enc,
5924 const char *start, const char *end)
5925{
5926 XML_Char *data;
Elliott Hughes72472942018-01-10 08:36:10 -08005927 if (!parser->m_commentHandler) {
5928 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005929 reportDefault(parser, enc, start, end);
5930 return 1;
5931 }
Elliott Hughes72472942018-01-10 08:36:10 -08005932 data = poolStoreString(&parser->m_tempPool,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005933 enc,
5934 start + enc->minBytesPerChar * 4,
5935 end - enc->minBytesPerChar * 3);
5936 if (!data)
5937 return 0;
5938 normalizeLines(data);
Elliott Hughes72472942018-01-10 08:36:10 -08005939 parser->m_commentHandler(parser->m_handlerArg, data);
5940 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005941 return 1;
5942}
5943
5944static void
5945reportDefault(XML_Parser parser, const ENCODING *enc,
5946 const char *s, const char *end)
5947{
5948 if (MUST_CONVERT(enc, s)) {
Paul Duffin4bf8f122016-05-13 12:35:25 +01005949 enum XML_Convert_Result convert_res;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005950 const char **eventPP;
5951 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08005952 if (enc == parser->m_encoding) {
5953 eventPP = &parser->m_eventPtr;
5954 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005955 }
5956 else {
Elliott Hughes72472942018-01-10 08:36:10 -08005957 /* To get here, two things must be true; the parser must be
5958 * using a character encoding that is not the same as the
5959 * encoding passed in, and the encoding passed in must need
5960 * conversion to the internal format (UTF-8 unless XML_UNICODE
5961 * is defined). The only occasions on which the encoding passed
5962 * in is not the same as the parser's encoding are when it is
5963 * the internal encoding (e.g. a previously defined parameter
5964 * entity, already converted to internal format). This by
5965 * definition doesn't need conversion, so the whole branch never
5966 * gets executed.
5967 *
5968 * For safety's sake we don't delete these lines and merely
5969 * exclude them from coverage statistics.
5970 *
5971 * LCOV_EXCL_START
5972 */
5973 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
5974 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
5975 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005976 }
5977 do {
Elliott Hughes72472942018-01-10 08:36:10 -08005978 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
5979 convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005980 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08005981 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 -08005982 *eventPP = s;
Paul Duffin4bf8f122016-05-13 12:35:25 +01005983 } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005984 }
5985 else
Elliott Hughes72472942018-01-10 08:36:10 -08005986 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 -08005987}
5988
5989
5990static int
5991defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
5992 XML_Bool isId, const XML_Char *value, XML_Parser parser)
5993{
5994 DEFAULT_ATTRIBUTE *att;
5995 if (value || isId) {
5996 /* The handling of default attributes gets messed up if we have
5997 a default which duplicates a non-default. */
5998 int i;
5999 for (i = 0; i < type->nDefaultAtts; i++)
6000 if (attId == type->defaultAtts[i].id)
6001 return 1;
6002 if (isId && !type->idAtt && !attId->xmlns)
6003 type->idAtt = attId;
6004 }
6005 if (type->nDefaultAtts == type->allocDefaultAtts) {
6006 if (type->allocDefaultAtts == 0) {
6007 type->allocDefaultAtts = 8;
Elliott Hughes72472942018-01-10 08:36:10 -08006008 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(parser, type->allocDefaultAtts
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006009 * sizeof(DEFAULT_ATTRIBUTE));
Elliott Hughes72472942018-01-10 08:36:10 -08006010 if (!type->defaultAtts) {
6011 type->allocDefaultAtts = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006012 return 0;
Elliott Hughes72472942018-01-10 08:36:10 -08006013 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006014 }
6015 else {
6016 DEFAULT_ATTRIBUTE *temp;
6017 int count = type->allocDefaultAtts * 2;
6018 temp = (DEFAULT_ATTRIBUTE *)
Elliott Hughes72472942018-01-10 08:36:10 -08006019 REALLOC(parser, type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006020 if (temp == NULL)
6021 return 0;
6022 type->allocDefaultAtts = count;
6023 type->defaultAtts = temp;
6024 }
6025 }
6026 att = type->defaultAtts + type->nDefaultAtts;
6027 att->id = attId;
6028 att->value = value;
6029 att->isCdata = isCdata;
6030 if (!isCdata)
6031 attId->maybeTokenized = XML_TRUE;
6032 type->nDefaultAtts += 1;
6033 return 1;
6034}
6035
6036static int
6037setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
6038{
Elliott Hughes72472942018-01-10 08:36:10 -08006039 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006040 const XML_Char *name;
6041 for (name = elementType->name; *name; name++) {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006042 if (*name == XML_T(ASCII_COLON)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006043 PREFIX *prefix;
6044 const XML_Char *s;
6045 for (s = elementType->name; s != name; s++) {
6046 if (!poolAppendChar(&dtd->pool, *s))
6047 return 0;
6048 }
6049 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6050 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006051 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006052 sizeof(PREFIX));
6053 if (!prefix)
6054 return 0;
6055 if (prefix->name == poolStart(&dtd->pool))
6056 poolFinish(&dtd->pool);
6057 else
6058 poolDiscard(&dtd->pool);
6059 elementType->prefix = prefix;
6060
6061 }
6062 }
6063 return 1;
6064}
6065
6066static ATTRIBUTE_ID *
6067getAttributeId(XML_Parser parser, const ENCODING *enc,
6068 const char *start, const char *end)
6069{
Elliott Hughes72472942018-01-10 08:36:10 -08006070 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006071 ATTRIBUTE_ID *id;
6072 const XML_Char *name;
6073 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6074 return NULL;
6075 name = poolStoreString(&dtd->pool, enc, start, end);
6076 if (!name)
6077 return NULL;
6078 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
6079 ++name;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006080 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006081 if (!id)
6082 return NULL;
6083 if (id->name != name)
6084 poolDiscard(&dtd->pool);
6085 else {
6086 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08006087 if (!parser->m_ns)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006088 ;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006089 else if (name[0] == XML_T(ASCII_x)
6090 && name[1] == XML_T(ASCII_m)
6091 && name[2] == XML_T(ASCII_l)
6092 && name[3] == XML_T(ASCII_n)
6093 && name[4] == XML_T(ASCII_s)
6094 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006095 if (name[5] == XML_T('\0'))
6096 id->prefix = &dtd->defaultPrefix;
6097 else
Elliott Hughes35e432d2012-09-09 14:23:38 -07006098 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006099 id->xmlns = XML_TRUE;
6100 }
6101 else {
6102 int i;
6103 for (i = 0; name[i]; i++) {
6104 /* attributes without prefix are *not* in the default namespace */
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006105 if (name[i] == XML_T(ASCII_COLON)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006106 int j;
6107 for (j = 0; j < i; j++) {
6108 if (!poolAppendChar(&dtd->pool, name[j]))
6109 return NULL;
6110 }
6111 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6112 return NULL;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006113 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006114 sizeof(PREFIX));
Paul Duffinc05e0322016-05-04 10:42:31 +01006115 if (!id->prefix)
6116 return NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006117 if (id->prefix->name == poolStart(&dtd->pool))
6118 poolFinish(&dtd->pool);
6119 else
6120 poolDiscard(&dtd->pool);
6121 break;
6122 }
6123 }
6124 }
6125 }
6126 return id;
6127}
6128
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006129#define CONTEXT_SEP XML_T(ASCII_FF)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006130
6131static const XML_Char *
6132getContext(XML_Parser parser)
6133{
Elliott Hughes72472942018-01-10 08:36:10 -08006134 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006135 HASH_TABLE_ITER iter;
6136 XML_Bool needSep = XML_FALSE;
6137
6138 if (dtd->defaultPrefix.binding) {
6139 int i;
6140 int len;
Elliott Hughes72472942018-01-10 08:36:10 -08006141 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006142 return NULL;
6143 len = dtd->defaultPrefix.binding->uriLen;
Elliott Hughes72472942018-01-10 08:36:10 -08006144 if (parser->m_namespaceSeparator)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006145 len--;
Elliott Hughes72472942018-01-10 08:36:10 -08006146 for (i = 0; i < len; i++) {
6147 if (!poolAppendChar(&parser->m_tempPool, dtd->defaultPrefix.binding->uri[i])) {
6148 /* Because of memory caching, I don't believe this line can be
6149 * executed.
6150 *
6151 * This is part of a loop copying the default prefix binding
6152 * URI into the parser's temporary string pool. Previously,
6153 * that URI was copied into the same string pool, with a
6154 * terminating NUL character, as part of setContext(). When
6155 * the pool was cleared, that leaves a block definitely big
6156 * enough to hold the URI on the free block list of the pool.
6157 * The URI copy in getContext() therefore cannot run out of
6158 * memory.
6159 *
6160 * If the pool is used between the setContext() and
6161 * getContext() calls, the worst it can do is leave a bigger
6162 * block on the front of the free list. Given that this is
6163 * all somewhat inobvious and program logic can be changed, we
6164 * don't delete the line but we do exclude it from the test
6165 * coverage statistics.
6166 */
6167 return NULL; /* LCOV_EXCL_LINE */
6168 }
6169 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006170 needSep = XML_TRUE;
6171 }
6172
6173 hashTableIterInit(&iter, &(dtd->prefixes));
6174 for (;;) {
6175 int i;
6176 int len;
6177 const XML_Char *s;
6178 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
6179 if (!prefix)
6180 break;
Elliott Hughes72472942018-01-10 08:36:10 -08006181 if (!prefix->binding) {
6182 /* This test appears to be (justifiable) paranoia. There does
6183 * not seem to be a way of injecting a prefix without a binding
6184 * that doesn't get errored long before this function is called.
6185 * The test should remain for safety's sake, so we instead
6186 * exclude the following line from the coverage statistics.
6187 */
6188 continue; /* LCOV_EXCL_LINE */
6189 }
6190 if (needSep && !poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006191 return NULL;
6192 for (s = prefix->name; *s; s++)
Elliott Hughes72472942018-01-10 08:36:10 -08006193 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006194 return NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08006195 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006196 return NULL;
6197 len = prefix->binding->uriLen;
Elliott Hughes72472942018-01-10 08:36:10 -08006198 if (parser->m_namespaceSeparator)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006199 len--;
6200 for (i = 0; i < len; i++)
Elliott Hughes72472942018-01-10 08:36:10 -08006201 if (!poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i]))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006202 return NULL;
6203 needSep = XML_TRUE;
6204 }
6205
6206
6207 hashTableIterInit(&iter, &(dtd->generalEntities));
6208 for (;;) {
6209 const XML_Char *s;
6210 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
6211 if (!e)
6212 break;
6213 if (!e->open)
6214 continue;
Elliott Hughes72472942018-01-10 08:36:10 -08006215 if (needSep && !poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006216 return NULL;
6217 for (s = e->name; *s; s++)
Elliott Hughes72472942018-01-10 08:36:10 -08006218 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006219 return 0;
6220 needSep = XML_TRUE;
6221 }
6222
Elliott Hughes72472942018-01-10 08:36:10 -08006223 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006224 return NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08006225 return parser->m_tempPool.start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006226}
6227
6228static XML_Bool
6229setContext(XML_Parser parser, const XML_Char *context)
6230{
Elliott Hughes72472942018-01-10 08:36:10 -08006231 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006232 const XML_Char *s = context;
6233
6234 while (*context != XML_T('\0')) {
6235 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
6236 ENTITY *e;
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 XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006239 e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&parser->m_tempPool), 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006240 if (e)
6241 e->open = XML_TRUE;
6242 if (*s != XML_T('\0'))
6243 s++;
6244 context = s;
Elliott Hughes72472942018-01-10 08:36:10 -08006245 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006246 }
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006247 else if (*s == XML_T(ASCII_EQUALS)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006248 PREFIX *prefix;
Elliott Hughes72472942018-01-10 08:36:10 -08006249 if (poolLength(&parser->m_tempPool) == 0)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006250 prefix = &dtd->defaultPrefix;
6251 else {
Elliott Hughes72472942018-01-10 08:36:10 -08006252 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006253 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006254 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&parser->m_tempPool),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006255 sizeof(PREFIX));
6256 if (!prefix)
6257 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006258 if (prefix->name == poolStart(&parser->m_tempPool)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006259 prefix->name = poolCopyString(&dtd->pool, prefix->name);
6260 if (!prefix->name)
6261 return XML_FALSE;
6262 }
Elliott Hughes72472942018-01-10 08:36:10 -08006263 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006264 }
6265 for (context = s + 1;
6266 *context != CONTEXT_SEP && *context != XML_T('\0');
6267 context++)
Elliott Hughes72472942018-01-10 08:36:10 -08006268 if (!poolAppendChar(&parser->m_tempPool, *context))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006269 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006270 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006271 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006272 if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool),
6273 &parser->m_inheritedBindings) != XML_ERROR_NONE)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006274 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006275 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006276 if (*context != XML_T('\0'))
6277 ++context;
6278 s = context;
6279 }
6280 else {
Elliott Hughes72472942018-01-10 08:36:10 -08006281 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006282 return XML_FALSE;
6283 s++;
6284 }
6285 }
6286 return XML_TRUE;
6287}
6288
6289static void FASTCALL
6290normalizePublicId(XML_Char *publicId)
6291{
6292 XML_Char *p = publicId;
6293 XML_Char *s;
6294 for (s = publicId; *s; s++) {
6295 switch (*s) {
6296 case 0x20:
6297 case 0xD:
6298 case 0xA:
6299 if (p != publicId && p[-1] != 0x20)
6300 *p++ = 0x20;
6301 break;
6302 default:
6303 *p++ = *s;
6304 }
6305 }
6306 if (p != publicId && p[-1] == 0x20)
6307 --p;
6308 *p = XML_T('\0');
6309}
6310
6311static DTD *
6312dtdCreate(const XML_Memory_Handling_Suite *ms)
6313{
6314 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
6315 if (p == NULL)
6316 return p;
6317 poolInit(&(p->pool), ms);
6318 poolInit(&(p->entityValuePool), ms);
6319 hashTableInit(&(p->generalEntities), ms);
6320 hashTableInit(&(p->elementTypes), ms);
6321 hashTableInit(&(p->attributeIds), ms);
6322 hashTableInit(&(p->prefixes), ms);
6323#ifdef XML_DTD
6324 p->paramEntityRead = XML_FALSE;
6325 hashTableInit(&(p->paramEntities), ms);
6326#endif /* XML_DTD */
6327 p->defaultPrefix.name = NULL;
6328 p->defaultPrefix.binding = NULL;
6329
6330 p->in_eldecl = XML_FALSE;
6331 p->scaffIndex = NULL;
6332 p->scaffold = NULL;
6333 p->scaffLevel = 0;
6334 p->scaffSize = 0;
6335 p->scaffCount = 0;
6336 p->contentStringLen = 0;
6337
6338 p->keepProcessing = XML_TRUE;
6339 p->hasParamEntityRefs = XML_FALSE;
6340 p->standalone = XML_FALSE;
6341 return p;
6342}
6343
6344static void
6345dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
6346{
6347 HASH_TABLE_ITER iter;
6348 hashTableIterInit(&iter, &(p->elementTypes));
6349 for (;;) {
6350 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6351 if (!e)
6352 break;
6353 if (e->allocDefaultAtts != 0)
6354 ms->free_fcn(e->defaultAtts);
6355 }
6356 hashTableClear(&(p->generalEntities));
6357#ifdef XML_DTD
6358 p->paramEntityRead = XML_FALSE;
6359 hashTableClear(&(p->paramEntities));
6360#endif /* XML_DTD */
6361 hashTableClear(&(p->elementTypes));
6362 hashTableClear(&(p->attributeIds));
6363 hashTableClear(&(p->prefixes));
6364 poolClear(&(p->pool));
6365 poolClear(&(p->entityValuePool));
6366 p->defaultPrefix.name = NULL;
6367 p->defaultPrefix.binding = NULL;
6368
6369 p->in_eldecl = XML_FALSE;
6370
6371 ms->free_fcn(p->scaffIndex);
6372 p->scaffIndex = NULL;
6373 ms->free_fcn(p->scaffold);
6374 p->scaffold = NULL;
6375
6376 p->scaffLevel = 0;
6377 p->scaffSize = 0;
6378 p->scaffCount = 0;
6379 p->contentStringLen = 0;
6380
6381 p->keepProcessing = XML_TRUE;
6382 p->hasParamEntityRefs = XML_FALSE;
6383 p->standalone = XML_FALSE;
6384}
6385
6386static void
6387dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
6388{
6389 HASH_TABLE_ITER iter;
6390 hashTableIterInit(&iter, &(p->elementTypes));
6391 for (;;) {
6392 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6393 if (!e)
6394 break;
6395 if (e->allocDefaultAtts != 0)
6396 ms->free_fcn(e->defaultAtts);
6397 }
6398 hashTableDestroy(&(p->generalEntities));
6399#ifdef XML_DTD
6400 hashTableDestroy(&(p->paramEntities));
6401#endif /* XML_DTD */
6402 hashTableDestroy(&(p->elementTypes));
6403 hashTableDestroy(&(p->attributeIds));
6404 hashTableDestroy(&(p->prefixes));
6405 poolDestroy(&(p->pool));
6406 poolDestroy(&(p->entityValuePool));
6407 if (isDocEntity) {
6408 ms->free_fcn(p->scaffIndex);
6409 ms->free_fcn(p->scaffold);
6410 }
6411 ms->free_fcn(p);
6412}
6413
6414/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
6415 The new DTD has already been initialized.
6416*/
6417static int
Elliott Hughes35e432d2012-09-09 14:23:38 -07006418dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006419{
6420 HASH_TABLE_ITER iter;
6421
6422 /* Copy the prefix table. */
6423
6424 hashTableIterInit(&iter, &(oldDtd->prefixes));
6425 for (;;) {
6426 const XML_Char *name;
6427 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
6428 if (!oldP)
6429 break;
6430 name = poolCopyString(&(newDtd->pool), oldP->name);
6431 if (!name)
6432 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006433 if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006434 return 0;
6435 }
6436
6437 hashTableIterInit(&iter, &(oldDtd->attributeIds));
6438
6439 /* Copy the attribute id table. */
6440
6441 for (;;) {
6442 ATTRIBUTE_ID *newA;
6443 const XML_Char *name;
6444 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
6445
6446 if (!oldA)
6447 break;
6448 /* Remember to allocate the scratch byte before the name. */
6449 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
6450 return 0;
6451 name = poolCopyString(&(newDtd->pool), oldA->name);
6452 if (!name)
6453 return 0;
6454 ++name;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006455 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006456 sizeof(ATTRIBUTE_ID));
6457 if (!newA)
6458 return 0;
6459 newA->maybeTokenized = oldA->maybeTokenized;
6460 if (oldA->prefix) {
6461 newA->xmlns = oldA->xmlns;
6462 if (oldA->prefix == &oldDtd->defaultPrefix)
6463 newA->prefix = &newDtd->defaultPrefix;
6464 else
Elliott Hughes35e432d2012-09-09 14:23:38 -07006465 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006466 oldA->prefix->name, 0);
6467 }
6468 }
6469
6470 /* Copy the element type table. */
6471
6472 hashTableIterInit(&iter, &(oldDtd->elementTypes));
6473
6474 for (;;) {
6475 int i;
6476 ELEMENT_TYPE *newE;
6477 const XML_Char *name;
6478 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6479 if (!oldE)
6480 break;
6481 name = poolCopyString(&(newDtd->pool), oldE->name);
6482 if (!name)
6483 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006484 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006485 sizeof(ELEMENT_TYPE));
6486 if (!newE)
6487 return 0;
6488 if (oldE->nDefaultAtts) {
6489 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
6490 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6491 if (!newE->defaultAtts) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006492 return 0;
6493 }
6494 }
6495 if (oldE->idAtt)
6496 newE->idAtt = (ATTRIBUTE_ID *)
Elliott Hughes35e432d2012-09-09 14:23:38 -07006497 lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006498 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
6499 if (oldE->prefix)
Elliott Hughes35e432d2012-09-09 14:23:38 -07006500 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006501 oldE->prefix->name, 0);
6502 for (i = 0; i < newE->nDefaultAtts; i++) {
6503 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
Elliott Hughes35e432d2012-09-09 14:23:38 -07006504 lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006505 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
6506 if (oldE->defaultAtts[i].value) {
6507 newE->defaultAtts[i].value
6508 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
6509 if (!newE->defaultAtts[i].value)
6510 return 0;
6511 }
6512 else
6513 newE->defaultAtts[i].value = NULL;
6514 }
6515 }
6516
6517 /* Copy the entity tables. */
Elliott Hughes35e432d2012-09-09 14:23:38 -07006518 if (!copyEntityTable(oldParser,
6519 &(newDtd->generalEntities),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006520 &(newDtd->pool),
6521 &(oldDtd->generalEntities)))
6522 return 0;
6523
6524#ifdef XML_DTD
Elliott Hughes35e432d2012-09-09 14:23:38 -07006525 if (!copyEntityTable(oldParser,
6526 &(newDtd->paramEntities),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006527 &(newDtd->pool),
6528 &(oldDtd->paramEntities)))
6529 return 0;
6530 newDtd->paramEntityRead = oldDtd->paramEntityRead;
6531#endif /* XML_DTD */
6532
6533 newDtd->keepProcessing = oldDtd->keepProcessing;
6534 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
6535 newDtd->standalone = oldDtd->standalone;
6536
6537 /* Don't want deep copying for scaffolding */
6538 newDtd->in_eldecl = oldDtd->in_eldecl;
6539 newDtd->scaffold = oldDtd->scaffold;
6540 newDtd->contentStringLen = oldDtd->contentStringLen;
6541 newDtd->scaffSize = oldDtd->scaffSize;
6542 newDtd->scaffLevel = oldDtd->scaffLevel;
6543 newDtd->scaffIndex = oldDtd->scaffIndex;
6544
6545 return 1;
6546} /* End dtdCopy */
6547
6548static int
Elliott Hughes35e432d2012-09-09 14:23:38 -07006549copyEntityTable(XML_Parser oldParser,
6550 HASH_TABLE *newTable,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006551 STRING_POOL *newPool,
6552 const HASH_TABLE *oldTable)
6553{
6554 HASH_TABLE_ITER iter;
6555 const XML_Char *cachedOldBase = NULL;
6556 const XML_Char *cachedNewBase = NULL;
6557
6558 hashTableIterInit(&iter, oldTable);
6559
6560 for (;;) {
6561 ENTITY *newE;
6562 const XML_Char *name;
6563 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
6564 if (!oldE)
6565 break;
6566 name = poolCopyString(newPool, oldE->name);
6567 if (!name)
6568 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006569 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006570 if (!newE)
6571 return 0;
6572 if (oldE->systemId) {
6573 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
6574 if (!tem)
6575 return 0;
6576 newE->systemId = tem;
6577 if (oldE->base) {
6578 if (oldE->base == cachedOldBase)
6579 newE->base = cachedNewBase;
6580 else {
6581 cachedOldBase = oldE->base;
6582 tem = poolCopyString(newPool, cachedOldBase);
6583 if (!tem)
6584 return 0;
6585 cachedNewBase = newE->base = tem;
6586 }
6587 }
6588 if (oldE->publicId) {
6589 tem = poolCopyString(newPool, oldE->publicId);
6590 if (!tem)
6591 return 0;
6592 newE->publicId = tem;
6593 }
6594 }
6595 else {
6596 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
6597 oldE->textLen);
6598 if (!tem)
6599 return 0;
6600 newE->textPtr = tem;
6601 newE->textLen = oldE->textLen;
6602 }
6603 if (oldE->notation) {
6604 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
6605 if (!tem)
6606 return 0;
6607 newE->notation = tem;
6608 }
6609 newE->is_param = oldE->is_param;
6610 newE->is_internal = oldE->is_internal;
6611 }
6612 return 1;
6613}
6614
6615#define INIT_POWER 6
6616
6617static XML_Bool FASTCALL
6618keyeq(KEY s1, KEY s2)
6619{
6620 for (; *s1 == *s2; s1++, s2++)
6621 if (*s1 == 0)
6622 return XML_TRUE;
6623 return XML_FALSE;
6624}
6625
Elliott Hughes72472942018-01-10 08:36:10 -08006626static size_t
6627keylen(KEY s)
6628{
6629 size_t len = 0;
6630 for (; *s; s++, len++);
6631 return len;
6632}
6633
6634static void
6635copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key)
6636{
6637 key->k[0] = 0;
6638 key->k[1] = get_hash_secret_salt(parser);
6639}
6640
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006641static unsigned long FASTCALL
Elliott Hughes35e432d2012-09-09 14:23:38 -07006642hash(XML_Parser parser, KEY s)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006643{
Elliott Hughes72472942018-01-10 08:36:10 -08006644 struct siphash state;
6645 struct sipkey key;
6646 (void)sip_tobin;
6647 (void)sip24_valid;
6648 copy_salt_to_sipkey(parser, &key);
6649 sip24_init(&state, &key);
6650 sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
6651 return (unsigned long)sip24_final(&state);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006652}
6653
6654static NAMED *
Elliott Hughes35e432d2012-09-09 14:23:38 -07006655lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006656{
6657 size_t i;
6658 if (table->size == 0) {
6659 size_t tsize;
6660 if (!createSize)
6661 return NULL;
6662 table->power = INIT_POWER;
6663 /* table->size is a power of 2 */
6664 table->size = (size_t)1 << INIT_POWER;
6665 tsize = table->size * sizeof(NAMED *);
6666 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
6667 if (!table->v) {
6668 table->size = 0;
6669 return NULL;
6670 }
6671 memset(table->v, 0, tsize);
Elliott Hughes35e432d2012-09-09 14:23:38 -07006672 i = hash(parser, name) & ((unsigned long)table->size - 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006673 }
6674 else {
Elliott Hughes35e432d2012-09-09 14:23:38 -07006675 unsigned long h = hash(parser, name);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006676 unsigned long mask = (unsigned long)table->size - 1;
6677 unsigned char step = 0;
6678 i = h & mask;
6679 while (table->v[i]) {
6680 if (keyeq(name, table->v[i]->name))
6681 return table->v[i];
6682 if (!step)
6683 step = PROBE_STEP(h, mask, table->power);
6684 i < step ? (i += table->size - step) : (i -= step);
6685 }
6686 if (!createSize)
6687 return NULL;
6688
6689 /* check for overflow (table is half full) */
6690 if (table->used >> (table->power - 1)) {
6691 unsigned char newPower = table->power + 1;
6692 size_t newSize = (size_t)1 << newPower;
6693 unsigned long newMask = (unsigned long)newSize - 1;
6694 size_t tsize = newSize * sizeof(NAMED *);
6695 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
6696 if (!newV)
6697 return NULL;
6698 memset(newV, 0, tsize);
6699 for (i = 0; i < table->size; i++)
6700 if (table->v[i]) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07006701 unsigned long newHash = hash(parser, table->v[i]->name);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006702 size_t j = newHash & newMask;
6703 step = 0;
6704 while (newV[j]) {
6705 if (!step)
6706 step = PROBE_STEP(newHash, newMask, newPower);
6707 j < step ? (j += newSize - step) : (j -= step);
6708 }
6709 newV[j] = table->v[i];
6710 }
6711 table->mem->free_fcn(table->v);
6712 table->v = newV;
6713 table->power = newPower;
6714 table->size = newSize;
6715 i = h & newMask;
6716 step = 0;
6717 while (table->v[i]) {
6718 if (!step)
6719 step = PROBE_STEP(h, newMask, newPower);
6720 i < step ? (i += newSize - step) : (i -= step);
6721 }
6722 }
6723 }
6724 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
6725 if (!table->v[i])
6726 return NULL;
6727 memset(table->v[i], 0, createSize);
6728 table->v[i]->name = name;
6729 (table->used)++;
6730 return table->v[i];
6731}
6732
6733static void FASTCALL
6734hashTableClear(HASH_TABLE *table)
6735{
6736 size_t i;
6737 for (i = 0; i < table->size; i++) {
6738 table->mem->free_fcn(table->v[i]);
6739 table->v[i] = NULL;
6740 }
6741 table->used = 0;
6742}
6743
6744static void FASTCALL
6745hashTableDestroy(HASH_TABLE *table)
6746{
6747 size_t i;
6748 for (i = 0; i < table->size; i++)
6749 table->mem->free_fcn(table->v[i]);
6750 table->mem->free_fcn(table->v);
6751}
6752
6753static void FASTCALL
6754hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
6755{
6756 p->power = 0;
6757 p->size = 0;
6758 p->used = 0;
6759 p->v = NULL;
6760 p->mem = ms;
6761}
6762
6763static void FASTCALL
6764hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
6765{
6766 iter->p = table->v;
6767 iter->end = iter->p + table->size;
6768}
6769
6770static NAMED * FASTCALL
6771hashTableIterNext(HASH_TABLE_ITER *iter)
6772{
6773 while (iter->p != iter->end) {
6774 NAMED *tem = *(iter->p)++;
6775 if (tem)
6776 return tem;
6777 }
6778 return NULL;
6779}
6780
6781static void FASTCALL
6782poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
6783{
6784 pool->blocks = NULL;
6785 pool->freeBlocks = NULL;
6786 pool->start = NULL;
6787 pool->ptr = NULL;
6788 pool->end = NULL;
6789 pool->mem = ms;
6790}
6791
6792static void FASTCALL
6793poolClear(STRING_POOL *pool)
6794{
6795 if (!pool->freeBlocks)
6796 pool->freeBlocks = pool->blocks;
6797 else {
6798 BLOCK *p = pool->blocks;
6799 while (p) {
6800 BLOCK *tem = p->next;
6801 p->next = pool->freeBlocks;
6802 pool->freeBlocks = p;
6803 p = tem;
6804 }
6805 }
6806 pool->blocks = NULL;
6807 pool->start = NULL;
6808 pool->ptr = NULL;
6809 pool->end = NULL;
6810}
6811
6812static void FASTCALL
6813poolDestroy(STRING_POOL *pool)
6814{
6815 BLOCK *p = pool->blocks;
6816 while (p) {
6817 BLOCK *tem = p->next;
6818 pool->mem->free_fcn(p);
6819 p = tem;
6820 }
6821 p = pool->freeBlocks;
6822 while (p) {
6823 BLOCK *tem = p->next;
6824 pool->mem->free_fcn(p);
6825 p = tem;
6826 }
6827}
6828
6829static XML_Char *
6830poolAppend(STRING_POOL *pool, const ENCODING *enc,
6831 const char *ptr, const char *end)
6832{
6833 if (!pool->ptr && !poolGrow(pool))
6834 return NULL;
6835 for (;;) {
Paul Duffin4bf8f122016-05-13 12:35:25 +01006836 const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6837 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006838 break;
6839 if (!poolGrow(pool))
6840 return NULL;
6841 }
6842 return pool->start;
6843}
6844
6845static const XML_Char * FASTCALL
6846poolCopyString(STRING_POOL *pool, const XML_Char *s)
6847{
6848 do {
6849 if (!poolAppendChar(pool, *s))
6850 return NULL;
6851 } while (*s++);
6852 s = pool->start;
6853 poolFinish(pool);
6854 return s;
6855}
6856
6857static const XML_Char *
6858poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6859{
Elliott Hughes72472942018-01-10 08:36:10 -08006860 if (!pool->ptr && !poolGrow(pool)) {
6861 /* The following line is unreachable given the current usage of
6862 * poolCopyStringN(). Currently it is called from exactly one
6863 * place to copy the text of a simple general entity. By that
6864 * point, the name of the entity is already stored in the pool, so
6865 * pool->ptr cannot be NULL.
6866 *
6867 * If poolCopyStringN() is used elsewhere as it well might be,
6868 * this line may well become executable again. Regardless, this
6869 * sort of check shouldn't be removed lightly, so we just exclude
6870 * it from the coverage statistics.
6871 */
6872 return NULL; /* LCOV_EXCL_LINE */
6873 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006874 for (; n > 0; --n, s++) {
6875 if (!poolAppendChar(pool, *s))
6876 return NULL;
6877 }
6878 s = pool->start;
6879 poolFinish(pool);
6880 return s;
6881}
6882
6883static const XML_Char * FASTCALL
6884poolAppendString(STRING_POOL *pool, const XML_Char *s)
6885{
6886 while (*s) {
6887 if (!poolAppendChar(pool, *s))
6888 return NULL;
6889 s++;
6890 }
6891 return pool->start;
6892}
6893
6894static XML_Char *
6895poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6896 const char *ptr, const char *end)
6897{
6898 if (!poolAppend(pool, enc, ptr, end))
6899 return NULL;
6900 if (pool->ptr == pool->end && !poolGrow(pool))
6901 return NULL;
6902 *(pool->ptr)++ = 0;
6903 return pool->start;
6904}
6905
Elliott Hughes72472942018-01-10 08:36:10 -08006906static size_t
6907poolBytesToAllocateFor(int blockSize)
6908{
6909 /* Unprotected math would be:
6910 ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
6911 **
6912 ** Detect overflow, avoiding _signed_ overflow undefined behavior
6913 ** For a + b * c we check b * c in isolation first, so that addition of a
6914 ** on top has no chance of making us accept a small non-negative number
6915 */
6916 const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
6917
6918 if (blockSize <= 0)
6919 return 0;
6920
6921 if (blockSize > (int)(INT_MAX / stretch))
6922 return 0;
6923
6924 {
6925 const int stretchedBlockSize = blockSize * (int)stretch;
6926 const int bytesToAllocate = (int)(
6927 offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
6928 if (bytesToAllocate < 0)
6929 return 0;
6930
6931 return (size_t)bytesToAllocate;
6932 }
6933}
6934
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006935static XML_Bool FASTCALL
6936poolGrow(STRING_POOL *pool)
6937{
6938 if (pool->freeBlocks) {
6939 if (pool->start == 0) {
6940 pool->blocks = pool->freeBlocks;
6941 pool->freeBlocks = pool->freeBlocks->next;
6942 pool->blocks->next = NULL;
6943 pool->start = pool->blocks->s;
6944 pool->end = pool->start + pool->blocks->size;
6945 pool->ptr = pool->start;
6946 return XML_TRUE;
6947 }
6948 if (pool->end - pool->start < pool->freeBlocks->size) {
6949 BLOCK *tem = pool->freeBlocks->next;
6950 pool->freeBlocks->next = pool->blocks;
6951 pool->blocks = pool->freeBlocks;
6952 pool->freeBlocks = tem;
6953 memcpy(pool->blocks->s, pool->start,
6954 (pool->end - pool->start) * sizeof(XML_Char));
6955 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6956 pool->start = pool->blocks->s;
6957 pool->end = pool->start + pool->blocks->size;
6958 return XML_TRUE;
6959 }
6960 }
6961 if (pool->blocks && pool->start == pool->blocks->s) {
Paul Duffin4bf8f122016-05-13 12:35:25 +01006962 BLOCK *temp;
Paul Duffinba34a0c2017-02-27 14:40:16 +00006963 int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
Elliott Hughes72472942018-01-10 08:36:10 -08006964 size_t bytesToAllocate;
Paul Duffin4bf8f122016-05-13 12:35:25 +01006965
Elliott Hughes72472942018-01-10 08:36:10 -08006966 /* NOTE: Needs to be calculated prior to calling `realloc`
6967 to avoid dangling pointers: */
6968 const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
6969
6970 if (blockSize < 0) {
6971 /* This condition traps a situation where either more than
6972 * INT_MAX/2 bytes have already been allocated. This isn't
6973 * readily testable, since it is unlikely that an average
6974 * machine will have that much memory, so we exclude it from the
6975 * coverage statistics.
6976 */
6977 return XML_FALSE; /* LCOV_EXCL_LINE */
6978 }
6979
6980 bytesToAllocate = poolBytesToAllocateFor(blockSize);
6981 if (bytesToAllocate == 0)
Paul Duffin4bf8f122016-05-13 12:35:25 +01006982 return XML_FALSE;
6983
6984 temp = (BLOCK *)
Elliott Hughes72472942018-01-10 08:36:10 -08006985 pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate);
Elliott Hughes35e432d2012-09-09 14:23:38 -07006986 if (temp == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006987 return XML_FALSE;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006988 pool->blocks = temp;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006989 pool->blocks->size = blockSize;
Elliott Hughes72472942018-01-10 08:36:10 -08006990 pool->ptr = pool->blocks->s + offsetInsideBlock;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006991 pool->start = pool->blocks->s;
6992 pool->end = pool->start + blockSize;
6993 }
6994 else {
6995 BLOCK *tem;
6996 int blockSize = (int)(pool->end - pool->start);
Elliott Hughes72472942018-01-10 08:36:10 -08006997 size_t bytesToAllocate;
Paul Duffin4bf8f122016-05-13 12:35:25 +01006998
Elliott Hughes72472942018-01-10 08:36:10 -08006999 if (blockSize < 0) {
7000 /* This condition traps a situation where either more than
7001 * INT_MAX bytes have already been allocated (which is prevented
7002 * by various pieces of program logic, not least this one, never
7003 * mind the unlikelihood of actually having that much memory) or
7004 * the pool control fields have been corrupted (which could
7005 * conceivably happen in an extremely buggy user handler
7006 * function). Either way it isn't readily testable, so we
7007 * exclude it from the coverage statistics.
7008 */
7009 return XML_FALSE; /* LCOV_EXCL_LINE */
7010 }
Paul Duffin4bf8f122016-05-13 12:35:25 +01007011
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007012 if (blockSize < INIT_BLOCK_SIZE)
7013 blockSize = INIT_BLOCK_SIZE;
Elliott Hughes72472942018-01-10 08:36:10 -08007014 else {
7015 /* Detect overflow, avoiding _signed_ overflow undefined behavior */
7016 if ((int)((unsigned)blockSize * 2U) < 0) {
7017 return XML_FALSE;
7018 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007019 blockSize *= 2;
Elliott Hughes72472942018-01-10 08:36:10 -08007020 }
7021
7022 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7023 if (bytesToAllocate == 0)
7024 return XML_FALSE;
7025
7026 tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007027 if (!tem)
7028 return XML_FALSE;
7029 tem->size = blockSize;
7030 tem->next = pool->blocks;
7031 pool->blocks = tem;
7032 if (pool->ptr != pool->start)
7033 memcpy(tem->s, pool->start,
7034 (pool->ptr - pool->start) * sizeof(XML_Char));
7035 pool->ptr = tem->s + (pool->ptr - pool->start);
7036 pool->start = tem->s;
7037 pool->end = tem->s + blockSize;
7038 }
7039 return XML_TRUE;
7040}
7041
7042static int FASTCALL
7043nextScaffoldPart(XML_Parser parser)
7044{
Elliott Hughes72472942018-01-10 08:36:10 -08007045 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007046 CONTENT_SCAFFOLD * me;
7047 int next;
7048
7049 if (!dtd->scaffIndex) {
Elliott Hughes72472942018-01-10 08:36:10 -08007050 dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007051 if (!dtd->scaffIndex)
7052 return -1;
7053 dtd->scaffIndex[0] = 0;
7054 }
7055
7056 if (dtd->scaffCount >= dtd->scaffSize) {
7057 CONTENT_SCAFFOLD *temp;
7058 if (dtd->scaffold) {
7059 temp = (CONTENT_SCAFFOLD *)
Elliott Hughes72472942018-01-10 08:36:10 -08007060 REALLOC(parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007061 if (temp == NULL)
7062 return -1;
7063 dtd->scaffSize *= 2;
7064 }
7065 else {
Elliott Hughes72472942018-01-10 08:36:10 -08007066 temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007067 * sizeof(CONTENT_SCAFFOLD));
7068 if (temp == NULL)
7069 return -1;
7070 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
7071 }
7072 dtd->scaffold = temp;
7073 }
7074 next = dtd->scaffCount++;
7075 me = &dtd->scaffold[next];
7076 if (dtd->scaffLevel) {
7077 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
7078 if (parent->lastchild) {
7079 dtd->scaffold[parent->lastchild].nextsib = next;
7080 }
7081 if (!parent->childcnt)
7082 parent->firstchild = next;
7083 parent->lastchild = next;
7084 parent->childcnt++;
7085 }
7086 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
7087 return next;
7088}
7089
7090static void
7091build_node(XML_Parser parser,
7092 int src_node,
7093 XML_Content *dest,
7094 XML_Content **contpos,
7095 XML_Char **strpos)
7096{
Elliott Hughes72472942018-01-10 08:36:10 -08007097 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007098 dest->type = dtd->scaffold[src_node].type;
7099 dest->quant = dtd->scaffold[src_node].quant;
7100 if (dest->type == XML_CTYPE_NAME) {
7101 const XML_Char *src;
7102 dest->name = *strpos;
7103 src = dtd->scaffold[src_node].name;
7104 for (;;) {
7105 *(*strpos)++ = *src;
7106 if (!*src)
7107 break;
7108 src++;
7109 }
7110 dest->numchildren = 0;
7111 dest->children = NULL;
7112 }
7113 else {
7114 unsigned int i;
7115 int cn;
7116 dest->numchildren = dtd->scaffold[src_node].childcnt;
7117 dest->children = *contpos;
7118 *contpos += dest->numchildren;
7119 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
7120 i < dest->numchildren;
7121 i++, cn = dtd->scaffold[cn].nextsib) {
7122 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
7123 }
7124 dest->name = NULL;
7125 }
7126}
7127
7128static XML_Content *
7129build_model (XML_Parser parser)
7130{
Elliott Hughes72472942018-01-10 08:36:10 -08007131 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007132 XML_Content *ret;
7133 XML_Content *cpos;
7134 XML_Char * str;
7135 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
7136 + (dtd->contentStringLen * sizeof(XML_Char)));
7137
Elliott Hughes72472942018-01-10 08:36:10 -08007138 ret = (XML_Content *)MALLOC(parser, allocsize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007139 if (!ret)
7140 return NULL;
7141
7142 str = (XML_Char *) (&ret[dtd->scaffCount]);
7143 cpos = &ret[1];
7144
7145 build_node(parser, 0, ret, &cpos, &str);
7146 return ret;
7147}
7148
7149static ELEMENT_TYPE *
7150getElementType(XML_Parser parser,
7151 const ENCODING *enc,
7152 const char *ptr,
7153 const char *end)
7154{
Elliott Hughes72472942018-01-10 08:36:10 -08007155 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007156 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
7157 ELEMENT_TYPE *ret;
7158
7159 if (!name)
7160 return NULL;
Elliott Hughes35e432d2012-09-09 14:23:38 -07007161 ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007162 if (!ret)
7163 return NULL;
7164 if (ret->name != name)
7165 poolDiscard(&dtd->pool);
7166 else {
7167 poolFinish(&dtd->pool);
7168 if (!setElementTypePrefix(parser, ret))
7169 return NULL;
7170 }
7171 return ret;
7172}
Elliott Hughes72472942018-01-10 08:36:10 -08007173
7174static XML_Char *
7175copyString(const XML_Char *s,
7176 const XML_Memory_Handling_Suite *memsuite)
7177{
7178 int charsRequired = 0;
7179 XML_Char *result;
7180
7181 /* First determine how long the string is */
7182 while (s[charsRequired] != 0) {
7183 charsRequired++;
7184 }
7185 /* Include the terminator */
7186 charsRequired++;
7187
7188 /* Now allocate space for the copy */
7189 result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
7190 if (result == NULL)
7191 return NULL;
7192 /* Copy the original into place */
7193 memcpy(result, s, charsRequired * sizeof(XML_Char));
7194 return result;
7195}