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