xref: /freebsd/contrib/expat/tests/acc_tests.c (revision 4543ef51)
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=\"&amp;&apos;&gt;&lt;&quot;\" />", 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>&amp;&apos;&gt;&lt;&quot;</e>", NULL, NULL,
79*4543ef51SXin LI        sizeof(XML_Char) * 5 /* number of predefined entities */},
80*4543ef51SXin LI       {"<e>&#65;&#41;</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 \"&#60;!ENTITY nine &#34;123456789&#34;&#62;\">\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 \"&#37;comment;<!--22-->&#37;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 \"&#60;!ENTITY five2 &#34;[&#37;five;][&#37;five;]]]]&#34;&#62;\">\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