• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1From 154e565f6ef329c9ec97e6534c411ddde0b320c8 Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Sun, 20 Feb 2022 03:26:57 +0100
4Subject: [PATCH] tests: Protect against nested element declaration
5 model regressions
6
7---
8 tests/runtests.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++
9 1 file changed, 77 insertions(+)
10
11diff --git a/tests/runtests.c b/tests/runtests.c
12index 2cd4acb..e28670d 100644
13--- a/tests/runtests.c
14+++ b/tests/runtests.c
15@@ -2664,6 +2664,82 @@ START_TEST(test_dtd_elements) {
16 }
17 END_TEST
18
19+static void XMLCALL
20+element_decl_check_model(void *userData, const XML_Char *name,
21+                         XML_Content *model) {
22+  UNUSED_P(userData);
23+  uint32_t errorFlags = 0;
24+
25+  /* Expected model array structure is this:
26+   * [0] (type 6, quant 0)
27+   *   [1] (type 5, quant 0)
28+   *     [3] (type 4, quant 0, name "bar")
29+   *     [4] (type 4, quant 0, name "foo")
30+   *     [5] (type 4, quant 3, name "xyz")
31+   *   [2] (type 4, quant 2, name "zebra")
32+   */
33+  errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0));
34+  errorFlags |= ((model != NULL) ? 0 : (1u << 1));
35+
36+  errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2));
37+  errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3));
38+  errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4));
39+  errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5));
40+  errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6));
41+
42+  errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7));
43+  errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8));
44+  errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9));
45+  errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10));
46+  errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11));
47+
48+  errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12));
49+  errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13));
50+  errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14));
51+  errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15));
52+  errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16));
53+
54+  errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17));
55+  errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18));
56+  errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19));
57+  errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20));
58+  errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21));
59+
60+  errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22));
61+  errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23));
62+  errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24));
63+  errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25));
64+  errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26));
65+
66+  errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27));
67+  errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28));
68+  errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29));
69+  errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30));
70+  errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31));
71+
72+  XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags);
73+  XML_FreeContentModel(g_parser, model);
74+}
75+
76+START_TEST(test_dtd_elements_nesting) {
77+  // Payload inspired by a test in Perl's XML::Parser
78+  const char *text = "<!DOCTYPE foo [\n"
79+                     "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n"
80+                     "]>\n"
81+                     "<foo/>";
82+
83+  XML_SetUserData(g_parser, (void *)(uintptr_t)-1);
84+
85+  XML_SetElementDeclHandler(g_parser, element_decl_check_model);
86+  if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
87+      == XML_STATUS_ERROR)
88+    xml_failure(g_parser);
89+
90+  if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0)
91+    fail("Element declaration model regression detected");
92+}
93+END_TEST
94+
95 /* Test foreign DTD handling */
96 START_TEST(test_set_foreign_dtd) {
97   const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
98@@ -11863,6 +11939,7 @@ make_suite(void) {
99   tcase_add_test(tc_basic, test_memory_allocation);
100   tcase_add_test(tc_basic, test_default_current);
101   tcase_add_test(tc_basic, test_dtd_elements);
102+  tcase_add_test(tc_basic, test_dtd_elements_nesting);
103   tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
104   tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
105   tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
106--
1071.8.3.1
108
109