1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter#include "apr.h" 18251876Speter#include "apr_general.h" 19251876Speter#include "apr_xml.h" 20251876Speter#include "abts.h" 21251876Speter#include "testutil.h" 22251876Speter 23251876Speterstatic apr_status_t create_dummy_file_error(abts_case *tc, apr_pool_t *p, 24251876Speter apr_file_t **fd) 25251876Speter{ 26251876Speter int i; 27251876Speter apr_status_t rv; 28251876Speter apr_off_t off = 0L; 29251876Speter char template[] = "data/testxmldummyerrorXXXXXX"; 30251876Speter 31251876Speter rv = apr_file_mktemp(fd, template, APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE | APR_FOPEN_DELONCLOSE | 32251876Speter APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_EXCL, p); 33251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 34251876Speter 35251876Speter if (rv != APR_SUCCESS) 36251876Speter return rv; 37251876Speter 38251876Speter rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<maryx>" 39251876Speter "<had a=\"little\"/><lamb/>\n", *fd); 40251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 41251876Speter 42251876Speter for (i = 0; i < 5000; i++) { 43251876Speter rv = apr_file_puts("<hmm roast=\"lamb\" " 44251876Speter "for=\"dinner\">yummy</hmm>\n", *fd); 45251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 46251876Speter } 47251876Speter 48251876Speter rv = apr_file_puts("</mary>\n", *fd); 49251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 50251876Speter 51251876Speter rv = apr_file_seek(*fd, APR_SET, &off); 52251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 53251876Speter 54251876Speter return rv; 55251876Speter} 56251876Speter 57251876Speterstatic apr_status_t create_dummy_file(abts_case *tc, apr_pool_t *p, 58251876Speter apr_file_t **fd) 59251876Speter{ 60251876Speter int i; 61251876Speter apr_status_t rv; 62251876Speter apr_off_t off = 0L; 63251876Speter char template[] = "data/testxmldummyXXXXXX"; 64251876Speter 65251876Speter rv = apr_file_mktemp(fd, template, APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE | APR_FOPEN_DELONCLOSE | 66251876Speter APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_EXCL, p); 67251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 68251876Speter 69251876Speter if (rv != APR_SUCCESS) 70251876Speter return rv; 71251876Speter 72251876Speter rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<mary>\n", *fd); 73251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 74251876Speter 75251876Speter for (i = 0; i < 5000; i++) { 76251876Speter rv = apr_file_puts("<hmm roast=\"lamb\" " 77251876Speter "for=\"dinner <>=\">yummy</hmm>\n", *fd); 78251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 79251876Speter } 80251876Speter 81251876Speter rv = apr_file_puts("</mary>\n", *fd); 82251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 83251876Speter 84251876Speter rv = apr_file_seek(*fd, APR_SET, &off); 85251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 86251876Speter 87251876Speter return rv; 88251876Speter} 89251876Speter 90251876Speterstatic void dump_xml(abts_case *tc, apr_xml_elem *e, int level) 91251876Speter{ 92251876Speter apr_xml_attr *a; 93251876Speter apr_xml_elem *ec; 94251876Speter 95251876Speter if (level == 0) { 96251876Speter ABTS_STR_EQUAL(tc, "mary", e->name); 97251876Speter } else { 98251876Speter ABTS_STR_EQUAL(tc, "hmm", e->name); 99251876Speter } 100251876Speter 101251876Speter if (e->attr) { 102251876Speter a = e->attr; 103251876Speter ABTS_PTR_NOTNULL(tc, a); 104251876Speter ABTS_STR_EQUAL(tc, "for", a->name); 105251876Speter ABTS_STR_EQUAL(tc, "dinner <>=", a->value); 106251876Speter a = a->next; 107251876Speter ABTS_PTR_NOTNULL(tc, a); 108251876Speter ABTS_STR_EQUAL(tc, "roast", a->name); 109251876Speter ABTS_STR_EQUAL(tc, "lamb", a->value); 110251876Speter } 111251876Speter if (e->first_child) { 112251876Speter ec = e->first_child; 113251876Speter while (ec) { 114251876Speter dump_xml(tc, ec, level + 1); 115251876Speter ec = ec->next; 116251876Speter } 117251876Speter } 118251876Speter} 119251876Speter 120251876Speterstatic void test_xml_parser(abts_case *tc, void *data) 121251876Speter{ 122251876Speter apr_file_t *fd; 123251876Speter apr_xml_parser *parser; 124251876Speter apr_xml_doc *doc; 125251876Speter apr_status_t rv; 126251876Speter 127251876Speter rv = create_dummy_file(tc, p, &fd); 128251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 129251876Speter 130251876Speter if (rv != APR_SUCCESS) 131251876Speter return; 132251876Speter 133251876Speter rv = apr_xml_parse_file(p, &parser, &doc, fd, 2000); 134251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 135251876Speter 136251876Speter dump_xml(tc, doc->root, 0); 137251876Speter 138251876Speter rv = apr_file_close(fd); 139251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 140251876Speter 141251876Speter rv = create_dummy_file_error(tc, p, &fd); 142251876Speter ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); 143251876Speter 144251876Speter if (rv != APR_SUCCESS) 145251876Speter return; 146251876Speter 147251876Speter rv = apr_xml_parse_file(p, &parser, &doc, fd, 2000); 148251876Speter ABTS_TRUE(tc, rv != APR_SUCCESS); 149251876Speter} 150251876Speter 151251876Speterstatic void test_billion_laughs(abts_case *tc, void *data) 152251876Speter{ 153251876Speter apr_file_t *fd; 154251876Speter apr_xml_parser *parser; 155251876Speter apr_xml_doc *doc; 156251876Speter apr_status_t rv; 157251876Speter 158251876Speter rv = apr_file_open(&fd, "data/billion-laughs.xml", 159251876Speter APR_FOPEN_READ, 0, p); 160251876Speter apr_assert_success(tc, "open billion-laughs.xml", rv); 161251876Speter 162251876Speter /* Don't test for return value; if it returns, chances are the bug 163251876Speter * is fixed or the machine has insane amounts of RAM. */ 164251876Speter apr_xml_parse_file(p, &parser, &doc, fd, 2000); 165251876Speter 166251876Speter apr_file_close(fd); 167251876Speter} 168251876Speter 169251876Speterstatic void test_CVE_2009_3720_alpha(abts_case *tc, void *data) 170251876Speter{ 171251876Speter apr_xml_parser *xp; 172251876Speter apr_xml_doc *doc; 173251876Speter apr_status_t rv; 174251876Speter 175251876Speter xp = apr_xml_parser_create(p); 176251876Speter 177251876Speter rv = apr_xml_parser_feed(xp, "\0\r\n", 3); 178251876Speter if (rv == APR_SUCCESS) 179251876Speter apr_xml_parser_done(xp, &doc); 180251876Speter} 181251876Speter 182251876Speterstatic void test_CVE_2009_3720_beta(abts_case *tc, void *data) 183251876Speter{ 184251876Speter apr_xml_parser *xp; 185251876Speter apr_xml_doc *doc; 186251876Speter apr_status_t rv; 187251876Speter 188251876Speter xp = apr_xml_parser_create(p); 189251876Speter 190251876Speter rv = apr_xml_parser_feed(xp, "<?xml version\xc2\x85='1.0'?>\r\n", 25); 191251876Speter if (rv == APR_SUCCESS) 192251876Speter apr_xml_parser_done(xp, &doc); 193251876Speter} 194251876Speter 195251876Speterabts_suite *testxml(abts_suite *suite) 196251876Speter{ 197251876Speter suite = ADD_SUITE(suite); 198251876Speter 199251876Speter abts_run_test(suite, test_xml_parser, NULL); 200251876Speter abts_run_test(suite, test_billion_laughs, NULL); 201251876Speter abts_run_test(suite, test_CVE_2009_3720_alpha, NULL); 202251876Speter abts_run_test(suite, test_CVE_2009_3720_beta, NULL); 203251876Speter 204251876Speter return suite; 205251876Speter} 206