1*4543ef51SXin LI /* Tests in the "accounting" test case for the Expat test suite
2*4543ef51SXin LI __ __ _
3*4543ef51SXin LI ___\ \/ /_ __ __ _| |_
4*4543ef51SXin LI / _ \\ /| '_ \ / _` | __|
5*4543ef51SXin LI | __// \| |_) | (_| | |_
6*4543ef51SXin LI \___/_/\_\ .__/ \__,_|\__|
7*4543ef51SXin LI |_| XML parser
8*4543ef51SXin LI
9*4543ef51SXin LI Copyright (c) 2001-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
10*4543ef51SXin LI Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
11*4543ef51SXin LI Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
12*4543ef51SXin LI Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
13*4543ef51SXin LI Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
14*4543ef51SXin LI Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
15*4543ef51SXin LI Copyright (c) 2017 Joe Orton <jorton@redhat.com>
16*4543ef51SXin LI Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
17*4543ef51SXin LI Copyright (c) 2018 Marco Maggi <marco.maggi-ipsu@poste.it>
18*4543ef51SXin LI Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
19*4543ef51SXin LI Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
20*4543ef51SXin LI Copyright (c) 2021 Donghee Na <donghee.na@python.org>
21*4543ef51SXin LI Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
22*4543ef51SXin LI Licensed under the MIT license:
23*4543ef51SXin LI
24*4543ef51SXin LI Permission is hereby granted, free of charge, to any person obtaining
25*4543ef51SXin LI a copy of this software and associated documentation files (the
26*4543ef51SXin LI "Software"), to deal in the Software without restriction, including
27*4543ef51SXin LI without limitation the rights to use, copy, modify, merge, publish,
28*4543ef51SXin LI distribute, sublicense, and/or sell copies of the Software, and to permit
29*4543ef51SXin LI persons to whom the Software is furnished to do so, subject to the
30*4543ef51SXin LI following conditions:
31*4543ef51SXin LI
32*4543ef51SXin LI The above copyright notice and this permission notice shall be included
33*4543ef51SXin LI in all copies or substantial portions of the Software.
34*4543ef51SXin LI
35*4543ef51SXin LI THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
36*4543ef51SXin LI EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37*4543ef51SXin LI MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
38*4543ef51SXin LI NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
39*4543ef51SXin LI DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
40*4543ef51SXin LI OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
41*4543ef51SXin LI USE OR OTHER DEALINGS IN THE SOFTWARE.
42*4543ef51SXin LI */
43*4543ef51SXin LI
44*4543ef51SXin LI #include <math.h> /* NAN, INFINITY */
45*4543ef51SXin LI #include <stdio.h>
46*4543ef51SXin LI #include <string.h>
47*4543ef51SXin LI
48*4543ef51SXin LI #include "expat_config.h"
49*4543ef51SXin LI
50*4543ef51SXin LI #include "expat.h"
51*4543ef51SXin LI #include "internal.h"
52*4543ef51SXin LI #include "common.h"
53*4543ef51SXin LI #include "minicheck.h"
54*4543ef51SXin LI #include "chardata.h"
55*4543ef51SXin LI #include "handlers.h"
56*4543ef51SXin LI #include "acc_tests.h"
57*4543ef51SXin LI
58*4543ef51SXin LI #if XML_GE == 1
START_TEST(test_accounting_precision)59*4543ef51SXin LI START_TEST(test_accounting_precision) {
60*4543ef51SXin LI struct AccountingTestCase cases[] = {
61*4543ef51SXin LI {"<e/>", NULL, NULL, 0},
62*4543ef51SXin LI {"<e></e>", NULL, NULL, 0},
63*4543ef51SXin LI
64*4543ef51SXin LI /* Attributes */
65*4543ef51SXin LI {"<e k1=\"v2\" k2=\"v2\"/>", NULL, NULL, 0},
66*4543ef51SXin LI {"<e k1=\"v2\" k2=\"v2\"></e>", NULL, NULL, 0},
67*4543ef51SXin LI {"<p:e xmlns:p=\"https://domain.invalid/\" />", NULL, NULL, 0},
68*4543ef51SXin LI {"<e k=\"&'><"\" />", NULL, NULL,
69*4543ef51SXin LI sizeof(XML_Char) * 5 /* number of predefined entities */},
70*4543ef51SXin LI {"<e1 xmlns='https://example.org/'>\n"
71*4543ef51SXin LI " <e2 xmlns=''/>\n"
72*4543ef51SXin LI "</e1>",
73*4543ef51SXin LI NULL, NULL, 0},
74*4543ef51SXin LI
75*4543ef51SXin LI /* Text */
76*4543ef51SXin LI {"<e>text</e>", NULL, NULL, 0},
77*4543ef51SXin LI {"<e1><e2>text1<e3/>text2</e2></e1>", NULL, NULL, 0},
78*4543ef51SXin LI {"<e>&'><"</e>", NULL, NULL,
79*4543ef51SXin LI sizeof(XML_Char) * 5 /* number of predefined entities */},
80*4543ef51SXin LI {"<e>A)</e>", NULL, NULL, 0},
81*4543ef51SXin LI
82*4543ef51SXin LI /* Prolog */
83*4543ef51SXin LI {"<?xml version=\"1.0\"?><root/>", NULL, NULL, 0},
84*4543ef51SXin LI
85*4543ef51SXin LI /* Whitespace */
86*4543ef51SXin LI {" <e1> <e2> </e2> </e1> ", NULL, NULL, 0},
87*4543ef51SXin LI {"<e1 ><e2 /></e1 >", NULL, NULL, 0},
88*4543ef51SXin LI {"<e1><e2 k = \"v\"/><e3 k = 'v'/></e1>", NULL, NULL, 0},
89*4543ef51SXin LI
90*4543ef51SXin LI /* Comments */
91*4543ef51SXin LI {"<!-- Comment --><e><!-- Comment --></e>", NULL, NULL, 0},
92*4543ef51SXin LI
93*4543ef51SXin LI /* Processing instructions */
94*4543ef51SXin LI {"<?xml-stylesheet type=\"text/xsl\" href=\"https://domain.invalid/\" media=\"all\"?><e/>",
95*4543ef51SXin LI NULL, NULL, 0},
96*4543ef51SXin LI {"<?pi0?><?pi1 ?><?pi2 ?><r/><?pi4?>", NULL, NULL, 0},
97*4543ef51SXin LI # ifdef XML_DTD
98*4543ef51SXin LI {"<?pi0?><?pi1 ?><?pi2 ?><!DOCTYPE r SYSTEM 'first.ent'><r/>",
99*4543ef51SXin LI "<?pi3?><!ENTITY % e1 SYSTEM 'second.ent'><?pi4?>%e1;<?pi5?>", "<?pi6?>",
100*4543ef51SXin LI 0},
101*4543ef51SXin LI # endif /* XML_DTD */
102*4543ef51SXin LI
103*4543ef51SXin LI /* CDATA */
104*4543ef51SXin LI {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0},
105*4543ef51SXin LI /* The following is the essence of this OSS-Fuzz finding:
106*4543ef51SXin LI https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302
107*4543ef51SXin LI https://oss-fuzz.com/testcase-detail/4860575394955264
108*4543ef51SXin LI */
109*4543ef51SXin LI {"<!DOCTYPE r [\n"
110*4543ef51SXin LI "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n"
111*4543ef51SXin LI "]>\n"
112*4543ef51SXin LI "<r>&e;</r>\n",
113*4543ef51SXin LI NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333")},
114*4543ef51SXin LI
115*4543ef51SXin LI # ifdef XML_DTD
116*4543ef51SXin LI /* Conditional sections */
117*4543ef51SXin LI {"<!DOCTYPE r [\n"
118*4543ef51SXin LI "<!ENTITY % draft 'INCLUDE'>\n"
119*4543ef51SXin LI "<!ENTITY % final 'IGNORE'>\n"
120*4543ef51SXin LI "<!ENTITY % import SYSTEM \"first.ent\">\n"
121*4543ef51SXin LI "%import;\n"
122*4543ef51SXin LI "]>\n"
123*4543ef51SXin LI "<r/>\n",
124*4543ef51SXin LI "<![%draft;[<!--1-->]]>\n"
125*4543ef51SXin LI "<![%final;[<!--22-->]]>",
126*4543ef51SXin LI NULL, sizeof(XML_Char) * (strlen("INCLUDE") + strlen("IGNORE"))},
127*4543ef51SXin LI # endif /* XML_DTD */
128*4543ef51SXin LI
129*4543ef51SXin LI /* General entities */
130*4543ef51SXin LI {"<!DOCTYPE root [\n"
131*4543ef51SXin LI "<!ENTITY nine \"123456789\">\n"
132*4543ef51SXin LI "]>\n"
133*4543ef51SXin LI "<root>&nine;</root>",
134*4543ef51SXin LI NULL, NULL, sizeof(XML_Char) * strlen("123456789")},
135*4543ef51SXin LI {"<!DOCTYPE root [\n"
136*4543ef51SXin LI "<!ENTITY nine \"123456789\">\n"
137*4543ef51SXin LI "]>\n"
138*4543ef51SXin LI "<root k1=\"&nine;\"/>",
139*4543ef51SXin LI NULL, NULL, sizeof(XML_Char) * strlen("123456789")},
140*4543ef51SXin LI {"<!DOCTYPE root [\n"
141*4543ef51SXin LI "<!ENTITY nine \"123456789\">\n"
142*4543ef51SXin LI "<!ENTITY nine2 \"&nine;&nine;\">\n"
143*4543ef51SXin LI "]>\n"
144*4543ef51SXin LI "<root>&nine2;&nine2;&nine2;</root>",
145*4543ef51SXin LI NULL, NULL,
146*4543ef51SXin LI sizeof(XML_Char) * 3 /* calls to &nine2; */ * 2 /* calls to &nine; */
147*4543ef51SXin LI * (strlen("&nine;") + strlen("123456789"))},
148*4543ef51SXin LI {"<!DOCTYPE r [\n"
149*4543ef51SXin LI " <!ENTITY five SYSTEM 'first.ent'>\n"
150*4543ef51SXin LI "]>\n"
151*4543ef51SXin LI "<r>&five;</r>",
152*4543ef51SXin LI "12345", NULL, 0},
153*4543ef51SXin LI {"<!DOCTYPE r [\n"
154*4543ef51SXin LI " <!ENTITY five SYSTEM 'first.ent'>\n"
155*4543ef51SXin LI "]>\n"
156*4543ef51SXin LI "<r>&five;</r>",
157*4543ef51SXin LI "\xEF\xBB\xBF" /* UTF-8 BOM */, NULL, 0},
158*4543ef51SXin LI
159*4543ef51SXin LI # ifdef XML_DTD
160*4543ef51SXin LI /* Parameter entities */
161*4543ef51SXin LI {"<!DOCTYPE r [\n"
162*4543ef51SXin LI "<!ENTITY % comment \"<!---->\">\n"
163*4543ef51SXin LI "%comment;\n"
164*4543ef51SXin LI "]>\n"
165*4543ef51SXin LI "<r/>",
166*4543ef51SXin LI NULL, NULL, sizeof(XML_Char) * strlen("<!---->")},
167*4543ef51SXin LI {"<!DOCTYPE r [\n"
168*4543ef51SXin LI "<!ENTITY % ninedef \"<!ENTITY nine "123456789">\">\n"
169*4543ef51SXin LI "%ninedef;\n"
170*4543ef51SXin LI "]>\n"
171*4543ef51SXin LI "<r>&nine;</r>",
172*4543ef51SXin LI NULL, NULL,
173*4543ef51SXin LI sizeof(XML_Char)
174*4543ef51SXin LI * (strlen("<!ENTITY nine \"123456789\">") + strlen("123456789"))},
175*4543ef51SXin LI {"<!DOCTYPE r [\n"
176*4543ef51SXin LI "<!ENTITY % comment \"<!--1-->\">\n"
177*4543ef51SXin LI "<!ENTITY % comment2 \"%comment;<!--22-->%comment;\">\n"
178*4543ef51SXin LI "%comment2;\n"
179*4543ef51SXin LI "]>\n"
180*4543ef51SXin LI "<r/>\n",
181*4543ef51SXin LI NULL, NULL,
182*4543ef51SXin LI sizeof(XML_Char)
183*4543ef51SXin LI * (strlen("%comment;<!--22-->%comment;") + 2 * strlen("<!--1-->"))},
184*4543ef51SXin LI {"<!DOCTYPE r [\n"
185*4543ef51SXin LI " <!ENTITY % five \"12345\">\n"
186*4543ef51SXin LI " <!ENTITY % five2def \"<!ENTITY five2 "[%five;][%five;]]]]">\">\n"
187*4543ef51SXin LI " %five2def;\n"
188*4543ef51SXin LI "]>\n"
189*4543ef51SXin LI "<r>&five2;</r>",
190*4543ef51SXin LI NULL, NULL, /* from "%five2def;": */
191*4543ef51SXin LI sizeof(XML_Char)
192*4543ef51SXin LI * (strlen("<!ENTITY five2 \"[%five;][%five;]]]]\">")
193*4543ef51SXin LI + 2 /* calls to "%five;" */ * strlen("12345")
194*4543ef51SXin LI + /* from "&five2;": */ strlen("[12345][12345]]]]"))},
195*4543ef51SXin LI {"<!DOCTYPE r SYSTEM \"first.ent\">\n"
196*4543ef51SXin LI "<r/>",
197*4543ef51SXin LI "<!ENTITY % comment '<!--1-->'>\n"
198*4543ef51SXin LI "<!ENTITY % comment2 '<!--22-->%comment;<!--22-->%comment;<!--22-->'>\n"
199*4543ef51SXin LI "%comment2;",
200*4543ef51SXin LI NULL,
201*4543ef51SXin LI sizeof(XML_Char)
202*4543ef51SXin LI * (strlen("<!--22-->%comment;<!--22-->%comment;<!--22-->")
203*4543ef51SXin LI + 2 /* calls to "%comment;" */ * strlen("<!---->"))},
204*4543ef51SXin LI {"<!DOCTYPE r SYSTEM 'first.ent'>\n"
205*4543ef51SXin LI "<r/>",
206*4543ef51SXin LI "<!ENTITY % e1 PUBLIC 'foo' 'second.ent'>\n"
207*4543ef51SXin LI "<!ENTITY % e2 '<!--22-->%e1;<!--22-->'>\n"
208*4543ef51SXin LI "%e2;\n",
209*4543ef51SXin LI "<!--1-->", sizeof(XML_Char) * strlen("<!--22--><!--1--><!--22-->")},
210*4543ef51SXin LI {
211*4543ef51SXin LI "<!DOCTYPE r SYSTEM 'first.ent'>\n"
212*4543ef51SXin LI "<r/>",
213*4543ef51SXin LI "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
214*4543ef51SXin LI "<!ENTITY % e2 '%e1;'>",
215*4543ef51SXin LI "<?xml version='1.0' encoding='utf-8'?>\n"
216*4543ef51SXin LI "hello\n"
217*4543ef51SXin LI "xml" /* without trailing newline! */,
218*4543ef51SXin LI 0,
219*4543ef51SXin LI },
220*4543ef51SXin LI {
221*4543ef51SXin LI "<!DOCTYPE r SYSTEM 'first.ent'>\n"
222*4543ef51SXin LI "<r/>",
223*4543ef51SXin LI "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
224*4543ef51SXin LI "<!ENTITY % e2 '%e1;'>",
225*4543ef51SXin LI "<?xml version='1.0' encoding='utf-8'?>\n"
226*4543ef51SXin LI "hello\n"
227*4543ef51SXin LI "xml\n" /* with trailing newline! */,
228*4543ef51SXin LI 0,
229*4543ef51SXin LI },
230*4543ef51SXin LI {"<!DOCTYPE doc SYSTEM 'first.ent'>\n"
231*4543ef51SXin LI "<doc></doc>\n",
232*4543ef51SXin LI "<!ELEMENT doc EMPTY>\n"
233*4543ef51SXin LI "<!ENTITY % e1 SYSTEM 'second.ent'>\n"
234*4543ef51SXin LI "<!ENTITY % e2 '%e1;'>\n"
235*4543ef51SXin LI "%e1;\n",
236*4543ef51SXin LI "\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>" /* UTF-8 BOM */,
237*4543ef51SXin LI strlen("\xEF\xBB\xBF<!ATTLIST doc a1 CDATA 'value'>")},
238*4543ef51SXin LI # endif /* XML_DTD */
239*4543ef51SXin LI };
240*4543ef51SXin LI
241*4543ef51SXin LI const size_t countCases = sizeof(cases) / sizeof(cases[0]);
242*4543ef51SXin LI size_t u = 0;
243*4543ef51SXin LI for (; u < countCases; u++) {
244*4543ef51SXin LI const unsigned long long expectedCountBytesDirect
245*4543ef51SXin LI = strlen(cases[u].primaryText);
246*4543ef51SXin LI const unsigned long long expectedCountBytesIndirect
247*4543ef51SXin LI = (cases[u].firstExternalText ? strlen(cases[u].firstExternalText) : 0)
248*4543ef51SXin LI + (cases[u].secondExternalText ? strlen(cases[u].secondExternalText)
249*4543ef51SXin LI : 0)
250*4543ef51SXin LI + cases[u].expectedCountBytesIndirectExtra;
251*4543ef51SXin LI
252*4543ef51SXin LI XML_Parser parser = XML_ParserCreate(NULL);
253*4543ef51SXin LI XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
254*4543ef51SXin LI if (cases[u].firstExternalText) {
255*4543ef51SXin LI XML_SetExternalEntityRefHandler(parser,
256*4543ef51SXin LI accounting_external_entity_ref_handler);
257*4543ef51SXin LI XML_SetUserData(parser, (void *)&cases[u]);
258*4543ef51SXin LI }
259*4543ef51SXin LI
260*4543ef51SXin LI enum XML_Status status
261*4543ef51SXin LI = _XML_Parse_SINGLE_BYTES(parser, cases[u].primaryText,
262*4543ef51SXin LI (int)strlen(cases[u].primaryText), XML_TRUE);
263*4543ef51SXin LI if (status != XML_STATUS_OK) {
264*4543ef51SXin LI _xml_failure(parser, __FILE__, __LINE__);
265*4543ef51SXin LI }
266*4543ef51SXin LI
267*4543ef51SXin LI const unsigned long long actualCountBytesDirect
268*4543ef51SXin LI = testingAccountingGetCountBytesDirect(parser);
269*4543ef51SXin LI const unsigned long long actualCountBytesIndirect
270*4543ef51SXin LI = testingAccountingGetCountBytesIndirect(parser);
271*4543ef51SXin LI
272*4543ef51SXin LI XML_ParserFree(parser);
273*4543ef51SXin LI
274*4543ef51SXin LI if (actualCountBytesDirect != expectedCountBytesDirect) {
275*4543ef51SXin LI fprintf(
276*4543ef51SXin LI stderr,
277*4543ef51SXin LI "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ": Expected " EXPAT_FMT_ULL(
278*4543ef51SXin LI "") " count direct bytes, got " EXPAT_FMT_ULL("") " instead.\n",
279*4543ef51SXin LI u + 1, countCases, expectedCountBytesDirect, actualCountBytesDirect);
280*4543ef51SXin LI fail("Count of direct bytes is off");
281*4543ef51SXin LI }
282*4543ef51SXin LI
283*4543ef51SXin LI if (actualCountBytesIndirect != expectedCountBytesIndirect) {
284*4543ef51SXin LI fprintf(
285*4543ef51SXin LI stderr,
286*4543ef51SXin LI "Document " EXPAT_FMT_SIZE_T("") " of " EXPAT_FMT_SIZE_T("") ": Expected " EXPAT_FMT_ULL(
287*4543ef51SXin LI "") " count indirect bytes, got " EXPAT_FMT_ULL("") " instead.\n",
288*4543ef51SXin LI u + 1, countCases, expectedCountBytesIndirect,
289*4543ef51SXin LI actualCountBytesIndirect);
290*4543ef51SXin LI fail("Count of indirect bytes is off");
291*4543ef51SXin LI }
292*4543ef51SXin LI }
293*4543ef51SXin LI }
294*4543ef51SXin LI END_TEST
295*4543ef51SXin LI
START_TEST(test_billion_laughs_attack_protection_api)296*4543ef51SXin LI START_TEST(test_billion_laughs_attack_protection_api) {
297*4543ef51SXin LI XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
298*4543ef51SXin LI XML_Parser parserWithParent = XML_ExternalEntityParserCreate(
299*4543ef51SXin LI parserWithoutParent, XCS("entity123"), NULL);
300*4543ef51SXin LI if (parserWithoutParent == NULL)
301*4543ef51SXin LI fail("parserWithoutParent is NULL");
302*4543ef51SXin LI if (parserWithParent == NULL)
303*4543ef51SXin LI fail("parserWithParent is NULL");
304*4543ef51SXin LI
305*4543ef51SXin LI // XML_SetBillionLaughsAttackProtectionMaximumAmplification, error cases
306*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(NULL, 123.0f)
307*4543ef51SXin LI == XML_TRUE)
308*4543ef51SXin LI fail("Call with NULL parser is NOT supposed to succeed");
309*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(parserWithParent,
310*4543ef51SXin LI 123.0f)
311*4543ef51SXin LI == XML_TRUE)
312*4543ef51SXin LI fail("Call with non-root parser is NOT supposed to succeed");
313*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
314*4543ef51SXin LI parserWithoutParent, NAN)
315*4543ef51SXin LI == XML_TRUE)
316*4543ef51SXin LI fail("Call with NaN limit is NOT supposed to succeed");
317*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
318*4543ef51SXin LI parserWithoutParent, -1.0f)
319*4543ef51SXin LI == XML_TRUE)
320*4543ef51SXin LI fail("Call with negative limit is NOT supposed to succeed");
321*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
322*4543ef51SXin LI parserWithoutParent, 0.9f)
323*4543ef51SXin LI == XML_TRUE)
324*4543ef51SXin LI fail("Call with positive limit <1.0 is NOT supposed to succeed");
325*4543ef51SXin LI
326*4543ef51SXin LI // XML_SetBillionLaughsAttackProtectionMaximumAmplification, success cases
327*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
328*4543ef51SXin LI parserWithoutParent, 1.0f)
329*4543ef51SXin LI == XML_FALSE)
330*4543ef51SXin LI fail("Call with positive limit >=1.0 is supposed to succeed");
331*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
332*4543ef51SXin LI parserWithoutParent, 123456.789f)
333*4543ef51SXin LI == XML_FALSE)
334*4543ef51SXin LI fail("Call with positive limit >=1.0 is supposed to succeed");
335*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
336*4543ef51SXin LI parserWithoutParent, INFINITY)
337*4543ef51SXin LI == XML_FALSE)
338*4543ef51SXin LI fail("Call with positive limit >=1.0 is supposed to succeed");
339*4543ef51SXin LI
340*4543ef51SXin LI // XML_SetBillionLaughsAttackProtectionActivationThreshold, error cases
341*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionActivationThreshold(NULL, 123)
342*4543ef51SXin LI == XML_TRUE)
343*4543ef51SXin LI fail("Call with NULL parser is NOT supposed to succeed");
344*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionActivationThreshold(parserWithParent,
345*4543ef51SXin LI 123)
346*4543ef51SXin LI == XML_TRUE)
347*4543ef51SXin LI fail("Call with non-root parser is NOT supposed to succeed");
348*4543ef51SXin LI
349*4543ef51SXin LI // XML_SetBillionLaughsAttackProtectionActivationThreshold, success cases
350*4543ef51SXin LI if (XML_SetBillionLaughsAttackProtectionActivationThreshold(
351*4543ef51SXin LI parserWithoutParent, 123)
352*4543ef51SXin LI == XML_FALSE)
353*4543ef51SXin LI fail("Call with non-NULL parentless parser is supposed to succeed");
354*4543ef51SXin LI
355*4543ef51SXin LI XML_ParserFree(parserWithParent);
356*4543ef51SXin LI XML_ParserFree(parserWithoutParent);
357*4543ef51SXin LI }
358*4543ef51SXin LI END_TEST
359*4543ef51SXin LI
START_TEST(test_helper_unsigned_char_to_printable)360*4543ef51SXin LI START_TEST(test_helper_unsigned_char_to_printable) {
361*4543ef51SXin LI // Smoke test
362*4543ef51SXin LI unsigned char uc = 0;
363*4543ef51SXin LI for (; uc < (unsigned char)-1; uc++) {
364*4543ef51SXin LI set_subtest("char %u", (unsigned)uc);
365*4543ef51SXin LI const char *const printable = unsignedCharToPrintable(uc);
366*4543ef51SXin LI if (printable == NULL)
367*4543ef51SXin LI fail("unsignedCharToPrintable returned NULL");
368*4543ef51SXin LI else if (strlen(printable) < (size_t)1)
369*4543ef51SXin LI fail("unsignedCharToPrintable returned empty string");
370*4543ef51SXin LI }
371*4543ef51SXin LI
372*4543ef51SXin LI // Two concrete samples
373*4543ef51SXin LI set_subtest("char 'A'");
374*4543ef51SXin LI if (strcmp(unsignedCharToPrintable('A'), "A") != 0)
375*4543ef51SXin LI fail("unsignedCharToPrintable result mistaken");
376*4543ef51SXin LI set_subtest("char '\\'");
377*4543ef51SXin LI if (strcmp(unsignedCharToPrintable('\\'), "\\\\") != 0)
378*4543ef51SXin LI fail("unsignedCharToPrintable result mistaken");
379*4543ef51SXin LI }
380*4543ef51SXin LI END_TEST
381*4543ef51SXin LI #endif // XML_GE == 1
382*4543ef51SXin LI
383*4543ef51SXin LI void
make_accounting_test_case(Suite * s)384*4543ef51SXin LI make_accounting_test_case(Suite *s) {
385*4543ef51SXin LI #if XML_GE == 1
386*4543ef51SXin LI TCase *tc_accounting = tcase_create("accounting tests");
387*4543ef51SXin LI
388*4543ef51SXin LI suite_add_tcase(s, tc_accounting);
389*4543ef51SXin LI
390*4543ef51SXin LI tcase_add_test(tc_accounting, test_accounting_precision);
391*4543ef51SXin LI tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api);
392*4543ef51SXin LI tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
393*4543ef51SXin LI #else
394*4543ef51SXin LI UNUSED_P(s);
395*4543ef51SXin LI #endif /* XML_GE == 1 */
396*4543ef51SXin LI }
397