diff --git a/ChangeLog b/ChangeLog index 0fc82255..037d9ef3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Sun Feb 17 20:41:37 CET 2002 Daniel Veillard + + * check-xml-test-suite.py: python script to run regression tests + against the XML Test suite of W3C/OASis + * SAX.c: fixed a validation bug + * parser.c: fixed 3 errors pointed by the test suite + * doc/buildDocBookCatalog: fixed a typo pointed by drake + * python/Makefile.am: fixed a dependendy + Fri Feb 15 21:47:13 CET 2002 Daniel Veillard * xmlmemory.c: avoid a warning bug #71594 diff --git a/SAX.c b/SAX.c index 399eed43..da133706 100644 --- a/SAX.c +++ b/SAX.c @@ -493,7 +493,7 @@ attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname, "SAX.attributeDecl(%s) called while not in subset\n", name); return; } - if (attr == 0) ctxt->valid = 0; + /* if (attr == 0) ctxt->valid = 0; */ if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc && ctxt->myDoc->intSubset) ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc, diff --git a/check-xml-test-suite.py b/check-xml-test-suite.py new file mode 100755 index 00000000..3bf9f9ec --- /dev/null +++ b/check-xml-test-suite.py @@ -0,0 +1,330 @@ +#!/usr/bin/python +import sys +import os +import string +sys.path.append("python") +import libxml2 + +# +# the testsuite description +# +CONF="xml-test-suite/xmlconf/xmlconf.xml" +LOG="check-xml-test-suite.log" + +log = open(LOG, "w") + +# +# Error and warning handlers +# +error_nr = 0 +def errorHandler(ctx, str): + global error_nr + + error_nr = error_nr + 1 + +libxml2.registerErrorHandler(errorHandler, None) + +#warning_nr = 0 +#warning = '' +#def warningHandler(ctx, str): +# global warning_nr +# global warning +# +# warning_nr = warning_nr + 1 +# warning = warning + str +# +#libxml2.registerWarningHandler(warningHandler, None) + +# +# Used to load the XML testsuite description +# +def loadNoentDoc(filename): + ctxt = libxml2.createFileParserCtxt(filename) + if ctxt == None: + return None + ctxt.replaceEntities(1) + ctxt.parseDocument() + doc = ctxt.doc() + if ctxt.wellFormed() != 1: + doc.freeDoc() + return None + return doc + +# +# The conformance testing routines +# + +def testNotWf(filename, id): + global error_nr + global log + + error_nr = 0 + + ctxt = libxml2.createFileParserCtxt(filename) + if ctxt == None: + return -1 + ctxt.parseDocument() + + doc = ctxt.doc() + if error_nr == 0 or ctxt.wellFormed() != 0: + print "%s: error: Well Formedness error not detected" % (id) + log.write("%s: error: Well Formedness error not detected\n" % (id)) + doc.freeDoc() + return 0 + return 1 + +def testNotWfEnt(filename, id): + global error_nr + global log + + error_nr = 0 + + ctxt = libxml2.createFileParserCtxt(filename) + if ctxt == None: + return -1 + ctxt.replaceEntities(1) + ctxt.parseDocument() + + doc = ctxt.doc() + if error_nr == 0 or ctxt.wellFormed() != 0: + print "%s: error: Well Formedness error not detected" % (id) + log.write("%s: error: Well Formedness error not detected\n" % (id)) + doc.freeDoc() + return 0 + return 1 + +def testNotWfEntDtd(filename, id): + global error_nr + global log + + error = '' + error_nr = 0 + + ctxt = libxml2.createFileParserCtxt(filename) + if ctxt == None: + return -1 + ctxt.replaceEntities(1) + ctxt.loadSubset(1) + ctxt.parseDocument() + + doc = ctxt.doc() + if error_nr == 0 or ctxt.wellFormed() != 0: + print "%s: error: Well Formedness error not detected" % (id) + log.write("%s: error: Well Formedness error not detected\n" % (id)) + doc.freeDoc() + return 0 + return 1 + +def testWfEntDtd(filename, id): + global error_nr + global log + + error = '' + error_nr = 0 + + ctxt = libxml2.createFileParserCtxt(filename) + if ctxt == None: + return -1 + ctxt.replaceEntities(1) + ctxt.loadSubset(1) + ctxt.parseDocument() + + doc = ctxt.doc() + if ctxt.wellFormed() == 0: + print "%s: error: wrongly failed to parse the document" % (id) + log.write("%s: error: wrongly failed to parse the document\n" % (id)) + return 0 + if error_nr != 0: + print "%s: warning: WF document generated an error msg" % (id) + log.write("%s: error: WF document generated an error msg\n" % (id)) + doc.freeDoc() + return 2 + doc.freeDoc() + return 1 + +def testInvalid(filename, id): + global error_nr + global log + + error_nr = 0 + + ctxt = libxml2.createFileParserCtxt(filename) + if ctxt == None: + return -1 + ctxt.validate(1) + ctxt.parseDocument() + + doc = ctxt.doc() + valid = ctxt.isValid() + if doc == None: + print "%s: error: wrongly failed to parse the document" % (id) + log.write("%s: error: wrongly failed to parse the document\n" % (id)) + return 0 + if valid == 1: + print "%s: error: Validity error not detected" % (id) + log.write("%s: error: Validity error not detected\n" % (id)) + doc.freeDoc() + return 0 + if error_nr == 0: + print "%s: warning: Validity error not reported" % (id) + log.write("%s: warning: Validity error not reported\n" % (id)) + doc.freeDoc() + return 2 + + doc.freeDoc() + return 1 + +def testValid(filename, id): + global error_nr + + error_nr = 0 + + ctxt = libxml2.createFileParserCtxt(filename) + if ctxt == None: + return -1 + ctxt.validate(1) + ctxt.parseDocument() + + doc = ctxt.doc() + valid = ctxt.isValid() + if doc == None: + print "%s: error: wrongly failed to parse the document" % (id) + log.write("%s: error: wrongly failed to parse the document\n" % (id)) + return 0 + if valid != 1: + print "%s: error: Validity check failed" % (id) + log.write("%s: error: Validity check failed\n" % (id)) + doc.freeDoc() + return 0 + if error_nr != 0 or valid != 1: + print "%s: warning: valid document reported an error" % (id) + log.write("%s: warning: valid document reported an error\n" % (id)) + doc.freeDoc() + return 2 + doc.freeDoc() + return 1 + +test_nr = 0 +test_succeed = 0 +test_failed = 0 +test_error = 0 +def runTest(test): + global test_nr + global test_failed + global test_error + global test_succeed + global log + + uri = test.prop('URI') + id = test.prop('ID') + if uri == None: + print "Test without ID:", uri + return -1 + if id == None: + print "Test without URI:", id + return -1 + base = test.getBase(None) + URI = libxml2.buildURI(uri, base) + if os.access(URI, os.R_OK) == 0: + print "Test %s missing: base %s uri %s" % (URI, base, uri) + return -1 + type = test.prop('TYPE') + if type == None: + print "Test %s missing TYPE" % (id) + return -1 + + extra = None + if type == "invalid": + res = testInvalid(URI, id) + elif type == "valid": + res = testValid(URI, id) + elif type == "not-wf": + extra = test.prop('ENTITIES') + # print URI + #if extra == None: + # res = testNotWfEntDtd(URI, id) + #elif extra == 'none': + # res = testNotWf(URI, id) + #elif extra == 'general': + # res = testNotWfEnt(URI, id) + #elif extra == 'both' or extra == 'parameter': + res = testNotWfEntDtd(URI, id) + #else: + # print "Unknow value %s for an ENTITIES test value" % (extra) + # return -1 + elif type == "error": + res = testWfEntDtd(URI, id) + else: + # TODO skipped for now + return -1 + + test_nr = test_nr + 1 + if res > 0: + test_succeed = test_succeed + 1 + elif res == 0: + test_failed = test_failed + 1 + elif res < 0: + test_error = test_error + 1 + + # Log the ontext + if res != 1: + log.write(" File: %s\n" % (URI)) + content = test.content + if extra != None: + log.write(" %s:%s:%s\n\n" % (type, extra, content)) + else: + log.write(" %s:%s\n\n" % (type, content)) + + return 0 + + +def runTestCases(case): + profile = case.prop('PROFILE') + if profile != None and \ + string.find(profile, "IBM XML Conformance Test Suite - Production") < 0: + print "=>", profile + test = case.children + while test != None: + if test.name == 'TEST': + runTest(test) + if test.name == 'TESTCASES': + runTestCases(test) + test = test.next + +conf = loadNoentDoc(CONF) +if conf == None: + print "Unable to load %s" % CONF + sys.exit(1) + +testsuite = conf.getRootElement() +if testsuite.name != 'TESTSUITE': + print "Expecting TESTSUITE root element: aborting" + sys.exit(1) + +profile = testsuite.prop('PROFILE') +if profile != None: + print profile + +case = testsuite.children +while case != None: + global test_nr + global test_succeed + global test_failed + global test_error + + if case.name == 'TESTCASES': + old_test_nr = test_nr + old_test_succeed = test_succeed + old_test_failed = test_failed + old_test_error = test_error + runTestCases(case) + print " Ran %d tests: %d suceeded, %d failed and %d generated an error" % ( + test_nr - old_test_nr, test_succeed - old_test_succeed, + test_failed - old_test_failed, test_error - old_test_error) + case = case.next + +conf.freeDoc() +log.close() + +print "Ran %d tests: %d suceeded, %d failed and %d generated an error" % ( + test_nr, test_succeed, test_failed, test_error) diff --git a/doc/buildDocBookCatalog b/doc/buildDocBookCatalog index 64cf9317..513796a6 100755 --- a/doc/buildDocBookCatalog +++ b/doc/buildDocBookCatalog @@ -51,7 +51,7 @@ if [ "$found" = "" ] ; then found=`find /usr/share/sgml -name docbookx.dtd` fi if [ "$found" = "" ] ; then - echo could not locate docbookx.dtd drom DocBook XML + echo could not locate docbookx.dtd for DocBook XML exit 1 fi diff --git a/parser.c b/parser.c index 8a783efe..fcb9e85d 100644 --- a/parser.c +++ b/parser.c @@ -469,7 +469,11 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) { SKIP(3); GROW; while (RAW != ';') { /* loop blocked by count */ - if ((RAW >= '0') && (RAW <= '9') && (count < 20)) + if (count++ > 20) { + count = 0; + GROW; + } + if ((RAW >= '0') && (RAW <= '9')) val = val * 16 + (CUR - '0'); else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20)) val = val * 16 + (CUR - 'a') + 10; @@ -497,7 +501,11 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) { SKIP(2); GROW; while (RAW != ';') { /* loop blocked by count */ - if ((RAW >= '0') && (RAW <= '9') && (count < 20)) + if (count++ > 20) { + count = 0; + GROW; + } + if ((RAW >= '0') && (RAW <= '9')) val = val * 10 + (CUR - '0'); else { ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF; @@ -2555,7 +2563,7 @@ xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) { in = ctxt->input->cur; do { get_more: - while (((*in >= 0x20) && (*in != '<') && + while (((*in >= 0x20) && (*in != '<') && (*in != ']') && (*in != '&') && (*in <= 0x7F)) || (*in == 0x09)) in++; if (*in == 0xA) { @@ -2567,6 +2575,20 @@ get_more: } goto get_more; } + if (*in == ']') { + if ((in[1] == ']') && (in[2] == '>')) { + ctxt->errNo = XML_ERR_MISPLACED_CDATA_END; + if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) + ctxt->sax->error(ctxt->userData, + "Sequence ']]>' not allowed in content\n"); + ctxt->input->cur = in; + ctxt->wellFormed = 0; + ctxt->disableSAX = 1; + return; + } + in++; + goto get_more; + } nbchar = in - ctxt->input->cur; if (nbchar > 0) { if (IS_BLANK(*ctxt->input->cur)) { @@ -2848,7 +2870,7 @@ xmlParseComment(xmlParserCtxtPtr ctxt) { while (IS_CHAR(cur) && /* checked */ ((cur != '>') || (r != '-') || (q != '-'))) { - if ((r == '-') && (q == '-') && (len > 1)) { + if ((r == '-') && (q == '-')) { ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT; if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, @@ -4814,7 +4836,7 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) { ctxt->disableSAX = 1; ctxt->instate = XML_PARSER_IGNORE; - while (depth >= 0) { + while ((depth >= 0) && (RAW != 0)) { if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) { depth++; SKIP(3); @@ -5149,6 +5171,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { } else { ent = xmlParseEntityRef(ctxt); if (ent == NULL) return; + if (!ctxt->wellFormed) + return; if ((ent->name != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) { xmlNodePtr list = NULL; @@ -5237,6 +5261,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { "Detected entity reference loop\n"); ctxt->wellFormed = 0; ctxt->disableSAX = 1; + return; } else if ((ret == 0) && (list != NULL)) { if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) || (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&& diff --git a/python/Makefile.am b/python/Makefile.am index a3fecfc6..2978b705 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -38,7 +38,7 @@ libxml2mod_so_LDFLAGS = $(mylibs) $(LIBS) -shared -Wl,-soname,libxml2mod.so noinst_LTLIBRARIES = libxmlmodule.la libxmlmodule_la_SOURCES = libxml.c types.c libxml2-py.c -libxml2mod.so: $(libxmlmodule_la_OBJECTS) +libxml2mod.so: $(libxmlmodule_la_OBJECTS) $(mylibs) $(LINK) -o $@ $(libxmlmodule_la_OBJECTS) $(libxml2mod_so_LDFLAGS)