1 /* Commonly used functions for the Expat test suite
2 __ __ _
3 ___\ \/ /_ __ __ _| |_
4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
7 |_| XML parser
8
9 Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
10 Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
11 Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
12 Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
13 Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
14 Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
15 Copyright (c) 2017 Joe Orton <jorton@redhat.com>
16 Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
17 Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it>
18 Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
19 Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
20 Copyright (c) 2021 Donghee Na <donghee.na@python.org>
21 Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
22 Licensed under the MIT license:
23
24 Permission is hereby granted, free of charge, to any person obtaining
25 a copy of this software and associated documentation files (the
26 "Software"), to deal in the Software without restriction, including
27 without limitation the rights to use, copy, modify, merge, publish,
28 distribute, sublicense, and/or sell copies of the Software, and to permit
29 persons to whom the Software is furnished to do so, subject to the
30 following conditions:
31
32 The above copyright notice and this permission notice shall be included
33 in all copies or substantial portions of the Software.
34
35 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
36 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
38 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
39 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
40 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
41 USE OR OTHER DEALINGS IN THE SOFTWARE.
42 */
43
44 #include <assert.h>
45 #include <stdio.h>
46 #include <string.h>
47
48 #include "expat_config.h"
49 #include "expat.h"
50 #include "internal.h"
51 #include "chardata.h"
52 #include "minicheck.h"
53 #include "common.h"
54 #include "handlers.h"
55
56 /* Common test data */
57
58 const char *long_character_data_text
59 = "<?xml version='1.0' encoding='iso-8859-1'?><s>"
60 "012345678901234567890123456789012345678901234567890123456789"
61 "012345678901234567890123456789012345678901234567890123456789"
62 "012345678901234567890123456789012345678901234567890123456789"
63 "012345678901234567890123456789012345678901234567890123456789"
64 "012345678901234567890123456789012345678901234567890123456789"
65 "012345678901234567890123456789012345678901234567890123456789"
66 "012345678901234567890123456789012345678901234567890123456789"
67 "012345678901234567890123456789012345678901234567890123456789"
68 "012345678901234567890123456789012345678901234567890123456789"
69 "012345678901234567890123456789012345678901234567890123456789"
70 "012345678901234567890123456789012345678901234567890123456789"
71 "012345678901234567890123456789012345678901234567890123456789"
72 "012345678901234567890123456789012345678901234567890123456789"
73 "012345678901234567890123456789012345678901234567890123456789"
74 "012345678901234567890123456789012345678901234567890123456789"
75 "012345678901234567890123456789012345678901234567890123456789"
76 "012345678901234567890123456789012345678901234567890123456789"
77 "012345678901234567890123456789012345678901234567890123456789"
78 "012345678901234567890123456789012345678901234567890123456789"
79 "012345678901234567890123456789012345678901234567890123456789"
80 "</s>";
81
82 const char *long_cdata_text
83 = "<s><![CDATA["
84 "012345678901234567890123456789012345678901234567890123456789"
85 "012345678901234567890123456789012345678901234567890123456789"
86 "012345678901234567890123456789012345678901234567890123456789"
87 "012345678901234567890123456789012345678901234567890123456789"
88 "012345678901234567890123456789012345678901234567890123456789"
89 "012345678901234567890123456789012345678901234567890123456789"
90 "012345678901234567890123456789012345678901234567890123456789"
91 "012345678901234567890123456789012345678901234567890123456789"
92 "012345678901234567890123456789012345678901234567890123456789"
93 "012345678901234567890123456789012345678901234567890123456789"
94 "012345678901234567890123456789012345678901234567890123456789"
95 "012345678901234567890123456789012345678901234567890123456789"
96 "012345678901234567890123456789012345678901234567890123456789"
97 "012345678901234567890123456789012345678901234567890123456789"
98 "012345678901234567890123456789012345678901234567890123456789"
99 "012345678901234567890123456789012345678901234567890123456789"
100 "012345678901234567890123456789012345678901234567890123456789"
101 "012345678901234567890123456789012345678901234567890123456789"
102 "012345678901234567890123456789012345678901234567890123456789"
103 "012345678901234567890123456789012345678901234567890123456789"
104 "]]></s>";
105
106 /* Having an element name longer than 1024 characters exercises some
107 * of the pool allocation code in the parser that otherwise does not
108 * get executed. The count at the end of the line is the number of
109 * characters (bytes) in the element name by that point.x
110 */
111 const char *get_buffer_test_text
112 = "<documentwitharidiculouslylongelementnametotease" /* 0x030 */
113 "aparticularcorneroftheallocationinXML_GetBuffers" /* 0x060 */
114 "othatwecanimprovethecoverageyetagain012345678901" /* 0x090 */
115 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0c0 */
116 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x0f0 */
117 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x120 */
118 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x150 */
119 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x180 */
120 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1b0 */
121 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x1e0 */
122 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x210 */
123 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x240 */
124 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x270 */
125 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2a0 */
126 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x2d0 */
127 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x300 */
128 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x330 */
129 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x360 */
130 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x390 */
131 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3c0 */
132 "123456789abcdef0123456789abcdef0123456789abcdef0" /* 0x3f0 */
133 "123456789abcdef0123456789abcdef0123456789>\n<ef0"; /* 0x420 */
134
135 /* Test control globals */
136
137 /* Used as the "resumable" parameter to XML_StopParser by some tests */
138 XML_Bool g_resumable = XML_FALSE;
139
140 /* Used to control abort checks in some tests */
141 XML_Bool g_abortable = XML_FALSE;
142
143 /* Used to control _XML_Parse_SINGLE_BYTES() chunk size */
144 int g_chunkSize = 1;
145
146 /* Common test functions */
147
148 void
tcase_add_test__ifdef_xml_dtd(TCase * tc,tcase_test_function test)149 tcase_add_test__ifdef_xml_dtd(TCase *tc, tcase_test_function test) {
150 #ifdef XML_DTD
151 tcase_add_test(tc, test);
152 #else
153 UNUSED_P(tc);
154 UNUSED_P(test);
155 #endif
156 }
157
158 void
tcase_add_test__if_xml_ge(TCase * tc,tcase_test_function test)159 tcase_add_test__if_xml_ge(TCase *tc, tcase_test_function test) {
160 #if XML_GE == 1
161 tcase_add_test(tc, test);
162 #else
163 UNUSED_P(tc);
164 UNUSED_P(test);
165 #endif
166 }
167
168 void
basic_teardown(void)169 basic_teardown(void) {
170 if (g_parser != NULL) {
171 XML_ParserFree(g_parser);
172 g_parser = NULL;
173 }
174 }
175
176 /* Generate a failure using the parser state to create an error message;
177 this should be used when the parser reports an error we weren't
178 expecting.
179 */
180 void
_xml_failure(XML_Parser parser,const char * file,int line)181 _xml_failure(XML_Parser parser, const char *file, int line) {
182 char buffer[1024];
183 enum XML_Error err = XML_GetErrorCode(parser);
184 snprintf(buffer, sizeof(buffer),
185 " %d: %" XML_FMT_STR " (line %" XML_FMT_INT_MOD
186 "u, offset %" XML_FMT_INT_MOD "u)\n reported from %s, line %d\n",
187 err, XML_ErrorString(err), XML_GetCurrentLineNumber(parser),
188 XML_GetCurrentColumnNumber(parser), file, line);
189 _fail(file, line, buffer);
190 }
191
192 enum XML_Status
_XML_Parse_SINGLE_BYTES(XML_Parser parser,const char * s,int len,int isFinal)193 _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
194 int isFinal) {
195 // This ensures that tests have to run pathological parse cases
196 // (e.g. when `s` is NULL) against plain XML_Parse rather than
197 // chunking _XML_Parse_SINGLE_BYTES.
198 assert((parser != NULL) && (s != NULL) && (len >= 0));
199 const int chunksize = g_chunkSize;
200 if (chunksize > 0) {
201 // parse in chunks of `chunksize` bytes as long as not exhausting
202 for (; len > chunksize; len -= chunksize, s += chunksize) {
203 enum XML_Status res = XML_Parse(parser, s, chunksize, XML_FALSE);
204 if (res != XML_STATUS_OK) {
205 return res;
206 }
207 }
208 }
209 // parse the final chunk, the size of which will be <= chunksize
210 return XML_Parse(parser, s, len, isFinal);
211 }
212
213 void
_expect_failure(const char * text,enum XML_Error errorCode,const char * errorMessage,const char * file,int lineno)214 _expect_failure(const char *text, enum XML_Error errorCode,
215 const char *errorMessage, const char *file, int lineno) {
216 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
217 == XML_STATUS_OK)
218 /* Hackish use of _fail() macro, but lets us report
219 the right filename and line number. */
220 _fail(file, lineno, errorMessage);
221 if (XML_GetErrorCode(g_parser) != errorCode)
222 _xml_failure(g_parser, file, lineno);
223 }
224
225 void
_run_character_check(const char * text,const XML_Char * expected,const char * file,int line)226 _run_character_check(const char *text, const XML_Char *expected,
227 const char *file, int line) {
228 CharData storage;
229
230 CharData_Init(&storage);
231 XML_SetUserData(g_parser, &storage);
232 XML_SetCharacterDataHandler(g_parser, accumulate_characters);
233 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
234 == XML_STATUS_ERROR)
235 _xml_failure(g_parser, file, line);
236 CharData_CheckXMLChars(&storage, expected);
237 }
238
239 void
_run_attribute_check(const char * text,const XML_Char * expected,const char * file,int line)240 _run_attribute_check(const char *text, const XML_Char *expected,
241 const char *file, int line) {
242 CharData storage;
243
244 CharData_Init(&storage);
245 XML_SetUserData(g_parser, &storage);
246 XML_SetStartElementHandler(g_parser, accumulate_attribute);
247 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
248 == XML_STATUS_ERROR)
249 _xml_failure(g_parser, file, line);
250 CharData_CheckXMLChars(&storage, expected);
251 }
252
253 void
_run_ext_character_check(const char * text,ExtTest * test_data,const XML_Char * expected,const char * file,int line)254 _run_ext_character_check(const char *text, ExtTest *test_data,
255 const XML_Char *expected, const char *file, int line) {
256 CharData *const storage = (CharData *)malloc(sizeof(CharData));
257
258 CharData_Init(storage);
259 test_data->storage = storage;
260 XML_SetUserData(g_parser, test_data);
261 XML_SetCharacterDataHandler(g_parser, ext_accumulate_characters);
262 if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
263 == XML_STATUS_ERROR)
264 _xml_failure(g_parser, file, line);
265 CharData_CheckXMLChars(storage, expected);
266
267 free(storage);
268 }
269
270 /* Control variable; the number of times duff_allocator() will successfully
271 * allocate */
272 #define ALLOC_ALWAYS_SUCCEED (-1)
273 #define REALLOC_ALWAYS_SUCCEED (-1)
274
275 int g_allocation_count = ALLOC_ALWAYS_SUCCEED;
276 int g_reallocation_count = REALLOC_ALWAYS_SUCCEED;
277
278 /* Crocked allocator for allocation failure tests */
279 void *
duff_allocator(size_t size)280 duff_allocator(size_t size) {
281 if (g_allocation_count == 0)
282 return NULL;
283 if (g_allocation_count != ALLOC_ALWAYS_SUCCEED)
284 g_allocation_count--;
285 return malloc(size);
286 }
287
288 /* Crocked reallocator for allocation failure tests */
289 void *
duff_reallocator(void * ptr,size_t size)290 duff_reallocator(void *ptr, size_t size) {
291 if (g_reallocation_count == 0)
292 return NULL;
293 if (g_reallocation_count != REALLOC_ALWAYS_SUCCEED)
294 g_reallocation_count--;
295 return realloc(ptr, size);
296 }
297