!45 merge master_1 into master

delete old expact

Created-by: gcw_TjfIWYag
Commit-by: Amber
Merged-by: openharmony_ci
Description: ### 一、内容说明(相关的Issue)



### 二、建议测试周期和提测地址  
  建议测试完成时间:xxxx.xx.xx  
  投产上线时间:xxxx.xx.xx  
  提测地址:CI环境/压测环境  
  测试账号:  

### 三、变更内容
  * 3.1 关联PR列表

  * 3.2 数据库和部署说明  
    1. 常规更新 
    2. 重启unicorn
    3. 重启sidekiq
    4. 迁移任务:是否有迁移任务,没有写 "无"
    5. rake脚本:`bundle exec xxx RAILS_ENV = production`;没有写 "无"

  * 3.4 其他技术优化内容(做了什么,变更了什么)
    - 重构了 xxxx 代码
    - xxxx 算法优化


  * 3.5 废弃通知(什么字段、方法弃用?)



  * 3.6  后向不兼容变更(是否有无法向后兼容的变更?)


  
### 四、研发自测点(自测哪些?冒烟用例全部自测?)
  自测测试结论:


### 五、测试关注点(需要提醒QA重点关注的、可能会忽略的地方)
  检查点:

| 需求名称 | 是否影响xx公共模块 | 是否需要xx功能 | 需求升级是否依赖其他子产品 |
|------|------------|----------|---------------|
| xxx  | 否          | 需要       | 不需要           |
|      |            |          |               |

  接口测试:

  性能测试:

  并发测试:

  其他:



See merge request: openharmony/third_party_expat!45
This commit is contained in:
openharmony_ci
2026-04-08 14:39:25 +08:00
34 changed files with 0 additions and 2423 deletions
View File
-62
View File
@@ -1,62 +0,0 @@
From 0adcb34c49bee5b19bd29b16a578c510c23597ea Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Mon, 27 Dec 2021 20:15:02 +0100
Subject: [PATCH] lib: Detect and prevent troublesome left shifts in function
storeAtts (CVE-2021-45960)
---
lib/xmlparse.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index d730f41..b47c31b 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -3414,7 +3414,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
if (nPrefixes) {
int j; /* hash table index */
unsigned long version = parser->m_nsAttsVersion;
- int nsAttsSize = (int)1 << parser->m_nsAttsPower;
+
+ /* Detect and prevent invalid shift */
+ if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ unsigned int nsAttsSize = 1u << parser->m_nsAttsPower;
unsigned char oldNsAttsPower = parser->m_nsAttsPower;
/* size of hash table must be at least 2 * (# of prefixed attributes) */
if ((nPrefixes << 1)
@@ -3425,7 +3431,28 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
;
if (parser->m_nsAttsPower < 3)
parser->m_nsAttsPower = 3;
- nsAttsSize = (int)1 << parser->m_nsAttsPower;
+
+ /* Detect and prevent invalid shift */
+ if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) {
+ /* Restore actual size of memory in m_nsAtts */
+ parser->m_nsAttsPower = oldNsAttsPower;
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ nsAttsSize = 1u << parser->m_nsAttsPower;
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) {
+ /* Restore actual size of memory in m_nsAtts */
+ parser->m_nsAttsPower = oldNsAttsPower;
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
nsAttsSize * sizeof(NS_ATT));
if (! temp) {
--
1.8.3.1
-46
View File
@@ -1,46 +0,0 @@
From 85ae9a2d7d0e9358f356b33977b842df8ebaec2b Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sat, 25 Dec 2021 20:52:08 +0100
Subject: [PATCH] lib: Prevent integer overflow on m_groupSize in function
doProlog (CVE-2021-46143)
---
lib/xmlparse.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index b47c31b..8f24312 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -5046,6 +5046,11 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
if (parser->m_prologState.level >= parser->m_groupSize) {
if (parser->m_groupSize) {
{
+ /* Detect and prevent integer overflow */
+ if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
char *const new_connector = (char *)REALLOC(
parser, parser->m_groupConnector, parser->m_groupSize *= 2);
if (new_connector == NULL) {
@@ -5056,6 +5061,16 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
}
if (dtd->scaffIndex) {
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
int *const new_scaff_index = (int *)REALLOC(
parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
if (new_scaff_index == NULL)
--
1.8.3.1
@@ -1,253 +0,0 @@
From 9f93e8036e842329863bf20395b8fb8f73834d9e Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Thu, 30 Dec 2021 22:46:03 +0100
Subject: [PATCH] lib: Prevent integer overflow at multiple places
(CVE-2022-22822 to CVE-2022-22827)
The involved functions are:
- addBinding (CVE-2022-22822)
- build_model (CVE-2022-22823)
- defineAttribute (CVE-2022-22824)
- lookup (CVE-2022-22825)
- nextScaffoldPart (CVE-2022-22826)
- storeAtts (CVE-2022-22827)
---
lib/xmlparse.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 151 insertions(+), 2 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 8f24312..575e73e 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -3261,13 +3261,38 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
/* get the attributes from the tokenizer */
n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
+
+ /* Detect and prevent integer overflow */
+ if (n > INT_MAX - nDefaultAtts) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
if (n + nDefaultAtts > parser->m_attsSize) {
int oldAttsSize = parser->m_attsSize;
ATTRIBUTE *temp;
#ifdef XML_ATTR_INFO
XML_AttrInfo *temp2;
#endif
+
+ /* Detect and prevent integer overflow */
+ if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE)
+ || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) {
+ parser->m_attsSize = oldAttsSize;
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
parser->m_attsSize * sizeof(ATTRIBUTE));
if (temp == NULL) {
@@ -3276,6 +3301,17 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
}
parser->m_atts = temp;
#ifdef XML_ATTR_INFO
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+# if UINT_MAX >= SIZE_MAX
+ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) {
+ parser->m_attsSize = oldAttsSize;
+ return XML_ERROR_NO_MEMORY;
+ }
+# endif
+
temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
parser->m_attsSize * sizeof(XML_AttrInfo));
if (temp2 == NULL) {
@@ -3610,9 +3646,31 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
tagNamePtr->prefixLen = prefixLen;
for (i = 0; localPart[i++];)
; /* i includes null terminator */
+
+ /* Detect and prevent integer overflow */
+ if (binding->uriLen > INT_MAX - prefixLen
+ || i > INT_MAX - (binding->uriLen + prefixLen)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
n = i + binding->uriLen + prefixLen;
if (n > binding->uriAlloc) {
TAG *p;
+
+ /* Detect and prevent integer overflow */
+ if (n > INT_MAX - EXPAND_SPARE) {
+ return XML_ERROR_NO_MEMORY;
+ }
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
if (! uri)
return XML_ERROR_NO_MEMORY;
@@ -3708,6 +3766,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
if (parser->m_freeBindingList) {
b = parser->m_freeBindingList;
if (len > b->uriAlloc) {
+ /* Detect and prevent integer overflow */
+ if (len > INT_MAX - EXPAND_SPARE) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
XML_Char *temp = (XML_Char *)REALLOC(
parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
if (temp == NULL)
@@ -3720,6 +3793,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
b = (BINDING *)MALLOC(parser, sizeof(BINDING));
if (! b)
return XML_ERROR_NO_MEMORY;
+
+ /* Detect and prevent integer overflow */
+ if (len > INT_MAX - EXPAND_SPARE) {
+ return XML_ERROR_NO_MEMORY;
+ }
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
b->uri
= (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
if (! b->uri) {
@@ -6141,7 +6229,24 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
}
} else {
DEFAULT_ATTRIBUTE *temp;
+
+ /* Detect and prevent integer overflow */
+ if (type->allocDefaultAtts > INT_MAX / 2) {
+ return 0;
+ }
+
int count = type->allocDefaultAtts * 2;
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) {
+ return 0;
+ }
+#endif
+
temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
(count * sizeof(DEFAULT_ATTRIBUTE)));
if (temp == NULL)
@@ -6792,8 +6897,20 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
/* check for overflow (table is half full) */
if (table->used >> (table->power - 1)) {
unsigned char newPower = table->power + 1;
+
+ /* Detect and prevent invalid shift */
+ if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
+ return NULL;
+ }
+
size_t newSize = (size_t)1 << newPower;
unsigned long newMask = (unsigned long)newSize - 1;
+
+ /* Detect and prevent integer overflow */
+ if (newSize > (size_t)(-1) / sizeof(NAMED *)) {
+ return NULL;
+ }
+
size_t tsize = newSize * sizeof(NAMED *);
NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
if (! newV)
@@ -7143,6 +7260,20 @@ nextScaffoldPart(XML_Parser parser) {
if (dtd->scaffCount >= dtd->scaffSize) {
CONTENT_SCAFFOLD *temp;
if (dtd->scaffold) {
+ /* Detect and prevent integer overflow */
+ if (dtd->scaffSize > UINT_MAX / 2u) {
+ return -1;
+ }
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) {
+ return -1;
+ }
+#endif
+
temp = (CONTENT_SCAFFOLD *)REALLOC(
parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
if (temp == NULL)
@@ -7212,8 +7343,26 @@ build_model(XML_Parser parser) {
XML_Content *ret;
XML_Content *cpos;
XML_Char *str;
- int allocsize = (dtd->scaffCount * sizeof(XML_Content)
- + (dtd->contentStringLen * sizeof(XML_Char)));
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) {
+ return NULL;
+ }
+ if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) {
+ return NULL;
+ }
+#endif
+ if (dtd->scaffCount * sizeof(XML_Content)
+ > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) {
+ return NULL;
+ }
+
+ const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
+ + (dtd->contentStringLen * sizeof(XML_Char)));
ret = (XML_Content *)MALLOC(parser, allocsize);
if (! ret)
--
1.8.3.1
@@ -1,29 +0,0 @@
From 847a645152f5ebc10ac63b74b604d0c1a79fae40 Mon Sep 17 00:00:00 2001
From: Samanta Navarro <ferivoz@riseup.net>
Date: Sat, 22 Jan 2022 17:48:00 +0100
Subject: [PATCH] lib: Detect and prevent integer overflow in
XML_GetBuffer (CVE-2022-23852)
---
lib/xmlparse.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index d54af68..5ce3140 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -2067,6 +2067,11 @@ XML_GetBuffer(XML_Parser parser, int len) {
keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
if (keep > XML_CONTEXT_BYTES)
keep = XML_CONTEXT_BYTES;
+ /* Detect and prevent integer overflow */
+ if (keep > INT_MAX - neededSize) {
+ parser->m_errorCode = XML_ERROR_NO_MEMORY;
+ return NULL;
+ }
neededSize += keep;
#endif /* defined XML_CONTEXT_BYTES */
if (neededSize
--
1.8.3.1
@@ -1,58 +0,0 @@
From acf956f14bf79a5e6383a969aaffec98bfbc2e44 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sun, 23 Jan 2022 18:17:04 +0100
Subject: [PATCH] tests: Cover integer overflow in XML_GetBuffer
(CVE-2022-23852)
---
tests/runtests.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/tests/runtests.c b/tests/runtests.c
index e89e822..579dad1 100644
--- a/tests/runtests.c
+++ b/tests/runtests.c
@@ -3847,6 +3847,30 @@ START_TEST(test_get_buffer_2) {
}
END_TEST
+/* Test for signed integer overflow CVE-2022-23852 */
+#if defined(XML_CONTEXT_BYTES)
+START_TEST(test_get_buffer_3_overflow) {
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert(parser != NULL);
+
+ const char *const text = "\n";
+ const int expectedKeepValue = (int)strlen(text);
+
+ // After this call, variable "keep" in XML_GetBuffer will
+ // have value expectedKeepValue
+ if (XML_Parse(parser, text, (int)strlen(text), XML_FALSE /* isFinal */)
+ == XML_STATUS_ERROR)
+ xml_failure(parser);
+
+ assert(expectedKeepValue > 0);
+ if (XML_GetBuffer(parser, INT_MAX - expectedKeepValue + 1) != NULL)
+ fail("enlarging buffer not failed");
+
+ XML_ParserFree(parser);
+}
+END_TEST
+#endif // defined(XML_CONTEXT_BYTES)
+
/* Test position information macros */
START_TEST(test_byte_info_at_end) {
const char *text = "<doc></doc>";
@@ -11731,6 +11755,9 @@ make_suite(void) {
tcase_add_test(tc_basic, test_empty_parse);
tcase_add_test(tc_basic, test_get_buffer_1);
tcase_add_test(tc_basic, test_get_buffer_2);
+#if defined(XML_CONTEXT_BYTES)
+ tcase_add_test(tc_basic, test_get_buffer_3_overflow);
+#endif
tcase_add_test(tc_basic, test_byte_info_at_end);
tcase_add_test(tc_basic, test_byte_info_at_error);
tcase_add_test(tc_basic, test_byte_info_at_cdata);
--
1.8.3.1
@@ -1,45 +0,0 @@
From ede41d1e186ed2aba88a06e84cac839b770af3a1 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Wed, 26 Jan 2022 02:36:43 +0100
Subject: [PATCH] lib: Prevent integer overflow in doProlog
(CVE-2022-23990)
The change from "int nameLen" to "size_t nameLen"
addresses the overflow on "nameLen++" in code
"for (; name[nameLen++];)" right above the second
change in the patch.
---
lib/xmlparse.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 5ce3140..d1d1700 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -5372,7 +5372,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
if (dtd->in_eldecl) {
ELEMENT_TYPE *el;
const XML_Char *name;
- int nameLen;
+ size_t nameLen;
const char *nxt
= (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
int myindex = nextScaffoldPart(parser);
@@ -5388,7 +5388,13 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
nameLen = 0;
for (; name[nameLen++];)
;
- dtd->contentStringLen += nameLen;
+
+ /* Detect and prevent integer overflow */
+ if (nameLen > UINT_MAX - dtd->contentStringLen) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ dtd->contentStringLen += (unsigned)nameLen;
if (parser->m_elementDeclHandler)
handleDefault = XML_FALSE;
}
--
1.8.3.1
@@ -1,42 +0,0 @@
From 3f0a0cb644438d4d8e3294cd0b1245d0edb0c6c6 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Tue, 8 Feb 2022 04:32:20 +0100
Subject: [PATCH] lib: Add missing validation of encoding (CVE-2022-25235)
---
lib/xmltok_impl.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c
index 0430591b4..64a3b2c15 100644
--- a/lib/xmltok_impl.c
+++ b/lib/xmltok_impl.c
@@ -69,7 +69,7 @@
case BT_LEAD##n: \
if (end - ptr < n) \
return XML_TOK_PARTIAL_CHAR; \
- if (! IS_NAME_CHAR(enc, ptr, n)) { \
+ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NAME_CHAR(enc, ptr, n)) { \
*nextTokPtr = ptr; \
return XML_TOK_INVALID; \
} \
@@ -98,7 +98,7 @@
case BT_LEAD##n: \
if (end - ptr < n) \
return XML_TOK_PARTIAL_CHAR; \
- if (! IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \
*nextTokPtr = ptr; \
return XML_TOK_INVALID; \
} \
@@ -1142,6 +1142,10 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
case BT_LEAD##n: \
if (end - ptr < n) \
return XML_TOK_PARTIAL_CHAR; \
+ if (IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
ptr += n; \
tok = XML_TOK_NAME; \
@@ -1,32 +0,0 @@
From a2fe525e660badd64b6c557c2b1ec26ddc07f6e4 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sat, 12 Feb 2022 01:09:29 +0100
Subject: [PATCH] lib: Protect against malicious namespace declarations
(CVE-2022-25236)
---
lib/xmlparse.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index c768f856..a3aef88c 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -3754,6 +3754,17 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
if (! mustBeXML && isXMLNS
&& (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
isXMLNS = XML_FALSE;
+
+ // NOTE: While Expat does not validate namespace URIs against RFC 3986,
+ // we have to at least make sure that the XML processor on top of
+ // Expat (that is splitting tag names by namespace separator into
+ // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused
+ // by an attacker putting additional namespace separator characters
+ // into namespace declarations. That would be ambiguous and not to
+ // be expected.
+ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) {
+ return XML_ERROR_SYNTAX;
+ }
}
isXML = isXML && len == xmlLen;
isXMLNS = isXMLNS && len == xmlnsLen;
@@ -1,222 +0,0 @@
From 9b4ce651b26557f16103c3a366c91934ecd439ab Mon Sep 17 00:00:00 2001
From: Samanta Navarro <ferivoz@riseup.net>
Date: Tue, 15 Feb 2022 11:54:29 +0000
Subject: [PATCH] Prevent stack exhaustion in build_model
It is possible to trigger stack exhaustion in build_model function if
depth of nested children in DTD element is large enough. This happens
because build_node is a recursively called function within build_model.
The code has been adjusted to run iteratively. It uses the already
allocated heap space as temporary stack (growing from top to bottom).
Output is identical to recursive version. No new fields in data
structures were added, i.e. it keeps full API and ABI compatibility.
Instead the numchildren variable is used to temporarily keep the
index of items (uint vs int).
Documentation and readability improvements kindly added by Sebastian.
Proof of Concept:
1. Compile poc binary which parses XML file line by line
```
cat > poc.c << EOF
#include <err.h>
#include <expat.h>
#include <stdio.h>
XML_Parser parser;
static void XMLCALL
dummy_element_decl_handler(void *userData, const XML_Char *name,
XML_Content *model) {
XML_FreeContentModel(parser, model);
}
int main(int argc, char *argv[]) {
FILE *fp;
char *p = NULL;
size_t s = 0;
ssize_t l;
if (argc != 2)
errx(1, "usage: poc poc.xml");
if ((parser = XML_ParserCreate(NULL)) == NULL)
errx(1, "XML_ParserCreate");
XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
if ((fp = fopen(argv[1], "r")) == NULL)
err(1, "fopen");
while ((l = getline(&p, &s, fp)) > 0)
if (XML_Parse(parser, p, (int)l, XML_FALSE) != XML_STATUS_OK)
errx(1, "XML_Parse");
XML_ParserFree(parser);
free(p);
fclose(fp);
return 0;
}
EOF
cc -std=c11 -D_POSIX_C_SOURCE=200809L -lexpat -o poc poc.c
```
2. Create XML file with a lot of nested groups in DTD element
```
cat > poc.xml.zst.b64 << EOF
KLUv/aQkACAAPAEA+DwhRE9DVFlQRSB1d3UgWwo8IUVMRU1FTlQgdXd1CigBAHv/58AJAgAQKAIA
ECgCABAoAgAQKAIAECgCABAoAgAQKHwAAChvd28KKQIA2/8gV24XBAIAECkCABApAgAQKQIAECkC
ABApAgAQKQIAEClVAAAgPl0+CgEA4A4I2VwwnQ==
EOF
base64 -d poc.xml.zst.b64 | zstd -d > poc.xml
```
3. Run Proof of Concept
```
./poc poc.xml
```
Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
---
lib/xmlparse.c | 116 +++++++++++++++++++++++++++++--------------
1 file changed, 79 insertions(+), 37 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 4b43e613..594cf12c 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -7317,44 +7317,15 @@ nextScaffoldPart(XML_Parser parser) {
return next;
}
-static void
-build_node(XML_Parser parser, int src_node, XML_Content *dest,
- XML_Content **contpos, XML_Char **strpos) {
- DTD *const dtd = parser->m_dtd; /* save one level of indirection */
- dest->type = dtd->scaffold[src_node].type;
- dest->quant = dtd->scaffold[src_node].quant;
- if (dest->type == XML_CTYPE_NAME) {
- const XML_Char *src;
- dest->name = *strpos;
- src = dtd->scaffold[src_node].name;
- for (;;) {
- *(*strpos)++ = *src;
- if (! *src)
- break;
- src++;
- }
- dest->numchildren = 0;
- dest->children = NULL;
- } else {
- unsigned int i;
- int cn;
- dest->numchildren = dtd->scaffold[src_node].childcnt;
- dest->children = *contpos;
- *contpos += dest->numchildren;
- for (i = 0, cn = dtd->scaffold[src_node].firstchild; i < dest->numchildren;
- i++, cn = dtd->scaffold[cn].nextsib) {
- build_node(parser, cn, &(dest->children[i]), contpos, strpos);
- }
- dest->name = NULL;
- }
-}
-
static XML_Content *
build_model(XML_Parser parser) {
+ /* Function build_model transforms the existing parser->m_dtd->scaffold
+ * array of CONTENT_SCAFFOLD tree nodes into a new array of
+ * XML_Content tree nodes followed by a gapless list of zero-terminated
+ * strings. */
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
XML_Content *ret;
- XML_Content *cpos;
- XML_Char *str;
+ XML_Char *str; /* the current string writing location */
/* Detect and prevent integer overflow.
* The preprocessor guard addresses the "always false" warning
@@ -7380,10 +7351,81 @@ build_model(XML_Parser parser) {
if (! ret)
return NULL;
- str = (XML_Char *)(&ret[dtd->scaffCount]);
- cpos = &ret[1];
+ /* What follows is an iterative implementation (of what was previously done
+ * recursively in a dedicated function called "build_node". The old recursive
+ * build_node could be forced into stack exhaustion from input as small as a
+ * few megabyte, and so that was a security issue. Hence, a function call
+ * stack is avoided now by resolving recursion.)
+ *
+ * The iterative approach works as follows:
+ *
+ * - We use space in the target array for building a temporary stack structure
+ * while that space is still unused.
+ * The stack grows from the array's end downwards and the "actual data"
+ * grows from the start upwards, sequentially.
+ * (Because stack grows downwards, pushing onto the stack is a decrement
+ * while popping off the stack is an increment.)
+ *
+ * - A stack element appears as a regular XML_Content node on the outside,
+ * but only uses a single field -- numchildren -- to store the source
+ * tree node array index. These are the breadcrumbs leading the way back
+ * during pre-order (node first) depth-first traversal.
+ *
+ * - The reason we know the stack will never grow into (or overlap with)
+ * the area with data of value at the start of the array is because
+ * the overall number of elements to process matches the size of the array,
+ * and the sum of fully processed nodes and yet-to-be processed nodes
+ * on the stack, cannot be more than the total number of nodes.
+ * It is possible for the top of the stack and the about-to-write node
+ * to meet, but that is safe because we get the source index out
+ * before doing any writes on that node.
+ */
+ XML_Content *dest = ret; /* tree node writing location, moves upwards */
+ XML_Content *const destLimit = &ret[dtd->scaffCount];
+ XML_Content *const stackBottom = &ret[dtd->scaffCount];
+ XML_Content *stackTop = stackBottom; /* i.e. stack is initially empty */
+ str = (XML_Char *)&ret[dtd->scaffCount];
+
+ /* Push source tree root node index onto the stack */
+ (--stackTop)->numchildren = 0;
+
+ for (; dest < destLimit; dest++) {
+ /* Pop source tree node index off the stack */
+ const int src_node = (int)(stackTop++)->numchildren;
+
+ /* Convert item */
+ dest->type = dtd->scaffold[src_node].type;
+ dest->quant = dtd->scaffold[src_node].quant;
+ if (dest->type == XML_CTYPE_NAME) {
+ const XML_Char *src;
+ dest->name = str;
+ src = dtd->scaffold[src_node].name;
+ for (;;) {
+ *str++ = *src;
+ if (! *src)
+ break;
+ src++;
+ }
+ dest->numchildren = 0;
+ dest->children = NULL;
+ } else {
+ unsigned int i;
+ int cn;
+ dest->name = NULL;
+ dest->numchildren = dtd->scaffold[src_node].childcnt;
+ dest->children = &dest[1];
+
+ /* Push children to the stack
+ * in a way where the first child ends up at the top of the
+ * (downwards growing) stack, in order to be processed first. */
+ stackTop -= dest->numchildren;
+ for (i = 0, cn = dtd->scaffold[src_node].firstchild;
+ i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) {
+ (stackTop + i)->numchildren = (unsigned int)cn;
+ }
+ }
+ }
- build_node(parser, 0, ret, &cpos, &str);
return ret;
}
@@ -1,24 +0,0 @@
From efcb347440ade24b9f1054671e6bd05e60b4cafd Mon Sep 17 00:00:00 2001
From: Samanta Navarro <ferivoz@riseup.net>
Date: Tue, 15 Feb 2022 11:56:57 +0000
Subject: [PATCH] Prevent integer overflow in copyString
The copyString function is only used for encoding string supplied by
the library user.
---
lib/xmlparse.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 4b43e613..a39377c2 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -7412,7 +7412,7 @@ getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
static XML_Char *
copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
- int charsRequired = 0;
+ size_t charsRequired = 0;
XML_Char *result;
/* First determine how long the string is */
@@ -1,138 +0,0 @@
From eb0362808b4f9f1e2345a0cf203b8cc196d776d9 Mon Sep 17 00:00:00 2001
From: Samanta Navarro <ferivoz@riseup.net>
Date: Tue, 15 Feb 2022 11:55:46 +0000
Subject: [PATCH] Prevent integer overflow in storeRawNames
It is possible to use an integer overflow in storeRawNames for out of
boundary heap writes. Default configuration is affected. If compiled
with XML_UNICODE then the attack does not work. Compiling with
-fsanitize=address confirms the following proof of concept.
The problem can be exploited by abusing the m_buffer expansion logic.
Even though the initial size of m_buffer is a power of two, eventually
it can end up a little bit lower, thus allowing allocations very close
to INT_MAX (since INT_MAX/2 can be surpassed). This means that tag
names can be parsed which are almost INT_MAX in size.
Unfortunately (from an attacker point of view) INT_MAX/2 is also a
limitation in string pools. Having a tag name of INT_MAX/2 characters
or more is not possible.
Expat can convert between different encodings. UTF-16 documents which
contain only ASCII representable characters are twice as large as their
ASCII encoded counter-parts.
The proof of concept works by taking these three considerations into
account:
1. Move the m_buffer size slightly below a power of two by having a
short root node <a>. This allows the m_buffer to grow very close
to INT_MAX.
2. The string pooling forbids tag names longer than or equal to
INT_MAX/2, so keep the attack tag name smaller than that.
3. To be able to still overflow INT_MAX even though the name is
limited at INT_MAX/2-1 (nul byte) we use UTF-16 encoding and a tag
which only contains ASCII characters. UTF-16 always stores two
bytes per character while the tag name is converted to using only
one. Our attack node byte count must be a bit higher than
2/3 INT_MAX so the converted tag name is around INT_MAX/3 which
in sum can overflow INT_MAX.
Thanks to our small root node, m_buffer can handle 2/3 INT_MAX bytes
without running into INT_MAX boundary check. The string pooling is
able to store INT_MAX/3 as tag name because the amount is below
INT_MAX/2 limitation. And creating the sum of both eventually overflows
in storeRawNames.
Proof of Concept:
1. Compile expat with -fsanitize=address.
2. Create Proof of Concept binary which iterates through input
file 16 MB at once for better performance and easier integer
calculations:
```
cat > poc.c << EOF
#include <err.h>
#include <expat.h>
#include <stdlib.h>
#include <stdio.h>
#define CHUNK (16 * 1024 * 1024)
int main(int argc, char *argv[]) {
XML_Parser parser;
FILE *fp;
char *buf;
int i;
if (argc != 2)
errx(1, "usage: poc file.xml");
if ((parser = XML_ParserCreate(NULL)) == NULL)
errx(1, "failed to create expat parser");
if ((fp = fopen(argv[1], "r")) == NULL) {
XML_ParserFree(parser);
err(1, "failed to open file");
}
if ((buf = malloc(CHUNK)) == NULL) {
fclose(fp);
XML_ParserFree(parser);
err(1, "failed to allocate buffer");
}
i = 0;
while (fread(buf, CHUNK, 1, fp) == 1) {
printf("iteration %d: XML_Parse returns %d\n", ++i,
XML_Parse(parser, buf, CHUNK, XML_FALSE));
}
free(buf);
fclose(fp);
XML_ParserFree(parser);
return 0;
}
EOF
gcc -fsanitize=address -lexpat -o poc poc.c
```
3. Construct specially prepared UTF-16 XML file:
```
dd if=/dev/zero bs=1024 count=794624 | tr '\0' 'a' > poc-utf8.xml
echo -n '<a><' | dd conv=notrunc of=poc-utf8.xml
echo -n '><' | dd conv=notrunc of=poc-utf8.xml bs=1 seek=805306368
iconv -f UTF-8 -t UTF-16LE poc-utf8.xml > poc-utf16.xml
```
4. Run proof of concept:
```
./poc poc-utf16.xml
```
---
lib/xmlparse.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 4b43e613..f34d6ab5 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -2563,6 +2563,7 @@ storeRawNames(XML_Parser parser) {
while (tag) {
int bufSize;
int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
+ size_t rawNameLen;
char *rawNameBuf = tag->buf + nameLen;
/* Stop if already stored. Since m_tagStack is a stack, we can stop
at the first entry that has already been copied; everything
@@ -2574,7 +2575,11 @@ storeRawNames(XML_Parser parser) {
/* For re-use purposes we need to ensure that the
size of tag->buf is a multiple of sizeof(XML_Char).
*/
- bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
+ rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
+ /* Detect and prevent integer overflow. */
+ if (rawNameLen > (size_t)INT_MAX - nameLen)
+ return XML_FALSE;
+ bufSize = nameLen + (int)rawNameLen;
if (bufSize > tag->bufEnd - tag->buf) {
char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
if (temp == NULL)
-52
View File
@@ -1,52 +0,0 @@
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
View File
@@ -1,104 +0,0 @@
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
-29
View File
@@ -1,29 +0,0 @@
From 5290462a7ea1278a8d5c0d5b2860d4e244f997e4 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Tue, 20 Sep 2022 02:44:34 +0200
Subject: [PATCH] lib: Fix overeager DTD destruction in
XML_ExternalEntityParserCreate
---
lib/xmlparse.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index aacd6e7fc..57bf103cc 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -1068,6 +1068,14 @@ parserCreate(const XML_Char *encodingName,
parserInit(parser, encodingName);
if (encodingName && ! parser->m_protocolEncodingName) {
+ if (dtd) {
+ // We need to stop the upcoming call to XML_ParserFree from happily
+ // destroying parser->m_dtd because the DTD is shared with the parent
+ // parser and the only guard that keeps XML_ParserFree from destroying
+ // parser->m_dtd is parser->m_isParamEntity but it will be set to
+ // XML_TRUE only later in XML_ExternalEntityParserCreate (or not at all).
+ parser->m_dtd = NULL;
+ }
XML_ParserFree(parser);
return NULL;
}
@@ -1,134 +0,0 @@
From b12f34fe32821a69dc12ff9a021daca0856de238 Mon Sep 17 00:00:00 2001
From: Samanta Navarro <ferivoz@riseup.net>
Date: Sat, 19 Feb 2022 23:59:25 +0000
Subject: [PATCH] Fix build_model regression.
The iterative approach in build_model failed to fill children arrays
correctly. A preorder traversal is not required and turned out to be the
culprit. Use an easier algorithm:
Add nodes from scaffold tree starting at index 0 (root) to the target
array whenever children are encountered. This ensures that children
are adjacent to each other. This complies with the recursive version.
Store only the scaffold index in numchildren field to prevent a direct
processing of these children, which would require a recursive solution.
This allows the algorithm to iterate through the target array from start
to end without jumping back and forth, converting on the fly.
Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
---
lib/xmlparse.c | 79 +++++++++++++++++++++++++++++++---------------------
1 file changed, 47 insertions(+), 32 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index c479a25..84885b5 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -7373,39 +7373,58 @@ build_model(XML_Parser parser) {
*
* The iterative approach works as follows:
*
- * - We use space in the target array for building a temporary stack structure
- * while that space is still unused.
- * The stack grows from the array's end downwards and the "actual data"
- * grows from the start upwards, sequentially.
- * (Because stack grows downwards, pushing onto the stack is a decrement
- * while popping off the stack is an increment.)
+ * - We have two writing pointers, both walking up the result array; one does
+ * the work, the other creates "jobs" for its colleague to do, and leads
+ * the way:
*
- * - A stack element appears as a regular XML_Content node on the outside,
- * but only uses a single field -- numchildren -- to store the source
- * tree node array index. These are the breadcrumbs leading the way back
- * during pre-order (node first) depth-first traversal.
+ * - The faster one, pointer jobDest, always leads and writes "what job
+ * to do" by the other, once they reach that place in the
+ * array: leader "jobDest" stores the source node array index (relative
+ * to array dtd->scaffold) in field "numchildren".
*
- * - The reason we know the stack will never grow into (or overlap with)
- * the area with data of value at the start of the array is because
- * the overall number of elements to process matches the size of the array,
- * and the sum of fully processed nodes and yet-to-be processed nodes
- * on the stack, cannot be more than the total number of nodes.
- * It is possible for the top of the stack and the about-to-write node
- * to meet, but that is safe because we get the source index out
- * before doing any writes on that node.
+ * - The slower one, pointer dest, looks at the value stored in the
+ * "numchildren" field (which actually holds a source node array index
+ * at that time) and puts the real data from dtd->scaffold in.
+ *
+ * - Before the loop starts, jobDest writes source array index 0
+ * (where the root node is located) so that dest will have something to do
+ * when it starts operation.
+ *
+ * - Whenever nodes with children are encountered, jobDest appends
+ * them as new jobs, in order. As a result, tree node siblings are
+ * adjacent in the resulting array, for example:
+ *
+ * [0] root, has two children
+ * [1] first child of 0, has three children
+ * [3] first child of 1, does not have children
+ * [4] second child of 1, does not have children
+ * [5] third child of 1, does not have children
+ * [2] second child of 0, does not have children
+ *
+ * Or (the same data) presented in flat array view:
+ *
+ * [0] root, has two children
+ *
+ * [1] first child of 0, has three children
+ * [2] second child of 0, does not have children
+ *
+ * [3] first child of 1, does not have children
+ * [4] second child of 1, does not have children
+ * [5] third child of 1, does not have children
+ *
+ * - The algorithm repeats until all target array indices have been processed.
*/
XML_Content *dest = ret; /* tree node writing location, moves upwards */
XML_Content *const destLimit = &ret[dtd->scaffCount];
- XML_Content *const stackBottom = &ret[dtd->scaffCount];
- XML_Content *stackTop = stackBottom; /* i.e. stack is initially empty */
+ XML_Content *jobDest = ret; /* next free writing location in target array */
str = (XML_Char *)&ret[dtd->scaffCount];
- /* Push source tree root node index onto the stack */
- (--stackTop)->numchildren = 0;
+ /* Add the starting job, the root node (index 0) of the source tree */
+ (jobDest++)->numchildren = 0;
for (; dest < destLimit; dest++) {
- /* Pop source tree node index off the stack */
- const int src_node = (int)(stackTop++)->numchildren;
+ /* Retrieve source tree array index from job storage */
+ const int src_node = (int)dest->numchildren;
/* Convert item */
dest->type = dtd->scaffold[src_node].type;
@@ -7427,16 +7446,12 @@ build_model(XML_Parser parser) {
int cn;
dest->name = NULL;
dest->numchildren = dtd->scaffold[src_node].childcnt;
- dest->children = &dest[1];
+ dest->children = jobDest;
- /* Push children to the stack
- * in a way where the first child ends up at the top of the
- * (downwards growing) stack, in order to be processed first. */
- stackTop -= dest->numchildren;
+ /* Append scaffold indices of children to array */
for (i = 0, cn = dtd->scaffold[src_node].firstchild;
- i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) {
- (stackTop + i)->numchildren = (unsigned int)cn;
- }
+ i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib)
+ (jobDest++)->numchildren = (unsigned int)cn;
}
}
--
1.8.3.1
@@ -1,28 +0,0 @@
From ee2a5b50e7d1940ba8745715b62ceb9efd3a96da Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Tue, 8 Feb 2022 17:37:14 +0100
Subject: [PATCH] lib: Drop unused macro UTF8_GET_NAMING
---
lib/xmltok.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/lib/xmltok.c b/lib/xmltok.c
index a72200e..3bddf12 100644
--- a/lib/xmltok.c
+++ b/lib/xmltok.c
@@ -98,11 +98,6 @@
+ ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)] \
& (1u << (((byte)[2]) & 0x1F)))
-#define UTF8_GET_NAMING(pages, p, n) \
- ((n) == 2 \
- ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
- : ((n) == 3 ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) : 0))
-
/* Detection of invalid UTF-8 sequences is based on Table 3.1B
of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/
with the additional restriction of not allowing the Unicode
--
1.8.3.1
@@ -1,36 +0,0 @@
From 6881a4fc8596307ab9ff2e85e605afa2e413ab71 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sat, 12 Feb 2022 00:19:13 +0100
Subject: [PATCH] lib: Fix (harmless) use of uninitialized memory
---
lib/xmlparse.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 902895d..c768f85 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -718,8 +718,7 @@ XML_ParserCreate(const XML_Char *encodingName) {
XML_Parser XMLCALL
XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
- XML_Char tmp[2];
- *tmp = nsSep;
+ XML_Char tmp[2] = {nsSep, 0};
return XML_ParserCreate_MM(encodingName, NULL, tmp);
}
@@ -1344,8 +1343,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
would be otherwise.
*/
if (parser->m_ns) {
- XML_Char tmp[2];
- *tmp = parser->m_namespaceSeparator;
+ XML_Char tmp[2] = {parser->m_namespaceSeparator, 0};
parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
} else {
parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
--
1.8.3.1
@@ -1,170 +0,0 @@
From 2ba6c76fca21397959145e18c5ef376201209020 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sun, 27 Feb 2022 16:58:08 +0100
Subject: [PATCH] lib: Relax fix to CVE-2022-25236 with regard to RFC
3986 URI characters
---
lib/xmlparse.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 131 insertions(+), 8 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 59da19c..6fe2cf1 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -3705,6 +3705,117 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
return XML_ERROR_NONE;
}
+static XML_Bool
+is_rfc3986_uri_char(XML_Char candidate) {
+ // For the RFC 3986 ANBF grammar see
+ // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A
+
+ switch (candidate) {
+ // From rule "ALPHA" (uppercase half)
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+
+ // From rule "ALPHA" (lowercase half)
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+
+ // From rule "DIGIT"
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+
+ // From rule "pct-encoded"
+ case '%':
+
+ // From rule "unreserved"
+ case '-':
+ case '.':
+ case '_':
+ case '~':
+
+ // From rule "gen-delims"
+ case ':':
+ case '/':
+ case '?':
+ case '#':
+ case '[':
+ case ']':
+ case '@':
+
+ // From rule "sub-delims"
+ case '!':
+ case '$':
+ case '&':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case ';':
+ case '=':
+ return XML_TRUE;
+
+ default:
+ return XML_FALSE;
+ }
+}
+
/* addBinding() overwrites the value of prefix->binding without checking.
Therefore one must keep track of the old value outside of addBinding().
*/
@@ -3763,14 +3874,26 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
&& (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
isXMLNS = XML_FALSE;
- // NOTE: While Expat does not validate namespace URIs against RFC 3986,
- // we have to at least make sure that the XML processor on top of
- // Expat (that is splitting tag names by namespace separator into
- // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused
- // by an attacker putting additional namespace separator characters
- // into namespace declarations. That would be ambiguous and not to
- // be expected.
- if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) {
+ // NOTE: While Expat does not validate namespace URIs against RFC 3986
+ // today (and is not REQUIRED to do so with regard to the XML 1.0
+ // namespaces specification) we have to at least make sure, that
+ // the application on top of Expat (that is likely splitting expanded
+ // element names ("qualified names") of form
+ // "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces
+ // in its element handler code) cannot be confused by an attacker
+ // putting additional namespace separator characters into namespace
+ // declarations. That would be ambiguous and not to be expected.
+ //
+ // While the HTML API docs of function XML_ParserCreateNS have been
+ // advising against use of a namespace separator character that can
+ // appear in a URI for >20 years now, some widespread applications
+ // are using URI characters (':' (colon) in particular) for a
+ // namespace separator, in practice. To keep these applications
+ // functional, we only reject namespaces URIs containing the
+ // application-chosen namespace separator if the chosen separator
+ // is a non-URI character with regard to RFC 3986.
+ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)
+ && ! is_rfc3986_uri_char(uri[len])) {
return XML_ERROR_SYNTAX;
}
}
--
1.8.3.1
@@ -1,60 +0,0 @@
From 2de077423fb22750ebea599677d523b53cb93b1d Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sat, 12 Feb 2022 00:51:43 +0100
Subject: [PATCH] tests: Cover CVE-2022-25236
---
tests/runtests.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/tests/runtests.c b/tests/runtests.c
index d07203f..bc5344b 100644
--- a/tests/runtests.c
+++ b/tests/runtests.c
@@ -7220,6 +7220,35 @@ START_TEST(test_ns_double_colon_doctype) {
}
END_TEST
+START_TEST(test_ns_separator_in_uri) {
+ struct test_case {
+ enum XML_Status expectedStatus;
+ const char *doc;
+ };
+ struct test_case cases[] = {
+ {XML_STATUS_OK, "<doc xmlns='one_two' />"},
+ {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />"},
+ };
+
+ size_t i = 0;
+ size_t failCount = 0;
+ for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
+ XML_Parser parser = XML_ParserCreateNS(NULL, '\n');
+ XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
+ if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
+ /*isFinal*/ XML_TRUE)
+ != cases[i].expectedStatus) {
+ failCount++;
+ }
+ XML_ParserFree(parser);
+ }
+
+ if (failCount) {
+ fail("Namespace separator handling is broken");
+ }
+}
+END_TEST
+
/* Control variable; the number of times duff_allocator() will successfully
* allocate */
#define ALLOC_ALWAYS_SUCCEED (-1)
@@ -11905,6 +11934,7 @@ make_suite(void) {
tcase_add_test(tc_namespace, test_ns_utf16_doctype);
tcase_add_test(tc_namespace, test_ns_invalid_doctype);
tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
+ tcase_add_test(tc_namespace, test_ns_separator_in_uri);
suite_add_tcase(s, tc_misc);
tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
--
1.8.3.1
@@ -1,154 +0,0 @@
From 6a5510bc6b7efe743356296724e0b38300f05379 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Tue, 8 Feb 2022 04:06:21 +0100
Subject: [PATCH] tests: Cover missing validation of encoding
(CVE-2022-25235)
---
tests/runtests.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/tests/runtests.c b/tests/runtests.c
index bc5344b..9b155b8 100644
--- a/tests/runtests.c
+++ b/tests/runtests.c
@@ -5998,6 +5998,105 @@ START_TEST(test_utf8_in_cdata_section_2) {
}
END_TEST
+START_TEST(test_utf8_in_start_tags) {
+ struct test_case {
+ bool goodName;
+ bool goodNameStart;
+ const char *tagName;
+ };
+
+ // The idea with the tests below is this:
+ // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences
+ // go to isNever and are hence not a concern.
+ //
+ // We start with a character that is a valid name character
+ // (or even name-start character, see XML 1.0r4 spec) and then we flip
+ // single bits at places where (1) the result leaves the UTF-8 encoding space
+ // and (2) we stay in the same n-byte sequence family.
+ //
+ // The flipped bits are highlighted in angle brackets in comments,
+ // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped
+ // the most significant bit to 1 to leave UTF-8 encoding space.
+ struct test_case cases[] = {
+ // 1-byte UTF-8: [0xxx xxxx]
+ {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':'
+ {false, false, "\xBA"}, // [<1>011 1010]
+ {true, false, "\x39"}, // [0011 1001] = ASCII nine '9'
+ {false, false, "\xB9"}, // [<1>011 1001]
+
+ // 2-byte UTF-8: [110x xxxx] [10xx xxxx]
+ {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] =
+ // Arabic small waw U+06E5
+ {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101]
+ {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101]
+ {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101]
+ {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] =
+ // combining char U+0301
+ {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001]
+ {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001]
+ {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001]
+
+ // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx]
+ {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] =
+ // Devanagari Letter A U+0905
+ {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101]
+ {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101]
+ {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101]
+ {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101]
+ {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101]
+ {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] =
+ // combining char U+0901
+ {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001]
+ {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001]
+ {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001]
+ {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001]
+ {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001]
+ };
+ const bool atNameStart[] = {true, false};
+
+ size_t i = 0;
+ char doc[1024];
+ size_t failCount = 0;
+
+ for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
+ size_t j = 0;
+ for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) {
+ const bool expectedSuccess
+ = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName;
+ sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName);
+ XML_Parser parser = XML_ParserCreate(NULL);
+
+ const enum XML_Status status
+ = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE);
+
+ bool success = true;
+ if ((status == XML_STATUS_OK) != expectedSuccess) {
+ success = false;
+ }
+ if ((status == XML_STATUS_ERROR)
+ && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) {
+ success = false;
+ }
+
+ if (! success) {
+ fprintf(
+ stderr,
+ "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n",
+ (unsigned)i + 1u, atNameStart[j] ? " " : "not ",
+ (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser));
+ failCount++;
+ }
+
+ XML_ParserFree(parser);
+ }
+ }
+
+ if (failCount > 0) {
+ fail("UTF-8 regression detected");
+ }
+}
+END_TEST
+
/* Test trailing spaces in elements are accepted */
static void XMLCALL
record_element_end_handler(void *userData, const XML_Char *name) {
@@ -6175,6 +6274,14 @@ START_TEST(test_bad_doctype) {
}
END_TEST
+START_TEST(test_bad_doctype_utf8) {
+ const char *text = "<!DOCTYPE \xDB\x25"
+ "doc><doc/>"; // [1101 1011] [<0>010 0101]
+ expect_failure(text, XML_ERROR_INVALID_TOKEN,
+ "Invalid UTF-8 in DOCTYPE not faulted");
+}
+END_TEST
+
START_TEST(test_bad_doctype_utf16) {
const char text[] =
/* <!DOCTYPE doc [ \x06f2 ]><doc/>
@@ -11870,6 +11977,7 @@ make_suite(void) {
tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
tcase_add_test(tc_basic, test_utf8_in_cdata_section);
tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
+ tcase_add_test(tc_basic, test_utf8_in_start_tags);
tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
tcase_add_test(tc_basic, test_utf16_attribute);
tcase_add_test(tc_basic, test_utf16_second_attr);
@@ -11878,6 +11986,7 @@ make_suite(void) {
tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
tcase_add_test(tc_basic, test_bad_doctype);
+ tcase_add_test(tc_basic, test_bad_doctype_utf8);
tcase_add_test(tc_basic, test_bad_doctype_utf16);
tcase_add_test(tc_basic, test_bad_doctype_plus);
tcase_add_test(tc_basic, test_bad_doctype_star);
--
1.8.3.1
@@ -1,77 +0,0 @@
From 43992e4ae25fc3dc0eec0cd3a29313555d56aee2 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Mon, 19 Sep 2022 18:16:15 +0200
Subject: [PATCH] tests: Cover overeager DTD destruction in
XML_ExternalEntityParserCreate
---
tests/runtests.c | 49 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/tests/runtests.c b/tests/runtests.c
index 245fe9bda..acb744dd4 100644
--- a/tests/runtests.c
+++ b/tests/runtests.c
@@ -10208,6 +10208,53 @@ START_TEST(test_alloc_long_notation) {
}
END_TEST
+static int XMLCALL
+external_entity_parser_create_alloc_fail_handler(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId) {
+ UNUSED_P(base);
+ UNUSED_P(systemId);
+ UNUSED_P(publicId);
+
+ if (context != NULL)
+ fail("Unexpected non-NULL context");
+
+ // The following number intends to fail the upcoming allocation in line
+ // "parser->m_protocolEncodingName = copyString(encodingName,
+ // &(parser->m_mem));" in function parserInit.
+ allocation_count = 3;
+
+ const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL
+ const XML_Parser ext_parser
+ = XML_ExternalEntityParserCreate(parser, context, encodingName);
+ if (ext_parser != NULL)
+ fail(
+ "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory");
+
+ allocation_count = ALLOC_ALWAYS_SUCCEED;
+ return XML_STATUS_ERROR;
+}
+
+START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) {
+ const char *const text = "<!DOCTYPE doc SYSTEM 'foo'><doc/>";
+
+ XML_SetExternalEntityRefHandler(
+ g_parser, external_entity_parser_create_alloc_fail_handler);
+ XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
+
+ if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
+ != XML_STATUS_ERROR)
+ fail("Call to parse was expected to fail");
+
+ if (XML_GetErrorCode(g_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING)
+ fail("Call to parse was expected to fail from the external entity handler");
+
+ XML_ParserReset(g_parser, NULL);
+}
+END_TEST
+
static void
nsalloc_setup(void) {
XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free};
@@ -12401,6 +12448,8 @@ make_suite(void) {
tcase_add_test(tc_alloc, test_alloc_long_public_id);
tcase_add_test(tc_alloc, test_alloc_long_entity_value);
tcase_add_test(tc_alloc, test_alloc_long_notation);
+ tcase_add_test__ifdef_xml_dtd(
+ tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail);
suite_add_tcase(s, tc_nsalloc);
tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown);
@@ -1,38 +0,0 @@
From e0f852db1e3b1e6d34922c68a653c3cc4b85361c Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Thu, 3 Mar 2022 17:29:54 +0100
Subject: [PATCH] tests: Cover relaxed fix to CVE-2022-25236
---
tests/runtests.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/tests/runtests.c b/tests/runtests.c
index 60da868..712706c 100644
--- a/tests/runtests.c
+++ b/tests/runtests.c
@@ -7406,16 +7406,18 @@ START_TEST(test_ns_separator_in_uri) {
struct test_case {
enum XML_Status expectedStatus;
const char *doc;
+ XML_Char namesep;
};
struct test_case cases[] = {
- {XML_STATUS_OK, "<doc xmlns='one_two' />"},
- {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />"},
+ {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')},
+ {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />", XCS('\n')},
+ {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')},
};
size_t i = 0;
size_t failCount = 0;
for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
- XML_Parser parser = XML_ParserCreateNS(NULL, '\n');
+ XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep);
XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
/*isFinal*/ XML_TRUE)
--
1.8.3.1
@@ -1,108 +0,0 @@
From 154e565f6ef329c9ec97e6534c411ddde0b320c8 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sun, 20 Feb 2022 03:26:57 +0100
Subject: [PATCH] tests: Protect against nested element declaration
model regressions
---
tests/runtests.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/tests/runtests.c b/tests/runtests.c
index 2cd4acb..e28670d 100644
--- a/tests/runtests.c
+++ b/tests/runtests.c
@@ -2664,6 +2664,82 @@ START_TEST(test_dtd_elements) {
}
END_TEST
+static void XMLCALL
+element_decl_check_model(void *userData, const XML_Char *name,
+ XML_Content *model) {
+ UNUSED_P(userData);
+ uint32_t errorFlags = 0;
+
+ /* Expected model array structure is this:
+ * [0] (type 6, quant 0)
+ * [1] (type 5, quant 0)
+ * [3] (type 4, quant 0, name "bar")
+ * [4] (type 4, quant 0, name "foo")
+ * [5] (type 4, quant 3, name "xyz")
+ * [2] (type 4, quant 2, name "zebra")
+ */
+ errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0));
+ errorFlags |= ((model != NULL) ? 0 : (1u << 1));
+
+ errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2));
+ errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3));
+ errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4));
+ errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5));
+ errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6));
+
+ errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7));
+ errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8));
+ errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9));
+ errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10));
+ errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11));
+
+ errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12));
+ errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13));
+ errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14));
+ errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15));
+ errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16));
+
+ errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17));
+ errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18));
+ errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19));
+ errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20));
+ errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21));
+
+ errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22));
+ errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23));
+ errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24));
+ errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25));
+ errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26));
+
+ errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27));
+ errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28));
+ errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29));
+ errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30));
+ errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31));
+
+ XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags);
+ XML_FreeContentModel(g_parser, model);
+}
+
+START_TEST(test_dtd_elements_nesting) {
+ // Payload inspired by a test in Perl's XML::Parser
+ const char *text = "<!DOCTYPE foo [\n"
+ "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n"
+ "]>\n"
+ "<foo/>";
+
+ XML_SetUserData(g_parser, (void *)(uintptr_t)-1);
+
+ XML_SetElementDeclHandler(g_parser, element_decl_check_model);
+ if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
+ == XML_STATUS_ERROR)
+ xml_failure(g_parser);
+
+ if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0)
+ fail("Element declaration model regression detected");
+}
+END_TEST
+
/* Test foreign DTD handling */
START_TEST(test_set_foreign_dtd) {
const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
@@ -11863,6 +11939,7 @@ make_suite(void) {
tcase_add_test(tc_basic, test_memory_allocation);
tcase_add_test(tc_basic, test_default_current);
tcase_add_test(tc_basic, test_dtd_elements);
+ tcase_add_test(tc_basic, test_dtd_elements_nesting);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
--
1.8.3.1
-55
View File
@@ -1,55 +0,0 @@
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 8199488..8453289 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -88,9 +88,9 @@
#ifdef _WIN32
# include "winconfig.h"
-#endif
-
-#include <expat_config.h>
+#elif defined(HAVE_EXPAT_CONFIG_H)
+# include <expat_config.h>
+#endif /* ndef _WIN32 */
#include "ascii.h"
#include "expat.h"
diff --git a/lib/xmlrole.c b/lib/xmlrole.c
index 08173b0..ddb22ef 100644
--- a/lib/xmlrole.c
+++ b/lib/xmlrole.c
@@ -41,9 +41,11 @@
#ifdef _WIN32
# include "winconfig.h"
-#endif
-
-#include <expat_config.h>
+#else
+# ifdef HAVE_EXPAT_CONFIG_H
+# include <expat_config.h>
+# endif
+#endif /* ndef _WIN32 */
#include "expat_external.h"
#include "internal.h"
diff --git a/lib/xmltok.c b/lib/xmltok.c
index 8d77d60..53ec1d0 100644
--- a/lib/xmltok.c
+++ b/lib/xmltok.c
@@ -48,9 +48,11 @@
#ifdef _WIN32
# include "winconfig.h"
-#endif
-
-#include <expat_config.h>
+#else
+# ifdef HAVE_EXPAT_CONFIG_H
+# include <expat_config.h>
+# endif
+#endif /* ndef _WIN32 */
#include "expat_external.h"
#include "internal.h"
-58
View File
@@ -1,58 +0,0 @@
import("//build/ohos.gni")
expat_path = root_out_dir + "/third_party_expat"
src_path = "//third_party/expat"
action("deps_expat") {
script = "install.sh"
args = [
rebase_path(src_path, root_build_dir),
rebase_path(expat_path, root_build_dir),
]
inputs = [ src_path ]
outputs = [
"$expat_path/expat-2.4.1/lib/expat.h",
"$expat_path/expat-2.4.1/lib/xmlparse.c",
"$expat_path/expat-2.4.1/lib/xmlrole.c",
"$expat_path/expat-2.4.1/lib/xmltok.c",
]
}
## Build expat.a {{{
config("expat_config") {
visibility = [ ":*" ]
include_dirs = []
cflags = [
"-DXML_POOR_ENTROPY",
"-Wno-sign-compare",
]
}
config("expat_public_config") {
include_dirs = [
"$expat_path/expat-2.4.1",
"$expat_path/expat-2.4.1/lib",
]
defines = [ "XML_STATIC" ]
}
ohos_static_library("expat") {
part_name = "expat"
subsystem_name = "thirdparty"
deps = [ ":deps_expat" ]
sources = [
"$expat_path/expat-2.4.1/lib/expat.h",
"$expat_path/expat-2.4.1/lib/xmlparse.c",
"$expat_path/expat-2.4.1/lib/xmlrole.c",
"$expat_path/expat-2.4.1/lib/xmltok.c",
]
configs = [ ":expat_config" ]
public_configs = [ ":expat_public_config" ]
public_deps = []
}
## Build expat.a }}}
-21
View File
@@ -1,21 +0,0 @@
Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
Copyright (c) 2001-2019 Expat maintainers
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.
-46
View File
@@ -1,46 +0,0 @@
THIRD PARTY OPEN SOURCE SOFTWARE NOTICE
Please note we provide an open source software notice for the third party open source software along with this software and/or this software component contributed by Huawei (in the following just “this SOFTWARE”). The open source software licenses are granted by the respective right holders.
Warranty Disclaimer
THE OPEN SOURCE SOFTWARE IN THIS SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
Copyright Notice and License Texts
Software: Expat v2.2.9
Copyright notice:
Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
Copyright (c) 2000-2017 Expat development team
Copyright (c) 2017 Expat development team
(no indication of license or copyright there)
Copyright (C) 2016 The Android Open Source Project
Copyright (c) 2019 Expat development team
copyright 2010, Patrick Spendrin <psml@gmx.de>
Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
Copyright (c) 2001-2017 Expat maintainers
Copyright (C) Sebastian Pipping <sebastian@pipping.org>
Copyright (C) 2018 Sebastian Pipping <sebastian@pipping.org>
Copyright (C) 2016 Sebastian Pipping <sebastian@pipping.org>
License: MIT License
Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
Copyright (c) 2001-2017 Expat maintainers
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.
-75
View File
@@ -1,75 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2021 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Notes:
This is project config file for OpenHarmony OSS Audit Tool, if you have any questions or concerns, please email chenyaxun.
-->
<!-- OAT(OSS Audit Tool) configuration guide:
basedir: Root dir, the basedir + project path is the real source file location.
licensefile:
1.If the project don't have "LICENSE" in root dir, please define all the license files in this project in , OAT will check license files according to this rule.
tasklist(only for batch mode):
1. task: Define oat check thread, each task will start a new thread.
2. task name: Only an name, no practical effect.
3. task policy: Default policy for projects under this task, this field is required and the specified policy must defined in policylist.
4. task filter: Default filefilter for projects under this task, this field is required and the specified filefilter must defined in filefilterlist.
5. task project: Projects to be checked, the path field define the source root dir of the project.
policyList:
1. policy: All policyitems will be merged to default OAT.xml rules, the name of policy doesn't affect OAT check process.
2. policyitem: The fields type, name, path, desc is required, and the fields rule, group, filefilter is optional,the default value is:
<policyitem type="" name="" path="" desc="" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
3. policyitem type:
"compatibility" is used to check license compatibility in the specified path;
"license" is used to check source license header in the specified path;
"copyright" is used to check source copyright header in the specified path;
"import" is used to check source dependency in the specified path, such as import ... ,include ...
"filetype" is used to check file type in the specified path, supported file types: archive, binary
"filename" is used to check whether the specified file exists in the specified path(support projectroot in default OAT.xml), supported file names: LICENSE, README, README.OpenSource
4. policyitem name: This field is used for define the license, copyright, "*" means match all, the "!" prefix means could not match this value. For example, "!GPL" means can not use GPL license.
5. policyitem path: This field is used for define the source file scope to apply this policyitem, the "!" prefix means exclude the files. For example, "!.*/lib/.*" means files in lib dir will be exclude while process this policyitem.
6. policyitem rule and group: These two fields are used together to merge policy results. "may" policyitems in the same group means any one in this group passed, the result will be passed.
7. policyitem filefilter: Used to bind filefilter which define filter rules.
8. filefilter: Filter rules, the type filename is used to filter file name, the type filepath is used to filter file path.
Note:If the text contains special characters, please escape them according to the following rules:
" == &gt;
& == &gt;
' == &gt;
< == &gt;
> == &gt;
-->
<configuration>
<oatconfig>
<licensefile>COPYING</licensefile>
<policylist>
<policy name="projectPolicy" desc="">
<policyitem type="compatibility" name="LGPL" path="BUILD.gn" desc="They are used in dynamic link mode."/>
<policyitem type="compatibility" name="LGPL" path="install.sh" desc="They are used in dynamic link mode."/>
<policyitem type="compatibility" name="LGPL" path="libnl3.spec" desc="They are used in dynamic link mode."/>
</policy>
</policylist>
<filefilterlist>
<filefilter name="defaultPolicyFilter" desc="compatibilitylicense文件头校验策略的过滤条件" >
<filteritem type="filepath" name="configure.ac" desc="MIT LICENSE不影响兼容性"/>
<filteritem type="filepath" name="lib/siphash.h" desc="MIT LICENSE不影响兼容性"/>
</filefilter>
</filefilterlist>
</oatconfig>
</configuration>
-33
View File
@@ -1,33 +0,0 @@
{
"name": "@ohos/expat",
"description": "Expat is an XML parser library written in C. It is a stream-oriented parser in which an application registers handlers for things the parser might find in the XML document (like start tags).",
"version": "3.1",
"license": "MIT",
"publishAs": "code-segment",
"segment": {
"destPath": "third_party/expat"
},
"dirs": {},
"scripts": {},
"licensePath": "COPYING",
"component": {
"name": "expat",
"subsystem": "thirdparty",
"syscap": [],
"features": [],
"adapted_system_type": [
"standard"
],
"rom": "0",
"ram": "0",
"deps": {
"components": [],
"third_party": []
},
"build": {
"sub_component": [],
"inner_kits": [],
"test": []
}
}
}
Binary file not shown.
-161
View File
@@ -1,161 +0,0 @@
%define Rversion %(echo %{version} | sed -e 's/\\./_/g' -e 's/^/R_/')
Name: expat
Version: 2.4.1
Release: 8
Summary: An XML parser library
License: MIT
URL: https://libexpat.github.io/
Source0: https://github.com/libexpat/libexpat/releases/download/%{Rversion}/expat-%{version}.tar.gz
Patch0: backport-CVE-2021-45960.patch
Patch1: backport-CVE-2021-46143.patch
Patch2: backport-CVE-2022-22822-CVE-2022-22823-CVE-2022-22824-CVE-2022-22825-CVE-2022-22826-CVE-2022-22827.patch
Patch3: backport-CVE-2022-23852-lib-Detect-and-prevent-integer-overflow-in-XML_GetBu.patch
Patch4: backport-CVE-2022-23852-tests-Cover-integer-overflow-in-XML_GetBuffer-CVE-20.patch
Patch5: backport-CVE-2022-23990-lib-Prevent-integer-overflow-in-doProlog-CVE-2022-23.patch
Patch6: backport-CVE-2022-25235-lib-Add-missing-validation-of-encoding.patch
Patch7: backport-tests-Cover-missing-validation-of-encoding.patch
Patch8: backport-CVE-2022-25236-lib-Protect-against-malicious-namespace-declarations.patch
Patch9: backport-tests-Cover-CVE-2022-25236.patch
Patch10: backport-CVE-2022-25313-Prevent-stack-exhaustion-in-build_model.patch
Patch11: backport-CVE-2022-25314-Prevent-integer-overflow-in-copyString.patch
Patch12: backport-CVE-2022-25315-Prevent-integer-overflow-in-storeRawNames.patch
Patch13: backport-Fix-build_model-regression.patch
Patch14: backport-tests-Protect-against-nested-element-declaration-mod.patch
Patch15: backport-lib-Fix-harmless-use-of-uninitialized-memory.patch
Patch16: backport-lib-Drop-unused-macro-UTF8_GET_NAMING.patch
Patch17: backport-lib-Relax-fix-to-CVE-2022-25236-with-regard-to-RFC-3.patch
Patch18: backport-tests-Cover-relaxed-fix-to-CVE-2022-25236.patch
Patch19: backport-0001-CVE-2022-40674.patch
Patch20: backport-0002-CVE-2022-40674.patch
Patch21: backport-CVE-2022-43680.patch
Patch22: backport-tests-Cover-overeager-DTD-destruction-in-XML_Externa.patch
BuildRequires: sed,autoconf,automake,gcc-c++,libtool,xmlto
%description
expat is a stream-oriented XML parser library written in C.
expat excels with files too large to fit RAM, and where
performance and flexibility are crucial.
%package devel
Summary: Development files
Requires: %{name} = %{version}-%{release}
%description devel
This package provides with static libraries and header files for developing with expat.
%package_help
%prep
%autosetup -p1
%build
autoreconf -fiv
%configure CFLAGS="$RPM_OPT_FLAGS -fPIC" DOCBOOK_TO_MAN="xmlto man --skip-validation"
%make_build
%install
%makeinstall
find %{buildroot} -type f -name changelog -delete
%check
make check
%ldconfig_scriptlets
%files
%defattr(-,root,root)
%license COPYING AUTHORS
%{_bindir}/*
%{_libdir}/libexpat.so.1*
%exclude %{_docdir}/%{name}/AUTHORS
%files devel
%defattr(-,root,root)
%{_includedir}/*
%{_libdir}/{libexpat.*a,libexpat.so}
%{_libdir}/cmake/expat-%{version}
%{_libdir}/pkgconfig/expat.pc
%files help
%defattr(-,root,root)
%doc README.md
%{_mandir}/man1/*
%changelog
* Tue Dec 13 2022 zhoupengcheng <zhoupengcheng11@huawei.com> - 2.4.8-8
- Move autoreconf to build
* Sat Oct 29 2022 fuanan <fuanan3@h-partners.com> - 2.4.1-7
- fix CVE-2022-43680
* Thu Sep 15 2022 panxiaohe <panxh.life@foxmail.com> - 2.4.1-6
- fix CVE-2022-40674
* Mon Mar 7 2022 yangzhuangzhuang <yangzhuangzhuang1@h-partners.com> - 2.4.1-5
- Type:bugfix
- ID:NA
- SUG:NA
- DESC:Relax fix to CVE-2022-25236
* Sat Feb 26 2022 yangzhuangzhuang <yangzhuangzhuang1@h-partners.com> - 2.4.1-4
- Type:CVE
- ID:CVE-2022-25235 CVE-2022-25236 CVE-2022-25313 CVE-2022-25314 CVE-2022-25315
- SUG:NA
- DESC:Fix CVE-2022-25235 CVE-2022-25236 CVE-2022-25313 CVE-2022-25314 CVE-2022-25315
* Mon Feb 7 2022 yangzhuangzhuang <yangzhuangzhuang1@h-partners.com> - 2.4.1-3
- Type:CVE
- ID:CVE-2022-23852 CVE-2022-23990
- SUG:NA
- DESC:Fix CVE-2022-23852CVE-2022-23990
* Mon Jan 17 2022 wangjie <wangjie375@huawei.com> - 2.4.1-2
- Type:CVE
- ID:CVE-2021-45960 CVE-2021-46143 CVE-2022-22822 CVE-2022-22823 CVE-2022-22824 CVE-2022-22825 CVE-2022-22826 CVE-2022-22827
- SUG:NA
- DESC:fix CVE-2021-45960 CVE-2021-46143
CVE-2022-22822 CVE-2022-22823 CVE-2022-22824 CVE-2022-22825 CVE-2022-22826 CVE-2022-22827
* Tue Jul 6 2021 panxiaohe <panxiaohe@huawei.com> - 2.4.1-1
- update to 2.4.1
- fix CVE-2013-0340
* Wed Jan 20 2021 wangchen <wangchen137@huawei.com> - 2.2.10-1
- update to 2.2.10
* Sun Jun 28 2020 liuchenguang <liuchenguang4@huawei.com> - 2.2.9-2
- quality enhancement synchronization github patch
* Mon May 11 2020 openEuler Buildteam <buildteam@openeuler.org> - 2.2.9-1
- Type:requirement
- ID:NA
- SUG:NA
- DESC:update to 2.2.9
* Mon Oct 21 2019 shenyangyang <shenyangyang4@huawei.com> - 2.2.6-5
- Type:NA
- ID:NA
- SUG:NA
- DESC:modify the directory of AUTHORS
* Mon Oct 21 2019 shenyangyang <shenyangyang4@huawei.com> - 2.2.6-4
- Type:NA
- ID:NA
- SUG:NA
- DESC:move AUTHORS to license directory
* Sat Sep 28 2019 shenyangyang<shenyangyang4@huawei.com> - 2.2.6-3
- Type:cves
- ID:CVE-2019-15903
- SUG:NA
- DESC:fix CVE-2019-15903
* Fri Aug 30 2019 gulining<gulining1@huawei.com> - 2.2.6-2
- Type:cves
- ID:CVE-2018-20843
- SUG:NA
- DESC:fix CVE-2018-20843
* Thu Aug 29 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.2.6-1
- Package Init
-4
View File
@@ -1,4 +0,0 @@
version_control: github
src_repo: libexpat/libexpat
tag_prefix: "^R_"
seperator: _
-29
View File
@@ -1,29 +0,0 @@
#!/bin/bash
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation version 2.1
# of the License.
#
# Copyright(c) 2023 Huawei Device Co., Ltd.
set -e
if [ "$1" == "" ] || [ "$2" == "" ]; then
exit 1
fi
if [ -d "$2" ]; then
rm -rf "$2"
fi
mkdir -p $2
tar zxvf $1/expat-2.4.1.tar.gz -C $2
files=$(ls $1/*.patch)
for filename in $files
do
filenamebase=$(basename "$filename")
patch -d $2/expat-2.4.1 -p1 < $1/$filenamebase --fuzz=0 --no-backup-if-mismatch
done
exit 0