completely different fix for the recursion detection based on entity

* parser.c include/libxml/parser.h: completely different fix for
  the recursion detection based on entity density, big cleanups
  in the entity parsing code too
* result/*.sax*: the parser should not ask for used defined versions
  of the predefined entities
* testrecurse.c: automatic test for entity recursion checks
* Makefile.am: added testrecurse
* test/recurse/lol* test/recurse/good*: a first set of tests for
  the recursion
Daniel

svn path=/trunk/; revision=3783
This commit is contained in:
Daniel Veillard 2008-08-28 15:36:32 +00:00
parent 49d4405a6d
commit 0161e638c6
43 changed files with 2806 additions and 898 deletions

View File

@ -1,3 +1,15 @@
Thu Aug 28 17:31:46 CEST 2008 Daniel Veillard <daniel@veillard.com>
* parser.c include/libxml/parser.h: completely different fix for
the recursion detection based on entity density, big cleanups
in the entity parsing code too
* result/*.sax*: the parser should not ask for used defined versions
of the predefined entities
* testrecurse.c: automatic test for entity recursion checks
* Makefile.am: added testrecurse
* test/recurse/lol* test/recurse/good*: a first set of tests for
the recursion
Wed Aug 27 21:55:34 CEST 2008 Daniel Veillard <daniel@veillard.com>
* include/libxml/xmlerror.h parser.c: a bit of cleanup and

View File

@ -9,7 +9,7 @@ INCLUDES = -I$(top_builddir)/include -I@srcdir@/include @THREAD_CFLAGS@ @Z_CFLAG
noinst_PROGRAMS=testSchemas testRelax testSAX testHTML testXPath testURI \
testThreads testC14N testAutomata testRegexp \
testReader testapi testModule runtest runsuite testchar \
testdict runxmlconf
testdict runxmlconf testrecurse
bin_PROGRAMS = xmllint xmlcatalog
@ -56,6 +56,11 @@ runtest_LDFLAGS =
runtest_DEPENDENCIES = $(DEPS)
runtest_LDADD= @BASE_THREAD_LIBS@ @RDL_LIBS@ $(LDADDS)
testrecurse_SOURCES=testrecurse.c
testrecurse_LDFLAGS =
testrecurse_DEPENDENCIES = $(DEPS)
testrecurse_LDADD= @BASE_THREAD_LIBS@ @RDL_LIBS@ $(LDADDS)
testchar_SOURCES=testchar.c
testchar_LDFLAGS =
testchar_DEPENDENCIES = $(DEPS)

View File

@ -298,6 +298,7 @@ struct _xmlParserCtxt {
xmlError lastError;
xmlParserMode parseMode; /* the parser mode */
unsigned long nbentities; /* number of entities references */
unsigned long sizeentities; /* size of parsed entities */
};
/**

504
parser.c
View File

@ -80,6 +80,96 @@
#include <zlib.h>
#endif
static void
xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
/************************************************************************
* *
* Arbitrary limits set in the parser. See XML_PARSE_HUGE *
* *
************************************************************************/
#define XML_PARSER_BIG_ENTITY 1000
#define XML_PARSER_LOT_ENTITY 5000
/*
* XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
* replacement over the size in byte of the input indicates that you have
* and eponential behaviour. A value of 10 correspond to at least 3 entity
* replacement per byte of input.
*/
#define XML_PARSER_NON_LINEAR 10
/*
* xmlParserEntityCheck
*
* Function to check non-linear entity expansion behaviour
* This is here to detect and stop exponential linear entity expansion
* This is not a limitation of the parser but a safety
* boundary feature. It can be disabled with the XML_PARSE_HUGE
* parser option.
*/
static int
xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size,
xmlEntityPtr ent)
{
int consumed = 0;
if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
return (0);
if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
return (1);
if (size != 0) {
/*
* Do the check based on the replacement size of the entity
*/
if (size < XML_PARSER_BIG_ENTITY)
return(0);
/*
* A limit on the amount of text data reasonably used
*/
if (ctxt->input != NULL) {
consumed = ctxt->input->consumed +
(ctxt->input->cur - ctxt->input->base);
}
consumed += ctxt->sizeentities;
if ((size < XML_PARSER_NON_LINEAR * consumed) &&
(ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
return (0);
} else if (ent != NULL) {
/*
* use the number of parsed entities in the replacement
*/
size = ent->checked;
/*
* The amount of data parsed counting entities size only once
*/
if (ctxt->input != NULL) {
consumed = ctxt->input->consumed +
(ctxt->input->cur - ctxt->input->base);
}
consumed += ctxt->sizeentities;
/*
* Check the density of entities for the amount of data
* knowing an entity reference will take at least 3 bytes
*/
if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
return (0);
} else {
/*
* strange we got no data for checking just return
*/
return (0);
}
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
return (1);
}
/**
* xmlParserMaxDepth:
*
@ -90,11 +180,11 @@
*/
unsigned int xmlParserMaxDepth = 256;
#define SAX2 1
#define SAX2 1
#define XML_PARSER_BIG_BUFFER_SIZE 300
#define XML_PARSER_BUFFER_SIZE 100
#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
/*
@ -2346,9 +2436,10 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
/*
* Macro used to grow the current buffer.
*/
#define growBuffer(buffer) { \
#define growBuffer(buffer, n) { \
xmlChar *tmp; \
buffer##_size *= 2; \
buffer##_size += n; \
tmp = (xmlChar *) \
xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
if (tmp == NULL) goto mem_error; \
@ -2391,8 +2482,9 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
return(NULL);
last = str + len;
if (((ctxt->depth > 20) || (ctxt->nbentities >= 100000)) &&
((ctxt->options & XML_PARSE_HUGE) == 0)) {
if (((ctxt->depth > 40) &&
((ctxt->options & XML_PARSE_HUGE) == 0)) ||
(ctxt->depth > 1024)) {
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
return(NULL);
}
@ -2422,7 +2514,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
COPY_BUF(0,buffer,nbchars,val);
}
if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
}
} else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
if (xmlParserDebugEntities)
@ -2433,7 +2525,6 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
(ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
goto int_error;
ctxt->nbentities++;
if (ent != NULL)
ctxt->nbentities += ent->checked;
if ((ent != NULL) &&
@ -2441,7 +2532,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
if (ent->content != NULL) {
COPY_BUF(0,buffer,nbchars,ent->content[0]);
if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
}
} else {
xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
@ -2452,13 +2543,16 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
0, 0, 0);
ctxt->depth--;
if (rep != NULL) {
current = rep;
while (*current != 0) { /* non input consuming loop */
buffer[nbchars++] = *current++;
if (nbchars >
buffer_size - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
if (xmlParserEntityCheck(ctxt, nbchars, ent))
goto int_error;
growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
}
}
xmlFree(rep);
@ -2470,7 +2564,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
buffer[nbchars++] = '&';
if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
}
for (;i > 0;i--)
buffer[nbchars++] = *cur++;
@ -2483,7 +2577,6 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
ent = xmlParseStringPEReference(ctxt, &str);
if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
goto int_error;
ctxt->nbentities++;
if (ent != NULL)
ctxt->nbentities += ent->checked;
if (ent != NULL) {
@ -2500,7 +2593,9 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
buffer[nbchars++] = *current++;
if (nbchars >
buffer_size - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
if (xmlParserEntityCheck(ctxt, nbchars, ent))
goto int_error;
growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
}
}
xmlFree(rep);
@ -2511,21 +2606,13 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
COPY_BUF(l,buffer,nbchars,c);
str += l;
if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
growBuffer(buffer);
growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
}
}
if (str < last)
c = CUR_SCHAR(str, l);
else
c = 0;
if ((nbchars > 100000) &&
(ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
((ctxt->options & XML_PARSE_HUGE) == 0)) {
xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
"Excessive lenght of attribute: %d use XML_PARSE_HUGE option\n",
nbchars);
goto int_error;
}
}
buffer[nbchars++] = 0;
return(buffer);
@ -3549,7 +3636,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
if (val == '&') {
if (ctxt->replaceEntities) {
if (len > buf_size - 10) {
growBuffer(buf);
growBuffer(buf, 10);
}
buf[len++] = '&';
} else {
@ -3558,7 +3645,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
* called by the attribute() function in SAX.c
*/
if (len > buf_size - 10) {
growBuffer(buf);
growBuffer(buf, 10);
}
buf[len++] = '&';
buf[len++] = '#';
@ -3568,19 +3655,16 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
}
} else if (val != 0) {
if (len > buf_size - 10) {
growBuffer(buf);
growBuffer(buf, 10);
}
len += xmlCopyChar(0, &buf[len], val);
}
} else {
ent = xmlParseEntityRef(ctxt);
ctxt->nbentities++;
if (ent != NULL)
ctxt->nbentities += ent->checked;
if ((ent != NULL) &&
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
if (len > buf_size - 10) {
growBuffer(buf);
growBuffer(buf, 10);
}
if ((ctxt->replaceEntities == 0) &&
(ent->content[0] == '&')) {
@ -3603,7 +3687,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
while (*current != 0) { /* non input consuming */
buf[len++] = *current++;
if (len > buf_size - 10) {
growBuffer(buf);
growBuffer(buf, 10);
}
}
xmlFree(rep);
@ -3611,7 +3695,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
}
} else {
if (len > buf_size - 10) {
growBuffer(buf);
growBuffer(buf, 10);
}
if (ent->content != NULL)
buf[len++] = ent->content[0];
@ -3638,8 +3722,8 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
* Just output the reference
*/
buf[len++] = '&';
if (len > buf_size - i - 10) {
growBuffer(buf);
while (len > buf_size - i - 10) {
growBuffer(buf, i + 10);
}
for (;i > 0;i--)
buf[len++] = *cur++;
@ -3651,8 +3735,8 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
if ((len != 0) || (!normalize)) {
if ((!normalize) || (!in_space)) {
COPY_BUF(l,buf,len,0x20);
if (len > buf_size - 10) {
growBuffer(buf);
while (len > buf_size - 10) {
growBuffer(buf, 10);
}
}
in_space = 1;
@ -3661,20 +3745,13 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
in_space = 0;
COPY_BUF(l,buf,len,c);
if (len > buf_size - 10) {
growBuffer(buf);
growBuffer(buf, 10);
}
}
NEXTL(l);
}
GROW;
c = CUR_CHAR(l);
if ((len > 100000) &&
((ctxt->options & XML_PARSE_HUGE) == 0)) {
xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
"Excessive lenght of attribute: %d use XML_PARSE_HUGE option\n",
len);
goto int_error;
}
}
if ((in_space) && (normalize)) {
while (buf[len - 1] == 0x20) len--;
@ -4887,7 +4964,6 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
int isParameter = 0;
xmlChar *orig = NULL;
int skipped;
unsigned long oldnbent = ctxt->nbentities;
/* GROW; done in the caller */
if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
@ -5112,7 +5188,6 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
}
}
if (cur != NULL) {
cur->checked = ctxt->nbentities - oldnbent;
if (cur->orig != NULL)
xmlFree(orig);
else
@ -6521,8 +6596,17 @@ void
xmlParseReference(xmlParserCtxtPtr ctxt) {
xmlEntityPtr ent;
xmlChar *val;
if (RAW != '&') return;
int was_checked;
xmlNodePtr list = NULL;
xmlParserErrors ret = XML_ERR_OK;
if (RAW != '&')
return;
/*
* Simple case of a CharRef
*/
if (NXT(1) == '#') {
int i = 0;
xmlChar out[10];
@ -6562,25 +6646,31 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
(!ctxt->disableSAX))
ctxt->sax->characters(ctxt->userData, out, i);
}
} else {
int was_checked;
return;
}
/*
* We are seeing an entity reference
*/
ent = xmlParseEntityRef(ctxt);
if (ent == NULL) return;
if (!ctxt->wellFormed)
return;
ctxt->nbentities++;
if ((ctxt->nbentities >= 100000) &&
((ctxt->options & XML_PARSE_HUGE) == 0)) {
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
was_checked = ent->checked;
/* special case of predefined entities */
if ((ent->name == NULL) ||
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
val = ent->content;
if (val == NULL) return;
/*
* inline the entity.
*/
if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
return;
}
was_checked = ent->checked;
if ((ent->name != NULL) &&
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
xmlNodePtr list = NULL;
xmlParserErrors ret = XML_ERR_OK;
/*
* The first reference to the entity trigger a parsing phase
@ -6588,94 +6678,59 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
* the parsing.
*/
if (ent->checked == 0) {
xmlChar *value;
value = ent->content;
/*
* Check that this entity is well formed
*/
if ((value != NULL) && (value[0] != 0) &&
(value[1] == 0) && (value[0] == '<') &&
(xmlStrEqual(ent->name, BAD_CAST "lt"))) {
/*
* DONE: get definite answer on this !!!
* Lots of entity decls are used to declare a single
* char
* <!ENTITY lt "<">
* Which seems to be valid since
* 2.4: The ampersand character (&) and the left angle
* bracket (<) may appear in their literal form only
* when used ... They are also legal within the literal
* entity value of an internal entity declaration;i
* see "4.3.2 Well-Formed Parsed Entities".
* IMHO 2.4 and 4.3.2 are directly in contradiction.
* Looking at the OASIS test suite and James Clark
* tests, this is broken. However the XML REC uses
* it. Is the XML REC not well-formed ????
* This is a hack to avoid this problem
*
* ANSWER: since lt gt amp .. are already defined,
* this is a redefinition and hence the fact that the
* content is not well balanced is not a Wf error, this
* is lousy but acceptable.
*/
list = xmlNewDocText(ctxt->myDoc, value);
if (list != NULL) {
if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) &&
(ent->children == NULL)) {
ent->children = list;
ent->last = list;
ent->owner = 1;
list->parent = (xmlNodePtr) ent;
} else {
xmlFreeNodeList(list);
}
} else if (list != NULL) {
xmlFreeNodeList(list);
}
} else {
unsigned long oldnbent = ctxt->nbentities;
/*
* 4.3.2: An internal general parsed entity is well-formed
* if its replacement text matches the production labeled
* content.
*/
void *user_data;
/*
* This is a bit hackish but this seems the best
* way to make sure both SAX and DOM entity support
* behaves okay.
*/
void *user_data;
if (ctxt->userData == ctxt)
user_data = NULL;
else
user_data = ctxt->userData;
/*
* Check that this entity is well formed
* 4.3.2: An internal general parsed entity is well-formed
* if its replacement text matches the production labeled
* content.
*/
if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
ctxt->depth++;
ret = xmlParseBalancedChunkMemoryInternal(ctxt,
value, user_data, &list);
ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
user_data, &list);
ctxt->depth--;
} else if (ent->etype ==
XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
} else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
ctxt->depth++;
ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
ctxt->sax, user_data, ctxt->depth,
ent->URI, ent->ExternalID, &list);
ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
user_data, ctxt->depth, ent->URI,
ent->ExternalID, &list);
ctxt->depth--;
} else {
ret = XML_ERR_ENTITY_PE_INTERNAL;
xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
"invalid entity type found\n", NULL);
}
/*
* Store the number of entities needing parsing for this entity
* content and do checkings
*/
ent->checked = ctxt->nbentities - oldnbent;
if (ret == XML_ERR_ENTITY_LOOP) {
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
xmlFreeNodeList(list);
return;
} else if ((ret == XML_ERR_OK) && (list != NULL)) {
}
if (xmlParserEntityCheck(ctxt, 0, ent)) {
xmlFreeNodeList(list);
return;
}
if ((ret == XML_ERR_OK) && (list != NULL)) {
if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
(ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
(ent->children == NULL)) {
@ -6727,12 +6782,17 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
xmlFreeNodeList(list);
list = NULL;
}
}
if (ent->checked == 0)
ent->checked = 1;
}
} else if (ent->checked != 1) {
ctxt->nbentities += ent->checked;
}
/*
* Now that the entity content has been gathered
* provide it to the application, this can take different forms based
* on the parsing modes.
*/
if (ent->children == NULL) {
/*
* Probably running in SAX mode and the callbacks don't
@ -6784,6 +6844,10 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
}
return;
}
/*
* If we didn't get any children for the entity being built
*/
if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
(ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
/*
@ -6792,6 +6856,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
ctxt->sax->reference(ctxt->userData, ent->name);
return;
}
if ((ctxt->replaceEntities) || (ent->children == NULL)) {
/*
* There is a problem on the handling of _private for entities
@ -6918,17 +6983,6 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
return;
}
}
} else {
val = ent->content;
if (val == NULL) return;
/*
* inline the entity.
*/
if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
(!ctxt->disableSAX))
ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
}
}
}
/**
@ -6966,24 +7020,40 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
GROW;
if (RAW == '&') {
if (RAW != '&')
return(NULL);
NEXT;
name = xmlParseName(ctxt);
if (name == NULL) {
xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
"xmlParseEntityRef: no name\n");
} else {
if (RAW == ';') {
return(NULL);
}
if (RAW != ';') {
xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
return(NULL);
}
NEXT;
/*
* Predefined entites override any extra definition
*/
ent = xmlGetPredefinedEntity(name);
if (ent != NULL)
return(ent);
/*
* Increate the number of entity references parsed
*/
ctxt->nbentities++;
/*
* Ask first SAX for entity resolution, otherwise try the
* predefined set.
* entities which may have stored in the parser context.
*/
if (ctxt->sax != NULL) {
if (ctxt->sax->getEntity != NULL)
ent = ctxt->sax->getEntity(ctxt->userData, name);
if ((ctxt->wellFormed == 1 ) && (ent == NULL))
ent = xmlGetPredefinedEntity(name);
if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
(ctxt->userData==ctxt)) {
ent = xmlSAX2GetEntity(ctxt, name);
@ -7055,9 +7125,7 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
* not contain a <.
*/
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
(ent != NULL) &&
(!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
(ent->content != NULL) &&
(ent != NULL) && (ent->content != NULL) &&
(xmlStrchr(ent->content, '<'))) {
xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
"'<' in entity '%s' is not allowed in attributes values\n", name);
@ -7085,12 +7153,6 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
* to itself, either directly or indirectly.
* Done somewhere else
*/
} else {
xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
}
}
}
return(ent);
}
@ -7136,29 +7198,50 @@ xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
return(NULL);
ptr = *str;
cur = *ptr;
if (cur == '&') {
if (cur != '&')
return(NULL);
ptr++;
cur = *ptr;
name = xmlParseStringName(ctxt, &ptr);
if (name == NULL) {
xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
"xmlParseStringEntityRef: no name\n");
} else {
if (*ptr == ';') {
*str = ptr;
return(NULL);
}
if (*ptr != ';') {
xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
*str = ptr;
return(NULL);
}
ptr++;
/*
* Predefined entites override any extra definition
*/
ent = xmlGetPredefinedEntity(name);
if (ent != NULL)
return(ent);
/*
* Increate the number of entity references parsed
*/
ctxt->nbentities++;
/*
* Ask first SAX for entity resolution, otherwise try the
* predefined set.
* entities which may have stored in the parser context.
*/
if (ctxt->sax != NULL) {
if (ctxt->sax->getEntity != NULL)
ent = ctxt->sax->getEntity(ctxt->userData, name);
if (ent == NULL)
ent = xmlGetPredefinedEntity(name);
if ((ent == NULL) && (ctxt->userData==ctxt)) {
ent = xmlSAX2GetEntity(ctxt, name);
}
}
/*
* [ WFC: Entity Declared ]
* In a document without any DTD, a document with only an
@ -7221,9 +7304,7 @@ xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
* not contain a <.
*/
else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
(ent != NULL) &&
(!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
(ent->content != NULL) &&
(ent != NULL) && (ent->content != NULL) &&
(xmlStrchr(ent->content, '<'))) {
xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
"'<' in entity '%s' is not allowed in attributes values\n",
@ -7253,12 +7334,7 @@ xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
* Done somewhere else
*/
} else {
xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
}
xmlFree(name);
}
}
*str = ptr;
return(ent);
}
@ -7299,15 +7375,30 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
xmlEntityPtr entity = NULL;
xmlParserInputPtr input;
if (RAW == '%') {
if (RAW != '%')
return;
NEXT;
name = xmlParseName(ctxt);
if (name == NULL) {
xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
"xmlParsePEReference: no name\n");
} else {
if (RAW == ';') {
return;
}
if (RAW != ';') {
xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
return;
}
NEXT;
/*
* Increate the number of entity references parsed
*/
ctxt->nbentities++;
/*
* Request the entity from SAX
*/
if ((ctxt->sax != NULL) &&
(ctxt->sax->getParameterEntity != NULL))
entity = ctxt->sax->getParameterEntity(ctxt->userData,
@ -7350,8 +7441,7 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
"Internal: %%%s; is not a parameter entity\n",
name, NULL);
} else if (ctxt->input->free != deallocblankswrapper) {
input =
xmlNewBlanksWrapperInputStream(ctxt, entity);
input = xmlNewBlanksWrapperInputStream(ctxt, entity);
if (xmlPushInput(ctxt, input) < 0)
return;
} else {
@ -7380,11 +7470,6 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
}
}
ctxt->hasPErefs = 1;
} else {
xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
}
}
}
}
/**
@ -7512,18 +7597,34 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
if ((str == NULL) || (*str == NULL)) return(NULL);
ptr = *str;
cur = *ptr;
if (cur == '%') {
if (cur != '%')
return(NULL);
ptr++;
cur = *ptr;
name = xmlParseStringName(ctxt, &ptr);
if (name == NULL) {
xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
"xmlParseStringPEReference: no name\n");
} else {
*str = ptr;
return(NULL);
}
cur = *ptr;
if (cur == ';') {
if (cur != ';') {
xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
xmlFree(name);
*str = ptr;
return(NULL);
}
ptr++;
cur = *ptr;
/*
* Increate the number of entity references parsed
*/
ctxt->nbentities++;
/*
* Request the entity from SAX
*/
if ((ctxt->sax != NULL) &&
(ctxt->sax->getParameterEntity != NULL))
entity = ctxt->sax->getParameterEntity(ctxt->userData,
@ -7538,8 +7639,7 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
* any reference to it...
*/
if ((ctxt->standalone == 1) ||
((ctxt->hasExternalSubset == 0) &&
(ctxt->hasPErefs == 0))) {
((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
"PEReference: %%%s; not found\n", name);
} else {
@ -7567,12 +7667,7 @@ xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
}
}
ctxt->hasPErefs = 1;
} else {
xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
}
xmlFree(name);
}
}
*str = ptr;
return(entity);
}
@ -11920,8 +12015,8 @@ xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
if (ctx == NULL) return(-1);
if (((ctx->depth > 20) || (ctx->nbentities >= 100000)) &&
((ctx->options & XML_PARSE_HUGE) == 0)) {
if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) ||
(ctx->depth > 1024)) {
return(XML_ERR_ENTITY_LOOP);
}
@ -12131,9 +12226,9 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
xmlChar start[4];
xmlCharEncoding enc;
if (((depth > 20) ||
((oldctxt != NULL) && (oldctxt->nbentities >= 100000))) &&
((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) {
if (((depth > 40) &&
((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
(depth > 1024)) {
return(XML_ERR_ENTITY_LOOP);
}
@ -12270,12 +12365,30 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
}
ret = XML_ERR_OK;
}
/*
* Record in the parent context the number of entities replacement
* done when parsing that reference.
*/
oldctxt->nbentities += ctxt->nbentities;
/*
* Also record the size of the entity parsed
*/
if (ctxt->input != NULL) {
oldctxt->sizeentities += ctxt->input->consumed;
oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
}
/*
* And record the last error if any
*/
if (ctxt->lastError.code != XML_ERR_OK)
xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
if (sax != NULL)
ctxt->sax = oldsax;
oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
oldctxt->node_seq.length = ctxt->node_seq.length;
oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
oldctxt->nbentities += ctxt->nbentities;
ctxt->node_seq.maximum = 0;
ctxt->node_seq.length = 0;
ctxt->node_seq.buffer = NULL;
@ -12376,8 +12489,8 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
int size;
xmlParserErrors ret = XML_ERR_OK;
if (((oldctxt->depth > 20) || (oldctxt->nbentities >= 100000)) &&
((oldctxt->options & XML_PARSE_HUGE) == 0)) {
if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
(oldctxt->depth > 1024)) {
return(XML_ERR_ENTITY_LOOP);
}
@ -12502,7 +12615,17 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
ctxt->myDoc->last = last;
}
/*
* Record in the parent context the number of entities replacement
* done when parsing that reference.
*/
oldctxt->nbentities += ctxt->nbentities;
/*
* Also record the last error if any
*/
if (ctxt->lastError.code != XML_ERR_OK)
xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
ctxt->sax = oldsax;
ctxt->dict = NULL;
ctxt->attsDefault = NULL;
@ -12756,7 +12879,7 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
int size;
int ret = 0;
if (depth > 20) {
if (depth > 40) {
return(XML_ERR_ENTITY_LOOP);
}
@ -13820,6 +13943,7 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
ctxt->charset = XML_CHAR_ENCODING_UTF8;
ctxt->catalogs = NULL;
ctxt->nbentities = 0;
ctxt->sizeentities = 0;
xmlInitNodeInfoSeq(&ctxt->node_seq);
if (ctxt->attsDefault != NULL) {

View File

@ -29,52 +29,42 @@ SAX.startElement(norm, attr='foobar ')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(norm, attr=' &#38; ')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(norm, attr=' foo&#38;bar ')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(norm, attr=' foobar&#38;')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(norm, attr='&#38;foo bar ')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(norm, attr='foobar &#38;')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(norm, attr=' < ')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(norm, attr=' foo<bar ')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(norm, attr=' foobar<')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(norm, attr='<foo bar ')
SAX.endElement(norm)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(norm, attr='foobar <')
SAX.endElement(norm)
SAX.characters(
@ -107,52 +97,42 @@ SAX.startElement(normId, attr='foobar ')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(normId, attr=' &#38; ')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(normId, attr=' foo&#38;bar ')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(normId, attr=' foobar&#38;')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(normId, attr='&#38;foo bar ')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(normId, attr='foobar &#38;')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(normId, attr=' < ')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(normId, attr=' foo<bar ')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(normId, attr=' foobar<')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(normId, attr='<foo bar ')
SAX.endElement(normId)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElement(normId, attr='foobar <')
SAX.endElement(normId)
SAX.characters(

View File

@ -29,52 +29,42 @@ SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr='foob...', 8)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr=' &#3...', 7)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr=' f...', 17)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr=' fo...', 13)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr='&#38...', 13)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr='foob...', 13)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr=' < ...', 3)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr=' f...', 13)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr=' fo...', 9)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr='<foo...', 9)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(norm, NULL, NULL, 0, 1, 0, attr='foob...', 9)
SAX.endElementNs(norm, NULL, NULL)
SAX.characters(
@ -108,52 +98,42 @@ SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='foob...', 6)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='&#38...', 5)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='foo&...', 11)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='foob...', 11)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='&#38...', 12)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='foob...', 12)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='<...', 1)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='foo<...', 7)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='foob...', 7)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='<foo...', 8)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(
, 3)
SAX.getEntity(lt)
SAX.startElementNs(normId, NULL, NULL, 0, 1, 0, attr='foob...', 8)
SAX.endElementNs(normId, NULL, NULL)
SAX.characters(

View File

@ -6,10 +6,8 @@ SAX.characters(
SAX.startElement(cat:ReferencedOrder)
SAX.characters(
, 7)
SAX.getEntity(gt)
SAX.startElement(cat:SellersOrderID, schemeID='pvalue->ReferencedOrder.SellersOrderID.schemeID', schemeAgencyID='pvalue->ReferencedOrder.SellersOrderID.schemeAgencyID', schemeVersionID='pvalue->ReferencedOrder.SellersOrderID.schemeVersionID', schemeAgencySchemeID='pvalue->ReferencedOrder.SellersOrderID.schemeAgencySchemeID', schemeAgencySchemeAgencyID='pvalue->ReferencedOrder.SellersOrderID.schemeAgencySchemeAgencyID', schemeDataURI='pvalue->ReferencedOrder.SellersOrderID.schemeDataURI', schemeURI='pvalue->ReferencedOrder.SellersOrderID.schemeURI', UID='pvalue->ReferencedOrder.SellersOrderID.UID', UIDRef='pvalue->ReferencedOrder.SellersOrderID.UIDRef', UIDRefs='pvalue->ReferencedOrder.SellersOrderID.UIDRefs0', language='pvalue->ReferencedOrder.SellersOrderID.language')
SAX.characters(pvalue-, 7)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.characters(ReferencedOrder.SellersOrderID, 30)
SAX.endElement(cat:SellersOrderID)

View File

@ -6,10 +6,8 @@ SAX.characters(
SAX.startElementNs(ReferencedOrder, cat, 'urn:oasis:names:tc:ubl:CommonAggregateTypes:1.0:0.70', 0, 0, 0)
SAX.characters(
, 7)
SAX.getEntity(gt)
SAX.startElementNs(SellersOrderID, cat, 'urn:oasis:names:tc:ubl:CommonAggregateTypes:1.0:0.70', 0, 11, 0, schemeID='pval...', 47, schemeAgencyID='pval...', 53, schemeVersionID='pval...', 54, schemeAgencySchemeID='pval...', 59, schemeAgencySchemeAgencyID='pval...', 65, schemeDataURI='pval...', 52, schemeURI='pval...', 48, UID='pval...', 42, UIDRef='pval...', 45, UIDRefs='pval...', 47, language='pval...', 47)
SAX.characters(pvalue-, 7)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.characters(ReferencedOrder.SellersOrderID, 30)
SAX.endElementNs(SellersOrderID, cat, 'urn:oasis:names:tc:ubl:CommonAggregateTypes:1.0:0.70')

View File

@ -3,10 +3,8 @@ SAX.startDocument()
SAX.startElement(ino:response, xmlns:ino='http://namespaces.softwareag.com/tamino/response2', xmlns:xql='http://metalab.unc.edu/xql/', ino:sessionid='556', ino:sessionkey='1590469677')
SAX.startElement(xql:query)
SAX.characters(/bsk:DocPart[@docId=, 20)
SAX.getEntity(apos)
SAX.characters(', 1)
SAX.characters(20040308152601345236, 20)
SAX.getEntity(apos)
SAX.characters(', 1)
SAX.characters( and @docPartNo=1], 18)
SAX.endElement(xql:query)

View File

@ -3,10 +3,8 @@ SAX.startDocument()
SAX.startElementNs(response, ino, 'http://namespaces.softwareag.com/tamino/response2', 2, xmlns:ino='http://namespaces.softwareag.com/tamino/response2', xmlns:xql='http://metalab.unc.edu/xql/', 2, 0, ino:sessionid='556"...', 3, ino:sessionkey='1590...', 10)
SAX.startElementNs(query, xql, 'http://metalab.unc.edu/xql/', 0, 0, 0)
SAX.characters(/bsk:DocPart[@docId=, 20)
SAX.getEntity(apos)
SAX.characters(', 1)
SAX.characters(20040308152601345236, 20)
SAX.getEntity(apos)
SAX.characters(', 1)
SAX.characters( and @docPartNo=1], 18)
SAX.endElementNs(query, xql, 'http://metalab.unc.edu/xql/')

View File

@ -1,6 +1,5 @@
SAX.setDocumentLocator()
SAX.startDocument()
SAX.getEntity(apos)
SAX.startElement(item, title='Icrontic.com - Warning: Breakdancing midget with tourette's syndrome on-board                                                ', url='http://www.icrontic.com/', first_time='985034339', last_time='985034339', visits='1')
SAX.endElement(item)
SAX.endDocument()

View File

@ -1,6 +1,5 @@
SAX.setDocumentLocator()
SAX.startDocument()
SAX.getEntity(apos)
SAX.startElementNs(item, NULL, NULL, 0, 5, 0, title='Icro...', 173, url='http...', 24, first_time='9850...', 9, last_time='9850...', 9, visits='1"/>...', 1)
SAX.endElementNs(item, NULL, NULL)
SAX.endDocument()

View File

@ -7,7 +7,6 @@ SAX.startElement(test)
SAX.pcdata(
<![CDATA[abc], 18)
SAX.characters(], 1)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.pcdata(
, 3)

View File

@ -7,7 +7,6 @@ SAX.startElementNs(test, NULL, NULL, 0, 0, 0)
SAX.pcdata(
<![CDATA[abc], 18)
SAX.characters(], 1)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.pcdata(
, 3)

View File

@ -4,7 +4,6 @@ SAX.internalSubset(EXAMPLE, , example.dtd)
SAX.entityDecl(xml, 1, (null), (null), Extensible Markup Language)
SAX.getEntity(xml)
SAX.externalSubset(EXAMPLE, , example.dtd)
SAX.getEntity(amp)
SAX.getEntity(xml)
SAX.startElement(EXAMPLE, prop1='a&#38;b', prop2='&xml;')
SAX.characters(

View File

@ -4,7 +4,6 @@ SAX.internalSubset(EXAMPLE, , example.dtd)
SAX.entityDecl(xml, 1, (null), (null), Extensible Markup Language)
SAX.getEntity(xml)
SAX.externalSubset(EXAMPLE, , example.dtd)
SAX.getEntity(amp)
SAX.getEntity(xml)
SAX.startElementNs(EXAMPLE, NULL, NULL, 0, 2, 0, prop1='a&#3...', 7, prop2='&xml...', 5)
SAX.characters(

View File

@ -7,10 +7,8 @@ SAX.externalSubset(EXAMPLE, , example.dtd)
SAX.startElement(EXAMPLE)
SAX.characters(
Test of , 11)
SAX.getEntity(amp)
SAX.characters(&, 1)
SAX.characters(amp; behaviour a, 16)
SAX.getEntity(amp)
SAX.characters(&, 1)
SAX.characters(b .
, 4)

View File

@ -7,10 +7,8 @@ SAX.externalSubset(EXAMPLE, , example.dtd)
SAX.startElementNs(EXAMPLE, NULL, NULL, 0, 0, 0)
SAX.characters(
Test of , 11)
SAX.getEntity(amp)
SAX.characters(&, 1)
SAX.characters(amp; behaviour a, 16)
SAX.getEntity(amp)
SAX.characters(&, 1)
SAX.characters(b .
, 4)

View File

@ -18,9 +18,7 @@ SAX.endElement(Content)
SAX.characters(
, 4)
SAX.startElement(Content)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.endElement(Content)
SAX.characters(

View File

@ -18,9 +18,7 @@ SAX.endElementNs(Content, NULL, NULL)
SAX.characters(
, 4)
SAX.startElementNs(Content, NULL, NULL, 0, 0, 0)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.endElementNs(Content, NULL, NULL)
SAX.characters(

View File

@ -20,7 +20,6 @@ SAX.characters(©, 2)
SAX.characters( 1947 , 6)
SAX.characters(É, 2)
SAX.characters(ditions Gallimard. , 19)
SAX.getEntity(amp)
SAX.characters(&, 1)
SAX.characters(rights;, 7)
SAX.endElement(eg)

View File

@ -20,7 +20,6 @@ SAX.characters(©, 2)
SAX.characters( 1947 , 6)
SAX.characters(É, 2)
SAX.characters(ditions Gallimard. , 19)
SAX.getEntity(amp)
SAX.characters(&, 1)
SAX.characters(rights;, 7)
SAX.endElementNs(eg, NULL, NULL)

View File

@ -41,7 +41,6 @@ SAX.characters(
SAX.startElement(USES)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElement(STATEMENT, action='read&#38;write', purp='0', recpnt='0', id='1')
SAX.characters(
, 5)

View File

@ -42,7 +42,6 @@ SAX.characters(
SAX.startElementNs(USES, NULL, NULL, 0, 0, 0)
SAX.characters(
, 3)
SAX.getEntity(amp)
SAX.startElementNs(STATEMENT, NULL, NULL, 0, 4, 0, action='read...', 14, purp='0" r...', 1, recpnt='0" i...', 1, id='1">
...', 1)
SAX.characters(

View File

@ -43,10 +43,8 @@ SAX.characters(
, 5)
SAX.startElement(RPM:Packager)
SAX.characters(Red Hat Software , 17)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters(bugs@redhat.com, 15)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.endElement(RPM:Packager)
SAX.characters(
@ -73,10 +71,8 @@ SAX.characters(
, 5)
SAX.startElement(RPM:Changelog)
SAX.characters(* Sun May 10 1998 Prospector S, 36)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters(bugs@redhat.com, 15)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.characters(
- translations modified for, 42)

View File

@ -43,10 +43,8 @@ SAX.characters(
, 5)
SAX.startElementNs(Packager, RPM, 'http://www.rpm.org/', 0, 0, 0)
SAX.characters(Red Hat Software , 17)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters(bugs@redhat.com, 15)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.endElementNs(Packager, RPM, 'http://www.rpm.org/')
SAX.characters(
@ -73,10 +71,8 @@ SAX.characters(
, 5)
SAX.startElementNs(Changelog, RPM, 'http://www.rpm.org/', 0, 0, 0)
SAX.characters(* Sun May 10 1998 Prospector S, 36)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters(bugs@redhat.com, 15)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.characters(
- translations modified for, 42)

View File

@ -43,16 +43,12 @@ SAX.characters(
, 5)
SAX.startElement(RPM:Packager)
SAX.characters(Till Bubeck , 12)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters(bubeck@delix.de, 15)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.characters(, Ngo Than , 11)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters(than@delix.de, 13)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.endElement(RPM:Packager)
SAX.characters(
@ -75,10 +71,8 @@ Routinen zur Ansteuerung, 57)
SAX.characters(ü, 2)
SAX.characters(gung, die
speziell optimiert s, 57)
SAX.getEntity(apos)
SAX.characters(', 1)
SAX.characters(new curses, 10)
SAX.getEntity(apos)
SAX.characters(', 1)
SAX.characters( (ncurses) Variante und ist de, 51)
SAX.characters(ü, 2)

View File

@ -43,16 +43,12 @@ SAX.characters(
, 5)
SAX.startElementNs(Packager, RPM, 'http://www.rpm.org/', 0, 0, 0)
SAX.characters(Till Bubeck , 12)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters(bubeck@delix.de, 15)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.characters(, Ngo Than , 11)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters(than@delix.de, 13)
SAX.getEntity(gt)
SAX.characters(>, 1)
SAX.endElementNs(Packager, RPM, 'http://www.rpm.org/')
SAX.characters(
@ -75,10 +71,8 @@ Routinen zur Ansteuerung, 57)
SAX.characters(ü, 2)
SAX.characters(gung, die
speziell optimiert s, 57)
SAX.getEntity(apos)
SAX.characters(', 1)
SAX.characters(new curses, 10)
SAX.getEntity(apos)
SAX.characters(', 1)
SAX.characters( (ncurses) Variante und ist de, 51)
SAX.characters(ü, 2)

View File

@ -23,7 +23,6 @@ SAX.characters(
SAX.startElement(script, type='text/javascript')
SAX.characters(
... unescaped script , 24)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters( content ...
, 15)

View File

@ -23,7 +23,6 @@ SAX.characters(
SAX.startElementNs(script, NULL, NULL, 0, 1, 0, type='text...', 15)
SAX.characters(
... unescaped script , 24)
SAX.getEntity(lt)
SAX.characters(<, 1)
SAX.characters( content ...
, 15)

View File

@ -15,7 +15,6 @@ SAX.characters() may be escaped
numerically , 31)
SAX.characters(&, 1)
SAX.characters(#38;) or with a general entity, 34)
SAX.getEntity(amp)
SAX.characters(&, 1)
SAX.characters(amp;)., 6)
SAX.endElement(p)

View File

@ -15,7 +15,6 @@ SAX.characters() may be escaped
numerically , 31)
SAX.characters(&, 1)
SAX.characters(#38;) or with a general entity, 34)
SAX.getEntity(amp)
SAX.characters(&, 1)
SAX.characters(amp;)., 6)
SAX.endElementNs(p, NULL, NULL)

343
test/recurse/good.xml Normal file
View File

@ -0,0 +1,343 @@
<!DOCTYPE foo [
<!ENTITY f "some internal data">
<!ENTITY e "&f;&f;">
<!ENTITY d "&e;&e;">
]>
<foo>&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;</foo>

343
test/recurse/goodattr.xml Normal file
View File

@ -0,0 +1,343 @@
<!DOCTYPE foo [
<!ENTITY f "some internal data rather large taking quite some room">
<!ENTITY e "&f;&f;">
<!ENTITY d "&e;&e;">
]>
<foo bar="&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;
&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;"/>

23
test/recurse/lol1.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0"?>
<!DOCTYPE billion [
<!ELEMENT billion (#PCDATA)>
<!ENTITY laugh0 "ha">
<!ENTITY laugh1 "&laugh0;&laugh0;">
<!ENTITY laugh2 "&laugh1;&laugh1;">
<!ENTITY laugh3 "&laugh2;&laugh2;">
<!ENTITY laugh4 "&laugh3;&laugh3;">
<!ENTITY laugh5 "&laugh4;&laugh4;">
<!ENTITY laugh6 "&laugh5;&laugh5;">
<!ENTITY laugh7 "&laugh6;&laugh6;">
<!ENTITY laugh8 "&laugh7;&laugh7;">
<!ENTITY laugh9 "&laugh8;&laugh8;">
<!ENTITY laugh10 "&laugh9;&laugh9;">
<!ENTITY laugh11
"&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;">
<!ENTITY laugh12
"&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;">
<!ENTITY laugh13
"&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;">
]>
<billion>&laugh13;</billion>

23
test/recurse/lol2.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0"?>
<!DOCTYPE billion [
<!ELEMENT billion (#PCDATA)>
<!ENTITY laugh0 "ha">
<!ENTITY laugh1 "&laugh0;&laugh0;">
<!ENTITY laugh2 "&laugh1;&laugh1;">
<!ENTITY laugh3 "&laugh2;&laugh2;">
<!ENTITY laugh4 "&laugh3;&laugh3;">
<!ENTITY laugh5 "&laugh4;&laugh4;">
<!ENTITY laugh6 "&laugh5;&laugh5;">
<!ENTITY laugh7 "&laugh6;&laugh6;">
<!ENTITY laugh8 "&laugh7;&laugh7;">
<!ENTITY laugh9 "&laugh8;&laugh8;">
<!ENTITY laugh10 "&laugh9;&laugh9;">
<!ENTITY laugh11
"&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;&laugh10;">
<!ENTITY laugh12
"&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;&laugh11;">
<!ENTITY laugh13
"&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;&laugh12;">
]>
<billion location="&laugh13;">text</billion>

20
test/recurse/lol3.dtd Normal file
View File

@ -0,0 +1,20 @@
<!ELEMENT billion (#PCDATA)>
<!ENTITY % laugh0 "<!-- Ha ! -->">
<!ENTITY % laugh1 "%laugh0;%laugh0;">
<!ENTITY % laugh2 "%laugh1;%laugh1;">
<!ENTITY % laugh3 "%laugh2;%laugh2;">
<!ENTITY % laugh4 "%laugh3;%laugh3;">
<!ENTITY % laugh5 "%laugh4;%laugh4;">
<!ENTITY % laugh6 "%laugh5;%laugh5;">
<!ENTITY % laugh7 "%laugh6;%laugh6;">
<!ENTITY % laugh8 "%laugh7;%laugh7;">
<!ENTITY % laugh9 "%laugh8;%laugh8;">
<!ENTITY % laugh10 "%laugh9;%laugh9;">
<!ENTITY % laugh11
"%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;%laugh10;">
<!ENTITY % laugh12
"%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;%laugh11;">
<!ENTITY % laugh13
"%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;%laugh12;">
%laugh13;

5
test/recurse/lol3.xml Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<!DOCTYPE billion SYSTEM "lol3.dtd">
<billion></billion>

16
test/recurse/lol4.patch Normal file
View File

@ -0,0 +1,16 @@
Index: parser.c
===================================================================
--- parser.c (revision 3773)
+++ parser.c (working copy)
@@ -2505,6 +2505,11 @@ xmlStringLenDecodeEntities(xmlParserCtxt
c = CUR_SCHAR(str, l);
else
c = 0;
+ if ((nbchars > 500000) &&
+ (ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE)) {
+ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+ goto int_error;
+ }
}
buffer[nbchars++] = 0;
return(buffer);

36
test/recurse/lol4.xml Normal file

File diff suppressed because one or more lines are too long

51
test/recurse/lol5.xml Normal file
View File

@ -0,0 +1,51 @@
<!DOCTYPE root [
<!ENTITY ha "Ha !">
<!ENTITY ha2 "&ha; &ha;">
<!ENTITY ha3 "&ha2; &ha2;">
<!ENTITY ha4 "&ha3; &ha3;">
<!ENTITY ha5 "&ha4; &ha4;">
<!ENTITY ha6 "&ha5; &ha5;">
<!ENTITY ha7 "&ha6; &ha6;">
<!ENTITY ha8 "&ha7; &ha7;">
<!ENTITY ha9 "&ha8; &ha8;">
<!ENTITY ha10 "&ha9; &ha9;">
<!ENTITY ha11 "&ha10; &ha10;">
<!ENTITY ha12 "&ha11; &ha11;">
<!ENTITY ha13 "&ha12; &ha12;">
<!ENTITY ha14 "&ha13; &ha13;">
<!ENTITY ha15 "&ha14; &ha14;">
<!ENTITY ha16 "&ha15; &ha15;">
<!ENTITY ha17 "&ha16; &ha16;">
<!ENTITY ha18 "&ha17; &ha17;">
<!ENTITY ha19 "&ha18; &ha18;">
<!ENTITY ha20 "&ha19; &ha19;">
<!ENTITY ha21 "&ha20; &ha20;">
<!ENTITY ha22 "&ha21; &ha21;">
<!ENTITY ha23 "&ha22; &ha22;">
<!ENTITY ha24 "&ha23; &ha23;">
<!ENTITY ha25 "&ha24; &ha24;">
<!ENTITY ha26 "&ha25; &ha25;">
<!ENTITY ha27 "&ha26; &ha26;">
<!ENTITY ha28 "&ha27; &ha27;">
<!ENTITY ha29 "&ha28; &ha28;">
<!ENTITY ha30 "&ha29; &ha29;">
<!ENTITY ha31 "&ha30; &ha30;">
<!ENTITY ha32 "&ha31; &ha31;">
<!ENTITY ha33 "&ha32; &ha32;">
<!ENTITY ha34 "&ha33; &ha33;">
<!ENTITY ha35 "&ha34; &ha34;">
<!ENTITY ha36 "&ha35; &ha35;">
<!ENTITY ha37 "&ha36; &ha36;">
<!ENTITY ha38 "&ha37; &ha37;">
<!ENTITY ha39 "&ha38; &ha38;">
<!ENTITY ha40 "&ha39; &ha39;">
<!ENTITY ha41 "&ha40; &ha40;">
<!ENTITY ha42 "&ha41; &ha41;">
<!ENTITY ha43 "&ha42; &ha42;">
<!ENTITY ha44 "&ha43; &ha43;">
<!ENTITY ha45 "&ha44; &ha44;">
<!ENTITY ha46 "&ha45; &ha45;">
<!ENTITY ha47 "&ha46; &ha46;">
<!ENTITY ha48 "&ha47; &ha47;">
]>
<root>&ha48;</root>

23
test/recurse/lol6.xml Normal file

File diff suppressed because one or more lines are too long

973
testrecurse.c Normal file
View File

@ -0,0 +1,973 @@
/*
* testrecurse.c: C program to run libxml2 regression tests checking entities
* recursions
*
* To compile on Unixes:
* cc -o testrecurse `xml2-config --cflags` testrecurse.c `xml2-config --libs` -lpthread
*
* See Copyright for the status of this software.
*
* daniel@veillard.com
*/
#ifdef HAVE_CONFIG_H
#include "libxml.h"
#else
#include <stdio.h>
#endif
#if !defined(_WIN32) || defined(__CYGWIN__)
#include <unistd.h>
#endif
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/uri.h>
#ifdef LIBXML_READER_ENABLED
#include <libxml/xmlreader.h>
#endif
/*
* O_BINARY is just for Windows compatibility - if it isn't defined
* on this system, avoid any compilation error
*/
#ifdef O_BINARY
#define RD_FLAGS O_RDONLY | O_BINARY
#else
#define RD_FLAGS O_RDONLY
#endif
typedef int (*functest) (const char *filename, const char *result,
const char *error, int options);
typedef struct testDesc testDesc;
typedef testDesc *testDescPtr;
struct testDesc {
const char *desc; /* descripton of the test */
functest func; /* function implementing the test */
const char *in; /* glob to path for input files */
const char *out; /* output directory */
const char *suffix;/* suffix for output files */
const char *err; /* suffix for error output files */
int options; /* parser options for the test */
};
static int checkTestFile(const char *filename);
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#include <io.h>
typedef struct
{
size_t gl_pathc; /* Count of paths matched so far */
char **gl_pathv; /* List of matched pathnames. */
size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */
} glob_t;
#define GLOB_DOOFFS 0
static int glob(const char *pattern, int flags,
int errfunc(const char *epath, int eerrno),
glob_t *pglob) {
glob_t *ret;
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
unsigned int nb_paths = 0;
char directory[500];
int len;
if ((pattern == NULL) || (pglob == NULL)) return(-1);
strncpy(directory, pattern, 499);
for (len = strlen(directory);len >= 0;len--) {
if (directory[len] == '/') {
len++;
directory[len] = 0;
break;
}
}
if (len <= 0)
len = 0;
ret = pglob;
memset(ret, 0, sizeof(glob_t));
hFind = FindFirstFileA(pattern, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
return(0);
nb_paths = 20;
ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
if (ret->gl_pathv == NULL) {
FindClose(hFind);
return(-1);
}
strncpy(directory + len, FindFileData.cFileName, 499 - len);
ret->gl_pathv[ret->gl_pathc] = strdup(directory);
if (ret->gl_pathv[ret->gl_pathc] == NULL)
goto done;
ret->gl_pathc++;
while(FindNextFileA(hFind, &FindFileData)) {
if (FindFileData.cFileName[0] == '.')
continue;
if (ret->gl_pathc + 2 > nb_paths) {
char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
if (tmp == NULL)
break;
ret->gl_pathv = tmp;
nb_paths *= 2;
}
strncpy(directory + len, FindFileData.cFileName, 499 - len);
ret->gl_pathv[ret->gl_pathc] = strdup(directory);
if (ret->gl_pathv[ret->gl_pathc] == NULL)
break;
ret->gl_pathc++;
}
ret->gl_pathv[ret->gl_pathc] = NULL;
done:
FindClose(hFind);
return(0);
}
static void globfree(glob_t *pglob) {
unsigned int i;
if (pglob == NULL)
return;
for (i = 0;i < pglob->gl_pathc;i++) {
if (pglob->gl_pathv[i] != NULL)
free(pglob->gl_pathv[i]);
}
}
#define vsnprintf _vsnprintf
#define snprintf _snprintf
#else
#include <glob.h>
#endif
/************************************************************************
* *
* Huge document generator *
* *
************************************************************************/
#include <libxml/xmlIO.h>
static const char *start = "<!DOCTYPE foo [\
<!ENTITY f 'some internal data'> \
<!ENTITY e '&f;&f;'> \
<!ENTITY d '&e;&e;'> \
]> \
<foo>";
static const char *segment = " <bar>&e; &f; &d;</bar>\n";
static const char *finish = "</foo>";
static int curseg = 0;
static const char *current;
static int rlen;
/**
* hugeMatch:
* @URI: an URI to test
*
* Check for an huge: query
*
* Returns 1 if yes and 0 if another Input module should be used
*/
static int
hugeMatch(const char * URI) {
if ((URI != NULL) && (!strncmp(URI, "huge:", 4)))
return(1);
return(0);
}
/**
* hugeOpen:
* @URI: an URI to test
*
* Return a pointer to the huge: query handler, in this example simply
* the current pointer...
*
* Returns an Input context or NULL in case or error
*/
static void *
hugeOpen(const char * URI) {
if ((URI == NULL) || (strncmp(URI, "huge:", 4)))
return(NULL);
rlen = strlen(start);
current = start;
return((void *) current);
}
/**
* hugeClose:
* @context: the read context
*
* Close the huge: query handler
*
* Returns 0 or -1 in case of error
*/
static int
hugeClose(void * context) {
if (context == NULL) return(-1);
return(0);
}
#define MAX_NODES 1000000
/**
* hugeRead:
* @context: the read context
* @buffer: where to store data
* @len: number of bytes to read
*
* Implement an huge: query read.
*
* Returns the number of bytes read or -1 in case of error
*/
static int
hugeRead(void *context, char *buffer, int len)
{
if ((context == NULL) || (buffer == NULL) || (len < 0))
return (-1);
if (len >= rlen) {
if (curseg >= MAX_NODES + 1) {
rlen = 0;
return(0);
}
len = rlen;
rlen = 0;
memcpy(buffer, current, len);
curseg ++;
if (curseg == MAX_NODES) {
fprintf(stderr, "\n");
rlen = strlen(finish);
current = finish;
} else {
if (curseg % (MAX_NODES / 10) == 0)
fprintf(stderr, ".");
rlen = strlen(segment);
current = segment;
}
} else {
memcpy(buffer, current, len);
rlen -= len;
current += len;
}
return (len);
}
/************************************************************************
* *
* Libxml2 specific routines *
* *
************************************************************************/
static int nb_tests = 0;
static int nb_errors = 0;
static int nb_leaks = 0;
static int extraMemoryFromResolver = 0;
static int
fatalError(void) {
fprintf(stderr, "Exitting tests on fatal error\n");
exit(1);
}
/*
* We need to trap calls to the resolver to not account memory for the catalog
* which is shared to the current running test. We also don't want to have
* network downloads modifying tests.
*/
static xmlParserInputPtr
testExternalEntityLoader(const char *URL, const char *ID,
xmlParserCtxtPtr ctxt) {
xmlParserInputPtr ret;
if (checkTestFile(URL)) {
ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
} else {
int memused = xmlMemUsed();
ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
extraMemoryFromResolver += xmlMemUsed() - memused;
}
return(ret);
}
/*
* Trapping the error messages at the generic level to grab the equivalent of
* stderr messages on CLI tools.
*/
static char testErrors[32769];
static int testErrorsSize = 0;
static void XMLCDECL
channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
va_list args;
int res;
if (testErrorsSize >= 32768)
return;
va_start(args, msg);
res = vsnprintf(&testErrors[testErrorsSize],
32768 - testErrorsSize,
msg, args);
va_end(args);
if (testErrorsSize + res >= 32768) {
/* buffer is full */
testErrorsSize = 32768;
testErrors[testErrorsSize] = 0;
} else {
testErrorsSize += res;
}
testErrors[testErrorsSize] = 0;
}
/**
* xmlParserPrintFileContext:
* @input: an xmlParserInputPtr input
*
* Displays current context within the input content for error tracking
*/
static void
xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
xmlGenericErrorFunc chanl, void *data ) {
const xmlChar *cur, *base;
unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
xmlChar content[81]; /* space for 80 chars + line terminator */
xmlChar *ctnt;
if (input == NULL) return;
cur = input->cur;
base = input->base;
/* skip backwards over any end-of-lines */
while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
cur--;
}
n = 0;
/* search backwards for beginning-of-line (to max buff size) */
while ((n++ < (sizeof(content)-1)) && (cur > base) &&
(*(cur) != '\n') && (*(cur) != '\r'))
cur--;
if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
/* calculate the error position in terms of the current position */
col = input->cur - cur;
/* search forward for end-of-line (to max buff size) */
n = 0;
ctnt = content;
/* copy selected text to our buffer */
while ((*cur != 0) && (*(cur) != '\n') &&
(*(cur) != '\r') && (n < sizeof(content)-1)) {
*ctnt++ = *cur++;
n++;
}
*ctnt = 0;
/* print out the selected text */
chanl(data ,"%s\n", content);
/* create blank line with problem pointer */
n = 0;
ctnt = content;
/* (leave buffer space for pointer + line terminator) */
while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
if (*(ctnt) != '\t')
*(ctnt) = ' ';
ctnt++;
}
*ctnt++ = '^';
*ctnt = 0;
chanl(data ,"%s\n", content);
}
static void
testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, xmlErrorPtr err) {
char *file = NULL;
int line = 0;
int code = -1;
int domain;
void *data = NULL;
const char *str;
const xmlChar *name = NULL;
xmlNodePtr node;
xmlErrorLevel level;
xmlParserInputPtr input = NULL;
xmlParserInputPtr cur = NULL;
xmlParserCtxtPtr ctxt = NULL;
if (err == NULL)
return;
file = err->file;
line = err->line;
code = err->code;
domain = err->domain;
level = err->level;
node = err->node;
if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
(domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
ctxt = err->ctxt;
}
str = err->message;
if (code == XML_ERR_OK)
return;
if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
name = node->name;
/*
* Maintain the compatibility with the legacy error handling
*/
if (ctxt != NULL) {
input = ctxt->input;
if ((input != NULL) && (input->filename == NULL) &&
(ctxt->inputNr > 1)) {
cur = input;
input = ctxt->inputTab[ctxt->inputNr - 2];
}
if (input != NULL) {
if (input->filename)
channel(data, "%s:%d: ", input->filename, input->line);
else if ((line != 0) && (domain == XML_FROM_PARSER))
channel(data, "Entity: line %d: ", input->line);
}
} else {
if (file != NULL)
channel(data, "%s:%d: ", file, line);
else if ((line != 0) && (domain == XML_FROM_PARSER))
channel(data, "Entity: line %d: ", line);
}
if (name != NULL) {
channel(data, "element %s: ", name);
}
if (code == XML_ERR_OK)
return;
switch (domain) {
case XML_FROM_PARSER:
channel(data, "parser ");
break;
case XML_FROM_NAMESPACE:
channel(data, "namespace ");
break;
case XML_FROM_DTD:
case XML_FROM_VALID:
channel(data, "validity ");
break;
case XML_FROM_HTML:
channel(data, "HTML parser ");
break;
case XML_FROM_MEMORY:
channel(data, "memory ");
break;
case XML_FROM_OUTPUT:
channel(data, "output ");
break;
case XML_FROM_IO:
channel(data, "I/O ");
break;
case XML_FROM_XINCLUDE:
channel(data, "XInclude ");
break;
case XML_FROM_XPATH:
channel(data, "XPath ");
break;
case XML_FROM_XPOINTER:
channel(data, "parser ");
break;
case XML_FROM_REGEXP:
channel(data, "regexp ");
break;
case XML_FROM_MODULE:
channel(data, "module ");
break;
case XML_FROM_SCHEMASV:
channel(data, "Schemas validity ");
break;
case XML_FROM_SCHEMASP:
channel(data, "Schemas parser ");
break;
case XML_FROM_RELAXNGP:
channel(data, "Relax-NG parser ");
break;
case XML_FROM_RELAXNGV:
channel(data, "Relax-NG validity ");
break;
case XML_FROM_CATALOG:
channel(data, "Catalog ");
break;
case XML_FROM_C14N:
channel(data, "C14N ");
break;
case XML_FROM_XSLT:
channel(data, "XSLT ");
break;
default:
break;
}
if (code == XML_ERR_OK)
return;
switch (level) {
case XML_ERR_NONE:
channel(data, ": ");
break;
case XML_ERR_WARNING:
channel(data, "warning : ");
break;
case XML_ERR_ERROR:
channel(data, "error : ");
break;
case XML_ERR_FATAL:
channel(data, "error : ");
break;
}
if (code == XML_ERR_OK)
return;
if (str != NULL) {
int len;
len = xmlStrlen((const xmlChar *)str);
if ((len > 0) && (str[len - 1] != '\n'))
channel(data, "%s\n", str);
else
channel(data, "%s", str);
} else {
channel(data, "%s\n", "out of memory error");
}
if (code == XML_ERR_OK)
return;
if (ctxt != NULL) {
xmlParserPrintFileContextInternal(input, channel, data);
if (cur != NULL) {
if (cur->filename)
channel(data, "%s:%d: \n", cur->filename, cur->line);
else if ((line != 0) && (domain == XML_FROM_PARSER))
channel(data, "Entity: line %d: \n", cur->line);
xmlParserPrintFileContextInternal(cur, channel, data);
}
}
if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
(err->int1 < 100) &&
(err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
xmlChar buf[150];
int i;
channel(data, "%s\n", err->str1);
for (i=0;i < err->int1;i++)
buf[i] = ' ';
buf[i++] = '^';
buf[i] = 0;
channel(data, "%s\n", buf);
}
}
static void
initializeLibxml2(void) {
xmlGetWarningsDefaultValue = 0;
xmlPedanticParserDefault(0);
xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
xmlInitParser();
xmlSetExternalEntityLoader(testExternalEntityLoader);
xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
/*
* register the new I/O handlers
*/
if (xmlRegisterInputCallbacks(hugeMatch, hugeOpen,
hugeRead, hugeClose) < 0) {
fprintf(stderr, "failed to register Huge handler\n");
exit(1);
}
}
/************************************************************************
* *
* File name and path utilities *
* *
************************************************************************/
static const char *baseFilename(const char *filename) {
const char *cur;
if (filename == NULL)
return(NULL);
cur = &filename[strlen(filename)];
while ((cur > filename) && (*cur != '/'))
cur--;
if (*cur == '/')
return(cur + 1);
return(cur);
}
static char *resultFilename(const char *filename, const char *out,
const char *suffix) {
const char *base;
char res[500];
char suffixbuff[500];
/*************
if ((filename[0] == 't') && (filename[1] == 'e') &&
(filename[2] == 's') && (filename[3] == 't') &&
(filename[4] == '/'))
filename = &filename[5];
*************/
base = baseFilename(filename);
if (suffix == NULL)
suffix = ".tmp";
if (out == NULL)
out = "";
strncpy(suffixbuff,suffix,499);
#ifdef VMS
if(strstr(base,".") && suffixbuff[0]=='.')
suffixbuff[0]='_';
#endif
snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
res[499] = 0;
return(strdup(res));
}
static int checkTestFile(const char *filename) {
struct stat buf;
if (stat(filename, &buf) == -1)
return(0);
#if defined(_WIN32) && !defined(__CYGWIN__)
if (!(buf.st_mode & _S_IFREG))
return(0);
#else
if (!S_ISREG(buf.st_mode))
return(0);
#endif
return(1);
}
/************************************************************************
* *
* Test to detect or not recursive entities *
* *
************************************************************************/
/**
* recursiveDetectTest:
* @filename: the file to parse
* @result: the file with expected result
* @err: the file with error messages: unused
*
* Parse a file loading DTD and replacing entities check it fails for
* lol cases
*
* Returns 0 in case of success, an error code otherwise
*/
static int
recursiveDetectTest(const char *filename,
const char *result ATTRIBUTE_UNUSED,
const char *err ATTRIBUTE_UNUSED,
int options ATTRIBUTE_UNUSED) {
xmlDocPtr doc;
xmlParserCtxtPtr ctxt;
int res = 0;
int mem;
nb_tests++;
ctxt = xmlNewParserCtxt();
mem = xmlMemUsed();
/*
* base of the test, parse with the old API
*/
doc = xmlCtxtReadFile(ctxt, filename, NULL,
XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
if ((doc != NULL) || (ctxt->lastError.code != XML_ERR_ENTITY_LOOP)) {
fprintf(stderr, "Failed to detect recursion in %s\n", filename);
xmlFreeParserCtxt(ctxt);
xmlFreeDoc(doc);
return(1);
}
xmlFreeParserCtxt(ctxt);
return(res);
}
/**
* notRecursiveDetectTest:
* @filename: the file to parse
* @result: the file with expected result
* @err: the file with error messages: unused
*
* Parse a file loading DTD and replacing entities check it works for
* good cases
*
* Returns 0 in case of success, an error code otherwise
*/
static int
notRecursiveDetectTest(const char *filename,
const char *result ATTRIBUTE_UNUSED,
const char *err ATTRIBUTE_UNUSED,
int options ATTRIBUTE_UNUSED) {
xmlDocPtr doc;
xmlParserCtxtPtr ctxt;
int res = 0;
int mem;
nb_tests++;
ctxt = xmlNewParserCtxt();
mem = xmlMemUsed();
/*
* base of the test, parse with the old API
*/
doc = xmlCtxtReadFile(ctxt, filename, NULL,
XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
if (doc == NULL) {
fprintf(stderr, "Failed to parse correct file %s\n", filename);
xmlFreeParserCtxt(ctxt);
return(1);
}
xmlFreeDoc(doc);
xmlFreeParserCtxt(ctxt);
return(res);
}
#ifdef LIBXML_READER_ENABLED
/**
* notRecursiveHugeTest:
* @filename: the file to parse
* @result: the file with expected result
* @err: the file with error messages: unused
*
* Parse a memory generated file
* good cases
*
* Returns 0 in case of success, an error code otherwise
*/
static int
notRecursiveHugeTest(const char *filename ATTRIBUTE_UNUSED,
const char *result ATTRIBUTE_UNUSED,
const char *err ATTRIBUTE_UNUSED,
int options ATTRIBUTE_UNUSED) {
xmlTextReaderPtr reader;
int res = 0;
int ret;
nb_tests++;
reader = xmlReaderForFile("huge:test" , NULL,
XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
if (reader == NULL) {
fprintf(stderr, "Failed to open huge:test\n");
return(1);
}
ret = xmlTextReaderRead(reader);
while (ret == 1) {
ret = xmlTextReaderRead(reader);
}
if (ret != 0) {
fprintf(stderr, "Failed to parser huge:test with entities\n");
res = 1;
}
xmlFreeTextReader(reader);
return(res);
}
#endif
/************************************************************************
* *
* Tests Descriptions *
* *
************************************************************************/
static
testDesc testDescriptions[] = {
{ "Parsing recursive test cases" ,
recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL,
0 },
{ "Parsing non-recursive test cases" ,
notRecursiveDetectTest, "./test/recurse/good*.xml", NULL, NULL, NULL,
0 },
#ifdef LIBXML_READER_ENABLED
{ "Parsing non-recursive huge case" ,
notRecursiveHugeTest, NULL, NULL, NULL, NULL,
0 },
#endif
{NULL, NULL, NULL, NULL, NULL, NULL, 0}
};
/************************************************************************
* *
* The main code driving the tests *
* *
************************************************************************/
static int
launchTests(testDescPtr tst) {
int res = 0, err = 0;
size_t i;
char *result;
char *error;
int mem;
if (tst == NULL) return(-1);
if (tst->in != NULL) {
glob_t globbuf;
globbuf.gl_offs = 0;
glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
for (i = 0;i < globbuf.gl_pathc;i++) {
if (!checkTestFile(globbuf.gl_pathv[i]))
continue;
if (tst->suffix != NULL) {
result = resultFilename(globbuf.gl_pathv[i], tst->out,
tst->suffix);
if (result == NULL) {
fprintf(stderr, "Out of memory !\n");
fatalError();
}
} else {
result = NULL;
}
if (tst->err != NULL) {
error = resultFilename(globbuf.gl_pathv[i], tst->out,
tst->err);
if (error == NULL) {
fprintf(stderr, "Out of memory !\n");
fatalError();
}
} else {
error = NULL;
}
if ((result) &&(!checkTestFile(result))) {
fprintf(stderr, "Missing result file %s\n", result);
} else if ((error) &&(!checkTestFile(error))) {
fprintf(stderr, "Missing error file %s\n", error);
} else {
mem = xmlMemUsed();
extraMemoryFromResolver = 0;
testErrorsSize = 0;
testErrors[0] = 0;
res = tst->func(globbuf.gl_pathv[i], result, error,
tst->options | XML_PARSE_COMPACT);
xmlResetLastError();
if (res != 0) {
fprintf(stderr, "File %s generated an error\n",
globbuf.gl_pathv[i]);
nb_errors++;
err++;
}
else if (xmlMemUsed() != mem) {
if ((xmlMemUsed() != mem) &&
(extraMemoryFromResolver == 0)) {
fprintf(stderr, "File %s leaked %d bytes\n",
globbuf.gl_pathv[i], xmlMemUsed() - mem);
nb_leaks++;
err++;
}
}
testErrorsSize = 0;
}
if (result)
free(result);
if (error)
free(error);
}
globfree(&globbuf);
} else {
testErrorsSize = 0;
testErrors[0] = 0;
extraMemoryFromResolver = 0;
res = tst->func(NULL, NULL, NULL, tst->options);
if (res != 0) {
nb_errors++;
err++;
}
}
return(err);
}
static int verbose = 0;
static int tests_quiet = 0;
static int
runtest(int i) {
int ret = 0, res;
int old_errors, old_tests, old_leaks;
old_errors = nb_errors;
old_tests = nb_tests;
old_leaks = nb_leaks;
if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
printf("## %s\n", testDescriptions[i].desc);
res = launchTests(&testDescriptions[i]);
if (res != 0)
ret++;
if (verbose) {
if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
printf("Ran %d tests, no errors\n", nb_tests - old_tests);
else
printf("Ran %d tests, %d errors, %d leaks\n",
nb_tests - old_tests,
nb_errors - old_errors,
nb_leaks - old_leaks);
}
return(ret);
}
int
main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
int i, a, ret = 0;
int subset = 0;
initializeLibxml2();
for (a = 1; a < argc;a++) {
if (!strcmp(argv[a], "-v"))
verbose = 1;
else if (!strcmp(argv[a], "-quiet"))
tests_quiet = 1;
else {
for (i = 0; testDescriptions[i].func != NULL; i++) {
if (strstr(testDescriptions[i].desc, argv[a])) {
ret += runtest(i);
subset++;
}
}
}
}
if (subset == 0) {
for (i = 0; testDescriptions[i].func != NULL; i++) {
ret += runtest(i);
}
}
if ((nb_errors == 0) && (nb_leaks == 0)) {
ret = 0;
printf("Total %d tests, no errors\n",
nb_tests);
} else {
ret = 1;
printf("Total %d tests, %d errors, %d leaks\n",
nb_tests, nb_errors, nb_leaks);
}
xmlCleanupParser();
xmlMemoryDump();
return(ret);
}