upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr-util / test / testxml.c
1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
2  * applicable.
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "apr.h"
18 #include "apr_general.h"
19 #include "apr_xml.h"
20
21 #if APR_HAVE_STDLIB_H
22 #include <stdlib.h>  /* for exit() */
23 #endif
24
25 static const char *progname;
26 static const char *usage = "%s [xmlfile]\nIt will create "
27                            "a dummy XML file if none is supplied";
28 /*
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).
32  */
33
34 #ifdef L_tmpnam
35 static char tname_buf[L_tmpnam];
36 #else
37 static char *tname_buf = NULL;
38 #endif
39
40 static apr_status_t create_dummy_file_error(apr_pool_t *p, apr_file_t **fd)
41 {
42     apr_status_t rv;
43     char *tmpfile;
44     int i;
45     apr_off_t off = 0L;
46     tmpfile = tmpnam(tname_buf);
47
48     if ((tmpfile == NULL) || (*tmpfile == '\0')) {
49         fprintf(stderr, "unable to generate temporary filename\n");
50         if (errno == 0) {
51             errno = ENOENT;
52         }
53         perror("tmpnam");
54         return APR_ENOENT;
55     }
56     rv = apr_file_open(fd, tmpfile, APR_CREATE|APR_TRUNCATE|APR_DELONCLOSE|
57                        APR_READ|APR_WRITE|APR_EXCL, APR_OS_DEFAULT, p);
58
59     if (rv != APR_SUCCESS)
60         return rv;
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)
65         return rv;
66
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)
71             return rv;
72     }
73     rv = apr_file_puts("</mary>\n", *fd);
74     if (rv != APR_SUCCESS)
75         return rv;
76
77     return apr_file_seek(*fd, APR_SET, &off);
78 }
79
80 static apr_status_t create_dummy_file(apr_pool_t *p, apr_file_t **fd)
81 {
82     apr_status_t rv;
83     char *tmpfile;
84     int i;
85     apr_off_t off = 0L;
86     tmpfile = tmpnam(tname_buf);
87
88     if ((tmpfile == NULL) || (*tmpfile == '\0')) {
89         fprintf(stderr, "unable to generate temporary filename\n");
90         if (errno == 0) {
91             errno = ENOENT;
92         }
93         perror("tmpnam");
94         return APR_ENOENT;
95     }
96     rv = apr_file_open(fd, tmpfile, APR_CREATE|APR_TRUNCATE|APR_DELONCLOSE|
97                        APR_READ|APR_WRITE|APR_EXCL, APR_OS_DEFAULT, p);
98
99     if (rv != APR_SUCCESS)
100         return rv;
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)
105         return rv;
106
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)
111             return rv;
112     }
113     rv = apr_file_puts("</mary>\n", *fd);
114     if (rv != APR_SUCCESS)
115         return rv;
116
117     rv = apr_file_seek(*fd, APR_SET, &off);
118     return rv;
119 }
120
121 static void dump_xml(apr_xml_elem *e, int level)
122 {
123     apr_xml_attr *a;
124     apr_xml_elem *ec;
125
126     printf("%d: element %s\n", level, e->name);
127     if (e->attr) {
128         a = e->attr;
129         printf("%d:\tattrs\t", level);
130         while (a) {
131             printf("%s=%s\t", a->name, a->value);
132             a = a->next;
133         }
134         printf("\n");
135     }
136     if (e->first_child) {
137         ec = e->first_child;
138         while (ec) {
139             dump_xml(ec, level + 1);
140             ec = ec->next;
141         }
142     }
143 }
144
145 static void oops(const char *s1, const char *s2, apr_status_t rv)
146 {
147     if (progname)
148         fprintf(stderr, "%s: ", progname);
149     fprintf(stderr, s1, s2);
150     if (rv != APR_SUCCESS) {
151         char buf[120];
152
153         fprintf(stderr, " (%s)", apr_strerror(rv, buf, sizeof buf));
154     }
155     fprintf(stderr, "\n");
156     exit(1);
157 }
158
159 static int test_xml_parser(apr_pool_t *pool, const char *file)
160 {
161     apr_file_t *fd;
162     apr_xml_parser *parser;
163     apr_xml_doc *doc;
164     apr_status_t rv;
165     char errbuf[2000];
166     char errbufXML[2000];
167
168     if (file == NULL) {
169         rv = create_dummy_file(pool, &fd);
170         if (rv != APR_SUCCESS) {
171             oops("cannot create dummy file", "oops", rv);
172         }
173     }
174     else {
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);
178         }
179     }
180
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)));
186         return rv;
187     }
188
189     dump_xml(doc->root, 0);
190
191     rv = apr_file_close(fd);
192
193     if (file == NULL) {
194         rv = create_dummy_file_error(pool, &fd);
195         if (rv != APR_SUCCESS) {
196             oops("cannot create error dummy file", "oops", rv);
197         }
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 */
205         }
206         else {
207             fprintf(stderr, "Expected an error, but didn't get one ;( ");
208             return APR_EGENERAL;
209         }
210     }
211     return rv;
212 }
213
214 static void test_billion_laughs(apr_pool_t *pool)
215 {
216     apr_file_t *fd;
217     apr_xml_parser *parser;
218     apr_xml_doc *doc;
219     apr_status_t rv;
220     char errbuf[2000];
221
222     rv = apr_file_open(&fd, "data/billion-laughs.xml", 
223                        APR_READ, 0, pool);
224     if (rv != APR_SUCCESS) {
225         fprintf(stderr, "APR Error %s\n",
226                 apr_strerror(rv, errbuf, sizeof(errbuf)));
227     }
228
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);
232
233     apr_file_close(fd);
234 }
235
236 static void test_CVE_2009_3720_alpha(apr_pool_t *pool)
237 {
238     apr_xml_parser *xp;
239     apr_xml_doc *doc;
240     apr_status_t rv;
241
242     xp = apr_xml_parser_create(pool);
243     
244     rv = apr_xml_parser_feed(xp, "\0\r\n", 3);
245     if (rv == APR_SUCCESS)
246         apr_xml_parser_done(xp, &doc);
247 }
248
249 static void test_CVE_2009_3720_beta(apr_pool_t *pool)
250 {
251     apr_xml_parser *xp;
252     apr_xml_doc *doc;
253     apr_status_t rv;
254
255     xp = apr_xml_parser_create(pool);
256     
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);
260 }
261
262 int main(int argc, const char *const * argv)
263 {
264     apr_pool_t *pool;
265     apr_status_t rv;
266
267     (void) apr_initialize();
268     apr_pool_create(&pool, NULL);
269     progname = argv[0];
270     if (argc == 1) {
271         rv = test_xml_parser(pool, NULL);
272     }
273     else {
274         if (argc == 2) {
275             rv = test_xml_parser(pool, argv[1]);
276         }
277         else {
278             oops("usage: %s", usage, 0);
279         }
280     }
281     test_billion_laughs(pool);
282     test_CVE_2009_3720_alpha(pool);
283     test_CVE_2009_3720_beta(pool);
284     apr_pool_destroy(pool);
285     apr_terminate();
286     return rv;
287 }