diff options
author | Elliott Hughes <enh@google.com> | 2021-08-10 17:33:34 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2021-08-12 16:24:12 -0700 |
commit | 33bf9751da479e7b5a99f413426ab90f5b704453 (patch) | |
tree | fcdf2ba6814f8d5611f8b2d204b3bc9b20d145ec /tests | |
parent | 667f64dc71313399b79837222985a92ade9c1c2a (diff) | |
download | expat-33bf9751da479e7b5a99f413426ab90f5b704453.tar.gz |
Upgrade expat to R_2_4_1
Test: make
Change-Id: I4a5decaf80b7aa290b5539c67c93c5f44720cd04
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 8 | ||||
-rw-r--r-- | tests/Makefile.in | 14 | ||||
-rw-r--r-- | tests/benchmark/Makefile.am | 3 | ||||
-rw-r--r-- | tests/benchmark/Makefile.in | 5 | ||||
-rw-r--r-- | tests/benchmark/benchmark.c | 6 | ||||
-rw-r--r-- | tests/chardata.c | 12 | ||||
-rw-r--r-- | tests/chardata.h | 5 | ||||
-rw-r--r-- | tests/memcheck.c | 4 | ||||
-rw-r--r-- | tests/memcheck.h | 4 | ||||
-rw-r--r-- | tests/minicheck.c | 7 | ||||
-rw-r--r-- | tests/minicheck.h | 5 | ||||
-rw-r--r-- | tests/runtests.c | 429 | ||||
-rw-r--r-- | tests/runtestspp.cpp | 4 | ||||
-rw-r--r-- | tests/structdata.c | 8 | ||||
-rw-r--r-- | tests/structdata.h | 3 | ||||
-rwxr-xr-x | tests/udiffer.py | 3 | ||||
-rwxr-xr-x | tests/xmltest.sh | 43 |
17 files changed, 502 insertions, 61 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index e19fc1ae..b34a1542 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -6,7 +6,9 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017 Expat development team +# Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org> +# Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> +# Copyright (c) 2020 Jeffrey Walton <noloader@gmail.com> # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -52,8 +54,8 @@ runtests_SOURCES = \ runtestspp_SOURCES = \ runtestspp.cpp -runtests_LDADD = libruntests.a ../lib/libexpat.la -runtestspp_LDADD = libruntests.a ../lib/libexpat.la +runtests_LDADD = libruntests.a ../lib/libexpatinternal.la +runtestspp_LDADD = libruntests.a ../lib/libexpatinternal.la EXTRA_DIST = \ chardata.h \ diff --git a/tests/Makefile.in b/tests/Makefile.in index 90cc4f70..292f6573 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -22,7 +22,9 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017 Expat development team +# Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org> +# Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> +# Copyright (c) 2020 Jeffrey Walton <noloader@gmail.com> # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -154,14 +156,14 @@ am_libruntests_a_OBJECTS = chardata.$(OBJEXT) structdata.$(OBJEXT) \ libruntests_a_OBJECTS = $(am_libruntests_a_OBJECTS) am_runtests_OBJECTS = runtests.$(OBJEXT) runtests_OBJECTS = $(am_runtests_OBJECTS) -runtests_DEPENDENCIES = libruntests.a ../lib/libexpat.la +runtests_DEPENDENCIES = libruntests.a ../lib/libexpatinternal.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_runtestspp_OBJECTS = runtestspp.$(OBJEXT) runtestspp_OBJECTS = $(am_runtestspp_OBJECTS) -runtestspp_DEPENDENCIES = libruntests.a ../lib/libexpat.la +runtestspp_DEPENDENCIES = libruntests.a ../lib/libexpatinternal.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -510,6 +512,7 @@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ @@ -590,6 +593,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_cv_sizeof_void_p = @ac_cv_sizeof_void_p@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -653,8 +657,8 @@ runtests_SOURCES = \ runtestspp_SOURCES = \ runtestspp.cpp -runtests_LDADD = libruntests.a ../lib/libexpat.la -runtestspp_LDADD = libruntests.a ../lib/libexpat.la +runtests_LDADD = libruntests.a ../lib/libexpatinternal.la +runtestspp_LDADD = libruntests.a ../lib/libexpatinternal.la EXTRA_DIST = \ chardata.h \ structdata.h \ diff --git a/tests/benchmark/Makefile.am b/tests/benchmark/Makefile.am index 5ea8dc10..f1bf3365 100644 --- a/tests/benchmark/Makefile.am +++ b/tests/benchmark/Makefile.am @@ -6,7 +6,8 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017 Expat development team +# Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org> +# Copyright (c) 2020 Jeffrey Walton <noloader@gmail.com> # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/benchmark/Makefile.in b/tests/benchmark/Makefile.in index 5882f7d0..47fdf425 100644 --- a/tests/benchmark/Makefile.in +++ b/tests/benchmark/Makefile.in @@ -22,7 +22,8 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017 Expat development team +# Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org> +# Copyright (c) 2020 Jeffrey Walton <noloader@gmail.com> # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining @@ -228,6 +229,7 @@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ @@ -308,6 +310,7 @@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_cv_sizeof_void_p = @ac_cv_sizeof_void_p@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ diff --git a/tests/benchmark/benchmark.c b/tests/benchmark/benchmark.c index fda8268f..ba2bc6e1 100644 --- a/tests/benchmark/benchmark.c +++ b/tests/benchmark/benchmark.c @@ -6,8 +6,10 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2003-2006 Karl Waclawek <karl@waclawek.net> + Copyright (c) 2005-2007 Steven Solie <ssolie@users.sourceforge.net> + Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/chardata.c b/tests/chardata.c index 75a50166..d1989a84 100644 --- a/tests/chardata.c +++ b/tests/chardata.c @@ -6,8 +6,12 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2002-2004 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> + Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> + Copyright (c) 2016 Gilles Espinasse <g.esp@free.fr> + Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2017 Joe Orton <jorton@redhat.com> + Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -30,9 +34,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_EXPAT_CONFIG_H -# include <expat_config.h> -#endif +#include <expat_config.h> #include "minicheck.h" #include <assert.h> diff --git a/tests/chardata.h b/tests/chardata.h index 4001b9b9..ccb631f6 100644 --- a/tests/chardata.h +++ b/tests/chardata.h @@ -7,8 +7,9 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2002-2004 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> + Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> + Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/memcheck.c b/tests/memcheck.c index 41355f6c..48822e5d 100644 --- a/tests/memcheck.c +++ b/tests/memcheck.c @@ -6,8 +6,8 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> + Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/memcheck.h b/tests/memcheck.h index 4d20f4bb..4c0cb728 100644 --- a/tests/memcheck.h +++ b/tests/memcheck.h @@ -7,8 +7,8 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> + Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/minicheck.c b/tests/minicheck.c index ab0c35fd..1c657481 100644 --- a/tests/minicheck.c +++ b/tests/minicheck.c @@ -10,8 +10,11 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2004-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> + Copyright (c) 2016-2020 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> + Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it> + Copyright (c) 2019 David Loffredo <loffredo@steptools.com> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/minicheck.h b/tests/minicheck.h index 88a16584..cc1f8353 100644 --- a/tests/minicheck.h +++ b/tests/minicheck.h @@ -12,8 +12,9 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2004-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> + Copyright (c) 2006-2012 Karl Waclawek <karl@waclawek.net> + Copyright (c) 2016-2017 Sebastian Pipping <sebastian@pipping.org> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/runtests.c b/tests/runtests.c index 91ab4f21..45ba5d59 100644 --- a/tests/runtests.c +++ b/tests/runtests.c @@ -6,8 +6,17 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> + Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net> + Copyright (c) 2005-2007 Steven Solie <ssolie@users.sourceforge.net> + Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net> + Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org> + Copyright (c) 2017-2018 Rhodri James <rhodri@wildebeest.org.uk> + Copyright (c) 2017 Joe Orton <jorton@redhat.com> + Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com> + Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it> + Copyright (c) 2019 David Loffredo <loffredo@steptools.com> + Copyright (c) 2020 Tim Gates <tim.gates@iress.com> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -34,9 +43,7 @@ # undef NDEBUG /* because test suite relies on assert(...) at the moment */ #endif -#ifdef HAVE_EXPAT_CONFIG_H -# include <expat_config.h> -#endif +#include <expat_config.h> #include <assert.h> #include <stdlib.h> @@ -46,6 +53,7 @@ #include <ctype.h> #include <limits.h> #include <stdint.h> /* intptr_t uint64_t */ +#include <math.h> /* NAN, INFINITY, isnan */ #if ! defined(__cplusplus) # include <stdbool.h> @@ -54,7 +62,7 @@ #include "expat.h" #include "chardata.h" #include "structdata.h" -#include "internal.h" /* for UNUSED_P only */ +#include "internal.h" #include "minicheck.h" #include "memcheck.h" #include "siphash.h" @@ -2247,7 +2255,6 @@ START_TEST(test_long_cdata_utf16) { END_TEST /* Test handling of multiple unit UTF-16 characters */ -#ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */ START_TEST(test_multichar_cdata_utf16) { /* Test data is: * <?xml version='1.0' encoding='utf-16'?> @@ -2269,11 +2276,11 @@ START_TEST(test_multichar_cdata_utf16) { "\0<\0a\0>\0<\0!\0[\0C\0D\0A\0T\0A\0[" "\xd8\x34\xdd\x5e\xd8\x34\xdd\x5f" "\0]\0]\0>\0<\0/\0a\0>"; -# ifdef XML_UNICODE +#ifdef XML_UNICODE const XML_Char *expected = XCS("\xd834\xdd5e\xd834\xdd5f"); -# else +#else const XML_Char *expected = XCS("\xf0\x9d\x85\x9e\xf0\x9d\x85\x9f"); -# endif +#endif CharData storage; CharData_Init(&storage); @@ -2286,7 +2293,6 @@ START_TEST(test_multichar_cdata_utf16) { CharData_CheckXMLChars(&storage, expected); } END_TEST -#endif /* ifndef XML_MIN_SIZE */ /* Test that an element name with a UTF-16 surrogate pair is rejected */ START_TEST(test_utf16_bad_surrogate_pair) { @@ -2371,7 +2377,6 @@ START_TEST(test_bad_cdata) { END_TEST /* Test failures in UTF-16 CDATA */ -#ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */ START_TEST(test_bad_cdata_utf16) { struct CaseData { size_t text_bytes; @@ -2444,7 +2449,6 @@ START_TEST(test_bad_cdata_utf16) { } } END_TEST -#endif /* ifndef XML_MIN_SIZE */ static const char *long_cdata_text = "<s><![CDATA[" @@ -7347,7 +7351,7 @@ START_TEST(test_misc_version) { fail("Version mismatch"); #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T) - if (xcstrcmp(version_text, XCS("expat_2.3.0"))) /* needs bump on releases */ + if (xcstrcmp(version_text, XCS("expat_2.4.1"))) /* needs bump on releases */ fail("XML_*_VERSION in expat.h out of sync?\n"); #else /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T @@ -11222,6 +11226,389 @@ START_TEST(test_nsalloc_prefixed_element) { } END_TEST +#if defined(XML_DTD) +typedef enum XML_Status (*XmlParseFunction)(XML_Parser, const char *, int, int); + +struct AccountingTestCase { + const char *primaryText; + const char *firstExternalText; /* often NULL */ + const char *secondExternalText; /* often NULL */ + const unsigned long long expectedCountBytesIndirectExtra; + XML_Bool singleBytesWanted; +}; + +static int +accounting_external_entity_ref_handler(XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId) { + UNUSED_P(context); + UNUSED_P(base); + UNUSED_P(publicId); + + const struct AccountingTestCase *const testCase + = (const struct AccountingTestCase *)XML_GetUserData(parser); + + const char *externalText = NULL; + if (xcstrcmp(systemId, XCS("first.ent")) == 0) { + externalText = testCase->firstExternalText; + } else if (xcstrcmp(systemId, XCS("second.ent")) == 0) { + externalText = testCase->secondExternalText; + } else { + assert(! "systemId is neither \"first.ent\" nor \"second.ent\""); + } + assert(externalText); + + XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); + assert(entParser); + + const XmlParseFunction xmlParseFunction + = testCase->singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; + + const enum XML_Status status = xmlParseFunction( + entParser, externalText, (int)strlen(externalText), XML_TRUE); + + XML_ParserFree(entParser); + return status; +} + +START_TEST(test_accounting_precision) { + const XML_Bool filled_later = XML_TRUE; /* value is arbitrary */ + struct AccountingTestCase cases[] = { + {"<e/>", NULL, NULL, 0, 0}, + {"<e></e>", NULL, NULL, 0, 0}, + + /* Attributes */ + {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0, filled_later}, + {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0, 0}, + {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0, + filled_later}, + {"<e k=\"&'><"\" />", NULL, NULL, + sizeof(XML_Char) * 5 /* number of predefined entites */, filled_later}, + {"<e1 xmlns='https://example.org/'>\n" + " <e2 xmlns=''/>\n" + "</e1>", + NULL, NULL, 0, filled_later}, + + /* Text */ + {"<e>text</e>", NULL, NULL, 0, filled_later}, + {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0, filled_later}, + {"<e>&'><"</e>", NULL, NULL, + sizeof(XML_Char) * 5 /* number of predefined entites */, filled_later}, + {"<e>A)</e>", NULL, NULL, 0, filled_later}, + + /* Prolog */ + {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0, filled_later}, + + /* Whitespace */ + {" <e1> <e2> </e2> </e1> ", NULL, NULL, 0, filled_later}, + {"<e1 ><e2 /></e1 >", NULL, NULL, 0, filled_later}, + {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0, filled_later}, + + /* Comments */ + {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0, filled_later}, + + /* Processing instructions */ + {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>", + NULL, NULL, 0, filled_later}, + {"<?pi0?><?pi1 ?><?pi2 ?><!DOCTYPE r SYSTEM 'first.ent'><r/>", + "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>", + 0, filled_later}, + + /* CDATA */ + {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later}, + /* The following is the essence of this OSS-Fuzz finding: + https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302 + https://oss-fuzz.com/testcase-detail/4860575394955264 + */ + {"<!DOCTYPE r [\n" + "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n" + "]>\n" + "<r>&e;</r>\n", + NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"), + filled_later}, + + /* Conditional sections */ + {"<!DOCTYPE r [\n" + "<!ENTITY % draft 'INCLUDE'>\n" + "<!ENTITY % final 'IGNORE'>\n" + "<!ENTITY % import SYSTEM \"first.ent\">\n" + "%import;\n" + "]>\n" + "<r/>\n", + "<![%draft;[<!--1-->]]>\n" + "<![%final;[<!--22-->]]>", + NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE")), + filled_later}, + + /* General entities */ + {"<!DOCTYPE root [\n" + "<!ENTITY nine \"123456789\">\n" + "]>\n" + "<root>&nine;</root>", + NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, + {"<!DOCTYPE root [\n" + "<!ENTITY nine \"123456789\">\n" + "]>\n" + "<root k1=\"&nine;\"/>", + NULL, NULL, sizeof(XML_Char) * strlen("123456789"), filled_later}, + {"<!DOCTYPE root [\n" + "<!ENTITY nine \"123456789\">\n" + "<!ENTITY nine2 \"&nine;&nine;\">\n" + "]>\n" + "<root>&nine2;&nine2;&nine2;</root>", + NULL, NULL, + sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */ + * (strlen("&nine;") + strlen("123456789")), + filled_later}, + {"<!DOCTYPE r [\n" + " <!ENTITY five SYSTEM 'first.ent'>\n" + "]>\n" + "<r>&five;</r>", + "12345", NULL, 0, filled_later}, + + /* Parameter entities */ + {"<!DOCTYPE r [\n" + "<!ENTITY % comment \"<!---->\">\n" + "%comment;\n" + "]>\n" + "<r/>", + NULL, NULL, sizeof(XML_Char) * strlen("<!---->"), filled_later}, + {"<!DOCTYPE r [\n" + "<!ENTITY % ninedef \"<!ENTITY nine "123456789">\">\n" + "%ninedef;\n" + "]>\n" + "<r>&nine;</r>", + NULL, NULL, + sizeof(XML_Char) + * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789")), + filled_later}, + {"<!DOCTYPE r [\n" + "<!ENTITY % comment \"<!--1-->\">\n" + "<!ENTITY % comment2 \"%comment;<!--22-->%comment;\">\n" + "%comment2;\n" + "]>\n" + "<r/>\n", + NULL, NULL, + sizeof(XML_Char) + * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->")), + filled_later}, + {"<!DOCTYPE r [\n" + " <!ENTITY % five \"12345\">\n" + " <!ENTITY % five2def \"<!ENTITY five2 "[%five;][%five;]]]]">\">\n" + " %five2def;\n" + "]>\n" + "<r>&five2;</r>", + NULL, NULL, /* from "%five2def;": */ + sizeof(XML_Char) + * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">") + + 2 /* calls to "%five;" */ * strlen("12345") + + /* from "&five2;": */ strlen("[12345][12345]]]]")), + filled_later}, + {"<!DOCTYPE r SYSTEM \"first.ent\">\n" + "<r/>", + "<!ENTITY % comment '<!--1-->'>\n" + "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n" + "%comment2;", + NULL, + sizeof(XML_Char) + * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->") + + 2 /* calls to "%comment;" */ * strlen("<!---->")), + filled_later}, + {"<!DOCTYPE r SYSTEM 'first.ent'>\n" + "<r/>", + "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n" + "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n" + "%e2;\n", + "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->"), + filled_later}, + { + "<!DOCTYPE r SYSTEM 'first.ent'>\n" + "<r/>", + "<!ENTITY % e1 SYSTEM 'second.ent'>\n" + "<!ENTITY % e2 '%e1;'>", + "<?xml version='1.0' encoding='utf-8'?>\n" + "hello\n" + "xml" /* without trailing newline! */, + 0, + filled_later, + }, + { + "<!DOCTYPE r SYSTEM 'first.ent'>\n" + "<r/>", + "<!ENTITY % e1 SYSTEM 'second.ent'>\n" + "<!ENTITY % e2 '%e1;'>", + "<?xml version='1.0' encoding='utf-8'?>\n" + "hello\n" + "xml\n" /* with trailing newline! */, + 0, + filled_later, + }, + {"<!DOCTYPE doc SYSTEM 'first.ent'>\n" + "<doc></doc>\n", + "<!ELEMENT doc EMPTY>\n" + "<!ENTITY % e1 SYSTEM 'second.ent'>\n" + "<!ENTITY % e2 '%e1;'>\n" + "%e1;\n", + "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */, + strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>"), filled_later}, + {"<!DOCTYPE r [\n" + " <!ENTITY five SYSTEM 'first.ent'>\n" + "]>\n" + "<r>&five;</r>", + "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0, filled_later}, + }; + + const size_t countCases = sizeof(cases) / sizeof(cases[0]); + size_t u = 0; + for (; u < countCases; u++) { + size_t v = 0; + for (; v < 2; v++) { + const XML_Bool singleBytesWanted = (v == 0) ? XML_FALSE : XML_TRUE; + const unsigned long long expectedCountBytesDirect + = strlen(cases[u].primaryText); + const unsigned long long expectedCountBytesIndirect + = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText) + : 0) + + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText) + : 0) + + cases[u].expectedCountBytesIndirectExtra; + + XML_Parser parser = XML_ParserCreate(NULL); + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + if (cases[u].firstExternalText) { + XML_SetExternalEntityRefHandler(parser, + accounting_external_entity_ref_handler); + XML_SetUserData(parser, (void *)&cases[u]); + cases[u].singleBytesWanted = singleBytesWanted; + } + + const XmlParseFunction xmlParseFunction + = singleBytesWanted ? _XML_Parse_SINGLE_BYTES : XML_Parse; + + enum XML_Status status + = xmlParseFunction(parser, cases[u].primaryText, + (int)strlen(cases[u].primaryText), XML_TRUE); + if (status != XML_STATUS_OK) { + _xml_failure(parser, __FILE__, __LINE__); + } + + const unsigned long long actualCountBytesDirect + = testingAccountingGetCountBytesDirect(parser); + const unsigned long long actualCountBytesIndirect + = testingAccountingGetCountBytesIndirect(parser); + + XML_ParserFree(parser); + + if (actualCountBytesDirect != expectedCountBytesDirect) { + fprintf( + stderr, + "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( + "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n", + u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", + expectedCountBytesDirect, actualCountBytesDirect); + fail("Count of direct bytes is off"); + } + + if (actualCountBytesIndirect != expectedCountBytesIndirect) { + fprintf( + stderr, + "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ", %s: Expected " EXPAT_FMT_ULL( + "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n", + u + 1, countCases, singleBytesWanted ? "single bytes" : "chunks", + expectedCountBytesIndirect, actualCountBytesIndirect); + fail("Count of indirect bytes is off"); + } + } + } +} +END_TEST + +START_TEST(test_billion_laughs_attack_protection_api) { + XML_Parser parserWithoutParent = XML_ParserCreate(NULL); + XML_Parser parserWithParent + = XML_ExternalEntityParserCreate(parserWithoutParent, NULL, NULL); + if (parserWithoutParent == NULL) + fail("parserWithoutParent is NULL"); + if (parserWithParent == NULL) + fail("parserWithParent is NULL"); + + // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases + if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f) + == XML_TRUE) + fail("Call with NULL parser is NOT supposed to succeed"); + if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent, + 123.0f) + == XML_TRUE) + fail("Call with non-root parser is NOT supposed to succeed"); + if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( + parserWithoutParent, NAN) + == XML_TRUE) + fail("Call with NaN limit is NOT supposed to succeed"); + if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( + parserWithoutParent, -1.0f) + == XML_TRUE) + fail("Call with negative limit is NOT supposed to succeed"); + if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( + parserWithoutParent, 0.9f) + == XML_TRUE) + fail("Call with positive limit <1.0 is NOT supposed to succeed"); + + // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases + if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( + parserWithoutParent, 1.0f) + == XML_FALSE) + fail("Call with positive limit >=1.0 is supposed to succeed"); + if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( + parserWithoutParent, 123456.789f) + == XML_FALSE) + fail("Call with positive limit >=1.0 is supposed to succeed"); + if (XML_SetBillionLaughsAttackProtectionMaximumAmplification( + parserWithoutParent, INFINITY) + == XML_FALSE) + fail("Call with positive limit >=1.0 is supposed to succeed"); + + // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases + if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123) + == XML_TRUE) + fail("Call with NULL parser is NOT supposed to succeed"); + if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent, + 123) + == XML_TRUE) + fail("Call with non-root parser is NOT supposed to succeed"); + + // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases + if (XML_SetBillionLaughsAttackProtectionActivationThreshold( + parserWithoutParent, 123) + == XML_FALSE) + fail("Call with non-NULL parentless parser is supposed to succeed"); + + XML_ParserFree(parserWithParent); + XML_ParserFree(parserWithoutParent); +} +END_TEST + +START_TEST(test_helper_unsigned_char_to_printable) { + // Smoke test + unsigned char uc = 0; + for (; uc < (unsigned char)-1; uc++) { + const char *const printable = unsignedCharToPrintable(uc); + if (printable == NULL) + fail("unsignedCharToPrintable returned NULL"); + if (strlen(printable) < (size_t)1) + fail("unsignedCharToPrintable returned empty string"); + } + + // Two concrete samples + if (strcmp(unsignedCharToPrintable('A'), "A") != 0) + fail("unsignedCharToPrintable result mistaken"); + if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0) + fail("unsignedCharToPrintable result mistaken"); +} +END_TEST +#endif // defined(XML_DTD) + static Suite * make_suite(void) { Suite *s = suite_create("basic"); @@ -11230,6 +11617,9 @@ make_suite(void) { TCase *tc_misc = tcase_create("miscellaneous tests"); TCase *tc_alloc = tcase_create("allocation tests"); TCase *tc_nsalloc = tcase_create("namespace allocation tests"); +#if defined(XML_DTD) + TCase *tc_accounting = tcase_create("accounting tests"); +#endif suite_add_tcase(s, tc_basic); tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown); @@ -11303,14 +11693,10 @@ make_suite(void) { tcase_add_test(tc_basic, test_good_cdata_utf16); tcase_add_test(tc_basic, test_good_cdata_utf16_le); tcase_add_test(tc_basic, test_long_cdata_utf16); -#ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */ tcase_add_test(tc_basic, test_multichar_cdata_utf16); -#endif tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair); tcase_add_test(tc_basic, test_bad_cdata); -#ifndef XML_MIN_SIZE /* FIXME workaround -DXML_MIN_SIZE + ASan (issue #332) */ tcase_add_test(tc_basic, test_bad_cdata_utf16); -#endif tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls); tcase_add_test(tc_basic, test_suspend_parser_between_cdata_calls); tcase_add_test(tc_basic, test_memory_allocation); @@ -11594,6 +11980,13 @@ make_suite(void) { tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext); tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element); +#if defined(XML_DTD) + suite_add_tcase(s, tc_accounting); + tcase_add_test(tc_accounting, test_accounting_precision); + tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api); + tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable); +#endif + return s; } diff --git a/tests/runtestspp.cpp b/tests/runtestspp.cpp index fd3ceaa9..52f53052 100644 --- a/tests/runtestspp.cpp +++ b/tests/runtestspp.cpp @@ -9,8 +9,8 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> + Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/structdata.c b/tests/structdata.c index e81b7b18..d40e6c4b 100644 --- a/tests/structdata.c +++ b/tests/structdata.c @@ -6,8 +6,8 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> + Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -30,9 +30,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_EXPAT_CONFIG_H -# include "expat_config.h" -#endif +#include "expat_config.h" #include <assert.h> #include <stdlib.h> diff --git a/tests/structdata.h b/tests/structdata.h index 870ffaf2..09881b17 100644 --- a/tests/structdata.h +++ b/tests/structdata.h @@ -7,8 +7,7 @@ \___/_/\_\ .__/ \__,_|\__| |_| XML parser - Copyright (c) 1997-2000 Thai Open Source Software Center Ltd - Copyright (c) 2000-2017 Expat development team + Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/udiffer.py b/tests/udiffer.py index 6fb91be7..2b58a4c3 100755 --- a/tests/udiffer.py +++ b/tests/udiffer.py @@ -6,7 +6,8 @@ # \___/_/\_\ .__/ \__,_|\__| # |_| XML parser # -# Copyright (c) 2017 Expat development team +# Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> +# Copyright (c) 2017 Sebastian Pipping <sebastian@pipping.org> # Licensed under the MIT license: # # Permission is hereby granted, free of charge, to any person obtaining diff --git a/tests/xmltest.sh b/tests/xmltest.sh index 9b500351..dc409d01 100755 --- a/tests/xmltest.sh +++ b/tests/xmltest.sh @@ -1,24 +1,55 @@ #! /usr/bin/env bash - -# EXPAT TEST SCRIPT FOR W3C XML TEST SUITE - +# EXPAT TEST SCRIPT FOR W3C XML TEST SUITE +# # This script can be used to exercise Expat against the # w3c.org xml test suite, available from # http://www.w3.org/XML/Test/xmlts20020606.zip. - +# # To run this script, first set XMLWF below so that xmlwf can be # found, then set the output directory with OUTPUT. - +# # The script lists all test cases where Expat shows a discrepancy # from the expected result. Test cases where only the canonical # output differs are prefixed with "Output differs:", and a diff file # is generated in the appropriate subdirectory under $OUTPUT. - +# # If there are output files provided, the script will use # output from xmlwf and compare the desired output against it. # However, one has to take into account that the canonical output # produced by xmlwf conforms to an older definition of canonical XML # and does not generate notation declarations. +# +# __ __ _ +# ___\ \/ /_ __ __ _| |_ +# / _ \\ /| '_ \ / _` | __| +# | __// \| |_) | (_| | |_ +# \___/_/\_\ .__/ \__,_|\__| +# |_| XML parser +# +# Copyright (c) 2002-2004 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> +# Copyright (c) 2002 Karl Waclawek <karl@waclawek.net> +# Copyright (c) 2008-2019 Sebastian Pipping <sebastian@pipping.org> +# Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> +# Licensed under the MIT license: +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the +# following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +# USE OR OTHER DEALINGS IN THE SOFTWARE. shopt -s nullglob |