blob: c4f3ffc215c9ef9b3f385a9fc6e3199236e99b5a [file] [log] [blame]
Elliott Hughesaaec48e2018-08-16 16:29:01 -07001/* 19ac4776051591216f1874e34ee99b6a43a3784c8bd7d70efeb9258dd22b906a (2.2.6+)
Elliott Hughes72472942018-01-10 08:36:10 -08002 __ __ _
3 ___\ \/ /_ __ __ _| |_
4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
7 |_| XML parser
8
9 Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10 Copyright (c) 2000-2017 Expat development team
11 Licensed under the MIT license:
12
13 Permission is hereby granted, free of charge, to any person obtaining
14 a copy of this software and associated documentation files (the
15 "Software"), to deal in the Software without restriction, including
16 without limitation the rights to use, copy, modify, merge, publish,
17 distribute, sublicense, and/or sell copies of the Software, and to permit
18 persons to whom the Software is furnished to do so, subject to the
19 following conditions:
20
21 The above copyright notice and this permission notice shall be included
22 in all copies or substantial portions of the Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
29 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30 USE OR OTHER DEALINGS IN THE SOFTWARE.
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080031*/
32
Elliott Hughes72472942018-01-10 08:36:10 -080033#if !defined(_GNU_SOURCE)
34# define _GNU_SOURCE 1 /* syscall prototype */
35#endif
36
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080037#include <stddef.h>
38#include <string.h> /* memset(), memcpy() */
39#include <assert.h>
Elliott Hughes35e432d2012-09-09 14:23:38 -070040#include <limits.h> /* UINT_MAX */
Elliott Hughes72472942018-01-10 08:36:10 -080041#include <stdio.h> /* fprintf */
42#include <stdlib.h> /* getenv */
Paul Duffin3c2f09e2016-06-07 15:53:38 +010043
Elliott Hughes72472942018-01-10 08:36:10 -080044#ifdef _WIN32
Paul Duffin3c2f09e2016-06-07 15:53:38 +010045#define getpid GetCurrentProcessId
46#else
47#include <sys/time.h> /* gettimeofday() */
48#include <sys/types.h> /* getpid() */
49#include <unistd.h> /* getpid() */
Elliott Hughes72472942018-01-10 08:36:10 -080050#include <fcntl.h> /* O_RDONLY */
51#include <errno.h>
Paul Duffin3c2f09e2016-06-07 15:53:38 +010052#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080053
54#define XML_BUILDING_EXPAT 1
55
Elliott Hughes72472942018-01-10 08:36:10 -080056#ifdef _WIN32
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080057#include "winconfig.h"
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080058#elif defined(HAVE_EXPAT_CONFIG_H)
59#include <expat_config.h>
Elliott Hughes72472942018-01-10 08:36:10 -080060#endif /* ndef _WIN32 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080061
Elliott Hughesd07d5a72009-09-25 16:04:37 -070062#include "ascii.h"
The Android Open Source Projectb80e2872009-03-03 19:29:30 -080063#include "expat.h"
Elliott Hughes72472942018-01-10 08:36:10 -080064#include "siphash.h"
65
66#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
67# if defined(HAVE_GETRANDOM)
68# include <sys/random.h> /* getrandom */
69# else
70# include <unistd.h> /* syscall */
71# include <sys/syscall.h> /* SYS_getrandom */
72# endif
73# if ! defined(GRND_NONBLOCK)
74# define GRND_NONBLOCK 0x0001
75# endif /* defined(GRND_NONBLOCK) */
76#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
77
78#if defined(HAVE_LIBBSD) \
79 && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
80# include <bsd/stdlib.h>
81#endif
82
83#if defined(_WIN32) && !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
84# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
85#endif
86
87#if !defined(HAVE_GETRANDOM) && !defined(HAVE_SYSCALL_GETRANDOM) \
88 && !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM) \
89 && !defined(XML_DEV_URANDOM) \
90 && !defined(_WIN32) \
91 && !defined(XML_POOR_ENTROPY)
92# error \
93 You do not have support for any sources of high quality entropy \
94 enabled. For end user security, that is probably not what you want. \
95 \
96 Your options include: \
97 * Linux + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \
98 * Linux + glibc <2.25 (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \
99 * BSD / macOS >=10.7 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \
100 * BSD / macOS <10.7 (arc4random): HAVE_ARC4RANDOM, \
101 * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
102 * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
103 * Linux / BSD / macOS (/dev/urandom): XML_DEV_URANDOM \
104 * Windows (RtlGenRandom): _WIN32. \
105 \
106 If insist on not using any of these, bypass this error by defining \
107 XML_POOR_ENTROPY; you have been warned. \
108 \
109 If you have reasons to patch this detection code away or need changes \
110 to the build system, please open a bug. Thank you!
111#endif
112
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800113
114#ifdef XML_UNICODE
115#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
116#define XmlConvert XmlUtf16Convert
117#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
118#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
119#define XmlEncode XmlUtf16Encode
Elliott Hughesd07d5a72009-09-25 16:04:37 -0700120/* Using pointer subtraction to convert to integer type. */
121#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800122typedef unsigned short ICHAR;
123#else
124#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
125#define XmlConvert XmlUtf8Convert
126#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
127#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
128#define XmlEncode XmlUtf8Encode
129#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
130typedef char ICHAR;
131#endif
132
133
134#ifndef XML_NS
135
136#define XmlInitEncodingNS XmlInitEncoding
137#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
138#undef XmlGetInternalEncodingNS
139#define XmlGetInternalEncodingNS XmlGetInternalEncoding
140#define XmlParseXmlDeclNS XmlParseXmlDecl
141
142#endif
143
144#ifdef XML_UNICODE
145
146#ifdef XML_UNICODE_WCHAR_T
147#define XML_T(x) (const wchar_t)x
148#define XML_L(x) L ## x
149#else
150#define XML_T(x) (const unsigned short)x
151#define XML_L(x) x
152#endif
153
154#else
155
156#define XML_T(x) x
157#define XML_L(x) x
158
159#endif
160
161/* Round up n to be a multiple of sz, where sz is a power of 2. */
162#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
163
Elliott Hughesaaec48e2018-08-16 16:29:01 -0700164/* Do safe (NULL-aware) pointer arithmetic */
165#define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
166
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800167/* Handle the case where memmove() doesn't exist. */
168#ifndef HAVE_MEMMOVE
169#ifdef HAVE_BCOPY
170#define memmove(d,s,l) bcopy((s),(d),(l))
171#else
172#error memmove does not exist on this platform, nor is a substitute available
173#endif /* HAVE_BCOPY */
174#endif /* HAVE_MEMMOVE */
175
176#include "internal.h"
177#include "xmltok.h"
178#include "xmlrole.h"
179
180typedef const XML_Char *KEY;
181
182typedef struct {
183 KEY name;
184} NAMED;
185
186typedef struct {
187 NAMED **v;
188 unsigned char power;
189 size_t size;
190 size_t used;
191 const XML_Memory_Handling_Suite *mem;
192} HASH_TABLE;
193
Elliott Hughes72472942018-01-10 08:36:10 -0800194static size_t
195keylen(KEY s);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800196
Elliott Hughes72472942018-01-10 08:36:10 -0800197static void
198copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800199
200/* For probing (after a collision) we need a step size relative prime
201 to the hash table size, which is a power of 2. We use double-hashing,
202 since we can calculate a second hash value cheaply by taking those bits
203 of the first hash value that were discarded (masked out) when the table
204 index was calculated: index = hash & mask, where mask = table->size - 1.
205 We limit the maximum step size to table->size / 4 (mask >> 2) and make
206 it odd, since odd numbers are always relative prime to a power of 2.
207*/
208#define SECOND_HASH(hash, mask, power) \
209 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
210#define PROBE_STEP(hash, mask, power) \
211 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
212
213typedef struct {
214 NAMED **p;
215 NAMED **end;
216} HASH_TABLE_ITER;
217
218#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
219#define INIT_DATA_BUF_SIZE 1024
220#define INIT_ATTS_SIZE 16
221#define INIT_ATTS_VERSION 0xFFFFFFFF
222#define INIT_BLOCK_SIZE 1024
223#define INIT_BUFFER_SIZE 1024
224
225#define EXPAND_SPARE 24
226
227typedef struct binding {
228 struct prefix *prefix;
229 struct binding *nextTagBinding;
230 struct binding *prevPrefixBinding;
231 const struct attribute_id *attId;
232 XML_Char *uri;
233 int uriLen;
234 int uriAlloc;
235} BINDING;
236
237typedef struct prefix {
238 const XML_Char *name;
239 BINDING *binding;
240} PREFIX;
241
242typedef struct {
243 const XML_Char *str;
244 const XML_Char *localPart;
245 const XML_Char *prefix;
246 int strLen;
247 int uriLen;
248 int prefixLen;
249} TAG_NAME;
250
251/* TAG represents an open element.
252 The name of the element is stored in both the document and API
253 encodings. The memory buffer 'buf' is a separately-allocated
254 memory area which stores the name. During the XML_Parse()/
255 XMLParseBuffer() when the element is open, the memory for the 'raw'
256 version of the name (in the document encoding) is shared with the
257 document buffer. If the element is open across calls to
258 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
259 contain the 'raw' name as well.
260
261 A parser re-uses these structures, maintaining a list of allocated
262 TAG objects in a free list.
263*/
264typedef struct tag {
265 struct tag *parent; /* parent of this element */
266 const char *rawName; /* tagName in the original encoding */
267 int rawNameLength;
268 TAG_NAME name; /* tagName in the API encoding */
269 char *buf; /* buffer for name components */
270 char *bufEnd; /* end of the buffer */
271 BINDING *bindings;
272} TAG;
273
274typedef struct {
275 const XML_Char *name;
276 const XML_Char *textPtr;
277 int textLen; /* length in XML_Chars */
278 int processed; /* # of processed bytes - when suspended */
279 const XML_Char *systemId;
280 const XML_Char *base;
281 const XML_Char *publicId;
282 const XML_Char *notation;
283 XML_Bool open;
284 XML_Bool is_param;
285 XML_Bool is_internal; /* true if declared in internal subset outside PE */
286} ENTITY;
287
288typedef struct {
289 enum XML_Content_Type type;
290 enum XML_Content_Quant quant;
291 const XML_Char * name;
292 int firstchild;
293 int lastchild;
294 int childcnt;
295 int nextsib;
296} CONTENT_SCAFFOLD;
297
298#define INIT_SCAFFOLD_ELEMENTS 32
299
300typedef struct block {
301 struct block *next;
302 int size;
303 XML_Char s[1];
304} BLOCK;
305
306typedef struct {
307 BLOCK *blocks;
308 BLOCK *freeBlocks;
309 const XML_Char *end;
310 XML_Char *ptr;
311 XML_Char *start;
312 const XML_Memory_Handling_Suite *mem;
313} STRING_POOL;
314
315/* The XML_Char before the name is used to determine whether
316 an attribute has been specified. */
317typedef struct attribute_id {
318 XML_Char *name;
319 PREFIX *prefix;
320 XML_Bool maybeTokenized;
321 XML_Bool xmlns;
322} ATTRIBUTE_ID;
323
324typedef struct {
325 const ATTRIBUTE_ID *id;
326 XML_Bool isCdata;
327 const XML_Char *value;
328} DEFAULT_ATTRIBUTE;
329
330typedef struct {
331 unsigned long version;
332 unsigned long hash;
333 const XML_Char *uriName;
334} NS_ATT;
335
336typedef struct {
337 const XML_Char *name;
338 PREFIX *prefix;
339 const ATTRIBUTE_ID *idAtt;
340 int nDefaultAtts;
341 int allocDefaultAtts;
342 DEFAULT_ATTRIBUTE *defaultAtts;
343} ELEMENT_TYPE;
344
345typedef struct {
346 HASH_TABLE generalEntities;
347 HASH_TABLE elementTypes;
348 HASH_TABLE attributeIds;
349 HASH_TABLE prefixes;
350 STRING_POOL pool;
351 STRING_POOL entityValuePool;
352 /* false once a parameter entity reference has been skipped */
353 XML_Bool keepProcessing;
354 /* true once an internal or external PE reference has been encountered;
355 this includes the reference to an external subset */
356 XML_Bool hasParamEntityRefs;
357 XML_Bool standalone;
358#ifdef XML_DTD
359 /* indicates if external PE has been read */
360 XML_Bool paramEntityRead;
361 HASH_TABLE paramEntities;
362#endif /* XML_DTD */
363 PREFIX defaultPrefix;
364 /* === scaffolding for building content model === */
365 XML_Bool in_eldecl;
366 CONTENT_SCAFFOLD *scaffold;
367 unsigned contentStringLen;
368 unsigned scaffSize;
369 unsigned scaffCount;
370 int scaffLevel;
371 int *scaffIndex;
372} DTD;
373
374typedef struct open_internal_entity {
375 const char *internalEventPtr;
376 const char *internalEventEndPtr;
377 struct open_internal_entity *next;
378 ENTITY *entity;
379 int startTagLevel;
380 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
381} OPEN_INTERNAL_ENTITY;
382
383typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
384 const char *start,
385 const char *end,
386 const char **endPtr);
387
388static Processor prologProcessor;
389static Processor prologInitProcessor;
390static Processor contentProcessor;
391static Processor cdataSectionProcessor;
392#ifdef XML_DTD
393static Processor ignoreSectionProcessor;
394static Processor externalParEntProcessor;
395static Processor externalParEntInitProcessor;
396static Processor entityValueProcessor;
397static Processor entityValueInitProcessor;
398#endif /* XML_DTD */
399static Processor epilogProcessor;
400static Processor errorProcessor;
401static Processor externalEntityInitProcessor;
402static Processor externalEntityInitProcessor2;
403static Processor externalEntityInitProcessor3;
404static Processor externalEntityContentProcessor;
405static Processor internalEntityProcessor;
406
407static enum XML_Error
408handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
409static enum XML_Error
410processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
411 const char *s, const char *next);
412static enum XML_Error
413initializeEncoding(XML_Parser parser);
414static enum XML_Error
Elliott Hughes35e432d2012-09-09 14:23:38 -0700415doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
416 const char *end, int tok, const char *next, const char **nextPtr,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800417 XML_Bool haveMore);
418static enum XML_Error
Elliott Hughes35e432d2012-09-09 14:23:38 -0700419processInternalEntity(XML_Parser parser, ENTITY *entity,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800420 XML_Bool betweenDecl);
421static enum XML_Error
422doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
Elliott Hughes35e432d2012-09-09 14:23:38 -0700423 const char *start, const char *end, const char **endPtr,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800424 XML_Bool haveMore);
425static enum XML_Error
426doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
427 const char *end, const char **nextPtr, XML_Bool haveMore);
428#ifdef XML_DTD
429static enum XML_Error
430doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
431 const char *end, const char **nextPtr, XML_Bool haveMore);
432#endif /* XML_DTD */
433
Elliott Hughes72472942018-01-10 08:36:10 -0800434static void
435freeBindings(XML_Parser parser, BINDING *bindings);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800436static enum XML_Error
437storeAtts(XML_Parser parser, const ENCODING *, const char *s,
438 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
439static enum XML_Error
440addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
441 const XML_Char *uri, BINDING **bindingsPtr);
442static int
Elliott Hughes35e432d2012-09-09 14:23:38 -0700443defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800444 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
445static enum XML_Error
446storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
447 const char *, const char *, STRING_POOL *);
448static enum XML_Error
449appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
450 const char *, const char *, STRING_POOL *);
451static ATTRIBUTE_ID *
452getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
453 const char *end);
454static int
455setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
456static enum XML_Error
457storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
458 const char *end);
459static int
460reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
461 const char *start, const char *end);
462static int
463reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
464 const char *end);
465static void
466reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
467 const char *end);
468
469static const XML_Char * getContext(XML_Parser parser);
470static XML_Bool
471setContext(XML_Parser parser, const XML_Char *context);
472
473static void FASTCALL normalizePublicId(XML_Char *s);
474
475static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
Elliott Hughes72472942018-01-10 08:36:10 -0800476/* do not call if m_parentParser != NULL */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800477static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
478static void
479dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
480static int
Elliott Hughes35e432d2012-09-09 14:23:38 -0700481dtdCopy(XML_Parser oldParser,
482 DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800483static int
Elliott Hughes35e432d2012-09-09 14:23:38 -0700484copyEntityTable(XML_Parser oldParser,
485 HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800486static NAMED *
Elliott Hughes35e432d2012-09-09 14:23:38 -0700487lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800488static void FASTCALL
489hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
490static void FASTCALL hashTableClear(HASH_TABLE *);
491static void FASTCALL hashTableDestroy(HASH_TABLE *);
492static void FASTCALL
493hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
494static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
495
496static void FASTCALL
497poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
498static void FASTCALL poolClear(STRING_POOL *);
499static void FASTCALL poolDestroy(STRING_POOL *);
500static XML_Char *
501poolAppend(STRING_POOL *pool, const ENCODING *enc,
502 const char *ptr, const char *end);
503static XML_Char *
504poolStoreString(STRING_POOL *pool, const ENCODING *enc,
505 const char *ptr, const char *end);
506static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
507static const XML_Char * FASTCALL
508poolCopyString(STRING_POOL *pool, const XML_Char *s);
509static const XML_Char *
510poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
511static const XML_Char * FASTCALL
512poolAppendString(STRING_POOL *pool, const XML_Char *s);
513
514static int FASTCALL nextScaffoldPart(XML_Parser parser);
515static XML_Content * build_model(XML_Parser parser);
516static ELEMENT_TYPE *
517getElementType(XML_Parser parser, const ENCODING *enc,
518 const char *ptr, const char *end);
519
Elliott Hughes72472942018-01-10 08:36:10 -0800520static XML_Char *copyString(const XML_Char *s,
521 const XML_Memory_Handling_Suite *memsuite);
522
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100523static unsigned long generate_hash_secret_salt(XML_Parser parser);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700524static XML_Bool startParsing(XML_Parser parser);
525
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800526static XML_Parser
527parserCreate(const XML_Char *encodingName,
528 const XML_Memory_Handling_Suite *memsuite,
529 const XML_Char *nameSep,
530 DTD *dtd);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700531
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800532static void
533parserInit(XML_Parser parser, const XML_Char *encodingName);
534
535#define poolStart(pool) ((pool)->start)
536#define poolEnd(pool) ((pool)->ptr)
537#define poolLength(pool) ((pool)->ptr - (pool)->start)
538#define poolChop(pool) ((void)--(pool->ptr))
539#define poolLastChar(pool) (((pool)->ptr)[-1])
540#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
541#define poolFinish(pool) ((pool)->start = (pool)->ptr)
542#define poolAppendChar(pool, c) \
543 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
544 ? 0 \
545 : ((*((pool)->ptr)++ = c), 1))
546
547struct XML_ParserStruct {
Elliott Hughes72472942018-01-10 08:36:10 -0800548 /* The first member must be m_userData so that the XML_GetUserData
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800549 macro works. */
550 void *m_userData;
551 void *m_handlerArg;
552 char *m_buffer;
553 const XML_Memory_Handling_Suite m_mem;
554 /* first character to be parsed */
555 const char *m_bufferPtr;
556 /* past last character to be parsed */
557 char *m_bufferEnd;
Elliott Hughes72472942018-01-10 08:36:10 -0800558 /* allocated end of m_buffer */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800559 const char *m_bufferLim;
560 XML_Index m_parseEndByteIndex;
561 const char *m_parseEndPtr;
562 XML_Char *m_dataBuf;
563 XML_Char *m_dataBufEnd;
564 XML_StartElementHandler m_startElementHandler;
565 XML_EndElementHandler m_endElementHandler;
566 XML_CharacterDataHandler m_characterDataHandler;
567 XML_ProcessingInstructionHandler m_processingInstructionHandler;
568 XML_CommentHandler m_commentHandler;
569 XML_StartCdataSectionHandler m_startCdataSectionHandler;
570 XML_EndCdataSectionHandler m_endCdataSectionHandler;
571 XML_DefaultHandler m_defaultHandler;
572 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
573 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
574 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
575 XML_NotationDeclHandler m_notationDeclHandler;
576 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
577 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
578 XML_NotStandaloneHandler m_notStandaloneHandler;
579 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
580 XML_Parser m_externalEntityRefHandlerArg;
581 XML_SkippedEntityHandler m_skippedEntityHandler;
582 XML_UnknownEncodingHandler m_unknownEncodingHandler;
583 XML_ElementDeclHandler m_elementDeclHandler;
584 XML_AttlistDeclHandler m_attlistDeclHandler;
585 XML_EntityDeclHandler m_entityDeclHandler;
586 XML_XmlDeclHandler m_xmlDeclHandler;
587 const ENCODING *m_encoding;
588 INIT_ENCODING m_initEncoding;
589 const ENCODING *m_internalEncoding;
590 const XML_Char *m_protocolEncodingName;
591 XML_Bool m_ns;
592 XML_Bool m_ns_triplets;
593 void *m_unknownEncodingMem;
594 void *m_unknownEncodingData;
595 void *m_unknownEncodingHandlerData;
596 void (XMLCALL *m_unknownEncodingRelease)(void *);
597 PROLOG_STATE m_prologState;
598 Processor *m_processor;
599 enum XML_Error m_errorCode;
600 const char *m_eventPtr;
601 const char *m_eventEndPtr;
602 const char *m_positionPtr;
603 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
604 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
605 XML_Bool m_defaultExpandInternalEntities;
606 int m_tagLevel;
607 ENTITY *m_declEntity;
608 const XML_Char *m_doctypeName;
609 const XML_Char *m_doctypeSysid;
610 const XML_Char *m_doctypePubid;
611 const XML_Char *m_declAttributeType;
612 const XML_Char *m_declNotationName;
613 const XML_Char *m_declNotationPublicId;
614 ELEMENT_TYPE *m_declElementType;
615 ATTRIBUTE_ID *m_declAttributeId;
616 XML_Bool m_declAttributeIsCdata;
617 XML_Bool m_declAttributeIsId;
618 DTD *m_dtd;
619 const XML_Char *m_curBase;
620 TAG *m_tagStack;
621 TAG *m_freeTagList;
622 BINDING *m_inheritedBindings;
623 BINDING *m_freeBindingList;
624 int m_attsSize;
625 int m_nSpecifiedAtts;
626 int m_idAttIndex;
627 ATTRIBUTE *m_atts;
628 NS_ATT *m_nsAtts;
629 unsigned long m_nsAttsVersion;
630 unsigned char m_nsAttsPower;
Elliott Hughes35e432d2012-09-09 14:23:38 -0700631#ifdef XML_ATTR_INFO
632 XML_AttrInfo *m_attInfo;
633#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800634 POSITION m_position;
635 STRING_POOL m_tempPool;
636 STRING_POOL m_temp2Pool;
637 char *m_groupConnector;
638 unsigned int m_groupSize;
639 XML_Char m_namespaceSeparator;
640 XML_Parser m_parentParser;
641 XML_ParsingStatus m_parsingStatus;
642#ifdef XML_DTD
643 XML_Bool m_isParamEntity;
644 XML_Bool m_useForeignDTD;
645 enum XML_ParamEntityParsing m_paramEntityParsing;
646#endif
Elliott Hughes35e432d2012-09-09 14:23:38 -0700647 unsigned long m_hash_secret_salt;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800648};
649
Elliott Hughes72472942018-01-10 08:36:10 -0800650#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
651#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p),(s)))
652#define FREE(parser, p) (parser->m_mem.free_fcn((p)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800653
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800654
655XML_Parser XMLCALL
656XML_ParserCreate(const XML_Char *encodingName)
657{
658 return XML_ParserCreate_MM(encodingName, NULL, NULL);
659}
660
661XML_Parser XMLCALL
662XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
663{
664 XML_Char tmp[2];
665 *tmp = nsSep;
666 return XML_ParserCreate_MM(encodingName, NULL, tmp);
667}
668
669static const XML_Char implicitContext[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -0700670 ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
Elliott Hughes35e432d2012-09-09 14:23:38 -0700671 ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
Elliott Hughesd07d5a72009-09-25 16:04:37 -0700672 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
673 ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
674 ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
675 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800676};
677
Elliott Hughes72472942018-01-10 08:36:10 -0800678
679/* To avoid warnings about unused functions: */
680#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
681
682#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
683
684/* Obtain entropy on Linux 3.17+ */
685static int
686writeRandomBytes_getrandom_nonblock(void * target, size_t count) {
687 int success = 0; /* full count bytes written? */
688 size_t bytesWrittenTotal = 0;
689 const unsigned int getrandomFlags = GRND_NONBLOCK;
690
691 do {
692 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
693 const size_t bytesToWrite = count - bytesWrittenTotal;
694
695 const int bytesWrittenMore =
696#if defined(HAVE_GETRANDOM)
697 getrandom(currentTarget, bytesToWrite, getrandomFlags);
698#else
699 syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
700#endif
701
702 if (bytesWrittenMore > 0) {
703 bytesWrittenTotal += bytesWrittenMore;
704 if (bytesWrittenTotal >= count)
705 success = 1;
706 }
707 } while (! success && (errno == EINTR));
708
709 return success;
710}
711
712#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
713
714
715#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
716
717/* Extract entropy from /dev/urandom */
718static int
719writeRandomBytes_dev_urandom(void * target, size_t count) {
720 int success = 0; /* full count bytes written? */
721 size_t bytesWrittenTotal = 0;
722
723 const int fd = open("/dev/urandom", O_RDONLY);
724 if (fd < 0) {
725 return 0;
726 }
727
728 do {
729 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
730 const size_t bytesToWrite = count - bytesWrittenTotal;
731
732 const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
733
734 if (bytesWrittenMore > 0) {
735 bytesWrittenTotal += bytesWrittenMore;
736 if (bytesWrittenTotal >= count)
737 success = 1;
738 }
739 } while (! success && (errno == EINTR));
740
741 close(fd);
742 return success;
743}
744
745#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
746
747#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
748
749
750#if defined(HAVE_ARC4RANDOM)
751
752static void
753writeRandomBytes_arc4random(void * target, size_t count) {
754 size_t bytesWrittenTotal = 0;
755
756 while (bytesWrittenTotal < count) {
757 const uint32_t random32 = arc4random();
758 size_t i = 0;
759
760 for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
761 i++, bytesWrittenTotal++) {
762 const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
763 ((uint8_t *)target)[bytesWrittenTotal] = random8;
764 }
765 }
766}
767
768#endif /* defined(HAVE_ARC4RANDOM) */
769
770
771#ifdef _WIN32
772
773typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
774HMODULE _Expat_LoadLibrary(LPCTSTR filename); /* see loadlibrary.c */
775
776/* Obtain entropy on Windows XP / Windows Server 2003 and later.
777 * Hint on RtlGenRandom and the following article from libsodium.
778 *
779 * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
780 * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
781 */
782static int
783writeRandomBytes_RtlGenRandom(void * target, size_t count) {
784 int success = 0; /* full count bytes written? */
785 const HMODULE advapi32 = _Expat_LoadLibrary(TEXT("ADVAPI32.DLL"));
786
787 if (advapi32) {
788 const RTLGENRANDOM_FUNC RtlGenRandom
789 = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
790 if (RtlGenRandom) {
791 if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
792 success = 1;
793 }
794 }
795 FreeLibrary(advapi32);
796 }
797
798 return success;
799}
800
801#endif /* _WIN32 */
802
803
804#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
805
Elliott Hughes35e432d2012-09-09 14:23:38 -0700806static unsigned long
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100807gather_time_entropy(void)
Elliott Hughes35e432d2012-09-09 14:23:38 -0700808{
Elliott Hughes72472942018-01-10 08:36:10 -0800809#ifdef _WIN32
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100810 FILETIME ft;
811 GetSystemTimeAsFileTime(&ft); /* never fails */
812 return ft.dwHighDateTime ^ ft.dwLowDateTime;
813#else
814 struct timeval tv;
815 int gettimeofday_res;
816
817 gettimeofday_res = gettimeofday(&tv, NULL);
Elliott Hughes72472942018-01-10 08:36:10 -0800818
819#if defined(NDEBUG)
820 (void)gettimeofday_res;
821#else
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100822 assert (gettimeofday_res == 0);
Elliott Hughes72472942018-01-10 08:36:10 -0800823#endif /* defined(NDEBUG) */
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100824
825 /* Microseconds time is <20 bits entropy */
826 return tv.tv_usec;
827#endif
828}
829
Elliott Hughes72472942018-01-10 08:36:10 -0800830#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
831
832
833static unsigned long
834ENTROPY_DEBUG(const char * label, unsigned long entropy) {
835 const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
836 if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
837 fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
838 label,
839 (int)sizeof(entropy) * 2, entropy,
840 (unsigned long)sizeof(entropy));
841 }
842 return entropy;
843}
844
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100845static unsigned long
846generate_hash_secret_salt(XML_Parser parser)
847{
Elliott Hughes72472942018-01-10 08:36:10 -0800848 unsigned long entropy;
849 (void)parser;
850
851 /* "Failproof" high quality providers: */
852#if defined(HAVE_ARC4RANDOM_BUF)
853 arc4random_buf(&entropy, sizeof(entropy));
854 return ENTROPY_DEBUG("arc4random_buf", entropy);
855#elif defined(HAVE_ARC4RANDOM)
856 writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
857 return ENTROPY_DEBUG("arc4random", entropy);
858#else
859 /* Try high quality providers first .. */
860#ifdef _WIN32
861 if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
862 return ENTROPY_DEBUG("RtlGenRandom", entropy);
863 }
864#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
865 if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
866 return ENTROPY_DEBUG("getrandom", entropy);
867 }
868#endif
869#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
870 if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
871 return ENTROPY_DEBUG("/dev/urandom", entropy);
872 }
873#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
874 /* .. and self-made low quality for backup: */
875
876 /* Process ID is 0 bits entropy if attacker has local access */
877 entropy = gather_time_entropy() ^ getpid();
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100878
879 /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
880 if (sizeof(unsigned long) == 4) {
Elliott Hughes72472942018-01-10 08:36:10 -0800881 return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100882 } else {
Elliott Hughes72472942018-01-10 08:36:10 -0800883 return ENTROPY_DEBUG("fallback(8)",
884 entropy * (unsigned long)2305843009213693951ULL);
Paul Duffin3c2f09e2016-06-07 15:53:38 +0100885 }
Elliott Hughes72472942018-01-10 08:36:10 -0800886#endif
887}
888
889static unsigned long
890get_hash_secret_salt(XML_Parser parser) {
891 if (parser->m_parentParser != NULL)
892 return get_hash_secret_salt(parser->m_parentParser);
893 return parser->m_hash_secret_salt;
Elliott Hughes35e432d2012-09-09 14:23:38 -0700894}
895
896static XML_Bool /* only valid for root parser */
897startParsing(XML_Parser parser)
898{
899 /* hash functions must be initialized before setContext() is called */
Elliott Hughes72472942018-01-10 08:36:10 -0800900 if (parser->m_hash_secret_salt == 0)
901 parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
902 if (parser->m_ns) {
Elliott Hughes35e432d2012-09-09 14:23:38 -0700903 /* implicit context only set for root parser, since child
904 parsers (i.e. external entity parsers) will inherit it
905 */
906 return setContext(parser, implicitContext);
907 }
908 return XML_TRUE;
909}
910
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800911XML_Parser XMLCALL
912XML_ParserCreate_MM(const XML_Char *encodingName,
913 const XML_Memory_Handling_Suite *memsuite,
914 const XML_Char *nameSep)
915{
Elliott Hughes35e432d2012-09-09 14:23:38 -0700916 return parserCreate(encodingName, memsuite, nameSep, NULL);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800917}
918
919static XML_Parser
920parserCreate(const XML_Char *encodingName,
921 const XML_Memory_Handling_Suite *memsuite,
922 const XML_Char *nameSep,
923 DTD *dtd)
924{
925 XML_Parser parser;
926
927 if (memsuite) {
928 XML_Memory_Handling_Suite *mtemp;
929 parser = (XML_Parser)
930 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
931 if (parser != NULL) {
932 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
933 mtemp->malloc_fcn = memsuite->malloc_fcn;
934 mtemp->realloc_fcn = memsuite->realloc_fcn;
935 mtemp->free_fcn = memsuite->free_fcn;
936 }
937 }
938 else {
939 XML_Memory_Handling_Suite *mtemp;
940 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
941 if (parser != NULL) {
942 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
943 mtemp->malloc_fcn = malloc;
944 mtemp->realloc_fcn = realloc;
945 mtemp->free_fcn = free;
946 }
947 }
948
949 if (!parser)
950 return parser;
951
Elliott Hughes72472942018-01-10 08:36:10 -0800952 parser->m_buffer = NULL;
953 parser->m_bufferLim = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800954
Elliott Hughes72472942018-01-10 08:36:10 -0800955 parser->m_attsSize = INIT_ATTS_SIZE;
956 parser->m_atts = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
957 if (parser->m_atts == NULL) {
958 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800959 return NULL;
960 }
Elliott Hughes35e432d2012-09-09 14:23:38 -0700961#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -0800962 parser->m_attInfo = (XML_AttrInfo*)MALLOC(parser, parser->m_attsSize * sizeof(XML_AttrInfo));
963 if (parser->m_attInfo == NULL) {
964 FREE(parser, parser->m_atts);
965 FREE(parser, parser);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700966 return NULL;
967 }
968#endif
Elliott Hughes72472942018-01-10 08:36:10 -0800969 parser->m_dataBuf = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
970 if (parser->m_dataBuf == NULL) {
971 FREE(parser, parser->m_atts);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700972#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -0800973 FREE(parser, parser->m_attInfo);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700974#endif
Elliott Hughes72472942018-01-10 08:36:10 -0800975 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800976 return NULL;
977 }
Elliott Hughes72472942018-01-10 08:36:10 -0800978 parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800979
980 if (dtd)
Elliott Hughes72472942018-01-10 08:36:10 -0800981 parser->m_dtd = dtd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800982 else {
Elliott Hughes72472942018-01-10 08:36:10 -0800983 parser->m_dtd = dtdCreate(&parser->m_mem);
984 if (parser->m_dtd == NULL) {
985 FREE(parser, parser->m_dataBuf);
986 FREE(parser, parser->m_atts);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700987#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -0800988 FREE(parser, parser->m_attInfo);
Elliott Hughes35e432d2012-09-09 14:23:38 -0700989#endif
Elliott Hughes72472942018-01-10 08:36:10 -0800990 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800991 return NULL;
992 }
993 }
994
Elliott Hughes72472942018-01-10 08:36:10 -0800995 parser->m_freeBindingList = NULL;
996 parser->m_freeTagList = NULL;
997 parser->m_freeInternalEntities = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -0800998
Elliott Hughes72472942018-01-10 08:36:10 -0800999 parser->m_groupSize = 0;
1000 parser->m_groupConnector = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001001
Elliott Hughes72472942018-01-10 08:36:10 -08001002 parser->m_unknownEncodingHandler = NULL;
1003 parser->m_unknownEncodingHandlerData = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001004
Elliott Hughes72472942018-01-10 08:36:10 -08001005 parser->m_namespaceSeparator = ASCII_EXCL;
1006 parser->m_ns = XML_FALSE;
1007 parser->m_ns_triplets = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001008
Elliott Hughes72472942018-01-10 08:36:10 -08001009 parser->m_nsAtts = NULL;
1010 parser->m_nsAttsVersion = 0;
1011 parser->m_nsAttsPower = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001012
Elliott Hughes72472942018-01-10 08:36:10 -08001013 parser->m_protocolEncodingName = NULL;
1014
1015 poolInit(&parser->m_tempPool, &(parser->m_mem));
1016 poolInit(&parser->m_temp2Pool, &(parser->m_mem));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001017 parserInit(parser, encodingName);
1018
Elliott Hughes72472942018-01-10 08:36:10 -08001019 if (encodingName && !parser->m_protocolEncodingName) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001020 XML_ParserFree(parser);
1021 return NULL;
1022 }
1023
1024 if (nameSep) {
Elliott Hughes72472942018-01-10 08:36:10 -08001025 parser->m_ns = XML_TRUE;
1026 parser->m_internalEncoding = XmlGetInternalEncodingNS();
1027 parser->m_namespaceSeparator = *nameSep;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001028 }
1029 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001030 parser->m_internalEncoding = XmlGetInternalEncoding();
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001031 }
1032
1033 return parser;
1034}
1035
1036static void
1037parserInit(XML_Parser parser, const XML_Char *encodingName)
1038{
Elliott Hughes72472942018-01-10 08:36:10 -08001039 parser->m_processor = prologInitProcessor;
1040 XmlPrologStateInit(&parser->m_prologState);
1041 if (encodingName != NULL) {
1042 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1043 }
1044 parser->m_curBase = NULL;
1045 XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0);
1046 parser->m_userData = NULL;
1047 parser->m_handlerArg = NULL;
1048 parser->m_startElementHandler = NULL;
1049 parser->m_endElementHandler = NULL;
1050 parser->m_characterDataHandler = NULL;
1051 parser->m_processingInstructionHandler = NULL;
1052 parser->m_commentHandler = NULL;
1053 parser->m_startCdataSectionHandler = NULL;
1054 parser->m_endCdataSectionHandler = NULL;
1055 parser->m_defaultHandler = NULL;
1056 parser->m_startDoctypeDeclHandler = NULL;
1057 parser->m_endDoctypeDeclHandler = NULL;
1058 parser->m_unparsedEntityDeclHandler = NULL;
1059 parser->m_notationDeclHandler = NULL;
1060 parser->m_startNamespaceDeclHandler = NULL;
1061 parser->m_endNamespaceDeclHandler = NULL;
1062 parser->m_notStandaloneHandler = NULL;
1063 parser->m_externalEntityRefHandler = NULL;
1064 parser->m_externalEntityRefHandlerArg = parser;
1065 parser->m_skippedEntityHandler = NULL;
1066 parser->m_elementDeclHandler = NULL;
1067 parser->m_attlistDeclHandler = NULL;
1068 parser->m_entityDeclHandler = NULL;
1069 parser->m_xmlDeclHandler = NULL;
1070 parser->m_bufferPtr = parser->m_buffer;
1071 parser->m_bufferEnd = parser->m_buffer;
1072 parser->m_parseEndByteIndex = 0;
1073 parser->m_parseEndPtr = NULL;
1074 parser->m_declElementType = NULL;
1075 parser->m_declAttributeId = NULL;
1076 parser->m_declEntity = NULL;
1077 parser->m_doctypeName = NULL;
1078 parser->m_doctypeSysid = NULL;
1079 parser->m_doctypePubid = NULL;
1080 parser->m_declAttributeType = NULL;
1081 parser->m_declNotationName = NULL;
1082 parser->m_declNotationPublicId = NULL;
1083 parser->m_declAttributeIsCdata = XML_FALSE;
1084 parser->m_declAttributeIsId = XML_FALSE;
1085 memset(&parser->m_position, 0, sizeof(POSITION));
1086 parser->m_errorCode = XML_ERROR_NONE;
1087 parser->m_eventPtr = NULL;
1088 parser->m_eventEndPtr = NULL;
1089 parser->m_positionPtr = NULL;
1090 parser->m_openInternalEntities = NULL;
1091 parser->m_defaultExpandInternalEntities = XML_TRUE;
1092 parser->m_tagLevel = 0;
1093 parser->m_tagStack = NULL;
1094 parser->m_inheritedBindings = NULL;
1095 parser->m_nSpecifiedAtts = 0;
1096 parser->m_unknownEncodingMem = NULL;
1097 parser->m_unknownEncodingRelease = NULL;
1098 parser->m_unknownEncodingData = NULL;
1099 parser->m_parentParser = NULL;
1100 parser->m_parsingStatus.parsing = XML_INITIALIZED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001101#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001102 parser->m_isParamEntity = XML_FALSE;
1103 parser->m_useForeignDTD = XML_FALSE;
1104 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001105#endif
Elliott Hughes72472942018-01-10 08:36:10 -08001106 parser->m_hash_secret_salt = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001107}
1108
Elliott Hughes72472942018-01-10 08:36:10 -08001109/* moves list of bindings to m_freeBindingList */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001110static void FASTCALL
1111moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
1112{
1113 while (bindings) {
1114 BINDING *b = bindings;
1115 bindings = bindings->nextTagBinding;
Elliott Hughes72472942018-01-10 08:36:10 -08001116 b->nextTagBinding = parser->m_freeBindingList;
1117 parser->m_freeBindingList = b;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001118 }
1119}
1120
1121XML_Bool XMLCALL
1122XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
1123{
1124 TAG *tStk;
1125 OPEN_INTERNAL_ENTITY *openEntityList;
Elliott Hughes72472942018-01-10 08:36:10 -08001126
1127 if (parser == NULL)
1128 return XML_FALSE;
1129
1130 if (parser->m_parentParser)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001131 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08001132 /* move m_tagStack to m_freeTagList */
1133 tStk = parser->m_tagStack;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001134 while (tStk) {
1135 TAG *tag = tStk;
1136 tStk = tStk->parent;
Elliott Hughes72472942018-01-10 08:36:10 -08001137 tag->parent = parser->m_freeTagList;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001138 moveToFreeBindingList(parser, tag->bindings);
1139 tag->bindings = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08001140 parser->m_freeTagList = tag;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001141 }
Elliott Hughes72472942018-01-10 08:36:10 -08001142 /* move m_openInternalEntities to m_freeInternalEntities */
1143 openEntityList = parser->m_openInternalEntities;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001144 while (openEntityList) {
1145 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
1146 openEntityList = openEntity->next;
Elliott Hughes72472942018-01-10 08:36:10 -08001147 openEntity->next = parser->m_freeInternalEntities;
1148 parser->m_freeInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001149 }
Elliott Hughes72472942018-01-10 08:36:10 -08001150 moveToFreeBindingList(parser, parser->m_inheritedBindings);
1151 FREE(parser, parser->m_unknownEncodingMem);
1152 if (parser->m_unknownEncodingRelease)
1153 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1154 poolClear(&parser->m_tempPool);
1155 poolClear(&parser->m_temp2Pool);
1156 FREE(parser, (void *)parser->m_protocolEncodingName);
1157 parser->m_protocolEncodingName = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001158 parserInit(parser, encodingName);
Elliott Hughes72472942018-01-10 08:36:10 -08001159 dtdReset(parser->m_dtd, &parser->m_mem);
Elliott Hughes35e432d2012-09-09 14:23:38 -07001160 return XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001161}
1162
1163enum XML_Status XMLCALL
1164XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
1165{
Elliott Hughes72472942018-01-10 08:36:10 -08001166 if (parser == NULL)
1167 return XML_STATUS_ERROR;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001168 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
1169 XXX There's no way for the caller to determine which of the
1170 XXX possible error cases caused the XML_STATUS_ERROR return.
1171 */
Elliott Hughes72472942018-01-10 08:36:10 -08001172 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001173 return XML_STATUS_ERROR;
Elliott Hughes72472942018-01-10 08:36:10 -08001174
1175 /* Get rid of any previous encoding name */
1176 FREE(parser, (void *)parser->m_protocolEncodingName);
1177
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001178 if (encodingName == NULL)
Elliott Hughes72472942018-01-10 08:36:10 -08001179 /* No new encoding name */
1180 parser->m_protocolEncodingName = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001181 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001182 /* Copy the new encoding name into allocated memory */
1183 parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1184 if (!parser->m_protocolEncodingName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001185 return XML_STATUS_ERROR;
1186 }
1187 return XML_STATUS_OK;
1188}
1189
1190XML_Parser XMLCALL
1191XML_ExternalEntityParserCreate(XML_Parser oldParser,
1192 const XML_Char *context,
1193 const XML_Char *encodingName)
1194{
1195 XML_Parser parser = oldParser;
1196 DTD *newDtd = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08001197 DTD *oldDtd;
1198 XML_StartElementHandler oldStartElementHandler;
1199 XML_EndElementHandler oldEndElementHandler;
1200 XML_CharacterDataHandler oldCharacterDataHandler;
1201 XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
1202 XML_CommentHandler oldCommentHandler;
1203 XML_StartCdataSectionHandler oldStartCdataSectionHandler;
1204 XML_EndCdataSectionHandler oldEndCdataSectionHandler;
1205 XML_DefaultHandler oldDefaultHandler;
1206 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
1207 XML_NotationDeclHandler oldNotationDeclHandler;
1208 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
1209 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
1210 XML_NotStandaloneHandler oldNotStandaloneHandler;
1211 XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
1212 XML_SkippedEntityHandler oldSkippedEntityHandler;
1213 XML_UnknownEncodingHandler oldUnknownEncodingHandler;
1214 XML_ElementDeclHandler oldElementDeclHandler;
1215 XML_AttlistDeclHandler oldAttlistDeclHandler;
1216 XML_EntityDeclHandler oldEntityDeclHandler;
1217 XML_XmlDeclHandler oldXmlDeclHandler;
1218 ELEMENT_TYPE * oldDeclElementType;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001219
Elliott Hughes72472942018-01-10 08:36:10 -08001220 void *oldUserData;
1221 void *oldHandlerArg;
1222 XML_Bool oldDefaultExpandInternalEntities;
1223 XML_Parser oldExternalEntityRefHandlerArg;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001224#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001225 enum XML_ParamEntityParsing oldParamEntityParsing;
1226 int oldInEntityValue;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001227#endif
Elliott Hughes72472942018-01-10 08:36:10 -08001228 XML_Bool oldns_triplets;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001229 /* Note that the new parser shares the same hash secret as the old
1230 parser, so that dtdCopy and copyEntityTable can lookup values
1231 from hash tables associated with either parser without us having
1232 to worry which hash secrets each table has.
1233 */
Elliott Hughes72472942018-01-10 08:36:10 -08001234 unsigned long oldhash_secret_salt;
1235
1236 /* Validate the oldParser parameter before we pull everything out of it */
1237 if (oldParser == NULL)
1238 return NULL;
1239
1240 /* Stash the original parser contents on the stack */
1241 oldDtd = parser->m_dtd;
1242 oldStartElementHandler = parser->m_startElementHandler;
1243 oldEndElementHandler = parser->m_endElementHandler;
1244 oldCharacterDataHandler = parser->m_characterDataHandler;
1245 oldProcessingInstructionHandler = parser->m_processingInstructionHandler;
1246 oldCommentHandler = parser->m_commentHandler;
1247 oldStartCdataSectionHandler = parser->m_startCdataSectionHandler;
1248 oldEndCdataSectionHandler = parser->m_endCdataSectionHandler;
1249 oldDefaultHandler = parser->m_defaultHandler;
1250 oldUnparsedEntityDeclHandler = parser->m_unparsedEntityDeclHandler;
1251 oldNotationDeclHandler = parser->m_notationDeclHandler;
1252 oldStartNamespaceDeclHandler = parser->m_startNamespaceDeclHandler;
1253 oldEndNamespaceDeclHandler = parser->m_endNamespaceDeclHandler;
1254 oldNotStandaloneHandler = parser->m_notStandaloneHandler;
1255 oldExternalEntityRefHandler = parser->m_externalEntityRefHandler;
1256 oldSkippedEntityHandler = parser->m_skippedEntityHandler;
1257 oldUnknownEncodingHandler = parser->m_unknownEncodingHandler;
1258 oldElementDeclHandler = parser->m_elementDeclHandler;
1259 oldAttlistDeclHandler = parser->m_attlistDeclHandler;
1260 oldEntityDeclHandler = parser->m_entityDeclHandler;
1261 oldXmlDeclHandler = parser->m_xmlDeclHandler;
1262 oldDeclElementType = parser->m_declElementType;
1263
1264 oldUserData = parser->m_userData;
1265 oldHandlerArg = parser->m_handlerArg;
1266 oldDefaultExpandInternalEntities = parser->m_defaultExpandInternalEntities;
1267 oldExternalEntityRefHandlerArg = parser->m_externalEntityRefHandlerArg;
1268#ifdef XML_DTD
1269 oldParamEntityParsing = parser->m_paramEntityParsing;
1270 oldInEntityValue = parser->m_prologState.inEntityValue;
1271#endif
1272 oldns_triplets = parser->m_ns_triplets;
1273 /* Note that the new parser shares the same hash secret as the old
1274 parser, so that dtdCopy and copyEntityTable can lookup values
1275 from hash tables associated with either parser without us having
1276 to worry which hash secrets each table has.
1277 */
1278 oldhash_secret_salt = parser->m_hash_secret_salt;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001279
1280#ifdef XML_DTD
1281 if (!context)
1282 newDtd = oldDtd;
1283#endif /* XML_DTD */
1284
1285 /* Note that the magical uses of the pre-processor to make field
1286 access look more like C++ require that `parser' be overwritten
1287 here. This makes this function more painful to follow than it
1288 would be otherwise.
1289 */
Elliott Hughes72472942018-01-10 08:36:10 -08001290 if (parser->m_ns) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001291 XML_Char tmp[2];
Elliott Hughes72472942018-01-10 08:36:10 -08001292 *tmp = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001293 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1294 }
1295 else {
1296 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1297 }
1298
1299 if (!parser)
1300 return NULL;
1301
Elliott Hughes72472942018-01-10 08:36:10 -08001302 parser->m_startElementHandler = oldStartElementHandler;
1303 parser->m_endElementHandler = oldEndElementHandler;
1304 parser->m_characterDataHandler = oldCharacterDataHandler;
1305 parser->m_processingInstructionHandler = oldProcessingInstructionHandler;
1306 parser->m_commentHandler = oldCommentHandler;
1307 parser->m_startCdataSectionHandler = oldStartCdataSectionHandler;
1308 parser->m_endCdataSectionHandler = oldEndCdataSectionHandler;
1309 parser->m_defaultHandler = oldDefaultHandler;
1310 parser->m_unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1311 parser->m_notationDeclHandler = oldNotationDeclHandler;
1312 parser->m_startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1313 parser->m_endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1314 parser->m_notStandaloneHandler = oldNotStandaloneHandler;
1315 parser->m_externalEntityRefHandler = oldExternalEntityRefHandler;
1316 parser->m_skippedEntityHandler = oldSkippedEntityHandler;
1317 parser->m_unknownEncodingHandler = oldUnknownEncodingHandler;
1318 parser->m_elementDeclHandler = oldElementDeclHandler;
1319 parser->m_attlistDeclHandler = oldAttlistDeclHandler;
1320 parser->m_entityDeclHandler = oldEntityDeclHandler;
1321 parser->m_xmlDeclHandler = oldXmlDeclHandler;
1322 parser->m_declElementType = oldDeclElementType;
1323 parser->m_userData = oldUserData;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001324 if (oldUserData == oldHandlerArg)
Elliott Hughes72472942018-01-10 08:36:10 -08001325 parser->m_handlerArg = parser->m_userData;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001326 else
Elliott Hughes72472942018-01-10 08:36:10 -08001327 parser->m_handlerArg = parser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001328 if (oldExternalEntityRefHandlerArg != oldParser)
Elliott Hughes72472942018-01-10 08:36:10 -08001329 parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1330 parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1331 parser->m_ns_triplets = oldns_triplets;
1332 parser->m_hash_secret_salt = oldhash_secret_salt;
1333 parser->m_parentParser = oldParser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001334#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001335 parser->m_paramEntityParsing = oldParamEntityParsing;
1336 parser->m_prologState.inEntityValue = oldInEntityValue;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001337 if (context) {
1338#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08001339 if (!dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001340 || !setContext(parser, context)) {
1341 XML_ParserFree(parser);
1342 return NULL;
1343 }
Elliott Hughes72472942018-01-10 08:36:10 -08001344 parser->m_processor = externalEntityInitProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001345#ifdef XML_DTD
1346 }
1347 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001348 /* The DTD instance referenced by parser->m_dtd is shared between the document's
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001349 root parser and external PE parsers, therefore one does not need to
1350 call setContext. In addition, one also *must* not call setContext,
1351 because this would overwrite existing prefix->binding pointers in
Elliott Hughes72472942018-01-10 08:36:10 -08001352 parser->m_dtd with ones that get destroyed with the external PE parser.
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001353 This would leave those prefixes with dangling pointers.
1354 */
Elliott Hughes72472942018-01-10 08:36:10 -08001355 parser->m_isParamEntity = XML_TRUE;
1356 XmlPrologStateInitExternalEntity(&parser->m_prologState);
1357 parser->m_processor = externalParEntInitProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001358 }
1359#endif /* XML_DTD */
1360 return parser;
1361}
1362
1363static void FASTCALL
1364destroyBindings(BINDING *bindings, XML_Parser parser)
1365{
1366 for (;;) {
1367 BINDING *b = bindings;
1368 if (!b)
1369 break;
1370 bindings = b->nextTagBinding;
Elliott Hughes72472942018-01-10 08:36:10 -08001371 FREE(parser, b->uri);
1372 FREE(parser, b);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001373 }
1374}
1375
1376void XMLCALL
1377XML_ParserFree(XML_Parser parser)
1378{
1379 TAG *tagList;
1380 OPEN_INTERNAL_ENTITY *entityList;
1381 if (parser == NULL)
1382 return;
Elliott Hughes72472942018-01-10 08:36:10 -08001383 /* free m_tagStack and m_freeTagList */
1384 tagList = parser->m_tagStack;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001385 for (;;) {
1386 TAG *p;
1387 if (tagList == NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08001388 if (parser->m_freeTagList == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001389 break;
Elliott Hughes72472942018-01-10 08:36:10 -08001390 tagList = parser->m_freeTagList;
1391 parser->m_freeTagList = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001392 }
1393 p = tagList;
1394 tagList = tagList->parent;
Elliott Hughes72472942018-01-10 08:36:10 -08001395 FREE(parser, p->buf);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001396 destroyBindings(p->bindings, parser);
Elliott Hughes72472942018-01-10 08:36:10 -08001397 FREE(parser, p);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001398 }
Elliott Hughes72472942018-01-10 08:36:10 -08001399 /* free m_openInternalEntities and m_freeInternalEntities */
1400 entityList = parser->m_openInternalEntities;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001401 for (;;) {
1402 OPEN_INTERNAL_ENTITY *openEntity;
1403 if (entityList == NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08001404 if (parser->m_freeInternalEntities == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001405 break;
Elliott Hughes72472942018-01-10 08:36:10 -08001406 entityList = parser->m_freeInternalEntities;
1407 parser->m_freeInternalEntities = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001408 }
1409 openEntity = entityList;
1410 entityList = entityList->next;
Elliott Hughes72472942018-01-10 08:36:10 -08001411 FREE(parser, openEntity);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001412 }
1413
Elliott Hughes72472942018-01-10 08:36:10 -08001414 destroyBindings(parser->m_freeBindingList, parser);
1415 destroyBindings(parser->m_inheritedBindings, parser);
1416 poolDestroy(&parser->m_tempPool);
1417 poolDestroy(&parser->m_temp2Pool);
1418 FREE(parser, (void *)parser->m_protocolEncodingName);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001419#ifdef XML_DTD
1420 /* external parameter entity parsers share the DTD structure
1421 parser->m_dtd with the root parser, so we must not destroy it
1422 */
Elliott Hughes72472942018-01-10 08:36:10 -08001423 if (!parser->m_isParamEntity && parser->m_dtd)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001424#else
Elliott Hughes72472942018-01-10 08:36:10 -08001425 if (parser->m_dtd)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001426#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08001427 dtdDestroy(parser->m_dtd, (XML_Bool)!parser->m_parentParser, &parser->m_mem);
1428 FREE(parser, (void *)parser->m_atts);
Elliott Hughes35e432d2012-09-09 14:23:38 -07001429#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08001430 FREE(parser, (void *)parser->m_attInfo);
Elliott Hughes35e432d2012-09-09 14:23:38 -07001431#endif
Elliott Hughes72472942018-01-10 08:36:10 -08001432 FREE(parser, parser->m_groupConnector);
1433 FREE(parser, parser->m_buffer);
1434 FREE(parser, parser->m_dataBuf);
1435 FREE(parser, parser->m_nsAtts);
1436 FREE(parser, parser->m_unknownEncodingMem);
1437 if (parser->m_unknownEncodingRelease)
1438 parser->m_unknownEncodingRelease(parser->m_unknownEncodingData);
1439 FREE(parser, parser);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001440}
1441
1442void XMLCALL
1443XML_UseParserAsHandlerArg(XML_Parser parser)
1444{
Elliott Hughes72472942018-01-10 08:36:10 -08001445 if (parser != NULL)
1446 parser->m_handlerArg = parser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001447}
1448
1449enum XML_Error XMLCALL
1450XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1451{
Elliott Hughes72472942018-01-10 08:36:10 -08001452 if (parser == NULL)
1453 return XML_ERROR_INVALID_ARGUMENT;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001454#ifdef XML_DTD
1455 /* block after XML_Parse()/XML_ParseBuffer() has been called */
Elliott Hughes72472942018-01-10 08:36:10 -08001456 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001457 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
Elliott Hughes72472942018-01-10 08:36:10 -08001458 parser->m_useForeignDTD = useDTD;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001459 return XML_ERROR_NONE;
1460#else
1461 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1462#endif
1463}
1464
1465void XMLCALL
1466XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1467{
Elliott Hughes72472942018-01-10 08:36:10 -08001468 if (parser == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001469 return;
Elliott Hughes72472942018-01-10 08:36:10 -08001470 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1471 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1472 return;
1473 parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001474}
1475
1476void XMLCALL
1477XML_SetUserData(XML_Parser parser, void *p)
1478{
Elliott Hughes72472942018-01-10 08:36:10 -08001479 if (parser == NULL)
1480 return;
1481 if (parser->m_handlerArg == parser->m_userData)
1482 parser->m_handlerArg = parser->m_userData = p;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001483 else
Elliott Hughes72472942018-01-10 08:36:10 -08001484 parser->m_userData = p;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001485}
1486
1487enum XML_Status XMLCALL
1488XML_SetBase(XML_Parser parser, const XML_Char *p)
1489{
Elliott Hughes72472942018-01-10 08:36:10 -08001490 if (parser == NULL)
1491 return XML_STATUS_ERROR;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001492 if (p) {
Elliott Hughes72472942018-01-10 08:36:10 -08001493 p = poolCopyString(&parser->m_dtd->pool, p);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001494 if (!p)
1495 return XML_STATUS_ERROR;
Elliott Hughes72472942018-01-10 08:36:10 -08001496 parser->m_curBase = p;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001497 }
1498 else
Elliott Hughes72472942018-01-10 08:36:10 -08001499 parser->m_curBase = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001500 return XML_STATUS_OK;
1501}
1502
1503const XML_Char * XMLCALL
1504XML_GetBase(XML_Parser parser)
1505{
Elliott Hughes72472942018-01-10 08:36:10 -08001506 if (parser == NULL)
1507 return NULL;
1508 return parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001509}
1510
1511int XMLCALL
1512XML_GetSpecifiedAttributeCount(XML_Parser parser)
1513{
Elliott Hughes72472942018-01-10 08:36:10 -08001514 if (parser == NULL)
1515 return -1;
1516 return parser->m_nSpecifiedAtts;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001517}
1518
1519int XMLCALL
1520XML_GetIdAttributeIndex(XML_Parser parser)
1521{
Elliott Hughes72472942018-01-10 08:36:10 -08001522 if (parser == NULL)
1523 return -1;
1524 return parser->m_idAttIndex;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001525}
1526
Elliott Hughes35e432d2012-09-09 14:23:38 -07001527#ifdef XML_ATTR_INFO
1528const XML_AttrInfo * XMLCALL
1529XML_GetAttributeInfo(XML_Parser parser)
1530{
Elliott Hughes72472942018-01-10 08:36:10 -08001531 if (parser == NULL)
1532 return NULL;
1533 return parser->m_attInfo;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001534}
1535#endif
1536
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001537void XMLCALL
1538XML_SetElementHandler(XML_Parser parser,
1539 XML_StartElementHandler start,
1540 XML_EndElementHandler end)
1541{
Elliott Hughes72472942018-01-10 08:36:10 -08001542 if (parser == NULL)
1543 return;
1544 parser->m_startElementHandler = start;
1545 parser->m_endElementHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001546}
1547
1548void XMLCALL
1549XML_SetStartElementHandler(XML_Parser parser,
1550 XML_StartElementHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001551 if (parser != NULL)
1552 parser->m_startElementHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001553}
1554
1555void XMLCALL
1556XML_SetEndElementHandler(XML_Parser parser,
1557 XML_EndElementHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001558 if (parser != NULL)
1559 parser->m_endElementHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001560}
1561
1562void XMLCALL
1563XML_SetCharacterDataHandler(XML_Parser parser,
1564 XML_CharacterDataHandler handler)
1565{
Elliott Hughes72472942018-01-10 08:36:10 -08001566 if (parser != NULL)
1567 parser->m_characterDataHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001568}
1569
1570void XMLCALL
1571XML_SetProcessingInstructionHandler(XML_Parser parser,
1572 XML_ProcessingInstructionHandler handler)
1573{
Elliott Hughes72472942018-01-10 08:36:10 -08001574 if (parser != NULL)
1575 parser->m_processingInstructionHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001576}
1577
1578void XMLCALL
1579XML_SetCommentHandler(XML_Parser parser,
1580 XML_CommentHandler handler)
1581{
Elliott Hughes72472942018-01-10 08:36:10 -08001582 if (parser != NULL)
1583 parser->m_commentHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001584}
1585
1586void XMLCALL
1587XML_SetCdataSectionHandler(XML_Parser parser,
1588 XML_StartCdataSectionHandler start,
1589 XML_EndCdataSectionHandler end)
1590{
Elliott Hughes72472942018-01-10 08:36:10 -08001591 if (parser == NULL)
1592 return;
1593 parser->m_startCdataSectionHandler = start;
1594 parser->m_endCdataSectionHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001595}
1596
1597void XMLCALL
1598XML_SetStartCdataSectionHandler(XML_Parser parser,
1599 XML_StartCdataSectionHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001600 if (parser != NULL)
1601 parser->m_startCdataSectionHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001602}
1603
1604void XMLCALL
1605XML_SetEndCdataSectionHandler(XML_Parser parser,
1606 XML_EndCdataSectionHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001607 if (parser != NULL)
1608 parser->m_endCdataSectionHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001609}
1610
1611void XMLCALL
1612XML_SetDefaultHandler(XML_Parser parser,
1613 XML_DefaultHandler handler)
1614{
Elliott Hughes72472942018-01-10 08:36:10 -08001615 if (parser == NULL)
1616 return;
1617 parser->m_defaultHandler = handler;
1618 parser->m_defaultExpandInternalEntities = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001619}
1620
1621void XMLCALL
1622XML_SetDefaultHandlerExpand(XML_Parser parser,
1623 XML_DefaultHandler handler)
1624{
Elliott Hughes72472942018-01-10 08:36:10 -08001625 if (parser == NULL)
1626 return;
1627 parser->m_defaultHandler = handler;
1628 parser->m_defaultExpandInternalEntities = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001629}
1630
1631void XMLCALL
1632XML_SetDoctypeDeclHandler(XML_Parser parser,
1633 XML_StartDoctypeDeclHandler start,
1634 XML_EndDoctypeDeclHandler end)
1635{
Elliott Hughes72472942018-01-10 08:36:10 -08001636 if (parser == NULL)
1637 return;
1638 parser->m_startDoctypeDeclHandler = start;
1639 parser->m_endDoctypeDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001640}
1641
1642void XMLCALL
1643XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1644 XML_StartDoctypeDeclHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001645 if (parser != NULL)
1646 parser->m_startDoctypeDeclHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001647}
1648
1649void XMLCALL
1650XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1651 XML_EndDoctypeDeclHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001652 if (parser != NULL)
1653 parser->m_endDoctypeDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001654}
1655
1656void XMLCALL
1657XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1658 XML_UnparsedEntityDeclHandler handler)
1659{
Elliott Hughes72472942018-01-10 08:36:10 -08001660 if (parser != NULL)
1661 parser->m_unparsedEntityDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001662}
1663
1664void XMLCALL
1665XML_SetNotationDeclHandler(XML_Parser parser,
1666 XML_NotationDeclHandler handler)
1667{
Elliott Hughes72472942018-01-10 08:36:10 -08001668 if (parser != NULL)
1669 parser->m_notationDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001670}
1671
1672void XMLCALL
1673XML_SetNamespaceDeclHandler(XML_Parser parser,
1674 XML_StartNamespaceDeclHandler start,
1675 XML_EndNamespaceDeclHandler end)
1676{
Elliott Hughes72472942018-01-10 08:36:10 -08001677 if (parser == NULL)
1678 return;
1679 parser->m_startNamespaceDeclHandler = start;
1680 parser->m_endNamespaceDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001681}
1682
1683void XMLCALL
1684XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1685 XML_StartNamespaceDeclHandler start) {
Elliott Hughes72472942018-01-10 08:36:10 -08001686 if (parser != NULL)
1687 parser->m_startNamespaceDeclHandler = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001688}
1689
1690void XMLCALL
1691XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1692 XML_EndNamespaceDeclHandler end) {
Elliott Hughes72472942018-01-10 08:36:10 -08001693 if (parser != NULL)
1694 parser->m_endNamespaceDeclHandler = end;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001695}
1696
1697void XMLCALL
1698XML_SetNotStandaloneHandler(XML_Parser parser,
1699 XML_NotStandaloneHandler handler)
1700{
Elliott Hughes72472942018-01-10 08:36:10 -08001701 if (parser != NULL)
1702 parser->m_notStandaloneHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001703}
1704
1705void XMLCALL
1706XML_SetExternalEntityRefHandler(XML_Parser parser,
1707 XML_ExternalEntityRefHandler handler)
1708{
Elliott Hughes72472942018-01-10 08:36:10 -08001709 if (parser != NULL)
1710 parser->m_externalEntityRefHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001711}
1712
1713void XMLCALL
1714XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1715{
Elliott Hughes72472942018-01-10 08:36:10 -08001716 if (parser == NULL)
1717 return;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001718 if (arg)
Elliott Hughes72472942018-01-10 08:36:10 -08001719 parser->m_externalEntityRefHandlerArg = (XML_Parser)arg;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001720 else
Elliott Hughes72472942018-01-10 08:36:10 -08001721 parser->m_externalEntityRefHandlerArg = parser;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001722}
1723
1724void XMLCALL
1725XML_SetSkippedEntityHandler(XML_Parser parser,
1726 XML_SkippedEntityHandler handler)
1727{
Elliott Hughes72472942018-01-10 08:36:10 -08001728 if (parser != NULL)
1729 parser->m_skippedEntityHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001730}
1731
1732void XMLCALL
1733XML_SetUnknownEncodingHandler(XML_Parser parser,
1734 XML_UnknownEncodingHandler handler,
1735 void *data)
1736{
Elliott Hughes72472942018-01-10 08:36:10 -08001737 if (parser == NULL)
1738 return;
1739 parser->m_unknownEncodingHandler = handler;
1740 parser->m_unknownEncodingHandlerData = data;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001741}
1742
1743void XMLCALL
1744XML_SetElementDeclHandler(XML_Parser parser,
1745 XML_ElementDeclHandler eldecl)
1746{
Elliott Hughes72472942018-01-10 08:36:10 -08001747 if (parser != NULL)
1748 parser->m_elementDeclHandler = eldecl;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001749}
1750
1751void XMLCALL
1752XML_SetAttlistDeclHandler(XML_Parser parser,
1753 XML_AttlistDeclHandler attdecl)
1754{
Elliott Hughes72472942018-01-10 08:36:10 -08001755 if (parser != NULL)
1756 parser->m_attlistDeclHandler = attdecl;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001757}
1758
1759void XMLCALL
1760XML_SetEntityDeclHandler(XML_Parser parser,
1761 XML_EntityDeclHandler handler)
1762{
Elliott Hughes72472942018-01-10 08:36:10 -08001763 if (parser != NULL)
1764 parser->m_entityDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001765}
1766
1767void XMLCALL
1768XML_SetXmlDeclHandler(XML_Parser parser,
1769 XML_XmlDeclHandler handler) {
Elliott Hughes72472942018-01-10 08:36:10 -08001770 if (parser != NULL)
1771 parser->m_xmlDeclHandler = handler;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001772}
1773
1774int XMLCALL
1775XML_SetParamEntityParsing(XML_Parser parser,
1776 enum XML_ParamEntityParsing peParsing)
1777{
Elliott Hughes72472942018-01-10 08:36:10 -08001778 if (parser == NULL)
1779 return 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001780 /* block after XML_Parse()/XML_ParseBuffer() has been called */
Elliott Hughes72472942018-01-10 08:36:10 -08001781 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001782 return 0;
1783#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08001784 parser->m_paramEntityParsing = peParsing;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001785 return 1;
1786#else
1787 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1788#endif
1789}
1790
Elliott Hughes35e432d2012-09-09 14:23:38 -07001791int XMLCALL
1792XML_SetHashSalt(XML_Parser parser,
1793 unsigned long hash_salt)
1794{
Elliott Hughes72472942018-01-10 08:36:10 -08001795 if (parser == NULL)
Elliott Hughes35e432d2012-09-09 14:23:38 -07001796 return 0;
Elliott Hughes72472942018-01-10 08:36:10 -08001797 if (parser->m_parentParser)
1798 return XML_SetHashSalt(parser->m_parentParser, hash_salt);
1799 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1800 if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
1801 return 0;
1802 parser->m_hash_secret_salt = hash_salt;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001803 return 1;
1804}
1805
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001806enum XML_Status XMLCALL
1807XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1808{
Elliott Hughes72472942018-01-10 08:36:10 -08001809 if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
1810 if (parser != NULL)
1811 parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
1812 return XML_STATUS_ERROR;
1813 }
1814 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001815 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08001816 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001817 return XML_STATUS_ERROR;
1818 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08001819 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001820 return XML_STATUS_ERROR;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001821 case XML_INITIALIZED:
Elliott Hughes72472942018-01-10 08:36:10 -08001822 if (parser->m_parentParser == NULL && !startParsing(parser)) {
1823 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001824 return XML_STATUS_ERROR;
1825 }
Elliott Hughesaaec48e2018-08-16 16:29:01 -07001826 /* fall through */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001827 default:
Elliott Hughes72472942018-01-10 08:36:10 -08001828 parser->m_parsingStatus.parsing = XML_PARSING;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001829 }
1830
1831 if (len == 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08001832 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001833 if (!isFinal)
1834 return XML_STATUS_OK;
Elliott Hughes72472942018-01-10 08:36:10 -08001835 parser->m_positionPtr = parser->m_bufferPtr;
1836 parser->m_parseEndPtr = parser->m_bufferEnd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001837
1838 /* If data are left over from last buffer, and we now know that these
1839 data are the final chunk of input, then we have to check them again
1840 to detect errors based on that fact.
1841 */
Elliott Hughes72472942018-01-10 08:36:10 -08001842 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 -08001843
Elliott Hughes72472942018-01-10 08:36:10 -08001844 if (parser->m_errorCode == XML_ERROR_NONE) {
1845 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001846 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08001847 /* It is hard to be certain, but it seems that this case
1848 * cannot occur. This code is cleaning up a previous parse
1849 * with no new data (since len == 0). Changing the parsing
1850 * state requires getting to execute a handler function, and
1851 * there doesn't seem to be an opportunity for that while in
1852 * this circumstance.
1853 *
1854 * Given the uncertainty, we retain the code but exclude it
1855 * from coverage tests.
1856 *
1857 * LCOV_EXCL_START
1858 */
1859 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
1860 parser->m_positionPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001861 return XML_STATUS_SUSPENDED;
Elliott Hughes72472942018-01-10 08:36:10 -08001862 /* LCOV_EXCL_STOP */
Elliott Hughes35e432d2012-09-09 14:23:38 -07001863 case XML_INITIALIZED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001864 case XML_PARSING:
Elliott Hughes72472942018-01-10 08:36:10 -08001865 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001866 /* fall through */
1867 default:
1868 return XML_STATUS_OK;
1869 }
1870 }
Elliott Hughes72472942018-01-10 08:36:10 -08001871 parser->m_eventEndPtr = parser->m_eventPtr;
1872 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001873 return XML_STATUS_ERROR;
1874 }
1875#ifndef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08001876 else if (parser->m_bufferPtr == parser->m_bufferEnd) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001877 const char *end;
1878 int nLeftOver;
Paul Duffinc05e0322016-05-04 10:42:31 +01001879 enum XML_Status result;
Elliott Hughes72472942018-01-10 08:36:10 -08001880 /* Detect overflow (a+b > MAX <==> b > MAX-a) */
1881 if (len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) {
1882 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1883 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1884 parser->m_processor = errorProcessor;
1885 return XML_STATUS_ERROR;
1886 }
1887 parser->m_parseEndByteIndex += len;
1888 parser->m_positionPtr = s;
1889 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001890
Elliott Hughes72472942018-01-10 08:36:10 -08001891 parser->m_errorCode = parser->m_processor(parser, s, parser->m_parseEndPtr = s + len, &end);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001892
Elliott Hughes72472942018-01-10 08:36:10 -08001893 if (parser->m_errorCode != XML_ERROR_NONE) {
1894 parser->m_eventEndPtr = parser->m_eventPtr;
1895 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001896 return XML_STATUS_ERROR;
1897 }
1898 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001899 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001900 case XML_SUSPENDED:
1901 result = XML_STATUS_SUSPENDED;
1902 break;
1903 case XML_INITIALIZED:
1904 case XML_PARSING:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001905 if (isFinal) {
Elliott Hughes72472942018-01-10 08:36:10 -08001906 parser->m_parsingStatus.parsing = XML_FINISHED;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001907 return XML_STATUS_OK;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001908 }
Elliott Hughes35e432d2012-09-09 14:23:38 -07001909 /* fall through */
1910 default:
1911 result = XML_STATUS_OK;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001912 }
1913 }
1914
Elliott Hughes72472942018-01-10 08:36:10 -08001915 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end, &parser->m_position);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001916 nLeftOver = s + len - end;
1917 if (nLeftOver) {
Elliott Hughes72472942018-01-10 08:36:10 -08001918 if (parser->m_buffer == NULL || nLeftOver > parser->m_bufferLim - parser->m_buffer) {
1919 /* avoid _signed_ integer overflow */
1920 char *temp = NULL;
1921 const int bytesToAllocate = (int)((unsigned)len * 2U);
1922 if (bytesToAllocate > 0) {
1923 temp = (char *)REALLOC(parser, parser->m_buffer, bytesToAllocate);
1924 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001925 if (temp == NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08001926 parser->m_errorCode = XML_ERROR_NO_MEMORY;
1927 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
1928 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001929 return XML_STATUS_ERROR;
1930 }
Elliott Hughes72472942018-01-10 08:36:10 -08001931 parser->m_buffer = temp;
1932 parser->m_bufferLim = parser->m_buffer + bytesToAllocate;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001933 }
Elliott Hughes72472942018-01-10 08:36:10 -08001934 memcpy(parser->m_buffer, end, nLeftOver);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001935 }
Elliott Hughes72472942018-01-10 08:36:10 -08001936 parser->m_bufferPtr = parser->m_buffer;
1937 parser->m_bufferEnd = parser->m_buffer + nLeftOver;
1938 parser->m_positionPtr = parser->m_bufferPtr;
1939 parser->m_parseEndPtr = parser->m_bufferEnd;
1940 parser->m_eventPtr = parser->m_bufferPtr;
1941 parser->m_eventEndPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001942 return result;
1943 }
1944#endif /* not defined XML_CONTEXT_BYTES */
1945 else {
1946 void *buff = XML_GetBuffer(parser, len);
1947 if (buff == NULL)
1948 return XML_STATUS_ERROR;
1949 else {
1950 memcpy(buff, s, len);
1951 return XML_ParseBuffer(parser, len, isFinal);
1952 }
1953 }
1954}
1955
1956enum XML_Status XMLCALL
1957XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
1958{
1959 const char *start;
1960 enum XML_Status result = XML_STATUS_OK;
1961
Elliott Hughes72472942018-01-10 08:36:10 -08001962 if (parser == NULL)
1963 return XML_STATUS_ERROR;
1964 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001965 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08001966 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001967 return XML_STATUS_ERROR;
1968 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08001969 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001970 return XML_STATUS_ERROR;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001971 case XML_INITIALIZED:
Elliott Hughes72472942018-01-10 08:36:10 -08001972 if (parser->m_parentParser == NULL && !startParsing(parser)) {
1973 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07001974 return XML_STATUS_ERROR;
1975 }
Elliott Hughesaaec48e2018-08-16 16:29:01 -07001976 /* fall through */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001977 default:
Elliott Hughes72472942018-01-10 08:36:10 -08001978 parser->m_parsingStatus.parsing = XML_PARSING;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001979 }
1980
Elliott Hughes72472942018-01-10 08:36:10 -08001981 start = parser->m_bufferPtr;
1982 parser->m_positionPtr = start;
1983 parser->m_bufferEnd += len;
1984 parser->m_parseEndPtr = parser->m_bufferEnd;
1985 parser->m_parseEndByteIndex += len;
1986 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001987
Elliott Hughes72472942018-01-10 08:36:10 -08001988 parser->m_errorCode = parser->m_processor(parser, start, parser->m_parseEndPtr, &parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001989
Elliott Hughes72472942018-01-10 08:36:10 -08001990 if (parser->m_errorCode != XML_ERROR_NONE) {
1991 parser->m_eventEndPtr = parser->m_eventPtr;
1992 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001993 return XML_STATUS_ERROR;
1994 }
1995 else {
Elliott Hughes72472942018-01-10 08:36:10 -08001996 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08001997 case XML_SUSPENDED:
1998 result = XML_STATUS_SUSPENDED;
1999 break;
Elliott Hughes35e432d2012-09-09 14:23:38 -07002000 case XML_INITIALIZED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002001 case XML_PARSING:
2002 if (isFinal) {
Elliott Hughes72472942018-01-10 08:36:10 -08002003 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002004 return result;
2005 }
2006 default: ; /* should not happen */
2007 }
2008 }
2009
Elliott Hughes72472942018-01-10 08:36:10 -08002010 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
2011 parser->m_positionPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002012 return result;
2013}
2014
2015void * XMLCALL
2016XML_GetBuffer(XML_Parser parser, int len)
2017{
Elliott Hughes72472942018-01-10 08:36:10 -08002018 if (parser == NULL)
2019 return NULL;
Paul Duffinc05e0322016-05-04 10:42:31 +01002020 if (len < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002021 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Paul Duffinc05e0322016-05-04 10:42:31 +01002022 return NULL;
2023 }
Elliott Hughes72472942018-01-10 08:36:10 -08002024 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002025 case XML_SUSPENDED:
Elliott Hughes72472942018-01-10 08:36:10 -08002026 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002027 return NULL;
2028 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08002029 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002030 return NULL;
2031 default: ;
2032 }
2033
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002034 if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)) {
Paul Duffinba34a0c2017-02-27 14:40:16 +00002035#ifdef XML_CONTEXT_BYTES
2036 int keep;
2037#endif /* defined XML_CONTEXT_BYTES */
2038 /* Do not invoke signed arithmetic overflow: */
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002039 int neededSize = (int) ((unsigned)len +
2040 (unsigned)EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd,
2041 parser->m_bufferPtr));
Paul Duffinc05e0322016-05-04 10:42:31 +01002042 if (neededSize < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002043 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Paul Duffinc05e0322016-05-04 10:42:31 +01002044 return NULL;
2045 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002046#ifdef XML_CONTEXT_BYTES
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002047 keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002048 if (keep > XML_CONTEXT_BYTES)
2049 keep = XML_CONTEXT_BYTES;
2050 neededSize += keep;
2051#endif /* defined XML_CONTEXT_BYTES */
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002052 if (neededSize <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002053#ifdef XML_CONTEXT_BYTES
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002054 if (keep < EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)) {
2055 int offset = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer) - keep;
2056 /* The buffer pointers cannot be NULL here; we have at least some bytes in the buffer */
Elliott Hughes72472942018-01-10 08:36:10 -08002057 memmove(parser->m_buffer, &parser->m_buffer[offset], parser->m_bufferEnd - parser->m_bufferPtr + keep);
2058 parser->m_bufferEnd -= offset;
2059 parser->m_bufferPtr -= offset;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002060 }
2061#else
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002062 if (parser->m_buffer && parser->m_bufferPtr) {
2063 memmove(parser->m_buffer, parser->m_bufferPtr,
2064 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
2065 parser->m_bufferEnd = parser->m_buffer +
2066 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
2067 parser->m_bufferPtr = parser->m_buffer;
2068 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002069#endif /* not defined XML_CONTEXT_BYTES */
2070 }
2071 else {
2072 char *newBuf;
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002073 int bufferSize = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002074 if (bufferSize == 0)
2075 bufferSize = INIT_BUFFER_SIZE;
2076 do {
Paul Duffinba34a0c2017-02-27 14:40:16 +00002077 /* Do not invoke signed arithmetic overflow: */
2078 bufferSize = (int) (2U * (unsigned) bufferSize);
Paul Duffinc05e0322016-05-04 10:42:31 +01002079 } while (bufferSize < neededSize && bufferSize > 0);
2080 if (bufferSize <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002081 parser->m_errorCode = XML_ERROR_NO_MEMORY;
Paul Duffinc05e0322016-05-04 10:42:31 +01002082 return NULL;
2083 }
Elliott Hughes72472942018-01-10 08:36:10 -08002084 newBuf = (char *)MALLOC(parser, bufferSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002085 if (newBuf == 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002086 parser->m_errorCode = XML_ERROR_NO_MEMORY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002087 return NULL;
2088 }
Elliott Hughes72472942018-01-10 08:36:10 -08002089 parser->m_bufferLim = newBuf + bufferSize;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002090#ifdef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08002091 if (parser->m_bufferPtr) {
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002092 int keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002093 if (keep > XML_CONTEXT_BYTES)
2094 keep = XML_CONTEXT_BYTES;
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002095 memcpy(newBuf, &parser->m_bufferPtr[-keep],
2096 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) + keep);
Elliott Hughes72472942018-01-10 08:36:10 -08002097 FREE(parser, parser->m_buffer);
2098 parser->m_buffer = newBuf;
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002099 parser->m_bufferEnd = parser->m_buffer +
2100 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) + keep;
Elliott Hughes72472942018-01-10 08:36:10 -08002101 parser->m_bufferPtr = parser->m_buffer + keep;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002102 }
2103 else {
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002104 /* This must be a brand new buffer with no data in it yet */
2105 parser->m_bufferEnd = newBuf;
Elliott Hughes72472942018-01-10 08:36:10 -08002106 parser->m_bufferPtr = parser->m_buffer = newBuf;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002107 }
2108#else
Elliott Hughes72472942018-01-10 08:36:10 -08002109 if (parser->m_bufferPtr) {
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002110 memcpy(newBuf, parser->m_bufferPtr,
2111 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
Elliott Hughes72472942018-01-10 08:36:10 -08002112 FREE(parser, parser->m_buffer);
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002113 parser->m_bufferEnd = newBuf +
2114 EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002115 }
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002116 else {
2117 /* This must be a brand new buffer with no data in it yet */
2118 parser->m_bufferEnd = newBuf;
2119 }
Elliott Hughes72472942018-01-10 08:36:10 -08002120 parser->m_bufferPtr = parser->m_buffer = newBuf;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002121#endif /* not defined XML_CONTEXT_BYTES */
2122 }
Elliott Hughes72472942018-01-10 08:36:10 -08002123 parser->m_eventPtr = parser->m_eventEndPtr = NULL;
2124 parser->m_positionPtr = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002125 }
Elliott Hughes72472942018-01-10 08:36:10 -08002126 return parser->m_bufferEnd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002127}
2128
2129enum XML_Status XMLCALL
2130XML_StopParser(XML_Parser parser, XML_Bool resumable)
2131{
Elliott Hughes72472942018-01-10 08:36:10 -08002132 if (parser == NULL)
2133 return XML_STATUS_ERROR;
2134 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002135 case XML_SUSPENDED:
2136 if (resumable) {
Elliott Hughes72472942018-01-10 08:36:10 -08002137 parser->m_errorCode = XML_ERROR_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002138 return XML_STATUS_ERROR;
2139 }
Elliott Hughes72472942018-01-10 08:36:10 -08002140 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002141 break;
2142 case XML_FINISHED:
Elliott Hughes72472942018-01-10 08:36:10 -08002143 parser->m_errorCode = XML_ERROR_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002144 return XML_STATUS_ERROR;
2145 default:
2146 if (resumable) {
2147#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08002148 if (parser->m_isParamEntity) {
2149 parser->m_errorCode = XML_ERROR_SUSPEND_PE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002150 return XML_STATUS_ERROR;
2151 }
2152#endif
Elliott Hughes72472942018-01-10 08:36:10 -08002153 parser->m_parsingStatus.parsing = XML_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002154 }
2155 else
Elliott Hughes72472942018-01-10 08:36:10 -08002156 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002157 }
2158 return XML_STATUS_OK;
2159}
2160
2161enum XML_Status XMLCALL
2162XML_ResumeParser(XML_Parser parser)
2163{
2164 enum XML_Status result = XML_STATUS_OK;
2165
Elliott Hughes72472942018-01-10 08:36:10 -08002166 if (parser == NULL)
2167 return XML_STATUS_ERROR;
2168 if (parser->m_parsingStatus.parsing != XML_SUSPENDED) {
2169 parser->m_errorCode = XML_ERROR_NOT_SUSPENDED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002170 return XML_STATUS_ERROR;
2171 }
Elliott Hughes72472942018-01-10 08:36:10 -08002172 parser->m_parsingStatus.parsing = XML_PARSING;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002173
Elliott Hughes72472942018-01-10 08:36:10 -08002174 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 -08002175
Elliott Hughes72472942018-01-10 08:36:10 -08002176 if (parser->m_errorCode != XML_ERROR_NONE) {
2177 parser->m_eventEndPtr = parser->m_eventPtr;
2178 parser->m_processor = errorProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002179 return XML_STATUS_ERROR;
2180 }
2181 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002182 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002183 case XML_SUSPENDED:
2184 result = XML_STATUS_SUSPENDED;
2185 break;
Elliott Hughes35e432d2012-09-09 14:23:38 -07002186 case XML_INITIALIZED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002187 case XML_PARSING:
Elliott Hughes72472942018-01-10 08:36:10 -08002188 if (parser->m_parsingStatus.finalBuffer) {
2189 parser->m_parsingStatus.parsing = XML_FINISHED;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002190 return result;
2191 }
2192 default: ;
2193 }
2194 }
2195
Elliott Hughes72472942018-01-10 08:36:10 -08002196 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
2197 parser->m_positionPtr = parser->m_bufferPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002198 return result;
2199}
2200
2201void XMLCALL
2202XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
2203{
Elliott Hughes72472942018-01-10 08:36:10 -08002204 if (parser == NULL)
2205 return;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002206 assert(status != NULL);
2207 *status = parser->m_parsingStatus;
2208}
2209
2210enum XML_Error XMLCALL
2211XML_GetErrorCode(XML_Parser parser)
2212{
Elliott Hughes72472942018-01-10 08:36:10 -08002213 if (parser == NULL)
2214 return XML_ERROR_INVALID_ARGUMENT;
2215 return parser->m_errorCode;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002216}
2217
2218XML_Index XMLCALL
2219XML_GetCurrentByteIndex(XML_Parser parser)
2220{
Elliott Hughes72472942018-01-10 08:36:10 -08002221 if (parser == NULL)
2222 return -1;
2223 if (parser->m_eventPtr)
2224 return (XML_Index)(parser->m_parseEndByteIndex - (parser->m_parseEndPtr - parser->m_eventPtr));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002225 return -1;
2226}
2227
2228int XMLCALL
2229XML_GetCurrentByteCount(XML_Parser parser)
2230{
Elliott Hughes72472942018-01-10 08:36:10 -08002231 if (parser == NULL)
2232 return 0;
2233 if (parser->m_eventEndPtr && parser->m_eventPtr)
2234 return (int)(parser->m_eventEndPtr - parser->m_eventPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002235 return 0;
2236}
2237
2238const char * XMLCALL
2239XML_GetInputContext(XML_Parser parser, int *offset, int *size)
2240{
2241#ifdef XML_CONTEXT_BYTES
Elliott Hughes72472942018-01-10 08:36:10 -08002242 if (parser == NULL)
2243 return NULL;
2244 if (parser->m_eventPtr && parser->m_buffer) {
2245 if (offset != NULL)
2246 *offset = (int)(parser->m_eventPtr - parser->m_buffer);
2247 if (size != NULL)
2248 *size = (int)(parser->m_bufferEnd - parser->m_buffer);
2249 return parser->m_buffer;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002250 }
Elliott Hughes72472942018-01-10 08:36:10 -08002251#else
2252 (void)parser;
2253 (void)offset;
2254 (void)size;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002255#endif /* defined XML_CONTEXT_BYTES */
2256 return (char *) 0;
2257}
2258
2259XML_Size XMLCALL
2260XML_GetCurrentLineNumber(XML_Parser parser)
2261{
Elliott Hughes72472942018-01-10 08:36:10 -08002262 if (parser == NULL)
2263 return 0;
2264 if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2265 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_eventPtr, &parser->m_position);
2266 parser->m_positionPtr = parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002267 }
Elliott Hughes72472942018-01-10 08:36:10 -08002268 return parser->m_position.lineNumber + 1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002269}
2270
2271XML_Size XMLCALL
2272XML_GetCurrentColumnNumber(XML_Parser parser)
2273{
Elliott Hughes72472942018-01-10 08:36:10 -08002274 if (parser == NULL)
2275 return 0;
2276 if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
2277 XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_eventPtr, &parser->m_position);
2278 parser->m_positionPtr = parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002279 }
Elliott Hughes72472942018-01-10 08:36:10 -08002280 return parser->m_position.columnNumber;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002281}
2282
2283void XMLCALL
2284XML_FreeContentModel(XML_Parser parser, XML_Content *model)
2285{
Elliott Hughes72472942018-01-10 08:36:10 -08002286 if (parser != NULL)
2287 FREE(parser, model);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002288}
2289
2290void * XMLCALL
2291XML_MemMalloc(XML_Parser parser, size_t size)
2292{
Elliott Hughes72472942018-01-10 08:36:10 -08002293 if (parser == NULL)
2294 return NULL;
2295 return MALLOC(parser, size);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002296}
2297
2298void * XMLCALL
2299XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
2300{
Elliott Hughes72472942018-01-10 08:36:10 -08002301 if (parser == NULL)
2302 return NULL;
2303 return REALLOC(parser, ptr, size);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002304}
2305
2306void XMLCALL
2307XML_MemFree(XML_Parser parser, void *ptr)
2308{
Elliott Hughes72472942018-01-10 08:36:10 -08002309 if (parser != NULL)
2310 FREE(parser, ptr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002311}
2312
2313void XMLCALL
2314XML_DefaultCurrent(XML_Parser parser)
2315{
Elliott Hughes72472942018-01-10 08:36:10 -08002316 if (parser == NULL)
2317 return;
2318 if (parser->m_defaultHandler) {
2319 if (parser->m_openInternalEntities)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002320 reportDefault(parser,
Elliott Hughes72472942018-01-10 08:36:10 -08002321 parser->m_internalEncoding,
2322 parser->m_openInternalEntities->internalEventPtr,
2323 parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002324 else
Elliott Hughes72472942018-01-10 08:36:10 -08002325 reportDefault(parser, parser->m_encoding, parser->m_eventPtr, parser->m_eventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002326 }
2327}
2328
2329const XML_LChar * XMLCALL
2330XML_ErrorString(enum XML_Error code)
2331{
Elliott Hughes72472942018-01-10 08:36:10 -08002332 switch (code) {
2333 case XML_ERROR_NONE:
2334 return NULL;
2335 case XML_ERROR_NO_MEMORY:
2336 return XML_L("out of memory");
2337 case XML_ERROR_SYNTAX:
2338 return XML_L("syntax error");
2339 case XML_ERROR_NO_ELEMENTS:
2340 return XML_L("no element found");
2341 case XML_ERROR_INVALID_TOKEN:
2342 return XML_L("not well-formed (invalid token)");
2343 case XML_ERROR_UNCLOSED_TOKEN:
2344 return XML_L("unclosed token");
2345 case XML_ERROR_PARTIAL_CHAR:
2346 return XML_L("partial character");
2347 case XML_ERROR_TAG_MISMATCH:
2348 return XML_L("mismatched tag");
2349 case XML_ERROR_DUPLICATE_ATTRIBUTE:
2350 return XML_L("duplicate attribute");
2351 case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
2352 return XML_L("junk after document element");
2353 case XML_ERROR_PARAM_ENTITY_REF:
2354 return XML_L("illegal parameter entity reference");
2355 case XML_ERROR_UNDEFINED_ENTITY:
2356 return XML_L("undefined entity");
2357 case XML_ERROR_RECURSIVE_ENTITY_REF:
2358 return XML_L("recursive entity reference");
2359 case XML_ERROR_ASYNC_ENTITY:
2360 return XML_L("asynchronous entity");
2361 case XML_ERROR_BAD_CHAR_REF:
2362 return XML_L("reference to invalid character number");
2363 case XML_ERROR_BINARY_ENTITY_REF:
2364 return XML_L("reference to binary entity");
2365 case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
2366 return XML_L("reference to external entity in attribute");
2367 case XML_ERROR_MISPLACED_XML_PI:
2368 return XML_L("XML or text declaration not at start of entity");
2369 case XML_ERROR_UNKNOWN_ENCODING:
2370 return XML_L("unknown encoding");
2371 case XML_ERROR_INCORRECT_ENCODING:
2372 return XML_L("encoding specified in XML declaration is incorrect");
2373 case XML_ERROR_UNCLOSED_CDATA_SECTION:
2374 return XML_L("unclosed CDATA section");
2375 case XML_ERROR_EXTERNAL_ENTITY_HANDLING:
2376 return XML_L("error in processing external entity reference");
2377 case XML_ERROR_NOT_STANDALONE:
2378 return XML_L("document is not standalone");
2379 case XML_ERROR_UNEXPECTED_STATE:
2380 return XML_L("unexpected parser state - please send a bug report");
2381 case XML_ERROR_ENTITY_DECLARED_IN_PE:
2382 return XML_L("entity declared in parameter entity");
2383 case XML_ERROR_FEATURE_REQUIRES_XML_DTD:
2384 return XML_L("requested feature requires XML_DTD support in Expat");
2385 case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:
2386 return XML_L("cannot change setting once parsing has begun");
2387 /* Added in 1.95.7. */
2388 case XML_ERROR_UNBOUND_PREFIX:
2389 return XML_L("unbound prefix");
2390 /* Added in 1.95.8. */
2391 case XML_ERROR_UNDECLARING_PREFIX:
2392 return XML_L("must not undeclare prefix");
2393 case XML_ERROR_INCOMPLETE_PE:
2394 return XML_L("incomplete markup in parameter entity");
2395 case XML_ERROR_XML_DECL:
2396 return XML_L("XML declaration not well-formed");
2397 case XML_ERROR_TEXT_DECL:
2398 return XML_L("text declaration not well-formed");
2399 case XML_ERROR_PUBLICID:
2400 return XML_L("illegal character(s) in public id");
2401 case XML_ERROR_SUSPENDED:
2402 return XML_L("parser suspended");
2403 case XML_ERROR_NOT_SUSPENDED:
2404 return XML_L("parser not suspended");
2405 case XML_ERROR_ABORTED:
2406 return XML_L("parsing aborted");
2407 case XML_ERROR_FINISHED:
2408 return XML_L("parsing finished");
2409 case XML_ERROR_SUSPEND_PE:
2410 return XML_L("cannot suspend in external parameter entity");
2411 /* Added in 2.0.0. */
2412 case XML_ERROR_RESERVED_PREFIX_XML:
2413 return XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name");
2414 case XML_ERROR_RESERVED_PREFIX_XMLNS:
2415 return XML_L("reserved prefix (xmlns) must not be declared or undeclared");
2416 case XML_ERROR_RESERVED_NAMESPACE_URI:
2417 return XML_L("prefix must not be bound to one of the reserved namespace names");
2418 /* Added in 2.2.5. */
2419 case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
2420 return XML_L("invalid argument");
2421 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002422 return NULL;
2423}
2424
2425const XML_LChar * XMLCALL
2426XML_ExpatVersion(void) {
2427
2428 /* V1 is used to string-ize the version number. However, it would
2429 string-ize the actual version macro *names* unless we get them
2430 substituted before being passed to V1. CPP is defined to expand
2431 a macro, then rescan for more expansions. Thus, we use V2 to expand
2432 the version macros, then CPP will expand the resulting V1() macro
2433 with the correct numerals. */
2434 /* ### I'm assuming cpp is portable in this respect... */
2435
2436#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
2437#define V2(a,b,c) XML_L("expat_")V1(a,b,c)
2438
2439 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
2440
2441#undef V1
2442#undef V2
2443}
2444
2445XML_Expat_Version XMLCALL
2446XML_ExpatVersionInfo(void)
2447{
2448 XML_Expat_Version version;
2449
2450 version.major = XML_MAJOR_VERSION;
2451 version.minor = XML_MINOR_VERSION;
2452 version.micro = XML_MICRO_VERSION;
2453
2454 return version;
2455}
2456
2457const XML_Feature * XMLCALL
2458XML_GetFeatureList(void)
2459{
2460 static const XML_Feature features[] = {
2461 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2462 sizeof(XML_Char)},
2463 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2464 sizeof(XML_LChar)},
2465#ifdef XML_UNICODE
2466 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2467#endif
2468#ifdef XML_UNICODE_WCHAR_T
2469 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2470#endif
2471#ifdef XML_DTD
2472 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2473#endif
2474#ifdef XML_CONTEXT_BYTES
2475 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2476 XML_CONTEXT_BYTES},
2477#endif
2478#ifdef XML_MIN_SIZE
2479 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2480#endif
2481#ifdef XML_NS
2482 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2483#endif
Elliott Hughesd07d5a72009-09-25 16:04:37 -07002484#ifdef XML_LARGE_SIZE
2485 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
Elliott Hughes35e432d2012-09-09 14:23:38 -07002486#endif
2487#ifdef XML_ATTR_INFO
2488 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2489#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002490 {XML_FEATURE_END, NULL, 0}
2491 };
2492
2493 return features;
2494}
2495
2496/* Initially tag->rawName always points into the parse buffer;
2497 for those TAG instances opened while the current parse buffer was
2498 processed, and not yet closed, we need to store tag->rawName in a more
2499 permanent location, since the parse buffer is about to be discarded.
2500*/
2501static XML_Bool
2502storeRawNames(XML_Parser parser)
2503{
Elliott Hughes72472942018-01-10 08:36:10 -08002504 TAG *tag = parser->m_tagStack;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002505 while (tag) {
2506 int bufSize;
2507 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2508 char *rawNameBuf = tag->buf + nameLen;
Elliott Hughes72472942018-01-10 08:36:10 -08002509 /* Stop if already stored. Since m_tagStack is a stack, we can stop
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002510 at the first entry that has already been copied; everything
2511 below it in the stack is already been accounted for in a
2512 previous call to this function.
2513 */
2514 if (tag->rawName == rawNameBuf)
2515 break;
2516 /* For re-use purposes we need to ensure that the
2517 size of tag->buf is a multiple of sizeof(XML_Char).
2518 */
2519 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2520 if (bufSize > tag->bufEnd - tag->buf) {
Elliott Hughes72472942018-01-10 08:36:10 -08002521 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002522 if (temp == NULL)
2523 return XML_FALSE;
2524 /* if tag->name.str points to tag->buf (only when namespace
2525 processing is off) then we have to update it
2526 */
2527 if (tag->name.str == (XML_Char *)tag->buf)
2528 tag->name.str = (XML_Char *)temp;
2529 /* if tag->name.localPart is set (when namespace processing is on)
2530 then update it as well, since it will always point into tag->buf
2531 */
2532 if (tag->name.localPart)
2533 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2534 (XML_Char *)tag->buf);
2535 tag->buf = temp;
2536 tag->bufEnd = temp + bufSize;
2537 rawNameBuf = temp + nameLen;
2538 }
2539 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2540 tag->rawName = rawNameBuf;
2541 tag = tag->parent;
2542 }
2543 return XML_TRUE;
2544}
2545
2546static enum XML_Error PTRCALL
2547contentProcessor(XML_Parser parser,
2548 const char *start,
2549 const char *end,
2550 const char **endPtr)
2551{
Elliott Hughes72472942018-01-10 08:36:10 -08002552 enum XML_Error result = doContent(parser, 0, parser->m_encoding, start, end,
2553 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002554 if (result == XML_ERROR_NONE) {
2555 if (!storeRawNames(parser))
2556 return XML_ERROR_NO_MEMORY;
2557 }
2558 return result;
2559}
2560
2561static enum XML_Error PTRCALL
2562externalEntityInitProcessor(XML_Parser parser,
2563 const char *start,
2564 const char *end,
2565 const char **endPtr)
2566{
2567 enum XML_Error result = initializeEncoding(parser);
2568 if (result != XML_ERROR_NONE)
2569 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002570 parser->m_processor = externalEntityInitProcessor2;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002571 return externalEntityInitProcessor2(parser, start, end, endPtr);
2572}
2573
2574static enum XML_Error PTRCALL
2575externalEntityInitProcessor2(XML_Parser parser,
2576 const char *start,
2577 const char *end,
2578 const char **endPtr)
2579{
2580 const char *next = start; /* XmlContentTok doesn't always set the last arg */
Elliott Hughes72472942018-01-10 08:36:10 -08002581 int tok = XmlContentTok(parser->m_encoding, start, end, &next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002582 switch (tok) {
2583 case XML_TOK_BOM:
2584 /* If we are at the end of the buffer, this would cause the next stage,
2585 i.e. externalEntityInitProcessor3, to pass control directly to
2586 doContent (by detecting XML_TOK_NONE) without processing any xml text
2587 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2588 */
Elliott Hughes72472942018-01-10 08:36:10 -08002589 if (next == end && !parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002590 *endPtr = next;
2591 return XML_ERROR_NONE;
2592 }
2593 start = next;
2594 break;
2595 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08002596 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002597 *endPtr = start;
2598 return XML_ERROR_NONE;
2599 }
Elliott Hughes72472942018-01-10 08:36:10 -08002600 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002601 return XML_ERROR_UNCLOSED_TOKEN;
2602 case XML_TOK_PARTIAL_CHAR:
Elliott Hughes72472942018-01-10 08:36:10 -08002603 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002604 *endPtr = start;
2605 return XML_ERROR_NONE;
2606 }
Elliott Hughes72472942018-01-10 08:36:10 -08002607 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002608 return XML_ERROR_PARTIAL_CHAR;
2609 }
Elliott Hughes72472942018-01-10 08:36:10 -08002610 parser->m_processor = externalEntityInitProcessor3;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002611 return externalEntityInitProcessor3(parser, start, end, endPtr);
2612}
2613
2614static enum XML_Error PTRCALL
2615externalEntityInitProcessor3(XML_Parser parser,
2616 const char *start,
2617 const char *end,
2618 const char **endPtr)
2619{
2620 int tok;
2621 const char *next = start; /* XmlContentTok doesn't always set the last arg */
Elliott Hughes72472942018-01-10 08:36:10 -08002622 parser->m_eventPtr = start;
2623 tok = XmlContentTok(parser->m_encoding, start, end, &next);
2624 parser->m_eventEndPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002625
2626 switch (tok) {
2627 case XML_TOK_XML_DECL:
2628 {
2629 enum XML_Error result;
2630 result = processXmlDecl(parser, 1, start, next);
2631 if (result != XML_ERROR_NONE)
2632 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002633 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07002634 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002635 *endPtr = next;
2636 return XML_ERROR_NONE;
2637 case XML_FINISHED:
2638 return XML_ERROR_ABORTED;
2639 default:
2640 start = next;
2641 }
2642 }
2643 break;
2644 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08002645 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002646 *endPtr = start;
2647 return XML_ERROR_NONE;
2648 }
2649 return XML_ERROR_UNCLOSED_TOKEN;
2650 case XML_TOK_PARTIAL_CHAR:
Elliott Hughes72472942018-01-10 08:36:10 -08002651 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002652 *endPtr = start;
2653 return XML_ERROR_NONE;
2654 }
2655 return XML_ERROR_PARTIAL_CHAR;
2656 }
Elliott Hughes72472942018-01-10 08:36:10 -08002657 parser->m_processor = externalEntityContentProcessor;
2658 parser->m_tagLevel = 1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002659 return externalEntityContentProcessor(parser, start, end, endPtr);
2660}
2661
2662static enum XML_Error PTRCALL
2663externalEntityContentProcessor(XML_Parser parser,
2664 const char *start,
2665 const char *end,
2666 const char **endPtr)
2667{
Elliott Hughes72472942018-01-10 08:36:10 -08002668 enum XML_Error result = doContent(parser, 1, parser->m_encoding, start, end,
2669 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002670 if (result == XML_ERROR_NONE) {
2671 if (!storeRawNames(parser))
2672 return XML_ERROR_NO_MEMORY;
2673 }
2674 return result;
2675}
2676
2677static enum XML_Error
2678doContent(XML_Parser parser,
2679 int startTagLevel,
2680 const ENCODING *enc,
2681 const char *s,
2682 const char *end,
2683 const char **nextPtr,
2684 XML_Bool haveMore)
2685{
2686 /* save one level of indirection */
Elliott Hughes72472942018-01-10 08:36:10 -08002687 DTD * const dtd = parser->m_dtd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002688
2689 const char **eventPP;
2690 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08002691 if (enc == parser->m_encoding) {
2692 eventPP = &parser->m_eventPtr;
2693 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002694 }
2695 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002696 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
2697 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002698 }
2699 *eventPP = s;
2700
2701 for (;;) {
2702 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2703 int tok = XmlContentTok(enc, s, end, &next);
2704 *eventEndPP = next;
2705 switch (tok) {
2706 case XML_TOK_TRAILING_CR:
2707 if (haveMore) {
2708 *nextPtr = s;
2709 return XML_ERROR_NONE;
2710 }
2711 *eventEndPP = end;
Elliott Hughes72472942018-01-10 08:36:10 -08002712 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002713 XML_Char c = 0xA;
Elliott Hughes72472942018-01-10 08:36:10 -08002714 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002715 }
Elliott Hughes72472942018-01-10 08:36:10 -08002716 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002717 reportDefault(parser, enc, s, end);
Elliott Hughes35e432d2012-09-09 14:23:38 -07002718 /* We are at the end of the final buffer, should we check for
2719 XML_SUSPENDED, XML_FINISHED?
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002720 */
2721 if (startTagLevel == 0)
2722 return XML_ERROR_NO_ELEMENTS;
Elliott Hughes72472942018-01-10 08:36:10 -08002723 if (parser->m_tagLevel != startTagLevel)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002724 return XML_ERROR_ASYNC_ENTITY;
2725 *nextPtr = end;
2726 return XML_ERROR_NONE;
2727 case XML_TOK_NONE:
2728 if (haveMore) {
2729 *nextPtr = s;
2730 return XML_ERROR_NONE;
2731 }
2732 if (startTagLevel > 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08002733 if (parser->m_tagLevel != startTagLevel)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002734 return XML_ERROR_ASYNC_ENTITY;
2735 *nextPtr = s;
2736 return XML_ERROR_NONE;
2737 }
2738 return XML_ERROR_NO_ELEMENTS;
2739 case XML_TOK_INVALID:
2740 *eventPP = next;
2741 return XML_ERROR_INVALID_TOKEN;
2742 case XML_TOK_PARTIAL:
2743 if (haveMore) {
2744 *nextPtr = s;
2745 return XML_ERROR_NONE;
2746 }
2747 return XML_ERROR_UNCLOSED_TOKEN;
2748 case XML_TOK_PARTIAL_CHAR:
2749 if (haveMore) {
2750 *nextPtr = s;
2751 return XML_ERROR_NONE;
2752 }
2753 return XML_ERROR_PARTIAL_CHAR;
2754 case XML_TOK_ENTITY_REF:
2755 {
2756 const XML_Char *name;
2757 ENTITY *entity;
2758 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2759 s + enc->minBytesPerChar,
2760 next - enc->minBytesPerChar);
2761 if (ch) {
Elliott Hughes72472942018-01-10 08:36:10 -08002762 if (parser->m_characterDataHandler)
2763 parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
2764 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002765 reportDefault(parser, enc, s, next);
2766 break;
2767 }
2768 name = poolStoreString(&dtd->pool, enc,
2769 s + enc->minBytesPerChar,
2770 next - enc->minBytesPerChar);
2771 if (!name)
2772 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07002773 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002774 poolDiscard(&dtd->pool);
2775 /* First, determine if a check for an existing declaration is needed;
2776 if yes, check that the entity exists, and that it is internal,
2777 otherwise call the skipped entity or default handler.
2778 */
2779 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2780 if (!entity)
2781 return XML_ERROR_UNDEFINED_ENTITY;
2782 else if (!entity->is_internal)
2783 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2784 }
2785 else if (!entity) {
Elliott Hughes72472942018-01-10 08:36:10 -08002786 if (parser->m_skippedEntityHandler)
2787 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
2788 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002789 reportDefault(parser, enc, s, next);
2790 break;
2791 }
2792 if (entity->open)
2793 return XML_ERROR_RECURSIVE_ENTITY_REF;
2794 if (entity->notation)
2795 return XML_ERROR_BINARY_ENTITY_REF;
2796 if (entity->textPtr) {
2797 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08002798 if (!parser->m_defaultExpandInternalEntities) {
2799 if (parser->m_skippedEntityHandler)
2800 parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name, 0);
2801 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002802 reportDefault(parser, enc, s, next);
2803 break;
2804 }
2805 result = processInternalEntity(parser, entity, XML_FALSE);
2806 if (result != XML_ERROR_NONE)
2807 return result;
2808 }
Elliott Hughes72472942018-01-10 08:36:10 -08002809 else if (parser->m_externalEntityRefHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002810 const XML_Char *context;
2811 entity->open = XML_TRUE;
2812 context = getContext(parser);
2813 entity->open = XML_FALSE;
2814 if (!context)
2815 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08002816 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002817 context,
2818 entity->base,
2819 entity->systemId,
2820 entity->publicId))
2821 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
Elliott Hughes72472942018-01-10 08:36:10 -08002822 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002823 }
Elliott Hughes72472942018-01-10 08:36:10 -08002824 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002825 reportDefault(parser, enc, s, next);
2826 break;
2827 }
2828 case XML_TOK_START_TAG_NO_ATTS:
2829 /* fall through */
2830 case XML_TOK_START_TAG_WITH_ATTS:
2831 {
2832 TAG *tag;
2833 enum XML_Error result;
2834 XML_Char *toPtr;
Elliott Hughes72472942018-01-10 08:36:10 -08002835 if (parser->m_freeTagList) {
2836 tag = parser->m_freeTagList;
2837 parser->m_freeTagList = parser->m_freeTagList->parent;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002838 }
2839 else {
Elliott Hughes72472942018-01-10 08:36:10 -08002840 tag = (TAG *)MALLOC(parser, sizeof(TAG));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002841 if (!tag)
2842 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08002843 tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002844 if (!tag->buf) {
Elliott Hughes72472942018-01-10 08:36:10 -08002845 FREE(parser, tag);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002846 return XML_ERROR_NO_MEMORY;
2847 }
2848 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2849 }
2850 tag->bindings = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08002851 tag->parent = parser->m_tagStack;
2852 parser->m_tagStack = tag;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002853 tag->name.localPart = NULL;
2854 tag->name.prefix = NULL;
2855 tag->rawName = s + enc->minBytesPerChar;
2856 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
Elliott Hughes72472942018-01-10 08:36:10 -08002857 ++parser->m_tagLevel;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002858 {
2859 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2860 const char *fromPtr = tag->rawName;
2861 toPtr = (XML_Char *)tag->buf;
2862 for (;;) {
2863 int bufSize;
2864 int convLen;
Paul Duffin4bf8f122016-05-13 12:35:25 +01002865 const enum XML_Convert_Result convert_res = XmlConvert(enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002866 &fromPtr, rawNameEnd,
2867 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2868 convLen = (int)(toPtr - (XML_Char *)tag->buf);
Elliott Hughes72472942018-01-10 08:36:10 -08002869 if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002870 tag->name.strLen = convLen;
2871 break;
2872 }
2873 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2874 {
Elliott Hughes72472942018-01-10 08:36:10 -08002875 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002876 if (temp == NULL)
2877 return XML_ERROR_NO_MEMORY;
2878 tag->buf = temp;
2879 tag->bufEnd = temp + bufSize;
2880 toPtr = (XML_Char *)temp + convLen;
2881 }
2882 }
2883 }
2884 tag->name.str = (XML_Char *)tag->buf;
2885 *toPtr = XML_T('\0');
2886 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2887 if (result)
2888 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002889 if (parser->m_startElementHandler)
2890 parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
2891 (const XML_Char **)parser->m_atts);
2892 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002893 reportDefault(parser, enc, s, next);
Elliott Hughes72472942018-01-10 08:36:10 -08002894 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002895 break;
2896 }
2897 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2898 /* fall through */
2899 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2900 {
2901 const char *rawName = s + enc->minBytesPerChar;
2902 enum XML_Error result;
2903 BINDING *bindings = NULL;
2904 XML_Bool noElmHandlers = XML_TRUE;
2905 TAG_NAME name;
Elliott Hughes72472942018-01-10 08:36:10 -08002906 name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002907 rawName + XmlNameLength(enc, rawName));
2908 if (!name.str)
2909 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08002910 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002911 result = storeAtts(parser, enc, s, &name, &bindings);
Elliott Hughes72472942018-01-10 08:36:10 -08002912 if (result != XML_ERROR_NONE) {
2913 freeBindings(parser, bindings);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002914 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08002915 }
2916 poolFinish(&parser->m_tempPool);
2917 if (parser->m_startElementHandler) {
2918 parser->m_startElementHandler(parser->m_handlerArg, name.str, (const XML_Char **)parser->m_atts);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002919 noElmHandlers = XML_FALSE;
2920 }
Elliott Hughes72472942018-01-10 08:36:10 -08002921 if (parser->m_endElementHandler) {
2922 if (parser->m_startElementHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002923 *eventPP = *eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08002924 parser->m_endElementHandler(parser->m_handlerArg, name.str);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002925 noElmHandlers = XML_FALSE;
2926 }
Elliott Hughes72472942018-01-10 08:36:10 -08002927 if (noElmHandlers && parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002928 reportDefault(parser, enc, s, next);
Elliott Hughes72472942018-01-10 08:36:10 -08002929 poolClear(&parser->m_tempPool);
2930 freeBindings(parser, bindings);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002931 }
Elliott Hughesaaec48e2018-08-16 16:29:01 -07002932 if ((parser->m_tagLevel == 0) && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
2933 if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
2934 parser->m_processor = epilogProcessor;
2935 else
2936 return epilogProcessor(parser, next, end, nextPtr);
Elliott Hughes72472942018-01-10 08:36:10 -08002937 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002938 break;
2939 case XML_TOK_END_TAG:
Elliott Hughes72472942018-01-10 08:36:10 -08002940 if (parser->m_tagLevel == startTagLevel)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002941 return XML_ERROR_ASYNC_ENTITY;
2942 else {
2943 int len;
2944 const char *rawName;
Elliott Hughes72472942018-01-10 08:36:10 -08002945 TAG *tag = parser->m_tagStack;
2946 parser->m_tagStack = tag->parent;
2947 tag->parent = parser->m_freeTagList;
2948 parser->m_freeTagList = tag;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002949 rawName = s + enc->minBytesPerChar*2;
2950 len = XmlNameLength(enc, rawName);
2951 if (len != tag->rawNameLength
2952 || memcmp(tag->rawName, rawName, len) != 0) {
2953 *eventPP = rawName;
2954 return XML_ERROR_TAG_MISMATCH;
2955 }
Elliott Hughes72472942018-01-10 08:36:10 -08002956 --parser->m_tagLevel;
2957 if (parser->m_endElementHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002958 const XML_Char *localPart;
2959 const XML_Char *prefix;
2960 XML_Char *uri;
2961 localPart = tag->name.localPart;
Elliott Hughes72472942018-01-10 08:36:10 -08002962 if (parser->m_ns && localPart) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002963 /* localPart and prefix may have been overwritten in
2964 tag->name.str, since this points to the binding->uri
2965 buffer which gets re-used; so we have to add them again
2966 */
2967 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2968 /* don't need to check for space - already done in storeAtts() */
2969 while (*localPart) *uri++ = *localPart++;
2970 prefix = (XML_Char *)tag->name.prefix;
Elliott Hughes72472942018-01-10 08:36:10 -08002971 if (parser->m_ns_triplets && prefix) {
2972 *uri++ = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002973 while (*prefix) *uri++ = *prefix++;
2974 }
2975 *uri = XML_T('\0');
2976 }
Elliott Hughes72472942018-01-10 08:36:10 -08002977 parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002978 }
Elliott Hughes72472942018-01-10 08:36:10 -08002979 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002980 reportDefault(parser, enc, s, next);
2981 while (tag->bindings) {
2982 BINDING *b = tag->bindings;
Elliott Hughes72472942018-01-10 08:36:10 -08002983 if (parser->m_endNamespaceDeclHandler)
2984 parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002985 tag->bindings = tag->bindings->nextTagBinding;
Elliott Hughes72472942018-01-10 08:36:10 -08002986 b->nextTagBinding = parser->m_freeBindingList;
2987 parser->m_freeBindingList = b;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002988 b->prefix->binding = b->prevPrefixBinding;
2989 }
Elliott Hughes72472942018-01-10 08:36:10 -08002990 if (parser->m_tagLevel == 0)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08002991 return epilogProcessor(parser, next, end, nextPtr);
2992 }
2993 break;
2994 case XML_TOK_CHAR_REF:
2995 {
2996 int n = XmlCharRefNumber(enc, s);
2997 if (n < 0)
2998 return XML_ERROR_BAD_CHAR_REF;
Elliott Hughes72472942018-01-10 08:36:10 -08002999 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003000 XML_Char buf[XML_ENCODE_MAX];
Elliott Hughes72472942018-01-10 08:36:10 -08003001 parser->m_characterDataHandler(parser->m_handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003002 }
Elliott Hughes72472942018-01-10 08:36:10 -08003003 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003004 reportDefault(parser, enc, s, next);
3005 }
3006 break;
3007 case XML_TOK_XML_DECL:
3008 return XML_ERROR_MISPLACED_XML_PI;
3009 case XML_TOK_DATA_NEWLINE:
Elliott Hughes72472942018-01-10 08:36:10 -08003010 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003011 XML_Char c = 0xA;
Elliott Hughes72472942018-01-10 08:36:10 -08003012 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003013 }
Elliott Hughes72472942018-01-10 08:36:10 -08003014 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003015 reportDefault(parser, enc, s, next);
3016 break;
3017 case XML_TOK_CDATA_SECT_OPEN:
3018 {
3019 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08003020 if (parser->m_startCdataSectionHandler)
3021 parser->m_startCdataSectionHandler(parser->m_handlerArg);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003022#if 0
3023 /* Suppose you doing a transformation on a document that involves
3024 changing only the character data. You set up a defaultHandler
3025 and a characterDataHandler. The defaultHandler simply copies
3026 characters through. The characterDataHandler does the
3027 transformation and writes the characters out escaping them as
3028 necessary. This case will fail to work if we leave out the
3029 following two lines (because & and < inside CDATA sections will
3030 be incorrectly escaped).
3031
3032 However, now we have a start/endCdataSectionHandler, so it seems
3033 easier to let the user deal with this.
3034 */
Elliott Hughes72472942018-01-10 08:36:10 -08003035 else if (parser->m_characterDataHandler)
3036 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003037#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003038 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003039 reportDefault(parser, enc, s, next);
3040 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
3041 if (result != XML_ERROR_NONE)
3042 return result;
3043 else if (!next) {
Elliott Hughes72472942018-01-10 08:36:10 -08003044 parser->m_processor = cdataSectionProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003045 return result;
3046 }
3047 }
3048 break;
3049 case XML_TOK_TRAILING_RSQB:
3050 if (haveMore) {
3051 *nextPtr = s;
3052 return XML_ERROR_NONE;
3053 }
Elliott Hughes72472942018-01-10 08:36:10 -08003054 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003055 if (MUST_CONVERT(enc, s)) {
Elliott Hughes72472942018-01-10 08:36:10 -08003056 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3057 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
3058 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3059 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003060 }
3061 else
Elliott Hughes72472942018-01-10 08:36:10 -08003062 parser->m_characterDataHandler(parser->m_handlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003063 (XML_Char *)s,
3064 (int)((XML_Char *)end - (XML_Char *)s));
3065 }
Elliott Hughes72472942018-01-10 08:36:10 -08003066 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003067 reportDefault(parser, enc, s, end);
Elliott Hughes35e432d2012-09-09 14:23:38 -07003068 /* We are at the end of the final buffer, should we check for
3069 XML_SUSPENDED, XML_FINISHED?
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003070 */
3071 if (startTagLevel == 0) {
3072 *eventPP = end;
3073 return XML_ERROR_NO_ELEMENTS;
3074 }
Elliott Hughes72472942018-01-10 08:36:10 -08003075 if (parser->m_tagLevel != startTagLevel) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003076 *eventPP = end;
3077 return XML_ERROR_ASYNC_ENTITY;
3078 }
3079 *nextPtr = end;
3080 return XML_ERROR_NONE;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003081 case XML_TOK_DATA_CHARS:
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003082 {
Elliott Hughes72472942018-01-10 08:36:10 -08003083 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003084 if (charDataHandler) {
3085 if (MUST_CONVERT(enc, s)) {
3086 for (;;) {
Elliott Hughes72472942018-01-10 08:36:10 -08003087 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3088 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003089 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08003090 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3091 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
Paul Duffin4bf8f122016-05-13 12:35:25 +01003092 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003093 break;
3094 *eventPP = s;
3095 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003096 }
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003097 else
Elliott Hughes72472942018-01-10 08:36:10 -08003098 charDataHandler(parser->m_handlerArg,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003099 (XML_Char *)s,
3100 (int)((XML_Char *)next - (XML_Char *)s));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003101 }
Elliott Hughes72472942018-01-10 08:36:10 -08003102 else if (parser->m_defaultHandler)
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003103 reportDefault(parser, enc, s, next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003104 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003105 break;
3106 case XML_TOK_PI:
3107 if (!reportProcessingInstruction(parser, enc, s, next))
3108 return XML_ERROR_NO_MEMORY;
3109 break;
3110 case XML_TOK_COMMENT:
3111 if (!reportComment(parser, enc, s, next))
3112 return XML_ERROR_NO_MEMORY;
3113 break;
3114 default:
Elliott Hughes72472942018-01-10 08:36:10 -08003115 /* All of the tokens produced by XmlContentTok() have their own
3116 * explicit cases, so this default is not strictly necessary.
3117 * However it is a useful safety net, so we retain the code and
3118 * simply exclude it from the coverage tests.
3119 *
3120 * LCOV_EXCL_START
3121 */
3122 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003123 reportDefault(parser, enc, s, next);
3124 break;
Elliott Hughes72472942018-01-10 08:36:10 -08003125 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003126 }
3127 *eventPP = s = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003128 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07003129 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003130 *nextPtr = next;
3131 return XML_ERROR_NONE;
3132 case XML_FINISHED:
3133 return XML_ERROR_ABORTED;
3134 default: ;
3135 }
3136 }
3137 /* not reached */
3138}
3139
Elliott Hughes72472942018-01-10 08:36:10 -08003140/* This function does not call free() on the allocated memory, merely
3141 * moving it to the parser's m_freeBindingList where it can be freed or
3142 * reused as appropriate.
3143 */
3144static void
3145freeBindings(XML_Parser parser, BINDING *bindings)
3146{
3147 while (bindings) {
3148 BINDING *b = bindings;
3149
3150 /* m_startNamespaceDeclHandler will have been called for this
3151 * binding in addBindings(), so call the end handler now.
3152 */
3153 if (parser->m_endNamespaceDeclHandler)
3154 parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
3155
3156 bindings = bindings->nextTagBinding;
3157 b->nextTagBinding = parser->m_freeBindingList;
3158 parser->m_freeBindingList = b;
3159 b->prefix->binding = b->prevPrefixBinding;
3160 }
3161}
3162
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003163/* Precondition: all arguments must be non-NULL;
3164 Purpose:
3165 - normalize attributes
3166 - check attributes for well-formedness
3167 - generate namespace aware attribute names (URI, prefix)
3168 - build list of attributes for startElementHandler
3169 - default attributes
3170 - process namespace declarations (check and report them)
3171 - generate namespace aware element name (URI, prefix)
3172*/
3173static enum XML_Error
3174storeAtts(XML_Parser parser, const ENCODING *enc,
3175 const char *attStr, TAG_NAME *tagNamePtr,
3176 BINDING **bindingsPtr)
3177{
Elliott Hughes72472942018-01-10 08:36:10 -08003178 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003179 ELEMENT_TYPE *elementType;
3180 int nDefaultAtts;
3181 const XML_Char **appAtts; /* the attribute list for the application */
3182 int attIndex = 0;
3183 int prefixLen;
3184 int i;
3185 int n;
3186 XML_Char *uri;
3187 int nPrefixes = 0;
3188 BINDING *binding;
3189 const XML_Char *localPart;
3190
3191 /* lookup the element type name */
Elliott Hughes35e432d2012-09-09 14:23:38 -07003192 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003193 if (!elementType) {
3194 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
3195 if (!name)
3196 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003197 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003198 sizeof(ELEMENT_TYPE));
3199 if (!elementType)
3200 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003201 if (parser->m_ns && !setElementTypePrefix(parser, elementType))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003202 return XML_ERROR_NO_MEMORY;
3203 }
3204 nDefaultAtts = elementType->nDefaultAtts;
3205
3206 /* get the attributes from the tokenizer */
Elliott Hughes72472942018-01-10 08:36:10 -08003207 n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
3208 if (n + nDefaultAtts > parser->m_attsSize) {
3209 int oldAttsSize = parser->m_attsSize;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003210 ATTRIBUTE *temp;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003211#ifdef XML_ATTR_INFO
3212 XML_AttrInfo *temp2;
3213#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003214 parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
3215 temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, parser->m_attsSize * sizeof(ATTRIBUTE));
3216 if (temp == NULL) {
3217 parser->m_attsSize = oldAttsSize;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003218 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003219 }
3220 parser->m_atts = temp;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003221#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08003222 temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, parser->m_attsSize * sizeof(XML_AttrInfo));
3223 if (temp2 == NULL) {
3224 parser->m_attsSize = oldAttsSize;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003225 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003226 }
3227 parser->m_attInfo = temp2;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003228#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003229 if (n > oldAttsSize)
Elliott Hughes72472942018-01-10 08:36:10 -08003230 XmlGetAttributes(enc, attStr, n, parser->m_atts);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003231 }
3232
Elliott Hughes72472942018-01-10 08:36:10 -08003233 appAtts = (const XML_Char **)parser->m_atts;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003234 for (i = 0; i < n; i++) {
Elliott Hughes72472942018-01-10 08:36:10 -08003235 ATTRIBUTE *currAtt = &parser->m_atts[i];
Elliott Hughes35e432d2012-09-09 14:23:38 -07003236#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08003237 XML_AttrInfo *currAttInfo = &parser->m_attInfo[i];
Elliott Hughes35e432d2012-09-09 14:23:38 -07003238#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003239 /* add the name and value to the attribute list */
Elliott Hughes35e432d2012-09-09 14:23:38 -07003240 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
3241 currAtt->name
3242 + XmlNameLength(enc, currAtt->name));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003243 if (!attId)
3244 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003245#ifdef XML_ATTR_INFO
Elliott Hughes72472942018-01-10 08:36:10 -08003246 currAttInfo->nameStart = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name);
Elliott Hughes35e432d2012-09-09 14:23:38 -07003247 currAttInfo->nameEnd = currAttInfo->nameStart +
3248 XmlNameLength(enc, currAtt->name);
Elliott Hughes72472942018-01-10 08:36:10 -08003249 currAttInfo->valueStart = parser->m_parseEndByteIndex -
3250 (parser->m_parseEndPtr - currAtt->valuePtr);
3251 currAttInfo->valueEnd = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->valueEnd);
Elliott Hughes35e432d2012-09-09 14:23:38 -07003252#endif
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003253 /* Detect duplicate attributes by their QNames. This does not work when
3254 namespace processing is turned on and different prefixes for the same
3255 namespace are used. For this case we have a check further down.
3256 */
3257 if ((attId->name)[-1]) {
Elliott Hughes72472942018-01-10 08:36:10 -08003258 if (enc == parser->m_encoding)
3259 parser->m_eventPtr = parser->m_atts[i].name;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003260 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3261 }
3262 (attId->name)[-1] = 1;
3263 appAtts[attIndex++] = attId->name;
Elliott Hughes72472942018-01-10 08:36:10 -08003264 if (!parser->m_atts[i].normalized) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003265 enum XML_Error result;
3266 XML_Bool isCdata = XML_TRUE;
3267
3268 /* figure out whether declared as other than CDATA */
3269 if (attId->maybeTokenized) {
3270 int j;
3271 for (j = 0; j < nDefaultAtts; j++) {
3272 if (attId == elementType->defaultAtts[j].id) {
3273 isCdata = elementType->defaultAtts[j].isCdata;
3274 break;
3275 }
3276 }
3277 }
3278
3279 /* normalize the attribute value */
3280 result = storeAttributeValue(parser, enc, isCdata,
Elliott Hughes72472942018-01-10 08:36:10 -08003281 parser->m_atts[i].valuePtr, parser->m_atts[i].valueEnd,
3282 &parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003283 if (result)
3284 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08003285 appAtts[attIndex] = poolStart(&parser->m_tempPool);
3286 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003287 }
3288 else {
3289 /* the value did not need normalizing */
Elliott Hughes72472942018-01-10 08:36:10 -08003290 appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc, parser->m_atts[i].valuePtr,
3291 parser->m_atts[i].valueEnd);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003292 if (appAtts[attIndex] == 0)
3293 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003294 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003295 }
3296 /* handle prefixed attribute names */
3297 if (attId->prefix) {
3298 if (attId->xmlns) {
3299 /* deal with namespace declarations here */
3300 enum XML_Error result = addBinding(parser, attId->prefix, attId,
3301 appAtts[attIndex], bindingsPtr);
3302 if (result)
3303 return result;
3304 --attIndex;
3305 }
3306 else {
3307 /* deal with other prefixed names later */
3308 attIndex++;
3309 nPrefixes++;
3310 (attId->name)[-1] = 2;
3311 }
3312 }
3313 else
3314 attIndex++;
3315 }
3316
3317 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
Elliott Hughes72472942018-01-10 08:36:10 -08003318 parser->m_nSpecifiedAtts = attIndex;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003319 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
3320 for (i = 0; i < attIndex; i += 2)
3321 if (appAtts[i] == elementType->idAtt->name) {
Elliott Hughes72472942018-01-10 08:36:10 -08003322 parser->m_idAttIndex = i;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003323 break;
3324 }
3325 }
3326 else
Elliott Hughes72472942018-01-10 08:36:10 -08003327 parser->m_idAttIndex = -1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003328
3329 /* do attribute defaulting */
3330 for (i = 0; i < nDefaultAtts; i++) {
3331 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
3332 if (!(da->id->name)[-1] && da->value) {
3333 if (da->id->prefix) {
3334 if (da->id->xmlns) {
3335 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
3336 da->value, bindingsPtr);
3337 if (result)
3338 return result;
3339 }
3340 else {
3341 (da->id->name)[-1] = 2;
3342 nPrefixes++;
3343 appAtts[attIndex++] = da->id->name;
3344 appAtts[attIndex++] = da->value;
3345 }
3346 }
3347 else {
3348 (da->id->name)[-1] = 1;
3349 appAtts[attIndex++] = da->id->name;
3350 appAtts[attIndex++] = da->value;
3351 }
3352 }
3353 }
3354 appAtts[attIndex] = 0;
3355
3356 /* expand prefixed attribute names, check for duplicates,
3357 and clear flags that say whether attributes were specified */
3358 i = 0;
3359 if (nPrefixes) {
3360 int j; /* hash table index */
Elliott Hughes72472942018-01-10 08:36:10 -08003361 unsigned long version = parser->m_nsAttsVersion;
3362 int nsAttsSize = (int)1 << parser->m_nsAttsPower;
3363 unsigned char oldNsAttsPower = parser->m_nsAttsPower;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003364 /* size of hash table must be at least 2 * (# of prefixed attributes) */
Elliott Hughes72472942018-01-10 08:36:10 -08003365 if ((nPrefixes << 1) >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003366 NS_ATT *temp;
3367 /* hash table size must also be a power of 2 and >= 8 */
Elliott Hughes72472942018-01-10 08:36:10 -08003368 while (nPrefixes >> parser->m_nsAttsPower++);
3369 if (parser->m_nsAttsPower < 3)
3370 parser->m_nsAttsPower = 3;
3371 nsAttsSize = (int)1 << parser->m_nsAttsPower;
3372 temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, nsAttsSize * sizeof(NS_ATT));
3373 if (!temp) {
3374 /* Restore actual size of memory in m_nsAtts */
3375 parser->m_nsAttsPower = oldNsAttsPower;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003376 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003377 }
3378 parser->m_nsAtts = temp;
3379 version = 0; /* force re-initialization of m_nsAtts hash table */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003380 }
Elliott Hughes72472942018-01-10 08:36:10 -08003381 /* using a version flag saves us from initializing m_nsAtts every time */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003382 if (!version) { /* initialize version flags when version wraps around */
3383 version = INIT_ATTS_VERSION;
3384 for (j = nsAttsSize; j != 0; )
Elliott Hughes72472942018-01-10 08:36:10 -08003385 parser->m_nsAtts[--j].version = version;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003386 }
Elliott Hughes72472942018-01-10 08:36:10 -08003387 parser->m_nsAttsVersion = --version;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003388
3389 /* expand prefixed names and check for duplicates */
3390 for (; i < attIndex; i += 2) {
3391 const XML_Char *s = appAtts[i];
3392 if (s[-1] == 2) { /* prefixed */
3393 ATTRIBUTE_ID *id;
3394 const BINDING *b;
Elliott Hughes72472942018-01-10 08:36:10 -08003395 unsigned long uriHash;
3396 struct siphash sip_state;
3397 struct sipkey sip_key;
3398
3399 copy_salt_to_sipkey(parser, &sip_key);
3400 sip24_init(&sip_state, &sip_key);
3401
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003402 ((XML_Char *)s)[-1] = 0; /* clear flag */
Elliott Hughes35e432d2012-09-09 14:23:38 -07003403 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
Elliott Hughes72472942018-01-10 08:36:10 -08003404 if (!id || !id->prefix) {
3405 /* This code is walking through the appAtts array, dealing
3406 * with (in this case) a prefixed attribute name. To be in
3407 * the array, the attribute must have already been bound, so
3408 * has to have passed through the hash table lookup once
3409 * already. That implies that an entry for it already
3410 * exists, so the lookup above will return a pointer to
3411 * already allocated memory. There is no opportunaity for
3412 * the allocator to fail, so the condition above cannot be
3413 * fulfilled.
3414 *
3415 * Since it is difficult to be certain that the above
3416 * analysis is complete, we retain the test and merely
3417 * remove the code from coverage tests.
3418 */
3419 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
3420 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003421 b = id->prefix->binding;
3422 if (!b)
3423 return XML_ERROR_UNBOUND_PREFIX;
3424
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003425 for (j = 0; j < b->uriLen; j++) {
3426 const XML_Char c = b->uri[j];
Elliott Hughes72472942018-01-10 08:36:10 -08003427 if (!poolAppendChar(&parser->m_tempPool, c))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003428 return XML_ERROR_NO_MEMORY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003429 }
Elliott Hughes72472942018-01-10 08:36:10 -08003430
3431 sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
3432
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003433 while (*s++ != XML_T(ASCII_COLON))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003434 ;
Elliott Hughes72472942018-01-10 08:36:10 -08003435
3436 sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
3437
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003438 do { /* copies null terminator */
Elliott Hughes72472942018-01-10 08:36:10 -08003439 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003440 return XML_ERROR_NO_MEMORY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003441 } while (*s++);
3442
Elliott Hughes72472942018-01-10 08:36:10 -08003443 uriHash = (unsigned long)sip24_final(&sip_state);
3444
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003445 { /* Check hash table for duplicate of expanded name (uriName).
Elliott Hughes35e432d2012-09-09 14:23:38 -07003446 Derived from code in lookup(parser, HASH_TABLE *table, ...).
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003447 */
3448 unsigned char step = 0;
3449 unsigned long mask = nsAttsSize - 1;
3450 j = uriHash & mask; /* index into hash table */
Elliott Hughes72472942018-01-10 08:36:10 -08003451 while (parser->m_nsAtts[j].version == version) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003452 /* for speed we compare stored hash values first */
Elliott Hughes72472942018-01-10 08:36:10 -08003453 if (uriHash == parser->m_nsAtts[j].hash) {
3454 const XML_Char *s1 = poolStart(&parser->m_tempPool);
3455 const XML_Char *s2 = parser->m_nsAtts[j].uriName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003456 /* s1 is null terminated, but not s2 */
3457 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
3458 if (*s1 == 0)
3459 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3460 }
3461 if (!step)
Elliott Hughes72472942018-01-10 08:36:10 -08003462 step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003463 j < step ? (j += nsAttsSize - step) : (j -= step);
3464 }
3465 }
3466
Elliott Hughes72472942018-01-10 08:36:10 -08003467 if (parser->m_ns_triplets) { /* append namespace separator and prefix */
3468 parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003469 s = b->prefix->name;
3470 do {
Elliott Hughes72472942018-01-10 08:36:10 -08003471 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003472 return XML_ERROR_NO_MEMORY;
3473 } while (*s++);
3474 }
3475
3476 /* store expanded name in attribute list */
Elliott Hughes72472942018-01-10 08:36:10 -08003477 s = poolStart(&parser->m_tempPool);
3478 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003479 appAtts[i] = s;
3480
3481 /* fill empty slot with new version, uriName and hash value */
Elliott Hughes72472942018-01-10 08:36:10 -08003482 parser->m_nsAtts[j].version = version;
3483 parser->m_nsAtts[j].hash = uriHash;
3484 parser->m_nsAtts[j].uriName = s;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003485
3486 if (!--nPrefixes) {
3487 i += 2;
3488 break;
3489 }
3490 }
3491 else /* not prefixed */
3492 ((XML_Char *)s)[-1] = 0; /* clear flag */
3493 }
3494 }
3495 /* clear flags for the remaining attributes */
3496 for (; i < attIndex; i += 2)
3497 ((XML_Char *)(appAtts[i]))[-1] = 0;
3498 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3499 binding->attId->name[-1] = 0;
3500
Elliott Hughes72472942018-01-10 08:36:10 -08003501 if (!parser->m_ns)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003502 return XML_ERROR_NONE;
3503
3504 /* expand the element type name */
3505 if (elementType->prefix) {
3506 binding = elementType->prefix->binding;
3507 if (!binding)
3508 return XML_ERROR_UNBOUND_PREFIX;
3509 localPart = tagNamePtr->str;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003510 while (*localPart++ != XML_T(ASCII_COLON))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003511 ;
3512 }
3513 else if (dtd->defaultPrefix.binding) {
3514 binding = dtd->defaultPrefix.binding;
3515 localPart = tagNamePtr->str;
3516 }
3517 else
3518 return XML_ERROR_NONE;
3519 prefixLen = 0;
Elliott Hughes72472942018-01-10 08:36:10 -08003520 if (parser->m_ns_triplets && binding->prefix->name) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003521 for (; binding->prefix->name[prefixLen++];)
3522 ; /* prefixLen includes null terminator */
3523 }
3524 tagNamePtr->localPart = localPart;
3525 tagNamePtr->uriLen = binding->uriLen;
3526 tagNamePtr->prefix = binding->prefix->name;
3527 tagNamePtr->prefixLen = prefixLen;
3528 for (i = 0; localPart[i++];)
3529 ; /* i includes null terminator */
3530 n = i + binding->uriLen + prefixLen;
3531 if (n > binding->uriAlloc) {
3532 TAG *p;
Elliott Hughes72472942018-01-10 08:36:10 -08003533 uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003534 if (!uri)
3535 return XML_ERROR_NO_MEMORY;
3536 binding->uriAlloc = n + EXPAND_SPARE;
3537 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
Elliott Hughes72472942018-01-10 08:36:10 -08003538 for (p = parser->m_tagStack; p; p = p->parent)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003539 if (p->name.str == binding->uri)
3540 p->name.str = uri;
Elliott Hughes72472942018-01-10 08:36:10 -08003541 FREE(parser, binding->uri);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003542 binding->uri = uri;
3543 }
Elliott Hughes72472942018-01-10 08:36:10 -08003544 /* if m_namespaceSeparator != '\0' then uri includes it already */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003545 uri = binding->uri + binding->uriLen;
3546 memcpy(uri, localPart, i * sizeof(XML_Char));
3547 /* we always have a namespace separator between localPart and prefix */
3548 if (prefixLen) {
3549 uri += i - 1;
Elliott Hughes72472942018-01-10 08:36:10 -08003550 *uri = parser->m_namespaceSeparator; /* replace null terminator */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003551 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3552 }
3553 tagNamePtr->str = binding->uri;
3554 return XML_ERROR_NONE;
3555}
3556
3557/* addBinding() overwrites the value of prefix->binding without checking.
3558 Therefore one must keep track of the old value outside of addBinding().
3559*/
3560static enum XML_Error
3561addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3562 const XML_Char *uri, BINDING **bindingsPtr)
3563{
3564 static const XML_Char xmlNamespace[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003565 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3566 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
Elliott Hughes35e432d2012-09-09 14:23:38 -07003567 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003568 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
3569 ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
3570 ASCII_e, '\0'
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003571 };
Elliott Hughes35e432d2012-09-09 14:23:38 -07003572 static const int xmlLen =
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003573 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
3574 static const XML_Char xmlnsNamespace[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003575 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3576 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
Elliott Hughes35e432d2012-09-09 14:23:38 -07003577 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
3578 ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003579 ASCII_SLASH, '\0'
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003580 };
Elliott Hughes35e432d2012-09-09 14:23:38 -07003581 static const int xmlnsLen =
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003582 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
3583
3584 XML_Bool mustBeXML = XML_FALSE;
3585 XML_Bool isXML = XML_TRUE;
3586 XML_Bool isXMLNS = XML_TRUE;
Elliott Hughes35e432d2012-09-09 14:23:38 -07003587
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003588 BINDING *b;
3589 int len;
3590
3591 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3592 if (*uri == XML_T('\0') && prefix->name)
3593 return XML_ERROR_UNDECLARING_PREFIX;
3594
3595 if (prefix->name
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003596 && prefix->name[0] == XML_T(ASCII_x)
3597 && prefix->name[1] == XML_T(ASCII_m)
3598 && prefix->name[2] == XML_T(ASCII_l)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003599
3600 /* Not allowed to bind xmlns */
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003601 if (prefix->name[3] == XML_T(ASCII_n)
3602 && prefix->name[4] == XML_T(ASCII_s)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003603 && prefix->name[5] == XML_T('\0'))
3604 return XML_ERROR_RESERVED_PREFIX_XMLNS;
3605
3606 if (prefix->name[3] == XML_T('\0'))
3607 mustBeXML = XML_TRUE;
3608 }
3609
3610 for (len = 0; uri[len]; len++) {
3611 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3612 isXML = XML_FALSE;
3613
Elliott Hughes35e432d2012-09-09 14:23:38 -07003614 if (!mustBeXML && isXMLNS
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003615 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3616 isXMLNS = XML_FALSE;
3617 }
3618 isXML = isXML && len == xmlLen;
3619 isXMLNS = isXMLNS && len == xmlnsLen;
3620
3621 if (mustBeXML != isXML)
3622 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3623 : XML_ERROR_RESERVED_NAMESPACE_URI;
3624
3625 if (isXMLNS)
3626 return XML_ERROR_RESERVED_NAMESPACE_URI;
3627
Elliott Hughes72472942018-01-10 08:36:10 -08003628 if (parser->m_namespaceSeparator)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003629 len++;
Elliott Hughes72472942018-01-10 08:36:10 -08003630 if (parser->m_freeBindingList) {
3631 b = parser->m_freeBindingList;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003632 if (len > b->uriAlloc) {
Elliott Hughes72472942018-01-10 08:36:10 -08003633 XML_Char *temp = (XML_Char *)REALLOC(parser, b->uri,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003634 sizeof(XML_Char) * (len + EXPAND_SPARE));
3635 if (temp == NULL)
3636 return XML_ERROR_NO_MEMORY;
3637 b->uri = temp;
3638 b->uriAlloc = len + EXPAND_SPARE;
3639 }
Elliott Hughes72472942018-01-10 08:36:10 -08003640 parser->m_freeBindingList = b->nextTagBinding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003641 }
3642 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003643 b = (BINDING *)MALLOC(parser, sizeof(BINDING));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003644 if (!b)
3645 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08003646 b->uri = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003647 if (!b->uri) {
Elliott Hughes72472942018-01-10 08:36:10 -08003648 FREE(parser, b);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003649 return XML_ERROR_NO_MEMORY;
3650 }
3651 b->uriAlloc = len + EXPAND_SPARE;
3652 }
3653 b->uriLen = len;
3654 memcpy(b->uri, uri, len * sizeof(XML_Char));
Elliott Hughes72472942018-01-10 08:36:10 -08003655 if (parser->m_namespaceSeparator)
3656 b->uri[len - 1] = parser->m_namespaceSeparator;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003657 b->prefix = prefix;
3658 b->attId = attId;
3659 b->prevPrefixBinding = prefix->binding;
3660 /* NULL binding when default namespace undeclared */
Elliott Hughes72472942018-01-10 08:36:10 -08003661 if (*uri == XML_T('\0') && prefix == &parser->m_dtd->defaultPrefix)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003662 prefix->binding = NULL;
3663 else
3664 prefix->binding = b;
3665 b->nextTagBinding = *bindingsPtr;
3666 *bindingsPtr = b;
3667 /* if attId == NULL then we are not starting a namespace scope */
Elliott Hughes72472942018-01-10 08:36:10 -08003668 if (attId && parser->m_startNamespaceDeclHandler)
3669 parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003670 prefix->binding ? uri : 0);
3671 return XML_ERROR_NONE;
3672}
3673
3674/* The idea here is to avoid using stack for each CDATA section when
3675 the whole file is parsed with one call.
3676*/
3677static enum XML_Error PTRCALL
3678cdataSectionProcessor(XML_Parser parser,
3679 const char *start,
3680 const char *end,
3681 const char **endPtr)
3682{
Elliott Hughes72472942018-01-10 08:36:10 -08003683 enum XML_Error result = doCdataSection(parser, parser->m_encoding, &start, end,
3684 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003685 if (result != XML_ERROR_NONE)
3686 return result;
3687 if (start) {
Elliott Hughes72472942018-01-10 08:36:10 -08003688 if (parser->m_parentParser) { /* we are parsing an external entity */
3689 parser->m_processor = externalEntityContentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003690 return externalEntityContentProcessor(parser, start, end, endPtr);
3691 }
3692 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003693 parser->m_processor = contentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003694 return contentProcessor(parser, start, end, endPtr);
3695 }
3696 }
3697 return result;
3698}
3699
3700/* startPtr gets set to non-null if the section is closed, and to null if
3701 the section is not yet closed.
3702*/
3703static enum XML_Error
3704doCdataSection(XML_Parser parser,
3705 const ENCODING *enc,
3706 const char **startPtr,
3707 const char *end,
3708 const char **nextPtr,
3709 XML_Bool haveMore)
3710{
3711 const char *s = *startPtr;
3712 const char **eventPP;
3713 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08003714 if (enc == parser->m_encoding) {
3715 eventPP = &parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003716 *eventPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08003717 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003718 }
3719 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003720 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3721 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003722 }
3723 *eventPP = s;
3724 *startPtr = NULL;
3725
3726 for (;;) {
3727 const char *next;
3728 int tok = XmlCdataSectionTok(enc, s, end, &next);
3729 *eventEndPP = next;
3730 switch (tok) {
3731 case XML_TOK_CDATA_SECT_CLOSE:
Elliott Hughes72472942018-01-10 08:36:10 -08003732 if (parser->m_endCdataSectionHandler)
3733 parser->m_endCdataSectionHandler(parser->m_handlerArg);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003734#if 0
3735 /* see comment under XML_TOK_CDATA_SECT_OPEN */
Elliott Hughes72472942018-01-10 08:36:10 -08003736 else if (parser->m_characterDataHandler)
3737 parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003738#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003739 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003740 reportDefault(parser, enc, s, next);
3741 *startPtr = next;
3742 *nextPtr = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003743 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003744 return XML_ERROR_ABORTED;
3745 else
3746 return XML_ERROR_NONE;
3747 case XML_TOK_DATA_NEWLINE:
Elliott Hughes72472942018-01-10 08:36:10 -08003748 if (parser->m_characterDataHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003749 XML_Char c = 0xA;
Elliott Hughes72472942018-01-10 08:36:10 -08003750 parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003751 }
Elliott Hughes72472942018-01-10 08:36:10 -08003752 else if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003753 reportDefault(parser, enc, s, next);
3754 break;
3755 case XML_TOK_DATA_CHARS:
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003756 {
Elliott Hughes72472942018-01-10 08:36:10 -08003757 XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003758 if (charDataHandler) {
3759 if (MUST_CONVERT(enc, s)) {
3760 for (;;) {
Elliott Hughes72472942018-01-10 08:36:10 -08003761 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
3762 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003763 *eventEndPP = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003764 charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
3765 (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
Paul Duffin4bf8f122016-05-13 12:35:25 +01003766 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003767 break;
3768 *eventPP = s;
3769 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003770 }
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003771 else
Elliott Hughes72472942018-01-10 08:36:10 -08003772 charDataHandler(parser->m_handlerArg,
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003773 (XML_Char *)s,
3774 (int)((XML_Char *)next - (XML_Char *)s));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003775 }
Elliott Hughes72472942018-01-10 08:36:10 -08003776 else if (parser->m_defaultHandler)
Elliott Hughesd07d5a72009-09-25 16:04:37 -07003777 reportDefault(parser, enc, s, next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003778 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003779 break;
3780 case XML_TOK_INVALID:
3781 *eventPP = next;
3782 return XML_ERROR_INVALID_TOKEN;
3783 case XML_TOK_PARTIAL_CHAR:
3784 if (haveMore) {
3785 *nextPtr = s;
3786 return XML_ERROR_NONE;
3787 }
3788 return XML_ERROR_PARTIAL_CHAR;
3789 case XML_TOK_PARTIAL:
3790 case XML_TOK_NONE:
3791 if (haveMore) {
3792 *nextPtr = s;
3793 return XML_ERROR_NONE;
3794 }
3795 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3796 default:
Elliott Hughes72472942018-01-10 08:36:10 -08003797 /* Every token returned by XmlCdataSectionTok() has its own
3798 * explicit case, so this default case will never be executed.
3799 * We retain it as a safety net and exclude it from the coverage
3800 * statistics.
3801 *
3802 * LCOV_EXCL_START
3803 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003804 *eventPP = next;
3805 return XML_ERROR_UNEXPECTED_STATE;
Elliott Hughes72472942018-01-10 08:36:10 -08003806 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003807 }
3808
3809 *eventPP = s = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003810 switch (parser->m_parsingStatus.parsing) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003811 case XML_SUSPENDED:
3812 *nextPtr = next;
3813 return XML_ERROR_NONE;
3814 case XML_FINISHED:
3815 return XML_ERROR_ABORTED;
3816 default: ;
3817 }
3818 }
3819 /* not reached */
3820}
3821
3822#ifdef XML_DTD
3823
3824/* The idea here is to avoid using stack for each IGNORE section when
3825 the whole file is parsed with one call.
3826*/
3827static enum XML_Error PTRCALL
3828ignoreSectionProcessor(XML_Parser parser,
3829 const char *start,
3830 const char *end,
3831 const char **endPtr)
3832{
Elliott Hughes72472942018-01-10 08:36:10 -08003833 enum XML_Error result = doIgnoreSection(parser, parser->m_encoding, &start, end,
3834 endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003835 if (result != XML_ERROR_NONE)
3836 return result;
3837 if (start) {
Elliott Hughes72472942018-01-10 08:36:10 -08003838 parser->m_processor = prologProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003839 return prologProcessor(parser, start, end, endPtr);
3840 }
3841 return result;
3842}
3843
3844/* startPtr gets set to non-null is the section is closed, and to null
3845 if the section is not yet closed.
3846*/
3847static enum XML_Error
3848doIgnoreSection(XML_Parser parser,
3849 const ENCODING *enc,
3850 const char **startPtr,
3851 const char *end,
3852 const char **nextPtr,
3853 XML_Bool haveMore)
3854{
3855 const char *next;
3856 int tok;
3857 const char *s = *startPtr;
3858 const char **eventPP;
3859 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08003860 if (enc == parser->m_encoding) {
3861 eventPP = &parser->m_eventPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003862 *eventPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08003863 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003864 }
3865 else {
Elliott Hughes72472942018-01-10 08:36:10 -08003866 /* It's not entirely clear, but it seems the following two lines
3867 * of code cannot be executed. The only occasions on which 'enc'
3868 * is not 'encoding' are when this function is called
3869 * from the internal entity processing, and IGNORE sections are an
3870 * error in internal entities.
3871 *
3872 * Since it really isn't clear that this is true, we keep the code
3873 * and just remove it from our coverage tests.
3874 *
3875 * LCOV_EXCL_START
3876 */
3877 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
3878 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
3879 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003880 }
3881 *eventPP = s;
3882 *startPtr = NULL;
3883 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3884 *eventEndPP = next;
3885 switch (tok) {
3886 case XML_TOK_IGNORE_SECT:
Elliott Hughes72472942018-01-10 08:36:10 -08003887 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003888 reportDefault(parser, enc, s, next);
3889 *startPtr = next;
3890 *nextPtr = next;
Elliott Hughes72472942018-01-10 08:36:10 -08003891 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003892 return XML_ERROR_ABORTED;
3893 else
3894 return XML_ERROR_NONE;
3895 case XML_TOK_INVALID:
3896 *eventPP = next;
3897 return XML_ERROR_INVALID_TOKEN;
3898 case XML_TOK_PARTIAL_CHAR:
3899 if (haveMore) {
3900 *nextPtr = s;
3901 return XML_ERROR_NONE;
3902 }
3903 return XML_ERROR_PARTIAL_CHAR;
3904 case XML_TOK_PARTIAL:
3905 case XML_TOK_NONE:
3906 if (haveMore) {
3907 *nextPtr = s;
3908 return XML_ERROR_NONE;
3909 }
3910 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3911 default:
Elliott Hughes72472942018-01-10 08:36:10 -08003912 /* All of the tokens that XmlIgnoreSectionTok() returns have
3913 * explicit cases to handle them, so this default case is never
3914 * executed. We keep it as a safety net anyway, and remove it
3915 * from our test coverage statistics.
3916 *
3917 * LCOV_EXCL_START
3918 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003919 *eventPP = next;
3920 return XML_ERROR_UNEXPECTED_STATE;
Elliott Hughes72472942018-01-10 08:36:10 -08003921 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003922 }
3923 /* not reached */
3924}
3925
3926#endif /* XML_DTD */
3927
3928static enum XML_Error
3929initializeEncoding(XML_Parser parser)
3930{
3931 const char *s;
3932#ifdef XML_UNICODE
3933 char encodingBuf[128];
Elliott Hughes72472942018-01-10 08:36:10 -08003934 /* See comments abount `protoclEncodingName` in parserInit() */
3935 if (!parser->m_protocolEncodingName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003936 s = NULL;
3937 else {
3938 int i;
Elliott Hughes72472942018-01-10 08:36:10 -08003939 for (i = 0; parser->m_protocolEncodingName[i]; i++) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003940 if (i == sizeof(encodingBuf) - 1
Elliott Hughes72472942018-01-10 08:36:10 -08003941 || (parser->m_protocolEncodingName[i] & ~0x7f) != 0) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003942 encodingBuf[0] = '\0';
3943 break;
3944 }
Elliott Hughes72472942018-01-10 08:36:10 -08003945 encodingBuf[i] = (char)parser->m_protocolEncodingName[i];
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003946 }
3947 encodingBuf[i] = '\0';
3948 s = encodingBuf;
3949 }
3950#else
Elliott Hughes72472942018-01-10 08:36:10 -08003951 s = parser->m_protocolEncodingName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003952#endif
Elliott Hughes72472942018-01-10 08:36:10 -08003953 if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(&parser->m_initEncoding, &parser->m_encoding, s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003954 return XML_ERROR_NONE;
Elliott Hughes72472942018-01-10 08:36:10 -08003955 return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003956}
3957
3958static enum XML_Error
3959processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3960 const char *s, const char *next)
3961{
3962 const char *encodingName = NULL;
3963 const XML_Char *storedEncName = NULL;
3964 const ENCODING *newEncoding = NULL;
3965 const char *version = NULL;
3966 const char *versionend;
3967 const XML_Char *storedversion = NULL;
3968 int standalone = -1;
Elliott Hughes72472942018-01-10 08:36:10 -08003969 if (!(parser->m_ns
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003970 ? XmlParseXmlDeclNS
3971 : XmlParseXmlDecl)(isGeneralTextEntity,
Elliott Hughes72472942018-01-10 08:36:10 -08003972 parser->m_encoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003973 s,
3974 next,
Elliott Hughes72472942018-01-10 08:36:10 -08003975 &parser->m_eventPtr,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003976 &version,
3977 &versionend,
3978 &encodingName,
3979 &newEncoding,
3980 &standalone)) {
3981 if (isGeneralTextEntity)
3982 return XML_ERROR_TEXT_DECL;
3983 else
3984 return XML_ERROR_XML_DECL;
3985 }
3986 if (!isGeneralTextEntity && standalone == 1) {
Elliott Hughes72472942018-01-10 08:36:10 -08003987 parser->m_dtd->standalone = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003988#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08003989 if (parser->m_paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
3990 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003991#endif /* XML_DTD */
3992 }
Elliott Hughes72472942018-01-10 08:36:10 -08003993 if (parser->m_xmlDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003994 if (encodingName != NULL) {
Elliott Hughes72472942018-01-10 08:36:10 -08003995 storedEncName = poolStoreString(&parser->m_temp2Pool,
3996 parser->m_encoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08003997 encodingName,
3998 encodingName
Elliott Hughes72472942018-01-10 08:36:10 -08003999 + XmlNameLength(parser->m_encoding, encodingName));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004000 if (!storedEncName)
4001 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004002 poolFinish(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004003 }
4004 if (version) {
Elliott Hughes72472942018-01-10 08:36:10 -08004005 storedversion = poolStoreString(&parser->m_temp2Pool,
4006 parser->m_encoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004007 version,
Elliott Hughes72472942018-01-10 08:36:10 -08004008 versionend - parser->m_encoding->minBytesPerChar);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004009 if (!storedversion)
4010 return XML_ERROR_NO_MEMORY;
4011 }
Elliott Hughes72472942018-01-10 08:36:10 -08004012 parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName, standalone);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004013 }
Elliott Hughes72472942018-01-10 08:36:10 -08004014 else if (parser->m_defaultHandler)
4015 reportDefault(parser, parser->m_encoding, s, next);
4016 if (parser->m_protocolEncodingName == NULL) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004017 if (newEncoding) {
Elliott Hughes72472942018-01-10 08:36:10 -08004018 /* Check that the specified encoding does not conflict with what
4019 * the parser has already deduced. Do we have the same number
4020 * of bytes in the smallest representation of a character? If
4021 * this is UTF-16, is it the same endianness?
4022 */
4023 if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
4024 || (newEncoding->minBytesPerChar == 2 &&
4025 newEncoding != parser->m_encoding)) {
4026 parser->m_eventPtr = encodingName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004027 return XML_ERROR_INCORRECT_ENCODING;
4028 }
Elliott Hughes72472942018-01-10 08:36:10 -08004029 parser->m_encoding = newEncoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004030 }
4031 else if (encodingName) {
4032 enum XML_Error result;
4033 if (!storedEncName) {
4034 storedEncName = poolStoreString(
Elliott Hughes72472942018-01-10 08:36:10 -08004035 &parser->m_temp2Pool, parser->m_encoding, encodingName,
4036 encodingName + XmlNameLength(parser->m_encoding, encodingName));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004037 if (!storedEncName)
4038 return XML_ERROR_NO_MEMORY;
4039 }
4040 result = handleUnknownEncoding(parser, storedEncName);
Elliott Hughes72472942018-01-10 08:36:10 -08004041 poolClear(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004042 if (result == XML_ERROR_UNKNOWN_ENCODING)
Elliott Hughes72472942018-01-10 08:36:10 -08004043 parser->m_eventPtr = encodingName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004044 return result;
4045 }
4046 }
4047
4048 if (storedEncName || storedversion)
Elliott Hughes72472942018-01-10 08:36:10 -08004049 poolClear(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004050
4051 return XML_ERROR_NONE;
4052}
4053
4054static enum XML_Error
4055handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
4056{
Elliott Hughes72472942018-01-10 08:36:10 -08004057 if (parser->m_unknownEncodingHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004058 XML_Encoding info;
4059 int i;
4060 for (i = 0; i < 256; i++)
4061 info.map[i] = -1;
4062 info.convert = NULL;
4063 info.data = NULL;
4064 info.release = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08004065 if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData, encodingName,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004066 &info)) {
4067 ENCODING *enc;
Elliott Hughes72472942018-01-10 08:36:10 -08004068 parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding());
4069 if (!parser->m_unknownEncodingMem) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004070 if (info.release)
4071 info.release(info.data);
4072 return XML_ERROR_NO_MEMORY;
4073 }
Elliott Hughes72472942018-01-10 08:36:10 -08004074 enc = (parser->m_ns
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004075 ? XmlInitUnknownEncodingNS
Elliott Hughes72472942018-01-10 08:36:10 -08004076 : XmlInitUnknownEncoding)(parser->m_unknownEncodingMem,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004077 info.map,
4078 info.convert,
4079 info.data);
4080 if (enc) {
Elliott Hughes72472942018-01-10 08:36:10 -08004081 parser->m_unknownEncodingData = info.data;
4082 parser->m_unknownEncodingRelease = info.release;
4083 parser->m_encoding = enc;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004084 return XML_ERROR_NONE;
4085 }
4086 }
4087 if (info.release != NULL)
4088 info.release(info.data);
4089 }
4090 return XML_ERROR_UNKNOWN_ENCODING;
4091}
4092
4093static enum XML_Error PTRCALL
4094prologInitProcessor(XML_Parser parser,
4095 const char *s,
4096 const char *end,
4097 const char **nextPtr)
4098{
4099 enum XML_Error result = initializeEncoding(parser);
4100 if (result != XML_ERROR_NONE)
4101 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004102 parser->m_processor = prologProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004103 return prologProcessor(parser, s, end, nextPtr);
4104}
4105
4106#ifdef XML_DTD
4107
4108static enum XML_Error PTRCALL
4109externalParEntInitProcessor(XML_Parser parser,
4110 const char *s,
4111 const char *end,
4112 const char **nextPtr)
4113{
4114 enum XML_Error result = initializeEncoding(parser);
4115 if (result != XML_ERROR_NONE)
4116 return result;
4117
4118 /* we know now that XML_Parse(Buffer) has been called,
4119 so we consider the external parameter entity read */
Elliott Hughes72472942018-01-10 08:36:10 -08004120 parser->m_dtd->paramEntityRead = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004121
Elliott Hughes72472942018-01-10 08:36:10 -08004122 if (parser->m_prologState.inEntityValue) {
4123 parser->m_processor = entityValueInitProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004124 return entityValueInitProcessor(parser, s, end, nextPtr);
4125 }
4126 else {
Elliott Hughes72472942018-01-10 08:36:10 -08004127 parser->m_processor = externalParEntProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004128 return externalParEntProcessor(parser, s, end, nextPtr);
4129 }
4130}
4131
4132static enum XML_Error PTRCALL
4133entityValueInitProcessor(XML_Parser parser,
4134 const char *s,
4135 const char *end,
4136 const char **nextPtr)
4137{
4138 int tok;
4139 const char *start = s;
4140 const char *next = start;
Elliott Hughes72472942018-01-10 08:36:10 -08004141 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004142
Elliott Hughes35e432d2012-09-09 14:23:38 -07004143 for (;;) {
Elliott Hughes72472942018-01-10 08:36:10 -08004144 tok = XmlPrologTok(parser->m_encoding, start, end, &next);
4145 parser->m_eventEndPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004146 if (tok <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08004147 if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004148 *nextPtr = s;
4149 return XML_ERROR_NONE;
4150 }
4151 switch (tok) {
4152 case XML_TOK_INVALID:
4153 return XML_ERROR_INVALID_TOKEN;
4154 case XML_TOK_PARTIAL:
4155 return XML_ERROR_UNCLOSED_TOKEN;
4156 case XML_TOK_PARTIAL_CHAR:
4157 return XML_ERROR_PARTIAL_CHAR;
4158 case XML_TOK_NONE: /* start == end */
4159 default:
4160 break;
4161 }
4162 /* found end of entity value - can store it now */
Elliott Hughes72472942018-01-10 08:36:10 -08004163 return storeEntityValue(parser, parser->m_encoding, s, end);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004164 }
4165 else if (tok == XML_TOK_XML_DECL) {
4166 enum XML_Error result;
4167 result = processXmlDecl(parser, 0, start, next);
4168 if (result != XML_ERROR_NONE)
4169 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004170 /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED. For that
4171 * to happen, a parameter entity parsing handler must have
4172 * attempted to suspend the parser, which fails and raises an
4173 * error. The parser can be aborted, but can't be suspended.
4174 */
4175 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004176 return XML_ERROR_ABORTED;
Elliott Hughes72472942018-01-10 08:36:10 -08004177 *nextPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004178 /* stop scanning for text declaration - we found one */
Elliott Hughes72472942018-01-10 08:36:10 -08004179 parser->m_processor = entityValueProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004180 return entityValueProcessor(parser, next, end, nextPtr);
4181 }
4182 /* If we are at the end of the buffer, this would cause XmlPrologTok to
4183 return XML_TOK_NONE on the next call, which would then cause the
4184 function to exit with *nextPtr set to s - that is what we want for other
4185 tokens, but not for the BOM - we would rather like to skip it;
4186 then, when this routine is entered the next time, XmlPrologTok will
4187 return XML_TOK_INVALID, since the BOM is still in the buffer
4188 */
Elliott Hughes72472942018-01-10 08:36:10 -08004189 else if (tok == XML_TOK_BOM && next == end && !parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004190 *nextPtr = next;
4191 return XML_ERROR_NONE;
4192 }
Elliott Hughes72472942018-01-10 08:36:10 -08004193 /* If we get this token, we have the start of what might be a
4194 normal tag, but not a declaration (i.e. it doesn't begin with
4195 "<!"). In a DTD context, that isn't legal.
4196 */
4197 else if (tok == XML_TOK_INSTANCE_START) {
4198 *nextPtr = next;
4199 return XML_ERROR_SYNTAX;
4200 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004201 start = next;
Elliott Hughes72472942018-01-10 08:36:10 -08004202 parser->m_eventPtr = start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004203 }
4204}
4205
4206static enum XML_Error PTRCALL
4207externalParEntProcessor(XML_Parser parser,
4208 const char *s,
4209 const char *end,
4210 const char **nextPtr)
4211{
4212 const char *next = s;
4213 int tok;
4214
Elliott Hughes72472942018-01-10 08:36:10 -08004215 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004216 if (tok <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08004217 if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004218 *nextPtr = s;
4219 return XML_ERROR_NONE;
4220 }
4221 switch (tok) {
4222 case XML_TOK_INVALID:
4223 return XML_ERROR_INVALID_TOKEN;
4224 case XML_TOK_PARTIAL:
4225 return XML_ERROR_UNCLOSED_TOKEN;
4226 case XML_TOK_PARTIAL_CHAR:
4227 return XML_ERROR_PARTIAL_CHAR;
4228 case XML_TOK_NONE: /* start == end */
4229 default:
4230 break;
4231 }
4232 }
4233 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
4234 However, when parsing an external subset, doProlog will not accept a BOM
4235 as valid, and report a syntax error, so we have to skip the BOM
4236 */
4237 else if (tok == XML_TOK_BOM) {
4238 s = next;
Elliott Hughes72472942018-01-10 08:36:10 -08004239 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004240 }
4241
Elliott Hughes72472942018-01-10 08:36:10 -08004242 parser->m_processor = prologProcessor;
4243 return doProlog(parser, parser->m_encoding, s, end, tok, next,
4244 nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004245}
4246
4247static enum XML_Error PTRCALL
4248entityValueProcessor(XML_Parser parser,
4249 const char *s,
4250 const char *end,
4251 const char **nextPtr)
4252{
4253 const char *start = s;
4254 const char *next = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004255 const ENCODING *enc = parser->m_encoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004256 int tok;
4257
4258 for (;;) {
4259 tok = XmlPrologTok(enc, start, end, &next);
4260 if (tok <= 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08004261 if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004262 *nextPtr = s;
4263 return XML_ERROR_NONE;
4264 }
4265 switch (tok) {
4266 case XML_TOK_INVALID:
4267 return XML_ERROR_INVALID_TOKEN;
4268 case XML_TOK_PARTIAL:
4269 return XML_ERROR_UNCLOSED_TOKEN;
4270 case XML_TOK_PARTIAL_CHAR:
4271 return XML_ERROR_PARTIAL_CHAR;
4272 case XML_TOK_NONE: /* start == end */
4273 default:
4274 break;
4275 }
4276 /* found end of entity value - can store it now */
4277 return storeEntityValue(parser, enc, s, end);
4278 }
4279 start = next;
4280 }
4281}
4282
4283#endif /* XML_DTD */
4284
4285static enum XML_Error PTRCALL
4286prologProcessor(XML_Parser parser,
4287 const char *s,
4288 const char *end,
4289 const char **nextPtr)
4290{
4291 const char *next = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004292 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
4293 return doProlog(parser, parser->m_encoding, s, end, tok, next,
4294 nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004295}
4296
4297static enum XML_Error
4298doProlog(XML_Parser parser,
4299 const ENCODING *enc,
4300 const char *s,
4301 const char *end,
4302 int tok,
4303 const char *next,
4304 const char **nextPtr,
4305 XML_Bool haveMore)
4306{
4307#ifdef XML_DTD
Elliott Hughesd07d5a72009-09-25 16:04:37 -07004308 static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004309#endif /* XML_DTD */
Elliott Hughes35e432d2012-09-09 14:23:38 -07004310 static const XML_Char atypeCDATA[] =
Elliott Hughesd07d5a72009-09-25 16:04:37 -07004311 { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
4312 static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
4313 static const XML_Char atypeIDREF[] =
4314 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
4315 static const XML_Char atypeIDREFS[] =
4316 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
4317 static const XML_Char atypeENTITY[] =
4318 { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
4319 static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
4320 ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004321 static const XML_Char atypeNMTOKEN[] = {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07004322 ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
4323 static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
4324 ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
4325 static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
4326 ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
4327 static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
4328 static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004329
4330 /* save one level of indirection */
Elliott Hughes72472942018-01-10 08:36:10 -08004331 DTD * const dtd = parser->m_dtd;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004332
4333 const char **eventPP;
4334 const char **eventEndPP;
4335 enum XML_Content_Quant quant;
4336
Elliott Hughes72472942018-01-10 08:36:10 -08004337 if (enc == parser->m_encoding) {
4338 eventPP = &parser->m_eventPtr;
4339 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004340 }
4341 else {
Elliott Hughes72472942018-01-10 08:36:10 -08004342 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
4343 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004344 }
4345
4346 for (;;) {
4347 int role;
4348 XML_Bool handleDefault = XML_TRUE;
4349 *eventPP = s;
4350 *eventEndPP = next;
4351 if (tok <= 0) {
4352 if (haveMore && tok != XML_TOK_INVALID) {
4353 *nextPtr = s;
4354 return XML_ERROR_NONE;
4355 }
4356 switch (tok) {
4357 case XML_TOK_INVALID:
4358 *eventPP = next;
4359 return XML_ERROR_INVALID_TOKEN;
4360 case XML_TOK_PARTIAL:
4361 return XML_ERROR_UNCLOSED_TOKEN;
4362 case XML_TOK_PARTIAL_CHAR:
4363 return XML_ERROR_PARTIAL_CHAR;
Elliott Hughes35e432d2012-09-09 14:23:38 -07004364 case -XML_TOK_PROLOG_S:
4365 tok = -tok;
4366 break;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004367 case XML_TOK_NONE:
4368#ifdef XML_DTD
4369 /* for internal PE NOT referenced between declarations */
Elliott Hughes72472942018-01-10 08:36:10 -08004370 if (enc != parser->m_encoding && !parser->m_openInternalEntities->betweenDecl) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004371 *nextPtr = s;
4372 return XML_ERROR_NONE;
4373 }
4374 /* WFC: PE Between Declarations - must check that PE contains
4375 complete markup, not only for external PEs, but also for
4376 internal PEs if the reference occurs between declarations.
4377 */
Elliott Hughes72472942018-01-10 08:36:10 -08004378 if (parser->m_isParamEntity || enc != parser->m_encoding) {
4379 if (XmlTokenRole(&parser->m_prologState, XML_TOK_NONE, end, end, enc)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004380 == XML_ROLE_ERROR)
4381 return XML_ERROR_INCOMPLETE_PE;
4382 *nextPtr = s;
4383 return XML_ERROR_NONE;
4384 }
4385#endif /* XML_DTD */
4386 return XML_ERROR_NO_ELEMENTS;
4387 default:
4388 tok = -tok;
4389 next = end;
4390 break;
4391 }
4392 }
Elliott Hughes72472942018-01-10 08:36:10 -08004393 role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004394 switch (role) {
4395 case XML_ROLE_XML_DECL:
4396 {
4397 enum XML_Error result = processXmlDecl(parser, 0, s, next);
4398 if (result != XML_ERROR_NONE)
4399 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004400 enc = parser->m_encoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004401 handleDefault = XML_FALSE;
4402 }
4403 break;
4404 case XML_ROLE_DOCTYPE_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004405 if (parser->m_startDoctypeDeclHandler) {
4406 parser->m_doctypeName = poolStoreString(&parser->m_tempPool, enc, s, next);
4407 if (!parser->m_doctypeName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004408 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004409 poolFinish(&parser->m_tempPool);
4410 parser->m_doctypePubid = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004411 handleDefault = XML_FALSE;
4412 }
Elliott Hughes72472942018-01-10 08:36:10 -08004413 parser->m_doctypeSysid = NULL; /* always initialize to NULL */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004414 break;
4415 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
Elliott Hughes72472942018-01-10 08:36:10 -08004416 if (parser->m_startDoctypeDeclHandler) {
4417 parser->m_startDoctypeDeclHandler(parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
4418 parser->m_doctypePubid, 1);
4419 parser->m_doctypeName = NULL;
4420 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004421 handleDefault = XML_FALSE;
4422 }
4423 break;
4424#ifdef XML_DTD
4425 case XML_ROLE_TEXT_DECL:
4426 {
4427 enum XML_Error result = processXmlDecl(parser, 1, s, next);
4428 if (result != XML_ERROR_NONE)
4429 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08004430 enc = parser->m_encoding;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004431 handleDefault = XML_FALSE;
4432 }
4433 break;
4434#endif /* XML_DTD */
4435 case XML_ROLE_DOCTYPE_PUBLIC_ID:
4436#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004437 parser->m_useForeignDTD = XML_FALSE;
4438 parser->m_declEntity = (ENTITY *)lookup(parser,
Elliott Hughes35e432d2012-09-09 14:23:38 -07004439 &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004440 externalSubsetName,
4441 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004442 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004443 return XML_ERROR_NO_MEMORY;
4444#endif /* XML_DTD */
4445 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004446 if (parser->m_startDoctypeDeclHandler) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004447 XML_Char *pubId;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004448 if (!XmlIsPublicId(enc, s, next, eventPP))
4449 return XML_ERROR_PUBLICID;
Elliott Hughes72472942018-01-10 08:36:10 -08004450 pubId = poolStoreString(&parser->m_tempPool, enc,
Elliott Hughes35e432d2012-09-09 14:23:38 -07004451 s + enc->minBytesPerChar,
4452 next - enc->minBytesPerChar);
4453 if (!pubId)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004454 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07004455 normalizePublicId(pubId);
Elliott Hughes72472942018-01-10 08:36:10 -08004456 poolFinish(&parser->m_tempPool);
4457 parser->m_doctypePubid = pubId;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004458 handleDefault = XML_FALSE;
4459 goto alreadyChecked;
4460 }
4461 /* fall through */
4462 case XML_ROLE_ENTITY_PUBLIC_ID:
4463 if (!XmlIsPublicId(enc, s, next, eventPP))
4464 return XML_ERROR_PUBLICID;
4465 alreadyChecked:
Elliott Hughes72472942018-01-10 08:36:10 -08004466 if (dtd->keepProcessing && parser->m_declEntity) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004467 XML_Char *tem = poolStoreString(&dtd->pool,
4468 enc,
4469 s + enc->minBytesPerChar,
4470 next - enc->minBytesPerChar);
4471 if (!tem)
4472 return XML_ERROR_NO_MEMORY;
4473 normalizePublicId(tem);
Elliott Hughes72472942018-01-10 08:36:10 -08004474 parser->m_declEntity->publicId = tem;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004475 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004476 /* Don't suppress the default handler if we fell through from
4477 * the XML_ROLE_DOCTYPE_PUBLIC_ID case.
4478 */
4479 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004480 handleDefault = XML_FALSE;
4481 }
4482 break;
4483 case XML_ROLE_DOCTYPE_CLOSE:
Elliott Hughes72472942018-01-10 08:36:10 -08004484 if (parser->m_doctypeName) {
4485 parser->m_startDoctypeDeclHandler(parser->m_handlerArg, parser->m_doctypeName,
4486 parser->m_doctypeSysid, parser->m_doctypePubid, 0);
4487 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004488 handleDefault = XML_FALSE;
4489 }
Elliott Hughes72472942018-01-10 08:36:10 -08004490 /* parser->m_doctypeSysid will be non-NULL in the case of a previous
4491 XML_ROLE_DOCTYPE_SYSTEM_ID, even if parser->m_startDoctypeDeclHandler
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004492 was not set, indicating an external subset
4493 */
4494#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004495 if (parser->m_doctypeSysid || parser->m_useForeignDTD) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004496 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4497 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004498 if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004499 ENTITY *entity = (ENTITY *)lookup(parser,
4500 &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004501 externalSubsetName,
4502 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004503 if (!entity) {
4504 /* The external subset name "#" will have already been
4505 * inserted into the hash table at the start of the
4506 * external entity parsing, so no allocation will happen
4507 * and lookup() cannot fail.
4508 */
4509 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
4510 }
4511 if (parser->m_useForeignDTD)
4512 entity->base = parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004513 dtd->paramEntityRead = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08004514 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004515 0,
4516 entity->base,
4517 entity->systemId,
4518 entity->publicId))
4519 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4520 if (dtd->paramEntityRead) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004521 if (!dtd->standalone &&
Elliott Hughes72472942018-01-10 08:36:10 -08004522 parser->m_notStandaloneHandler &&
4523 !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004524 return XML_ERROR_NOT_STANDALONE;
4525 }
4526 /* if we didn't read the foreign DTD then this means that there
4527 is no external subset and we must reset dtd->hasParamEntityRefs
4528 */
Elliott Hughes72472942018-01-10 08:36:10 -08004529 else if (!parser->m_doctypeSysid)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004530 dtd->hasParamEntityRefs = hadParamEntityRefs;
4531 /* end of DTD - no need to update dtd->keepProcessing */
4532 }
Elliott Hughes72472942018-01-10 08:36:10 -08004533 parser->m_useForeignDTD = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004534 }
4535#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004536 if (parser->m_endDoctypeDeclHandler) {
4537 parser->m_endDoctypeDeclHandler(parser->m_handlerArg);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004538 handleDefault = XML_FALSE;
4539 }
4540 break;
4541 case XML_ROLE_INSTANCE_START:
4542#ifdef XML_DTD
4543 /* if there is no DOCTYPE declaration then now is the
4544 last chance to read the foreign DTD
4545 */
Elliott Hughes72472942018-01-10 08:36:10 -08004546 if (parser->m_useForeignDTD) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004547 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4548 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004549 if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07004550 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004551 externalSubsetName,
4552 sizeof(ENTITY));
4553 if (!entity)
4554 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004555 entity->base = parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004556 dtd->paramEntityRead = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08004557 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004558 0,
4559 entity->base,
4560 entity->systemId,
4561 entity->publicId))
4562 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4563 if (dtd->paramEntityRead) {
4564 if (!dtd->standalone &&
Elliott Hughes72472942018-01-10 08:36:10 -08004565 parser->m_notStandaloneHandler &&
4566 !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004567 return XML_ERROR_NOT_STANDALONE;
4568 }
4569 /* if we didn't read the foreign DTD then this means that there
4570 is no external subset and we must reset dtd->hasParamEntityRefs
4571 */
4572 else
4573 dtd->hasParamEntityRefs = hadParamEntityRefs;
4574 /* end of DTD - no need to update dtd->keepProcessing */
4575 }
4576 }
4577#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004578 parser->m_processor = contentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004579 return contentProcessor(parser, s, end, nextPtr);
4580 case XML_ROLE_ATTLIST_ELEMENT_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004581 parser->m_declElementType = getElementType(parser, enc, s, next);
4582 if (!parser->m_declElementType)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004583 return XML_ERROR_NO_MEMORY;
4584 goto checkAttListDeclHandler;
4585 case XML_ROLE_ATTRIBUTE_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004586 parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
4587 if (!parser->m_declAttributeId)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004588 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004589 parser->m_declAttributeIsCdata = XML_FALSE;
4590 parser->m_declAttributeType = NULL;
4591 parser->m_declAttributeIsId = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004592 goto checkAttListDeclHandler;
4593 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
Elliott Hughes72472942018-01-10 08:36:10 -08004594 parser->m_declAttributeIsCdata = XML_TRUE;
4595 parser->m_declAttributeType = atypeCDATA;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004596 goto checkAttListDeclHandler;
4597 case XML_ROLE_ATTRIBUTE_TYPE_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004598 parser->m_declAttributeIsId = XML_TRUE;
4599 parser->m_declAttributeType = atypeID;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004600 goto checkAttListDeclHandler;
4601 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
Elliott Hughes72472942018-01-10 08:36:10 -08004602 parser->m_declAttributeType = atypeIDREF;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004603 goto checkAttListDeclHandler;
4604 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
Elliott Hughes72472942018-01-10 08:36:10 -08004605 parser->m_declAttributeType = atypeIDREFS;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004606 goto checkAttListDeclHandler;
4607 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
Elliott Hughes72472942018-01-10 08:36:10 -08004608 parser->m_declAttributeType = atypeENTITY;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004609 goto checkAttListDeclHandler;
4610 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
Elliott Hughes72472942018-01-10 08:36:10 -08004611 parser->m_declAttributeType = atypeENTITIES;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004612 goto checkAttListDeclHandler;
4613 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
Elliott Hughes72472942018-01-10 08:36:10 -08004614 parser->m_declAttributeType = atypeNMTOKEN;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004615 goto checkAttListDeclHandler;
4616 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
Elliott Hughes72472942018-01-10 08:36:10 -08004617 parser->m_declAttributeType = atypeNMTOKENS;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004618 checkAttListDeclHandler:
Elliott Hughes72472942018-01-10 08:36:10 -08004619 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004620 handleDefault = XML_FALSE;
4621 break;
4622 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4623 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
Elliott Hughes72472942018-01-10 08:36:10 -08004624 if (dtd->keepProcessing && parser->m_attlistDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004625 const XML_Char *prefix;
Elliott Hughes72472942018-01-10 08:36:10 -08004626 if (parser->m_declAttributeType) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004627 prefix = enumValueSep;
4628 }
4629 else {
4630 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
4631 ? notationPrefix
4632 : enumValueStart);
4633 }
Elliott Hughes72472942018-01-10 08:36:10 -08004634 if (!poolAppendString(&parser->m_tempPool, prefix))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004635 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004636 if (!poolAppend(&parser->m_tempPool, enc, s, next))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004637 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004638 parser->m_declAttributeType = parser->m_tempPool.start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004639 handleDefault = XML_FALSE;
4640 }
4641 break;
4642 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4643 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4644 if (dtd->keepProcessing) {
Elliott Hughes72472942018-01-10 08:36:10 -08004645 if (!defineAttribute(parser->m_declElementType, parser->m_declAttributeId,
4646 parser->m_declAttributeIsCdata, parser->m_declAttributeIsId,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004647 0, parser))
4648 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004649 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
4650 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
4651 || (*parser->m_declAttributeType == XML_T(ASCII_N)
4652 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004653 /* Enumerated or Notation type */
Elliott Hughes72472942018-01-10 08:36:10 -08004654 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
4655 || !poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004656 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004657 parser->m_declAttributeType = parser->m_tempPool.start;
4658 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004659 }
4660 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004661 parser->m_attlistDeclHandler(parser->m_handlerArg, parser->m_declElementType->name,
4662 parser->m_declAttributeId->name, parser->m_declAttributeType,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004663 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
Elliott Hughes72472942018-01-10 08:36:10 -08004664 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004665 handleDefault = XML_FALSE;
4666 }
4667 }
4668 break;
4669 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4670 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4671 if (dtd->keepProcessing) {
4672 const XML_Char *attVal;
4673 enum XML_Error result =
Elliott Hughes72472942018-01-10 08:36:10 -08004674 storeAttributeValue(parser, enc, parser->m_declAttributeIsCdata,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004675 s + enc->minBytesPerChar,
4676 next - enc->minBytesPerChar,
4677 &dtd->pool);
4678 if (result)
4679 return result;
4680 attVal = poolStart(&dtd->pool);
4681 poolFinish(&dtd->pool);
4682 /* ID attributes aren't allowed to have a default */
Elliott Hughes72472942018-01-10 08:36:10 -08004683 if (!defineAttribute(parser->m_declElementType, parser->m_declAttributeId,
4684 parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004685 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004686 if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
4687 if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
4688 || (*parser->m_declAttributeType == XML_T(ASCII_N)
4689 && parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004690 /* Enumerated or Notation type */
Elliott Hughes72472942018-01-10 08:36:10 -08004691 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
4692 || !poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004693 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004694 parser->m_declAttributeType = parser->m_tempPool.start;
4695 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004696 }
4697 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004698 parser->m_attlistDeclHandler(parser->m_handlerArg, parser->m_declElementType->name,
4699 parser->m_declAttributeId->name, parser->m_declAttributeType,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004700 attVal,
4701 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
Elliott Hughes72472942018-01-10 08:36:10 -08004702 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004703 handleDefault = XML_FALSE;
4704 }
4705 }
4706 break;
4707 case XML_ROLE_ENTITY_VALUE:
4708 if (dtd->keepProcessing) {
4709 enum XML_Error result = storeEntityValue(parser, enc,
4710 s + enc->minBytesPerChar,
4711 next - enc->minBytesPerChar);
Elliott Hughes72472942018-01-10 08:36:10 -08004712 if (parser->m_declEntity) {
4713 parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
4714 parser->m_declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004715 poolFinish(&dtd->entityValuePool);
Elliott Hughes72472942018-01-10 08:36:10 -08004716 if (parser->m_entityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004717 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004718 parser->m_entityDeclHandler(parser->m_handlerArg,
4719 parser->m_declEntity->name,
4720 parser->m_declEntity->is_param,
4721 parser->m_declEntity->textPtr,
4722 parser->m_declEntity->textLen,
4723 parser->m_curBase, 0, 0, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004724 handleDefault = XML_FALSE;
4725 }
4726 }
4727 else
4728 poolDiscard(&dtd->entityValuePool);
4729 if (result != XML_ERROR_NONE)
4730 return result;
4731 }
4732 break;
4733 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4734#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004735 parser->m_useForeignDTD = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004736#endif /* XML_DTD */
4737 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08004738 if (parser->m_startDoctypeDeclHandler) {
4739 parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004740 s + enc->minBytesPerChar,
4741 next - enc->minBytesPerChar);
Elliott Hughes72472942018-01-10 08:36:10 -08004742 if (parser->m_doctypeSysid == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004743 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004744 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004745 handleDefault = XML_FALSE;
4746 }
4747#ifdef XML_DTD
4748 else
Elliott Hughes72472942018-01-10 08:36:10 -08004749 /* use externalSubsetName to make parser->m_doctypeSysid non-NULL
4750 for the case where no parser->m_startDoctypeDeclHandler is set */
4751 parser->m_doctypeSysid = externalSubsetName;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004752#endif /* XML_DTD */
4753 if (!dtd->standalone
4754#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08004755 && !parser->m_paramEntityParsing
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004756#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004757 && parser->m_notStandaloneHandler
4758 && !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004759 return XML_ERROR_NOT_STANDALONE;
4760#ifndef XML_DTD
4761 break;
4762#else /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004763 if (!parser->m_declEntity) {
4764 parser->m_declEntity = (ENTITY *)lookup(parser,
Elliott Hughes35e432d2012-09-09 14:23:38 -07004765 &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004766 externalSubsetName,
4767 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004768 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004769 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004770 parser->m_declEntity->publicId = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004771 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004772#endif /* XML_DTD */
Elliott Hughesaaec48e2018-08-16 16:29:01 -07004773 /* fall through */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004774 case XML_ROLE_ENTITY_SYSTEM_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004775 if (dtd->keepProcessing && parser->m_declEntity) {
4776 parser->m_declEntity->systemId = poolStoreString(&dtd->pool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004777 s + enc->minBytesPerChar,
4778 next - enc->minBytesPerChar);
Elliott Hughes72472942018-01-10 08:36:10 -08004779 if (!parser->m_declEntity->systemId)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004780 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004781 parser->m_declEntity->base = parser->m_curBase;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004782 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004783 /* Don't suppress the default handler if we fell through from
4784 * the XML_ROLE_DOCTYPE_SYSTEM_ID case.
4785 */
4786 if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004787 handleDefault = XML_FALSE;
4788 }
4789 break;
4790 case XML_ROLE_ENTITY_COMPLETE:
Elliott Hughes72472942018-01-10 08:36:10 -08004791 if (dtd->keepProcessing && parser->m_declEntity && parser->m_entityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004792 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004793 parser->m_entityDeclHandler(parser->m_handlerArg,
4794 parser->m_declEntity->name,
4795 parser->m_declEntity->is_param,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004796 0,0,
Elliott Hughes72472942018-01-10 08:36:10 -08004797 parser->m_declEntity->base,
4798 parser->m_declEntity->systemId,
4799 parser->m_declEntity->publicId,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004800 0);
4801 handleDefault = XML_FALSE;
4802 }
4803 break;
4804 case XML_ROLE_ENTITY_NOTATION_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004805 if (dtd->keepProcessing && parser->m_declEntity) {
4806 parser->m_declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4807 if (!parser->m_declEntity->notation)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004808 return XML_ERROR_NO_MEMORY;
4809 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004810 if (parser->m_unparsedEntityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004811 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004812 parser->m_unparsedEntityDeclHandler(parser->m_handlerArg,
4813 parser->m_declEntity->name,
4814 parser->m_declEntity->base,
4815 parser->m_declEntity->systemId,
4816 parser->m_declEntity->publicId,
4817 parser->m_declEntity->notation);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004818 handleDefault = XML_FALSE;
4819 }
Elliott Hughes72472942018-01-10 08:36:10 -08004820 else if (parser->m_entityDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004821 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004822 parser->m_entityDeclHandler(parser->m_handlerArg,
4823 parser->m_declEntity->name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004824 0,0,0,
Elliott Hughes72472942018-01-10 08:36:10 -08004825 parser->m_declEntity->base,
4826 parser->m_declEntity->systemId,
4827 parser->m_declEntity->publicId,
4828 parser->m_declEntity->notation);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004829 handleDefault = XML_FALSE;
4830 }
4831 }
4832 break;
4833 case XML_ROLE_GENERAL_ENTITY_NAME:
4834 {
4835 if (XmlPredefinedEntityName(enc, s, next)) {
Elliott Hughes72472942018-01-10 08:36:10 -08004836 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004837 break;
4838 }
4839 if (dtd->keepProcessing) {
4840 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4841 if (!name)
4842 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004843 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004844 sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004845 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004846 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004847 if (parser->m_declEntity->name != name) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004848 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004849 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004850 }
4851 else {
4852 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004853 parser->m_declEntity->publicId = NULL;
4854 parser->m_declEntity->is_param = XML_FALSE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004855 /* if we have a parent parser or are reading an internal parameter
4856 entity, then the entity declaration is not considered "internal"
4857 */
Elliott Hughes72472942018-01-10 08:36:10 -08004858 parser->m_declEntity->is_internal = !(parser->m_parentParser || parser->m_openInternalEntities);
4859 if (parser->m_entityDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004860 handleDefault = XML_FALSE;
4861 }
4862 }
4863 else {
4864 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004865 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004866 }
4867 }
4868 break;
4869 case XML_ROLE_PARAM_ENTITY_NAME:
4870#ifdef XML_DTD
4871 if (dtd->keepProcessing) {
4872 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4873 if (!name)
4874 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004875 parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004876 name, sizeof(ENTITY));
Elliott Hughes72472942018-01-10 08:36:10 -08004877 if (!parser->m_declEntity)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004878 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004879 if (parser->m_declEntity->name != name) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004880 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004881 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004882 }
4883 else {
4884 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004885 parser->m_declEntity->publicId = NULL;
4886 parser->m_declEntity->is_param = XML_TRUE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004887 /* if we have a parent parser or are reading an internal parameter
4888 entity, then the entity declaration is not considered "internal"
4889 */
Elliott Hughes72472942018-01-10 08:36:10 -08004890 parser->m_declEntity->is_internal = !(parser->m_parentParser || parser->m_openInternalEntities);
4891 if (parser->m_entityDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004892 handleDefault = XML_FALSE;
4893 }
4894 }
4895 else {
4896 poolDiscard(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08004897 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004898 }
4899#else /* not XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08004900 parser->m_declEntity = NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004901#endif /* XML_DTD */
4902 break;
4903 case XML_ROLE_NOTATION_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08004904 parser->m_declNotationPublicId = NULL;
4905 parser->m_declNotationName = NULL;
4906 if (parser->m_notationDeclHandler) {
4907 parser->m_declNotationName = poolStoreString(&parser->m_tempPool, enc, s, next);
4908 if (!parser->m_declNotationName)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004909 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004910 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004911 handleDefault = XML_FALSE;
4912 }
4913 break;
4914 case XML_ROLE_NOTATION_PUBLIC_ID:
4915 if (!XmlIsPublicId(enc, s, next, eventPP))
4916 return XML_ERROR_PUBLICID;
Elliott Hughes72472942018-01-10 08:36:10 -08004917 if (parser->m_declNotationName) { /* means m_notationDeclHandler != NULL */
4918 XML_Char *tem = poolStoreString(&parser->m_tempPool,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004919 enc,
4920 s + enc->minBytesPerChar,
4921 next - enc->minBytesPerChar);
4922 if (!tem)
4923 return XML_ERROR_NO_MEMORY;
4924 normalizePublicId(tem);
Elliott Hughes72472942018-01-10 08:36:10 -08004925 parser->m_declNotationPublicId = tem;
4926 poolFinish(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004927 handleDefault = XML_FALSE;
4928 }
4929 break;
4930 case XML_ROLE_NOTATION_SYSTEM_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004931 if (parser->m_declNotationName && parser->m_notationDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004932 const XML_Char *systemId
Elliott Hughes72472942018-01-10 08:36:10 -08004933 = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004934 s + enc->minBytesPerChar,
4935 next - enc->minBytesPerChar);
4936 if (!systemId)
4937 return XML_ERROR_NO_MEMORY;
4938 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004939 parser->m_notationDeclHandler(parser->m_handlerArg,
4940 parser->m_declNotationName,
4941 parser->m_curBase,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004942 systemId,
Elliott Hughes72472942018-01-10 08:36:10 -08004943 parser->m_declNotationPublicId);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004944 handleDefault = XML_FALSE;
4945 }
Elliott Hughes72472942018-01-10 08:36:10 -08004946 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004947 break;
4948 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
Elliott Hughes72472942018-01-10 08:36:10 -08004949 if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004950 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08004951 parser->m_notationDeclHandler(parser->m_handlerArg,
4952 parser->m_declNotationName,
4953 parser->m_curBase,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004954 0,
Elliott Hughes72472942018-01-10 08:36:10 -08004955 parser->m_declNotationPublicId);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004956 handleDefault = XML_FALSE;
4957 }
Elliott Hughes72472942018-01-10 08:36:10 -08004958 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004959 break;
4960 case XML_ROLE_ERROR:
4961 switch (tok) {
4962 case XML_TOK_PARAM_ENTITY_REF:
4963 /* PE references in internal subset are
Elliott Hughes35e432d2012-09-09 14:23:38 -07004964 not allowed within declarations. */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004965 return XML_ERROR_PARAM_ENTITY_REF;
4966 case XML_TOK_XML_DECL:
4967 return XML_ERROR_MISPLACED_XML_PI;
4968 default:
4969 return XML_ERROR_SYNTAX;
4970 }
4971#ifdef XML_DTD
4972 case XML_ROLE_IGNORE_SECT:
4973 {
4974 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08004975 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004976 reportDefault(parser, enc, s, next);
4977 handleDefault = XML_FALSE;
4978 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
4979 if (result != XML_ERROR_NONE)
4980 return result;
4981 else if (!next) {
Elliott Hughes72472942018-01-10 08:36:10 -08004982 parser->m_processor = ignoreSectionProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004983 return result;
4984 }
4985 }
4986 break;
4987#endif /* XML_DTD */
4988 case XML_ROLE_GROUP_OPEN:
Elliott Hughes72472942018-01-10 08:36:10 -08004989 if (parser->m_prologState.level >= parser->m_groupSize) {
4990 if (parser->m_groupSize) {
4991 char *temp = (char *)REALLOC(parser, parser->m_groupConnector, parser->m_groupSize *= 2);
4992 if (temp == NULL) {
4993 parser->m_groupSize /= 2;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004994 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08004995 }
4996 parser->m_groupConnector = temp;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08004997 if (dtd->scaffIndex) {
Elliott Hughes72472942018-01-10 08:36:10 -08004998 int *temp = (int *)REALLOC(parser, dtd->scaffIndex,
4999 parser->m_groupSize * sizeof(int));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005000 if (temp == NULL)
5001 return XML_ERROR_NO_MEMORY;
5002 dtd->scaffIndex = temp;
5003 }
5004 }
5005 else {
Elliott Hughes72472942018-01-10 08:36:10 -08005006 parser->m_groupConnector = (char *)MALLOC(parser, parser->m_groupSize = 32);
5007 if (!parser->m_groupConnector) {
5008 parser->m_groupSize = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005009 return XML_ERROR_NO_MEMORY;
Elliott Hughes72472942018-01-10 08:36:10 -08005010 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005011 }
5012 }
Elliott Hughes72472942018-01-10 08:36:10 -08005013 parser->m_groupConnector[parser->m_prologState.level] = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005014 if (dtd->in_eldecl) {
5015 int myindex = nextScaffoldPart(parser);
5016 if (myindex < 0)
5017 return XML_ERROR_NO_MEMORY;
5018 dtd->scaffIndex[dtd->scaffLevel] = myindex;
5019 dtd->scaffLevel++;
5020 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
Elliott Hughes72472942018-01-10 08:36:10 -08005021 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005022 handleDefault = XML_FALSE;
5023 }
5024 break;
5025 case XML_ROLE_GROUP_SEQUENCE:
Elliott Hughes72472942018-01-10 08:36:10 -08005026 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005027 return XML_ERROR_SYNTAX;
Elliott Hughes72472942018-01-10 08:36:10 -08005028 parser->m_groupConnector[parser->m_prologState.level] = ASCII_COMMA;
5029 if (dtd->in_eldecl && parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005030 handleDefault = XML_FALSE;
5031 break;
5032 case XML_ROLE_GROUP_CHOICE:
Elliott Hughes72472942018-01-10 08:36:10 -08005033 if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005034 return XML_ERROR_SYNTAX;
5035 if (dtd->in_eldecl
Elliott Hughes72472942018-01-10 08:36:10 -08005036 && !parser->m_groupConnector[parser->m_prologState.level]
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005037 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5038 != XML_CTYPE_MIXED)
5039 ) {
5040 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5041 = XML_CTYPE_CHOICE;
Elliott Hughes72472942018-01-10 08:36:10 -08005042 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005043 handleDefault = XML_FALSE;
5044 }
Elliott Hughes72472942018-01-10 08:36:10 -08005045 parser->m_groupConnector[parser->m_prologState.level] = ASCII_PIPE;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005046 break;
5047 case XML_ROLE_PARAM_ENTITY_REF:
5048#ifdef XML_DTD
5049 case XML_ROLE_INNER_PARAM_ENTITY_REF:
5050 dtd->hasParamEntityRefs = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005051 if (!parser->m_paramEntityParsing)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005052 dtd->keepProcessing = dtd->standalone;
5053 else {
5054 const XML_Char *name;
5055 ENTITY *entity;
5056 name = poolStoreString(&dtd->pool, enc,
5057 s + enc->minBytesPerChar,
5058 next - enc->minBytesPerChar);
5059 if (!name)
5060 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005061 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005062 poolDiscard(&dtd->pool);
5063 /* first, determine if a check for an existing declaration is needed;
5064 if yes, check that the entity exists, and that it is internal,
5065 otherwise call the skipped entity handler
5066 */
Elliott Hughes72472942018-01-10 08:36:10 -08005067 if (parser->m_prologState.documentEntity &&
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005068 (dtd->standalone
Elliott Hughes72472942018-01-10 08:36:10 -08005069 ? !parser->m_openInternalEntities
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005070 : !dtd->hasParamEntityRefs)) {
5071 if (!entity)
5072 return XML_ERROR_UNDEFINED_ENTITY;
Elliott Hughes72472942018-01-10 08:36:10 -08005073 else if (!entity->is_internal) {
5074 /* It's hard to exhaustively search the code to be sure,
5075 * but there doesn't seem to be a way of executing the
5076 * following line. There are two cases:
5077 *
5078 * If 'standalone' is false, the DTD must have no
5079 * parameter entities or we wouldn't have passed the outer
5080 * 'if' statement. That measn the only entity in the hash
5081 * table is the external subset name "#" which cannot be
5082 * given as a parameter entity name in XML syntax, so the
5083 * lookup must have returned NULL and we don't even reach
5084 * the test for an internal entity.
5085 *
5086 * If 'standalone' is true, it does not seem to be
5087 * possible to create entities taking this code path that
5088 * are not internal entities, so fail the test above.
5089 *
5090 * Because this analysis is very uncertain, the code is
5091 * being left in place and merely removed from the
5092 * coverage test statistics.
5093 */
5094 return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
5095 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005096 }
5097 else if (!entity) {
5098 dtd->keepProcessing = dtd->standalone;
5099 /* cannot report skipped entities in declarations */
Elliott Hughes72472942018-01-10 08:36:10 -08005100 if ((role == XML_ROLE_PARAM_ENTITY_REF) && parser->m_skippedEntityHandler) {
5101 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005102 handleDefault = XML_FALSE;
5103 }
5104 break;
5105 }
5106 if (entity->open)
5107 return XML_ERROR_RECURSIVE_ENTITY_REF;
5108 if (entity->textPtr) {
5109 enum XML_Error result;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005110 XML_Bool betweenDecl =
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005111 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
5112 result = processInternalEntity(parser, entity, betweenDecl);
5113 if (result != XML_ERROR_NONE)
5114 return result;
5115 handleDefault = XML_FALSE;
5116 break;
5117 }
Elliott Hughes72472942018-01-10 08:36:10 -08005118 if (parser->m_externalEntityRefHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005119 dtd->paramEntityRead = XML_FALSE;
5120 entity->open = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005121 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005122 0,
5123 entity->base,
5124 entity->systemId,
5125 entity->publicId)) {
5126 entity->open = XML_FALSE;
5127 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5128 }
5129 entity->open = XML_FALSE;
5130 handleDefault = XML_FALSE;
5131 if (!dtd->paramEntityRead) {
5132 dtd->keepProcessing = dtd->standalone;
5133 break;
5134 }
5135 }
5136 else {
5137 dtd->keepProcessing = dtd->standalone;
5138 break;
5139 }
5140 }
5141#endif /* XML_DTD */
5142 if (!dtd->standalone &&
Elliott Hughes72472942018-01-10 08:36:10 -08005143 parser->m_notStandaloneHandler &&
5144 !parser->m_notStandaloneHandler(parser->m_handlerArg))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005145 return XML_ERROR_NOT_STANDALONE;
5146 break;
5147
5148 /* Element declaration stuff */
5149
5150 case XML_ROLE_ELEMENT_NAME:
Elliott Hughes72472942018-01-10 08:36:10 -08005151 if (parser->m_elementDeclHandler) {
5152 parser->m_declElementType = getElementType(parser, enc, s, next);
5153 if (!parser->m_declElementType)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005154 return XML_ERROR_NO_MEMORY;
5155 dtd->scaffLevel = 0;
5156 dtd->scaffCount = 0;
5157 dtd->in_eldecl = XML_TRUE;
5158 handleDefault = XML_FALSE;
5159 }
5160 break;
5161
5162 case XML_ROLE_CONTENT_ANY:
5163 case XML_ROLE_CONTENT_EMPTY:
5164 if (dtd->in_eldecl) {
Elliott Hughes72472942018-01-10 08:36:10 -08005165 if (parser->m_elementDeclHandler) {
5166 XML_Content * content = (XML_Content *) MALLOC(parser, sizeof(XML_Content));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005167 if (!content)
5168 return XML_ERROR_NO_MEMORY;
5169 content->quant = XML_CQUANT_NONE;
5170 content->name = NULL;
5171 content->numchildren = 0;
5172 content->children = NULL;
5173 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
5174 XML_CTYPE_ANY :
5175 XML_CTYPE_EMPTY);
5176 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08005177 parser->m_elementDeclHandler(parser->m_handlerArg, parser->m_declElementType->name, content);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005178 handleDefault = XML_FALSE;
5179 }
5180 dtd->in_eldecl = XML_FALSE;
5181 }
5182 break;
5183
5184 case XML_ROLE_CONTENT_PCDATA:
5185 if (dtd->in_eldecl) {
5186 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5187 = XML_CTYPE_MIXED;
Elliott Hughes72472942018-01-10 08:36:10 -08005188 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005189 handleDefault = XML_FALSE;
5190 }
5191 break;
5192
5193 case XML_ROLE_CONTENT_ELEMENT:
5194 quant = XML_CQUANT_NONE;
5195 goto elementContent;
5196 case XML_ROLE_CONTENT_ELEMENT_OPT:
5197 quant = XML_CQUANT_OPT;
5198 goto elementContent;
5199 case XML_ROLE_CONTENT_ELEMENT_REP:
5200 quant = XML_CQUANT_REP;
5201 goto elementContent;
5202 case XML_ROLE_CONTENT_ELEMENT_PLUS:
5203 quant = XML_CQUANT_PLUS;
5204 elementContent:
5205 if (dtd->in_eldecl) {
5206 ELEMENT_TYPE *el;
5207 const XML_Char *name;
5208 int nameLen;
5209 const char *nxt = (quant == XML_CQUANT_NONE
5210 ? next
5211 : next - enc->minBytesPerChar);
5212 int myindex = nextScaffoldPart(parser);
5213 if (myindex < 0)
5214 return XML_ERROR_NO_MEMORY;
5215 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
5216 dtd->scaffold[myindex].quant = quant;
5217 el = getElementType(parser, enc, s, nxt);
5218 if (!el)
5219 return XML_ERROR_NO_MEMORY;
5220 name = el->name;
5221 dtd->scaffold[myindex].name = name;
5222 nameLen = 0;
5223 for (; name[nameLen++]; );
5224 dtd->contentStringLen += nameLen;
Elliott Hughes72472942018-01-10 08:36:10 -08005225 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005226 handleDefault = XML_FALSE;
5227 }
5228 break;
5229
5230 case XML_ROLE_GROUP_CLOSE:
5231 quant = XML_CQUANT_NONE;
5232 goto closeGroup;
5233 case XML_ROLE_GROUP_CLOSE_OPT:
5234 quant = XML_CQUANT_OPT;
5235 goto closeGroup;
5236 case XML_ROLE_GROUP_CLOSE_REP:
5237 quant = XML_CQUANT_REP;
5238 goto closeGroup;
5239 case XML_ROLE_GROUP_CLOSE_PLUS:
5240 quant = XML_CQUANT_PLUS;
5241 closeGroup:
5242 if (dtd->in_eldecl) {
Elliott Hughes72472942018-01-10 08:36:10 -08005243 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005244 handleDefault = XML_FALSE;
5245 dtd->scaffLevel--;
5246 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
5247 if (dtd->scaffLevel == 0) {
5248 if (!handleDefault) {
5249 XML_Content *model = build_model(parser);
5250 if (!model)
5251 return XML_ERROR_NO_MEMORY;
5252 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08005253 parser->m_elementDeclHandler(parser->m_handlerArg, parser->m_declElementType->name, model);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005254 }
5255 dtd->in_eldecl = XML_FALSE;
5256 dtd->contentStringLen = 0;
5257 }
5258 }
5259 break;
5260 /* End element declaration stuff */
5261
5262 case XML_ROLE_PI:
5263 if (!reportProcessingInstruction(parser, enc, s, next))
5264 return XML_ERROR_NO_MEMORY;
5265 handleDefault = XML_FALSE;
5266 break;
5267 case XML_ROLE_COMMENT:
5268 if (!reportComment(parser, enc, s, next))
5269 return XML_ERROR_NO_MEMORY;
5270 handleDefault = XML_FALSE;
5271 break;
5272 case XML_ROLE_NONE:
5273 switch (tok) {
5274 case XML_TOK_BOM:
5275 handleDefault = XML_FALSE;
5276 break;
5277 }
5278 break;
5279 case XML_ROLE_DOCTYPE_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005280 if (parser->m_startDoctypeDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005281 handleDefault = XML_FALSE;
5282 break;
5283 case XML_ROLE_ENTITY_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005284 if (dtd->keepProcessing && parser->m_entityDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005285 handleDefault = XML_FALSE;
5286 break;
5287 case XML_ROLE_NOTATION_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005288 if (parser->m_notationDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005289 handleDefault = XML_FALSE;
5290 break;
5291 case XML_ROLE_ATTLIST_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005292 if (dtd->keepProcessing && parser->m_attlistDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005293 handleDefault = XML_FALSE;
5294 break;
5295 case XML_ROLE_ELEMENT_NONE:
Elliott Hughes72472942018-01-10 08:36:10 -08005296 if (parser->m_elementDeclHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005297 handleDefault = XML_FALSE;
5298 break;
5299 } /* end of big switch */
5300
Elliott Hughes72472942018-01-10 08:36:10 -08005301 if (handleDefault && parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005302 reportDefault(parser, enc, s, next);
5303
Elliott Hughes72472942018-01-10 08:36:10 -08005304 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07005305 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005306 *nextPtr = next;
5307 return XML_ERROR_NONE;
5308 case XML_FINISHED:
5309 return XML_ERROR_ABORTED;
5310 default:
5311 s = next;
5312 tok = XmlPrologTok(enc, s, end, &next);
5313 }
5314 }
5315 /* not reached */
5316}
5317
5318static enum XML_Error PTRCALL
5319epilogProcessor(XML_Parser parser,
5320 const char *s,
5321 const char *end,
5322 const char **nextPtr)
5323{
Elliott Hughes72472942018-01-10 08:36:10 -08005324 parser->m_processor = epilogProcessor;
5325 parser->m_eventPtr = s;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005326 for (;;) {
5327 const char *next = NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08005328 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5329 parser->m_eventEndPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005330 switch (tok) {
5331 /* report partial linebreak - it might be the last token */
5332 case -XML_TOK_PROLOG_S:
Elliott Hughes72472942018-01-10 08:36:10 -08005333 if (parser->m_defaultHandler) {
5334 reportDefault(parser, parser->m_encoding, s, next);
5335 if (parser->m_parsingStatus.parsing == XML_FINISHED)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005336 return XML_ERROR_ABORTED;
5337 }
5338 *nextPtr = next;
5339 return XML_ERROR_NONE;
5340 case XML_TOK_NONE:
5341 *nextPtr = s;
5342 return XML_ERROR_NONE;
5343 case XML_TOK_PROLOG_S:
Elliott Hughes72472942018-01-10 08:36:10 -08005344 if (parser->m_defaultHandler)
5345 reportDefault(parser, parser->m_encoding, s, next);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005346 break;
5347 case XML_TOK_PI:
Elliott Hughes72472942018-01-10 08:36:10 -08005348 if (!reportProcessingInstruction(parser, parser->m_encoding, s, next))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005349 return XML_ERROR_NO_MEMORY;
5350 break;
5351 case XML_TOK_COMMENT:
Elliott Hughes72472942018-01-10 08:36:10 -08005352 if (!reportComment(parser, parser->m_encoding, s, next))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005353 return XML_ERROR_NO_MEMORY;
5354 break;
5355 case XML_TOK_INVALID:
Elliott Hughes72472942018-01-10 08:36:10 -08005356 parser->m_eventPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005357 return XML_ERROR_INVALID_TOKEN;
5358 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08005359 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005360 *nextPtr = s;
5361 return XML_ERROR_NONE;
5362 }
5363 return XML_ERROR_UNCLOSED_TOKEN;
5364 case XML_TOK_PARTIAL_CHAR:
Elliott Hughes72472942018-01-10 08:36:10 -08005365 if (!parser->m_parsingStatus.finalBuffer) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005366 *nextPtr = s;
5367 return XML_ERROR_NONE;
5368 }
5369 return XML_ERROR_PARTIAL_CHAR;
5370 default:
5371 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
5372 }
Elliott Hughes72472942018-01-10 08:36:10 -08005373 parser->m_eventPtr = s = next;
5374 switch (parser->m_parsingStatus.parsing) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07005375 case XML_SUSPENDED:
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005376 *nextPtr = next;
5377 return XML_ERROR_NONE;
5378 case XML_FINISHED:
5379 return XML_ERROR_ABORTED;
5380 default: ;
5381 }
5382 }
5383}
5384
5385static enum XML_Error
5386processInternalEntity(XML_Parser parser, ENTITY *entity,
5387 XML_Bool betweenDecl)
5388{
5389 const char *textStart, *textEnd;
5390 const char *next;
5391 enum XML_Error result;
5392 OPEN_INTERNAL_ENTITY *openEntity;
5393
Elliott Hughes72472942018-01-10 08:36:10 -08005394 if (parser->m_freeInternalEntities) {
5395 openEntity = parser->m_freeInternalEntities;
5396 parser->m_freeInternalEntities = openEntity->next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005397 }
5398 else {
Elliott Hughes72472942018-01-10 08:36:10 -08005399 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005400 if (!openEntity)
5401 return XML_ERROR_NO_MEMORY;
5402 }
5403 entity->open = XML_TRUE;
5404 entity->processed = 0;
Elliott Hughes72472942018-01-10 08:36:10 -08005405 openEntity->next = parser->m_openInternalEntities;
5406 parser->m_openInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005407 openEntity->entity = entity;
Elliott Hughes72472942018-01-10 08:36:10 -08005408 openEntity->startTagLevel = parser->m_tagLevel;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005409 openEntity->betweenDecl = betweenDecl;
5410 openEntity->internalEventPtr = NULL;
5411 openEntity->internalEventEndPtr = NULL;
5412 textStart = (char *)entity->textPtr;
5413 textEnd = (char *)(entity->textPtr + entity->textLen);
Elliott Hughes72472942018-01-10 08:36:10 -08005414 /* Set a safe default value in case 'next' does not get set */
5415 next = textStart;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005416
5417#ifdef XML_DTD
5418 if (entity->is_param) {
Elliott Hughes72472942018-01-10 08:36:10 -08005419 int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5420 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005421 next, &next, XML_FALSE);
5422 }
Elliott Hughes35e432d2012-09-09 14:23:38 -07005423 else
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005424#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08005425 result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding, textStart,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005426 textEnd, &next, XML_FALSE);
5427
5428 if (result == XML_ERROR_NONE) {
Elliott Hughes72472942018-01-10 08:36:10 -08005429 if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005430 entity->processed = (int)(next - textStart);
Elliott Hughes72472942018-01-10 08:36:10 -08005431 parser->m_processor = internalEntityProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005432 }
5433 else {
5434 entity->open = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08005435 parser->m_openInternalEntities = openEntity->next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005436 /* put openEntity back in list of free instances */
Elliott Hughes72472942018-01-10 08:36:10 -08005437 openEntity->next = parser->m_freeInternalEntities;
5438 parser->m_freeInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005439 }
5440 }
5441 return result;
5442}
5443
5444static enum XML_Error PTRCALL
5445internalEntityProcessor(XML_Parser parser,
5446 const char *s,
5447 const char *end,
5448 const char **nextPtr)
5449{
5450 ENTITY *entity;
5451 const char *textStart, *textEnd;
5452 const char *next;
5453 enum XML_Error result;
Elliott Hughes72472942018-01-10 08:36:10 -08005454 OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005455 if (!openEntity)
5456 return XML_ERROR_UNEXPECTED_STATE;
5457
5458 entity = openEntity->entity;
5459 textStart = ((char *)entity->textPtr) + entity->processed;
5460 textEnd = (char *)(entity->textPtr + entity->textLen);
Elliott Hughes72472942018-01-10 08:36:10 -08005461 /* Set a safe default value in case 'next' does not get set */
5462 next = textStart;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005463
5464#ifdef XML_DTD
5465 if (entity->is_param) {
Elliott Hughes72472942018-01-10 08:36:10 -08005466 int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
5467 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005468 next, &next, XML_FALSE);
5469 }
5470 else
5471#endif /* XML_DTD */
Elliott Hughes72472942018-01-10 08:36:10 -08005472 result = doContent(parser, openEntity->startTagLevel, parser->m_internalEncoding,
Elliott Hughes35e432d2012-09-09 14:23:38 -07005473 textStart, textEnd, &next, XML_FALSE);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005474
5475 if (result != XML_ERROR_NONE)
5476 return result;
Elliott Hughes72472942018-01-10 08:36:10 -08005477 else if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005478 entity->processed = (int)(next - (char *)entity->textPtr);
5479 return result;
5480 }
5481 else {
5482 entity->open = XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08005483 parser->m_openInternalEntities = openEntity->next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005484 /* put openEntity back in list of free instances */
Elliott Hughes72472942018-01-10 08:36:10 -08005485 openEntity->next = parser->m_freeInternalEntities;
5486 parser->m_freeInternalEntities = openEntity;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005487 }
5488
5489#ifdef XML_DTD
5490 if (entity->is_param) {
5491 int tok;
Elliott Hughes72472942018-01-10 08:36:10 -08005492 parser->m_processor = prologProcessor;
5493 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
5494 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
5495 (XML_Bool)!parser->m_parsingStatus.finalBuffer);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005496 }
5497 else
5498#endif /* XML_DTD */
5499 {
Elliott Hughes72472942018-01-10 08:36:10 -08005500 parser->m_processor = contentProcessor;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005501 /* see externalEntityContentProcessor vs contentProcessor */
Elliott Hughes72472942018-01-10 08:36:10 -08005502 return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, s, end,
5503 nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
Elliott Hughes35e432d2012-09-09 14:23:38 -07005504 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005505}
5506
5507static enum XML_Error PTRCALL
5508errorProcessor(XML_Parser parser,
Paul Duffinba34a0c2017-02-27 14:40:16 +00005509 const char *UNUSED_P(s),
5510 const char *UNUSED_P(end),
5511 const char **UNUSED_P(nextPtr))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005512{
Elliott Hughes72472942018-01-10 08:36:10 -08005513 return parser->m_errorCode;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005514}
5515
5516static enum XML_Error
5517storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5518 const char *ptr, const char *end,
5519 STRING_POOL *pool)
5520{
5521 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
5522 end, pool);
5523 if (result)
5524 return result;
5525 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
5526 poolChop(pool);
5527 if (!poolAppendChar(pool, XML_T('\0')))
5528 return XML_ERROR_NO_MEMORY;
5529 return XML_ERROR_NONE;
5530}
5531
5532static enum XML_Error
5533appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5534 const char *ptr, const char *end,
5535 STRING_POOL *pool)
5536{
Elliott Hughes72472942018-01-10 08:36:10 -08005537 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005538 for (;;) {
5539 const char *next;
5540 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
5541 switch (tok) {
5542 case XML_TOK_NONE:
5543 return XML_ERROR_NONE;
5544 case XML_TOK_INVALID:
Elliott Hughes72472942018-01-10 08:36:10 -08005545 if (enc == parser->m_encoding)
5546 parser->m_eventPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005547 return XML_ERROR_INVALID_TOKEN;
5548 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08005549 if (enc == parser->m_encoding)
5550 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005551 return XML_ERROR_INVALID_TOKEN;
5552 case XML_TOK_CHAR_REF:
5553 {
5554 XML_Char buf[XML_ENCODE_MAX];
5555 int i;
5556 int n = XmlCharRefNumber(enc, ptr);
5557 if (n < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08005558 if (enc == parser->m_encoding)
5559 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005560 return XML_ERROR_BAD_CHAR_REF;
5561 }
5562 if (!isCdata
5563 && n == 0x20 /* space */
5564 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5565 break;
5566 n = XmlEncode(n, (ICHAR *)buf);
Elliott Hughes72472942018-01-10 08:36:10 -08005567 /* The XmlEncode() functions can never return 0 here. That
5568 * error return happens if the code point passed in is either
5569 * negative or greater than or equal to 0x110000. The
5570 * XmlCharRefNumber() functions will all return a number
5571 * strictly less than 0x110000 or a negative value if an error
5572 * occurred. The negative value is intercepted above, so
5573 * XmlEncode() is never passed a value it might return an
5574 * error for.
5575 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005576 for (i = 0; i < n; i++) {
5577 if (!poolAppendChar(pool, buf[i]))
5578 return XML_ERROR_NO_MEMORY;
5579 }
5580 }
5581 break;
5582 case XML_TOK_DATA_CHARS:
5583 if (!poolAppend(pool, enc, ptr, next))
5584 return XML_ERROR_NO_MEMORY;
5585 break;
5586 case XML_TOK_TRAILING_CR:
5587 next = ptr + enc->minBytesPerChar;
5588 /* fall through */
5589 case XML_TOK_ATTRIBUTE_VALUE_S:
5590 case XML_TOK_DATA_NEWLINE:
5591 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5592 break;
5593 if (!poolAppendChar(pool, 0x20))
5594 return XML_ERROR_NO_MEMORY;
5595 break;
5596 case XML_TOK_ENTITY_REF:
5597 {
5598 const XML_Char *name;
5599 ENTITY *entity;
5600 char checkEntityDecl;
5601 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
5602 ptr + enc->minBytesPerChar,
5603 next - enc->minBytesPerChar);
5604 if (ch) {
5605 if (!poolAppendChar(pool, ch))
5606 return XML_ERROR_NO_MEMORY;
5607 break;
5608 }
Elliott Hughes72472942018-01-10 08:36:10 -08005609 name = poolStoreString(&parser->m_temp2Pool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005610 ptr + enc->minBytesPerChar,
5611 next - enc->minBytesPerChar);
5612 if (!name)
5613 return XML_ERROR_NO_MEMORY;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005614 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
Elliott Hughes72472942018-01-10 08:36:10 -08005615 poolDiscard(&parser->m_temp2Pool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005616 /* First, determine if a check for an existing declaration is needed;
5617 if yes, check that the entity exists, and that it is internal.
5618 */
5619 if (pool == &dtd->pool) /* are we called from prolog? */
5620 checkEntityDecl =
5621#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005622 parser->m_prologState.documentEntity &&
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005623#endif /* XML_DTD */
5624 (dtd->standalone
Elliott Hughes72472942018-01-10 08:36:10 -08005625 ? !parser->m_openInternalEntities
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005626 : !dtd->hasParamEntityRefs);
Elliott Hughes72472942018-01-10 08:36:10 -08005627 else /* if (pool == &parser->m_tempPool): we are called from content */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005628 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
5629 if (checkEntityDecl) {
5630 if (!entity)
5631 return XML_ERROR_UNDEFINED_ENTITY;
5632 else if (!entity->is_internal)
5633 return XML_ERROR_ENTITY_DECLARED_IN_PE;
5634 }
5635 else if (!entity) {
5636 /* Cannot report skipped entity here - see comments on
Elliott Hughes72472942018-01-10 08:36:10 -08005637 parser->m_skippedEntityHandler.
5638 if (parser->m_skippedEntityHandler)
5639 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005640 */
5641 /* Cannot call the default handler because this would be
5642 out of sync with the call to the startElementHandler.
Elliott Hughes72472942018-01-10 08:36:10 -08005643 if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005644 reportDefault(parser, enc, ptr, next);
5645 */
5646 break;
5647 }
5648 if (entity->open) {
Elliott Hughes72472942018-01-10 08:36:10 -08005649 if (enc == parser->m_encoding) {
5650 /* It does not appear that this line can be executed.
5651 *
5652 * The "if (entity->open)" check catches recursive entity
5653 * definitions. In order to be called with an open
5654 * entity, it must have gone through this code before and
5655 * been through the recursive call to
5656 * appendAttributeValue() some lines below. That call
5657 * sets the local encoding ("enc") to the parser's
5658 * internal encoding (internal_utf8 or internal_utf16),
5659 * which can never be the same as the principle encoding.
5660 * It doesn't appear there is another code path that gets
5661 * here with entity->open being TRUE.
5662 *
5663 * Since it is not certain that this logic is watertight,
5664 * we keep the line and merely exclude it from coverage
5665 * tests.
5666 */
5667 parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
5668 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005669 return XML_ERROR_RECURSIVE_ENTITY_REF;
5670 }
5671 if (entity->notation) {
Elliott Hughes72472942018-01-10 08:36:10 -08005672 if (enc == parser->m_encoding)
5673 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005674 return XML_ERROR_BINARY_ENTITY_REF;
5675 }
5676 if (!entity->textPtr) {
Elliott Hughes72472942018-01-10 08:36:10 -08005677 if (enc == parser->m_encoding)
5678 parser->m_eventPtr = ptr;
Elliott Hughes35e432d2012-09-09 14:23:38 -07005679 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005680 }
5681 else {
5682 enum XML_Error result;
5683 const XML_Char *textEnd = entity->textPtr + entity->textLen;
5684 entity->open = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005685 result = appendAttributeValue(parser, parser->m_internalEncoding, isCdata,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005686 (char *)entity->textPtr,
5687 (char *)textEnd, pool);
5688 entity->open = XML_FALSE;
5689 if (result)
5690 return result;
5691 }
5692 }
5693 break;
5694 default:
Elliott Hughes72472942018-01-10 08:36:10 -08005695 /* The only token returned by XmlAttributeValueTok() that does
5696 * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
5697 * Getting that would require an entity name to contain an
5698 * incomplete XML character (e.g. \xE2\x82); however previous
5699 * tokenisers will have already recognised and rejected such
5700 * names before XmlAttributeValueTok() gets a look-in. This
5701 * default case should be retained as a safety net, but the code
5702 * excluded from coverage tests.
5703 *
5704 * LCOV_EXCL_START
5705 */
5706 if (enc == parser->m_encoding)
5707 parser->m_eventPtr = ptr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005708 return XML_ERROR_UNEXPECTED_STATE;
Elliott Hughes72472942018-01-10 08:36:10 -08005709 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005710 }
5711 ptr = next;
5712 }
5713 /* not reached */
5714}
5715
5716static enum XML_Error
5717storeEntityValue(XML_Parser parser,
5718 const ENCODING *enc,
5719 const char *entityTextPtr,
5720 const char *entityTextEnd)
5721{
Elliott Hughes72472942018-01-10 08:36:10 -08005722 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005723 STRING_POOL *pool = &(dtd->entityValuePool);
5724 enum XML_Error result = XML_ERROR_NONE;
5725#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005726 int oldInEntityValue = parser->m_prologState.inEntityValue;
5727 parser->m_prologState.inEntityValue = 1;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005728#endif /* XML_DTD */
5729 /* never return Null for the value argument in EntityDeclHandler,
5730 since this would indicate an external entity; therefore we
5731 have to make sure that entityValuePool.start is not null */
5732 if (!pool->blocks) {
5733 if (!poolGrow(pool))
5734 return XML_ERROR_NO_MEMORY;
5735 }
5736
5737 for (;;) {
5738 const char *next;
5739 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5740 switch (tok) {
5741 case XML_TOK_PARAM_ENTITY_REF:
5742#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005743 if (parser->m_isParamEntity || enc != parser->m_encoding) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005744 const XML_Char *name;
5745 ENTITY *entity;
Elliott Hughes72472942018-01-10 08:36:10 -08005746 name = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005747 entityTextPtr + enc->minBytesPerChar,
5748 next - enc->minBytesPerChar);
5749 if (!name) {
5750 result = XML_ERROR_NO_MEMORY;
5751 goto endEntityValue;
5752 }
Elliott Hughes35e432d2012-09-09 14:23:38 -07005753 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
Elliott Hughes72472942018-01-10 08:36:10 -08005754 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005755 if (!entity) {
5756 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5757 /* cannot report skipped entity here - see comments on
Elliott Hughes72472942018-01-10 08:36:10 -08005758 parser->m_skippedEntityHandler
5759 if (parser->m_skippedEntityHandler)
5760 parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005761 */
5762 dtd->keepProcessing = dtd->standalone;
5763 goto endEntityValue;
5764 }
5765 if (entity->open) {
Elliott Hughes72472942018-01-10 08:36:10 -08005766 if (enc == parser->m_encoding)
5767 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005768 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5769 goto endEntityValue;
5770 }
5771 if (entity->systemId) {
Elliott Hughes72472942018-01-10 08:36:10 -08005772 if (parser->m_externalEntityRefHandler) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005773 dtd->paramEntityRead = XML_FALSE;
5774 entity->open = XML_TRUE;
Elliott Hughes72472942018-01-10 08:36:10 -08005775 if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005776 0,
5777 entity->base,
5778 entity->systemId,
5779 entity->publicId)) {
5780 entity->open = XML_FALSE;
5781 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5782 goto endEntityValue;
5783 }
5784 entity->open = XML_FALSE;
5785 if (!dtd->paramEntityRead)
5786 dtd->keepProcessing = dtd->standalone;
5787 }
5788 else
5789 dtd->keepProcessing = dtd->standalone;
5790 }
5791 else {
5792 entity->open = XML_TRUE;
5793 result = storeEntityValue(parser,
Elliott Hughes72472942018-01-10 08:36:10 -08005794 parser->m_internalEncoding,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005795 (char *)entity->textPtr,
5796 (char *)(entity->textPtr
5797 + entity->textLen));
5798 entity->open = XML_FALSE;
5799 if (result)
5800 goto endEntityValue;
5801 }
5802 break;
5803 }
5804#endif /* XML_DTD */
5805 /* In the internal subset, PE references are not legal
5806 within markup declarations, e.g entity values in this case. */
Elliott Hughes72472942018-01-10 08:36:10 -08005807 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005808 result = XML_ERROR_PARAM_ENTITY_REF;
5809 goto endEntityValue;
5810 case XML_TOK_NONE:
5811 result = XML_ERROR_NONE;
5812 goto endEntityValue;
5813 case XML_TOK_ENTITY_REF:
5814 case XML_TOK_DATA_CHARS:
5815 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5816 result = XML_ERROR_NO_MEMORY;
5817 goto endEntityValue;
5818 }
5819 break;
5820 case XML_TOK_TRAILING_CR:
5821 next = entityTextPtr + enc->minBytesPerChar;
5822 /* fall through */
5823 case XML_TOK_DATA_NEWLINE:
5824 if (pool->end == pool->ptr && !poolGrow(pool)) {
5825 result = XML_ERROR_NO_MEMORY;
5826 goto endEntityValue;
5827 }
5828 *(pool->ptr)++ = 0xA;
5829 break;
5830 case XML_TOK_CHAR_REF:
5831 {
5832 XML_Char buf[XML_ENCODE_MAX];
5833 int i;
5834 int n = XmlCharRefNumber(enc, entityTextPtr);
5835 if (n < 0) {
Elliott Hughes72472942018-01-10 08:36:10 -08005836 if (enc == parser->m_encoding)
5837 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005838 result = XML_ERROR_BAD_CHAR_REF;
5839 goto endEntityValue;
5840 }
5841 n = XmlEncode(n, (ICHAR *)buf);
Elliott Hughes72472942018-01-10 08:36:10 -08005842 /* The XmlEncode() functions can never return 0 here. That
5843 * error return happens if the code point passed in is either
5844 * negative or greater than or equal to 0x110000. The
5845 * XmlCharRefNumber() functions will all return a number
5846 * strictly less than 0x110000 or a negative value if an error
5847 * occurred. The negative value is intercepted above, so
5848 * XmlEncode() is never passed a value it might return an
5849 * error for.
5850 */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005851 for (i = 0; i < n; i++) {
5852 if (pool->end == pool->ptr && !poolGrow(pool)) {
5853 result = XML_ERROR_NO_MEMORY;
5854 goto endEntityValue;
5855 }
5856 *(pool->ptr)++ = buf[i];
5857 }
5858 }
5859 break;
5860 case XML_TOK_PARTIAL:
Elliott Hughes72472942018-01-10 08:36:10 -08005861 if (enc == parser->m_encoding)
5862 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005863 result = XML_ERROR_INVALID_TOKEN;
5864 goto endEntityValue;
5865 case XML_TOK_INVALID:
Elliott Hughes72472942018-01-10 08:36:10 -08005866 if (enc == parser->m_encoding)
5867 parser->m_eventPtr = next;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005868 result = XML_ERROR_INVALID_TOKEN;
5869 goto endEntityValue;
5870 default:
Elliott Hughes72472942018-01-10 08:36:10 -08005871 /* This default case should be unnecessary -- all the tokens
5872 * that XmlEntityValueTok() can return have their own explicit
5873 * cases -- but should be retained for safety. We do however
5874 * exclude it from the coverage statistics.
5875 *
5876 * LCOV_EXCL_START
5877 */
5878 if (enc == parser->m_encoding)
5879 parser->m_eventPtr = entityTextPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005880 result = XML_ERROR_UNEXPECTED_STATE;
5881 goto endEntityValue;
Elliott Hughes72472942018-01-10 08:36:10 -08005882 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005883 }
5884 entityTextPtr = next;
5885 }
5886endEntityValue:
5887#ifdef XML_DTD
Elliott Hughes72472942018-01-10 08:36:10 -08005888 parser->m_prologState.inEntityValue = oldInEntityValue;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005889#endif /* XML_DTD */
5890 return result;
5891}
5892
5893static void FASTCALL
5894normalizeLines(XML_Char *s)
5895{
5896 XML_Char *p;
5897 for (;; s++) {
5898 if (*s == XML_T('\0'))
5899 return;
5900 if (*s == 0xD)
5901 break;
5902 }
5903 p = s;
5904 do {
5905 if (*s == 0xD) {
5906 *p++ = 0xA;
5907 if (*++s == 0xA)
5908 s++;
5909 }
5910 else
5911 *p++ = *s++;
5912 } while (*s);
5913 *p = XML_T('\0');
5914}
5915
5916static int
5917reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5918 const char *start, const char *end)
5919{
5920 const XML_Char *target;
5921 XML_Char *data;
5922 const char *tem;
Elliott Hughes72472942018-01-10 08:36:10 -08005923 if (!parser->m_processingInstructionHandler) {
5924 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005925 reportDefault(parser, enc, start, end);
5926 return 1;
5927 }
5928 start += enc->minBytesPerChar * 2;
5929 tem = start + XmlNameLength(enc, start);
Elliott Hughes72472942018-01-10 08:36:10 -08005930 target = poolStoreString(&parser->m_tempPool, enc, start, tem);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005931 if (!target)
5932 return 0;
Elliott Hughes72472942018-01-10 08:36:10 -08005933 poolFinish(&parser->m_tempPool);
5934 data = poolStoreString(&parser->m_tempPool, enc,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005935 XmlSkipS(enc, tem),
5936 end - enc->minBytesPerChar*2);
5937 if (!data)
5938 return 0;
5939 normalizeLines(data);
Elliott Hughes72472942018-01-10 08:36:10 -08005940 parser->m_processingInstructionHandler(parser->m_handlerArg, target, data);
5941 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005942 return 1;
5943}
5944
5945static int
5946reportComment(XML_Parser parser, const ENCODING *enc,
5947 const char *start, const char *end)
5948{
5949 XML_Char *data;
Elliott Hughes72472942018-01-10 08:36:10 -08005950 if (!parser->m_commentHandler) {
5951 if (parser->m_defaultHandler)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005952 reportDefault(parser, enc, start, end);
5953 return 1;
5954 }
Elliott Hughes72472942018-01-10 08:36:10 -08005955 data = poolStoreString(&parser->m_tempPool,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005956 enc,
5957 start + enc->minBytesPerChar * 4,
5958 end - enc->minBytesPerChar * 3);
5959 if (!data)
5960 return 0;
5961 normalizeLines(data);
Elliott Hughes72472942018-01-10 08:36:10 -08005962 parser->m_commentHandler(parser->m_handlerArg, data);
5963 poolClear(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005964 return 1;
5965}
5966
5967static void
5968reportDefault(XML_Parser parser, const ENCODING *enc,
5969 const char *s, const char *end)
5970{
5971 if (MUST_CONVERT(enc, s)) {
Paul Duffin4bf8f122016-05-13 12:35:25 +01005972 enum XML_Convert_Result convert_res;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005973 const char **eventPP;
5974 const char **eventEndPP;
Elliott Hughes72472942018-01-10 08:36:10 -08005975 if (enc == parser->m_encoding) {
5976 eventPP = &parser->m_eventPtr;
5977 eventEndPP = &parser->m_eventEndPtr;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005978 }
5979 else {
Elliott Hughes72472942018-01-10 08:36:10 -08005980 /* To get here, two things must be true; the parser must be
5981 * using a character encoding that is not the same as the
5982 * encoding passed in, and the encoding passed in must need
5983 * conversion to the internal format (UTF-8 unless XML_UNICODE
5984 * is defined). The only occasions on which the encoding passed
5985 * in is not the same as the parser's encoding are when it is
5986 * the internal encoding (e.g. a previously defined parameter
5987 * entity, already converted to internal format). This by
5988 * definition doesn't need conversion, so the whole branch never
5989 * gets executed.
5990 *
5991 * For safety's sake we don't delete these lines and merely
5992 * exclude them from coverage statistics.
5993 *
5994 * LCOV_EXCL_START
5995 */
5996 eventPP = &(parser->m_openInternalEntities->internalEventPtr);
5997 eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
5998 /* LCOV_EXCL_STOP */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08005999 }
6000 do {
Elliott Hughes72472942018-01-10 08:36:10 -08006001 ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
6002 convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006003 *eventEndPP = s;
Elliott Hughes72472942018-01-10 08:36:10 -08006004 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 -08006005 *eventPP = s;
Paul Duffin4bf8f122016-05-13 12:35:25 +01006006 } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006007 }
6008 else
Elliott Hughes72472942018-01-10 08:36:10 -08006009 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 -08006010}
6011
6012
6013static int
6014defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
6015 XML_Bool isId, const XML_Char *value, XML_Parser parser)
6016{
6017 DEFAULT_ATTRIBUTE *att;
6018 if (value || isId) {
6019 /* The handling of default attributes gets messed up if we have
6020 a default which duplicates a non-default. */
6021 int i;
6022 for (i = 0; i < type->nDefaultAtts; i++)
6023 if (attId == type->defaultAtts[i].id)
6024 return 1;
6025 if (isId && !type->idAtt && !attId->xmlns)
6026 type->idAtt = attId;
6027 }
6028 if (type->nDefaultAtts == type->allocDefaultAtts) {
6029 if (type->allocDefaultAtts == 0) {
6030 type->allocDefaultAtts = 8;
Elliott Hughes72472942018-01-10 08:36:10 -08006031 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(parser, type->allocDefaultAtts
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006032 * sizeof(DEFAULT_ATTRIBUTE));
Elliott Hughes72472942018-01-10 08:36:10 -08006033 if (!type->defaultAtts) {
6034 type->allocDefaultAtts = 0;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006035 return 0;
Elliott Hughes72472942018-01-10 08:36:10 -08006036 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006037 }
6038 else {
6039 DEFAULT_ATTRIBUTE *temp;
6040 int count = type->allocDefaultAtts * 2;
6041 temp = (DEFAULT_ATTRIBUTE *)
Elliott Hughes72472942018-01-10 08:36:10 -08006042 REALLOC(parser, type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006043 if (temp == NULL)
6044 return 0;
6045 type->allocDefaultAtts = count;
6046 type->defaultAtts = temp;
6047 }
6048 }
6049 att = type->defaultAtts + type->nDefaultAtts;
6050 att->id = attId;
6051 att->value = value;
6052 att->isCdata = isCdata;
6053 if (!isCdata)
6054 attId->maybeTokenized = XML_TRUE;
6055 type->nDefaultAtts += 1;
6056 return 1;
6057}
6058
6059static int
6060setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
6061{
Elliott Hughes72472942018-01-10 08:36:10 -08006062 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006063 const XML_Char *name;
6064 for (name = elementType->name; *name; name++) {
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006065 if (*name == XML_T(ASCII_COLON)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006066 PREFIX *prefix;
6067 const XML_Char *s;
6068 for (s = elementType->name; s != name; s++) {
6069 if (!poolAppendChar(&dtd->pool, *s))
6070 return 0;
6071 }
6072 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6073 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006074 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006075 sizeof(PREFIX));
6076 if (!prefix)
6077 return 0;
6078 if (prefix->name == poolStart(&dtd->pool))
6079 poolFinish(&dtd->pool);
6080 else
6081 poolDiscard(&dtd->pool);
6082 elementType->prefix = prefix;
6083
6084 }
6085 }
6086 return 1;
6087}
6088
6089static ATTRIBUTE_ID *
6090getAttributeId(XML_Parser parser, const ENCODING *enc,
6091 const char *start, const char *end)
6092{
Elliott Hughes72472942018-01-10 08:36:10 -08006093 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006094 ATTRIBUTE_ID *id;
6095 const XML_Char *name;
6096 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6097 return NULL;
6098 name = poolStoreString(&dtd->pool, enc, start, end);
6099 if (!name)
6100 return NULL;
6101 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
6102 ++name;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006103 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006104 if (!id)
6105 return NULL;
6106 if (id->name != name)
6107 poolDiscard(&dtd->pool);
6108 else {
6109 poolFinish(&dtd->pool);
Elliott Hughes72472942018-01-10 08:36:10 -08006110 if (!parser->m_ns)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006111 ;
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006112 else if (name[0] == XML_T(ASCII_x)
6113 && name[1] == XML_T(ASCII_m)
6114 && name[2] == XML_T(ASCII_l)
6115 && name[3] == XML_T(ASCII_n)
6116 && name[4] == XML_T(ASCII_s)
6117 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006118 if (name[5] == XML_T('\0'))
6119 id->prefix = &dtd->defaultPrefix;
6120 else
Elliott Hughes35e432d2012-09-09 14:23:38 -07006121 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006122 id->xmlns = XML_TRUE;
6123 }
6124 else {
6125 int i;
6126 for (i = 0; name[i]; i++) {
6127 /* attributes without prefix are *not* in the default namespace */
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006128 if (name[i] == XML_T(ASCII_COLON)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006129 int j;
6130 for (j = 0; j < i; j++) {
6131 if (!poolAppendChar(&dtd->pool, name[j]))
6132 return NULL;
6133 }
6134 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6135 return NULL;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006136 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006137 sizeof(PREFIX));
Paul Duffinc05e0322016-05-04 10:42:31 +01006138 if (!id->prefix)
6139 return NULL;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006140 if (id->prefix->name == poolStart(&dtd->pool))
6141 poolFinish(&dtd->pool);
6142 else
6143 poolDiscard(&dtd->pool);
6144 break;
6145 }
6146 }
6147 }
6148 }
6149 return id;
6150}
6151
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006152#define CONTEXT_SEP XML_T(ASCII_FF)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006153
6154static const XML_Char *
6155getContext(XML_Parser parser)
6156{
Elliott Hughes72472942018-01-10 08:36:10 -08006157 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006158 HASH_TABLE_ITER iter;
6159 XML_Bool needSep = XML_FALSE;
6160
6161 if (dtd->defaultPrefix.binding) {
6162 int i;
6163 int len;
Elliott Hughes72472942018-01-10 08:36:10 -08006164 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006165 return NULL;
6166 len = dtd->defaultPrefix.binding->uriLen;
Elliott Hughes72472942018-01-10 08:36:10 -08006167 if (parser->m_namespaceSeparator)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006168 len--;
Elliott Hughes72472942018-01-10 08:36:10 -08006169 for (i = 0; i < len; i++) {
6170 if (!poolAppendChar(&parser->m_tempPool, dtd->defaultPrefix.binding->uri[i])) {
6171 /* Because of memory caching, I don't believe this line can be
6172 * executed.
6173 *
6174 * This is part of a loop copying the default prefix binding
6175 * URI into the parser's temporary string pool. Previously,
6176 * that URI was copied into the same string pool, with a
6177 * terminating NUL character, as part of setContext(). When
6178 * the pool was cleared, that leaves a block definitely big
6179 * enough to hold the URI on the free block list of the pool.
6180 * The URI copy in getContext() therefore cannot run out of
6181 * memory.
6182 *
6183 * If the pool is used between the setContext() and
6184 * getContext() calls, the worst it can do is leave a bigger
6185 * block on the front of the free list. Given that this is
6186 * all somewhat inobvious and program logic can be changed, we
6187 * don't delete the line but we do exclude it from the test
6188 * coverage statistics.
6189 */
6190 return NULL; /* LCOV_EXCL_LINE */
6191 }
6192 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006193 needSep = XML_TRUE;
6194 }
6195
6196 hashTableIterInit(&iter, &(dtd->prefixes));
6197 for (;;) {
6198 int i;
6199 int len;
6200 const XML_Char *s;
6201 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
6202 if (!prefix)
6203 break;
Elliott Hughes72472942018-01-10 08:36:10 -08006204 if (!prefix->binding) {
6205 /* This test appears to be (justifiable) paranoia. There does
6206 * not seem to be a way of injecting a prefix without a binding
6207 * that doesn't get errored long before this function is called.
6208 * The test should remain for safety's sake, so we instead
6209 * exclude the following line from the coverage statistics.
6210 */
6211 continue; /* LCOV_EXCL_LINE */
6212 }
6213 if (needSep && !poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006214 return NULL;
6215 for (s = prefix->name; *s; s++)
Elliott Hughes72472942018-01-10 08:36:10 -08006216 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006217 return NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08006218 if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006219 return NULL;
6220 len = prefix->binding->uriLen;
Elliott Hughes72472942018-01-10 08:36:10 -08006221 if (parser->m_namespaceSeparator)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006222 len--;
6223 for (i = 0; i < len; i++)
Elliott Hughes72472942018-01-10 08:36:10 -08006224 if (!poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i]))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006225 return NULL;
6226 needSep = XML_TRUE;
6227 }
6228
6229
6230 hashTableIterInit(&iter, &(dtd->generalEntities));
6231 for (;;) {
6232 const XML_Char *s;
6233 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
6234 if (!e)
6235 break;
6236 if (!e->open)
6237 continue;
Elliott Hughes72472942018-01-10 08:36:10 -08006238 if (needSep && !poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006239 return NULL;
6240 for (s = e->name; *s; s++)
Elliott Hughes72472942018-01-10 08:36:10 -08006241 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006242 return 0;
6243 needSep = XML_TRUE;
6244 }
6245
Elliott Hughes72472942018-01-10 08:36:10 -08006246 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006247 return NULL;
Elliott Hughes72472942018-01-10 08:36:10 -08006248 return parser->m_tempPool.start;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006249}
6250
6251static XML_Bool
6252setContext(XML_Parser parser, const XML_Char *context)
6253{
Elliott Hughes72472942018-01-10 08:36:10 -08006254 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006255 const XML_Char *s = context;
6256
6257 while (*context != XML_T('\0')) {
6258 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
6259 ENTITY *e;
Elliott Hughes72472942018-01-10 08:36:10 -08006260 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006261 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006262 e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&parser->m_tempPool), 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006263 if (e)
6264 e->open = XML_TRUE;
6265 if (*s != XML_T('\0'))
6266 s++;
6267 context = s;
Elliott Hughes72472942018-01-10 08:36:10 -08006268 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006269 }
Elliott Hughesd07d5a72009-09-25 16:04:37 -07006270 else if (*s == XML_T(ASCII_EQUALS)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006271 PREFIX *prefix;
Elliott Hughes72472942018-01-10 08:36:10 -08006272 if (poolLength(&parser->m_tempPool) == 0)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006273 prefix = &dtd->defaultPrefix;
6274 else {
Elliott Hughes72472942018-01-10 08:36:10 -08006275 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006276 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006277 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&parser->m_tempPool),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006278 sizeof(PREFIX));
6279 if (!prefix)
6280 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006281 if (prefix->name == poolStart(&parser->m_tempPool)) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006282 prefix->name = poolCopyString(&dtd->pool, prefix->name);
6283 if (!prefix->name)
6284 return XML_FALSE;
6285 }
Elliott Hughes72472942018-01-10 08:36:10 -08006286 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006287 }
6288 for (context = s + 1;
6289 *context != CONTEXT_SEP && *context != XML_T('\0');
6290 context++)
Elliott Hughes72472942018-01-10 08:36:10 -08006291 if (!poolAppendChar(&parser->m_tempPool, *context))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006292 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006293 if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006294 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006295 if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool),
6296 &parser->m_inheritedBindings) != XML_ERROR_NONE)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006297 return XML_FALSE;
Elliott Hughes72472942018-01-10 08:36:10 -08006298 poolDiscard(&parser->m_tempPool);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006299 if (*context != XML_T('\0'))
6300 ++context;
6301 s = context;
6302 }
6303 else {
Elliott Hughes72472942018-01-10 08:36:10 -08006304 if (!poolAppendChar(&parser->m_tempPool, *s))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006305 return XML_FALSE;
6306 s++;
6307 }
6308 }
6309 return XML_TRUE;
6310}
6311
6312static void FASTCALL
6313normalizePublicId(XML_Char *publicId)
6314{
6315 XML_Char *p = publicId;
6316 XML_Char *s;
6317 for (s = publicId; *s; s++) {
6318 switch (*s) {
6319 case 0x20:
6320 case 0xD:
6321 case 0xA:
6322 if (p != publicId && p[-1] != 0x20)
6323 *p++ = 0x20;
6324 break;
6325 default:
6326 *p++ = *s;
6327 }
6328 }
6329 if (p != publicId && p[-1] == 0x20)
6330 --p;
6331 *p = XML_T('\0');
6332}
6333
6334static DTD *
6335dtdCreate(const XML_Memory_Handling_Suite *ms)
6336{
6337 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
6338 if (p == NULL)
6339 return p;
6340 poolInit(&(p->pool), ms);
6341 poolInit(&(p->entityValuePool), ms);
6342 hashTableInit(&(p->generalEntities), ms);
6343 hashTableInit(&(p->elementTypes), ms);
6344 hashTableInit(&(p->attributeIds), ms);
6345 hashTableInit(&(p->prefixes), ms);
6346#ifdef XML_DTD
6347 p->paramEntityRead = XML_FALSE;
6348 hashTableInit(&(p->paramEntities), ms);
6349#endif /* XML_DTD */
6350 p->defaultPrefix.name = NULL;
6351 p->defaultPrefix.binding = NULL;
6352
6353 p->in_eldecl = XML_FALSE;
6354 p->scaffIndex = NULL;
6355 p->scaffold = NULL;
6356 p->scaffLevel = 0;
6357 p->scaffSize = 0;
6358 p->scaffCount = 0;
6359 p->contentStringLen = 0;
6360
6361 p->keepProcessing = XML_TRUE;
6362 p->hasParamEntityRefs = XML_FALSE;
6363 p->standalone = XML_FALSE;
6364 return p;
6365}
6366
6367static void
6368dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
6369{
6370 HASH_TABLE_ITER iter;
6371 hashTableIterInit(&iter, &(p->elementTypes));
6372 for (;;) {
6373 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6374 if (!e)
6375 break;
6376 if (e->allocDefaultAtts != 0)
6377 ms->free_fcn(e->defaultAtts);
6378 }
6379 hashTableClear(&(p->generalEntities));
6380#ifdef XML_DTD
6381 p->paramEntityRead = XML_FALSE;
6382 hashTableClear(&(p->paramEntities));
6383#endif /* XML_DTD */
6384 hashTableClear(&(p->elementTypes));
6385 hashTableClear(&(p->attributeIds));
6386 hashTableClear(&(p->prefixes));
6387 poolClear(&(p->pool));
6388 poolClear(&(p->entityValuePool));
6389 p->defaultPrefix.name = NULL;
6390 p->defaultPrefix.binding = NULL;
6391
6392 p->in_eldecl = XML_FALSE;
6393
6394 ms->free_fcn(p->scaffIndex);
6395 p->scaffIndex = NULL;
6396 ms->free_fcn(p->scaffold);
6397 p->scaffold = NULL;
6398
6399 p->scaffLevel = 0;
6400 p->scaffSize = 0;
6401 p->scaffCount = 0;
6402 p->contentStringLen = 0;
6403
6404 p->keepProcessing = XML_TRUE;
6405 p->hasParamEntityRefs = XML_FALSE;
6406 p->standalone = XML_FALSE;
6407}
6408
6409static void
6410dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
6411{
6412 HASH_TABLE_ITER iter;
6413 hashTableIterInit(&iter, &(p->elementTypes));
6414 for (;;) {
6415 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6416 if (!e)
6417 break;
6418 if (e->allocDefaultAtts != 0)
6419 ms->free_fcn(e->defaultAtts);
6420 }
6421 hashTableDestroy(&(p->generalEntities));
6422#ifdef XML_DTD
6423 hashTableDestroy(&(p->paramEntities));
6424#endif /* XML_DTD */
6425 hashTableDestroy(&(p->elementTypes));
6426 hashTableDestroy(&(p->attributeIds));
6427 hashTableDestroy(&(p->prefixes));
6428 poolDestroy(&(p->pool));
6429 poolDestroy(&(p->entityValuePool));
6430 if (isDocEntity) {
6431 ms->free_fcn(p->scaffIndex);
6432 ms->free_fcn(p->scaffold);
6433 }
6434 ms->free_fcn(p);
6435}
6436
6437/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
6438 The new DTD has already been initialized.
6439*/
6440static int
Elliott Hughes35e432d2012-09-09 14:23:38 -07006441dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006442{
6443 HASH_TABLE_ITER iter;
6444
6445 /* Copy the prefix table. */
6446
6447 hashTableIterInit(&iter, &(oldDtd->prefixes));
6448 for (;;) {
6449 const XML_Char *name;
6450 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
6451 if (!oldP)
6452 break;
6453 name = poolCopyString(&(newDtd->pool), oldP->name);
6454 if (!name)
6455 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006456 if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006457 return 0;
6458 }
6459
6460 hashTableIterInit(&iter, &(oldDtd->attributeIds));
6461
6462 /* Copy the attribute id table. */
6463
6464 for (;;) {
6465 ATTRIBUTE_ID *newA;
6466 const XML_Char *name;
6467 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
6468
6469 if (!oldA)
6470 break;
6471 /* Remember to allocate the scratch byte before the name. */
6472 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
6473 return 0;
6474 name = poolCopyString(&(newDtd->pool), oldA->name);
6475 if (!name)
6476 return 0;
6477 ++name;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006478 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006479 sizeof(ATTRIBUTE_ID));
6480 if (!newA)
6481 return 0;
6482 newA->maybeTokenized = oldA->maybeTokenized;
6483 if (oldA->prefix) {
6484 newA->xmlns = oldA->xmlns;
6485 if (oldA->prefix == &oldDtd->defaultPrefix)
6486 newA->prefix = &newDtd->defaultPrefix;
6487 else
Elliott Hughes35e432d2012-09-09 14:23:38 -07006488 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006489 oldA->prefix->name, 0);
6490 }
6491 }
6492
6493 /* Copy the element type table. */
6494
6495 hashTableIterInit(&iter, &(oldDtd->elementTypes));
6496
6497 for (;;) {
6498 int i;
6499 ELEMENT_TYPE *newE;
6500 const XML_Char *name;
6501 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6502 if (!oldE)
6503 break;
6504 name = poolCopyString(&(newDtd->pool), oldE->name);
6505 if (!name)
6506 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006507 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006508 sizeof(ELEMENT_TYPE));
6509 if (!newE)
6510 return 0;
6511 if (oldE->nDefaultAtts) {
6512 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
6513 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6514 if (!newE->defaultAtts) {
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006515 return 0;
6516 }
6517 }
6518 if (oldE->idAtt)
6519 newE->idAtt = (ATTRIBUTE_ID *)
Elliott Hughes35e432d2012-09-09 14:23:38 -07006520 lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006521 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
6522 if (oldE->prefix)
Elliott Hughes35e432d2012-09-09 14:23:38 -07006523 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006524 oldE->prefix->name, 0);
6525 for (i = 0; i < newE->nDefaultAtts; i++) {
6526 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
Elliott Hughes35e432d2012-09-09 14:23:38 -07006527 lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006528 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
6529 if (oldE->defaultAtts[i].value) {
6530 newE->defaultAtts[i].value
6531 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
6532 if (!newE->defaultAtts[i].value)
6533 return 0;
6534 }
6535 else
6536 newE->defaultAtts[i].value = NULL;
6537 }
6538 }
6539
6540 /* Copy the entity tables. */
Elliott Hughes35e432d2012-09-09 14:23:38 -07006541 if (!copyEntityTable(oldParser,
6542 &(newDtd->generalEntities),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006543 &(newDtd->pool),
6544 &(oldDtd->generalEntities)))
6545 return 0;
6546
6547#ifdef XML_DTD
Elliott Hughes35e432d2012-09-09 14:23:38 -07006548 if (!copyEntityTable(oldParser,
6549 &(newDtd->paramEntities),
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006550 &(newDtd->pool),
6551 &(oldDtd->paramEntities)))
6552 return 0;
6553 newDtd->paramEntityRead = oldDtd->paramEntityRead;
6554#endif /* XML_DTD */
6555
6556 newDtd->keepProcessing = oldDtd->keepProcessing;
6557 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
6558 newDtd->standalone = oldDtd->standalone;
6559
6560 /* Don't want deep copying for scaffolding */
6561 newDtd->in_eldecl = oldDtd->in_eldecl;
6562 newDtd->scaffold = oldDtd->scaffold;
6563 newDtd->contentStringLen = oldDtd->contentStringLen;
6564 newDtd->scaffSize = oldDtd->scaffSize;
6565 newDtd->scaffLevel = oldDtd->scaffLevel;
6566 newDtd->scaffIndex = oldDtd->scaffIndex;
6567
6568 return 1;
6569} /* End dtdCopy */
6570
6571static int
Elliott Hughes35e432d2012-09-09 14:23:38 -07006572copyEntityTable(XML_Parser oldParser,
6573 HASH_TABLE *newTable,
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006574 STRING_POOL *newPool,
6575 const HASH_TABLE *oldTable)
6576{
6577 HASH_TABLE_ITER iter;
6578 const XML_Char *cachedOldBase = NULL;
6579 const XML_Char *cachedNewBase = NULL;
6580
6581 hashTableIterInit(&iter, oldTable);
6582
6583 for (;;) {
6584 ENTITY *newE;
6585 const XML_Char *name;
6586 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
6587 if (!oldE)
6588 break;
6589 name = poolCopyString(newPool, oldE->name);
6590 if (!name)
6591 return 0;
Elliott Hughes35e432d2012-09-09 14:23:38 -07006592 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006593 if (!newE)
6594 return 0;
6595 if (oldE->systemId) {
6596 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
6597 if (!tem)
6598 return 0;
6599 newE->systemId = tem;
6600 if (oldE->base) {
6601 if (oldE->base == cachedOldBase)
6602 newE->base = cachedNewBase;
6603 else {
6604 cachedOldBase = oldE->base;
6605 tem = poolCopyString(newPool, cachedOldBase);
6606 if (!tem)
6607 return 0;
6608 cachedNewBase = newE->base = tem;
6609 }
6610 }
6611 if (oldE->publicId) {
6612 tem = poolCopyString(newPool, oldE->publicId);
6613 if (!tem)
6614 return 0;
6615 newE->publicId = tem;
6616 }
6617 }
6618 else {
6619 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
6620 oldE->textLen);
6621 if (!tem)
6622 return 0;
6623 newE->textPtr = tem;
6624 newE->textLen = oldE->textLen;
6625 }
6626 if (oldE->notation) {
6627 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
6628 if (!tem)
6629 return 0;
6630 newE->notation = tem;
6631 }
6632 newE->is_param = oldE->is_param;
6633 newE->is_internal = oldE->is_internal;
6634 }
6635 return 1;
6636}
6637
6638#define INIT_POWER 6
6639
6640static XML_Bool FASTCALL
6641keyeq(KEY s1, KEY s2)
6642{
6643 for (; *s1 == *s2; s1++, s2++)
6644 if (*s1 == 0)
6645 return XML_TRUE;
6646 return XML_FALSE;
6647}
6648
Elliott Hughes72472942018-01-10 08:36:10 -08006649static size_t
6650keylen(KEY s)
6651{
6652 size_t len = 0;
6653 for (; *s; s++, len++);
6654 return len;
6655}
6656
6657static void
6658copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key)
6659{
6660 key->k[0] = 0;
6661 key->k[1] = get_hash_secret_salt(parser);
6662}
6663
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006664static unsigned long FASTCALL
Elliott Hughes35e432d2012-09-09 14:23:38 -07006665hash(XML_Parser parser, KEY s)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006666{
Elliott Hughes72472942018-01-10 08:36:10 -08006667 struct siphash state;
6668 struct sipkey key;
Elliott Hughes72472942018-01-10 08:36:10 -08006669 (void)sip24_valid;
6670 copy_salt_to_sipkey(parser, &key);
6671 sip24_init(&state, &key);
6672 sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
6673 return (unsigned long)sip24_final(&state);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006674}
6675
6676static NAMED *
Elliott Hughes35e432d2012-09-09 14:23:38 -07006677lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006678{
6679 size_t i;
6680 if (table->size == 0) {
6681 size_t tsize;
6682 if (!createSize)
6683 return NULL;
6684 table->power = INIT_POWER;
6685 /* table->size is a power of 2 */
6686 table->size = (size_t)1 << INIT_POWER;
6687 tsize = table->size * sizeof(NAMED *);
6688 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
6689 if (!table->v) {
6690 table->size = 0;
6691 return NULL;
6692 }
6693 memset(table->v, 0, tsize);
Elliott Hughes35e432d2012-09-09 14:23:38 -07006694 i = hash(parser, name) & ((unsigned long)table->size - 1);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006695 }
6696 else {
Elliott Hughes35e432d2012-09-09 14:23:38 -07006697 unsigned long h = hash(parser, name);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006698 unsigned long mask = (unsigned long)table->size - 1;
6699 unsigned char step = 0;
6700 i = h & mask;
6701 while (table->v[i]) {
6702 if (keyeq(name, table->v[i]->name))
6703 return table->v[i];
6704 if (!step)
6705 step = PROBE_STEP(h, mask, table->power);
6706 i < step ? (i += table->size - step) : (i -= step);
6707 }
6708 if (!createSize)
6709 return NULL;
6710
6711 /* check for overflow (table is half full) */
6712 if (table->used >> (table->power - 1)) {
6713 unsigned char newPower = table->power + 1;
6714 size_t newSize = (size_t)1 << newPower;
6715 unsigned long newMask = (unsigned long)newSize - 1;
6716 size_t tsize = newSize * sizeof(NAMED *);
6717 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
6718 if (!newV)
6719 return NULL;
6720 memset(newV, 0, tsize);
6721 for (i = 0; i < table->size; i++)
6722 if (table->v[i]) {
Elliott Hughes35e432d2012-09-09 14:23:38 -07006723 unsigned long newHash = hash(parser, table->v[i]->name);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006724 size_t j = newHash & newMask;
6725 step = 0;
6726 while (newV[j]) {
6727 if (!step)
6728 step = PROBE_STEP(newHash, newMask, newPower);
6729 j < step ? (j += newSize - step) : (j -= step);
6730 }
6731 newV[j] = table->v[i];
6732 }
6733 table->mem->free_fcn(table->v);
6734 table->v = newV;
6735 table->power = newPower;
6736 table->size = newSize;
6737 i = h & newMask;
6738 step = 0;
6739 while (table->v[i]) {
6740 if (!step)
6741 step = PROBE_STEP(h, newMask, newPower);
6742 i < step ? (i += newSize - step) : (i -= step);
6743 }
6744 }
6745 }
6746 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
6747 if (!table->v[i])
6748 return NULL;
6749 memset(table->v[i], 0, createSize);
6750 table->v[i]->name = name;
6751 (table->used)++;
6752 return table->v[i];
6753}
6754
6755static void FASTCALL
6756hashTableClear(HASH_TABLE *table)
6757{
6758 size_t i;
6759 for (i = 0; i < table->size; i++) {
6760 table->mem->free_fcn(table->v[i]);
6761 table->v[i] = NULL;
6762 }
6763 table->used = 0;
6764}
6765
6766static void FASTCALL
6767hashTableDestroy(HASH_TABLE *table)
6768{
6769 size_t i;
6770 for (i = 0; i < table->size; i++)
6771 table->mem->free_fcn(table->v[i]);
6772 table->mem->free_fcn(table->v);
6773}
6774
6775static void FASTCALL
6776hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
6777{
6778 p->power = 0;
6779 p->size = 0;
6780 p->used = 0;
6781 p->v = NULL;
6782 p->mem = ms;
6783}
6784
6785static void FASTCALL
6786hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
6787{
6788 iter->p = table->v;
6789 iter->end = iter->p + table->size;
6790}
6791
6792static NAMED * FASTCALL
6793hashTableIterNext(HASH_TABLE_ITER *iter)
6794{
6795 while (iter->p != iter->end) {
6796 NAMED *tem = *(iter->p)++;
6797 if (tem)
6798 return tem;
6799 }
6800 return NULL;
6801}
6802
6803static void FASTCALL
6804poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
6805{
6806 pool->blocks = NULL;
6807 pool->freeBlocks = NULL;
6808 pool->start = NULL;
6809 pool->ptr = NULL;
6810 pool->end = NULL;
6811 pool->mem = ms;
6812}
6813
6814static void FASTCALL
6815poolClear(STRING_POOL *pool)
6816{
6817 if (!pool->freeBlocks)
6818 pool->freeBlocks = pool->blocks;
6819 else {
6820 BLOCK *p = pool->blocks;
6821 while (p) {
6822 BLOCK *tem = p->next;
6823 p->next = pool->freeBlocks;
6824 pool->freeBlocks = p;
6825 p = tem;
6826 }
6827 }
6828 pool->blocks = NULL;
6829 pool->start = NULL;
6830 pool->ptr = NULL;
6831 pool->end = NULL;
6832}
6833
6834static void FASTCALL
6835poolDestroy(STRING_POOL *pool)
6836{
6837 BLOCK *p = pool->blocks;
6838 while (p) {
6839 BLOCK *tem = p->next;
6840 pool->mem->free_fcn(p);
6841 p = tem;
6842 }
6843 p = pool->freeBlocks;
6844 while (p) {
6845 BLOCK *tem = p->next;
6846 pool->mem->free_fcn(p);
6847 p = tem;
6848 }
6849}
6850
6851static XML_Char *
6852poolAppend(STRING_POOL *pool, const ENCODING *enc,
6853 const char *ptr, const char *end)
6854{
6855 if (!pool->ptr && !poolGrow(pool))
6856 return NULL;
6857 for (;;) {
Paul Duffin4bf8f122016-05-13 12:35:25 +01006858 const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6859 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006860 break;
6861 if (!poolGrow(pool))
6862 return NULL;
6863 }
6864 return pool->start;
6865}
6866
6867static const XML_Char * FASTCALL
6868poolCopyString(STRING_POOL *pool, const XML_Char *s)
6869{
6870 do {
6871 if (!poolAppendChar(pool, *s))
6872 return NULL;
6873 } while (*s++);
6874 s = pool->start;
6875 poolFinish(pool);
6876 return s;
6877}
6878
6879static const XML_Char *
6880poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6881{
Elliott Hughes72472942018-01-10 08:36:10 -08006882 if (!pool->ptr && !poolGrow(pool)) {
6883 /* The following line is unreachable given the current usage of
6884 * poolCopyStringN(). Currently it is called from exactly one
6885 * place to copy the text of a simple general entity. By that
6886 * point, the name of the entity is already stored in the pool, so
6887 * pool->ptr cannot be NULL.
6888 *
6889 * If poolCopyStringN() is used elsewhere as it well might be,
6890 * this line may well become executable again. Regardless, this
6891 * sort of check shouldn't be removed lightly, so we just exclude
6892 * it from the coverage statistics.
6893 */
6894 return NULL; /* LCOV_EXCL_LINE */
6895 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006896 for (; n > 0; --n, s++) {
6897 if (!poolAppendChar(pool, *s))
6898 return NULL;
6899 }
6900 s = pool->start;
6901 poolFinish(pool);
6902 return s;
6903}
6904
6905static const XML_Char * FASTCALL
6906poolAppendString(STRING_POOL *pool, const XML_Char *s)
6907{
6908 while (*s) {
6909 if (!poolAppendChar(pool, *s))
6910 return NULL;
6911 s++;
6912 }
6913 return pool->start;
6914}
6915
6916static XML_Char *
6917poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6918 const char *ptr, const char *end)
6919{
6920 if (!poolAppend(pool, enc, ptr, end))
6921 return NULL;
6922 if (pool->ptr == pool->end && !poolGrow(pool))
6923 return NULL;
6924 *(pool->ptr)++ = 0;
6925 return pool->start;
6926}
6927
Elliott Hughes72472942018-01-10 08:36:10 -08006928static size_t
6929poolBytesToAllocateFor(int blockSize)
6930{
6931 /* Unprotected math would be:
6932 ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
6933 **
6934 ** Detect overflow, avoiding _signed_ overflow undefined behavior
6935 ** For a + b * c we check b * c in isolation first, so that addition of a
6936 ** on top has no chance of making us accept a small non-negative number
6937 */
6938 const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
6939
6940 if (blockSize <= 0)
6941 return 0;
6942
6943 if (blockSize > (int)(INT_MAX / stretch))
6944 return 0;
6945
6946 {
6947 const int stretchedBlockSize = blockSize * (int)stretch;
6948 const int bytesToAllocate = (int)(
6949 offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
6950 if (bytesToAllocate < 0)
6951 return 0;
6952
6953 return (size_t)bytesToAllocate;
6954 }
6955}
6956
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08006957static XML_Bool FASTCALL
6958poolGrow(STRING_POOL *pool)
6959{
6960 if (pool->freeBlocks) {
6961 if (pool->start == 0) {
6962 pool->blocks = pool->freeBlocks;
6963 pool->freeBlocks = pool->freeBlocks->next;
6964 pool->blocks->next = NULL;
6965 pool->start = pool->blocks->s;
6966 pool->end = pool->start + pool->blocks->size;
6967 pool->ptr = pool->start;
6968 return XML_TRUE;
6969 }
6970 if (pool->end - pool->start < pool->freeBlocks->size) {
6971 BLOCK *tem = pool->freeBlocks->next;
6972 pool->freeBlocks->next = pool->blocks;
6973 pool->blocks = pool->freeBlocks;
6974 pool->freeBlocks = tem;
6975 memcpy(pool->blocks->s, pool->start,
6976 (pool->end - pool->start) * sizeof(XML_Char));
6977 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6978 pool->start = pool->blocks->s;
6979 pool->end = pool->start + pool->blocks->size;
6980 return XML_TRUE;
6981 }
6982 }
6983 if (pool->blocks && pool->start == pool->blocks->s) {
Paul Duffin4bf8f122016-05-13 12:35:25 +01006984 BLOCK *temp;
Paul Duffinba34a0c2017-02-27 14:40:16 +00006985 int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
Elliott Hughes72472942018-01-10 08:36:10 -08006986 size_t bytesToAllocate;
Paul Duffin4bf8f122016-05-13 12:35:25 +01006987
Elliott Hughes72472942018-01-10 08:36:10 -08006988 /* NOTE: Needs to be calculated prior to calling `realloc`
6989 to avoid dangling pointers: */
6990 const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
6991
6992 if (blockSize < 0) {
6993 /* This condition traps a situation where either more than
6994 * INT_MAX/2 bytes have already been allocated. This isn't
6995 * readily testable, since it is unlikely that an average
6996 * machine will have that much memory, so we exclude it from the
6997 * coverage statistics.
6998 */
6999 return XML_FALSE; /* LCOV_EXCL_LINE */
7000 }
7001
7002 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7003 if (bytesToAllocate == 0)
Paul Duffin4bf8f122016-05-13 12:35:25 +01007004 return XML_FALSE;
7005
7006 temp = (BLOCK *)
Elliott Hughes72472942018-01-10 08:36:10 -08007007 pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate);
Elliott Hughes35e432d2012-09-09 14:23:38 -07007008 if (temp == NULL)
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007009 return XML_FALSE;
Elliott Hughes35e432d2012-09-09 14:23:38 -07007010 pool->blocks = temp;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007011 pool->blocks->size = blockSize;
Elliott Hughes72472942018-01-10 08:36:10 -08007012 pool->ptr = pool->blocks->s + offsetInsideBlock;
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007013 pool->start = pool->blocks->s;
7014 pool->end = pool->start + blockSize;
7015 }
7016 else {
7017 BLOCK *tem;
7018 int blockSize = (int)(pool->end - pool->start);
Elliott Hughes72472942018-01-10 08:36:10 -08007019 size_t bytesToAllocate;
Paul Duffin4bf8f122016-05-13 12:35:25 +01007020
Elliott Hughes72472942018-01-10 08:36:10 -08007021 if (blockSize < 0) {
7022 /* This condition traps a situation where either more than
7023 * INT_MAX bytes have already been allocated (which is prevented
7024 * by various pieces of program logic, not least this one, never
7025 * mind the unlikelihood of actually having that much memory) or
7026 * the pool control fields have been corrupted (which could
7027 * conceivably happen in an extremely buggy user handler
7028 * function). Either way it isn't readily testable, so we
7029 * exclude it from the coverage statistics.
7030 */
7031 return XML_FALSE; /* LCOV_EXCL_LINE */
7032 }
Paul Duffin4bf8f122016-05-13 12:35:25 +01007033
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007034 if (blockSize < INIT_BLOCK_SIZE)
7035 blockSize = INIT_BLOCK_SIZE;
Elliott Hughes72472942018-01-10 08:36:10 -08007036 else {
7037 /* Detect overflow, avoiding _signed_ overflow undefined behavior */
7038 if ((int)((unsigned)blockSize * 2U) < 0) {
7039 return XML_FALSE;
7040 }
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007041 blockSize *= 2;
Elliott Hughes72472942018-01-10 08:36:10 -08007042 }
7043
7044 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7045 if (bytesToAllocate == 0)
7046 return XML_FALSE;
7047
7048 tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007049 if (!tem)
7050 return XML_FALSE;
7051 tem->size = blockSize;
7052 tem->next = pool->blocks;
7053 pool->blocks = tem;
7054 if (pool->ptr != pool->start)
7055 memcpy(tem->s, pool->start,
7056 (pool->ptr - pool->start) * sizeof(XML_Char));
7057 pool->ptr = tem->s + (pool->ptr - pool->start);
7058 pool->start = tem->s;
7059 pool->end = tem->s + blockSize;
7060 }
7061 return XML_TRUE;
7062}
7063
7064static int FASTCALL
7065nextScaffoldPart(XML_Parser parser)
7066{
Elliott Hughes72472942018-01-10 08:36:10 -08007067 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007068 CONTENT_SCAFFOLD * me;
7069 int next;
7070
7071 if (!dtd->scaffIndex) {
Elliott Hughes72472942018-01-10 08:36:10 -08007072 dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007073 if (!dtd->scaffIndex)
7074 return -1;
7075 dtd->scaffIndex[0] = 0;
7076 }
7077
7078 if (dtd->scaffCount >= dtd->scaffSize) {
7079 CONTENT_SCAFFOLD *temp;
7080 if (dtd->scaffold) {
7081 temp = (CONTENT_SCAFFOLD *)
Elliott Hughes72472942018-01-10 08:36:10 -08007082 REALLOC(parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007083 if (temp == NULL)
7084 return -1;
7085 dtd->scaffSize *= 2;
7086 }
7087 else {
Elliott Hughes72472942018-01-10 08:36:10 -08007088 temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007089 * sizeof(CONTENT_SCAFFOLD));
7090 if (temp == NULL)
7091 return -1;
7092 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
7093 }
7094 dtd->scaffold = temp;
7095 }
7096 next = dtd->scaffCount++;
7097 me = &dtd->scaffold[next];
7098 if (dtd->scaffLevel) {
7099 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
7100 if (parent->lastchild) {
7101 dtd->scaffold[parent->lastchild].nextsib = next;
7102 }
7103 if (!parent->childcnt)
7104 parent->firstchild = next;
7105 parent->lastchild = next;
7106 parent->childcnt++;
7107 }
7108 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
7109 return next;
7110}
7111
7112static void
7113build_node(XML_Parser parser,
7114 int src_node,
7115 XML_Content *dest,
7116 XML_Content **contpos,
7117 XML_Char **strpos)
7118{
Elliott Hughes72472942018-01-10 08:36:10 -08007119 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007120 dest->type = dtd->scaffold[src_node].type;
7121 dest->quant = dtd->scaffold[src_node].quant;
7122 if (dest->type == XML_CTYPE_NAME) {
7123 const XML_Char *src;
7124 dest->name = *strpos;
7125 src = dtd->scaffold[src_node].name;
7126 for (;;) {
7127 *(*strpos)++ = *src;
7128 if (!*src)
7129 break;
7130 src++;
7131 }
7132 dest->numchildren = 0;
7133 dest->children = NULL;
7134 }
7135 else {
7136 unsigned int i;
7137 int cn;
7138 dest->numchildren = dtd->scaffold[src_node].childcnt;
7139 dest->children = *contpos;
7140 *contpos += dest->numchildren;
7141 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
7142 i < dest->numchildren;
7143 i++, cn = dtd->scaffold[cn].nextsib) {
7144 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
7145 }
7146 dest->name = NULL;
7147 }
7148}
7149
7150static XML_Content *
7151build_model (XML_Parser parser)
7152{
Elliott Hughes72472942018-01-10 08:36:10 -08007153 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007154 XML_Content *ret;
7155 XML_Content *cpos;
7156 XML_Char * str;
7157 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
7158 + (dtd->contentStringLen * sizeof(XML_Char)));
7159
Elliott Hughes72472942018-01-10 08:36:10 -08007160 ret = (XML_Content *)MALLOC(parser, allocsize);
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007161 if (!ret)
7162 return NULL;
7163
7164 str = (XML_Char *) (&ret[dtd->scaffCount]);
7165 cpos = &ret[1];
7166
7167 build_node(parser, 0, ret, &cpos, &str);
7168 return ret;
7169}
7170
7171static ELEMENT_TYPE *
7172getElementType(XML_Parser parser,
7173 const ENCODING *enc,
7174 const char *ptr,
7175 const char *end)
7176{
Elliott Hughes72472942018-01-10 08:36:10 -08007177 DTD * const dtd = parser->m_dtd; /* save one level of indirection */
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007178 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
7179 ELEMENT_TYPE *ret;
7180
7181 if (!name)
7182 return NULL;
Elliott Hughes35e432d2012-09-09 14:23:38 -07007183 ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
The Android Open Source Projectb80e2872009-03-03 19:29:30 -08007184 if (!ret)
7185 return NULL;
7186 if (ret->name != name)
7187 poolDiscard(&dtd->pool);
7188 else {
7189 poolFinish(&dtd->pool);
7190 if (!setElementTypePrefix(parser, ret))
7191 return NULL;
7192 }
7193 return ret;
7194}
Elliott Hughes72472942018-01-10 08:36:10 -08007195
7196static XML_Char *
7197copyString(const XML_Char *s,
7198 const XML_Memory_Handling_Suite *memsuite)
7199{
7200 int charsRequired = 0;
7201 XML_Char *result;
7202
7203 /* First determine how long the string is */
7204 while (s[charsRequired] != 0) {
7205 charsRequired++;
7206 }
7207 /* Include the terminator */
7208 charsRequired++;
7209
7210 /* Now allocate space for the copy */
7211 result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
7212 if (result == NULL)
7213 return NULL;
7214 /* Copy the original into place */
7215 memcpy(result, s, charsRequired * sizeof(XML_Char));
7216 return result;
7217}