1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "apr_general.h"
22 #include <stdlib.h> /* for exit() */
25 static const char *progname;
26 static const char *usage = "%s [xmlfile]\nIt will create "
27 "a dummy XML file if none is supplied";
29 * If our platform knows about the tmpnam() external buffer size, create
30 * a buffer to pass in. This is needed in a threaded environment, or
31 * one that thinks it is (like HP-UX).
35 static char tname_buf[L_tmpnam];
37 static char *tname_buf = NULL;
40 static apr_status_t create_dummy_file_error(apr_pool_t *p, apr_file_t **fd)
46 tmpfile = tmpnam(tname_buf);
48 if ((tmpfile == NULL) || (*tmpfile == '\0')) {
49 fprintf(stderr, "unable to generate temporary filename\n");
56 rv = apr_file_open(fd, tmpfile, APR_CREATE|APR_TRUNCATE|APR_DELONCLOSE|
57 APR_READ|APR_WRITE|APR_EXCL, APR_OS_DEFAULT, p);
59 if (rv != APR_SUCCESS)
61 rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<maryx>"
62 "<had a=\"little\"/><lamb its='fleece "
63 "was white as snow' />\n", *fd);
64 if (rv != APR_SUCCESS)
67 for (i = 0; i < 5000; i++) {
68 rv = apr_file_puts("<hmm roast=\"lamb\" "
69 "for=\"dinner\">yummy</hmm>\n", *fd);
70 if (rv != APR_SUCCESS)
73 rv = apr_file_puts("</mary>\n", *fd);
74 if (rv != APR_SUCCESS)
77 return apr_file_seek(*fd, APR_SET, &off);
80 static apr_status_t create_dummy_file(apr_pool_t *p, apr_file_t **fd)
86 tmpfile = tmpnam(tname_buf);
88 if ((tmpfile == NULL) || (*tmpfile == '\0')) {
89 fprintf(stderr, "unable to generate temporary filename\n");
96 rv = apr_file_open(fd, tmpfile, APR_CREATE|APR_TRUNCATE|APR_DELONCLOSE|
97 APR_READ|APR_WRITE|APR_EXCL, APR_OS_DEFAULT, p);
99 if (rv != APR_SUCCESS)
101 rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<mary>"
102 "<had a=\"little\"/><lamb its='fleece "
103 "was white as snow' />\n", *fd);
104 if (rv != APR_SUCCESS)
107 for (i = 0; i < 5000; i++) {
108 rv = apr_file_puts("<hmm roast=\"lamb\" "
109 "for=\"dinner\">yummy</hmm>\n", *fd);
110 if (rv != APR_SUCCESS)
113 rv = apr_file_puts("</mary>\n", *fd);
114 if (rv != APR_SUCCESS)
117 rv = apr_file_seek(*fd, APR_SET, &off);
121 static void dump_xml(apr_xml_elem *e, int level)
126 printf("%d: element %s\n", level, e->name);
129 printf("%d:\tattrs\t", level);
131 printf("%s=%s\t", a->name, a->value);
136 if (e->first_child) {
139 dump_xml(ec, level + 1);
145 static void oops(const char *s1, const char *s2, apr_status_t rv)
148 fprintf(stderr, "%s: ", progname);
149 fprintf(stderr, s1, s2);
150 if (rv != APR_SUCCESS) {
153 fprintf(stderr, " (%s)", apr_strerror(rv, buf, sizeof buf));
155 fprintf(stderr, "\n");
159 static int test_xml_parser(apr_pool_t *pool, const char *file)
162 apr_xml_parser *parser;
166 char errbufXML[2000];
169 rv = create_dummy_file(pool, &fd);
170 if (rv != APR_SUCCESS) {
171 oops("cannot create dummy file", "oops", rv);
175 rv = apr_file_open(&fd, file, APR_READ, APR_OS_DEFAULT, pool);
176 if (rv != APR_SUCCESS) {
177 oops("cannot open: %s", file, rv);
181 rv = apr_xml_parse_file(pool, &parser, &doc, fd, 2000);
182 if (rv != APR_SUCCESS) {
183 fprintf(stderr, "APR Error %s\nXML Error: %s\n",
184 apr_strerror(rv, errbuf, sizeof(errbuf)),
185 apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML)));
189 dump_xml(doc->root, 0);
191 rv = apr_file_close(fd);
194 rv = create_dummy_file_error(pool, &fd);
195 if (rv != APR_SUCCESS) {
196 oops("cannot create error dummy file", "oops", rv);
198 rv = apr_xml_parse_file(pool, &parser, &doc, fd, 2000);
199 if (rv != APR_SUCCESS) {
200 fprintf(stdout, "APR Error %s\nXML Error: %s "
201 "(EXPECTED) This is good.\n",
202 apr_strerror(rv, errbuf, sizeof(errbuf)),
203 apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML)));
204 rv = APR_SUCCESS; /* reset the return code, as the test is supposed to get this error */
207 fprintf(stderr, "Expected an error, but didn't get one ;( ");
214 static void test_billion_laughs(apr_pool_t *pool)
217 apr_xml_parser *parser;
222 rv = apr_file_open(&fd, "data/billion-laughs.xml",
224 if (rv != APR_SUCCESS) {
225 fprintf(stderr, "APR Error %s\n",
226 apr_strerror(rv, errbuf, sizeof(errbuf)));
229 /* Don't test for return value; if it returns, chances are the bug
230 * is fixed or the machine has insane amounts of RAM. */
231 apr_xml_parse_file(pool, &parser, &doc, fd, 2000);
236 static void test_CVE_2009_3720_alpha(apr_pool_t *pool)
242 xp = apr_xml_parser_create(pool);
244 rv = apr_xml_parser_feed(xp, "\0\r\n", 3);
245 if (rv == APR_SUCCESS)
246 apr_xml_parser_done(xp, &doc);
249 static void test_CVE_2009_3720_beta(apr_pool_t *pool)
255 xp = apr_xml_parser_create(pool);
257 rv = apr_xml_parser_feed(xp, "<?xml version\xc2\x85='1.0'?>\r\n", 25);
258 if (rv == APR_SUCCESS)
259 apr_xml_parser_done(xp, &doc);
262 int main(int argc, const char *const * argv)
267 (void) apr_initialize();
268 apr_pool_create(&pool, NULL);
271 rv = test_xml_parser(pool, NULL);
275 rv = test_xml_parser(pool, argv[1]);
278 oops("usage: %s", usage, 0);
281 test_billion_laughs(pool);
282 test_CVE_2009_3720_alpha(pool);
283 test_CVE_2009_3720_beta(pool);
284 apr_pool_destroy(pool);