summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2024-11-12 20:33:39 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2024-11-12 20:33:39 +0000
commita6c6dbe4d7e62c2bdd1308242aec0d9e11cee5b8 (patch)
tree9f39d4764a6663bad4d4ac03cad6f7b58ee5b795 /lib
parentf170683aac7637bf94515fbaae2d48f3e9086811 (diff)
Update libexpat to version 2.6.4.
Relevant for OpenBSD are security fix #915, other changes #905 #902 #904 #317 #918 #914. Major library bump is necessary as new error constant has been added to a public header file. CVE-2024-50602 OK matthieu@ tb@ deraadt@
Diffstat (limited to 'lib')
-rw-r--r--lib/libexpat/Changes31
-rw-r--r--lib/libexpat/README.md47
-rw-r--r--lib/libexpat/doc/reference.html2
-rw-r--r--lib/libexpat/examples/element_declarations.c9
-rw-r--r--lib/libexpat/lib/expat.h6
-rw-r--r--lib/libexpat/lib/xmlparse.c18
-rw-r--r--lib/libexpat/shlib_version4
-rw-r--r--lib/libexpat/tests/basic_tests.c17
-rw-r--r--lib/libexpat/tests/common.c33
-rw-r--r--lib/libexpat/tests/common.h11
-rw-r--r--lib/libexpat/tests/handlers.c42
-rw-r--r--lib/libexpat/tests/handlers.h17
-rw-r--r--lib/libexpat/tests/misc_tests.c39
13 files changed, 195 insertions, 81 deletions
diff --git a/lib/libexpat/Changes b/lib/libexpat/Changes
index c1d22efa5a3..aa19f70ae21 100644
--- a/lib/libexpat/Changes
+++ b/lib/libexpat/Changes
@@ -30,6 +30,37 @@
!! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+Release 2.6.4 Wed November 6 2024
+ Security fixes:
+ #915 CVE-2024-50602 -- Fix crash within function XML_ResumeParser
+ from a NULL pointer dereference by disallowing function
+ XML_StopParser to (stop or) suspend an unstarted parser.
+ A new error code XML_ERROR_NOT_STARTED was introduced to
+ properly communicate this situation. // CWE-476 CWE-754
+
+ Other changes:
+ #903 CMake: Add alias target "expat::expat"
+ #905 docs: Document use via CMake >=3.18 with FetchContent
+ and SOURCE_SUBDIR and its consequences
+ #902 tests: Reduce use of global parser instance
+ #904 tests: Resolve duplicate handler
+ #317 #918 tests: Improve tests on doctype closing (ex CVE-2019-15903)
+ #914 Fix signedness of format strings
+ #919 #920 Version info bumped from 10:3:9 (libexpat*.so.1.9.3)
+ to 11:0:10 (libexpat*.so.1.10.0); see https://verbump.de/
+ for what these numbers do
+
+ Infrastructure:
+ #907 CI: Upgrade Clang from 18 to 19
+ #913 CI: Drop macos-12 and add macos-15
+ #910 CI: Adapt to breaking changes in GitHub Actions
+ #898 Add missing entries to .gitignore
+
+ Special thanks to:
+ Hanno Böck
+ José Eduardo Gutiérrez Conejo
+ José Ricardo Cardona Quesada
+
Release 2.6.3 Wed September 4 2024
Security fixes:
#887 #890 CVE-2024-45490 -- Calling function XML_ParseBuffer with
diff --git a/lib/libexpat/README.md b/lib/libexpat/README.md
index 180a68e4abb..23d26dad2b9 100644
--- a/lib/libexpat/README.md
+++ b/lib/libexpat/README.md
@@ -11,7 +11,7 @@
> at the top of the `Changes` file.
-# Expat, Release 2.6.3
+# Expat, Release 2.6.4
This is Expat, a C99 library for parsing
[XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by
@@ -43,9 +43,9 @@ This license is the same as the MIT/X Consortium license.
## Using libexpat in your CMake-Based Project
-There are two ways of using libexpat with CMake:
+There are three documented ways of using libexpat with CMake:
-### a) Module Mode
+### a) `find_package` with Module Mode
This approach leverages CMake's own [module `FindEXPAT`](https://cmake.org/cmake/help/latest/module/FindEXPAT.html).
@@ -70,7 +70,7 @@ target_include_directories(hello PRIVATE ${EXPAT_INCLUDE_DIRS})
target_link_libraries(hello PUBLIC ${EXPAT_LIBRARIES})
```
-### b) Config Mode
+### b) `find_package` with Config Mode
This approach requires files from…
@@ -98,6 +98,45 @@ add_executable(hello
target_link_libraries(hello PUBLIC expat::expat)
```
+### c) The `FetchContent` module
+
+This approach — as demonstrated below — requires CMake >=3.18 for both the
+[`FetchContent` module](https://cmake.org/cmake/help/latest/module/FetchContent.html)
+and its support for the `SOURCE_SUBDIR` option to be available.
+
+Please note that:
+- Use of the `FetchContent` module with *non-release* SHA1s or `master`
+ of libexpat is neither advised nor considered officially supported.
+- Pinning to a specific commit is great for robust CI.
+- Pinning to a specific commit needs updating every time there is a new
+ release of libexpat — either manually or through automation —,
+ to not miss out on libexpat security updates.
+
+For an example that pulls in libexpat via Git:
+
+```cmake
+cmake_minimum_required(VERSION 3.18)
+
+include(FetchContent)
+
+project(hello VERSION 1.0.0)
+
+FetchContent_Declare(
+ expat
+ GIT_REPOSITORY https://github.com/libexpat/libexpat/
+ GIT_TAG 000000000_GIT_COMMIT_SHA1_HERE_000000000 # i.e. Git tag R_0_Y_Z
+ SOURCE_SUBDIR expat/
+)
+
+FetchContent_MakeAvailable(expat)
+
+add_executable(hello
+ hello.c
+)
+
+target_link_libraries(hello PUBLIC expat)
+```
+
## Building from a Git Clone
diff --git a/lib/libexpat/doc/reference.html b/lib/libexpat/doc/reference.html
index 4cfb2ce9384..c2ae9bb7143 100644
--- a/lib/libexpat/doc/reference.html
+++ b/lib/libexpat/doc/reference.html
@@ -52,7 +52,7 @@
<div>
<h1>
The Expat XML Parser
- <small>Release 2.6.3</small>
+ <small>Release 2.6.4</small>
</h1>
</div>
<div class="content">
diff --git a/lib/libexpat/examples/element_declarations.c b/lib/libexpat/examples/element_declarations.c
index 7ce8544f6f0..d644b2ffa5e 100644
--- a/lib/libexpat/examples/element_declarations.c
+++ b/lib/libexpat/examples/element_declarations.c
@@ -15,6 +15,7 @@
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
Copyright (c) 2019 Zhongyuan Zhou <zhouzhongyuan@huawei.com>
+ Copyright (c) 2024 Hanno Böck <hanno@gentoo.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -127,15 +128,15 @@ dumpContentModelElement(const XML_Content *model, unsigned level,
}
// Node
- printf("[%u] type=%s(%d), quant=%s(%d)", (unsigned)(model - root),
- contentTypeName(model->type), model->type,
- contentQuantName(model->quant), model->quant);
+ printf("[%u] type=%s(%u), quant=%s(%u)", (unsigned)(model - root),
+ contentTypeName(model->type), (unsigned int)model->type,
+ contentQuantName(model->quant), (unsigned int)model->quant);
if (model->name) {
printf(", name=\"%" XML_FMT_STR "\"", model->name);
} else {
printf(", name=NULL");
}
- printf(", numchildren=%d", model->numchildren);
+ printf(", numchildren=%u", model->numchildren);
printf("\n");
}
diff --git a/lib/libexpat/lib/expat.h b/lib/libexpat/lib/expat.h
index d0d6015a662..523b37d8d57 100644
--- a/lib/libexpat/lib/expat.h
+++ b/lib/libexpat/lib/expat.h
@@ -130,7 +130,9 @@ enum XML_Error {
/* Added in 2.3.0. */
XML_ERROR_NO_BUFFER,
/* Added in 2.4.0. */
- XML_ERROR_AMPLIFICATION_LIMIT_BREACH
+ XML_ERROR_AMPLIFICATION_LIMIT_BREACH,
+ /* Added in 2.6.4. */
+ XML_ERROR_NOT_STARTED,
};
enum XML_Content_Type {
@@ -1066,7 +1068,7 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
*/
#define XML_MAJOR_VERSION 2
#define XML_MINOR_VERSION 6
-#define XML_MICRO_VERSION 3
+#define XML_MICRO_VERSION 4
#ifdef __cplusplus
}
diff --git a/lib/libexpat/lib/xmlparse.c b/lib/libexpat/lib/xmlparse.c
index d9285b213b3..a4e091e7c33 100644
--- a/lib/libexpat/lib/xmlparse.c
+++ b/lib/libexpat/lib/xmlparse.c
@@ -1,4 +1,4 @@
-/* ba4cdf9bdb534f355a9def4c9e25d20ee8e72f95b0a4d930be52e563f5080196 (2.6.3+)
+/* c5625880f4bf417c1463deee4eb92d86ff413f802048621c57e25fe483eb59e4 (2.6.4+)
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
@@ -40,6 +40,7 @@
Copyright (c) 2023 Owain Davies <owaind@bath.edu>
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2024 Berkay Eren Ürün <berkay.ueruen@siemens.com>
+ Copyright (c) 2024 Hanno Böck <hanno@gentoo.org>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@@ -2234,6 +2235,9 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable) {
if (parser == NULL)
return XML_STATUS_ERROR;
switch (parser->m_parsingStatus.parsing) {
+ case XML_INITIALIZED:
+ parser->m_errorCode = XML_ERROR_NOT_STARTED;
+ return XML_STATUS_ERROR;
case XML_SUSPENDED:
if (resumable) {
parser->m_errorCode = XML_ERROR_SUSPENDED;
@@ -2244,7 +2248,7 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable) {
case XML_FINISHED:
parser->m_errorCode = XML_ERROR_FINISHED;
return XML_STATUS_ERROR;
- default:
+ case XML_PARSING:
if (resumable) {
#ifdef XML_DTD
if (parser->m_isParamEntity) {
@@ -2255,6 +2259,9 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable) {
parser->m_parsingStatus.parsing = XML_SUSPENDED;
} else
parser->m_parsingStatus.parsing = XML_FINISHED;
+ break;
+ default:
+ assert(0);
}
return XML_STATUS_OK;
}
@@ -2519,6 +2526,9 @@ XML_ErrorString(enum XML_Error code) {
case XML_ERROR_AMPLIFICATION_LIMIT_BREACH:
return XML_L(
"limit on input amplification factor (from DTD and entities) breached");
+ /* Added in 2.6.4. */
+ case XML_ERROR_NOT_STARTED:
+ return XML_L("parser not started");
}
return NULL;
}
@@ -7856,7 +7866,7 @@ accountingReportDiff(XML_Parser rootParser,
assert(! rootParser->m_parentParser);
fprintf(stderr,
- " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"",
+ " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%u, xmlparse.c:%d) %*s\"",
bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP",
levelsAwayFromRootParser, source_line, 10, "");
@@ -7969,7 +7979,7 @@ entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
fprintf(
stderr,
- "expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n",
+ "expat: Entities(%p): Count %9u, depth %2u/%2u %*s%s%s; %s length %d (xmlparse.c:%d)\n",
(void *)rootParser, rootParser->m_entity_stats.countEverOpened,
rootParser->m_entity_stats.currentDepth,
rootParser->m_entity_stats.maximumDepthSeen,
diff --git a/lib/libexpat/shlib_version b/lib/libexpat/shlib_version
index 7cc7abc9d73..77913220429 100644
--- a/lib/libexpat/shlib_version
+++ b/lib/libexpat/shlib_version
@@ -1,2 +1,2 @@
-major=14
-minor=1
+major=15
+minor=0
diff --git a/lib/libexpat/tests/basic_tests.c b/lib/libexpat/tests/basic_tests.c
index 5dba5ed594f..cb124a24ecd 100644
--- a/lib/libexpat/tests/basic_tests.c
+++ b/lib/libexpat/tests/basic_tests.c
@@ -2357,11 +2357,20 @@ START_TEST(test_attributes) {
info[0].attributes = doc_info;
info[1].attributes = tag_info;
- XML_SetStartElementHandler(g_parser, counting_start_element_handler);
- XML_SetUserData(g_parser, info);
- if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert_true(parser != NULL);
+ ParserAndElementInfo parserAndElementInfos = {
+ parser,
+ info,
+ };
+
+ XML_SetStartElementHandler(parser, counting_start_element_handler);
+ XML_SetUserData(parser, &parserAndElementInfos);
+ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
== XML_STATUS_ERROR)
- xml_failure(g_parser);
+ xml_failure(parser);
+
+ XML_ParserFree(parser);
}
END_TEST
diff --git a/lib/libexpat/tests/common.c b/lib/libexpat/tests/common.c
index 26d0c5473a6..3aea8d74d1e 100644
--- a/lib/libexpat/tests/common.c
+++ b/lib/libexpat/tests/common.c
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017-2022 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>
@@ -51,6 +51,7 @@
#include "chardata.h"
#include "minicheck.h"
#include "common.h"
+#include "handlers.h"
/* Common test data */
@@ -221,30 +222,6 @@ _expect_failure(const char *text, enum XML_Error errorCode,
_xml_failure(g_parser, file, lineno);
}
-/* Character data support for handlers, built on top of the code in
- * chardata.c
- */
-void XMLCALL
-accumulate_characters(void *userData, const XML_Char *s, int len) {
- CharData_AppendXMLChars((CharData *)userData, s, len);
-}
-
-void XMLCALL
-accumulate_attribute(void *userData, const XML_Char *name,
- const XML_Char **atts) {
- CharData *storage = (CharData *)userData;
- UNUSED_P(name);
- /* Check there are attributes to deal with */
- if (atts == NULL)
- return;
-
- while (storage->count < 0 && atts[0] != NULL) {
- /* "accumulate" the value of the first attribute we see */
- CharData_AppendXMLChars(storage, atts[1], -1);
- atts += 2;
- }
-}
-
void
_run_character_check(const char *text, const XML_Char *expected,
const char *file, int line) {
@@ -273,12 +250,6 @@ _run_attribute_check(const char *text, const XML_Char *expected,
CharData_CheckXMLChars(&storage, expected);
}
-void XMLCALL
-ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
- ExtTest *test_data = (ExtTest *)userData;
- accumulate_characters(test_data->storage, s, len);
-}
-
void
_run_ext_character_check(const char *text, ExtTest *test_data,
const XML_Char *expected, const char *file, int line) {
diff --git a/lib/libexpat/tests/common.h b/lib/libexpat/tests/common.h
index 52f00cc0eeb..bc4c7da6807 100644
--- a/lib/libexpat/tests/common.h
+++ b/lib/libexpat/tests/common.h
@@ -10,7 +10,7 @@
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
- Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org>
+ Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
Copyright (c) 2017-2022 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>
@@ -111,12 +111,6 @@ extern void _expect_failure(const char *text, enum XML_Error errorCode,
/* Support functions for handlers to collect up character and attribute data.
*/
-extern void XMLCALL accumulate_characters(void *userData, const XML_Char *s,
- int len);
-
-extern void XMLCALL accumulate_attribute(void *userData, const XML_Char *name,
- const XML_Char **atts);
-
extern void _run_character_check(const char *text, const XML_Char *expected,
const char *file, int line);
@@ -135,9 +129,6 @@ typedef struct ExtTest {
CharData *storage;
} ExtTest;
-extern void XMLCALL ext_accumulate_characters(void *userData, const XML_Char *s,
- int len);
-
extern void _run_ext_character_check(const char *text, ExtTest *test_data,
const XML_Char *expected, const char *file,
int line);
diff --git a/lib/libexpat/tests/handlers.c b/lib/libexpat/tests/handlers.c
index 449ada70f9a..0211985fe95 100644
--- a/lib/libexpat/tests/handlers.c
+++ b/lib/libexpat/tests/handlers.c
@@ -103,7 +103,9 @@ end_element_event_handler2(void *userData, const XML_Char *name) {
void XMLCALL
counting_start_element_handler(void *userData, const XML_Char *name,
const XML_Char **atts) {
- ElementInfo *info = (ElementInfo *)userData;
+ ParserAndElementInfo *const parserAndElementInfos
+ = (ParserAndElementInfo *)userData;
+ ElementInfo *info = parserAndElementInfos->info;
AttrInfo *attr;
int count, id, i;
@@ -120,12 +122,12 @@ counting_start_element_handler(void *userData, const XML_Char *name,
* is possibly a little unexpected, but it is what the
* documentation in expat.h tells us to expect.
*/
- count = XML_GetSpecifiedAttributeCount(g_parser);
+ count = XML_GetSpecifiedAttributeCount(parserAndElementInfos->parser);
if (info->attr_count * 2 != count) {
fail("Not got expected attribute count");
return;
}
- id = XML_GetIdAttributeIndex(g_parser);
+ id = XML_GetIdAttributeIndex(parserAndElementInfos->parser);
if (id == -1 && info->id_name != NULL) {
fail("ID not present");
return;
@@ -1881,12 +1883,6 @@ accumulate_entity_decl(void *userData, const XML_Char *entityName,
}
void XMLCALL
-accumulate_char_data(void *userData, const XML_Char *s, int len) {
- CharData *const storage = (CharData *)userData;
- CharData_AppendXMLChars(storage, s, len);
-}
-
-void XMLCALL
accumulate_start_element(void *userData, const XML_Char *name,
const XML_Char **atts) {
CharData *const storage = (CharData *)userData;
@@ -1911,6 +1907,34 @@ accumulate_start_element(void *userData, const XML_Char *name,
}
void XMLCALL
+accumulate_characters(void *userData, const XML_Char *s, int len) {
+ CharData *const storage = (CharData *)userData;
+ CharData_AppendXMLChars(storage, s, len);
+}
+
+void XMLCALL
+accumulate_attribute(void *userData, const XML_Char *name,
+ const XML_Char **atts) {
+ CharData *const storage = (CharData *)userData;
+ UNUSED_P(name);
+ /* Check there are attributes to deal with */
+ if (atts == NULL)
+ return;
+
+ while (storage->count < 0 && atts[0] != NULL) {
+ /* "accumulate" the value of the first attribute we see */
+ CharData_AppendXMLChars(storage, atts[1], -1);
+ atts += 2;
+ }
+}
+
+void XMLCALL
+ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
+ ExtTest *const test_data = (ExtTest *)userData;
+ accumulate_characters(test_data->storage, s, len);
+}
+
+void XMLCALL
checking_default_handler(void *userData, const XML_Char *s, int len) {
DefaultCheck *data = (DefaultCheck *)userData;
int i;
diff --git a/lib/libexpat/tests/handlers.h b/lib/libexpat/tests/handlers.h
index e1f0995f79e..8850bb948da 100644
--- a/lib/libexpat/tests/handlers.h
+++ b/lib/libexpat/tests/handlers.h
@@ -92,6 +92,11 @@ typedef struct elementInfo {
AttrInfo *attributes;
} ElementInfo;
+typedef struct StructParserAndElementInfo {
+ XML_Parser parser;
+ ElementInfo *info;
+} ParserAndElementInfo;
+
extern void XMLCALL counting_start_element_handler(void *userData,
const XML_Char *name,
const XML_Char **atts);
@@ -564,13 +569,19 @@ extern void XMLCALL accumulate_entity_decl(
const XML_Char *systemId, const XML_Char *publicId,
const XML_Char *notationName);
-extern void XMLCALL accumulate_char_data(void *userData, const XML_Char *s,
- int len);
-
extern void XMLCALL accumulate_start_element(void *userData,
const XML_Char *name,
const XML_Char **atts);
+extern void XMLCALL accumulate_characters(void *userData, const XML_Char *s,
+ int len);
+
+extern void XMLCALL accumulate_attribute(void *userData, const XML_Char *name,
+ const XML_Char **atts);
+
+extern void XMLCALL ext_accumulate_characters(void *userData, const XML_Char *s,
+ int len);
+
typedef struct default_check {
const XML_Char *expected;
const int expectedLen;
diff --git a/lib/libexpat/tests/misc_tests.c b/lib/libexpat/tests/misc_tests.c
index 2ee9320b139..9afe0922d6b 100644
--- a/lib/libexpat/tests/misc_tests.c
+++ b/lib/libexpat/tests/misc_tests.c
@@ -208,7 +208,7 @@ START_TEST(test_misc_version) {
if (! versions_equal(&read_version, &parsed_version))
fail("Version mismatch");
- if (xcstrcmp(version_text, XCS("expat_2.6.3"))) /* needs bump on releases */
+ if (xcstrcmp(version_text, XCS("expat_2.6.4"))) /* needs bump on releases */
fail("XML_*_VERSION in expat.h out of sync?\n");
}
END_TEST
@@ -332,14 +332,15 @@ START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
"<!ENTITY % e ']><d/>'>\n"
"\n"
"%e;";
- const char *const inputTwo = "<!DOCTYPE d [\n"
- "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
- "\n"
- "%e2;";
+ const char *const inputTwo
+ = "<!DOCTYPE d [\n"
+ "<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&#37;e1;'>\n"
+ "\n"
+ "%e2;";
const char *const inputThree = "<!DOCTYPE d [\n"
"<!ENTITY % e ']><d'>\n"
"\n"
- "%e;";
+ "%e;/>";
const char *const inputIssue317 = "<!DOCTYPE doc [\n"
"<!ENTITY % foo ']>\n"
"<doc>Hell<oc (#PCDATA)*>'>\n"
@@ -447,7 +448,7 @@ START_TEST(test_misc_general_entities_support) {
XML_SetExternalEntityRefHandler(parser,
external_entity_failer__if_not_xml_ge);
XML_SetEntityDeclHandler(parser, accumulate_entity_decl);
- XML_SetCharacterDataHandler(parser, accumulate_char_data);
+ XML_SetCharacterDataHandler(parser, accumulate_characters);
if (_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), XML_TRUE)
!= XML_STATUS_OK) {
@@ -496,6 +497,28 @@ START_TEST(test_misc_char_handler_stop_without_leak) {
}
END_TEST
+START_TEST(test_misc_resumeparser_not_crashing) {
+ XML_Parser parser = XML_ParserCreate(NULL);
+ XML_GetBuffer(parser, 1);
+ XML_StopParser(parser, /*resumable=*/XML_TRUE);
+ XML_ResumeParser(parser); // could crash here, previously
+ XML_ParserFree(parser);
+}
+END_TEST
+
+START_TEST(test_misc_stopparser_rejects_unstarted_parser) {
+ const XML_Bool cases[] = {XML_TRUE, XML_FALSE};
+ for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
+ const XML_Bool resumable = cases[i];
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert_true(XML_GetErrorCode(parser) == XML_ERROR_NONE);
+ assert_true(XML_StopParser(parser, resumable) == XML_STATUS_ERROR);
+ assert_true(XML_GetErrorCode(parser) == XML_ERROR_NOT_STARTED);
+ XML_ParserFree(parser);
+ }
+}
+END_TEST
+
void
make_miscellaneous_test_case(Suite *s) {
TCase *tc_misc = tcase_create("miscellaneous tests");
@@ -520,4 +543,6 @@ make_miscellaneous_test_case(Suite *s) {
test_misc_create_external_entity_parser_with_null_context);
tcase_add_test(tc_misc, test_misc_general_entities_support);
tcase_add_test(tc_misc, test_misc_char_handler_stop_without_leak);
+ tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing);
+ tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
}