add test for CVE-2022-40674
This commit is contained in:
parent
3418237b0e
commit
448e94c4d1
52
backport-0001-CVE-2022-40674.patch
Normal file
52
backport-0001-CVE-2022-40674.patch
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
From 4a32da87e931ba54393d465bb77c40b5c33d343b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rhodri James <rhodri@wildebeest.org.uk>
|
||||||
|
Date: Wed, 17 Aug 2022 18:26:18 +0100
|
||||||
|
Subject: [PATCH] Ensure raw tagnames are safe exiting internalEntityParser
|
||||||
|
|
||||||
|
It is possible to concoct a situation in which parsing is
|
||||||
|
suspended while substituting in an internal entity, so that
|
||||||
|
XML_ResumeParser directly uses internalEntityProcessor as
|
||||||
|
its processor. If the subsequent parse includes some unclosed
|
||||||
|
tags, this will return without calling storeRawNames to ensure
|
||||||
|
that the raw versions of the tag names are stored in memory other
|
||||||
|
than the parse buffer itself. If the parse buffer is then changed
|
||||||
|
or reallocated (for example if processing a file line by line),
|
||||||
|
badness will ensue.
|
||||||
|
|
||||||
|
This patch ensures storeRawNames is always called when needed
|
||||||
|
after calling doContent. The earlier call do doContent does
|
||||||
|
not need the same protection; it only deals with entity
|
||||||
|
substitution, which cannot leave unbalanced tags, and in any
|
||||||
|
case the raw names will be pointing into the stored entity
|
||||||
|
value not the parse buffer.
|
||||||
|
---
|
||||||
|
lib/xmlparse.c | 13 +++++++++----
|
||||||
|
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
|
||||||
|
index 7bcabf7f..d73f419c 100644
|
||||||
|
--- a/lib/xmlparse.c
|
||||||
|
+++ b/lib/xmlparse.c
|
||||||
|
@@ -5826,10 +5826,15 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
|
||||||
|
{
|
||||||
|
parser->m_processor = contentProcessor;
|
||||||
|
/* see externalEntityContentProcessor vs contentProcessor */
|
||||||
|
- return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
|
||||||
|
- s, end, nextPtr,
|
||||||
|
- (XML_Bool)! parser->m_parsingStatus.finalBuffer,
|
||||||
|
- XML_ACCOUNT_DIRECT);
|
||||||
|
+ result = doContent(parser, parser->m_parentParser ? 1 : 0,
|
||||||
|
+ parser->m_encoding, s, end, nextPtr,
|
||||||
|
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer,
|
||||||
|
+ XML_ACCOUNT_DIRECT);
|
||||||
|
+ if (result == XML_ERROR_NONE) {
|
||||||
|
+ if (! storeRawNames(parser))
|
||||||
|
+ return XML_ERROR_NO_MEMORY;
|
||||||
|
+ }
|
||||||
|
+ return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
104
backport-0002-CVE-2022-40674.patch
Normal file
104
backport-0002-CVE-2022-40674.patch
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
From a7ce80a013f2a08cb1ac4aac368f2250eea03ebf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sebastian Pipping <sebastian@pipping.org>
|
||||||
|
Date: Sun, 11 Sep 2022 19:34:33 +0200
|
||||||
|
Subject: [PATCH] tests: Cover heap use-after-free issue in doContent
|
||||||
|
|
||||||
|
---
|
||||||
|
tests/runtests.c | 74 ++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 74 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/tests/runtests.c b/tests/runtests.c
|
||||||
|
index ea371b42..ab3aff65 100644
|
||||||
|
--- a/tests/runtests.c
|
||||||
|
+++ b/tests/runtests.c
|
||||||
|
@@ -4990,6 +4990,78 @@ START_TEST(test_suspend_resume_internal_entity) {
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
+void
|
||||||
|
+suspending_comment_handler(void *userData, const XML_Char *data) {
|
||||||
|
+ UNUSED_P(data);
|
||||||
|
+ XML_Parser parser = (XML_Parser)userData;
|
||||||
|
+ XML_StopParser(parser, XML_TRUE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+START_TEST(test_suspend_resume_internal_entity_issue_629) {
|
||||||
|
+ const char *const text
|
||||||
|
+ = "<!DOCTYPE a [<!ENTITY e '<!--COMMENT-->a'>]><a>&e;<b>\n"
|
||||||
|
+ "<"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
+ "/>"
|
||||||
|
+ "</b></a>";
|
||||||
|
+ const size_t firstChunkSizeBytes = 54;
|
||||||
|
+
|
||||||
|
+ XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
+ XML_SetUserData(parser, parser);
|
||||||
|
+ XML_SetCommentHandler(parser, suspending_comment_handler);
|
||||||
|
+
|
||||||
|
+ if (XML_Parse(parser, text, (int)firstChunkSizeBytes, XML_FALSE)
|
||||||
|
+ != XML_STATUS_SUSPENDED)
|
||||||
|
+ xml_failure(parser);
|
||||||
|
+ if (XML_ResumeParser(parser) != XML_STATUS_OK)
|
||||||
|
+ xml_failure(parser);
|
||||||
|
+ if (XML_Parse(parser, text + firstChunkSizeBytes,
|
||||||
|
+ (int)(strlen(text) - firstChunkSizeBytes), XML_TRUE)
|
||||||
|
+ != XML_STATUS_OK)
|
||||||
|
+ xml_failure(parser);
|
||||||
|
+ XML_ParserFree(parser);
|
||||||
|
+}
|
||||||
|
+END_TEST
|
||||||
|
+
|
||||||
|
/* Test syntax error is caught at parse resumption */
|
||||||
|
START_TEST(test_resume_entity_with_syntax_error) {
|
||||||
|
const char *text = "<!DOCTYPE doc [\n"
|
||||||
|
@@ -12016,6 +12088,8 @@ make_suite(void) {
|
||||||
|
tcase_add_test(tc_basic, test_partial_char_in_epilog);
|
||||||
|
tcase_add_test(tc_basic, test_hash_collision);
|
||||||
|
tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_internal_entity);
|
||||||
|
+ tcase_add_test__ifdef_xml_dtd(tc_basic,
|
||||||
|
+ test_suspend_resume_internal_entity_issue_629);
|
||||||
|
tcase_add_test__ifdef_xml_dtd(tc_basic, test_resume_entity_with_syntax_error);
|
||||||
|
tcase_add_test__ifdef_xml_dtd(tc_basic, test_suspend_resume_parameter_entity);
|
||||||
|
tcase_add_test(tc_basic, test_restart_on_error);
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
@ -1,12 +1,14 @@
|
|||||||
%define Rversion %(echo %{version} | sed -e 's/\\./_/g' -e 's/^/R_/')
|
%define Rversion %(echo %{version} | sed -e 's/\\./_/g' -e 's/^/R_/')
|
||||||
Name: expat
|
Name: expat
|
||||||
Version: 2.4.8
|
Version: 2.4.8
|
||||||
Release: 2
|
Release: 3
|
||||||
Summary: An XML parser library
|
Summary: An XML parser library
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: https://libexpat.github.io/
|
URL: https://libexpat.github.io/
|
||||||
Source0: https://github.com/libexpat/libexpat/releases/download/%{Rversion}/expat-%{version}.tar.gz
|
Source0: https://github.com/libexpat/libexpat/releases/download/%{Rversion}/expat-%{version}.tar.gz
|
||||||
Patch1: xmlparse.CVE-2022-40674.patch
|
|
||||||
|
Patch0: backport-0001-CVE-2022-40674.patch
|
||||||
|
Patch1: backport-0002-CVE-2022-40674.patch
|
||||||
|
|
||||||
BuildRequires: sed,autoconf,automake,gcc-c++,libtool,xmlto
|
BuildRequires: sed,autoconf,automake,gcc-c++,libtool,xmlto
|
||||||
|
|
||||||
@ -60,6 +62,9 @@ make check
|
|||||||
%{_mandir}/man1/*
|
%{_mandir}/man1/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Sep 15 2022 panxiaohe <panxh.life@foxmail.com> - 2.4.8-3
|
||||||
|
- add test for CVE-2022-40674
|
||||||
|
|
||||||
* Thu Sep 15 2022 dillon chen<dillon.chen@gmail.com> -2.4.8-2
|
* Thu Sep 15 2022 dillon chen<dillon.chen@gmail.com> -2.4.8-2
|
||||||
- fix CVE-2022-40674
|
- fix CVE-2022-40674
|
||||||
|
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
--- expat-2.4.8/lib/xmlparse.c 2022-03-29 05:11:43.000000000 +0800
|
|
||||||
+++ xmlparse.c 2022-09-15 10:56:50.317146415 +0800
|
|
||||||
@@ -4271,7 +4271,7 @@
|
|
||||||
const XML_Char *storedEncName = NULL;
|
|
||||||
const ENCODING *newEncoding = NULL;
|
|
||||||
const char *version = NULL;
|
|
||||||
- const char *versionend;
|
|
||||||
+ const char *versionend = NULL;
|
|
||||||
const XML_Char *storedversion = NULL;
|
|
||||||
int standalone = -1;
|
|
||||||
|
|
||||||
@@ -5826,10 +5826,15 @@
|
|
||||||
{
|
|
||||||
parser->m_processor = contentProcessor;
|
|
||||||
/* see externalEntityContentProcessor vs contentProcessor */
|
|
||||||
- return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
|
|
||||||
- s, end, nextPtr,
|
|
||||||
- (XML_Bool)! parser->m_parsingStatus.finalBuffer,
|
|
||||||
- XML_ACCOUNT_DIRECT);
|
|
||||||
+ result = doContent(parser, parser->m_parentParser ? 1 : 0,
|
|
||||||
+ parser->m_encoding, s, end, nextPtr,
|
|
||||||
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer,
|
|
||||||
+ XML_ACCOUNT_DIRECT);
|
|
||||||
+ if (result == XML_ERROR_NONE) {
|
|
||||||
+ if (! storeRawNames(parser))
|
|
||||||
+ return XML_ERROR_NO_MEMORY;
|
|
||||||
+ }
|
|
||||||
+ return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user