diff options
Diffstat (limited to 'chromium/third_party/libxml/src/testrecurse.c')
-rw-r--r-- | chromium/third_party/libxml/src/testrecurse.c | 371 |
1 files changed, 309 insertions, 62 deletions
diff --git a/chromium/third_party/libxml/src/testrecurse.c b/chromium/third_party/libxml/src/testrecurse.c index d213ebc63dc..acfe08b7613 100644 --- a/chromium/third_party/libxml/src/testrecurse.c +++ b/chromium/third_party/libxml/src/testrecurse.c @@ -13,19 +13,13 @@ #include "libxml.h" #include <stdio.h> -#if !defined(_WIN32) -#include <unistd.h> -#endif #include <string.h> #include <sys/stat.h> -#include <fcntl.h> #include <libxml/parser.h> +#include <libxml/parserInternals.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 @@ -37,6 +31,9 @@ #define RD_FLAGS O_RDONLY #endif +#define OPT_SAX (1<<0) +#define OPT_NO_SUBST (1<<1) + typedef int (*functest) (const char *filename, const char *result, const char *error, int options); @@ -58,7 +55,6 @@ static int checkTestFile(const char *filename); #if defined(_WIN32) #include <windows.h> -#include <io.h> typedef struct { @@ -157,17 +153,61 @@ static void globfree(glob_t *pglob) { #include <libxml/xmlIO.h> +typedef struct { + const char *URL; + const char *start; + const char *segment; + const char *finish; +} xmlHugeDocParts; + +static const xmlHugeDocParts hugeDocTable[] = { + { + "test/recurse/huge.xml", + + "<!DOCTYPE foo [" + "<!ELEMENT foo (bar*)> " + "<!ELEMENT bar (#PCDATA)> " + "<!ATTLIST bar attr CDATA #IMPLIED> " + "<!ENTITY a SYSTEM 'ga.ent'> " + "<!ENTITY b SYSTEM 'gb.ent'> " + "<!ENTITY c SYSTEM 'gc.ent'> " + "<!ENTITY f 'some internal data'> " + "<!ENTITY e '&f;&f;'> " + "<!ENTITY d '&e;&e;'> " + "]> " + "<foo>", + + " <bar attr='&e; &f; &d;'>&a; &b; &c; &e; &f; &d;</bar>\n" + " <bar>_123456789_123456789_123456789_123456789</bar>\n" + " <bar>_123456789_123456789_123456789_123456789</bar>\n" + " <bar>_123456789_123456789_123456789_123456789</bar>\n", + + "</foo>" + }, + { + "test/recurse/huge_dtd.dtd", + + "<!ELEMENT foo (#PCDATA)>\n" + "<!ENTITY ent 'success'>\n" + "<!ENTITY % a SYSTEM 'pa.ent'>\n" + "<!ENTITY % b SYSTEM 'pb.ent'>\n" + "<!ENTITY % c SYSTEM 'pc.ent'>\n" + "<!ENTITY % d '<!-- comment -->'>\n" + "<!ENTITY % e '%d;%d;'>\n" + "<!ENTITY % f '%e;%e;'>\n", + + "<!ENTITY ent '%a; %b; %c; %d; %e; %f;'>\n" + "%a; %b; %c; %d; %e; %f;\n" + "<!-- _123456789_123456789_123456789_123456789 -->\n" + "<!-- _123456789_123456789_123456789_123456789 -->\n" + "<!-- _123456789_123456789_123456789_123456789 -->\n", + + "" + }, + { NULL, NULL, NULL, NULL } +}; -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 const xmlHugeDocParts *hugeDocParts; static int curseg = 0; static const char *current; static int rlen; @@ -176,14 +216,22 @@ static int rlen; * hugeMatch: * @URI: an URI to test * - * Check for an huge: query + * Check for a 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); + int i; + + if (URI == NULL) + return(0); + + for (i = 0; hugeDocTable[i].URL; i++) { + if (strcmp(URI, hugeDocTable[i].URL) == 0) + return(1); + } + return(0); } @@ -191,25 +239,36 @@ hugeMatch(const char * URI) { * hugeOpen: * @URI: an URI to test * - * Return a pointer to the huge: query handler, in this example simply + * 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))) + int i; + + if (URI == NULL) return(NULL); - rlen = strlen(start); - current = start; - return((void *) current); + + for (i = 0; hugeDocTable[i].URL; i++) { + if (strcmp(URI, hugeDocTable[i].URL) == 0) { + hugeDocParts = hugeDocTable + i; + curseg = 0; + current = hugeDocParts->start; + rlen = strlen(current); + return((void *) current); + } + } + + return(NULL); } /** * hugeClose: * @context: the read context * - * Close the huge: query handler + * Close the huge query handler * * Returns 0 or -1 in case of error */ @@ -219,7 +278,7 @@ hugeClose(void * context) { return(0); } -#define MAX_NODES 1000000 +#define MAX_NODES 10000 /** * hugeRead: @@ -227,7 +286,7 @@ hugeClose(void * context) { * @buffer: where to store data * @len: number of bytes to read * - * Implement an huge: query read. + * Implement an huge query read. * * Returns the number of bytes read or -1 in case of error */ @@ -247,15 +306,11 @@ hugeRead(void *context, char *buffer, int len) memcpy(buffer, current, len); curseg ++; if (curseg == MAX_NODES) { - fprintf(stderr, "\n"); - rlen = strlen(finish); - current = finish; + current = hugeDocParts->finish; } else { - if (curseg % (MAX_NODES / 10) == 0) - fprintf(stderr, "."); - rlen = strlen(segment); - current = segment; + current = hugeDocParts->segment; } + rlen = strlen(current); } else { memcpy(buffer, current, len); rlen -= len; @@ -309,7 +364,7 @@ testExternalEntityLoader(const char *URL, const char *ID, static char testErrors[32769]; static int testErrorsSize = 0; -static void XMLCDECL +static void channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { va_list args; int res; @@ -588,6 +643,17 @@ initializeLibxml2(void) { } } +static void +initSAX(xmlParserCtxtPtr ctxt) { + ctxt->sax->startElementNs = NULL; + ctxt->sax->endElementNs = NULL; + ctxt->sax->characters = NULL; + ctxt->sax->cdataBlock = NULL; + ctxt->sax->ignorableWhitespace = NULL; + ctxt->sax->processingInstruction = NULL; + ctxt->sax->comment = NULL; +} + /************************************************************************ * * * File name and path utilities * @@ -675,19 +741,28 @@ static int recursiveDetectTest(const char *filename, const char *result ATTRIBUTE_UNUSED, const char *err ATTRIBUTE_UNUSED, - int options ATTRIBUTE_UNUSED) { + int options) { xmlDocPtr doc; xmlParserCtxtPtr ctxt; int res = 0; + /* + * XML_PARSE_DTDVALID is the only way to load external entities + * without XML_PARSE_NOENT. The validation result doesn't matter + * anyway. + */ + int parserOptions = XML_PARSE_DTDVALID; nb_tests++; ctxt = xmlNewParserCtxt(); + if (options & OPT_SAX) + initSAX(ctxt); + if ((options & OPT_NO_SUBST) == 0) + parserOptions |= XML_PARSE_NOENT; /* * base of the test, parse with the old API */ - doc = xmlCtxtReadFile(ctxt, filename, NULL, - XML_PARSE_NOENT | XML_PARSE_DTDLOAD); + doc = xmlCtxtReadFile(ctxt, filename, NULL, parserOptions); if ((doc != NULL) || (ctxt->lastError.code != XML_ERR_ENTITY_LOOP)) { fprintf(stderr, "Failed to detect recursion in %s\n", filename); xmlFreeParserCtxt(ctxt); @@ -714,19 +789,23 @@ static int notRecursiveDetectTest(const char *filename, const char *result ATTRIBUTE_UNUSED, const char *err ATTRIBUTE_UNUSED, - int options ATTRIBUTE_UNUSED) { + int options) { xmlDocPtr doc; xmlParserCtxtPtr ctxt; int res = 0; + int parserOptions = XML_PARSE_DTDLOAD; nb_tests++; ctxt = xmlNewParserCtxt(); + if (options & OPT_SAX) + initSAX(ctxt); + if ((options & OPT_NO_SUBST) == 0) + parserOptions |= XML_PARSE_NOENT; /* * base of the test, parse with the old API */ - doc = xmlCtxtReadFile(ctxt, filename, NULL, - XML_PARSE_NOENT | XML_PARSE_DTDLOAD); + doc = xmlCtxtReadFile(ctxt, filename, NULL, parserOptions); if (doc == NULL) { fprintf(stderr, "Failed to parse correct file %s\n", filename); xmlFreeParserCtxt(ctxt); @@ -738,7 +817,6 @@ notRecursiveDetectTest(const char *filename, return(res); } -#ifdef LIBXML_READER_ENABLED /** * notRecursiveHugeTest: * @filename: the file to parse @@ -754,32 +832,179 @@ 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 options) { + xmlParserCtxtPtr ctxt; + xmlDocPtr doc; int res = 0; - int ret; + int parserOptions = XML_PARSE_DTDVALID; 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); + ctxt = xmlNewParserCtxt(); + if (options & OPT_SAX) + initSAX(ctxt); + if ((options & OPT_NO_SUBST) == 0) + parserOptions |= XML_PARSE_NOENT; + doc = xmlCtxtReadFile(ctxt, "test/recurse/huge.xml", NULL, parserOptions); + if (doc == NULL) { + fprintf(stderr, "Failed to parse huge.xml\n"); + res = 1; + } else { + xmlEntityPtr ent; + unsigned long fixed_cost = 50; + unsigned long f_size = xmlStrlen(BAD_CAST "some internal data"); + unsigned long e_size; + unsigned long d_size; + unsigned long total_size; + + ent = xmlGetDocEntity(doc, BAD_CAST "e"); + e_size = f_size * 2 + + xmlStrlen(BAD_CAST "&f;") * 2 + + fixed_cost * 2; + if (ent->expandedSize != e_size) { + fprintf(stderr, "Wrong size for entity e: %lu (expected %lu)\n", + ent->expandedSize, e_size); + res = 1; + } + + ent = xmlGetDocEntity(doc, BAD_CAST "b"); + if (ent->expandedSize != e_size) { + fprintf(stderr, "Wrong size for entity b: %lu (expected %lu)\n", + ent->expandedSize, e_size); + res = 1; + } + + ent = xmlGetDocEntity(doc, BAD_CAST "d"); + d_size = e_size * 2 + + xmlStrlen(BAD_CAST "&e;") * 2 + + fixed_cost * 2; + if (ent->expandedSize != d_size) { + fprintf(stderr, "Wrong size for entity d: %lu (expected %lu)\n", + ent->expandedSize, d_size); + res = 1; + } + + ent = xmlGetDocEntity(doc, BAD_CAST "c"); + if (ent->expandedSize != d_size) { + fprintf(stderr, "Wrong size for entity c: %lu (expected %lu)\n", + ent->expandedSize, d_size); + res = 1; + } + + if (ctxt->sizeentcopy < XML_MAX_TEXT_LENGTH) { + fprintf(stderr, "Total entity size too small: %lu\n", + ctxt->sizeentcopy); + res = 1; + } + + total_size = (f_size + e_size + d_size + 3 * fixed_cost) * + (MAX_NODES - 1) * 3; + if (ctxt->sizeentcopy != total_size) { + fprintf(stderr, "Wrong total entity size: %lu (expected %lu)\n", + ctxt->sizeentcopy, total_size); + res = 1; + } + + if (ctxt->sizeentities != 30) { + fprintf(stderr, "Wrong parsed entity size: %lu (expected %lu)\n", + ctxt->sizeentities, 30lu); + res = 1; + } } - if (ret != 0) { - fprintf(stderr, "Failed to parser huge:test with entities\n"); + + xmlFreeDoc(doc); + xmlFreeParserCtxt(ctxt); + + return(res); +} + +/** + * 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 +hugeDtdTest(const char *filename ATTRIBUTE_UNUSED, + const char *result ATTRIBUTE_UNUSED, + const char *err ATTRIBUTE_UNUSED, + int options) { + xmlParserCtxtPtr ctxt; + xmlDocPtr doc; + int res = 0; + int parserOptions = XML_PARSE_DTDVALID; + + nb_tests++; + + ctxt = xmlNewParserCtxt(); + if (options & OPT_SAX) + initSAX(ctxt); + if ((options & OPT_NO_SUBST) == 0) + parserOptions |= XML_PARSE_NOENT; + doc = xmlCtxtReadFile(ctxt, "test/recurse/huge_dtd.xml", NULL, + parserOptions); + if (doc == NULL) { + fprintf(stderr, "Failed to parse huge_dtd.xml\n"); res = 1; + } else { + unsigned long fixed_cost = 50; + unsigned long a_size = xmlStrlen(BAD_CAST "<!-- comment -->"); + unsigned long b_size; + unsigned long c_size; + unsigned long e_size; + unsigned long f_size; + unsigned long total_size; + + if (ctxt->sizeentcopy < XML_MAX_TEXT_LENGTH) { + fprintf(stderr, "Total entity size too small: %lu\n", + ctxt->sizeentcopy); + res = 1; + } + + b_size = (a_size + strlen("&a;") + fixed_cost) * 2; + c_size = (b_size + strlen("&b;") + fixed_cost) * 2; + /* + * Internal parameter entites are substitued eagerly and + * need different accounting. + */ + e_size = a_size * 2; + f_size = e_size * 2; + total_size = /* internal */ + e_size + f_size + fixed_cost * 4 + + (a_size + e_size + f_size + fixed_cost * 3) * + (MAX_NODES - 1) * 2 + + /* external */ + (a_size + b_size + c_size + fixed_cost * 3) * + (MAX_NODES - 1) * 2 + + /* final reference in main doc */ + strlen("success") + fixed_cost; + if (ctxt->sizeentcopy != total_size) { + fprintf(stderr, "Wrong total entity size: %lu (expected %lu)\n", + ctxt->sizeentcopy, total_size); + res = 1; + } + + total_size = strlen(hugeDocParts->start) + + strlen(hugeDocParts->segment) * (MAX_NODES - 1) + + strlen(hugeDocParts->finish) + + 28; + if (ctxt->sizeentities != total_size) { + fprintf(stderr, "Wrong parsed entity size: %lu (expected %lu)\n", + ctxt->sizeentities, total_size); + res = 1; + } } - xmlFreeTextReader(reader); + + xmlFreeDoc(doc); + xmlFreeParserCtxt(ctxt); return(res); } -#endif /************************************************************************ * * @@ -792,14 +1017,36 @@ testDesc testDescriptions[] = { { "Parsing recursive test cases" , recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL, 0 }, + { "Parsing recursive test cases (no substitution)" , + recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL, + OPT_NO_SUBST }, + { "Parsing recursive test cases (SAX)" , + recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL, + OPT_SAX }, + { "Parsing recursive test cases (SAX, no substitution)" , + recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL, + OPT_SAX | OPT_NO_SUBST }, { "Parsing non-recursive test cases" , notRecursiveDetectTest, "./test/recurse/good*.xml", NULL, NULL, NULL, 0 }, -#ifdef LIBXML_READER_ENABLED + { "Parsing non-recursive test cases (SAX)" , + notRecursiveDetectTest, "./test/recurse/good*.xml", NULL, NULL, NULL, + OPT_SAX }, { "Parsing non-recursive huge case" , notRecursiveHugeTest, NULL, NULL, NULL, NULL, 0 }, -#endif + { "Parsing non-recursive huge case (no substitution)" , + notRecursiveHugeTest, NULL, NULL, NULL, NULL, + OPT_NO_SUBST }, + { "Parsing non-recursive huge case (SAX)" , + notRecursiveHugeTest, NULL, NULL, NULL, NULL, + OPT_SAX }, + { "Parsing non-recursive huge case (SAX, no substitution)" , + notRecursiveHugeTest, NULL, NULL, NULL, NULL, + OPT_SAX | OPT_NO_SUBST }, + { "Parsing non-recursive huge DTD case" , + hugeDtdTest, NULL, NULL, NULL, NULL, + 0 }, {NULL, NULL, NULL, NULL, NULL, NULL, 0} }; |