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