1/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
2 See the file COPYING for copying permission.
3
4 101bfd65d1ff3d1511cf6671e6aae65f82cd97df6f4da137d46d510731830ad9 (2.2.3+)
5*/
6
7#if !defined(_GNU_SOURCE)
8# define _GNU_SOURCE 1 /* syscall prototype */
9#endif
10
11#include <stddef.h>
12#include <string.h> /* memset(), memcpy() */
13#include <assert.h>
14#include <limits.h> /* UINT_MAX */
15#include <stdio.h> /* fprintf */
16#include <stdlib.h> /* getenv */
17
18#define EXPAT_POCO 1
19
20#if defined(EXPAT_POCO)
21#include "Poco/RandomStream.h"
22#include "Poco/BinaryReader.h"
23#elif defined(_WIN32)
24#define getpid GetCurrentProcessId
25#else
26#include <sys/time.h> /* gettimeofday() */
27#include <sys/types.h> /* getpid() */
28#include <unistd.h> /* getpid() */
29#include <fcntl.h> /* O_RDONLY */
30#include <errno.h>
31#endif
32
33#define XML_BUILDING_EXPAT 1
34
35#ifdef EXPAT_WIN32
36#include "winconfig.h"
37#elif defined(HAVE_EXPAT_CONFIG_H)
38#include "expat_config.h"
39#endif /* ndef EXPAT_WIN32 */
40
41#include "ascii.h"
42#include "Poco/XML/expat.h"
43#include "siphash.h"
44
45#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
46# if defined(HAVE_GETRANDOM)
47# include <sys/random.h> /* getrandom */
48# else
49# include <unistd.h> /* syscall */
50# include <sys/syscall.h> /* SYS_getrandom */
51# endif
52# if ! defined(GRND_NONBLOCK)
53# define GRND_NONBLOCK 0x0001
54# endif /* defined(GRND_NONBLOCK) */
55#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
56
57#if defined(HAVE_LIBBSD) \
58 && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
59# include <bsd/stdlib.h>
60#endif
61
62#if defined(_WIN32) && !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
63# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
64#endif
65
66#if !defined(HAVE_GETRANDOM) && !defined(HAVE_SYSCALL_GETRANDOM) \
67 && !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM) \
68 && !defined(XML_DEV_URANDOM) \
69 && !defined(_WIN32) \
70 && !defined(XML_POOR_ENTROPY) \
71 && !defined(EXPAT_POCO)
72# error \
73 You do not have support for any sources of high quality entropy \
74 enabled. For end user security, that is probably not what you want. \
75 \
76 Your options include: \
77 * Linux + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \
78 * Linux + glibc <2.25 (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \
79 * BSD / macOS >=10.7 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \
80 * BSD / macOS <10.7 (arc4random): HAVE_ARC4RANDOM, \
81 * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
82 * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
83 * Linux / BSD / macOS (/dev/urandom): XML_DEV_URANDOM \
84 * Windows (RtlGenRandom): _WIN32. \
85 \
86 If insist on not using any of these, bypass this error by defining \
87 XML_POOR_ENTROPY; you have been warned. \
88 \
89 If you have reasons to patch this detection code away or need changes \
90 to the build system, please open a bug. Thank you!
91#endif
92
93
94#ifdef XML_UNICODE
95#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
96#define XmlConvert XmlUtf16Convert
97#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
98#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
99#define XmlEncode XmlUtf16Encode
100/* Using pointer subtraction to convert to integer type. */
101#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
102typedef unsigned short ICHAR;
103#else
104#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
105#define XmlConvert XmlUtf8Convert
106#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
107#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
108#define XmlEncode XmlUtf8Encode
109#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
110typedef char ICHAR;
111#endif
112
113
114#ifndef XML_NS
115
116#define XmlInitEncodingNS XmlInitEncoding
117#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
118#undef XmlGetInternalEncodingNS
119#define XmlGetInternalEncodingNS XmlGetInternalEncoding
120#define XmlParseXmlDeclNS XmlParseXmlDecl
121
122#endif
123
124#ifdef XML_UNICODE
125
126#ifdef XML_UNICODE_WCHAR_T
127#define XML_T(x) (const wchar_t)x
128#define XML_L(x) L ## x
129#else
130#define XML_T(x) (const unsigned short)x
131#define XML_L(x) x
132#endif
133
134#else
135
136#define XML_T(x) x
137#define XML_L(x) x
138
139#endif
140
141/* Round up n to be a multiple of sz, where sz is a power of 2. */
142#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
143
144/* Handle the case where memmove() doesn't exist. */
145#ifndef HAVE_MEMMOVE
146#ifdef HAVE_BCOPY
147#define memmove(d,s,l) bcopy((s),(d),(l))
148#else
149#error memmove does not exist on this platform, nor is a substitute available
150#endif /* HAVE_BCOPY */
151#endif /* HAVE_MEMMOVE */
152
153#include "internal.h"
154#include "xmltok.h"
155#include "xmlrole.h"
156
157typedef const XML_Char *KEY;
158
159typedef struct {
160 KEY name;
161} NAMED;
162
163typedef struct {
164 NAMED **v;
165 unsigned char power;
166 size_t size;
167 size_t used;
168 const XML_Memory_Handling_Suite *mem;
169} HASH_TABLE;
170
171static size_t
172keylen(KEY s);
173
174static void
175copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key);
176
177/* For probing (after a collision) we need a step size relative prime
178 to the hash table size, which is a power of 2. We use double-hashing,
179 since we can calculate a second hash value cheaply by taking those bits
180 of the first hash value that were discarded (masked out) when the table
181 index was calculated: index = hash & mask, where mask = table->size - 1.
182 We limit the maximum step size to table->size / 4 (mask >> 2) and make
183 it odd, since odd numbers are always relative prime to a power of 2.
184*/
185#define SECOND_HASH(hash, mask, power) \
186 ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
187#define PROBE_STEP(hash, mask, power) \
188 ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
189
190typedef struct {
191 NAMED **p;
192 NAMED **end;
193} HASH_TABLE_ITER;
194
195#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
196#define INIT_DATA_BUF_SIZE 1024
197#define INIT_ATTS_SIZE 16
198#define INIT_ATTS_VERSION 0xFFFFFFFF
199#define INIT_BLOCK_SIZE 1024
200#define INIT_BUFFER_SIZE 1024
201
202#define EXPAND_SPARE 24
203
204typedef struct binding {
205 struct prefix *prefix;
206 struct binding *nextTagBinding;
207 struct binding *prevPrefixBinding;
208 const struct attribute_id *attId;
209 XML_Char *uri;
210 int uriLen;
211 int uriAlloc;
212} BINDING;
213
214typedef struct prefix {
215 const XML_Char *name;
216 BINDING *binding;
217} PREFIX;
218
219typedef struct {
220 const XML_Char *str;
221 const XML_Char *localPart;
222 const XML_Char *prefix;
223 int strLen;
224 int uriLen;
225 int prefixLen;
226} TAG_NAME;
227
228/* TAG represents an open element.
229 The name of the element is stored in both the document and API
230 encodings. The memory buffer 'buf' is a separately-allocated
231 memory area which stores the name. During the XML_Parse()/
232 XMLParseBuffer() when the element is open, the memory for the 'raw'
233 version of the name (in the document encoding) is shared with the
234 document buffer. If the element is open across calls to
235 XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
236 contain the 'raw' name as well.
237
238 A parser re-uses these structures, maintaining a list of allocated
239 TAG objects in a free list.
240*/
241typedef struct tag {
242 struct tag *parent; /* parent of this element */
243 const char *rawName; /* tagName in the original encoding */
244 int rawNameLength;
245 TAG_NAME name; /* tagName in the API encoding */
246 char *buf; /* buffer for name components */
247 char *bufEnd; /* end of the buffer */
248 BINDING *bindings;
249} TAG;
250
251typedef struct {
252 const XML_Char *name;
253 const XML_Char *textPtr;
254 int textLen; /* length in XML_Chars */
255 int processed; /* # of processed bytes - when suspended */
256 const XML_Char *systemId;
257 const XML_Char *base;
258 const XML_Char *publicId;
259 const XML_Char *notation;
260 XML_Bool open;
261 XML_Bool is_param;
262 XML_Bool is_internal; /* true if declared in internal subset outside PE */
263} ENTITY;
264
265typedef struct {
266 enum XML_Content_Type type;
267 enum XML_Content_Quant quant;
268 const XML_Char * name;
269 int firstchild;
270 int lastchild;
271 int childcnt;
272 int nextsib;
273} CONTENT_SCAFFOLD;
274
275#define INIT_SCAFFOLD_ELEMENTS 32
276
277typedef struct block {
278 struct block *next;
279 int size;
280 XML_Char s[1];
281} BLOCK;
282
283typedef struct {
284 BLOCK *blocks;
285 BLOCK *freeBlocks;
286 const XML_Char *end;
287 XML_Char *ptr;
288 XML_Char *start;
289 const XML_Memory_Handling_Suite *mem;
290} STRING_POOL;
291
292/* The XML_Char before the name is used to determine whether
293 an attribute has been specified. */
294typedef struct attribute_id {
295 XML_Char *name;
296 PREFIX *prefix;
297 XML_Bool maybeTokenized;
298 XML_Bool xmlns;
299} ATTRIBUTE_ID;
300
301typedef struct {
302 const ATTRIBUTE_ID *id;
303 XML_Bool isCdata;
304 const XML_Char *value;
305} DEFAULT_ATTRIBUTE;
306
307typedef struct {
308 unsigned long version;
309 unsigned long hash;
310 const XML_Char *uriName;
311} NS_ATT;
312
313typedef struct {
314 const XML_Char *name;
315 PREFIX *prefix;
316 const ATTRIBUTE_ID *idAtt;
317 int nDefaultAtts;
318 int allocDefaultAtts;
319 DEFAULT_ATTRIBUTE *defaultAtts;
320} ELEMENT_TYPE;
321
322typedef struct {
323 HASH_TABLE generalEntities;
324 HASH_TABLE elementTypes;
325 HASH_TABLE attributeIds;
326 HASH_TABLE prefixes;
327 STRING_POOL pool;
328 STRING_POOL entityValuePool;
329 /* false once a parameter entity reference has been skipped */
330 XML_Bool keepProcessing;
331 /* true once an internal or external PE reference has been encountered;
332 this includes the reference to an external subset */
333 XML_Bool hasParamEntityRefs;
334 XML_Bool standalone;
335#ifdef XML_DTD
336 /* indicates if external PE has been read */
337 XML_Bool paramEntityRead;
338 HASH_TABLE paramEntities;
339#endif /* XML_DTD */
340 PREFIX defaultPrefix;
341 /* === scaffolding for building content model === */
342 XML_Bool in_eldecl;
343 CONTENT_SCAFFOLD *scaffold;
344 unsigned contentStringLen;
345 unsigned scaffSize;
346 unsigned scaffCount;
347 int scaffLevel;
348 int *scaffIndex;
349} DTD;
350
351typedef struct open_internal_entity {
352 const char *internalEventPtr;
353 const char *internalEventEndPtr;
354 struct open_internal_entity *next;
355 ENTITY *entity;
356 int startTagLevel;
357 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
358} OPEN_INTERNAL_ENTITY;
359
360typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
361 const char *start,
362 const char *end,
363 const char **endPtr);
364
365static Processor prologProcessor;
366static Processor prologInitProcessor;
367static Processor contentProcessor;
368static Processor cdataSectionProcessor;
369#ifdef XML_DTD
370static Processor ignoreSectionProcessor;
371static Processor externalParEntProcessor;
372static Processor externalParEntInitProcessor;
373static Processor entityValueProcessor;
374static Processor entityValueInitProcessor;
375#endif /* XML_DTD */
376static Processor epilogProcessor;
377static Processor errorProcessor;
378static Processor externalEntityInitProcessor;
379static Processor externalEntityInitProcessor2;
380static Processor externalEntityInitProcessor3;
381static Processor externalEntityContentProcessor;
382static Processor internalEntityProcessor;
383
384static enum XML_Error
385handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
386static enum XML_Error
387processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
388 const char *s, const char *next);
389static enum XML_Error
390initializeEncoding(XML_Parser parser);
391static enum XML_Error
392doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
393 const char *end, int tok, const char *next, const char **nextPtr,
394 XML_Bool haveMore);
395static enum XML_Error
396processInternalEntity(XML_Parser parser, ENTITY *entity,
397 XML_Bool betweenDecl);
398static enum XML_Error
399doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
400 const char *start, const char *end, const char **endPtr,
401 XML_Bool haveMore);
402static enum XML_Error
403doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
404 const char *end, const char **nextPtr, XML_Bool haveMore);
405#ifdef XML_DTD
406static enum XML_Error
407doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
408 const char *end, const char **nextPtr, XML_Bool haveMore);
409#endif /* XML_DTD */
410
411static void
412freeBindings(XML_Parser parser, BINDING *bindings);
413static enum XML_Error
414storeAtts(XML_Parser parser, const ENCODING *, const char *s,
415 TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
416static enum XML_Error
417addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
418 const XML_Char *uri, BINDING **bindingsPtr);
419static int
420defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
421 XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
422static enum XML_Error
423storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
424 const char *, const char *, STRING_POOL *);
425static enum XML_Error
426appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
427 const char *, const char *, STRING_POOL *);
428static ATTRIBUTE_ID *
429getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
430 const char *end);
431static int
432setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
433static enum XML_Error
434storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
435 const char *end);
436static int
437reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
438 const char *start, const char *end);
439static int
440reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
441 const char *end);
442static void
443reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
444 const char *end);
445
446static const XML_Char * getContext(XML_Parser parser);
447static XML_Bool
448setContext(XML_Parser parser, const XML_Char *context);
449
450static void FASTCALL normalizePublicId(XML_Char *s);
451
452static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
453/* do not call if parentParser != NULL */
454static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
455static void
456dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
457static int
458dtdCopy(XML_Parser oldParser,
459 DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
460static int
461copyEntityTable(XML_Parser oldParser,
462 HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
463static NAMED *
464lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
465static void FASTCALL
466hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
467static void FASTCALL hashTableClear(HASH_TABLE *);
468static void FASTCALL hashTableDestroy(HASH_TABLE *);
469static void FASTCALL
470hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
471static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
472
473static void FASTCALL
474poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
475static void FASTCALL poolClear(STRING_POOL *);
476static void FASTCALL poolDestroy(STRING_POOL *);
477static XML_Char *
478poolAppend(STRING_POOL *pool, const ENCODING *enc,
479 const char *ptr, const char *end);
480static XML_Char *
481poolStoreString(STRING_POOL *pool, const ENCODING *enc,
482 const char *ptr, const char *end);
483static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
484static const XML_Char * FASTCALL
485poolCopyString(STRING_POOL *pool, const XML_Char *s);
486static const XML_Char *
487poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
488static const XML_Char * FASTCALL
489poolAppendString(STRING_POOL *pool, const XML_Char *s);
490
491static int FASTCALL nextScaffoldPart(XML_Parser parser);
492static XML_Content * build_model(XML_Parser parser);
493static ELEMENT_TYPE *
494getElementType(XML_Parser parser, const ENCODING *enc,
495 const char *ptr, const char *end);
496
497static XML_Char *copyString(const XML_Char *s,
498 const XML_Memory_Handling_Suite *memsuite);
499
500static unsigned long generate_hash_secret_salt(XML_Parser parser);
501static XML_Bool startParsing(XML_Parser parser);
502
503static XML_Parser
504parserCreate(const XML_Char *encodingName,
505 const XML_Memory_Handling_Suite *memsuite,
506 const XML_Char *nameSep,
507 DTD *dtd);
508
509static void
510parserInit(XML_Parser parser, const XML_Char *encodingName);
511
512#define poolStart(pool) ((pool)->start)
513#define poolEnd(pool) ((pool)->ptr)
514#define poolLength(pool) ((pool)->ptr - (pool)->start)
515#define poolChop(pool) ((void)--(pool->ptr))
516#define poolLastChar(pool) (((pool)->ptr)[-1])
517#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
518#define poolFinish(pool) ((pool)->start = (pool)->ptr)
519#define poolAppendChar(pool, c) \
520 (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
521 ? 0 \
522 : ((*((pool)->ptr)++ = c), 1))
523
524struct XML_ParserStruct {
525 /* The first member must be userData so that the XML_GetUserData
526 macro works. */
527 void *m_userData;
528 void *m_handlerArg;
529 char *m_buffer;
530 const XML_Memory_Handling_Suite m_mem;
531 /* first character to be parsed */
532 const char *m_bufferPtr;
533 /* past last character to be parsed */
534 char *m_bufferEnd;
535 /* allocated end of buffer */
536 const char *m_bufferLim;
537 XML_Index m_parseEndByteIndex;
538 const char *m_parseEndPtr;
539 XML_Char *m_dataBuf;
540 XML_Char *m_dataBufEnd;
541 XML_StartElementHandler m_startElementHandler;
542 XML_EndElementHandler m_endElementHandler;
543 XML_CharacterDataHandler m_characterDataHandler;
544 XML_ProcessingInstructionHandler m_processingInstructionHandler;
545 XML_CommentHandler m_commentHandler;
546 XML_StartCdataSectionHandler m_startCdataSectionHandler;
547 XML_EndCdataSectionHandler m_endCdataSectionHandler;
548 XML_DefaultHandler m_defaultHandler;
549 XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
550 XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
551 XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
552 XML_NotationDeclHandler m_notationDeclHandler;
553 XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
554 XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
555 XML_NotStandaloneHandler m_notStandaloneHandler;
556 XML_ExternalEntityRefHandler m_externalEntityRefHandler;
557 XML_Parser m_externalEntityRefHandlerArg;
558 XML_SkippedEntityHandler m_skippedEntityHandler;
559 XML_UnknownEncodingHandler m_unknownEncodingHandler;
560 XML_ElementDeclHandler m_elementDeclHandler;
561 XML_AttlistDeclHandler m_attlistDeclHandler;
562 XML_EntityDeclHandler m_entityDeclHandler;
563 XML_XmlDeclHandler m_xmlDeclHandler;
564 const ENCODING *m_encoding;
565 INIT_ENCODING m_initEncoding;
566 const ENCODING *m_internalEncoding;
567 const XML_Char *m_protocolEncodingName;
568 XML_Bool m_ns;
569 XML_Bool m_ns_triplets;
570 void *m_unknownEncodingMem;
571 void *m_unknownEncodingData;
572 void *m_unknownEncodingHandlerData;
573 void (XMLCALL *m_unknownEncodingRelease)(void *);
574 PROLOG_STATE m_prologState;
575 Processor *m_processor;
576 enum XML_Error m_errorCode;
577 const char *m_eventPtr;
578 const char *m_eventEndPtr;
579 const char *m_positionPtr;
580 OPEN_INTERNAL_ENTITY *m_openInternalEntities;
581 OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
582 XML_Bool m_defaultExpandInternalEntities;
583 int m_tagLevel;
584 ENTITY *m_declEntity;
585 const XML_Char *m_doctypeName;
586 const XML_Char *m_doctypeSysid;
587 const XML_Char *m_doctypePubid;
588 const XML_Char *m_declAttributeType;
589 const XML_Char *m_declNotationName;
590 const XML_Char *m_declNotationPublicId;
591 ELEMENT_TYPE *m_declElementType;
592 ATTRIBUTE_ID *m_declAttributeId;
593 XML_Bool m_declAttributeIsCdata;
594 XML_Bool m_declAttributeIsId;
595 DTD *m_dtd;
596 const XML_Char *m_curBase;
597 TAG *m_tagStack;
598 TAG *m_freeTagList;
599 BINDING *m_inheritedBindings;
600 BINDING *m_freeBindingList;
601 int m_attsSize;
602 int m_nSpecifiedAtts;
603 int m_idAttIndex;
604 ATTRIBUTE *m_atts;
605 NS_ATT *m_nsAtts;
606 unsigned long m_nsAttsVersion;
607 unsigned char m_nsAttsPower;
608#ifdef XML_ATTR_INFO
609 XML_AttrInfo *m_attInfo;
610#endif
611 POSITION m_position;
612 STRING_POOL m_tempPool;
613 STRING_POOL m_temp2Pool;
614 char *m_groupConnector;
615 unsigned int m_groupSize;
616 XML_Char m_namespaceSeparator;
617 XML_Parser m_parentParser;
618 XML_ParsingStatus m_parsingStatus;
619#ifdef XML_DTD
620 XML_Bool m_isParamEntity;
621 XML_Bool m_useForeignDTD;
622 enum XML_ParamEntityParsing m_paramEntityParsing;
623#endif
624 unsigned long m_hash_secret_salt;
625};
626
627#define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
628#define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
629#define FREE(p) (parser->m_mem.free_fcn((p)))
630
631#define userData (parser->m_userData)
632#define handlerArg (parser->m_handlerArg)
633#define startElementHandler (parser->m_startElementHandler)
634#define endElementHandler (parser->m_endElementHandler)
635#define characterDataHandler (parser->m_characterDataHandler)
636#define processingInstructionHandler \
637 (parser->m_processingInstructionHandler)
638#define commentHandler (parser->m_commentHandler)
639#define startCdataSectionHandler \
640 (parser->m_startCdataSectionHandler)
641#define endCdataSectionHandler (parser->m_endCdataSectionHandler)
642#define defaultHandler (parser->m_defaultHandler)
643#define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
644#define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
645#define unparsedEntityDeclHandler \
646 (parser->m_unparsedEntityDeclHandler)
647#define notationDeclHandler (parser->m_notationDeclHandler)
648#define startNamespaceDeclHandler \
649 (parser->m_startNamespaceDeclHandler)
650#define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
651#define notStandaloneHandler (parser->m_notStandaloneHandler)
652#define externalEntityRefHandler \
653 (parser->m_externalEntityRefHandler)
654#define externalEntityRefHandlerArg \
655 (parser->m_externalEntityRefHandlerArg)
656#define internalEntityRefHandler \
657 (parser->m_internalEntityRefHandler)
658#define skippedEntityHandler (parser->m_skippedEntityHandler)
659#define unknownEncodingHandler (parser->m_unknownEncodingHandler)
660#define elementDeclHandler (parser->m_elementDeclHandler)
661#define attlistDeclHandler (parser->m_attlistDeclHandler)
662#define entityDeclHandler (parser->m_entityDeclHandler)
663#define xmlDeclHandler (parser->m_xmlDeclHandler)
664#define encoding (parser->m_encoding)
665#define initEncoding (parser->m_initEncoding)
666#define internalEncoding (parser->m_internalEncoding)
667#define unknownEncodingMem (parser->m_unknownEncodingMem)
668#define unknownEncodingData (parser->m_unknownEncodingData)
669#define unknownEncodingHandlerData \
670 (parser->m_unknownEncodingHandlerData)
671#define unknownEncodingRelease (parser->m_unknownEncodingRelease)
672#define protocolEncodingName (parser->m_protocolEncodingName)
673#define ns (parser->m_ns)
674#define ns_triplets (parser->m_ns_triplets)
675#define prologState (parser->m_prologState)
676#define processor (parser->m_processor)
677#define errorCode (parser->m_errorCode)
678#define eventPtr (parser->m_eventPtr)
679#define eventEndPtr (parser->m_eventEndPtr)
680#define positionPtr (parser->m_positionPtr)
681#define position (parser->m_position)
682#define openInternalEntities (parser->m_openInternalEntities)
683#define freeInternalEntities (parser->m_freeInternalEntities)
684#define defaultExpandInternalEntities \
685 (parser->m_defaultExpandInternalEntities)
686#define tagLevel (parser->m_tagLevel)
687#define buffer (parser->m_buffer)
688#define bufferPtr (parser->m_bufferPtr)
689#define bufferEnd (parser->m_bufferEnd)
690#define parseEndByteIndex (parser->m_parseEndByteIndex)
691#define parseEndPtr (parser->m_parseEndPtr)
692#define bufferLim (parser->m_bufferLim)
693#define dataBuf (parser->m_dataBuf)
694#define dataBufEnd (parser->m_dataBufEnd)
695#define _dtd (parser->m_dtd)
696#define curBase (parser->m_curBase)
697#define declEntity (parser->m_declEntity)
698#define doctypeName (parser->m_doctypeName)
699#define doctypeSysid (parser->m_doctypeSysid)
700#define doctypePubid (parser->m_doctypePubid)
701#define declAttributeType (parser->m_declAttributeType)
702#define declNotationName (parser->m_declNotationName)
703#define declNotationPublicId (parser->m_declNotationPublicId)
704#define declElementType (parser->m_declElementType)
705#define declAttributeId (parser->m_declAttributeId)
706#define declAttributeIsCdata (parser->m_declAttributeIsCdata)
707#define declAttributeIsId (parser->m_declAttributeIsId)
708#define freeTagList (parser->m_freeTagList)
709#define freeBindingList (parser->m_freeBindingList)
710#define inheritedBindings (parser->m_inheritedBindings)
711#define tagStack (parser->m_tagStack)
712#define atts (parser->m_atts)
713#define attsSize (parser->m_attsSize)
714#define nSpecifiedAtts (parser->m_nSpecifiedAtts)
715#define idAttIndex (parser->m_idAttIndex)
716#define nsAtts (parser->m_nsAtts)
717#define nsAttsVersion (parser->m_nsAttsVersion)
718#define nsAttsPower (parser->m_nsAttsPower)
719#define attInfo (parser->m_attInfo)
720#define tempPool (parser->m_tempPool)
721#define temp2Pool (parser->m_temp2Pool)
722#define groupConnector (parser->m_groupConnector)
723#define groupSize (parser->m_groupSize)
724#define namespaceSeparator (parser->m_namespaceSeparator)
725#define parentParser (parser->m_parentParser)
726#define ps_parsing (parser->m_parsingStatus.parsing)
727#define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
728#ifdef XML_DTD
729#define isParamEntity (parser->m_isParamEntity)
730#define useForeignDTD (parser->m_useForeignDTD)
731#define paramEntityParsing (parser->m_paramEntityParsing)
732#endif /* XML_DTD */
733#define hash_secret_salt (parser->m_hash_secret_salt)
734
735XML_Parser XMLCALL
736XML_ParserCreate(const XML_Char *encodingName)
737{
738 return XML_ParserCreate_MM(encodingName, NULL, NULL);
739}
740
741XML_Parser XMLCALL
742XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
743{
744 XML_Char tmp[2];
745 *tmp = nsSep;
746 return XML_ParserCreate_MM(encodingName, NULL, tmp);
747}
748
749static const XML_Char implicitContext[] = {
750 ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
751 ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
752 ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
753 ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
754 ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
755 ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
756};
757
758
759#if !defined(EXPAT_POCO)
760#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
761# include <errno.h>
762
763# if defined(HAVE_GETRANDOM)
764# include <sys/random.h> /* getrandom */
765# else
766# include <unistd.h> /* syscall */
767# include <sys/syscall.h> /* SYS_getrandom */
768# endif
769
770/* Obtain entropy on Linux 3.17+ */
771static int
772writeRandomBytes_getrandom_nonblock(void * target, size_t count) {
773 int success = 0; /* full count bytes written? */
774 size_t bytesWrittenTotal = 0;
775 const unsigned int getrandomFlags = GRND_NONBLOCK;
776
777 do {
778 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
779 const size_t bytesToWrite = count - bytesWrittenTotal;
780
781 const int bytesWrittenMore =
782#if defined(HAVE_GETRANDOM)
783 getrandom(currentTarget, bytesToWrite, getrandomFlags);
784#else
785 syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
786#endif
787
788 if (bytesWrittenMore > 0) {
789 bytesWrittenTotal += bytesWrittenMore;
790 if (bytesWrittenTotal >= count)
791 success = 1;
792 }
793 } while (! success && (errno == EINTR));
794
795 return success;
796}
797
798#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
799
800
801#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
802
803/* Extract entropy from /dev/urandom */
804static int
805writeRandomBytes_dev_urandom(void * target, size_t count) {
806 int success = 0; /* full count bytes written? */
807 size_t bytesWrittenTotal = 0;
808
809 const int fd = open("/dev/urandom", O_RDONLY);
810 if (fd < 0) {
811 return 0;
812 }
813
814 do {
815 void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
816 const size_t bytesToWrite = count - bytesWrittenTotal;
817
818 const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
819
820 if (bytesWrittenMore > 0) {
821 bytesWrittenTotal += bytesWrittenMore;
822 if (bytesWrittenTotal >= count)
823 success = 1;
824 }
825 } while (! success && (errno == EINTR));
826
827 close(fd);
828 return success;
829}
830
831#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
832
833
834#if defined(HAVE_ARC4RANDOM)
835
836static void
837writeRandomBytes_arc4random(void * target, size_t count) {
838 size_t bytesWrittenTotal = 0;
839
840 while (bytesWrittenTotal < count) {
841 const uint32_t random32 = arc4random();
842 size_t i = 0;
843
844 for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
845 i++, bytesWrittenTotal++) {
846 const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
847 ((uint8_t *)target)[bytesWrittenTotal] = random8;
848 }
849 }
850}
851
852#endif /* defined(HAVE_ARC4RANDOM) */
853
854
855#ifdef _WIN32
856
857typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
858HMODULE _Expat_LoadLibrary(LPCTSTR filename); /* see loadlibrary.c */
859
860/* Obtain entropy on Windows XP / Windows Server 2003 and later.
861 * Hint on RtlGenRandom and the following article from libsodium.
862 *
863 * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
864 * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
865 */
866static int
867writeRandomBytes_RtlGenRandom(void * target, size_t count) {
868 int success = 0; /* full count bytes written? */
869 const HMODULE advapi32 = _Expat_LoadLibrary(TEXT("ADVAPI32.DLL"));
870
871 if (advapi32) {
872 const RTLGENRANDOM_FUNC RtlGenRandom
873 = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
874 if (RtlGenRandom) {
875 if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
876 success = 1;
877 }
878 }
879 FreeLibrary(advapi32);
880 }
881
882 return success;
883}
884
885#endif /* _WIN32 */
886
887
888#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
889
890static unsigned long
891gather_time_entropy(void)
892{
893#ifdef _WIN32
894 FILETIME ft;
895 GetSystemTimeAsFileTime(&ft); /* never fails */
896 return ft.dwHighDateTime ^ ft.dwLowDateTime;
897#else
898 struct timeval tv;
899 int gettimeofday_res;
900
901 gettimeofday_res = gettimeofday(&tv, NULL);
902
903#if defined(NDEBUG)
904 (void)gettimeofday_res;
905#else
906 assert (gettimeofday_res == 0);
907#endif /* defined(NDEBUG) */
908
909 /* Microseconds time is <20 bits entropy */
910 return tv.tv_usec;
911#endif
912}
913#endif
914
915#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
916
917
918static unsigned long
919ENTROPY_DEBUG(const char * label, unsigned long entropy) {
920#ifdef ENABLE_EXPAT_ENTROPY_DEBUG
921 const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
922 if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
923 fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
924 label,
925 (int)sizeof(entropy) * 2, entropy,
926 (unsigned long)sizeof(entropy));
927 }
928#endif
929 return entropy;
930}
931
932static unsigned long
933generate_hash_secret_salt(XML_Parser parser)
934{
935#if defined(EXPAT_POCO)
936 Poco::UInt64 entropy;
937 Poco::RandomInputStream rstr;
938 Poco::BinaryReader rrdr(rstr);
939 rrdr >> entropy;
940 return ENTROPY_DEBUG("RandomInputStream", (unsigned long)entropy);
941#else
942 unsigned long entropy;
943 (void)parser;
944#if defined(HAVE_ARC4RANDOM_BUF) || defined(__CloudABI__)
945 (void)gather_time_entropy;
946 arc4random_buf(&entropy, sizeof(entropy));
947 return ENTROPY_DEBUG("arc4random_buf", entropy);
948#elif defined(HAVE_ARC4RANDOM)
949 writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
950 return ENTROPY_DEBUG("arc4random", entropy);
951#else
952 /* Try high quality providers first .. */
953#ifdef _WIN32
954 if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
955 return ENTROPY_DEBUG("RtlGenRandom", entropy);
956 }
957#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
958 if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
959 return ENTROPY_DEBUG("getrandom", entropy);
960 }
961#endif
962#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
963 if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
964 return ENTROPY_DEBUG("/dev/urandom", entropy);
965 }
966#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
967 /* .. and self-made low quality for backup: */
968
969 /* Process ID is 0 bits entropy if attacker has local access */
970 entropy = gather_time_entropy() ^ getpid();
971
972 /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
973 if (sizeof(unsigned long) == 4) {
974 return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
975 } else {
976 return ENTROPY_DEBUG("fallback(8)",
977 entropy * (unsigned long)2305843009213693951ULL);
978 }
979#endif
980#endif
981}
982
983static unsigned long
984get_hash_secret_salt(XML_Parser parser) {
985 if (parser->m_parentParser != NULL)
986 return get_hash_secret_salt(parser->m_parentParser);
987 return parser->m_hash_secret_salt;
988}
989
990static XML_Bool /* only valid for root parser */
991startParsing(XML_Parser parser)
992{
993 /* hash functions must be initialized before setContext() is called */
994 if (hash_secret_salt == 0)
995 hash_secret_salt = generate_hash_secret_salt(parser);
996 if (ns) {
997 /* implicit context only set for root parser, since child
998 parsers (i.e. external entity parsers) will inherit it
999 */
1000 return setContext(parser, implicitContext);
1001 }
1002 return XML_TRUE;
1003}
1004
1005XML_Parser XMLCALL
1006XML_ParserCreate_MM(const XML_Char *encodingName,
1007 const XML_Memory_Handling_Suite *memsuite,
1008 const XML_Char *nameSep)
1009{
1010 return parserCreate(encodingName, memsuite, nameSep, NULL);
1011}
1012
1013static XML_Parser
1014parserCreate(const XML_Char *encodingName,
1015 const XML_Memory_Handling_Suite *memsuite,
1016 const XML_Char *nameSep,
1017 DTD *dtd)
1018{
1019 XML_Parser parser;
1020
1021 if (memsuite) {
1022 XML_Memory_Handling_Suite *mtemp;
1023 parser = (XML_Parser)
1024 memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
1025 if (parser != NULL) {
1026 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
1027 mtemp->malloc_fcn = memsuite->malloc_fcn;
1028 mtemp->realloc_fcn = memsuite->realloc_fcn;
1029 mtemp->free_fcn = memsuite->free_fcn;
1030 }
1031 }
1032 else {
1033 XML_Memory_Handling_Suite *mtemp;
1034 parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
1035 if (parser != NULL) {
1036 mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
1037 mtemp->malloc_fcn = malloc;
1038 mtemp->realloc_fcn = realloc;
1039 mtemp->free_fcn = free;
1040 }
1041 }
1042
1043 if (!parser)
1044 return parser;
1045
1046 buffer = NULL;
1047 bufferLim = NULL;
1048
1049 attsSize = INIT_ATTS_SIZE;
1050 atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
1051 if (atts == NULL) {
1052 FREE(parser);
1053 return NULL;
1054 }
1055#ifdef XML_ATTR_INFO
1056 attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));
1057 if (attInfo == NULL) {
1058 FREE(atts);
1059 FREE(parser);
1060 return NULL;
1061 }
1062#endif
1063 dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
1064 if (dataBuf == NULL) {
1065 FREE(atts);
1066#ifdef XML_ATTR_INFO
1067 FREE(attInfo);
1068#endif
1069 FREE(parser);
1070 return NULL;
1071 }
1072 dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
1073
1074 if (dtd)
1075 _dtd = dtd;
1076 else {
1077 _dtd = dtdCreate(&parser->m_mem);
1078 if (_dtd == NULL) {
1079 FREE(dataBuf);
1080 FREE(atts);
1081#ifdef XML_ATTR_INFO
1082 FREE(attInfo);
1083#endif
1084 FREE(parser);
1085 return NULL;
1086 }
1087 }
1088
1089 freeBindingList = NULL;
1090 freeTagList = NULL;
1091 freeInternalEntities = NULL;
1092
1093 groupSize = 0;
1094 groupConnector = NULL;
1095
1096 unknownEncodingHandler = NULL;
1097 unknownEncodingHandlerData = NULL;
1098
1099 namespaceSeparator = ASCII_EXCL;
1100 ns = XML_FALSE;
1101 ns_triplets = XML_FALSE;
1102
1103 nsAtts = NULL;
1104 nsAttsVersion = 0;
1105 nsAttsPower = 0;
1106
1107 protocolEncodingName = NULL;
1108
1109 poolInit(&tempPool, &(parser->m_mem));
1110 poolInit(&temp2Pool, &(parser->m_mem));
1111 parserInit(parser, encodingName);
1112
1113 if (encodingName && !protocolEncodingName) {
1114 XML_ParserFree(parser);
1115 return NULL;
1116 }
1117
1118 if (nameSep) {
1119 ns = XML_TRUE;
1120 internalEncoding = XmlGetInternalEncodingNS();
1121 namespaceSeparator = *nameSep;
1122 }
1123 else {
1124 internalEncoding = XmlGetInternalEncoding();
1125 }
1126
1127 return parser;
1128}
1129
1130static void
1131parserInit(XML_Parser parser, const XML_Char *encodingName)
1132{
1133 processor = prologInitProcessor;
1134 XmlPrologStateInit(&prologState);
1135 if (encodingName != NULL) {
1136 protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1137 }
1138 curBase = NULL;
1139 XmlInitEncoding(&initEncoding, &encoding, 0);
1140 userData = NULL;
1141 handlerArg = NULL;
1142 startElementHandler = NULL;
1143 endElementHandler = NULL;
1144 characterDataHandler = NULL;
1145 processingInstructionHandler = NULL;
1146 commentHandler = NULL;
1147 startCdataSectionHandler = NULL;
1148 endCdataSectionHandler = NULL;
1149 defaultHandler = NULL;
1150 startDoctypeDeclHandler = NULL;
1151 endDoctypeDeclHandler = NULL;
1152 unparsedEntityDeclHandler = NULL;
1153 notationDeclHandler = NULL;
1154 startNamespaceDeclHandler = NULL;
1155 endNamespaceDeclHandler = NULL;
1156 notStandaloneHandler = NULL;
1157 externalEntityRefHandler = NULL;
1158 externalEntityRefHandlerArg = parser;
1159 skippedEntityHandler = NULL;
1160 elementDeclHandler = NULL;
1161 attlistDeclHandler = NULL;
1162 entityDeclHandler = NULL;
1163 xmlDeclHandler = NULL;
1164 bufferPtr = buffer;
1165 bufferEnd = buffer;
1166 parseEndByteIndex = 0;
1167 parseEndPtr = NULL;
1168 declElementType = NULL;
1169 declAttributeId = NULL;
1170 declEntity = NULL;
1171 doctypeName = NULL;
1172 doctypeSysid = NULL;
1173 doctypePubid = NULL;
1174 declAttributeType = NULL;
1175 declNotationName = NULL;
1176 declNotationPublicId = NULL;
1177 declAttributeIsCdata = XML_FALSE;
1178 declAttributeIsId = XML_FALSE;
1179 memset(&position, 0, sizeof(POSITION));
1180 errorCode = XML_ERROR_NONE;
1181 eventPtr = NULL;
1182 eventEndPtr = NULL;
1183 positionPtr = NULL;
1184 openInternalEntities = NULL;
1185 defaultExpandInternalEntities = XML_TRUE;
1186 tagLevel = 0;
1187 tagStack = NULL;
1188 inheritedBindings = NULL;
1189 nSpecifiedAtts = 0;
1190 unknownEncodingMem = NULL;
1191 unknownEncodingRelease = NULL;
1192 unknownEncodingData = NULL;
1193 parentParser = NULL;
1194 ps_parsing = XML_INITIALIZED;
1195#ifdef XML_DTD
1196 isParamEntity = XML_FALSE;
1197 useForeignDTD = XML_FALSE;
1198 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
1199#endif
1200 hash_secret_salt = 0;
1201}
1202
1203/* moves list of bindings to freeBindingList */
1204static void FASTCALL
1205moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
1206{
1207 while (bindings) {
1208 BINDING *b = bindings;
1209 bindings = bindings->nextTagBinding;
1210 b->nextTagBinding = freeBindingList;
1211 freeBindingList = b;
1212 }
1213}
1214
1215XML_Bool XMLCALL
1216XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
1217{
1218 TAG *tStk;
1219 OPEN_INTERNAL_ENTITY *openEntityList;
1220
1221 if (parser == NULL)
1222 return XML_FALSE;
1223
1224 if (parentParser)
1225 return XML_FALSE;
1226 /* move tagStack to freeTagList */
1227 tStk = tagStack;
1228 while (tStk) {
1229 TAG *tag = tStk;
1230 tStk = tStk->parent;
1231 tag->parent = freeTagList;
1232 moveToFreeBindingList(parser, tag->bindings);
1233 tag->bindings = NULL;
1234 freeTagList = tag;
1235 }
1236 /* move openInternalEntities to freeInternalEntities */
1237 openEntityList = openInternalEntities;
1238 while (openEntityList) {
1239 OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
1240 openEntityList = openEntity->next;
1241 openEntity->next = freeInternalEntities;
1242 freeInternalEntities = openEntity;
1243 }
1244 moveToFreeBindingList(parser, inheritedBindings);
1245 FREE(unknownEncodingMem);
1246 if (unknownEncodingRelease)
1247 unknownEncodingRelease(unknownEncodingData);
1248 poolClear(&tempPool);
1249 poolClear(&temp2Pool);
1250 FREE((void *)protocolEncodingName);
1251 protocolEncodingName = NULL;
1252 parserInit(parser, encodingName);
1253 dtdReset(_dtd, &parser->m_mem);
1254 return XML_TRUE;
1255}
1256
1257enum XML_Status XMLCALL
1258XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
1259{
1260 if (parser == NULL)
1261 return XML_STATUS_ERROR;
1262 /* Block after XML_Parse()/XML_ParseBuffer() has been called.
1263 XXX There's no way for the caller to determine which of the
1264 XXX possible error cases caused the XML_STATUS_ERROR return.
1265 */
1266 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1267 return XML_STATUS_ERROR;
1268
1269 /* Get rid of any previous encoding name */
1270 FREE((void *)protocolEncodingName);
1271
1272 if (encodingName == NULL)
1273 /* No new encoding name */
1274 protocolEncodingName = NULL;
1275 else {
1276 /* Copy the new encoding name into allocated memory */
1277 protocolEncodingName = copyString(encodingName, &(parser->m_mem));
1278 if (!protocolEncodingName)
1279 return XML_STATUS_ERROR;
1280 }
1281 return XML_STATUS_OK;
1282}
1283
1284XML_Parser XMLCALL
1285XML_ExternalEntityParserCreate(XML_Parser oldParser,
1286 const XML_Char *context,
1287 const XML_Char *encodingName)
1288{
1289 XML_Parser parser = oldParser;
1290 DTD *newDtd = NULL;
1291 DTD *oldDtd;
1292 XML_StartElementHandler oldStartElementHandler;
1293 XML_EndElementHandler oldEndElementHandler;
1294 XML_CharacterDataHandler oldCharacterDataHandler;
1295 XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
1296 XML_CommentHandler oldCommentHandler;
1297 XML_StartCdataSectionHandler oldStartCdataSectionHandler;
1298 XML_EndCdataSectionHandler oldEndCdataSectionHandler;
1299 XML_DefaultHandler oldDefaultHandler;
1300 XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
1301 XML_NotationDeclHandler oldNotationDeclHandler;
1302 XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
1303 XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
1304 XML_NotStandaloneHandler oldNotStandaloneHandler;
1305 XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
1306 XML_SkippedEntityHandler oldSkippedEntityHandler;
1307 XML_UnknownEncodingHandler oldUnknownEncodingHandler;
1308 XML_ElementDeclHandler oldElementDeclHandler;
1309 XML_AttlistDeclHandler oldAttlistDeclHandler;
1310 XML_EntityDeclHandler oldEntityDeclHandler;
1311 XML_XmlDeclHandler oldXmlDeclHandler;
1312 ELEMENT_TYPE * oldDeclElementType;
1313
1314 void *oldUserData;
1315 void *oldHandlerArg;
1316 XML_Bool oldDefaultExpandInternalEntities;
1317 XML_Parser oldExternalEntityRefHandlerArg;
1318#ifdef XML_DTD
1319 enum XML_ParamEntityParsing oldParamEntityParsing;
1320 int oldInEntityValue;
1321#endif
1322 XML_Bool oldns_triplets;
1323 /* Note that the new parser shares the same hash secret as the old
1324 parser, so that dtdCopy and copyEntityTable can lookup values
1325 from hash tables associated with either parser without us having
1326 to worry which hash secrets each table has.
1327 */
1328 unsigned long oldhash_secret_salt;
1329
1330 /* Validate the oldParser parameter before we pull everything out of it */
1331 if (oldParser == NULL)
1332 return NULL;
1333
1334 /* Stash the original parser contents on the stack */
1335 oldDtd = _dtd;
1336 oldStartElementHandler = startElementHandler;
1337 oldEndElementHandler = endElementHandler;
1338 oldCharacterDataHandler = characterDataHandler;
1339 oldProcessingInstructionHandler = processingInstructionHandler;
1340 oldCommentHandler = commentHandler;
1341 oldStartCdataSectionHandler = startCdataSectionHandler;
1342 oldEndCdataSectionHandler = endCdataSectionHandler;
1343 oldDefaultHandler = defaultHandler;
1344 oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
1345 oldNotationDeclHandler = notationDeclHandler;
1346 oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
1347 oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
1348 oldNotStandaloneHandler = notStandaloneHandler;
1349 oldExternalEntityRefHandler = externalEntityRefHandler;
1350 oldSkippedEntityHandler = skippedEntityHandler;
1351 oldUnknownEncodingHandler = unknownEncodingHandler;
1352 oldElementDeclHandler = elementDeclHandler;
1353 oldAttlistDeclHandler = attlistDeclHandler;
1354 oldEntityDeclHandler = entityDeclHandler;
1355 oldXmlDeclHandler = xmlDeclHandler;
1356 oldDeclElementType = declElementType;
1357
1358 oldUserData = userData;
1359 oldHandlerArg = handlerArg;
1360 oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
1361 oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
1362#ifdef XML_DTD
1363 oldParamEntityParsing = paramEntityParsing;
1364 oldInEntityValue = prologState.inEntityValue;
1365#endif
1366 oldns_triplets = ns_triplets;
1367 /* Note that the new parser shares the same hash secret as the old
1368 parser, so that dtdCopy and copyEntityTable can lookup values
1369 from hash tables associated with either parser without us having
1370 to worry which hash secrets each table has.
1371 */
1372 oldhash_secret_salt = hash_secret_salt;
1373
1374#ifdef XML_DTD
1375 if (!context)
1376 newDtd = oldDtd;
1377#endif /* XML_DTD */
1378
1379 /* Note that the magical uses of the pre-processor to make field
1380 access look more like C++ require that `parser' be overwritten
1381 here. This makes this function more painful to follow than it
1382 would be otherwise.
1383 */
1384 if (ns) {
1385 XML_Char tmp[2];
1386 *tmp = namespaceSeparator;
1387 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
1388 }
1389 else {
1390 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
1391 }
1392
1393 if (!parser)
1394 return NULL;
1395
1396 startElementHandler = oldStartElementHandler;
1397 endElementHandler = oldEndElementHandler;
1398 characterDataHandler = oldCharacterDataHandler;
1399 processingInstructionHandler = oldProcessingInstructionHandler;
1400 commentHandler = oldCommentHandler;
1401 startCdataSectionHandler = oldStartCdataSectionHandler;
1402 endCdataSectionHandler = oldEndCdataSectionHandler;
1403 defaultHandler = oldDefaultHandler;
1404 unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
1405 notationDeclHandler = oldNotationDeclHandler;
1406 startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
1407 endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
1408 notStandaloneHandler = oldNotStandaloneHandler;
1409 externalEntityRefHandler = oldExternalEntityRefHandler;
1410 skippedEntityHandler = oldSkippedEntityHandler;
1411 unknownEncodingHandler = oldUnknownEncodingHandler;
1412 elementDeclHandler = oldElementDeclHandler;
1413 attlistDeclHandler = oldAttlistDeclHandler;
1414 entityDeclHandler = oldEntityDeclHandler;
1415 xmlDeclHandler = oldXmlDeclHandler;
1416 declElementType = oldDeclElementType;
1417 userData = oldUserData;
1418 if (oldUserData == oldHandlerArg)
1419 handlerArg = userData;
1420 else
1421 handlerArg = parser;
1422 if (oldExternalEntityRefHandlerArg != oldParser)
1423 externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
1424 defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
1425 ns_triplets = oldns_triplets;
1426 hash_secret_salt = oldhash_secret_salt;
1427 parentParser = oldParser;
1428#ifdef XML_DTD
1429 paramEntityParsing = oldParamEntityParsing;
1430 prologState.inEntityValue = oldInEntityValue;
1431 if (context) {
1432#endif /* XML_DTD */
1433 if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
1434 || !setContext(parser, context)) {
1435 XML_ParserFree(parser);
1436 return NULL;
1437 }
1438 processor = externalEntityInitProcessor;
1439#ifdef XML_DTD
1440 }
1441 else {
1442 /* The DTD instance referenced by _dtd is shared between the document's
1443 root parser and external PE parsers, therefore one does not need to
1444 call setContext. In addition, one also *must* not call setContext,
1445 because this would overwrite existing prefix->binding pointers in
1446 _dtd with ones that get destroyed with the external PE parser.
1447 This would leave those prefixes with dangling pointers.
1448 */
1449 isParamEntity = XML_TRUE;
1450 XmlPrologStateInitExternalEntity(&prologState);
1451 processor = externalParEntInitProcessor;
1452 }
1453#endif /* XML_DTD */
1454 return parser;
1455}
1456
1457static void FASTCALL
1458destroyBindings(BINDING *bindings, XML_Parser parser)
1459{
1460 for (;;) {
1461 BINDING *b = bindings;
1462 if (!b)
1463 break;
1464 bindings = b->nextTagBinding;
1465 FREE(b->uri);
1466 FREE(b);
1467 }
1468}
1469
1470void XMLCALL
1471XML_ParserFree(XML_Parser parser)
1472{
1473 TAG *tagList;
1474 OPEN_INTERNAL_ENTITY *entityList;
1475 if (parser == NULL)
1476 return;
1477 /* free tagStack and freeTagList */
1478 tagList = tagStack;
1479 for (;;) {
1480 TAG *p;
1481 if (tagList == NULL) {
1482 if (freeTagList == NULL)
1483 break;
1484 tagList = freeTagList;
1485 freeTagList = NULL;
1486 }
1487 p = tagList;
1488 tagList = tagList->parent;
1489 FREE(p->buf);
1490 destroyBindings(p->bindings, parser);
1491 FREE(p);
1492 }
1493 /* free openInternalEntities and freeInternalEntities */
1494 entityList = openInternalEntities;
1495 for (;;) {
1496 OPEN_INTERNAL_ENTITY *openEntity;
1497 if (entityList == NULL) {
1498 if (freeInternalEntities == NULL)
1499 break;
1500 entityList = freeInternalEntities;
1501 freeInternalEntities = NULL;
1502 }
1503 openEntity = entityList;
1504 entityList = entityList->next;
1505 FREE(openEntity);
1506 }
1507
1508 destroyBindings(freeBindingList, parser);
1509 destroyBindings(inheritedBindings, parser);
1510 poolDestroy(&tempPool);
1511 poolDestroy(&temp2Pool);
1512 FREE((void *)protocolEncodingName);
1513#ifdef XML_DTD
1514 /* external parameter entity parsers share the DTD structure
1515 parser->m_dtd with the root parser, so we must not destroy it
1516 */
1517 if (!isParamEntity && _dtd)
1518#else
1519 if (_dtd)
1520#endif /* XML_DTD */
1521 dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
1522 FREE((void *)atts);
1523#ifdef XML_ATTR_INFO
1524 FREE((void *)attInfo);
1525#endif
1526 FREE(groupConnector);
1527 FREE(buffer);
1528 FREE(dataBuf);
1529 FREE(nsAtts);
1530 FREE(unknownEncodingMem);
1531 if (unknownEncodingRelease)
1532 unknownEncodingRelease(unknownEncodingData);
1533 FREE(parser);
1534}
1535
1536void XMLCALL
1537XML_UseParserAsHandlerArg(XML_Parser parser)
1538{
1539 if (parser != NULL)
1540 handlerArg = parser;
1541}
1542
1543enum XML_Error XMLCALL
1544XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
1545{
1546 if (parser == NULL)
1547 return XML_ERROR_INVALID_ARGUMENT;
1548#ifdef XML_DTD
1549 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1550 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1551 return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
1552 useForeignDTD = useDTD;
1553 return XML_ERROR_NONE;
1554#else
1555 return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
1556#endif
1557}
1558
1559void XMLCALL
1560XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
1561{
1562 if (parser == NULL)
1563 return;
1564 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1565 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1566 return;
1567 ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
1568}
1569
1570void XMLCALL
1571XML_SetUserData(XML_Parser parser, void *p)
1572{
1573 if (parser == NULL)
1574 return;
1575 if (handlerArg == userData)
1576 handlerArg = userData = p;
1577 else
1578 userData = p;
1579}
1580
1581enum XML_Status XMLCALL
1582XML_SetBase(XML_Parser parser, const XML_Char *p)
1583{
1584 if (parser == NULL)
1585 return XML_STATUS_ERROR;
1586 if (p) {
1587 p = poolCopyString(&_dtd->pool, p);
1588 if (!p)
1589 return XML_STATUS_ERROR;
1590 curBase = p;
1591 }
1592 else
1593 curBase = NULL;
1594 return XML_STATUS_OK;
1595}
1596
1597const XML_Char * XMLCALL
1598XML_GetBase(XML_Parser parser)
1599{
1600 if (parser == NULL)
1601 return NULL;
1602 return curBase;
1603}
1604
1605int XMLCALL
1606XML_GetSpecifiedAttributeCount(XML_Parser parser)
1607{
1608 if (parser == NULL)
1609 return -1;
1610 return nSpecifiedAtts;
1611}
1612
1613int XMLCALL
1614XML_GetIdAttributeIndex(XML_Parser parser)
1615{
1616 if (parser == NULL)
1617 return -1;
1618 return idAttIndex;
1619}
1620
1621#ifdef XML_ATTR_INFO
1622const XML_AttrInfo * XMLCALL
1623XML_GetAttributeInfo(XML_Parser parser)
1624{
1625 if (parser == NULL)
1626 return NULL;
1627 return attInfo;
1628}
1629#endif
1630
1631void XMLCALL
1632XML_SetElementHandler(XML_Parser parser,
1633 XML_StartElementHandler start,
1634 XML_EndElementHandler end)
1635{
1636 if (parser == NULL)
1637 return;
1638 startElementHandler = start;
1639 endElementHandler = end;
1640}
1641
1642void XMLCALL
1643XML_SetStartElementHandler(XML_Parser parser,
1644 XML_StartElementHandler start) {
1645 if (parser != NULL)
1646 startElementHandler = start;
1647}
1648
1649void XMLCALL
1650XML_SetEndElementHandler(XML_Parser parser,
1651 XML_EndElementHandler end) {
1652 if (parser != NULL)
1653 endElementHandler = end;
1654}
1655
1656void XMLCALL
1657XML_SetCharacterDataHandler(XML_Parser parser,
1658 XML_CharacterDataHandler handler)
1659{
1660 if (parser != NULL)
1661 characterDataHandler = handler;
1662}
1663
1664void XMLCALL
1665XML_SetProcessingInstructionHandler(XML_Parser parser,
1666 XML_ProcessingInstructionHandler handler)
1667{
1668 if (parser != NULL)
1669 processingInstructionHandler = handler;
1670}
1671
1672void XMLCALL
1673XML_SetCommentHandler(XML_Parser parser,
1674 XML_CommentHandler handler)
1675{
1676 if (parser != NULL)
1677 commentHandler = handler;
1678}
1679
1680void XMLCALL
1681XML_SetCdataSectionHandler(XML_Parser parser,
1682 XML_StartCdataSectionHandler start,
1683 XML_EndCdataSectionHandler end)
1684{
1685 if (parser == NULL)
1686 return;
1687 startCdataSectionHandler = start;
1688 endCdataSectionHandler = end;
1689}
1690
1691void XMLCALL
1692XML_SetStartCdataSectionHandler(XML_Parser parser,
1693 XML_StartCdataSectionHandler start) {
1694 if (parser != NULL)
1695 startCdataSectionHandler = start;
1696}
1697
1698void XMLCALL
1699XML_SetEndCdataSectionHandler(XML_Parser parser,
1700 XML_EndCdataSectionHandler end) {
1701 if (parser != NULL)
1702 endCdataSectionHandler = end;
1703}
1704
1705void XMLCALL
1706XML_SetDefaultHandler(XML_Parser parser,
1707 XML_DefaultHandler handler)
1708{
1709 if (parser == NULL)
1710 return;
1711 defaultHandler = handler;
1712 defaultExpandInternalEntities = XML_FALSE;
1713}
1714
1715void XMLCALL
1716XML_SetDefaultHandlerExpand(XML_Parser parser,
1717 XML_DefaultHandler handler)
1718{
1719 if (parser == NULL)
1720 return;
1721 defaultHandler = handler;
1722 defaultExpandInternalEntities = XML_TRUE;
1723}
1724
1725void XMLCALL
1726XML_SetDoctypeDeclHandler(XML_Parser parser,
1727 XML_StartDoctypeDeclHandler start,
1728 XML_EndDoctypeDeclHandler end)
1729{
1730 if (parser == NULL)
1731 return;
1732 startDoctypeDeclHandler = start;
1733 endDoctypeDeclHandler = end;
1734}
1735
1736void XMLCALL
1737XML_SetStartDoctypeDeclHandler(XML_Parser parser,
1738 XML_StartDoctypeDeclHandler start) {
1739 if (parser != NULL)
1740 startDoctypeDeclHandler = start;
1741}
1742
1743void XMLCALL
1744XML_SetEndDoctypeDeclHandler(XML_Parser parser,
1745 XML_EndDoctypeDeclHandler end) {
1746 if (parser != NULL)
1747 endDoctypeDeclHandler = end;
1748}
1749
1750void XMLCALL
1751XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
1752 XML_UnparsedEntityDeclHandler handler)
1753{
1754 if (parser != NULL)
1755 unparsedEntityDeclHandler = handler;
1756}
1757
1758void XMLCALL
1759XML_SetNotationDeclHandler(XML_Parser parser,
1760 XML_NotationDeclHandler handler)
1761{
1762 if (parser != NULL)
1763 notationDeclHandler = handler;
1764}
1765
1766void XMLCALL
1767XML_SetNamespaceDeclHandler(XML_Parser parser,
1768 XML_StartNamespaceDeclHandler start,
1769 XML_EndNamespaceDeclHandler end)
1770{
1771 if (parser == NULL)
1772 return;
1773 startNamespaceDeclHandler = start;
1774 endNamespaceDeclHandler = end;
1775}
1776
1777void XMLCALL
1778XML_SetStartNamespaceDeclHandler(XML_Parser parser,
1779 XML_StartNamespaceDeclHandler start) {
1780 if (parser != NULL)
1781 startNamespaceDeclHandler = start;
1782}
1783
1784void XMLCALL
1785XML_SetEndNamespaceDeclHandler(XML_Parser parser,
1786 XML_EndNamespaceDeclHandler end) {
1787 if (parser != NULL)
1788 endNamespaceDeclHandler = end;
1789}
1790
1791void XMLCALL
1792XML_SetNotStandaloneHandler(XML_Parser parser,
1793 XML_NotStandaloneHandler handler)
1794{
1795 if (parser != NULL)
1796 notStandaloneHandler = handler;
1797}
1798
1799void XMLCALL
1800XML_SetExternalEntityRefHandler(XML_Parser parser,
1801 XML_ExternalEntityRefHandler handler)
1802{
1803 if (parser != NULL)
1804 externalEntityRefHandler = handler;
1805}
1806
1807void XMLCALL
1808XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
1809{
1810 if (parser == NULL)
1811 return;
1812 if (arg)
1813 externalEntityRefHandlerArg = (XML_Parser)arg;
1814 else
1815 externalEntityRefHandlerArg = parser;
1816}
1817
1818void XMLCALL
1819XML_SetSkippedEntityHandler(XML_Parser parser,
1820 XML_SkippedEntityHandler handler)
1821{
1822 if (parser != NULL)
1823 skippedEntityHandler = handler;
1824}
1825
1826void XMLCALL
1827XML_SetUnknownEncodingHandler(XML_Parser parser,
1828 XML_UnknownEncodingHandler handler,
1829 void *data)
1830{
1831 if (parser == NULL)
1832 return;
1833 unknownEncodingHandler = handler;
1834 unknownEncodingHandlerData = data;
1835}
1836
1837void XMLCALL
1838XML_SetElementDeclHandler(XML_Parser parser,
1839 XML_ElementDeclHandler eldecl)
1840{
1841 if (parser != NULL)
1842 elementDeclHandler = eldecl;
1843}
1844
1845void XMLCALL
1846XML_SetAttlistDeclHandler(XML_Parser parser,
1847 XML_AttlistDeclHandler attdecl)
1848{
1849 if (parser != NULL)
1850 attlistDeclHandler = attdecl;
1851}
1852
1853void XMLCALL
1854XML_SetEntityDeclHandler(XML_Parser parser,
1855 XML_EntityDeclHandler handler)
1856{
1857 if (parser != NULL)
1858 entityDeclHandler = handler;
1859}
1860
1861void XMLCALL
1862XML_SetXmlDeclHandler(XML_Parser parser,
1863 XML_XmlDeclHandler handler) {
1864 if (parser != NULL)
1865 xmlDeclHandler = handler;
1866}
1867
1868int XMLCALL
1869XML_SetParamEntityParsing(XML_Parser parser,
1870 enum XML_ParamEntityParsing peParsing)
1871{
1872 if (parser == NULL)
1873 return 0;
1874 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1875 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1876 return 0;
1877#ifdef XML_DTD
1878 paramEntityParsing = peParsing;
1879 return 1;
1880#else
1881 return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
1882#endif
1883}
1884
1885int XMLCALL
1886XML_SetHashSalt(XML_Parser parser,
1887 unsigned long hash_salt)
1888{
1889 if (parser == NULL)
1890 return 0;
1891 if (parser->m_parentParser)
1892 return XML_SetHashSalt(parser->m_parentParser, hash_salt);
1893 /* block after XML_Parse()/XML_ParseBuffer() has been called */
1894 if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
1895 return 0;
1896 hash_secret_salt = hash_salt;
1897 return 1;
1898}
1899
1900enum XML_Status XMLCALL
1901XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
1902{
1903 if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
1904 if (parser != NULL)
1905 parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
1906 return XML_STATUS_ERROR;
1907 }
1908 switch (ps_parsing) {
1909 case XML_SUSPENDED:
1910 errorCode = XML_ERROR_SUSPENDED;
1911 return XML_STATUS_ERROR;
1912 case XML_FINISHED:
1913 errorCode = XML_ERROR_FINISHED;
1914 return XML_STATUS_ERROR;
1915 case XML_INITIALIZED:
1916 if (parentParser == NULL && !startParsing(parser)) {
1917 errorCode = XML_ERROR_NO_MEMORY;
1918 return XML_STATUS_ERROR;
1919 }
1920 default:
1921 ps_parsing = XML_PARSING;
1922 }
1923
1924 if (len == 0) {
1925 ps_finalBuffer = (XML_Bool)isFinal;
1926 if (!isFinal)
1927 return XML_STATUS_OK;
1928 positionPtr = bufferPtr;
1929 parseEndPtr = bufferEnd;
1930
1931 /* If data are left over from last buffer, and we now know that these
1932 data are the final chunk of input, then we have to check them again
1933 to detect errors based on that fact.
1934 */
1935 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
1936
1937 if (errorCode == XML_ERROR_NONE) {
1938 switch (ps_parsing) {
1939 case XML_SUSPENDED:
1940 /* It is hard to be certain, but it seems that this case
1941 * cannot occur. This code is cleaning up a previous parse
1942 * with no new data (since len == 0). Changing the parsing
1943 * state requires getting to execute a handler function, and
1944 * there doesn't seem to be an opportunity for that while in
1945 * this circumstance.
1946 *
1947 * Given the uncertainty, we retain the code but exclude it
1948 * from coverage tests.
1949 *
1950 * LCOV_EXCL_START
1951 */
1952 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
1953 positionPtr = bufferPtr;
1954 return XML_STATUS_SUSPENDED;
1955 /* LCOV_EXCL_STOP */
1956 case XML_INITIALIZED:
1957 case XML_PARSING:
1958 ps_parsing = XML_FINISHED;
1959 /* fall through */
1960 default:
1961 return XML_STATUS_OK;
1962 }
1963 }
1964 eventEndPtr = eventPtr;
1965 processor = errorProcessor;
1966 return XML_STATUS_ERROR;
1967 }
1968#ifndef XML_CONTEXT_BYTES
1969 else if (bufferPtr == bufferEnd) {
1970 const char *end;
1971 int nLeftOver;
1972 enum XML_Status result;
1973 /* Detect overflow (a+b > MAX <==> b > MAX-a) */
1974 if (len > ((XML_Size)-1) / 2 - parseEndByteIndex) {
1975 errorCode = XML_ERROR_NO_MEMORY;
1976 eventPtr = eventEndPtr = NULL;
1977 processor = errorProcessor;
1978 return XML_STATUS_ERROR;
1979 }
1980 parseEndByteIndex += len;
1981 positionPtr = s;
1982 ps_finalBuffer = (XML_Bool)isFinal;
1983
1984 errorCode = processor(parser, s, parseEndPtr = s + len, &end);
1985
1986 if (errorCode != XML_ERROR_NONE) {
1987 eventEndPtr = eventPtr;
1988 processor = errorProcessor;
1989 return XML_STATUS_ERROR;
1990 }
1991 else {
1992 switch (ps_parsing) {
1993 case XML_SUSPENDED:
1994 result = XML_STATUS_SUSPENDED;
1995 break;
1996 case XML_INITIALIZED:
1997 case XML_PARSING:
1998 if (isFinal) {
1999 ps_parsing = XML_FINISHED;
2000 return XML_STATUS_OK;
2001 }
2002 /* fall through */
2003 default:
2004 result = XML_STATUS_OK;
2005 }
2006 }
2007
2008 XmlUpdatePosition(encoding, positionPtr, end, &position);
2009 nLeftOver = s + len - end;
2010 if (nLeftOver) {
2011 if (buffer == NULL || nLeftOver > bufferLim - buffer) {
2012 /* avoid _signed_ integer overflow */
2013 char *temp = NULL;
2014 const int bytesToAllocate = (int)((unsigned)len * 2U);
2015 if (bytesToAllocate > 0) {
2016 temp = (buffer == NULL
2017 ? (char *)MALLOC(bytesToAllocate)
2018 : (char *)REALLOC(buffer, bytesToAllocate));
2019 }
2020 if (temp == NULL) {
2021 errorCode = XML_ERROR_NO_MEMORY;
2022 eventPtr = eventEndPtr = NULL;
2023 processor = errorProcessor;
2024 return XML_STATUS_ERROR;
2025 }
2026 buffer = temp;
2027 bufferLim = buffer + bytesToAllocate;
2028 }
2029 memcpy(buffer, end, nLeftOver);
2030 }
2031 bufferPtr = buffer;
2032 bufferEnd = buffer + nLeftOver;
2033 positionPtr = bufferPtr;
2034 parseEndPtr = bufferEnd;
2035 eventPtr = bufferPtr;
2036 eventEndPtr = bufferPtr;
2037 return result;
2038 }
2039#endif /* not defined XML_CONTEXT_BYTES */
2040 else {
2041 void *buff = XML_GetBuffer(parser, len);
2042 if (buff == NULL)
2043 return XML_STATUS_ERROR;
2044 else {
2045 memcpy(buff, s, len);
2046 return XML_ParseBuffer(parser, len, isFinal);
2047 }
2048 }
2049}
2050
2051enum XML_Status XMLCALL
2052XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
2053{
2054 const char *start;
2055 enum XML_Status result = XML_STATUS_OK;
2056
2057 if (parser == NULL)
2058 return XML_STATUS_ERROR;
2059 switch (ps_parsing) {
2060 case XML_SUSPENDED:
2061 errorCode = XML_ERROR_SUSPENDED;
2062 return XML_STATUS_ERROR;
2063 case XML_FINISHED:
2064 errorCode = XML_ERROR_FINISHED;
2065 return XML_STATUS_ERROR;
2066 case XML_INITIALIZED:
2067 if (parentParser == NULL && !startParsing(parser)) {
2068 errorCode = XML_ERROR_NO_MEMORY;
2069 return XML_STATUS_ERROR;
2070 }
2071 default:
2072 ps_parsing = XML_PARSING;
2073 }
2074
2075 start = bufferPtr;
2076 positionPtr = start;
2077 bufferEnd += len;
2078 parseEndPtr = bufferEnd;
2079 parseEndByteIndex += len;
2080 ps_finalBuffer = (XML_Bool)isFinal;
2081
2082 errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
2083
2084 if (errorCode != XML_ERROR_NONE) {
2085 eventEndPtr = eventPtr;
2086 processor = errorProcessor;
2087 return XML_STATUS_ERROR;
2088 }
2089 else {
2090 switch (ps_parsing) {
2091 case XML_SUSPENDED:
2092 result = XML_STATUS_SUSPENDED;
2093 break;
2094 case XML_INITIALIZED:
2095 case XML_PARSING:
2096 if (isFinal) {
2097 ps_parsing = XML_FINISHED;
2098 return result;
2099 }
2100 default: ; /* should not happen */
2101 }
2102 }
2103
2104 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
2105 positionPtr = bufferPtr;
2106 return result;
2107}
2108
2109void * XMLCALL
2110XML_GetBuffer(XML_Parser parser, int len)
2111{
2112 if (parser == NULL)
2113 return NULL;
2114 if (len < 0) {
2115 errorCode = XML_ERROR_NO_MEMORY;
2116 return NULL;
2117 }
2118 switch (ps_parsing) {
2119 case XML_SUSPENDED:
2120 errorCode = XML_ERROR_SUSPENDED;
2121 return NULL;
2122 case XML_FINISHED:
2123 errorCode = XML_ERROR_FINISHED;
2124 return NULL;
2125 default: ;
2126 }
2127
2128 if (len > bufferLim - bufferEnd) {
2129#ifdef XML_CONTEXT_BYTES
2130 int keep;
2131#endif /* defined XML_CONTEXT_BYTES */
2132 /* Do not invoke signed arithmetic overflow: */
2133 int neededSize = (int) ((unsigned)len + (unsigned)(bufferEnd - bufferPtr));
2134 if (neededSize < 0) {
2135 errorCode = XML_ERROR_NO_MEMORY;
2136 return NULL;
2137 }
2138#ifdef XML_CONTEXT_BYTES
2139 keep = (int)(bufferPtr - buffer);
2140 if (keep > XML_CONTEXT_BYTES)
2141 keep = XML_CONTEXT_BYTES;
2142 neededSize += keep;
2143#endif /* defined XML_CONTEXT_BYTES */
2144 if (neededSize <= bufferLim - buffer) {
2145#ifdef XML_CONTEXT_BYTES
2146 if (keep < bufferPtr - buffer) {
2147 int offset = (int)(bufferPtr - buffer) - keep;
2148 memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
2149 bufferEnd -= offset;
2150 bufferPtr -= offset;
2151 }
2152#else
2153 memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
2154 bufferEnd = buffer + (bufferEnd - bufferPtr);
2155 bufferPtr = buffer;
2156#endif /* not defined XML_CONTEXT_BYTES */
2157 }
2158 else {
2159 char *newBuf;
2160 int bufferSize = (int)(bufferLim - bufferPtr);
2161 if (bufferSize == 0)
2162 bufferSize = INIT_BUFFER_SIZE;
2163 do {
2164 /* Do not invoke signed arithmetic overflow: */
2165 bufferSize = (int) (2U * (unsigned) bufferSize);
2166 } while (bufferSize < neededSize && bufferSize > 0);
2167 if (bufferSize <= 0) {
2168 errorCode = XML_ERROR_NO_MEMORY;
2169 return NULL;
2170 }
2171 newBuf = (char *)MALLOC(bufferSize);
2172 if (newBuf == 0) {
2173 errorCode = XML_ERROR_NO_MEMORY;
2174 return NULL;
2175 }
2176 bufferLim = newBuf + bufferSize;
2177#ifdef XML_CONTEXT_BYTES
2178 if (bufferPtr) {
2179 int keep = (int)(bufferPtr - buffer);
2180 if (keep > XML_CONTEXT_BYTES)
2181 keep = XML_CONTEXT_BYTES;
2182 memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
2183 FREE(buffer);
2184 buffer = newBuf;
2185 bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
2186 bufferPtr = buffer + keep;
2187 }
2188 else {
2189 bufferEnd = newBuf + (bufferEnd - bufferPtr);
2190 bufferPtr = buffer = newBuf;
2191 }
2192#else
2193 if (bufferPtr) {
2194 memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
2195 FREE(buffer);
2196 }
2197 bufferEnd = newBuf + (bufferEnd - bufferPtr);
2198 bufferPtr = buffer = newBuf;
2199#endif /* not defined XML_CONTEXT_BYTES */
2200 }
2201 eventPtr = eventEndPtr = NULL;
2202 positionPtr = NULL;
2203 }
2204 return bufferEnd;
2205}
2206
2207enum XML_Status XMLCALL
2208XML_StopParser(XML_Parser parser, XML_Bool resumable)
2209{
2210 if (parser == NULL)
2211 return XML_STATUS_ERROR;
2212 switch (ps_parsing) {
2213 case XML_SUSPENDED:
2214 if (resumable) {
2215 errorCode = XML_ERROR_SUSPENDED;
2216 return XML_STATUS_ERROR;
2217 }
2218 ps_parsing = XML_FINISHED;
2219 break;
2220 case XML_FINISHED:
2221 errorCode = XML_ERROR_FINISHED;
2222 return XML_STATUS_ERROR;
2223 default:
2224 if (resumable) {
2225#ifdef XML_DTD
2226 if (isParamEntity) {
2227 errorCode = XML_ERROR_SUSPEND_PE;
2228 return XML_STATUS_ERROR;
2229 }
2230#endif
2231 ps_parsing = XML_SUSPENDED;
2232 }
2233 else
2234 ps_parsing = XML_FINISHED;
2235 }
2236 return XML_STATUS_OK;
2237}
2238
2239enum XML_Status XMLCALL
2240XML_ResumeParser(XML_Parser parser)
2241{
2242 enum XML_Status result = XML_STATUS_OK;
2243
2244 if (parser == NULL)
2245 return XML_STATUS_ERROR;
2246 if (ps_parsing != XML_SUSPENDED) {
2247 errorCode = XML_ERROR_NOT_SUSPENDED;
2248 return XML_STATUS_ERROR;
2249 }
2250 ps_parsing = XML_PARSING;
2251
2252 errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
2253
2254 if (errorCode != XML_ERROR_NONE) {
2255 eventEndPtr = eventPtr;
2256 processor = errorProcessor;
2257 return XML_STATUS_ERROR;
2258 }
2259 else {
2260 switch (ps_parsing) {
2261 case XML_SUSPENDED:
2262 result = XML_STATUS_SUSPENDED;
2263 break;
2264 case XML_INITIALIZED:
2265 case XML_PARSING:
2266 if (ps_finalBuffer) {
2267 ps_parsing = XML_FINISHED;
2268 return result;
2269 }
2270 default: ;
2271 }
2272 }
2273
2274 XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
2275 positionPtr = bufferPtr;
2276 return result;
2277}
2278
2279void XMLCALL
2280XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
2281{
2282 if (parser == NULL)
2283 return;
2284 assert(status != NULL);
2285 *status = parser->m_parsingStatus;
2286}
2287
2288enum XML_Error XMLCALL
2289XML_GetErrorCode(XML_Parser parser)
2290{
2291 if (parser == NULL)
2292 return XML_ERROR_INVALID_ARGUMENT;
2293 return errorCode;
2294}
2295
2296XML_Index XMLCALL
2297XML_GetCurrentByteIndex(XML_Parser parser)
2298{
2299 if (parser == NULL)
2300 return -1;
2301 if (eventPtr)
2302 return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr));
2303 return -1;
2304}
2305
2306int XMLCALL
2307XML_GetCurrentByteCount(XML_Parser parser)
2308{
2309 if (parser == NULL)
2310 return 0;
2311 if (eventEndPtr && eventPtr)
2312 return (int)(eventEndPtr - eventPtr);
2313 return 0;
2314}
2315
2316const char * XMLCALL
2317XML_GetInputContext(XML_Parser parser, int *offset, int *size)
2318{
2319#ifdef XML_CONTEXT_BYTES
2320 if (parser == NULL)
2321 return NULL;
2322 if (eventPtr && buffer) {
2323 if (offset != NULL)
2324 *offset = (int)(eventPtr - buffer);
2325 if (size != NULL)
2326 *size = (int)(bufferEnd - buffer);
2327 return buffer;
2328 }
2329#else
2330 (void)parser;
2331 (void)offset;
2332 (void)size;
2333#endif /* defined XML_CONTEXT_BYTES */
2334 return (char *) 0;
2335}
2336
2337XML_Size XMLCALL
2338XML_GetCurrentLineNumber(XML_Parser parser)
2339{
2340 if (parser == NULL)
2341 return 0;
2342 if (eventPtr && eventPtr >= positionPtr) {
2343 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
2344 positionPtr = eventPtr;
2345 }
2346 return position.lineNumber + 1;
2347}
2348
2349XML_Size XMLCALL
2350XML_GetCurrentColumnNumber(XML_Parser parser)
2351{
2352 if (parser == NULL)
2353 return 0;
2354 if (eventPtr && eventPtr >= positionPtr) {
2355 XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
2356 positionPtr = eventPtr;
2357 }
2358 return position.columnNumber;
2359}
2360
2361void XMLCALL
2362XML_FreeContentModel(XML_Parser parser, XML_Content *model)
2363{
2364 if (parser != NULL)
2365 FREE(model);
2366}
2367
2368void * XMLCALL
2369XML_MemMalloc(XML_Parser parser, size_t size)
2370{
2371 if (parser == NULL)
2372 return NULL;
2373 return MALLOC(size);
2374}
2375
2376void * XMLCALL
2377XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
2378{
2379 if (parser == NULL)
2380 return NULL;
2381 return REALLOC(ptr, size);
2382}
2383
2384void XMLCALL
2385XML_MemFree(XML_Parser parser, void *ptr)
2386{
2387 if (parser != NULL)
2388 FREE(ptr);
2389}
2390
2391void XMLCALL
2392XML_DefaultCurrent(XML_Parser parser)
2393{
2394 if (parser == NULL)
2395 return;
2396 if (defaultHandler) {
2397 if (openInternalEntities)
2398 reportDefault(parser,
2399 internalEncoding,
2400 openInternalEntities->internalEventPtr,
2401 openInternalEntities->internalEventEndPtr);
2402 else
2403 reportDefault(parser, encoding, eventPtr, eventEndPtr);
2404 }
2405}
2406
2407const XML_LChar * XMLCALL
2408XML_ErrorString(enum XML_Error code)
2409{
2410 static const XML_LChar* const message[] = {
2411 0,
2412 XML_L("out of memory"),
2413 XML_L("syntax error"),
2414 XML_L("no element found"),
2415 XML_L("not well-formed (invalid token)"),
2416 XML_L("unclosed token"),
2417 XML_L("partial character"),
2418 XML_L("mismatched tag"),
2419 XML_L("duplicate attribute"),
2420 XML_L("junk after document element"),
2421 XML_L("illegal parameter entity reference"),
2422 XML_L("undefined entity"),
2423 XML_L("recursive entity reference"),
2424 XML_L("asynchronous entity"),
2425 XML_L("reference to invalid character number"),
2426 XML_L("reference to binary entity"),
2427 XML_L("reference to external entity in attribute"),
2428 XML_L("XML or text declaration not at start of entity"),
2429 XML_L("unknown encoding"),
2430 XML_L("encoding specified in XML declaration is incorrect"),
2431 XML_L("unclosed CDATA section"),
2432 XML_L("error in processing external entity reference"),
2433 XML_L("document is not standalone"),
2434 XML_L("unexpected parser state - please send a bug report"),
2435 XML_L("entity declared in parameter entity"),
2436 XML_L("requested feature requires XML_DTD support in Expat"),
2437 XML_L("cannot change setting once parsing has begun"),
2438 XML_L("unbound prefix"),
2439 XML_L("must not undeclare prefix"),
2440 XML_L("incomplete markup in parameter entity"),
2441 XML_L("XML declaration not well-formed"),
2442 XML_L("text declaration not well-formed"),
2443 XML_L("illegal character(s) in public id"),
2444 XML_L("parser suspended"),
2445 XML_L("parser not suspended"),
2446 XML_L("parsing aborted"),
2447 XML_L("parsing finished"),
2448 XML_L("cannot suspend in external parameter entity"),
2449 XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
2450 XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
2451 XML_L("prefix must not be bound to one of the reserved namespace names")
2452 };
2453 if (code > 0 && code < sizeof(message)/sizeof(message[0]))
2454 return message[code];
2455 return NULL;
2456}
2457
2458const XML_LChar * XMLCALL
2459XML_ExpatVersion(void) {
2460
2461 /* V1 is used to string-ize the version number. However, it would
2462 string-ize the actual version macro *names* unless we get them
2463 substituted before being passed to V1. CPP is defined to expand
2464 a macro, then rescan for more expansions. Thus, we use V2 to expand
2465 the version macros, then CPP will expand the resulting V1() macro
2466 with the correct numerals. */
2467 /* ### I'm assuming cpp is portable in this respect... */
2468
2469#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
2470#define V2(a,b,c) XML_L("expat_")V1(a,b,c)
2471
2472 return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
2473
2474#undef V1
2475#undef V2
2476}
2477
2478XML_Expat_Version XMLCALL
2479XML_ExpatVersionInfo(void)
2480{
2481 XML_Expat_Version version;
2482
2483 version.major = XML_MAJOR_VERSION;
2484 version.minor = XML_MINOR_VERSION;
2485 version.micro = XML_MICRO_VERSION;
2486
2487 return version;
2488}
2489
2490const XML_Feature * XMLCALL
2491XML_GetFeatureList(void)
2492{
2493 static const XML_Feature features[] = {
2494 {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
2495 sizeof(XML_Char)},
2496 {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
2497 sizeof(XML_LChar)},
2498#ifdef XML_UNICODE
2499 {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
2500#endif
2501#ifdef XML_UNICODE_WCHAR_T
2502 {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
2503#endif
2504#ifdef XML_DTD
2505 {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
2506#endif
2507#ifdef XML_CONTEXT_BYTES
2508 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
2509 XML_CONTEXT_BYTES},
2510#endif
2511#ifdef XML_MIN_SIZE
2512 {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
2513#endif
2514#ifdef XML_NS
2515 {XML_FEATURE_NS, XML_L("XML_NS"), 0},
2516#endif
2517#ifdef XML_LARGE_SIZE
2518 {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
2519#endif
2520#ifdef XML_ATTR_INFO
2521 {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
2522#endif
2523 {XML_FEATURE_END, NULL, 0}
2524 };
2525
2526 return features;
2527}
2528
2529/* Initially tag->rawName always points into the parse buffer;
2530 for those TAG instances opened while the current parse buffer was
2531 processed, and not yet closed, we need to store tag->rawName in a more
2532 permanent location, since the parse buffer is about to be discarded.
2533*/
2534static XML_Bool
2535storeRawNames(XML_Parser parser)
2536{
2537 TAG *tag = tagStack;
2538 while (tag) {
2539 int bufSize;
2540 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
2541 char *rawNameBuf = tag->buf + nameLen;
2542 /* Stop if already stored. Since tagStack is a stack, we can stop
2543 at the first entry that has already been copied; everything
2544 below it in the stack is already been accounted for in a
2545 previous call to this function.
2546 */
2547 if (tag->rawName == rawNameBuf)
2548 break;
2549 /* For re-use purposes we need to ensure that the
2550 size of tag->buf is a multiple of sizeof(XML_Char).
2551 */
2552 bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
2553 if (bufSize > tag->bufEnd - tag->buf) {
2554 char *temp = (char *)REALLOC(tag->buf, bufSize);
2555 if (temp == NULL)
2556 return XML_FALSE;
2557 /* if tag->name.str points to tag->buf (only when namespace
2558 processing is off) then we have to update it
2559 */
2560 if (tag->name.str == (XML_Char *)tag->buf)
2561 tag->name.str = (XML_Char *)temp;
2562 /* if tag->name.localPart is set (when namespace processing is on)
2563 then update it as well, since it will always point into tag->buf
2564 */
2565 if (tag->name.localPart)
2566 tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
2567 (XML_Char *)tag->buf);
2568 tag->buf = temp;
2569 tag->bufEnd = temp + bufSize;
2570 rawNameBuf = temp + nameLen;
2571 }
2572 memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
2573 tag->rawName = rawNameBuf;
2574 tag = tag->parent;
2575 }
2576 return XML_TRUE;
2577}
2578
2579static enum XML_Error PTRCALL
2580contentProcessor(XML_Parser parser,
2581 const char *start,
2582 const char *end,
2583 const char **endPtr)
2584{
2585 enum XML_Error result = doContent(parser, 0, encoding, start, end,
2586 endPtr, (XML_Bool)!ps_finalBuffer);
2587 if (result == XML_ERROR_NONE) {
2588 if (!storeRawNames(parser))
2589 return XML_ERROR_NO_MEMORY;
2590 }
2591 return result;
2592}
2593
2594static enum XML_Error PTRCALL
2595externalEntityInitProcessor(XML_Parser parser,
2596 const char *start,
2597 const char *end,
2598 const char **endPtr)
2599{
2600 enum XML_Error result = initializeEncoding(parser);
2601 if (result != XML_ERROR_NONE)
2602 return result;
2603 processor = externalEntityInitProcessor2;
2604 return externalEntityInitProcessor2(parser, start, end, endPtr);
2605}
2606
2607static enum XML_Error PTRCALL
2608externalEntityInitProcessor2(XML_Parser parser,
2609 const char *start,
2610 const char *end,
2611 const char **endPtr)
2612{
2613 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2614 int tok = XmlContentTok(encoding, start, end, &next);
2615 switch (tok) {
2616 case XML_TOK_BOM:
2617 /* If we are at the end of the buffer, this would cause the next stage,
2618 i.e. externalEntityInitProcessor3, to pass control directly to
2619 doContent (by detecting XML_TOK_NONE) without processing any xml text
2620 declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
2621 */
2622 if (next == end && !ps_finalBuffer) {
2623 *endPtr = next;
2624 return XML_ERROR_NONE;
2625 }
2626 start = next;
2627 break;
2628 case XML_TOK_PARTIAL:
2629 if (!ps_finalBuffer) {
2630 *endPtr = start;
2631 return XML_ERROR_NONE;
2632 }
2633 eventPtr = start;
2634 return XML_ERROR_UNCLOSED_TOKEN;
2635 case XML_TOK_PARTIAL_CHAR:
2636 if (!ps_finalBuffer) {
2637 *endPtr = start;
2638 return XML_ERROR_NONE;
2639 }
2640 eventPtr = start;
2641 return XML_ERROR_PARTIAL_CHAR;
2642 }
2643 processor = externalEntityInitProcessor3;
2644 return externalEntityInitProcessor3(parser, start, end, endPtr);
2645}
2646
2647static enum XML_Error PTRCALL
2648externalEntityInitProcessor3(XML_Parser parser,
2649 const char *start,
2650 const char *end,
2651 const char **endPtr)
2652{
2653 int tok;
2654 const char *next = start; /* XmlContentTok doesn't always set the last arg */
2655 eventPtr = start;
2656 tok = XmlContentTok(encoding, start, end, &next);
2657 eventEndPtr = next;
2658
2659 switch (tok) {
2660 case XML_TOK_XML_DECL:
2661 {
2662 enum XML_Error result;
2663 result = processXmlDecl(parser, 1, start, next);
2664 if (result != XML_ERROR_NONE)
2665 return result;
2666 switch (ps_parsing) {
2667 case XML_SUSPENDED:
2668 *endPtr = next;
2669 return XML_ERROR_NONE;
2670 case XML_FINISHED:
2671 return XML_ERROR_ABORTED;
2672 default:
2673 start = next;
2674 }
2675 }
2676 break;
2677 case XML_TOK_PARTIAL:
2678 if (!ps_finalBuffer) {
2679 *endPtr = start;
2680 return XML_ERROR_NONE;
2681 }
2682 return XML_ERROR_UNCLOSED_TOKEN;
2683 case XML_TOK_PARTIAL_CHAR:
2684 if (!ps_finalBuffer) {
2685 *endPtr = start;
2686 return XML_ERROR_NONE;
2687 }
2688 return XML_ERROR_PARTIAL_CHAR;
2689 }
2690 processor = externalEntityContentProcessor;
2691 tagLevel = 1;
2692 return externalEntityContentProcessor(parser, start, end, endPtr);
2693}
2694
2695static enum XML_Error PTRCALL
2696externalEntityContentProcessor(XML_Parser parser,
2697 const char *start,
2698 const char *end,
2699 const char **endPtr)
2700{
2701 enum XML_Error result = doContent(parser, 1, encoding, start, end,
2702 endPtr, (XML_Bool)!ps_finalBuffer);
2703 if (result == XML_ERROR_NONE) {
2704 if (!storeRawNames(parser))
2705 return XML_ERROR_NO_MEMORY;
2706 }
2707 return result;
2708}
2709
2710static enum XML_Error
2711doContent(XML_Parser parser,
2712 int startTagLevel,
2713 const ENCODING *enc,
2714 const char *s,
2715 const char *end,
2716 const char **nextPtr,
2717 XML_Bool haveMore)
2718{
2719 /* save one level of indirection */
2720 DTD * const dtd = _dtd;
2721
2722 const char **eventPP;
2723 const char **eventEndPP;
2724 if (enc == encoding) {
2725 eventPP = &eventPtr;
2726 eventEndPP = &eventEndPtr;
2727 }
2728 else {
2729 eventPP = &(openInternalEntities->internalEventPtr);
2730 eventEndPP = &(openInternalEntities->internalEventEndPtr);
2731 }
2732 *eventPP = s;
2733
2734 for (;;) {
2735 const char *next = s; /* XmlContentTok doesn't always set the last arg */
2736 int tok = XmlContentTok(enc, s, end, &next);
2737 *eventEndPP = next;
2738 switch (tok) {
2739 case XML_TOK_TRAILING_CR:
2740 if (haveMore) {
2741 *nextPtr = s;
2742 return XML_ERROR_NONE;
2743 }
2744 *eventEndPP = end;
2745 if (characterDataHandler) {
2746 XML_Char c = 0xA;
2747 characterDataHandler(handlerArg, &c, 1);
2748 }
2749 else if (defaultHandler)
2750 reportDefault(parser, enc, s, end);
2751 /* We are at the end of the final buffer, should we check for
2752 XML_SUSPENDED, XML_FINISHED?
2753 */
2754 if (startTagLevel == 0)
2755 return XML_ERROR_NO_ELEMENTS;
2756 if (tagLevel != startTagLevel)
2757 return XML_ERROR_ASYNC_ENTITY;
2758 *nextPtr = end;
2759 return XML_ERROR_NONE;
2760 case XML_TOK_NONE:
2761 if (haveMore) {
2762 *nextPtr = s;
2763 return XML_ERROR_NONE;
2764 }
2765 if (startTagLevel > 0) {
2766 if (tagLevel != startTagLevel)
2767 return XML_ERROR_ASYNC_ENTITY;
2768 *nextPtr = s;
2769 return XML_ERROR_NONE;
2770 }
2771 return XML_ERROR_NO_ELEMENTS;
2772 case XML_TOK_INVALID:
2773 *eventPP = next;
2774 return XML_ERROR_INVALID_TOKEN;
2775 case XML_TOK_PARTIAL:
2776 if (haveMore) {
2777 *nextPtr = s;
2778 return XML_ERROR_NONE;
2779 }
2780 return XML_ERROR_UNCLOSED_TOKEN;
2781 case XML_TOK_PARTIAL_CHAR:
2782 if (haveMore) {
2783 *nextPtr = s;
2784 return XML_ERROR_NONE;
2785 }
2786 return XML_ERROR_PARTIAL_CHAR;
2787 case XML_TOK_ENTITY_REF:
2788 {
2789 const XML_Char *name;
2790 ENTITY *entity;
2791 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
2792 s + enc->minBytesPerChar,
2793 next - enc->minBytesPerChar);
2794 if (ch) {
2795 if (characterDataHandler)
2796 characterDataHandler(handlerArg, &ch, 1);
2797 else if (defaultHandler)
2798 reportDefault(parser, enc, s, next);
2799 break;
2800 }
2801 name = poolStoreString(&dtd->pool, enc,
2802 s + enc->minBytesPerChar,
2803 next - enc->minBytesPerChar);
2804 if (!name)
2805 return XML_ERROR_NO_MEMORY;
2806 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
2807 poolDiscard(&dtd->pool);
2808 /* First, determine if a check for an existing declaration is needed;
2809 if yes, check that the entity exists, and that it is internal,
2810 otherwise call the skipped entity or default handler.
2811 */
2812 if (!dtd->hasParamEntityRefs || dtd->standalone) {
2813 if (!entity)
2814 return XML_ERROR_UNDEFINED_ENTITY;
2815 else if (!entity->is_internal)
2816 return XML_ERROR_ENTITY_DECLARED_IN_PE;
2817 }
2818 else if (!entity) {
2819 if (skippedEntityHandler)
2820 skippedEntityHandler(handlerArg, name, 0);
2821 else if (defaultHandler)
2822 reportDefault(parser, enc, s, next);
2823 break;
2824 }
2825 if (entity->open)
2826 return XML_ERROR_RECURSIVE_ENTITY_REF;
2827 if (entity->notation)
2828 return XML_ERROR_BINARY_ENTITY_REF;
2829 if (entity->textPtr) {
2830 enum XML_Error result;
2831 if (!defaultExpandInternalEntities) {
2832 if (skippedEntityHandler)
2833 skippedEntityHandler(handlerArg, entity->name, 0);
2834 else if (defaultHandler)
2835 reportDefault(parser, enc, s, next);
2836 break;
2837 }
2838 result = processInternalEntity(parser, entity, XML_FALSE);
2839 if (result != XML_ERROR_NONE)
2840 return result;
2841 }
2842 else if (externalEntityRefHandler) {
2843 const XML_Char *context;
2844 entity->open = XML_TRUE;
2845 context = getContext(parser);
2846 entity->open = XML_FALSE;
2847 if (!context)
2848 return XML_ERROR_NO_MEMORY;
2849 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
2850 context,
2851 entity->base,
2852 entity->systemId,
2853 entity->publicId))
2854 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
2855 poolDiscard(&tempPool);
2856 }
2857 else if (defaultHandler)
2858 reportDefault(parser, enc, s, next);
2859 break;
2860 }
2861 case XML_TOK_START_TAG_NO_ATTS:
2862 /* fall through */
2863 case XML_TOK_START_TAG_WITH_ATTS:
2864 {
2865 TAG *tag;
2866 enum XML_Error result;
2867 XML_Char *toPtr;
2868 if (freeTagList) {
2869 tag = freeTagList;
2870 freeTagList = freeTagList->parent;
2871 }
2872 else {
2873 tag = (TAG *)MALLOC(sizeof(TAG));
2874 if (!tag)
2875 return XML_ERROR_NO_MEMORY;
2876 tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
2877 if (!tag->buf) {
2878 FREE(tag);
2879 return XML_ERROR_NO_MEMORY;
2880 }
2881 tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
2882 }
2883 tag->bindings = NULL;
2884 tag->parent = tagStack;
2885 tagStack = tag;
2886 tag->name.localPart = NULL;
2887 tag->name.prefix = NULL;
2888 tag->rawName = s + enc->minBytesPerChar;
2889 tag->rawNameLength = XmlNameLength(enc, tag->rawName);
2890 ++tagLevel;
2891 {
2892 const char *rawNameEnd = tag->rawName + tag->rawNameLength;
2893 const char *fromPtr = tag->rawName;
2894 toPtr = (XML_Char *)tag->buf;
2895 for (;;) {
2896 int bufSize;
2897 int convLen;
2898 const enum XML_Convert_Result convert_res = XmlConvert(enc,
2899 &fromPtr, rawNameEnd,
2900 (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
2901 convLen = (int)(toPtr - (XML_Char *)tag->buf);
2902 if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
2903 tag->name.strLen = convLen;
2904 break;
2905 }
2906 bufSize = (int)(tag->bufEnd - tag->buf) << 1;
2907 {
2908 char *temp = (char *)REALLOC(tag->buf, bufSize);
2909 if (temp == NULL)
2910 return XML_ERROR_NO_MEMORY;
2911 tag->buf = temp;
2912 tag->bufEnd = temp + bufSize;
2913 toPtr = (XML_Char *)temp + convLen;
2914 }
2915 }
2916 }
2917 tag->name.str = (XML_Char *)tag->buf;
2918 *toPtr = XML_T('\0');
2919 result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
2920 if (result)
2921 return result;
2922 if (startElementHandler)
2923 startElementHandler(handlerArg, tag->name.str,
2924 (const XML_Char **)atts);
2925 else if (defaultHandler)
2926 reportDefault(parser, enc, s, next);
2927 poolClear(&tempPool);
2928 break;
2929 }
2930 case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
2931 /* fall through */
2932 case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
2933 {
2934 const char *rawName = s + enc->minBytesPerChar;
2935 enum XML_Error result;
2936 BINDING *bindings = NULL;
2937 XML_Bool noElmHandlers = XML_TRUE;
2938 TAG_NAME name;
2939 name.str = poolStoreString(&tempPool, enc, rawName,
2940 rawName + XmlNameLength(enc, rawName));
2941 if (!name.str)
2942 return XML_ERROR_NO_MEMORY;
2943 poolFinish(&tempPool);
2944 result = storeAtts(parser, enc, s, &name, &bindings);
2945 if (result != XML_ERROR_NONE) {
2946 freeBindings(parser, bindings);
2947 return result;
2948 }
2949 poolFinish(&tempPool);
2950 if (startElementHandler) {
2951 startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
2952 noElmHandlers = XML_FALSE;
2953 }
2954 if (endElementHandler) {
2955 if (startElementHandler)
2956 *eventPP = *eventEndPP;
2957 endElementHandler(handlerArg, name.str);
2958 noElmHandlers = XML_FALSE;
2959 }
2960 if (noElmHandlers && defaultHandler)
2961 reportDefault(parser, enc, s, next);
2962 poolClear(&tempPool);
2963 freeBindings(parser, bindings);
2964 }
2965 if (tagLevel == 0)
2966 return epilogProcessor(parser, next, end, nextPtr);
2967 break;
2968 case XML_TOK_END_TAG:
2969 if (tagLevel == startTagLevel)
2970 return XML_ERROR_ASYNC_ENTITY;
2971 else {
2972 int len;
2973 const char *rawName;
2974 TAG *tag = tagStack;
2975 tagStack = tag->parent;
2976 tag->parent = freeTagList;
2977 freeTagList = tag;
2978 rawName = s + enc->minBytesPerChar*2;
2979 len = XmlNameLength(enc, rawName);
2980 if (len != tag->rawNameLength
2981 || memcmp(tag->rawName, rawName, len) != 0) {
2982 *eventPP = rawName;
2983 return XML_ERROR_TAG_MISMATCH;
2984 }
2985 --tagLevel;
2986 if (endElementHandler) {
2987 const XML_Char *localPart;
2988 const XML_Char *prefix;
2989 XML_Char *uri;
2990 localPart = tag->name.localPart;
2991 if (ns && localPart) {
2992 /* localPart and prefix may have been overwritten in
2993 tag->name.str, since this points to the binding->uri
2994 buffer which gets re-used; so we have to add them again
2995 */
2996 uri = (XML_Char *)tag->name.str + tag->name.uriLen;
2997 /* don't need to check for space - already done in storeAtts() */
2998 while (*localPart) *uri++ = *localPart++;
2999 prefix = (XML_Char *)tag->name.prefix;
3000 if (ns_triplets && prefix) {
3001 *uri++ = namespaceSeparator;
3002 while (*prefix) *uri++ = *prefix++;
3003 }
3004 *uri = XML_T('\0');
3005 }
3006 endElementHandler(handlerArg, tag->name.str);
3007 }
3008 else if (defaultHandler)
3009 reportDefault(parser, enc, s, next);
3010 while (tag->bindings) {
3011 BINDING *b = tag->bindings;
3012 if (endNamespaceDeclHandler)
3013 endNamespaceDeclHandler(handlerArg, b->prefix->name);
3014 tag->bindings = tag->bindings->nextTagBinding;
3015 b->nextTagBinding = freeBindingList;
3016 freeBindingList = b;
3017 b->prefix->binding = b->prevPrefixBinding;
3018 }
3019 if (tagLevel == 0)
3020 return epilogProcessor(parser, next, end, nextPtr);
3021 }
3022 break;
3023 case XML_TOK_CHAR_REF:
3024 {
3025 int n = XmlCharRefNumber(enc, s);
3026 if (n < 0)
3027 return XML_ERROR_BAD_CHAR_REF;
3028 if (characterDataHandler) {
3029 XML_Char buf[XML_ENCODE_MAX];
3030 characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
3031 }
3032 else if (defaultHandler)
3033 reportDefault(parser, enc, s, next);
3034 }
3035 break;
3036 case XML_TOK_XML_DECL:
3037 return XML_ERROR_MISPLACED_XML_PI;
3038 case XML_TOK_DATA_NEWLINE:
3039 if (characterDataHandler) {
3040 XML_Char c = 0xA;
3041 characterDataHandler(handlerArg, &c, 1);
3042 }
3043 else if (defaultHandler)
3044 reportDefault(parser, enc, s, next);
3045 break;
3046 case XML_TOK_CDATA_SECT_OPEN:
3047 {
3048 enum XML_Error result;
3049 if (startCdataSectionHandler)
3050 startCdataSectionHandler(handlerArg);
3051#if 0
3052 /* Suppose you doing a transformation on a document that involves
3053 changing only the character data. You set up a defaultHandler
3054 and a characterDataHandler. The defaultHandler simply copies
3055 characters through. The characterDataHandler does the
3056 transformation and writes the characters out escaping them as
3057 necessary. This case will fail to work if we leave out the
3058 following two lines (because & and < inside CDATA sections will
3059 be incorrectly escaped).
3060
3061 However, now we have a start/endCdataSectionHandler, so it seems
3062 easier to let the user deal with this.
3063 */
3064 else if (characterDataHandler)
3065 characterDataHandler(handlerArg, dataBuf, 0);
3066#endif
3067 else if (defaultHandler)
3068 reportDefault(parser, enc, s, next);
3069 result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
3070 if (result != XML_ERROR_NONE)
3071 return result;
3072 else if (!next) {
3073 processor = cdataSectionProcessor;
3074 return result;
3075 }
3076 }
3077 break;
3078 case XML_TOK_TRAILING_RSQB:
3079 if (haveMore) {
3080 *nextPtr = s;
3081 return XML_ERROR_NONE;
3082 }
3083 if (characterDataHandler) {
3084 if (MUST_CONVERT(enc, s)) {
3085 ICHAR *dataPtr = (ICHAR *)dataBuf;
3086 XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
3087 characterDataHandler(handlerArg, dataBuf,
3088 (int)(dataPtr - (ICHAR *)dataBuf));
3089 }
3090 else
3091 characterDataHandler(handlerArg,
3092 (XML_Char *)s,
3093 (int)((XML_Char *)end - (XML_Char *)s));
3094 }
3095 else if (defaultHandler)
3096 reportDefault(parser, enc, s, end);
3097 /* We are at the end of the final buffer, should we check for
3098 XML_SUSPENDED, XML_FINISHED?
3099 */
3100 if (startTagLevel == 0) {
3101 *eventPP = end;
3102 return XML_ERROR_NO_ELEMENTS;
3103 }
3104 if (tagLevel != startTagLevel) {
3105 *eventPP = end;
3106 return XML_ERROR_ASYNC_ENTITY;
3107 }
3108 *nextPtr = end;
3109 return XML_ERROR_NONE;
3110 case XML_TOK_DATA_CHARS:
3111 {
3112 XML_CharacterDataHandler charDataHandler = characterDataHandler;
3113 if (charDataHandler) {
3114 if (MUST_CONVERT(enc, s)) {
3115 for (;;) {
3116 ICHAR *dataPtr = (ICHAR *)dataBuf;
3117 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3118 *eventEndPP = s;
3119 charDataHandler(handlerArg, dataBuf,
3120 (int)(dataPtr - (ICHAR *)dataBuf));
3121 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3122 break;
3123 *eventPP = s;
3124 }
3125 }
3126 else
3127 charDataHandler(handlerArg,
3128 (XML_Char *)s,
3129 (int)((XML_Char *)next - (XML_Char *)s));
3130 }
3131 else if (defaultHandler)
3132 reportDefault(parser, enc, s, next);
3133 }
3134 break;
3135 case XML_TOK_PI:
3136 if (!reportProcessingInstruction(parser, enc, s, next))
3137 return XML_ERROR_NO_MEMORY;
3138 break;
3139 case XML_TOK_COMMENT:
3140 if (!reportComment(parser, enc, s, next))
3141 return XML_ERROR_NO_MEMORY;
3142 break;
3143 default:
3144 /* All of the tokens produced by XmlContentTok() have their own
3145 * explicit cases, so this default is not strictly necessary.
3146 * However it is a useful safety net, so we retain the code and
3147 * simply exclude it from the coverage tests.
3148 *
3149 * LCOV_EXCL_START
3150 */
3151 if (defaultHandler)
3152 reportDefault(parser, enc, s, next);
3153 break;
3154 /* LCOV_EXCL_STOP */
3155 }
3156 *eventPP = s = next;
3157 switch (ps_parsing) {
3158 case XML_SUSPENDED:
3159 *nextPtr = next;
3160 return XML_ERROR_NONE;
3161 case XML_FINISHED:
3162 return XML_ERROR_ABORTED;
3163 default: ;
3164 }
3165 }
3166 /* not reached */
3167}
3168
3169/* This function does not call free() on the allocated memory, merely
3170 * moving it to the parser's freeBindingList where it can be freed or
3171 * reused as appropriate.
3172 */
3173static void
3174freeBindings(XML_Parser parser, BINDING *bindings)
3175{
3176 while (bindings) {
3177 BINDING *b = bindings;
3178
3179 /* startNamespaceDeclHandler will have been called for this
3180 * binding in addBindings(), so call the end handler now.
3181 */
3182 if (endNamespaceDeclHandler)
3183 endNamespaceDeclHandler(handlerArg, b->prefix->name);
3184
3185 bindings = bindings->nextTagBinding;
3186 b->nextTagBinding = freeBindingList;
3187 freeBindingList = b;
3188 b->prefix->binding = b->prevPrefixBinding;
3189 }
3190}
3191
3192/* Precondition: all arguments must be non-NULL;
3193 Purpose:
3194 - normalize attributes
3195 - check attributes for well-formedness
3196 - generate namespace aware attribute names (URI, prefix)
3197 - build list of attributes for startElementHandler
3198 - default attributes
3199 - process namespace declarations (check and report them)
3200 - generate namespace aware element name (URI, prefix)
3201*/
3202static enum XML_Error
3203storeAtts(XML_Parser parser, const ENCODING *enc,
3204 const char *attStr, TAG_NAME *tagNamePtr,
3205 BINDING **bindingsPtr)
3206{
3207 DTD * const dtd = _dtd; /* save one level of indirection */
3208 ELEMENT_TYPE *elementType;
3209 int nDefaultAtts;
3210 const XML_Char **appAtts; /* the attribute list for the application */
3211 int attIndex = 0;
3212 int prefixLen;
3213 int i;
3214 int n;
3215 XML_Char *uri;
3216 int nPrefixes = 0;
3217 BINDING *binding;
3218 const XML_Char *localPart;
3219
3220 /* lookup the element type name */
3221 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
3222 if (!elementType) {
3223 const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
3224 if (!name)
3225 return XML_ERROR_NO_MEMORY;
3226 elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
3227 sizeof(ELEMENT_TYPE));
3228 if (!elementType)
3229 return XML_ERROR_NO_MEMORY;
3230 if (ns && !setElementTypePrefix(parser, elementType))
3231 return XML_ERROR_NO_MEMORY;
3232 }
3233 nDefaultAtts = elementType->nDefaultAtts;
3234
3235 /* get the attributes from the tokenizer */
3236 n = XmlGetAttributes(enc, attStr, attsSize, atts);
3237 if (n + nDefaultAtts > attsSize) {
3238 int oldAttsSize = attsSize;
3239 ATTRIBUTE *temp;
3240#ifdef XML_ATTR_INFO
3241 XML_AttrInfo *temp2;
3242#endif
3243 attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
3244 temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
3245 if (temp == NULL) {
3246 attsSize = oldAttsSize;
3247 return XML_ERROR_NO_MEMORY;
3248 }
3249 atts = temp;
3250#ifdef XML_ATTR_INFO
3251 temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));
3252 if (temp2 == NULL) {
3253 attsSize = oldAttsSize;
3254 return XML_ERROR_NO_MEMORY;
3255 }
3256 attInfo = temp2;
3257#endif
3258 if (n > oldAttsSize)
3259 XmlGetAttributes(enc, attStr, n, atts);
3260 }
3261
3262 appAtts = (const XML_Char **)atts;
3263 for (i = 0; i < n; i++) {
3264 ATTRIBUTE *currAtt = &atts[i];
3265#ifdef XML_ATTR_INFO
3266 XML_AttrInfo *currAttInfo = &attInfo[i];
3267#endif
3268 /* add the name and value to the attribute list */
3269 ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
3270 currAtt->name
3271 + XmlNameLength(enc, currAtt->name));
3272 if (!attId)
3273 return XML_ERROR_NO_MEMORY;
3274#ifdef XML_ATTR_INFO
3275 currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);
3276 currAttInfo->nameEnd = currAttInfo->nameStart +
3277 XmlNameLength(enc, currAtt->name);
3278 currAttInfo->valueStart = parseEndByteIndex -
3279 (parseEndPtr - currAtt->valuePtr);
3280 currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);
3281#endif
3282 /* Detect duplicate attributes by their QNames. This does not work when
3283 namespace processing is turned on and different prefixes for the same
3284 namespace are used. For this case we have a check further down.
3285 */
3286 if ((attId->name)[-1]) {
3287 if (enc == encoding)
3288 eventPtr = atts[i].name;
3289 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3290 }
3291 (attId->name)[-1] = 1;
3292 appAtts[attIndex++] = attId->name;
3293 if (!atts[i].normalized) {
3294 enum XML_Error result;
3295 XML_Bool isCdata = XML_TRUE;
3296
3297 /* figure out whether declared as other than CDATA */
3298 if (attId->maybeTokenized) {
3299 int j;
3300 for (j = 0; j < nDefaultAtts; j++) {
3301 if (attId == elementType->defaultAtts[j].id) {
3302 isCdata = elementType->defaultAtts[j].isCdata;
3303 break;
3304 }
3305 }
3306 }
3307
3308 /* normalize the attribute value */
3309 result = storeAttributeValue(parser, enc, isCdata,
3310 atts[i].valuePtr, atts[i].valueEnd,
3311 &tempPool);
3312 if (result)
3313 return result;
3314 appAtts[attIndex] = poolStart(&tempPool);
3315 poolFinish(&tempPool);
3316 }
3317 else {
3318 /* the value did not need normalizing */
3319 appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
3320 atts[i].valueEnd);
3321 if (appAtts[attIndex] == 0)
3322 return XML_ERROR_NO_MEMORY;
3323 poolFinish(&tempPool);
3324 }
3325 /* handle prefixed attribute names */
3326 if (attId->prefix) {
3327 if (attId->xmlns) {
3328 /* deal with namespace declarations here */
3329 enum XML_Error result = addBinding(parser, attId->prefix, attId,
3330 appAtts[attIndex], bindingsPtr);
3331 if (result)
3332 return result;
3333 --attIndex;
3334 }
3335 else {
3336 /* deal with other prefixed names later */
3337 attIndex++;
3338 nPrefixes++;
3339 (attId->name)[-1] = 2;
3340 }
3341 }
3342 else
3343 attIndex++;
3344 }
3345
3346 /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
3347 nSpecifiedAtts = attIndex;
3348 if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
3349 for (i = 0; i < attIndex; i += 2)
3350 if (appAtts[i] == elementType->idAtt->name) {
3351 idAttIndex = i;
3352 break;
3353 }
3354 }
3355 else
3356 idAttIndex = -1;
3357
3358 /* do attribute defaulting */
3359 for (i = 0; i < nDefaultAtts; i++) {
3360 const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
3361 if (!(da->id->name)[-1] && da->value) {
3362 if (da->id->prefix) {
3363 if (da->id->xmlns) {
3364 enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
3365 da->value, bindingsPtr);
3366 if (result)
3367 return result;
3368 }
3369 else {
3370 (da->id->name)[-1] = 2;
3371 nPrefixes++;
3372 appAtts[attIndex++] = da->id->name;
3373 appAtts[attIndex++] = da->value;
3374 }
3375 }
3376 else {
3377 (da->id->name)[-1] = 1;
3378 appAtts[attIndex++] = da->id->name;
3379 appAtts[attIndex++] = da->value;
3380 }
3381 }
3382 }
3383 appAtts[attIndex] = 0;
3384
3385 /* expand prefixed attribute names, check for duplicates,
3386 and clear flags that say whether attributes were specified */
3387 i = 0;
3388 if (nPrefixes) {
3389 int j; /* hash table index */
3390 unsigned long version = nsAttsVersion;
3391 int nsAttsSize = (int)1 << nsAttsPower;
3392 unsigned char oldNsAttsPower = nsAttsPower;
3393 /* size of hash table must be at least 2 * (# of prefixed attributes) */
3394 if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
3395 NS_ATT *temp;
3396 /* hash table size must also be a power of 2 and >= 8 */
3397 while (nPrefixes >> nsAttsPower++);
3398 if (nsAttsPower < 3)
3399 nsAttsPower = 3;
3400 nsAttsSize = (int)1 << nsAttsPower;
3401 temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
3402 if (!temp) {
3403 /* Restore actual size of memory in nsAtts */
3404 nsAttsPower = oldNsAttsPower;
3405 return XML_ERROR_NO_MEMORY;
3406 }
3407 nsAtts = temp;
3408 version = 0; /* force re-initialization of nsAtts hash table */
3409 }
3410 /* using a version flag saves us from initializing nsAtts every time */
3411 if (!version) { /* initialize version flags when version wraps around */
3412 version = INIT_ATTS_VERSION;
3413 for (j = nsAttsSize; j != 0; )
3414 nsAtts[--j].version = version;
3415 }
3416 nsAttsVersion = --version;
3417
3418 /* expand prefixed names and check for duplicates */
3419 for (; i < attIndex; i += 2) {
3420 const XML_Char *s = appAtts[i];
3421 if (s[-1] == 2) { /* prefixed */
3422 ATTRIBUTE_ID *id;
3423 const BINDING *b;
3424 unsigned long uriHash;
3425 struct siphash sip_state;
3426 struct sipkey sip_key;
3427
3428 copy_salt_to_sipkey(parser, &sip_key);
3429 sip24_init(&sip_state, &sip_key);
3430
3431 ((XML_Char *)s)[-1] = 0; /* clear flag */
3432 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
3433 if (!id || !id->prefix) {
3434 /* This code is walking through the appAtts array, dealing
3435 * with (in this case) a prefixed attribute name. To be in
3436 * the array, the attribute must have already been bound, so
3437 * has to have passed through the hash table lookup once
3438 * already. That implies that an entry for it already
3439 * exists, so the lookup above will return a pointer to
3440 * already allocated memory. There is no opportunaity for
3441 * the allocator to fail, so the condition above cannot be
3442 * fulfilled.
3443 *
3444 * Since it is difficult to be certain that the above
3445 * analysis is complete, we retain the test and merely
3446 * remove the code from coverage tests.
3447 */
3448 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
3449 }
3450 b = id->prefix->binding;
3451 if (!b)
3452 return XML_ERROR_UNBOUND_PREFIX;
3453
3454 for (j = 0; j < b->uriLen; j++) {
3455 const XML_Char c = b->uri[j];
3456 if (!poolAppendChar(&tempPool, c))
3457 return XML_ERROR_NO_MEMORY;
3458 }
3459
3460 sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
3461
3462 while (*s++ != XML_T(ASCII_COLON))
3463 ;
3464
3465 sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
3466
3467 do { /* copies null terminator */
3468 if (!poolAppendChar(&tempPool, *s))
3469 return XML_ERROR_NO_MEMORY;
3470 } while (*s++);
3471
3472 uriHash = (unsigned long)sip24_final(&sip_state);
3473
3474 { /* Check hash table for duplicate of expanded name (uriName).
3475 Derived from code in lookup(parser, HASH_TABLE *table, ...).
3476 */
3477 unsigned char step = 0;
3478 unsigned long mask = nsAttsSize - 1;
3479 j = uriHash & mask; /* index into hash table */
3480 while (nsAtts[j].version == version) {
3481 /* for speed we compare stored hash values first */
3482 if (uriHash == nsAtts[j].hash) {
3483 const XML_Char *s1 = poolStart(&tempPool);
3484 const XML_Char *s2 = nsAtts[j].uriName;
3485 /* s1 is null terminated, but not s2 */
3486 for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
3487 if (*s1 == 0)
3488 return XML_ERROR_DUPLICATE_ATTRIBUTE;
3489 }
3490 if (!step)
3491 step = PROBE_STEP(uriHash, mask, nsAttsPower);
3492 j < step ? (j += nsAttsSize - step) : (j -= step);
3493 }
3494 }
3495
3496 if (ns_triplets) { /* append namespace separator and prefix */
3497 tempPool.ptr[-1] = namespaceSeparator;
3498 s = b->prefix->name;
3499 do {
3500 if (!poolAppendChar(&tempPool, *s))
3501 return XML_ERROR_NO_MEMORY;
3502 } while (*s++);
3503 }
3504
3505 /* store expanded name in attribute list */
3506 s = poolStart(&tempPool);
3507 poolFinish(&tempPool);
3508 appAtts[i] = s;
3509
3510 /* fill empty slot with new version, uriName and hash value */
3511 nsAtts[j].version = version;
3512 nsAtts[j].hash = uriHash;
3513 nsAtts[j].uriName = s;
3514
3515 if (!--nPrefixes) {
3516 i += 2;
3517 break;
3518 }
3519 }
3520 else /* not prefixed */
3521 ((XML_Char *)s)[-1] = 0; /* clear flag */
3522 }
3523 }
3524 /* clear flags for the remaining attributes */
3525 for (; i < attIndex; i += 2)
3526 ((XML_Char *)(appAtts[i]))[-1] = 0;
3527 for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
3528 binding->attId->name[-1] = 0;
3529
3530 if (!ns)
3531 return XML_ERROR_NONE;
3532
3533 /* expand the element type name */
3534 if (elementType->prefix) {
3535 binding = elementType->prefix->binding;
3536 if (!binding)
3537 return XML_ERROR_UNBOUND_PREFIX;
3538 localPart = tagNamePtr->str;
3539 while (*localPart++ != XML_T(ASCII_COLON))
3540 ;
3541 }
3542 else if (dtd->defaultPrefix.binding) {
3543 binding = dtd->defaultPrefix.binding;
3544 localPart = tagNamePtr->str;
3545 }
3546 else
3547 return XML_ERROR_NONE;
3548 prefixLen = 0;
3549 if (ns_triplets && binding->prefix->name) {
3550 for (; binding->prefix->name[prefixLen++];)
3551 ; /* prefixLen includes null terminator */
3552 }
3553 tagNamePtr->localPart = localPart;
3554 tagNamePtr->uriLen = binding->uriLen;
3555 tagNamePtr->prefix = binding->prefix->name;
3556 tagNamePtr->prefixLen = prefixLen;
3557 for (i = 0; localPart[i++];)
3558 ; /* i includes null terminator */
3559 n = i + binding->uriLen + prefixLen;
3560 if (n > binding->uriAlloc) {
3561 TAG *p;
3562 uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
3563 if (!uri)
3564 return XML_ERROR_NO_MEMORY;
3565 binding->uriAlloc = n + EXPAND_SPARE;
3566 memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
3567 for (p = tagStack; p; p = p->parent)
3568 if (p->name.str == binding->uri)
3569 p->name.str = uri;
3570 FREE(binding->uri);
3571 binding->uri = uri;
3572 }
3573 /* if namespaceSeparator != '\0' then uri includes it already */
3574 uri = binding->uri + binding->uriLen;
3575 memcpy(uri, localPart, i * sizeof(XML_Char));
3576 /* we always have a namespace separator between localPart and prefix */
3577 if (prefixLen) {
3578 uri += i - 1;
3579 *uri = namespaceSeparator; /* replace null terminator */
3580 memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
3581 }
3582 tagNamePtr->str = binding->uri;
3583 return XML_ERROR_NONE;
3584}
3585
3586/* addBinding() overwrites the value of prefix->binding without checking.
3587 Therefore one must keep track of the old value outside of addBinding().
3588*/
3589static enum XML_Error
3590addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
3591 const XML_Char *uri, BINDING **bindingsPtr)
3592{
3593 static const XML_Char xmlNamespace[] = {
3594 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3595 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3596 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
3597 ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
3598 ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
3599 ASCII_e, '\0'
3600 };
3601 static const int xmlLen =
3602 (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
3603 static const XML_Char xmlnsNamespace[] = {
3604 ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
3605 ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
3606 ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
3607 ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
3608 ASCII_SLASH, '\0'
3609 };
3610 static const int xmlnsLen =
3611 (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
3612
3613 XML_Bool mustBeXML = XML_FALSE;
3614 XML_Bool isXML = XML_TRUE;
3615 XML_Bool isXMLNS = XML_TRUE;
3616
3617 BINDING *b;
3618 int len;
3619
3620 /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
3621 if (*uri == XML_T('\0') && prefix->name)
3622 return XML_ERROR_UNDECLARING_PREFIX;
3623
3624 if (prefix->name
3625 && prefix->name[0] == XML_T(ASCII_x)
3626 && prefix->name[1] == XML_T(ASCII_m)
3627 && prefix->name[2] == XML_T(ASCII_l)) {
3628
3629 /* Not allowed to bind xmlns */
3630 if (prefix->name[3] == XML_T(ASCII_n)
3631 && prefix->name[4] == XML_T(ASCII_s)
3632 && prefix->name[5] == XML_T('\0'))
3633 return XML_ERROR_RESERVED_PREFIX_XMLNS;
3634
3635 if (prefix->name[3] == XML_T('\0'))
3636 mustBeXML = XML_TRUE;
3637 }
3638
3639 for (len = 0; uri[len]; len++) {
3640 if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
3641 isXML = XML_FALSE;
3642
3643 if (!mustBeXML && isXMLNS
3644 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
3645 isXMLNS = XML_FALSE;
3646 }
3647 isXML = isXML && len == xmlLen;
3648 isXMLNS = isXMLNS && len == xmlnsLen;
3649
3650 if (mustBeXML != isXML)
3651 return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
3652 : XML_ERROR_RESERVED_NAMESPACE_URI;
3653
3654 if (isXMLNS)
3655 return XML_ERROR_RESERVED_NAMESPACE_URI;
3656
3657 if (namespaceSeparator)
3658 len++;
3659 if (freeBindingList) {
3660 b = freeBindingList;
3661 if (len > b->uriAlloc) {
3662 XML_Char *temp = (XML_Char *)REALLOC(b->uri,
3663 sizeof(XML_Char) * (len + EXPAND_SPARE));
3664 if (temp == NULL)
3665 return XML_ERROR_NO_MEMORY;
3666 b->uri = temp;
3667 b->uriAlloc = len + EXPAND_SPARE;
3668 }
3669 freeBindingList = b->nextTagBinding;
3670 }
3671 else {
3672 b = (BINDING *)MALLOC(sizeof(BINDING));
3673 if (!b)
3674 return XML_ERROR_NO_MEMORY;
3675 b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
3676 if (!b->uri) {
3677 FREE(b);
3678 return XML_ERROR_NO_MEMORY;
3679 }
3680 b->uriAlloc = len + EXPAND_SPARE;
3681 }
3682 b->uriLen = len;
3683 memcpy(b->uri, uri, len * sizeof(XML_Char));
3684 if (namespaceSeparator)
3685 b->uri[len - 1] = namespaceSeparator;
3686 b->prefix = prefix;
3687 b->attId = attId;
3688 b->prevPrefixBinding = prefix->binding;
3689 /* NULL binding when default namespace undeclared */
3690 if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
3691 prefix->binding = NULL;
3692 else
3693 prefix->binding = b;
3694 b->nextTagBinding = *bindingsPtr;
3695 *bindingsPtr = b;
3696 /* if attId == NULL then we are not starting a namespace scope */
3697 if (attId && startNamespaceDeclHandler)
3698 startNamespaceDeclHandler(handlerArg, prefix->name,
3699 prefix->binding ? uri : 0);
3700 return XML_ERROR_NONE;
3701}
3702
3703/* The idea here is to avoid using stack for each CDATA section when
3704 the whole file is parsed with one call.
3705*/
3706static enum XML_Error PTRCALL
3707cdataSectionProcessor(XML_Parser parser,
3708 const char *start,
3709 const char *end,
3710 const char **endPtr)
3711{
3712 enum XML_Error result = doCdataSection(parser, encoding, &start, end,
3713 endPtr, (XML_Bool)!ps_finalBuffer);
3714 if (result != XML_ERROR_NONE)
3715 return result;
3716 if (start) {
3717 if (parentParser) { /* we are parsing an external entity */
3718 processor = externalEntityContentProcessor;
3719 return externalEntityContentProcessor(parser, start, end, endPtr);
3720 }
3721 else {
3722 processor = contentProcessor;
3723 return contentProcessor(parser, start, end, endPtr);
3724 }
3725 }
3726 return result;
3727}
3728
3729/* startPtr gets set to non-null if the section is closed, and to null if
3730 the section is not yet closed.
3731*/
3732static enum XML_Error
3733doCdataSection(XML_Parser parser,
3734 const ENCODING *enc,
3735 const char **startPtr,
3736 const char *end,
3737 const char **nextPtr,
3738 XML_Bool haveMore)
3739{
3740 const char *s = *startPtr;
3741 const char **eventPP;
3742 const char **eventEndPP;
3743 if (enc == encoding) {
3744 eventPP = &eventPtr;
3745 *eventPP = s;
3746 eventEndPP = &eventEndPtr;
3747 }
3748 else {
3749 eventPP = &(openInternalEntities->internalEventPtr);
3750 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3751 }
3752 *eventPP = s;
3753 *startPtr = NULL;
3754
3755 for (;;) {
3756 const char *next;
3757 int tok = XmlCdataSectionTok(enc, s, end, &next);
3758 *eventEndPP = next;
3759 switch (tok) {
3760 case XML_TOK_CDATA_SECT_CLOSE:
3761 if (endCdataSectionHandler)
3762 endCdataSectionHandler(handlerArg);
3763#if 0
3764 /* see comment under XML_TOK_CDATA_SECT_OPEN */
3765 else if (characterDataHandler)
3766 characterDataHandler(handlerArg, dataBuf, 0);
3767#endif
3768 else if (defaultHandler)
3769 reportDefault(parser, enc, s, next);
3770 *startPtr = next;
3771 *nextPtr = next;
3772 if (ps_parsing == XML_FINISHED)
3773 return XML_ERROR_ABORTED;
3774 else
3775 return XML_ERROR_NONE;
3776 case XML_TOK_DATA_NEWLINE:
3777 if (characterDataHandler) {
3778 XML_Char c = 0xA;
3779 characterDataHandler(handlerArg, &c, 1);
3780 }
3781 else if (defaultHandler)
3782 reportDefault(parser, enc, s, next);
3783 break;
3784 case XML_TOK_DATA_CHARS:
3785 {
3786 XML_CharacterDataHandler charDataHandler = characterDataHandler;
3787 if (charDataHandler) {
3788 if (MUST_CONVERT(enc, s)) {
3789 for (;;) {
3790 ICHAR *dataPtr = (ICHAR *)dataBuf;
3791 const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
3792 *eventEndPP = next;
3793 charDataHandler(handlerArg, dataBuf,
3794 (int)(dataPtr - (ICHAR *)dataBuf));
3795 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
3796 break;
3797 *eventPP = s;
3798 }
3799 }
3800 else
3801 charDataHandler(handlerArg,
3802 (XML_Char *)s,
3803 (int)((XML_Char *)next - (XML_Char *)s));
3804 }
3805 else if (defaultHandler)
3806 reportDefault(parser, enc, s, next);
3807 }
3808 break;
3809 case XML_TOK_INVALID:
3810 *eventPP = next;
3811 return XML_ERROR_INVALID_TOKEN;
3812 case XML_TOK_PARTIAL_CHAR:
3813 if (haveMore) {
3814 *nextPtr = s;
3815 return XML_ERROR_NONE;
3816 }
3817 return XML_ERROR_PARTIAL_CHAR;
3818 case XML_TOK_PARTIAL:
3819 case XML_TOK_NONE:
3820 if (haveMore) {
3821 *nextPtr = s;
3822 return XML_ERROR_NONE;
3823 }
3824 return XML_ERROR_UNCLOSED_CDATA_SECTION;
3825 default:
3826 /* Every token returned by XmlCdataSectionTok() has its own
3827 * explicit case, so this default case will never be executed.
3828 * We retain it as a safety net and exclude it from the coverage
3829 * statistics.
3830 *
3831 * LCOV_EXCL_START
3832 */
3833 *eventPP = next;
3834 return XML_ERROR_UNEXPECTED_STATE;
3835 /* LCOV_EXCL_STOP */
3836 }
3837
3838 *eventPP = s = next;
3839 switch (ps_parsing) {
3840 case XML_SUSPENDED:
3841 *nextPtr = next;
3842 return XML_ERROR_NONE;
3843 case XML_FINISHED:
3844 return XML_ERROR_ABORTED;
3845 default: ;
3846 }
3847 }
3848 /* not reached */
3849}
3850
3851#ifdef XML_DTD
3852
3853/* The idea here is to avoid using stack for each IGNORE section when
3854 the whole file is parsed with one call.
3855*/
3856static enum XML_Error PTRCALL
3857ignoreSectionProcessor(XML_Parser parser,
3858 const char *start,
3859 const char *end,
3860 const char **endPtr)
3861{
3862 enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
3863 endPtr, (XML_Bool)!ps_finalBuffer);
3864 if (result != XML_ERROR_NONE)
3865 return result;
3866 if (start) {
3867 processor = prologProcessor;
3868 return prologProcessor(parser, start, end, endPtr);
3869 }
3870 return result;
3871}
3872
3873/* startPtr gets set to non-null is the section is closed, and to null
3874 if the section is not yet closed.
3875*/
3876static enum XML_Error
3877doIgnoreSection(XML_Parser parser,
3878 const ENCODING *enc,
3879 const char **startPtr,
3880 const char *end,
3881 const char **nextPtr,
3882 XML_Bool haveMore)
3883{
3884 const char *next;
3885 int tok;
3886 const char *s = *startPtr;
3887 const char **eventPP;
3888 const char **eventEndPP;
3889 if (enc == encoding) {
3890 eventPP = &eventPtr;
3891 *eventPP = s;
3892 eventEndPP = &eventEndPtr;
3893 }
3894 else {
3895 /* It's not entirely clear, but it seems the following two lines
3896 * of code cannot be executed. The only occasions on which 'enc'
3897 * is not 'parser->m_encoding' are when this function is called
3898 * from the internal entity processing, and IGNORE sections are an
3899 * error in internal entities.
3900 *
3901 * Since it really isn't clear that this is true, we keep the code
3902 * and just remove it from our coverage tests.
3903 *
3904 * LCOV_EXCL_START
3905 */
3906 eventPP = &(openInternalEntities->internalEventPtr);
3907 eventEndPP = &(openInternalEntities->internalEventEndPtr);
3908 /* LCOV_EXCL_STOP */
3909 }
3910 *eventPP = s;
3911 *startPtr = NULL;
3912 tok = XmlIgnoreSectionTok(enc, s, end, &next);
3913 *eventEndPP = next;
3914 switch (tok) {
3915 case XML_TOK_IGNORE_SECT:
3916 if (defaultHandler)
3917 reportDefault(parser, enc, s, next);
3918 *startPtr = next;
3919 *nextPtr = next;
3920 if (ps_parsing == XML_FINISHED)
3921 return XML_ERROR_ABORTED;
3922 else
3923 return XML_ERROR_NONE;
3924 case XML_TOK_INVALID:
3925 *eventPP = next;
3926 return XML_ERROR_INVALID_TOKEN;
3927 case XML_TOK_PARTIAL_CHAR:
3928 if (haveMore) {
3929 *nextPtr = s;
3930 return XML_ERROR_NONE;
3931 }
3932 return XML_ERROR_PARTIAL_CHAR;
3933 case XML_TOK_PARTIAL:
3934 case XML_TOK_NONE:
3935 if (haveMore) {
3936 *nextPtr = s;
3937 return XML_ERROR_NONE;
3938 }
3939 return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
3940 default:
3941 /* All of the tokens that XmlIgnoreSectionTok() returns have
3942 * explicit cases to handle them, so this default case is never
3943 * executed. We keep it as a safety net anyway, and remove it
3944 * from our test coverage statistics.
3945 *
3946 * LCOV_EXCL_START
3947 */
3948 *eventPP = next;
3949 return XML_ERROR_UNEXPECTED_STATE;
3950 /* LCOV_EXCL_STOP */
3951 }
3952 /* not reached */
3953}
3954
3955#endif /* XML_DTD */
3956
3957static enum XML_Error
3958initializeEncoding(XML_Parser parser)
3959{
3960 const char *s;
3961#ifdef XML_UNICODE
3962 char encodingBuf[128];
3963 /* See comments abount `protoclEncodingName` in parserInit() */
3964 if (!protocolEncodingName)
3965 s = NULL;
3966 else {
3967 int i;
3968 for (i = 0; protocolEncodingName[i]; i++) {
3969 if (i == sizeof(encodingBuf) - 1
3970 || (protocolEncodingName[i] & ~0x7f) != 0) {
3971 encodingBuf[0] = '\0';
3972 break;
3973 }
3974 encodingBuf[i] = (char)protocolEncodingName[i];
3975 }
3976 encodingBuf[i] = '\0';
3977 s = encodingBuf;
3978 }
3979#else
3980 s = protocolEncodingName;
3981#endif
3982 if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
3983 return XML_ERROR_NONE;
3984 return handleUnknownEncoding(parser, protocolEncodingName);
3985}
3986
3987static enum XML_Error
3988processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
3989 const char *s, const char *next)
3990{
3991 const char *encodingName = NULL;
3992 const XML_Char *storedEncName = NULL;
3993 const ENCODING *newEncoding = NULL;
3994 const char *version = NULL;
3995 const char *versionend;
3996 const XML_Char *storedversion = NULL;
3997 int standalone = -1;
3998 if (!(ns
3999 ? XmlParseXmlDeclNS
4000 : XmlParseXmlDecl)(isGeneralTextEntity,
4001 encoding,
4002 s,
4003 next,
4004 &eventPtr,
4005 &version,
4006 &versionend,
4007 &encodingName,
4008 &newEncoding,
4009 &standalone)) {
4010 if (isGeneralTextEntity)
4011 return XML_ERROR_TEXT_DECL;
4012 else
4013 return XML_ERROR_XML_DECL;
4014 }
4015 if (!isGeneralTextEntity && standalone == 1) {
4016 _dtd->standalone = XML_TRUE;
4017#ifdef XML_DTD
4018 if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
4019 paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
4020#endif /* XML_DTD */
4021 }
4022 if (xmlDeclHandler) {
4023 if (encodingName != NULL) {
4024 storedEncName = poolStoreString(&temp2Pool,
4025 encoding,
4026 encodingName,
4027 encodingName
4028 + XmlNameLength(encoding, encodingName));
4029 if (!storedEncName)
4030 return XML_ERROR_NO_MEMORY;
4031 poolFinish(&temp2Pool);
4032 }
4033 if (version) {
4034 storedversion = poolStoreString(&temp2Pool,
4035 encoding,
4036 version,
4037 versionend - encoding->minBytesPerChar);
4038 if (!storedversion)
4039 return XML_ERROR_NO_MEMORY;
4040 }
4041 xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
4042 }
4043 else if (defaultHandler)
4044 reportDefault(parser, encoding, s, next);
4045 if (protocolEncodingName == NULL) {
4046 if (newEncoding) {
4047 /* Check that the specified encoding does not conflict with what
4048 * the parser has already deduced. Do we have the same number
4049 * of bytes in the smallest representation of a character? If
4050 * this is UTF-16, is it the same endianness?
4051 */
4052 if (newEncoding->minBytesPerChar != encoding->minBytesPerChar
4053 || (newEncoding->minBytesPerChar == 2 &&
4054 newEncoding != encoding)) {
4055 eventPtr = encodingName;
4056 return XML_ERROR_INCORRECT_ENCODING;
4057 }
4058 encoding = newEncoding;
4059 }
4060 else if (encodingName) {
4061 enum XML_Error result;
4062 if (!storedEncName) {
4063 storedEncName = poolStoreString(
4064 &temp2Pool, encoding, encodingName,
4065 encodingName + XmlNameLength(encoding, encodingName));
4066 if (!storedEncName)
4067 return XML_ERROR_NO_MEMORY;
4068 }
4069 result = handleUnknownEncoding(parser, storedEncName);
4070 poolClear(&temp2Pool);
4071 if (result == XML_ERROR_UNKNOWN_ENCODING)
4072 eventPtr = encodingName;
4073 return result;
4074 }
4075 }
4076
4077 if (storedEncName || storedversion)
4078 poolClear(&temp2Pool);
4079
4080 return XML_ERROR_NONE;
4081}
4082
4083static enum XML_Error
4084handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
4085{
4086 if (unknownEncodingHandler) {
4087 XML_Encoding info;
4088 int i;
4089 for (i = 0; i < 256; i++)
4090 info.map[i] = -1;
4091 info.convert = NULL;
4092 info.data = NULL;
4093 info.release = NULL;
4094 if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
4095 &info)) {
4096 ENCODING *enc;
4097 unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
4098 if (!unknownEncodingMem) {
4099 if (info.release)
4100 info.release(info.data);
4101 return XML_ERROR_NO_MEMORY;
4102 }
4103 enc = (ns
4104 ? XmlInitUnknownEncodingNS
4105 : XmlInitUnknownEncoding)(unknownEncodingMem,
4106 info.map,
4107 info.convert,
4108 info.data);
4109 if (enc) {
4110 unknownEncodingData = info.data;
4111 unknownEncodingRelease = info.release;
4112 encoding = enc;
4113 return XML_ERROR_NONE;
4114 }
4115 }
4116 if (info.release != NULL)
4117 info.release(info.data);
4118 }
4119 return XML_ERROR_UNKNOWN_ENCODING;
4120}
4121
4122static enum XML_Error PTRCALL
4123prologInitProcessor(XML_Parser parser,
4124 const char *s,
4125 const char *end,
4126 const char **nextPtr)
4127{
4128 enum XML_Error result = initializeEncoding(parser);
4129 if (result != XML_ERROR_NONE)
4130 return result;
4131 processor = prologProcessor;
4132 return prologProcessor(parser, s, end, nextPtr);
4133}
4134
4135#ifdef XML_DTD
4136
4137static enum XML_Error PTRCALL
4138externalParEntInitProcessor(XML_Parser parser,
4139 const char *s,
4140 const char *end,
4141 const char **nextPtr)
4142{
4143 enum XML_Error result = initializeEncoding(parser);
4144 if (result != XML_ERROR_NONE)
4145 return result;
4146
4147 /* we know now that XML_Parse(Buffer) has been called,
4148 so we consider the external parameter entity read */
4149 _dtd->paramEntityRead = XML_TRUE;
4150
4151 if (prologState.inEntityValue) {
4152 processor = entityValueInitProcessor;
4153 return entityValueInitProcessor(parser, s, end, nextPtr);
4154 }
4155 else {
4156 processor = externalParEntProcessor;
4157 return externalParEntProcessor(parser, s, end, nextPtr);
4158 }
4159}
4160
4161static enum XML_Error PTRCALL
4162entityValueInitProcessor(XML_Parser parser,
4163 const char *s,
4164 const char *end,
4165 const char **nextPtr)
4166{
4167 int tok;
4168 const char *start = s;
4169 const char *next = start;
4170 eventPtr = start;
4171
4172 for (;;) {
4173 tok = XmlPrologTok(encoding, start, end, &next);
4174 eventEndPtr = next;
4175 if (tok <= 0) {
4176 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
4177 *nextPtr = s;
4178 return XML_ERROR_NONE;
4179 }
4180 switch (tok) {
4181 case XML_TOK_INVALID:
4182 return XML_ERROR_INVALID_TOKEN;
4183 case XML_TOK_PARTIAL:
4184 return XML_ERROR_UNCLOSED_TOKEN;
4185 case XML_TOK_PARTIAL_CHAR:
4186 return XML_ERROR_PARTIAL_CHAR;
4187 case XML_TOK_NONE: /* start == end */
4188 default:
4189 break;
4190 }
4191 /* found end of entity value - can store it now */
4192 return storeEntityValue(parser, encoding, s, end);
4193 }
4194 else if (tok == XML_TOK_XML_DECL) {
4195 enum XML_Error result;
4196 result = processXmlDecl(parser, 0, start, next);
4197 if (result != XML_ERROR_NONE)
4198 return result;
4199 /* At this point, ps_parsing cannot be XML_SUSPENDED. For that
4200 * to happen, a parameter entity parsing handler must have
4201 * attempted to suspend the parser, which fails and raises an
4202 * error. The parser can be aborted, but can't be suspended.
4203 */
4204 if (ps_parsing == XML_FINISHED)
4205 return XML_ERROR_ABORTED;
4206 *nextPtr = next;
4207 /* stop scanning for text declaration - we found one */
4208 processor = entityValueProcessor;
4209 return entityValueProcessor(parser, next, end, nextPtr);
4210 }
4211 /* If we are at the end of the buffer, this would cause XmlPrologTok to
4212 return XML_TOK_NONE on the next call, which would then cause the
4213 function to exit with *nextPtr set to s - that is what we want for other
4214 tokens, but not for the BOM - we would rather like to skip it;
4215 then, when this routine is entered the next time, XmlPrologTok will
4216 return XML_TOK_INVALID, since the BOM is still in the buffer
4217 */
4218 else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
4219 *nextPtr = next;
4220 return XML_ERROR_NONE;
4221 }
4222 /* If we get this token, we have the start of what might be a
4223 normal tag, but not a declaration (i.e. it doesn't begin with
4224 "<!"). In a DTD context, that isn't legal.
4225 */
4226 else if (tok == XML_TOK_INSTANCE_START) {
4227 *nextPtr = next;
4228 return XML_ERROR_SYNTAX;
4229 }
4230 start = next;
4231 eventPtr = start;
4232 }
4233}
4234
4235static enum XML_Error PTRCALL
4236externalParEntProcessor(XML_Parser parser,
4237 const char *s,
4238 const char *end,
4239 const char **nextPtr)
4240{
4241 const char *next = s;
4242 int tok;
4243
4244 tok = XmlPrologTok(encoding, s, end, &next);
4245 if (tok <= 0) {
4246 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
4247 *nextPtr = s;
4248 return XML_ERROR_NONE;
4249 }
4250 switch (tok) {
4251 case XML_TOK_INVALID:
4252 return XML_ERROR_INVALID_TOKEN;
4253 case XML_TOK_PARTIAL:
4254 return XML_ERROR_UNCLOSED_TOKEN;
4255 case XML_TOK_PARTIAL_CHAR:
4256 return XML_ERROR_PARTIAL_CHAR;
4257 case XML_TOK_NONE: /* start == end */
4258 default:
4259 break;
4260 }
4261 }
4262 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
4263 However, when parsing an external subset, doProlog will not accept a BOM
4264 as valid, and report a syntax error, so we have to skip the BOM
4265 */
4266 else if (tok == XML_TOK_BOM) {
4267 s = next;
4268 tok = XmlPrologTok(encoding, s, end, &next);
4269 }
4270
4271 processor = prologProcessor;
4272 return doProlog(parser, encoding, s, end, tok, next,
4273 nextPtr, (XML_Bool)!ps_finalBuffer);
4274}
4275
4276static enum XML_Error PTRCALL
4277entityValueProcessor(XML_Parser parser,
4278 const char *s,
4279 const char *end,
4280 const char **nextPtr)
4281{
4282 const char *start = s;
4283 const char *next = s;
4284 const ENCODING *enc = encoding;
4285 int tok;
4286
4287 for (;;) {
4288 tok = XmlPrologTok(enc, start, end, &next);
4289 if (tok <= 0) {
4290 if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
4291 *nextPtr = s;
4292 return XML_ERROR_NONE;
4293 }
4294 switch (tok) {
4295 case XML_TOK_INVALID:
4296 return XML_ERROR_INVALID_TOKEN;
4297 case XML_TOK_PARTIAL:
4298 return XML_ERROR_UNCLOSED_TOKEN;
4299 case XML_TOK_PARTIAL_CHAR:
4300 return XML_ERROR_PARTIAL_CHAR;
4301 case XML_TOK_NONE: /* start == end */
4302 default:
4303 break;
4304 }
4305 /* found end of entity value - can store it now */
4306 return storeEntityValue(parser, enc, s, end);
4307 }
4308 start = next;
4309 }
4310}
4311
4312#endif /* XML_DTD */
4313
4314static enum XML_Error PTRCALL
4315prologProcessor(XML_Parser parser,
4316 const char *s,
4317 const char *end,
4318 const char **nextPtr)
4319{
4320 const char *next = s;
4321 int tok = XmlPrologTok(encoding, s, end, &next);
4322 return doProlog(parser, encoding, s, end, tok, next,
4323 nextPtr, (XML_Bool)!ps_finalBuffer);
4324}
4325
4326static enum XML_Error
4327doProlog(XML_Parser parser,
4328 const ENCODING *enc,
4329 const char *s,
4330 const char *end,
4331 int tok,
4332 const char *next,
4333 const char **nextPtr,
4334 XML_Bool haveMore)
4335{
4336#ifdef XML_DTD
4337 static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
4338#endif /* XML_DTD */
4339 static const XML_Char atypeCDATA[] =
4340 { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
4341 static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
4342 static const XML_Char atypeIDREF[] =
4343 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
4344 static const XML_Char atypeIDREFS[] =
4345 { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
4346 static const XML_Char atypeENTITY[] =
4347 { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
4348 static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
4349 ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
4350 static const XML_Char atypeNMTOKEN[] = {
4351 ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
4352 static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
4353 ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
4354 static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
4355 ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
4356 static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
4357 static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
4358
4359 /* save one level of indirection */
4360 DTD * const dtd = _dtd;
4361
4362 const char **eventPP;
4363 const char **eventEndPP;
4364 enum XML_Content_Quant quant;
4365
4366 if (enc == encoding) {
4367 eventPP = &eventPtr;
4368 eventEndPP = &eventEndPtr;
4369 }
4370 else {
4371 eventPP = &(openInternalEntities->internalEventPtr);
4372 eventEndPP = &(openInternalEntities->internalEventEndPtr);
4373 }
4374
4375 for (;;) {
4376 int role;
4377 XML_Bool handleDefault = XML_TRUE;
4378 *eventPP = s;
4379 *eventEndPP = next;
4380 if (tok <= 0) {
4381 if (haveMore && tok != XML_TOK_INVALID) {
4382 *nextPtr = s;
4383 return XML_ERROR_NONE;
4384 }
4385 switch (tok) {
4386 case XML_TOK_INVALID:
4387 *eventPP = next;
4388 return XML_ERROR_INVALID_TOKEN;
4389 case XML_TOK_PARTIAL:
4390 return XML_ERROR_UNCLOSED_TOKEN;
4391 case XML_TOK_PARTIAL_CHAR:
4392 return XML_ERROR_PARTIAL_CHAR;
4393 case -XML_TOK_PROLOG_S:
4394 tok = -tok;
4395 break;
4396 case XML_TOK_NONE:
4397#ifdef XML_DTD
4398 /* for internal PE NOT referenced between declarations */
4399 if (enc != encoding && !openInternalEntities->betweenDecl) {
4400 *nextPtr = s;
4401 return XML_ERROR_NONE;
4402 }
4403 /* WFC: PE Between Declarations - must check that PE contains
4404 complete markup, not only for external PEs, but also for
4405 internal PEs if the reference occurs between declarations.
4406 */
4407 if (isParamEntity || enc != encoding) {
4408 if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
4409 == XML_ROLE_ERROR)
4410 return XML_ERROR_INCOMPLETE_PE;
4411 *nextPtr = s;
4412 return XML_ERROR_NONE;
4413 }
4414#endif /* XML_DTD */
4415 return XML_ERROR_NO_ELEMENTS;
4416 default:
4417 tok = -tok;
4418 next = end;
4419 break;
4420 }
4421 }
4422 role = XmlTokenRole(&prologState, tok, s, next, enc);
4423 switch (role) {
4424 case XML_ROLE_XML_DECL:
4425 {
4426 enum XML_Error result = processXmlDecl(parser, 0, s, next);
4427 if (result != XML_ERROR_NONE)
4428 return result;
4429 enc = encoding;
4430 handleDefault = XML_FALSE;
4431 }
4432 break;
4433 case XML_ROLE_DOCTYPE_NAME:
4434 if (startDoctypeDeclHandler) {
4435 doctypeName = poolStoreString(&tempPool, enc, s, next);
4436 if (!doctypeName)
4437 return XML_ERROR_NO_MEMORY;
4438 poolFinish(&tempPool);
4439 doctypePubid = NULL;
4440 handleDefault = XML_FALSE;
4441 }
4442 doctypeSysid = NULL; /* always initialize to NULL */
4443 break;
4444 case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
4445 if (startDoctypeDeclHandler) {
4446 startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
4447 doctypePubid, 1);
4448 doctypeName = NULL;
4449 poolClear(&tempPool);
4450 handleDefault = XML_FALSE;
4451 }
4452 break;
4453#ifdef XML_DTD
4454 case XML_ROLE_TEXT_DECL:
4455 {
4456 enum XML_Error result = processXmlDecl(parser, 1, s, next);
4457 if (result != XML_ERROR_NONE)
4458 return result;
4459 enc = encoding;
4460 handleDefault = XML_FALSE;
4461 }
4462 break;
4463#endif /* XML_DTD */
4464 case XML_ROLE_DOCTYPE_PUBLIC_ID:
4465#ifdef XML_DTD
4466 useForeignDTD = XML_FALSE;
4467 declEntity = (ENTITY *)lookup(parser,
4468 &dtd->paramEntities,
4469 externalSubsetName,
4470 sizeof(ENTITY));
4471 if (!declEntity)
4472 return XML_ERROR_NO_MEMORY;
4473#endif /* XML_DTD */
4474 dtd->hasParamEntityRefs = XML_TRUE;
4475 if (startDoctypeDeclHandler) {
4476 XML_Char *pubId;
4477 if (!XmlIsPublicId(enc, s, next, eventPP))
4478 return XML_ERROR_PUBLICID;
4479 pubId = poolStoreString(&tempPool, enc,
4480 s + enc->minBytesPerChar,
4481 next - enc->minBytesPerChar);
4482 if (!pubId)
4483 return XML_ERROR_NO_MEMORY;
4484 normalizePublicId(pubId);
4485 poolFinish(&tempPool);
4486 doctypePubid = pubId;
4487 handleDefault = XML_FALSE;
4488 goto alreadyChecked;
4489 }
4490 /* fall through */
4491 case XML_ROLE_ENTITY_PUBLIC_ID:
4492 if (!XmlIsPublicId(enc, s, next, eventPP))
4493 return XML_ERROR_PUBLICID;
4494 alreadyChecked:
4495 if (dtd->keepProcessing && declEntity) {
4496 XML_Char *tem = poolStoreString(&dtd->pool,
4497 enc,
4498 s + enc->minBytesPerChar,
4499 next - enc->minBytesPerChar);
4500 if (!tem)
4501 return XML_ERROR_NO_MEMORY;
4502 normalizePublicId(tem);
4503 declEntity->publicId = tem;
4504 poolFinish(&dtd->pool);
4505 if (entityDeclHandler)
4506 handleDefault = XML_FALSE;
4507 }
4508 break;
4509 case XML_ROLE_DOCTYPE_CLOSE:
4510 if (doctypeName) {
4511 startDoctypeDeclHandler(handlerArg, doctypeName,
4512 doctypeSysid, doctypePubid, 0);
4513 poolClear(&tempPool);
4514 handleDefault = XML_FALSE;
4515 }
4516 /* doctypeSysid will be non-NULL in the case of a previous
4517 XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
4518 was not set, indicating an external subset
4519 */
4520#ifdef XML_DTD
4521 if (doctypeSysid || useForeignDTD) {
4522 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4523 dtd->hasParamEntityRefs = XML_TRUE;
4524 if (paramEntityParsing && externalEntityRefHandler) {
4525 ENTITY *entity = (ENTITY *)lookup(parser,
4526 &dtd->paramEntities,
4527 externalSubsetName,
4528 sizeof(ENTITY));
4529 if (!entity) {
4530 /* The external subset name "#" will have already been
4531 * inserted into the hash table at the start of the
4532 * external entity parsing, so no allocation will happen
4533 * and lookup() cannot fail.
4534 */
4535 return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
4536 }
4537 if (useForeignDTD)
4538 entity->base = curBase;
4539 dtd->paramEntityRead = XML_FALSE;
4540 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4541 0,
4542 entity->base,
4543 entity->systemId,
4544 entity->publicId))
4545 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4546 if (dtd->paramEntityRead) {
4547 if (!dtd->standalone &&
4548 notStandaloneHandler &&
4549 !notStandaloneHandler(handlerArg))
4550 return XML_ERROR_NOT_STANDALONE;
4551 }
4552 /* if we didn't read the foreign DTD then this means that there
4553 is no external subset and we must reset dtd->hasParamEntityRefs
4554 */
4555 else if (!doctypeSysid)
4556 dtd->hasParamEntityRefs = hadParamEntityRefs;
4557 /* end of DTD - no need to update dtd->keepProcessing */
4558 }
4559 useForeignDTD = XML_FALSE;
4560 }
4561#endif /* XML_DTD */
4562 if (endDoctypeDeclHandler) {
4563 endDoctypeDeclHandler(handlerArg);
4564 handleDefault = XML_FALSE;
4565 }
4566 break;
4567 case XML_ROLE_INSTANCE_START:
4568#ifdef XML_DTD
4569 /* if there is no DOCTYPE declaration then now is the
4570 last chance to read the foreign DTD
4571 */
4572 if (useForeignDTD) {
4573 XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
4574 dtd->hasParamEntityRefs = XML_TRUE;
4575 if (paramEntityParsing && externalEntityRefHandler) {
4576 ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4577 externalSubsetName,
4578 sizeof(ENTITY));
4579 if (!entity)
4580 return XML_ERROR_NO_MEMORY;
4581 entity->base = curBase;
4582 dtd->paramEntityRead = XML_FALSE;
4583 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
4584 0,
4585 entity->base,
4586 entity->systemId,
4587 entity->publicId))
4588 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
4589 if (dtd->paramEntityRead) {
4590 if (!dtd->standalone &&
4591 notStandaloneHandler &&
4592 !notStandaloneHandler(handlerArg))
4593 return XML_ERROR_NOT_STANDALONE;
4594 }
4595 /* if we didn't read the foreign DTD then this means that there
4596 is no external subset and we must reset dtd->hasParamEntityRefs
4597 */
4598 else
4599 dtd->hasParamEntityRefs = hadParamEntityRefs;
4600 /* end of DTD - no need to update dtd->keepProcessing */
4601 }
4602 }
4603#endif /* XML_DTD */
4604 processor = contentProcessor;
4605 return contentProcessor(parser, s, end, nextPtr);
4606 case XML_ROLE_ATTLIST_ELEMENT_NAME:
4607 declElementType = getElementType(parser, enc, s, next);
4608 if (!declElementType)
4609 return XML_ERROR_NO_MEMORY;
4610 goto checkAttListDeclHandler;
4611 case XML_ROLE_ATTRIBUTE_NAME:
4612 declAttributeId = getAttributeId(parser, enc, s, next);
4613 if (!declAttributeId)
4614 return XML_ERROR_NO_MEMORY;
4615 declAttributeIsCdata = XML_FALSE;
4616 declAttributeType = NULL;
4617 declAttributeIsId = XML_FALSE;
4618 goto checkAttListDeclHandler;
4619 case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
4620 declAttributeIsCdata = XML_TRUE;
4621 declAttributeType = atypeCDATA;
4622 goto checkAttListDeclHandler;
4623 case XML_ROLE_ATTRIBUTE_TYPE_ID:
4624 declAttributeIsId = XML_TRUE;
4625 declAttributeType = atypeID;
4626 goto checkAttListDeclHandler;
4627 case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
4628 declAttributeType = atypeIDREF;
4629 goto checkAttListDeclHandler;
4630 case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
4631 declAttributeType = atypeIDREFS;
4632 goto checkAttListDeclHandler;
4633 case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
4634 declAttributeType = atypeENTITY;
4635 goto checkAttListDeclHandler;
4636 case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
4637 declAttributeType = atypeENTITIES;
4638 goto checkAttListDeclHandler;
4639 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
4640 declAttributeType = atypeNMTOKEN;
4641 goto checkAttListDeclHandler;
4642 case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
4643 declAttributeType = atypeNMTOKENS;
4644 checkAttListDeclHandler:
4645 if (dtd->keepProcessing && attlistDeclHandler)
4646 handleDefault = XML_FALSE;
4647 break;
4648 case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
4649 case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
4650 if (dtd->keepProcessing && attlistDeclHandler) {
4651 const XML_Char *prefix;
4652 if (declAttributeType) {
4653 prefix = enumValueSep;
4654 }
4655 else {
4656 prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
4657 ? notationPrefix
4658 : enumValueStart);
4659 }
4660 if (!poolAppendString(&tempPool, prefix))
4661 return XML_ERROR_NO_MEMORY;
4662 if (!poolAppend(&tempPool, enc, s, next))
4663 return XML_ERROR_NO_MEMORY;
4664 declAttributeType = tempPool.start;
4665 handleDefault = XML_FALSE;
4666 }
4667 break;
4668 case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
4669 case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
4670 if (dtd->keepProcessing) {
4671 if (!defineAttribute(declElementType, declAttributeId,
4672 declAttributeIsCdata, declAttributeIsId,
4673 0, parser))
4674 return XML_ERROR_NO_MEMORY;
4675 if (attlistDeclHandler && declAttributeType) {
4676 if (*declAttributeType == XML_T(ASCII_LPAREN)
4677 || (*declAttributeType == XML_T(ASCII_N)
4678 && declAttributeType[1] == XML_T(ASCII_O))) {
4679 /* Enumerated or Notation type */
4680 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4681 || !poolAppendChar(&tempPool, XML_T('\0')))
4682 return XML_ERROR_NO_MEMORY;
4683 declAttributeType = tempPool.start;
4684 poolFinish(&tempPool);
4685 }
4686 *eventEndPP = s;
4687 attlistDeclHandler(handlerArg, declElementType->name,
4688 declAttributeId->name, declAttributeType,
4689 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
4690 poolClear(&tempPool);
4691 handleDefault = XML_FALSE;
4692 }
4693 }
4694 break;
4695 case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
4696 case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
4697 if (dtd->keepProcessing) {
4698 const XML_Char *attVal;
4699 enum XML_Error result =
4700 storeAttributeValue(parser, enc, declAttributeIsCdata,
4701 s + enc->minBytesPerChar,
4702 next - enc->minBytesPerChar,
4703 &dtd->pool);
4704 if (result)
4705 return result;
4706 attVal = poolStart(&dtd->pool);
4707 poolFinish(&dtd->pool);
4708 /* ID attributes aren't allowed to have a default */
4709 if (!defineAttribute(declElementType, declAttributeId,
4710 declAttributeIsCdata, XML_FALSE, attVal, parser))
4711 return XML_ERROR_NO_MEMORY;
4712 if (attlistDeclHandler && declAttributeType) {
4713 if (*declAttributeType == XML_T(ASCII_LPAREN)
4714 || (*declAttributeType == XML_T(ASCII_N)
4715 && declAttributeType[1] == XML_T(ASCII_O))) {
4716 /* Enumerated or Notation type */
4717 if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
4718 || !poolAppendChar(&tempPool, XML_T('\0')))
4719 return XML_ERROR_NO_MEMORY;
4720 declAttributeType = tempPool.start;
4721 poolFinish(&tempPool);
4722 }
4723 *eventEndPP = s;
4724 attlistDeclHandler(handlerArg, declElementType->name,
4725 declAttributeId->name, declAttributeType,
4726 attVal,
4727 role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
4728 poolClear(&tempPool);
4729 handleDefault = XML_FALSE;
4730 }
4731 }
4732 break;
4733 case XML_ROLE_ENTITY_VALUE:
4734 if (dtd->keepProcessing) {
4735 enum XML_Error result = storeEntityValue(parser, enc,
4736 s + enc->minBytesPerChar,
4737 next - enc->minBytesPerChar);
4738 if (declEntity) {
4739 declEntity->textPtr = poolStart(&dtd->entityValuePool);
4740 declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
4741 poolFinish(&dtd->entityValuePool);
4742 if (entityDeclHandler) {
4743 *eventEndPP = s;
4744 entityDeclHandler(handlerArg,
4745 declEntity->name,
4746 declEntity->is_param,
4747 declEntity->textPtr,
4748 declEntity->textLen,
4749 curBase, 0, 0, 0);
4750 handleDefault = XML_FALSE;
4751 }
4752 }
4753 else
4754 poolDiscard(&dtd->entityValuePool);
4755 if (result != XML_ERROR_NONE)
4756 return result;
4757 }
4758 break;
4759 case XML_ROLE_DOCTYPE_SYSTEM_ID:
4760#ifdef XML_DTD
4761 useForeignDTD = XML_FALSE;
4762#endif /* XML_DTD */
4763 dtd->hasParamEntityRefs = XML_TRUE;
4764 if (startDoctypeDeclHandler) {
4765 doctypeSysid = poolStoreString(&tempPool, enc,
4766 s + enc->minBytesPerChar,
4767 next - enc->minBytesPerChar);
4768 if (doctypeSysid == NULL)
4769 return XML_ERROR_NO_MEMORY;
4770 poolFinish(&tempPool);
4771 handleDefault = XML_FALSE;
4772 }
4773#ifdef XML_DTD
4774 else
4775 /* use externalSubsetName to make doctypeSysid non-NULL
4776 for the case where no startDoctypeDeclHandler is set */
4777 doctypeSysid = externalSubsetName;
4778#endif /* XML_DTD */
4779 if (!dtd->standalone
4780#ifdef XML_DTD
4781 && !paramEntityParsing
4782#endif /* XML_DTD */
4783 && notStandaloneHandler
4784 && !notStandaloneHandler(handlerArg))
4785 return XML_ERROR_NOT_STANDALONE;
4786#ifndef XML_DTD
4787 break;
4788#else /* XML_DTD */
4789 if (!declEntity) {
4790 declEntity = (ENTITY *)lookup(parser,
4791 &dtd->paramEntities,
4792 externalSubsetName,
4793 sizeof(ENTITY));
4794 if (!declEntity)
4795 return XML_ERROR_NO_MEMORY;
4796 declEntity->publicId = NULL;
4797 }
4798 /* fall through */
4799#endif /* XML_DTD */
4800 case XML_ROLE_ENTITY_SYSTEM_ID:
4801 if (dtd->keepProcessing && declEntity) {
4802 declEntity->systemId = poolStoreString(&dtd->pool, enc,
4803 s + enc->minBytesPerChar,
4804 next - enc->minBytesPerChar);
4805 if (!declEntity->systemId)
4806 return XML_ERROR_NO_MEMORY;
4807 declEntity->base = curBase;
4808 poolFinish(&dtd->pool);
4809 if (entityDeclHandler)
4810 handleDefault = XML_FALSE;
4811 }
4812 break;
4813 case XML_ROLE_ENTITY_COMPLETE:
4814 if (dtd->keepProcessing && declEntity && entityDeclHandler) {
4815 *eventEndPP = s;
4816 entityDeclHandler(handlerArg,
4817 declEntity->name,
4818 declEntity->is_param,
4819 0,0,
4820 declEntity->base,
4821 declEntity->systemId,
4822 declEntity->publicId,
4823 0);
4824 handleDefault = XML_FALSE;
4825 }
4826 break;
4827 case XML_ROLE_ENTITY_NOTATION_NAME:
4828 if (dtd->keepProcessing && declEntity) {
4829 declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
4830 if (!declEntity->notation)
4831 return XML_ERROR_NO_MEMORY;
4832 poolFinish(&dtd->pool);
4833 if (unparsedEntityDeclHandler) {
4834 *eventEndPP = s;
4835 unparsedEntityDeclHandler(handlerArg,
4836 declEntity->name,
4837 declEntity->base,
4838 declEntity->systemId,
4839 declEntity->publicId,
4840 declEntity->notation);
4841 handleDefault = XML_FALSE;
4842 }
4843 else if (entityDeclHandler) {
4844 *eventEndPP = s;
4845 entityDeclHandler(handlerArg,
4846 declEntity->name,
4847 0,0,0,
4848 declEntity->base,
4849 declEntity->systemId,
4850 declEntity->publicId,
4851 declEntity->notation);
4852 handleDefault = XML_FALSE;
4853 }
4854 }
4855 break;
4856 case XML_ROLE_GENERAL_ENTITY_NAME:
4857 {
4858 if (XmlPredefinedEntityName(enc, s, next)) {
4859 declEntity = NULL;
4860 break;
4861 }
4862 if (dtd->keepProcessing) {
4863 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4864 if (!name)
4865 return XML_ERROR_NO_MEMORY;
4866 declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
4867 sizeof(ENTITY));
4868 if (!declEntity)
4869 return XML_ERROR_NO_MEMORY;
4870 if (declEntity->name != name) {
4871 poolDiscard(&dtd->pool);
4872 declEntity = NULL;
4873 }
4874 else {
4875 poolFinish(&dtd->pool);
4876 declEntity->publicId = NULL;
4877 declEntity->is_param = XML_FALSE;
4878 /* if we have a parent parser or are reading an internal parameter
4879 entity, then the entity declaration is not considered "internal"
4880 */
4881 declEntity->is_internal = !(parentParser || openInternalEntities);
4882 if (entityDeclHandler)
4883 handleDefault = XML_FALSE;
4884 }
4885 }
4886 else {
4887 poolDiscard(&dtd->pool);
4888 declEntity = NULL;
4889 }
4890 }
4891 break;
4892 case XML_ROLE_PARAM_ENTITY_NAME:
4893#ifdef XML_DTD
4894 if (dtd->keepProcessing) {
4895 const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
4896 if (!name)
4897 return XML_ERROR_NO_MEMORY;
4898 declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
4899 name, sizeof(ENTITY));
4900 if (!declEntity)
4901 return XML_ERROR_NO_MEMORY;
4902 if (declEntity->name != name) {
4903 poolDiscard(&dtd->pool);
4904 declEntity = NULL;
4905 }
4906 else {
4907 poolFinish(&dtd->pool);
4908 declEntity->publicId = NULL;
4909 declEntity->is_param = XML_TRUE;
4910 /* if we have a parent parser or are reading an internal parameter
4911 entity, then the entity declaration is not considered "internal"
4912 */
4913 declEntity->is_internal = !(parentParser || openInternalEntities);
4914 if (entityDeclHandler)
4915 handleDefault = XML_FALSE;
4916 }
4917 }
4918 else {
4919 poolDiscard(&dtd->pool);
4920 declEntity = NULL;
4921 }
4922#else /* not XML_DTD */
4923 declEntity = NULL;
4924#endif /* XML_DTD */
4925 break;
4926 case XML_ROLE_NOTATION_NAME:
4927 declNotationPublicId = NULL;
4928 declNotationName = NULL;
4929 if (notationDeclHandler) {
4930 declNotationName = poolStoreString(&tempPool, enc, s, next);
4931 if (!declNotationName)
4932 return XML_ERROR_NO_MEMORY;
4933 poolFinish(&tempPool);
4934 handleDefault = XML_FALSE;
4935 }
4936 break;
4937 case XML_ROLE_NOTATION_PUBLIC_ID:
4938 if (!XmlIsPublicId(enc, s, next, eventPP))
4939 return XML_ERROR_PUBLICID;
4940 if (declNotationName) { /* means notationDeclHandler != NULL */
4941 XML_Char *tem = poolStoreString(&tempPool,
4942 enc,
4943 s + enc->minBytesPerChar,
4944 next - enc->minBytesPerChar);
4945 if (!tem)
4946 return XML_ERROR_NO_MEMORY;
4947 normalizePublicId(tem);
4948 declNotationPublicId = tem;
4949 poolFinish(&tempPool);
4950 handleDefault = XML_FALSE;
4951 }
4952 break;
4953 case XML_ROLE_NOTATION_SYSTEM_ID:
4954 if (declNotationName && notationDeclHandler) {
4955 const XML_Char *systemId
4956 = poolStoreString(&tempPool, enc,
4957 s + enc->minBytesPerChar,
4958 next - enc->minBytesPerChar);
4959 if (!systemId)
4960 return XML_ERROR_NO_MEMORY;
4961 *eventEndPP = s;
4962 notationDeclHandler(handlerArg,
4963 declNotationName,
4964 curBase,
4965 systemId,
4966 declNotationPublicId);
4967 handleDefault = XML_FALSE;
4968 }
4969 poolClear(&tempPool);
4970 break;
4971 case XML_ROLE_NOTATION_NO_SYSTEM_ID:
4972 if (declNotationPublicId && notationDeclHandler) {
4973 *eventEndPP = s;
4974 notationDeclHandler(handlerArg,
4975 declNotationName,
4976 curBase,
4977 0,
4978 declNotationPublicId);
4979 handleDefault = XML_FALSE;
4980 }
4981 poolClear(&tempPool);
4982 break;
4983 case XML_ROLE_ERROR:
4984 switch (tok) {
4985 case XML_TOK_PARAM_ENTITY_REF:
4986 /* PE references in internal subset are
4987 not allowed within declarations. */
4988 return XML_ERROR_PARAM_ENTITY_REF;
4989 case XML_TOK_XML_DECL:
4990 return XML_ERROR_MISPLACED_XML_PI;
4991 default:
4992 return XML_ERROR_SYNTAX;
4993 }
4994#ifdef XML_DTD
4995 case XML_ROLE_IGNORE_SECT:
4996 {
4997 enum XML_Error result;
4998 if (defaultHandler)
4999 reportDefault(parser, enc, s, next);
5000 handleDefault = XML_FALSE;
5001 result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
5002 if (result != XML_ERROR_NONE)
5003 return result;
5004 else if (!next) {
5005 processor = ignoreSectionProcessor;
5006 return result;
5007 }
5008 }
5009 break;
5010#endif /* XML_DTD */
5011 case XML_ROLE_GROUP_OPEN:
5012 if (prologState.level >= groupSize) {
5013 if (groupSize) {
5014 char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
5015 if (temp == NULL) {
5016 groupSize /= 2;
5017 return XML_ERROR_NO_MEMORY;
5018 }
5019 groupConnector = temp;
5020 if (dtd->scaffIndex) {
5021 int *temp = (int *)REALLOC(dtd->scaffIndex,
5022 groupSize * sizeof(int));
5023 if (temp == NULL)
5024 return XML_ERROR_NO_MEMORY;
5025 dtd->scaffIndex = temp;
5026 }
5027 }
5028 else {
5029 groupConnector = (char *)MALLOC(groupSize = 32);
5030 if (!groupConnector) {
5031 groupSize = 0;
5032 return XML_ERROR_NO_MEMORY;
5033 }
5034 }
5035 }
5036 groupConnector[prologState.level] = 0;
5037 if (dtd->in_eldecl) {
5038 int myindex = nextScaffoldPart(parser);
5039 if (myindex < 0)
5040 return XML_ERROR_NO_MEMORY;
5041 dtd->scaffIndex[dtd->scaffLevel] = myindex;
5042 dtd->scaffLevel++;
5043 dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
5044 if (elementDeclHandler)
5045 handleDefault = XML_FALSE;
5046 }
5047 break;
5048 case XML_ROLE_GROUP_SEQUENCE:
5049 if (groupConnector[prologState.level] == ASCII_PIPE)
5050 return XML_ERROR_SYNTAX;
5051 groupConnector[prologState.level] = ASCII_COMMA;
5052 if (dtd->in_eldecl && elementDeclHandler)
5053 handleDefault = XML_FALSE;
5054 break;
5055 case XML_ROLE_GROUP_CHOICE:
5056 if (groupConnector[prologState.level] == ASCII_COMMA)
5057 return XML_ERROR_SYNTAX;
5058 if (dtd->in_eldecl
5059 && !groupConnector[prologState.level]
5060 && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5061 != XML_CTYPE_MIXED)
5062 ) {
5063 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5064 = XML_CTYPE_CHOICE;
5065 if (elementDeclHandler)
5066 handleDefault = XML_FALSE;
5067 }
5068 groupConnector[prologState.level] = ASCII_PIPE;
5069 break;
5070 case XML_ROLE_PARAM_ENTITY_REF:
5071#ifdef XML_DTD
5072 case XML_ROLE_INNER_PARAM_ENTITY_REF:
5073 dtd->hasParamEntityRefs = XML_TRUE;
5074 if (!paramEntityParsing)
5075 dtd->keepProcessing = dtd->standalone;
5076 else {
5077 const XML_Char *name;
5078 ENTITY *entity;
5079 name = poolStoreString(&dtd->pool, enc,
5080 s + enc->minBytesPerChar,
5081 next - enc->minBytesPerChar);
5082 if (!name)
5083 return XML_ERROR_NO_MEMORY;
5084 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5085 poolDiscard(&dtd->pool);
5086 /* first, determine if a check for an existing declaration is needed;
5087 if yes, check that the entity exists, and that it is internal,
5088 otherwise call the skipped entity handler
5089 */
5090 if (prologState.documentEntity &&
5091 (dtd->standalone
5092 ? !openInternalEntities
5093 : !dtd->hasParamEntityRefs)) {
5094 if (!entity)
5095 return XML_ERROR_UNDEFINED_ENTITY;
5096 else if (!entity->is_internal) {
5097 /* It's hard to exhaustively search the code to be sure,
5098 * but there doesn't seem to be a way of executing the
5099 * following line. There are two cases:
5100 *
5101 * If 'standalone' is false, the DTD must have no
5102 * parameter entities or we wouldn't have passed the outer
5103 * 'if' statement. That measn the only entity in the hash
5104 * table is the external subset name "#" which cannot be
5105 * given as a parameter entity name in XML syntax, so the
5106 * lookup must have returned NULL and we don't even reach
5107 * the test for an internal entity.
5108 *
5109 * If 'standalone' is true, it does not seem to be
5110 * possible to create entities taking this code path that
5111 * are not internal entities, so fail the test above.
5112 *
5113 * Because this analysis is very uncertain, the code is
5114 * being left in place and merely removed from the
5115 * coverage test statistics.
5116 */
5117 return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
5118 }
5119 }
5120 else if (!entity) {
5121 dtd->keepProcessing = dtd->standalone;
5122 /* cannot report skipped entities in declarations */
5123 if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
5124 skippedEntityHandler(handlerArg, name, 1);
5125 handleDefault = XML_FALSE;
5126 }
5127 break;
5128 }
5129 if (entity->open)
5130 return XML_ERROR_RECURSIVE_ENTITY_REF;
5131 if (entity->textPtr) {
5132 enum XML_Error result;
5133 XML_Bool betweenDecl =
5134 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
5135 result = processInternalEntity(parser, entity, betweenDecl);
5136 if (result != XML_ERROR_NONE)
5137 return result;
5138 handleDefault = XML_FALSE;
5139 break;
5140 }
5141 if (externalEntityRefHandler) {
5142 dtd->paramEntityRead = XML_FALSE;
5143 entity->open = XML_TRUE;
5144 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5145 0,
5146 entity->base,
5147 entity->systemId,
5148 entity->publicId)) {
5149 entity->open = XML_FALSE;
5150 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5151 }
5152 entity->open = XML_FALSE;
5153 handleDefault = XML_FALSE;
5154 if (!dtd->paramEntityRead) {
5155 dtd->keepProcessing = dtd->standalone;
5156 break;
5157 }
5158 }
5159 else {
5160 dtd->keepProcessing = dtd->standalone;
5161 break;
5162 }
5163 }
5164#endif /* XML_DTD */
5165 if (!dtd->standalone &&
5166 notStandaloneHandler &&
5167 !notStandaloneHandler(handlerArg))
5168 return XML_ERROR_NOT_STANDALONE;
5169 break;
5170
5171 /* Element declaration stuff */
5172
5173 case XML_ROLE_ELEMENT_NAME:
5174 if (elementDeclHandler) {
5175 declElementType = getElementType(parser, enc, s, next);
5176 if (!declElementType)
5177 return XML_ERROR_NO_MEMORY;
5178 dtd->scaffLevel = 0;
5179 dtd->scaffCount = 0;
5180 dtd->in_eldecl = XML_TRUE;
5181 handleDefault = XML_FALSE;
5182 }
5183 break;
5184
5185 case XML_ROLE_CONTENT_ANY:
5186 case XML_ROLE_CONTENT_EMPTY:
5187 if (dtd->in_eldecl) {
5188 if (elementDeclHandler) {
5189 XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
5190 if (!content)
5191 return XML_ERROR_NO_MEMORY;
5192 content->quant = XML_CQUANT_NONE;
5193 content->name = NULL;
5194 content->numchildren = 0;
5195 content->children = NULL;
5196 content->type = ((role == XML_ROLE_CONTENT_ANY) ?
5197 XML_CTYPE_ANY :
5198 XML_CTYPE_EMPTY);
5199 *eventEndPP = s;
5200 elementDeclHandler(handlerArg, declElementType->name, content);
5201 handleDefault = XML_FALSE;
5202 }
5203 dtd->in_eldecl = XML_FALSE;
5204 }
5205 break;
5206
5207 case XML_ROLE_CONTENT_PCDATA:
5208 if (dtd->in_eldecl) {
5209 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
5210 = XML_CTYPE_MIXED;
5211 if (elementDeclHandler)
5212 handleDefault = XML_FALSE;
5213 }
5214 break;
5215
5216 case XML_ROLE_CONTENT_ELEMENT:
5217 quant = XML_CQUANT_NONE;
5218 goto elementContent;
5219 case XML_ROLE_CONTENT_ELEMENT_OPT:
5220 quant = XML_CQUANT_OPT;
5221 goto elementContent;
5222 case XML_ROLE_CONTENT_ELEMENT_REP:
5223 quant = XML_CQUANT_REP;
5224 goto elementContent;
5225 case XML_ROLE_CONTENT_ELEMENT_PLUS:
5226 quant = XML_CQUANT_PLUS;
5227 elementContent:
5228 if (dtd->in_eldecl) {
5229 ELEMENT_TYPE *el;
5230 const XML_Char *name;
5231 int nameLen;
5232 const char *nxt = (quant == XML_CQUANT_NONE
5233 ? next
5234 : next - enc->minBytesPerChar);
5235 int myindex = nextScaffoldPart(parser);
5236 if (myindex < 0)
5237 return XML_ERROR_NO_MEMORY;
5238 dtd->scaffold[myindex].type = XML_CTYPE_NAME;
5239 dtd->scaffold[myindex].quant = quant;
5240 el = getElementType(parser, enc, s, nxt);
5241 if (!el)
5242 return XML_ERROR_NO_MEMORY;
5243 name = el->name;
5244 dtd->scaffold[myindex].name = name;
5245 nameLen = 0;
5246 for (; name[nameLen++]; );
5247 dtd->contentStringLen += nameLen;
5248 if (elementDeclHandler)
5249 handleDefault = XML_FALSE;
5250 }
5251 break;
5252
5253 case XML_ROLE_GROUP_CLOSE:
5254 quant = XML_CQUANT_NONE;
5255 goto closeGroup;
5256 case XML_ROLE_GROUP_CLOSE_OPT:
5257 quant = XML_CQUANT_OPT;
5258 goto closeGroup;
5259 case XML_ROLE_GROUP_CLOSE_REP:
5260 quant = XML_CQUANT_REP;
5261 goto closeGroup;
5262 case XML_ROLE_GROUP_CLOSE_PLUS:
5263 quant = XML_CQUANT_PLUS;
5264 closeGroup:
5265 if (dtd->in_eldecl) {
5266 if (elementDeclHandler)
5267 handleDefault = XML_FALSE;
5268 dtd->scaffLevel--;
5269 dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
5270 if (dtd->scaffLevel == 0) {
5271 if (!handleDefault) {
5272 XML_Content *model = build_model(parser);
5273 if (!model)
5274 return XML_ERROR_NO_MEMORY;
5275 *eventEndPP = s;
5276 elementDeclHandler(handlerArg, declElementType->name, model);
5277 }
5278 dtd->in_eldecl = XML_FALSE;
5279 dtd->contentStringLen = 0;
5280 }
5281 }
5282 break;
5283 /* End element declaration stuff */
5284
5285 case XML_ROLE_PI:
5286 if (!reportProcessingInstruction(parser, enc, s, next))
5287 return XML_ERROR_NO_MEMORY;
5288 handleDefault = XML_FALSE;
5289 break;
5290 case XML_ROLE_COMMENT:
5291 if (!reportComment(parser, enc, s, next))
5292 return XML_ERROR_NO_MEMORY;
5293 handleDefault = XML_FALSE;
5294 break;
5295 case XML_ROLE_NONE:
5296 switch (tok) {
5297 case XML_TOK_BOM:
5298 handleDefault = XML_FALSE;
5299 break;
5300 }
5301 break;
5302 case XML_ROLE_DOCTYPE_NONE:
5303 if (startDoctypeDeclHandler)
5304 handleDefault = XML_FALSE;
5305 break;
5306 case XML_ROLE_ENTITY_NONE:
5307 if (dtd->keepProcessing && entityDeclHandler)
5308 handleDefault = XML_FALSE;
5309 break;
5310 case XML_ROLE_NOTATION_NONE:
5311 if (notationDeclHandler)
5312 handleDefault = XML_FALSE;
5313 break;
5314 case XML_ROLE_ATTLIST_NONE:
5315 if (dtd->keepProcessing && attlistDeclHandler)
5316 handleDefault = XML_FALSE;
5317 break;
5318 case XML_ROLE_ELEMENT_NONE:
5319 if (elementDeclHandler)
5320 handleDefault = XML_FALSE;
5321 break;
5322 } /* end of big switch */
5323
5324 if (handleDefault && defaultHandler)
5325 reportDefault(parser, enc, s, next);
5326
5327 switch (ps_parsing) {
5328 case XML_SUSPENDED:
5329 *nextPtr = next;
5330 return XML_ERROR_NONE;
5331 case XML_FINISHED:
5332 return XML_ERROR_ABORTED;
5333 default:
5334 s = next;
5335 tok = XmlPrologTok(enc, s, end, &next);
5336 }
5337 }
5338 /* not reached */
5339}
5340
5341static enum XML_Error PTRCALL
5342epilogProcessor(XML_Parser parser,
5343 const char *s,
5344 const char *end,
5345 const char **nextPtr)
5346{
5347 processor = epilogProcessor;
5348 eventPtr = s;
5349 for (;;) {
5350 const char *next = NULL;
5351 int tok = XmlPrologTok(encoding, s, end, &next);
5352 eventEndPtr = next;
5353 switch (tok) {
5354 /* report partial linebreak - it might be the last token */
5355 case -XML_TOK_PROLOG_S:
5356 if (defaultHandler) {
5357 reportDefault(parser, encoding, s, next);
5358 if (ps_parsing == XML_FINISHED)
5359 return XML_ERROR_ABORTED;
5360 }
5361 *nextPtr = next;
5362 return XML_ERROR_NONE;
5363 case XML_TOK_NONE:
5364 *nextPtr = s;
5365 return XML_ERROR_NONE;
5366 case XML_TOK_PROLOG_S:
5367 if (defaultHandler)
5368 reportDefault(parser, encoding, s, next);
5369 break;
5370 case XML_TOK_PI:
5371 if (!reportProcessingInstruction(parser, encoding, s, next))
5372 return XML_ERROR_NO_MEMORY;
5373 break;
5374 case XML_TOK_COMMENT:
5375 if (!reportComment(parser, encoding, s, next))
5376 return XML_ERROR_NO_MEMORY;
5377 break;
5378 case XML_TOK_INVALID:
5379 eventPtr = next;
5380 return XML_ERROR_INVALID_TOKEN;
5381 case XML_TOK_PARTIAL:
5382 if (!ps_finalBuffer) {
5383 *nextPtr = s;
5384 return XML_ERROR_NONE;
5385 }
5386 return XML_ERROR_UNCLOSED_TOKEN;
5387 case XML_TOK_PARTIAL_CHAR:
5388 if (!ps_finalBuffer) {
5389 *nextPtr = s;
5390 return XML_ERROR_NONE;
5391 }
5392 return XML_ERROR_PARTIAL_CHAR;
5393 default:
5394 return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
5395 }
5396 eventPtr = s = next;
5397 switch (ps_parsing) {
5398 case XML_SUSPENDED:
5399 *nextPtr = next;
5400 return XML_ERROR_NONE;
5401 case XML_FINISHED:
5402 return XML_ERROR_ABORTED;
5403 default: ;
5404 }
5405 }
5406}
5407
5408static enum XML_Error
5409processInternalEntity(XML_Parser parser, ENTITY *entity,
5410 XML_Bool betweenDecl)
5411{
5412 const char *textStart, *textEnd;
5413 const char *next;
5414 enum XML_Error result;
5415 OPEN_INTERNAL_ENTITY *openEntity;
5416
5417 if (freeInternalEntities) {
5418 openEntity = freeInternalEntities;
5419 freeInternalEntities = openEntity->next;
5420 }
5421 else {
5422 openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
5423 if (!openEntity)
5424 return XML_ERROR_NO_MEMORY;
5425 }
5426 entity->open = XML_TRUE;
5427 entity->processed = 0;
5428 openEntity->next = openInternalEntities;
5429 openInternalEntities = openEntity;
5430 openEntity->entity = entity;
5431 openEntity->startTagLevel = tagLevel;
5432 openEntity->betweenDecl = betweenDecl;
5433 openEntity->internalEventPtr = NULL;
5434 openEntity->internalEventEndPtr = NULL;
5435 textStart = (char *)entity->textPtr;
5436 textEnd = (char *)(entity->textPtr + entity->textLen);
5437 /* Set a safe default value in case 'next' does not get set */
5438 next = textStart;
5439
5440#ifdef XML_DTD
5441 if (entity->is_param) {
5442 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
5443 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
5444 next, &next, XML_FALSE);
5445 }
5446 else
5447#endif /* XML_DTD */
5448 result = doContent(parser, tagLevel, internalEncoding, textStart,
5449 textEnd, &next, XML_FALSE);
5450
5451 if (result == XML_ERROR_NONE) {
5452 if (textEnd != next && ps_parsing == XML_SUSPENDED) {
5453 entity->processed = (int)(next - textStart);
5454 processor = internalEntityProcessor;
5455 }
5456 else {
5457 entity->open = XML_FALSE;
5458 openInternalEntities = openEntity->next;
5459 /* put openEntity back in list of free instances */
5460 openEntity->next = freeInternalEntities;
5461 freeInternalEntities = openEntity;
5462 }
5463 }
5464 return result;
5465}
5466
5467static enum XML_Error PTRCALL
5468internalEntityProcessor(XML_Parser parser,
5469 const char *s,
5470 const char *end,
5471 const char **nextPtr)
5472{
5473 ENTITY *entity;
5474 const char *textStart, *textEnd;
5475 const char *next;
5476 enum XML_Error result;
5477 OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
5478 if (!openEntity)
5479 return XML_ERROR_UNEXPECTED_STATE;
5480
5481 entity = openEntity->entity;
5482 textStart = ((char *)entity->textPtr) + entity->processed;
5483 textEnd = (char *)(entity->textPtr + entity->textLen);
5484 /* Set a safe default value in case 'next' does not get set */
5485 next = textStart;
5486
5487#ifdef XML_DTD
5488 if (entity->is_param) {
5489 int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
5490 result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
5491 next, &next, XML_FALSE);
5492 }
5493 else
5494#endif /* XML_DTD */
5495 result = doContent(parser, openEntity->startTagLevel, internalEncoding,
5496 textStart, textEnd, &next, XML_FALSE);
5497
5498 if (result != XML_ERROR_NONE)
5499 return result;
5500 else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
5501 entity->processed = (int)(next - (char *)entity->textPtr);
5502 return result;
5503 }
5504 else {
5505 entity->open = XML_FALSE;
5506 openInternalEntities = openEntity->next;
5507 /* put openEntity back in list of free instances */
5508 openEntity->next = freeInternalEntities;
5509 freeInternalEntities = openEntity;
5510 }
5511
5512#ifdef XML_DTD
5513 if (entity->is_param) {
5514 int tok;
5515 processor = prologProcessor;
5516 tok = XmlPrologTok(encoding, s, end, &next);
5517 return doProlog(parser, encoding, s, end, tok, next, nextPtr,
5518 (XML_Bool)!ps_finalBuffer);
5519 }
5520 else
5521#endif /* XML_DTD */
5522 {
5523 processor = contentProcessor;
5524 /* see externalEntityContentProcessor vs contentProcessor */
5525 return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
5526 nextPtr, (XML_Bool)!ps_finalBuffer);
5527 }
5528}
5529
5530static enum XML_Error PTRCALL
5531errorProcessor(XML_Parser parser,
5532 const char *UNUSED_P(s),
5533 const char *UNUSED_P(end),
5534 const char **UNUSED_P(nextPtr))
5535{
5536 return errorCode;
5537}
5538
5539static enum XML_Error
5540storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5541 const char *ptr, const char *end,
5542 STRING_POOL *pool)
5543{
5544 enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
5545 end, pool);
5546 if (result)
5547 return result;
5548 if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
5549 poolChop(pool);
5550 if (!poolAppendChar(pool, XML_T('\0')))
5551 return XML_ERROR_NO_MEMORY;
5552 return XML_ERROR_NONE;
5553}
5554
5555static enum XML_Error
5556appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
5557 const char *ptr, const char *end,
5558 STRING_POOL *pool)
5559{
5560 DTD * const dtd = _dtd; /* save one level of indirection */
5561 for (;;) {
5562 const char *next;
5563 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
5564 switch (tok) {
5565 case XML_TOK_NONE:
5566 return XML_ERROR_NONE;
5567 case XML_TOK_INVALID:
5568 if (enc == encoding)
5569 eventPtr = next;
5570 return XML_ERROR_INVALID_TOKEN;
5571 case XML_TOK_PARTIAL:
5572 if (enc == encoding)
5573 eventPtr = ptr;
5574 return XML_ERROR_INVALID_TOKEN;
5575 case XML_TOK_CHAR_REF:
5576 {
5577 XML_Char buf[XML_ENCODE_MAX];
5578 int i;
5579 int n = XmlCharRefNumber(enc, ptr);
5580 if (n < 0) {
5581 if (enc == encoding)
5582 eventPtr = ptr;
5583 return XML_ERROR_BAD_CHAR_REF;
5584 }
5585 if (!isCdata
5586 && n == 0x20 /* space */
5587 && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5588 break;
5589 n = XmlEncode(n, (ICHAR *)buf);
5590 /* The XmlEncode() functions can never return 0 here. That
5591 * error return happens if the code point passed in is either
5592 * negative or greater than or equal to 0x110000. The
5593 * XmlCharRefNumber() functions will all return a number
5594 * strictly less than 0x110000 or a negative value if an error
5595 * occurred. The negative value is intercepted above, so
5596 * XmlEncode() is never passed a value it might return an
5597 * error for.
5598 */
5599 for (i = 0; i < n; i++) {
5600 if (!poolAppendChar(pool, buf[i]))
5601 return XML_ERROR_NO_MEMORY;
5602 }
5603 }
5604 break;
5605 case XML_TOK_DATA_CHARS:
5606 if (!poolAppend(pool, enc, ptr, next))
5607 return XML_ERROR_NO_MEMORY;
5608 break;
5609 case XML_TOK_TRAILING_CR:
5610 next = ptr + enc->minBytesPerChar;
5611 /* fall through */
5612 case XML_TOK_ATTRIBUTE_VALUE_S:
5613 case XML_TOK_DATA_NEWLINE:
5614 if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
5615 break;
5616 if (!poolAppendChar(pool, 0x20))
5617 return XML_ERROR_NO_MEMORY;
5618 break;
5619 case XML_TOK_ENTITY_REF:
5620 {
5621 const XML_Char *name;
5622 ENTITY *entity;
5623 char checkEntityDecl;
5624 XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
5625 ptr + enc->minBytesPerChar,
5626 next - enc->minBytesPerChar);
5627 if (ch) {
5628 if (!poolAppendChar(pool, ch))
5629 return XML_ERROR_NO_MEMORY;
5630 break;
5631 }
5632 name = poolStoreString(&temp2Pool, enc,
5633 ptr + enc->minBytesPerChar,
5634 next - enc->minBytesPerChar);
5635 if (!name)
5636 return XML_ERROR_NO_MEMORY;
5637 entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
5638 poolDiscard(&temp2Pool);
5639 /* First, determine if a check for an existing declaration is needed;
5640 if yes, check that the entity exists, and that it is internal.
5641 */
5642 if (pool == &dtd->pool) /* are we called from prolog? */
5643 checkEntityDecl =
5644#ifdef XML_DTD
5645 prologState.documentEntity &&
5646#endif /* XML_DTD */
5647 (dtd->standalone
5648 ? !openInternalEntities
5649 : !dtd->hasParamEntityRefs);
5650 else /* if (pool == &tempPool): we are called from content */
5651 checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
5652 if (checkEntityDecl) {
5653 if (!entity)
5654 return XML_ERROR_UNDEFINED_ENTITY;
5655 else if (!entity->is_internal)
5656 return XML_ERROR_ENTITY_DECLARED_IN_PE;
5657 }
5658 else if (!entity) {
5659 /* Cannot report skipped entity here - see comments on
5660 skippedEntityHandler.
5661 if (skippedEntityHandler)
5662 skippedEntityHandler(handlerArg, name, 0);
5663 */
5664 /* Cannot call the default handler because this would be
5665 out of sync with the call to the startElementHandler.
5666 if ((pool == &tempPool) && defaultHandler)
5667 reportDefault(parser, enc, ptr, next);
5668 */
5669 break;
5670 }
5671 if (entity->open) {
5672 if (enc == encoding) {
5673 /* It does not appear that this line can be executed.
5674 *
5675 * The "if (entity->open)" check catches recursive entity
5676 * definitions. In order to be called with an open
5677 * entity, it must have gone through this code before and
5678 * been through the recursive call to
5679 * appendAttributeValue() some lines below. That call
5680 * sets the local encoding ("enc") to the parser's
5681 * internal encoding (internal_utf8 or internal_utf16),
5682 * which can never be the same as the principle encoding.
5683 * It doesn't appear there is another code path that gets
5684 * here with entity->open being TRUE.
5685 *
5686 * Since it is not certain that this logic is watertight,
5687 * we keep the line and merely exclude it from coverage
5688 * tests.
5689 */
5690 eventPtr = ptr; /* LCOV_EXCL_LINE */
5691 }
5692 return XML_ERROR_RECURSIVE_ENTITY_REF;
5693 }
5694 if (entity->notation) {
5695 if (enc == encoding)
5696 eventPtr = ptr;
5697 return XML_ERROR_BINARY_ENTITY_REF;
5698 }
5699 if (!entity->textPtr) {
5700 if (enc == encoding)
5701 eventPtr = ptr;
5702 return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
5703 }
5704 else {
5705 enum XML_Error result;
5706 const XML_Char *textEnd = entity->textPtr + entity->textLen;
5707 entity->open = XML_TRUE;
5708 result = appendAttributeValue(parser, internalEncoding, isCdata,
5709 (char *)entity->textPtr,
5710 (char *)textEnd, pool);
5711 entity->open = XML_FALSE;
5712 if (result)
5713 return result;
5714 }
5715 }
5716 break;
5717 default:
5718 /* The only token returned by XmlAttributeValueTok() that does
5719 * not have an explicit case here is XML_TOK_PARTIAL_CHAR.
5720 * Getting that would require an entity name to contain an
5721 * incomplete XML character (e.g. \xE2\x82); however previous
5722 * tokenisers will have already recognised and rejected such
5723 * names before XmlAttributeValueTok() gets a look-in. This
5724 * default case should be retained as a safety net, but the code
5725 * excluded from coverage tests.
5726 *
5727 * LCOV_EXCL_START
5728 */
5729 if (enc == encoding)
5730 eventPtr = ptr;
5731 return XML_ERROR_UNEXPECTED_STATE;
5732 /* LCOV_EXCL_STOP */
5733 }
5734 ptr = next;
5735 }
5736 /* not reached */
5737}
5738
5739static enum XML_Error
5740storeEntityValue(XML_Parser parser,
5741 const ENCODING *enc,
5742 const char *entityTextPtr,
5743 const char *entityTextEnd)
5744{
5745 DTD * const dtd = _dtd; /* save one level of indirection */
5746 STRING_POOL *pool = &(dtd->entityValuePool);
5747 enum XML_Error result = XML_ERROR_NONE;
5748#ifdef XML_DTD
5749 int oldInEntityValue = prologState.inEntityValue;
5750 prologState.inEntityValue = 1;
5751#endif /* XML_DTD */
5752 /* never return Null for the value argument in EntityDeclHandler,
5753 since this would indicate an external entity; therefore we
5754 have to make sure that entityValuePool.start is not null */
5755 if (!pool->blocks) {
5756 if (!poolGrow(pool))
5757 return XML_ERROR_NO_MEMORY;
5758 }
5759
5760 for (;;) {
5761 const char *next;
5762 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
5763 switch (tok) {
5764 case XML_TOK_PARAM_ENTITY_REF:
5765#ifdef XML_DTD
5766 if (isParamEntity || enc != encoding) {
5767 const XML_Char *name;
5768 ENTITY *entity;
5769 name = poolStoreString(&tempPool, enc,
5770 entityTextPtr + enc->minBytesPerChar,
5771 next - enc->minBytesPerChar);
5772 if (!name) {
5773 result = XML_ERROR_NO_MEMORY;
5774 goto endEntityValue;
5775 }
5776 entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
5777 poolDiscard(&tempPool);
5778 if (!entity) {
5779 /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
5780 /* cannot report skipped entity here - see comments on
5781 skippedEntityHandler
5782 if (skippedEntityHandler)
5783 skippedEntityHandler(handlerArg, name, 0);
5784 */
5785 dtd->keepProcessing = dtd->standalone;
5786 goto endEntityValue;
5787 }
5788 if (entity->open) {
5789 if (enc == encoding)
5790 eventPtr = entityTextPtr;
5791 result = XML_ERROR_RECURSIVE_ENTITY_REF;
5792 goto endEntityValue;
5793 }
5794 if (entity->systemId) {
5795 if (externalEntityRefHandler) {
5796 dtd->paramEntityRead = XML_FALSE;
5797 entity->open = XML_TRUE;
5798 if (!externalEntityRefHandler(externalEntityRefHandlerArg,
5799 0,
5800 entity->base,
5801 entity->systemId,
5802 entity->publicId)) {
5803 entity->open = XML_FALSE;
5804 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
5805 goto endEntityValue;
5806 }
5807 entity->open = XML_FALSE;
5808 if (!dtd->paramEntityRead)
5809 dtd->keepProcessing = dtd->standalone;
5810 }
5811 else
5812 dtd->keepProcessing = dtd->standalone;
5813 }
5814 else {
5815 entity->open = XML_TRUE;
5816 result = storeEntityValue(parser,
5817 internalEncoding,
5818 (char *)entity->textPtr,
5819 (char *)(entity->textPtr
5820 + entity->textLen));
5821 entity->open = XML_FALSE;
5822 if (result)
5823 goto endEntityValue;
5824 }
5825 break;
5826 }
5827#endif /* XML_DTD */
5828 /* In the internal subset, PE references are not legal
5829 within markup declarations, e.g entity values in this case. */
5830 eventPtr = entityTextPtr;
5831 result = XML_ERROR_PARAM_ENTITY_REF;
5832 goto endEntityValue;
5833 case XML_TOK_NONE:
5834 result = XML_ERROR_NONE;
5835 goto endEntityValue;
5836 case XML_TOK_ENTITY_REF:
5837 case XML_TOK_DATA_CHARS:
5838 if (!poolAppend(pool, enc, entityTextPtr, next)) {
5839 result = XML_ERROR_NO_MEMORY;
5840 goto endEntityValue;
5841 }
5842 break;
5843 case XML_TOK_TRAILING_CR:
5844 next = entityTextPtr + enc->minBytesPerChar;
5845 /* fall through */
5846 case XML_TOK_DATA_NEWLINE:
5847 if (pool->end == pool->ptr && !poolGrow(pool)) {
5848 result = XML_ERROR_NO_MEMORY;
5849 goto endEntityValue;
5850 }
5851 *(pool->ptr)++ = 0xA;
5852 break;
5853 case XML_TOK_CHAR_REF:
5854 {
5855 XML_Char buf[XML_ENCODE_MAX];
5856 int i;
5857 int n = XmlCharRefNumber(enc, entityTextPtr);
5858 if (n < 0) {
5859 if (enc == encoding)
5860 eventPtr = entityTextPtr;
5861 result = XML_ERROR_BAD_CHAR_REF;
5862 goto endEntityValue;
5863 }
5864 n = XmlEncode(n, (ICHAR *)buf);
5865 /* The XmlEncode() functions can never return 0 here. That
5866 * error return happens if the code point passed in is either
5867 * negative or greater than or equal to 0x110000. The
5868 * XmlCharRefNumber() functions will all return a number
5869 * strictly less than 0x110000 or a negative value if an error
5870 * occurred. The negative value is intercepted above, so
5871 * XmlEncode() is never passed a value it might return an
5872 * error for.
5873 */
5874 for (i = 0; i < n; i++) {
5875 if (pool->end == pool->ptr && !poolGrow(pool)) {
5876 result = XML_ERROR_NO_MEMORY;
5877 goto endEntityValue;
5878 }
5879 *(pool->ptr)++ = buf[i];
5880 }
5881 }
5882 break;
5883 case XML_TOK_PARTIAL:
5884 if (enc == encoding)
5885 eventPtr = entityTextPtr;
5886 result = XML_ERROR_INVALID_TOKEN;
5887 goto endEntityValue;
5888 case XML_TOK_INVALID:
5889 if (enc == encoding)
5890 eventPtr = next;
5891 result = XML_ERROR_INVALID_TOKEN;
5892 goto endEntityValue;
5893 default:
5894 /* This default case should be unnecessary -- all the tokens
5895 * that XmlEntityValueTok() can return have their own explicit
5896 * cases -- but should be retained for safety. We do however
5897 * exclude it from the coverage statistics.
5898 *
5899 * LCOV_EXCL_START
5900 */
5901 if (enc == encoding)
5902 eventPtr = entityTextPtr;
5903 result = XML_ERROR_UNEXPECTED_STATE;
5904 goto endEntityValue;
5905 /* LCOV_EXCL_STOP */
5906 }
5907 entityTextPtr = next;
5908 }
5909endEntityValue:
5910#ifdef XML_DTD
5911 prologState.inEntityValue = oldInEntityValue;
5912#endif /* XML_DTD */
5913 return result;
5914}
5915
5916static void FASTCALL
5917normalizeLines(XML_Char *s)
5918{
5919 XML_Char *p;
5920 for (;; s++) {
5921 if (*s == XML_T('\0'))
5922 return;
5923 if (*s == 0xD)
5924 break;
5925 }
5926 p = s;
5927 do {
5928 if (*s == 0xD) {
5929 *p++ = 0xA;
5930 if (*++s == 0xA)
5931 s++;
5932 }
5933 else
5934 *p++ = *s++;
5935 } while (*s);
5936 *p = XML_T('\0');
5937}
5938
5939static int
5940reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
5941 const char *start, const char *end)
5942{
5943 const XML_Char *target;
5944 XML_Char *data;
5945 const char *tem;
5946 if (!processingInstructionHandler) {
5947 if (defaultHandler)
5948 reportDefault(parser, enc, start, end);
5949 return 1;
5950 }
5951 start += enc->minBytesPerChar * 2;
5952 tem = start + XmlNameLength(enc, start);
5953 target = poolStoreString(&tempPool, enc, start, tem);
5954 if (!target)
5955 return 0;
5956 poolFinish(&tempPool);
5957 data = poolStoreString(&tempPool, enc,
5958 XmlSkipS(enc, tem),
5959 end - enc->minBytesPerChar*2);
5960 if (!data)
5961 return 0;
5962 normalizeLines(data);
5963 processingInstructionHandler(handlerArg, target, data);
5964 poolClear(&tempPool);
5965 return 1;
5966}
5967
5968static int
5969reportComment(XML_Parser parser, const ENCODING *enc,
5970 const char *start, const char *end)
5971{
5972 XML_Char *data;
5973 if (!commentHandler) {
5974 if (defaultHandler)
5975 reportDefault(parser, enc, start, end);
5976 return 1;
5977 }
5978 data = poolStoreString(&tempPool,
5979 enc,
5980 start + enc->minBytesPerChar * 4,
5981 end - enc->minBytesPerChar * 3);
5982 if (!data)
5983 return 0;
5984 normalizeLines(data);
5985 commentHandler(handlerArg, data);
5986 poolClear(&tempPool);
5987 return 1;
5988}
5989
5990static void
5991reportDefault(XML_Parser parser, const ENCODING *enc,
5992 const char *s, const char *end)
5993{
5994 if (MUST_CONVERT(enc, s)) {
5995 enum XML_Convert_Result convert_res;
5996 const char **eventPP;
5997 const char **eventEndPP;
5998 if (enc == encoding) {
5999 eventPP = &eventPtr;
6000 eventEndPP = &eventEndPtr;
6001 }
6002 else {
6003 /* To get here, two things must be true; the parser must be
6004 * using a character encoding that is not the same as the
6005 * encoding passed in, and the encoding passed in must need
6006 * conversion to the internal format (UTF-8 unless XML_UNICODE
6007 * is defined). The only occasions on which the encoding passed
6008 * in is not the same as the parser's encoding are when it is
6009 * the internal encoding (e.g. a previously defined parameter
6010 * entity, already converted to internal format). This by
6011 * definition doesn't need conversion, so the whole branch never
6012 * gets executed.
6013 *
6014 * For safety's sake we don't delete these lines and merely
6015 * exclude them from coverage statistics.
6016 *
6017 * LCOV_EXCL_START
6018 */
6019 eventPP = &(openInternalEntities->internalEventPtr);
6020 eventEndPP = &(openInternalEntities->internalEventEndPtr);
6021 /* LCOV_EXCL_STOP */
6022 }
6023 do {
6024 ICHAR *dataPtr = (ICHAR *)dataBuf;
6025 convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
6026 *eventEndPP = s;
6027 defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
6028 *eventPP = s;
6029 } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
6030 }
6031 else
6032 defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
6033}
6034
6035
6036static int
6037defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
6038 XML_Bool isId, const XML_Char *value, XML_Parser parser)
6039{
6040 DEFAULT_ATTRIBUTE *att;
6041 if (value || isId) {
6042 /* The handling of default attributes gets messed up if we have
6043 a default which duplicates a non-default. */
6044 int i;
6045 for (i = 0; i < type->nDefaultAtts; i++)
6046 if (attId == type->defaultAtts[i].id)
6047 return 1;
6048 if (isId && !type->idAtt && !attId->xmlns)
6049 type->idAtt = attId;
6050 }
6051 if (type->nDefaultAtts == type->allocDefaultAtts) {
6052 if (type->allocDefaultAtts == 0) {
6053 type->allocDefaultAtts = 8;
6054 type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
6055 * sizeof(DEFAULT_ATTRIBUTE));
6056 if (!type->defaultAtts)
6057 return 0;
6058 }
6059 else {
6060 DEFAULT_ATTRIBUTE *temp;
6061 int count = type->allocDefaultAtts * 2;
6062 temp = (DEFAULT_ATTRIBUTE *)
6063 REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
6064 if (temp == NULL)
6065 return 0;
6066 type->allocDefaultAtts = count;
6067 type->defaultAtts = temp;
6068 }
6069 }
6070 att = type->defaultAtts + type->nDefaultAtts;
6071 att->id = attId;
6072 att->value = value;
6073 att->isCdata = isCdata;
6074 if (!isCdata)
6075 attId->maybeTokenized = XML_TRUE;
6076 type->nDefaultAtts += 1;
6077 return 1;
6078}
6079
6080static int
6081setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
6082{
6083 DTD * const dtd = _dtd; /* save one level of indirection */
6084 const XML_Char *name;
6085 for (name = elementType->name; *name; name++) {
6086 if (*name == XML_T(ASCII_COLON)) {
6087 PREFIX *prefix;
6088 const XML_Char *s;
6089 for (s = elementType->name; s != name; s++) {
6090 if (!poolAppendChar(&dtd->pool, *s))
6091 return 0;
6092 }
6093 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6094 return 0;
6095 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
6096 sizeof(PREFIX));
6097 if (!prefix)
6098 return 0;
6099 if (prefix->name == poolStart(&dtd->pool))
6100 poolFinish(&dtd->pool);
6101 else
6102 poolDiscard(&dtd->pool);
6103 elementType->prefix = prefix;
6104
6105 }
6106 }
6107 return 1;
6108}
6109
6110static ATTRIBUTE_ID *
6111getAttributeId(XML_Parser parser, const ENCODING *enc,
6112 const char *start, const char *end)
6113{
6114 DTD * const dtd = _dtd; /* save one level of indirection */
6115 ATTRIBUTE_ID *id;
6116 const XML_Char *name;
6117 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6118 return NULL;
6119 name = poolStoreString(&dtd->pool, enc, start, end);
6120 if (!name)
6121 return NULL;
6122 /* skip quotation mark - its storage will be re-used (like in name[-1]) */
6123 ++name;
6124 id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
6125 if (!id)
6126 return NULL;
6127 if (id->name != name)
6128 poolDiscard(&dtd->pool);
6129 else {
6130 poolFinish(&dtd->pool);
6131 if (!ns)
6132 ;
6133 else if (name[0] == XML_T(ASCII_x)
6134 && name[1] == XML_T(ASCII_m)
6135 && name[2] == XML_T(ASCII_l)
6136 && name[3] == XML_T(ASCII_n)
6137 && name[4] == XML_T(ASCII_s)
6138 && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
6139 if (name[5] == XML_T('\0'))
6140 id->prefix = &dtd->defaultPrefix;
6141 else
6142 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
6143 id->xmlns = XML_TRUE;
6144 }
6145 else {
6146 int i;
6147 for (i = 0; name[i]; i++) {
6148 /* attributes without prefix are *not* in the default namespace */
6149 if (name[i] == XML_T(ASCII_COLON)) {
6150 int j;
6151 for (j = 0; j < i; j++) {
6152 if (!poolAppendChar(&dtd->pool, name[j]))
6153 return NULL;
6154 }
6155 if (!poolAppendChar(&dtd->pool, XML_T('\0')))
6156 return NULL;
6157 id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
6158 sizeof(PREFIX));
6159 if (!id->prefix)
6160 return NULL;
6161 if (id->prefix->name == poolStart(&dtd->pool))
6162 poolFinish(&dtd->pool);
6163 else
6164 poolDiscard(&dtd->pool);
6165 break;
6166 }
6167 }
6168 }
6169 }
6170 return id;
6171}
6172
6173#define CONTEXT_SEP XML_T(ASCII_FF)
6174
6175static const XML_Char *
6176getContext(XML_Parser parser)
6177{
6178 DTD * const dtd = _dtd; /* save one level of indirection */
6179 HASH_TABLE_ITER iter;
6180 XML_Bool needSep = XML_FALSE;
6181
6182 if (dtd->defaultPrefix.binding) {
6183 int i;
6184 int len;
6185 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
6186 return NULL;
6187 len = dtd->defaultPrefix.binding->uriLen;
6188 if (namespaceSeparator)
6189 len--;
6190 for (i = 0; i < len; i++) {
6191 if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i])) {
6192 /* Because of memory caching, I don't believe this line can be
6193 * executed.
6194 *
6195 * This is part of a loop copying the default prefix binding
6196 * URI into the parser's temporary string pool. Previously,
6197 * that URI was copied into the same string pool, with a
6198 * terminating NUL character, as part of setContext(). When
6199 * the pool was cleared, that leaves a block definitely big
6200 * enough to hold the URI on the free block list of the pool.
6201 * The URI copy in getContext() therefore cannot run out of
6202 * memory.
6203 *
6204 * If the pool is used between the setContext() and
6205 * getContext() calls, the worst it can do is leave a bigger
6206 * block on the front of the free list. Given that this is
6207 * all somewhat inobvious and program logic can be changed, we
6208 * don't delete the line but we do exclude it from the test
6209 * coverage statistics.
6210 */
6211 return NULL; /* LCOV_EXCL_LINE */
6212 }
6213 }
6214 needSep = XML_TRUE;
6215 }
6216
6217 hashTableIterInit(&iter, &(dtd->prefixes));
6218 for (;;) {
6219 int i;
6220 int len;
6221 const XML_Char *s;
6222 PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
6223 if (!prefix)
6224 break;
6225 if (!prefix->binding) {
6226 /* This test appears to be (justifiable) paranoia. There does
6227 * not seem to be a way of injecting a prefix without a binding
6228 * that doesn't get errored long before this function is called.
6229 * The test should remain for safety's sake, so we instead
6230 * exclude the following line from the coverage statistics.
6231 */
6232 continue; /* LCOV_EXCL_LINE */
6233 }
6234 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
6235 return NULL;
6236 for (s = prefix->name; *s; s++)
6237 if (!poolAppendChar(&tempPool, *s))
6238 return NULL;
6239 if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
6240 return NULL;
6241 len = prefix->binding->uriLen;
6242 if (namespaceSeparator)
6243 len--;
6244 for (i = 0; i < len; i++)
6245 if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
6246 return NULL;
6247 needSep = XML_TRUE;
6248 }
6249
6250
6251 hashTableIterInit(&iter, &(dtd->generalEntities));
6252 for (;;) {
6253 const XML_Char *s;
6254 ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
6255 if (!e)
6256 break;
6257 if (!e->open)
6258 continue;
6259 if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
6260 return NULL;
6261 for (s = e->name; *s; s++)
6262 if (!poolAppendChar(&tempPool, *s))
6263 return 0;
6264 needSep = XML_TRUE;
6265 }
6266
6267 if (!poolAppendChar(&tempPool, XML_T('\0')))
6268 return NULL;
6269 return tempPool.start;
6270}
6271
6272static XML_Bool
6273setContext(XML_Parser parser, const XML_Char *context)
6274{
6275 DTD * const dtd = _dtd; /* save one level of indirection */
6276 const XML_Char *s = context;
6277
6278 while (*context != XML_T('\0')) {
6279 if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
6280 ENTITY *e;
6281 if (!poolAppendChar(&tempPool, XML_T('\0')))
6282 return XML_FALSE;
6283 e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
6284 if (e)
6285 e->open = XML_TRUE;
6286 if (*s != XML_T('\0'))
6287 s++;
6288 context = s;
6289 poolDiscard(&tempPool);
6290 }
6291 else if (*s == XML_T(ASCII_EQUALS)) {
6292 PREFIX *prefix;
6293 if (poolLength(&tempPool) == 0)
6294 prefix = &dtd->defaultPrefix;
6295 else {
6296 if (!poolAppendChar(&tempPool, XML_T('\0')))
6297 return XML_FALSE;
6298 prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
6299 sizeof(PREFIX));
6300 if (!prefix)
6301 return XML_FALSE;
6302 if (prefix->name == poolStart(&tempPool)) {
6303 prefix->name = poolCopyString(&dtd->pool, prefix->name);
6304 if (!prefix->name)
6305 return XML_FALSE;
6306 }
6307 poolDiscard(&tempPool);
6308 }
6309 for (context = s + 1;
6310 *context != CONTEXT_SEP && *context != XML_T('\0');
6311 context++)
6312 if (!poolAppendChar(&tempPool, *context))
6313 return XML_FALSE;
6314 if (!poolAppendChar(&tempPool, XML_T('\0')))
6315 return XML_FALSE;
6316 if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
6317 &inheritedBindings) != XML_ERROR_NONE)
6318 return XML_FALSE;
6319 poolDiscard(&tempPool);
6320 if (*context != XML_T('\0'))
6321 ++context;
6322 s = context;
6323 }
6324 else {
6325 if (!poolAppendChar(&tempPool, *s))
6326 return XML_FALSE;
6327 s++;
6328 }
6329 }
6330 return XML_TRUE;
6331}
6332
6333static void FASTCALL
6334normalizePublicId(XML_Char *publicId)
6335{
6336 XML_Char *p = publicId;
6337 XML_Char *s;
6338 for (s = publicId; *s; s++) {
6339 switch (*s) {
6340 case 0x20:
6341 case 0xD:
6342 case 0xA:
6343 if (p != publicId && p[-1] != 0x20)
6344 *p++ = 0x20;
6345 break;
6346 default:
6347 *p++ = *s;
6348 }
6349 }
6350 if (p != publicId && p[-1] == 0x20)
6351 --p;
6352 *p = XML_T('\0');
6353}
6354
6355static DTD *
6356dtdCreate(const XML_Memory_Handling_Suite *ms)
6357{
6358 DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
6359 if (p == NULL)
6360 return p;
6361 poolInit(&(p->pool), ms);
6362 poolInit(&(p->entityValuePool), ms);
6363 hashTableInit(&(p->generalEntities), ms);
6364 hashTableInit(&(p->elementTypes), ms);
6365 hashTableInit(&(p->attributeIds), ms);
6366 hashTableInit(&(p->prefixes), ms);
6367#ifdef XML_DTD
6368 p->paramEntityRead = XML_FALSE;
6369 hashTableInit(&(p->paramEntities), ms);
6370#endif /* XML_DTD */
6371 p->defaultPrefix.name = NULL;
6372 p->defaultPrefix.binding = NULL;
6373
6374 p->in_eldecl = XML_FALSE;
6375 p->scaffIndex = NULL;
6376 p->scaffold = NULL;
6377 p->scaffLevel = 0;
6378 p->scaffSize = 0;
6379 p->scaffCount = 0;
6380 p->contentStringLen = 0;
6381
6382 p->keepProcessing = XML_TRUE;
6383 p->hasParamEntityRefs = XML_FALSE;
6384 p->standalone = XML_FALSE;
6385 return p;
6386}
6387
6388static void
6389dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
6390{
6391 HASH_TABLE_ITER iter;
6392 hashTableIterInit(&iter, &(p->elementTypes));
6393 for (;;) {
6394 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6395 if (!e)
6396 break;
6397 if (e->allocDefaultAtts != 0)
6398 ms->free_fcn(e->defaultAtts);
6399 }
6400 hashTableClear(&(p->generalEntities));
6401#ifdef XML_DTD
6402 p->paramEntityRead = XML_FALSE;
6403 hashTableClear(&(p->paramEntities));
6404#endif /* XML_DTD */
6405 hashTableClear(&(p->elementTypes));
6406 hashTableClear(&(p->attributeIds));
6407 hashTableClear(&(p->prefixes));
6408 poolClear(&(p->pool));
6409 poolClear(&(p->entityValuePool));
6410 p->defaultPrefix.name = NULL;
6411 p->defaultPrefix.binding = NULL;
6412
6413 p->in_eldecl = XML_FALSE;
6414
6415 ms->free_fcn(p->scaffIndex);
6416 p->scaffIndex = NULL;
6417 ms->free_fcn(p->scaffold);
6418 p->scaffold = NULL;
6419
6420 p->scaffLevel = 0;
6421 p->scaffSize = 0;
6422 p->scaffCount = 0;
6423 p->contentStringLen = 0;
6424
6425 p->keepProcessing = XML_TRUE;
6426 p->hasParamEntityRefs = XML_FALSE;
6427 p->standalone = XML_FALSE;
6428}
6429
6430static void
6431dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
6432{
6433 HASH_TABLE_ITER iter;
6434 hashTableIterInit(&iter, &(p->elementTypes));
6435 for (;;) {
6436 ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6437 if (!e)
6438 break;
6439 if (e->allocDefaultAtts != 0)
6440 ms->free_fcn(e->defaultAtts);
6441 }
6442 hashTableDestroy(&(p->generalEntities));
6443#ifdef XML_DTD
6444 hashTableDestroy(&(p->paramEntities));
6445#endif /* XML_DTD */
6446 hashTableDestroy(&(p->elementTypes));
6447 hashTableDestroy(&(p->attributeIds));
6448 hashTableDestroy(&(p->prefixes));
6449 poolDestroy(&(p->pool));
6450 poolDestroy(&(p->entityValuePool));
6451 if (isDocEntity) {
6452 ms->free_fcn(p->scaffIndex);
6453 ms->free_fcn(p->scaffold);
6454 }
6455 ms->free_fcn(p);
6456}
6457
6458/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
6459 The new DTD has already been initialized.
6460*/
6461static int
6462dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
6463{
6464 HASH_TABLE_ITER iter;
6465
6466 /* Copy the prefix table. */
6467
6468 hashTableIterInit(&iter, &(oldDtd->prefixes));
6469 for (;;) {
6470 const XML_Char *name;
6471 const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
6472 if (!oldP)
6473 break;
6474 name = poolCopyString(&(newDtd->pool), oldP->name);
6475 if (!name)
6476 return 0;
6477 if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
6478 return 0;
6479 }
6480
6481 hashTableIterInit(&iter, &(oldDtd->attributeIds));
6482
6483 /* Copy the attribute id table. */
6484
6485 for (;;) {
6486 ATTRIBUTE_ID *newA;
6487 const XML_Char *name;
6488 const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
6489
6490 if (!oldA)
6491 break;
6492 /* Remember to allocate the scratch byte before the name. */
6493 if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
6494 return 0;
6495 name = poolCopyString(&(newDtd->pool), oldA->name);
6496 if (!name)
6497 return 0;
6498 ++name;
6499 newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
6500 sizeof(ATTRIBUTE_ID));
6501 if (!newA)
6502 return 0;
6503 newA->maybeTokenized = oldA->maybeTokenized;
6504 if (oldA->prefix) {
6505 newA->xmlns = oldA->xmlns;
6506 if (oldA->prefix == &oldDtd->defaultPrefix)
6507 newA->prefix = &newDtd->defaultPrefix;
6508 else
6509 newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
6510 oldA->prefix->name, 0);
6511 }
6512 }
6513
6514 /* Copy the element type table. */
6515
6516 hashTableIterInit(&iter, &(oldDtd->elementTypes));
6517
6518 for (;;) {
6519 int i;
6520 ELEMENT_TYPE *newE;
6521 const XML_Char *name;
6522 const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
6523 if (!oldE)
6524 break;
6525 name = poolCopyString(&(newDtd->pool), oldE->name);
6526 if (!name)
6527 return 0;
6528 newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
6529 sizeof(ELEMENT_TYPE));
6530 if (!newE)
6531 return 0;
6532 if (oldE->nDefaultAtts) {
6533 newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
6534 ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
6535 if (!newE->defaultAtts) {
6536 return 0;
6537 }
6538 }
6539 if (oldE->idAtt)
6540 newE->idAtt = (ATTRIBUTE_ID *)
6541 lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
6542 newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
6543 if (oldE->prefix)
6544 newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
6545 oldE->prefix->name, 0);
6546 for (i = 0; i < newE->nDefaultAtts; i++) {
6547 newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
6548 lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
6549 newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
6550 if (oldE->defaultAtts[i].value) {
6551 newE->defaultAtts[i].value
6552 = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
6553 if (!newE->defaultAtts[i].value)
6554 return 0;
6555 }
6556 else
6557 newE->defaultAtts[i].value = NULL;
6558 }
6559 }
6560
6561 /* Copy the entity tables. */
6562 if (!copyEntityTable(oldParser,
6563 &(newDtd->generalEntities),
6564 &(newDtd->pool),
6565 &(oldDtd->generalEntities)))
6566 return 0;
6567
6568#ifdef XML_DTD
6569 if (!copyEntityTable(oldParser,
6570 &(newDtd->paramEntities),
6571 &(newDtd->pool),
6572 &(oldDtd->paramEntities)))
6573 return 0;
6574 newDtd->paramEntityRead = oldDtd->paramEntityRead;
6575#endif /* XML_DTD */
6576
6577 newDtd->keepProcessing = oldDtd->keepProcessing;
6578 newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
6579 newDtd->standalone = oldDtd->standalone;
6580
6581 /* Don't want deep copying for scaffolding */
6582 newDtd->in_eldecl = oldDtd->in_eldecl;
6583 newDtd->scaffold = oldDtd->scaffold;
6584 newDtd->contentStringLen = oldDtd->contentStringLen;
6585 newDtd->scaffSize = oldDtd->scaffSize;
6586 newDtd->scaffLevel = oldDtd->scaffLevel;
6587 newDtd->scaffIndex = oldDtd->scaffIndex;
6588
6589 return 1;
6590} /* End dtdCopy */
6591
6592static int
6593copyEntityTable(XML_Parser oldParser,
6594 HASH_TABLE *newTable,
6595 STRING_POOL *newPool,
6596 const HASH_TABLE *oldTable)
6597{
6598 HASH_TABLE_ITER iter;
6599 const XML_Char *cachedOldBase = NULL;
6600 const XML_Char *cachedNewBase = NULL;
6601
6602 hashTableIterInit(&iter, oldTable);
6603
6604 for (;;) {
6605 ENTITY *newE;
6606 const XML_Char *name;
6607 const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
6608 if (!oldE)
6609 break;
6610 name = poolCopyString(newPool, oldE->name);
6611 if (!name)
6612 return 0;
6613 newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
6614 if (!newE)
6615 return 0;
6616 if (oldE->systemId) {
6617 const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
6618 if (!tem)
6619 return 0;
6620 newE->systemId = tem;
6621 if (oldE->base) {
6622 if (oldE->base == cachedOldBase)
6623 newE->base = cachedNewBase;
6624 else {
6625 cachedOldBase = oldE->base;
6626 tem = poolCopyString(newPool, cachedOldBase);
6627 if (!tem)
6628 return 0;
6629 cachedNewBase = newE->base = tem;
6630 }
6631 }
6632 if (oldE->publicId) {
6633 tem = poolCopyString(newPool, oldE->publicId);
6634 if (!tem)
6635 return 0;
6636 newE->publicId = tem;
6637 }
6638 }
6639 else {
6640 const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
6641 oldE->textLen);
6642 if (!tem)
6643 return 0;
6644 newE->textPtr = tem;
6645 newE->textLen = oldE->textLen;
6646 }
6647 if (oldE->notation) {
6648 const XML_Char *tem = poolCopyString(newPool, oldE->notation);
6649 if (!tem)
6650 return 0;
6651 newE->notation = tem;
6652 }
6653 newE->is_param = oldE->is_param;
6654 newE->is_internal = oldE->is_internal;
6655 }
6656 return 1;
6657}
6658
6659#define INIT_POWER 6
6660
6661static XML_Bool FASTCALL
6662keyeq(KEY s1, KEY s2)
6663{
6664 for (; *s1 == *s2; s1++, s2++)
6665 if (*s1 == 0)
6666 return XML_TRUE;
6667 return XML_FALSE;
6668}
6669
6670static size_t
6671keylen(KEY s)
6672{
6673 size_t len = 0;
6674 for (; *s; s++, len++);
6675 return len;
6676}
6677
6678static void
6679copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key)
6680{
6681 key->k[0] = 0;
6682 key->k[1] = get_hash_secret_salt(parser);
6683}
6684
6685static unsigned long FASTCALL
6686hash(XML_Parser parser, KEY s)
6687{
6688 struct siphash state;
6689 struct sipkey key;
6690 copy_salt_to_sipkey(parser, &key);
6691 sip24_init(&state, &key);
6692 sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
6693 return (unsigned long)sip24_final(&state);
6694}
6695
6696static NAMED *
6697lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
6698{
6699 size_t i;
6700 if (table->size == 0) {
6701 size_t tsize;
6702 if (!createSize)
6703 return NULL;
6704 table->power = INIT_POWER;
6705 /* table->size is a power of 2 */
6706 table->size = (size_t)1 << INIT_POWER;
6707 tsize = table->size * sizeof(NAMED *);
6708 table->v = (NAMED **)table->mem->malloc_fcn(tsize);
6709 if (!table->v) {
6710 table->size = 0;
6711 return NULL;
6712 }
6713 memset(table->v, 0, tsize);
6714 i = hash(parser, name) & ((unsigned long)table->size - 1);
6715 }
6716 else {
6717 unsigned long h = hash(parser, name);
6718 unsigned long mask = (unsigned long)table->size - 1;
6719 unsigned char step = 0;
6720 i = h & mask;
6721 while (table->v[i]) {
6722 if (keyeq(name, table->v[i]->name))
6723 return table->v[i];
6724 if (!step)
6725 step = PROBE_STEP(h, mask, table->power);
6726 i < step ? (i += table->size - step) : (i -= step);
6727 }
6728 if (!createSize)
6729 return NULL;
6730
6731 /* check for overflow (table is half full) */
6732 if (table->used >> (table->power - 1)) {
6733 unsigned char newPower = table->power + 1;
6734 size_t newSize = (size_t)1 << newPower;
6735 unsigned long newMask = (unsigned long)newSize - 1;
6736 size_t tsize = newSize * sizeof(NAMED *);
6737 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
6738 if (!newV)
6739 return NULL;
6740 memset(newV, 0, tsize);
6741 for (i = 0; i < table->size; i++)
6742 if (table->v[i]) {
6743 unsigned long newHash = hash(parser, table->v[i]->name);
6744 size_t j = newHash & newMask;
6745 step = 0;
6746 while (newV[j]) {
6747 if (!step)
6748 step = PROBE_STEP(newHash, newMask, newPower);
6749 j < step ? (j += newSize - step) : (j -= step);
6750 }
6751 newV[j] = table->v[i];
6752 }
6753 table->mem->free_fcn(table->v);
6754 table->v = newV;
6755 table->power = newPower;
6756 table->size = newSize;
6757 i = h & newMask;
6758 step = 0;
6759 while (table->v[i]) {
6760 if (!step)
6761 step = PROBE_STEP(h, newMask, newPower);
6762 i < step ? (i += newSize - step) : (i -= step);
6763 }
6764 }
6765 }
6766 table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
6767 if (!table->v[i])
6768 return NULL;
6769 memset(table->v[i], 0, createSize);
6770 table->v[i]->name = name;
6771 (table->used)++;
6772 return table->v[i];
6773}
6774
6775static void FASTCALL
6776hashTableClear(HASH_TABLE *table)
6777{
6778 size_t i;
6779 for (i = 0; i < table->size; i++) {
6780 table->mem->free_fcn(table->v[i]);
6781 table->v[i] = NULL;
6782 }
6783 table->used = 0;
6784}
6785
6786static void FASTCALL
6787hashTableDestroy(HASH_TABLE *table)
6788{
6789 size_t i;
6790 for (i = 0; i < table->size; i++)
6791 table->mem->free_fcn(table->v[i]);
6792 table->mem->free_fcn(table->v);
6793}
6794
6795static void FASTCALL
6796hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
6797{
6798 p->power = 0;
6799 p->size = 0;
6800 p->used = 0;
6801 p->v = NULL;
6802 p->mem = ms;
6803}
6804
6805static void FASTCALL
6806hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
6807{
6808 iter->p = table->v;
6809 iter->end = iter->p + table->size;
6810}
6811
6812static NAMED * FASTCALL
6813hashTableIterNext(HASH_TABLE_ITER *iter)
6814{
6815 while (iter->p != iter->end) {
6816 NAMED *tem = *(iter->p)++;
6817 if (tem)
6818 return tem;
6819 }
6820 return NULL;
6821}
6822
6823static void FASTCALL
6824poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
6825{
6826 pool->blocks = NULL;
6827 pool->freeBlocks = NULL;
6828 pool->start = NULL;
6829 pool->ptr = NULL;
6830 pool->end = NULL;
6831 pool->mem = ms;
6832}
6833
6834static void FASTCALL
6835poolClear(STRING_POOL *pool)
6836{
6837 if (!pool->freeBlocks)
6838 pool->freeBlocks = pool->blocks;
6839 else {
6840 BLOCK *p = pool->blocks;
6841 while (p) {
6842 BLOCK *tem = p->next;
6843 p->next = pool->freeBlocks;
6844 pool->freeBlocks = p;
6845 p = tem;
6846 }
6847 }
6848 pool->blocks = NULL;
6849 pool->start = NULL;
6850 pool->ptr = NULL;
6851 pool->end = NULL;
6852}
6853
6854static void FASTCALL
6855poolDestroy(STRING_POOL *pool)
6856{
6857 BLOCK *p = pool->blocks;
6858 while (p) {
6859 BLOCK *tem = p->next;
6860 pool->mem->free_fcn(p);
6861 p = tem;
6862 }
6863 p = pool->freeBlocks;
6864 while (p) {
6865 BLOCK *tem = p->next;
6866 pool->mem->free_fcn(p);
6867 p = tem;
6868 }
6869}
6870
6871static XML_Char *
6872poolAppend(STRING_POOL *pool, const ENCODING *enc,
6873 const char *ptr, const char *end)
6874{
6875 if (!pool->ptr && !poolGrow(pool))
6876 return NULL;
6877 for (;;) {
6878 const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
6879 if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
6880 break;
6881 if (!poolGrow(pool))
6882 return NULL;
6883 }
6884 return pool->start;
6885}
6886
6887static const XML_Char * FASTCALL
6888poolCopyString(STRING_POOL *pool, const XML_Char *s)
6889{
6890 do {
6891 if (!poolAppendChar(pool, *s))
6892 return NULL;
6893 } while (*s++);
6894 s = pool->start;
6895 poolFinish(pool);
6896 return s;
6897}
6898
6899static const XML_Char *
6900poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
6901{
6902 if (!pool->ptr && !poolGrow(pool)) {
6903 /* The following line is unreachable given the current usage of
6904 * poolCopyStringN(). Currently it is called from exactly one
6905 * place to copy the text of a simple general entity. By that
6906 * point, the name of the entity is already stored in the pool, so
6907 * pool->ptr cannot be NULL.
6908 *
6909 * If poolCopyStringN() is used elsewhere as it well might be,
6910 * this line may well become executable again. Regardless, this
6911 * sort of check shouldn't be removed lightly, so we just exclude
6912 * it from the coverage statistics.
6913 */
6914 return NULL; /* LCOV_EXCL_LINE */
6915 }
6916 for (; n > 0; --n, s++) {
6917 if (!poolAppendChar(pool, *s))
6918 return NULL;
6919 }
6920 s = pool->start;
6921 poolFinish(pool);
6922 return s;
6923}
6924
6925static const XML_Char * FASTCALL
6926poolAppendString(STRING_POOL *pool, const XML_Char *s)
6927{
6928 while (*s) {
6929 if (!poolAppendChar(pool, *s))
6930 return NULL;
6931 s++;
6932 }
6933 return pool->start;
6934}
6935
6936static XML_Char *
6937poolStoreString(STRING_POOL *pool, const ENCODING *enc,
6938 const char *ptr, const char *end)
6939{
6940 if (!poolAppend(pool, enc, ptr, end))
6941 return NULL;
6942 if (pool->ptr == pool->end && !poolGrow(pool))
6943 return NULL;
6944 *(pool->ptr)++ = 0;
6945 return pool->start;
6946}
6947
6948static size_t
6949poolBytesToAllocateFor(int blockSize)
6950{
6951 /* Unprotected math would be:
6952 ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
6953 **
6954 ** Detect overflow, avoiding _signed_ overflow undefined behavior
6955 ** For a + b * c we check b * c in isolation first, so that addition of a
6956 ** on top has no chance of making us accept a small non-negative number
6957 */
6958 const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
6959
6960 if (blockSize <= 0)
6961 return 0;
6962
6963 if (blockSize > (int)(INT_MAX / stretch))
6964 return 0;
6965
6966 {
6967 const int stretchedBlockSize = blockSize * (int)stretch;
6968 const int bytesToAllocate = (int)(
6969 offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
6970 if (bytesToAllocate < 0)
6971 return 0;
6972
6973 return (size_t)bytesToAllocate;
6974 }
6975}
6976
6977static XML_Bool FASTCALL
6978poolGrow(STRING_POOL *pool)
6979{
6980 if (pool->freeBlocks) {
6981 if (pool->start == 0) {
6982 pool->blocks = pool->freeBlocks;
6983 pool->freeBlocks = pool->freeBlocks->next;
6984 pool->blocks->next = NULL;
6985 pool->start = pool->blocks->s;
6986 pool->end = pool->start + pool->blocks->size;
6987 pool->ptr = pool->start;
6988 return XML_TRUE;
6989 }
6990 if (pool->end - pool->start < pool->freeBlocks->size) {
6991 BLOCK *tem = pool->freeBlocks->next;
6992 pool->freeBlocks->next = pool->blocks;
6993 pool->blocks = pool->freeBlocks;
6994 pool->freeBlocks = tem;
6995 memcpy(pool->blocks->s, pool->start,
6996 (pool->end - pool->start) * sizeof(XML_Char));
6997 pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
6998 pool->start = pool->blocks->s;
6999 pool->end = pool->start + pool->blocks->size;
7000 return XML_TRUE;
7001 }
7002 }
7003 if (pool->blocks && pool->start == pool->blocks->s) {
7004 BLOCK *temp;
7005 int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
7006 size_t bytesToAllocate;
7007
7008 // NOTE: Needs to be calculated prior to calling `realloc`
7009 // to avoid dangling pointers:
7010 const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start;
7011
7012 if (blockSize < 0) {
7013 /* This condition traps a situation where either more than
7014 * INT_MAX/2 bytes have already been allocated. This isn't
7015 * readily testable, since it is unlikely that an average
7016 * machine will have that much memory, so we exclude it from the
7017 * coverage statistics.
7018 */
7019 return XML_FALSE; /* LCOV_EXCL_LINE */
7020 }
7021
7022 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7023 if (bytesToAllocate == 0)
7024 return XML_FALSE;
7025
7026 temp = (BLOCK *)
7027 pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate);
7028 if (temp == NULL)
7029 return XML_FALSE;
7030 pool->blocks = temp;
7031 pool->blocks->size = blockSize;
7032 pool->ptr = pool->blocks->s + offsetInsideBlock;
7033 pool->start = pool->blocks->s;
7034 pool->end = pool->start + blockSize;
7035 }
7036 else {
7037 BLOCK *tem;
7038 int blockSize = (int)(pool->end - pool->start);
7039 size_t bytesToAllocate;
7040
7041 if (blockSize < 0) {
7042 /* This condition traps a situation where either more than
7043 * INT_MAX bytes have already been allocated (which is prevented
7044 * by various pieces of program logic, not least this one, never
7045 * mind the unlikelihood of actually having that much memory) or
7046 * the pool control fields have been corrupted (which could
7047 * conceivably happen in an extremely buggy user handler
7048 * function). Either way it isn't readily testable, so we
7049 * exclude it from the coverage statistics.
7050 */
7051 return XML_FALSE; /* LCOV_EXCL_LINE */
7052 }
7053
7054 if (blockSize < INIT_BLOCK_SIZE)
7055 blockSize = INIT_BLOCK_SIZE;
7056 else {
7057 /* Detect overflow, avoiding _signed_ overflow undefined behavior */
7058 if ((int)((unsigned)blockSize * 2U) < 0) {
7059 return XML_FALSE;
7060 }
7061 blockSize *= 2;
7062 }
7063
7064 bytesToAllocate = poolBytesToAllocateFor(blockSize);
7065 if (bytesToAllocate == 0)
7066 return XML_FALSE;
7067
7068 tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
7069 if (!tem)
7070 return XML_FALSE;
7071 tem->size = blockSize;
7072 tem->next = pool->blocks;
7073 pool->blocks = tem;
7074 if (pool->ptr != pool->start)
7075 memcpy(tem->s, pool->start,
7076 (pool->ptr - pool->start) * sizeof(XML_Char));
7077 pool->ptr = tem->s + (pool->ptr - pool->start);
7078 pool->start = tem->s;
7079 pool->end = tem->s + blockSize;
7080 }
7081 return XML_TRUE;
7082}
7083
7084static int FASTCALL
7085nextScaffoldPart(XML_Parser parser)
7086{
7087 DTD * const dtd = _dtd; /* save one level of indirection */
7088 CONTENT_SCAFFOLD * me;
7089 int next;
7090
7091 if (!dtd->scaffIndex) {
7092 dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
7093 if (!dtd->scaffIndex)
7094 return -1;
7095 dtd->scaffIndex[0] = 0;
7096 }
7097
7098 if (dtd->scaffCount >= dtd->scaffSize) {
7099 CONTENT_SCAFFOLD *temp;
7100 if (dtd->scaffold) {
7101 temp = (CONTENT_SCAFFOLD *)
7102 REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
7103 if (temp == NULL)
7104 return -1;
7105 dtd->scaffSize *= 2;
7106 }
7107 else {
7108 temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
7109 * sizeof(CONTENT_SCAFFOLD));
7110 if (temp == NULL)
7111 return -1;
7112 dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
7113 }
7114 dtd->scaffold = temp;
7115 }
7116 next = dtd->scaffCount++;
7117 me = &dtd->scaffold[next];
7118 if (dtd->scaffLevel) {
7119 CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
7120 if (parent->lastchild) {
7121 dtd->scaffold[parent->lastchild].nextsib = next;
7122 }
7123 if (!parent->childcnt)
7124 parent->firstchild = next;
7125 parent->lastchild = next;
7126 parent->childcnt++;
7127 }
7128 me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
7129 return next;
7130}
7131
7132static void
7133build_node(XML_Parser parser,
7134 int src_node,
7135 XML_Content *dest,
7136 XML_Content **contpos,
7137 XML_Char **strpos)
7138{
7139 DTD * const dtd = _dtd; /* save one level of indirection */
7140 dest->type = dtd->scaffold[src_node].type;
7141 dest->quant = dtd->scaffold[src_node].quant;
7142 if (dest->type == XML_CTYPE_NAME) {
7143 const XML_Char *src;
7144 dest->name = *strpos;
7145 src = dtd->scaffold[src_node].name;
7146 for (;;) {
7147 *(*strpos)++ = *src;
7148 if (!*src)
7149 break;
7150 src++;
7151 }
7152 dest->numchildren = 0;
7153 dest->children = NULL;
7154 }
7155 else {
7156 unsigned int i;
7157 int cn;
7158 dest->numchildren = dtd->scaffold[src_node].childcnt;
7159 dest->children = *contpos;
7160 *contpos += dest->numchildren;
7161 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
7162 i < dest->numchildren;
7163 i++, cn = dtd->scaffold[cn].nextsib) {
7164 build_node(parser, cn, &(dest->children[i]), contpos, strpos);
7165 }
7166 dest->name = NULL;
7167 }
7168}
7169
7170static XML_Content *
7171build_model (XML_Parser parser)
7172{
7173 DTD * const dtd = _dtd; /* save one level of indirection */
7174 XML_Content *ret;
7175 XML_Content *cpos;
7176 XML_Char * str;
7177 int allocsize = (dtd->scaffCount * sizeof(XML_Content)
7178 + (dtd->contentStringLen * sizeof(XML_Char)));
7179
7180 ret = (XML_Content *)MALLOC(allocsize);
7181 if (!ret)
7182 return NULL;
7183
7184 str = (XML_Char *) (&ret[dtd->scaffCount]);
7185 cpos = &ret[1];
7186
7187 build_node(parser, 0, ret, &cpos, &str);
7188 return ret;
7189}
7190
7191static ELEMENT_TYPE *
7192getElementType(XML_Parser parser,
7193 const ENCODING *enc,
7194 const char *ptr,
7195 const char *end)
7196{
7197 DTD * const dtd = _dtd; /* save one level of indirection */
7198 const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
7199 ELEMENT_TYPE *ret;
7200
7201 if (!name)
7202 return NULL;
7203 ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
7204 if (!ret)
7205 return NULL;
7206 if (ret->name != name)
7207 poolDiscard(&dtd->pool);
7208 else {
7209 poolFinish(&dtd->pool);
7210 if (!setElementTypePrefix(parser, ret))
7211 return NULL;
7212 }
7213 return ret;
7214}
7215
7216static XML_Char *
7217copyString(const XML_Char *s,
7218 const XML_Memory_Handling_Suite *memsuite)
7219{
7220 int charsRequired = 0;
7221 XML_Char *result;
7222
7223 /* First determine how long the string is */
7224 while (s[charsRequired] != 0) {
7225 charsRequired++;
7226 }
7227 /* Include the terminator */
7228 charsRequired++;
7229
7230 /* Now allocate space for the copy */
7231 result = (XML_Char*)memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
7232 if (result == NULL)
7233 return NULL;
7234 /* Copy the original into place */
7235 memcpy(result, s, charsRequired * sizeof(XML_Char));
7236 return result;
7237}
7238