xref: /freebsd/contrib/expat/tests/common.c (revision b64c5a0ace59af62eff52bfe110a521dc73c937b)
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
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
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
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
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
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
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
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
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
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 *
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 *
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