Skip to content

Commit

Permalink
Imported apr-util-1.3.7
Browse files Browse the repository at this point in the history
Summary: Imported apr-util-1.3.7
Keywords:

Imported apr-util-1.3.7
into Git repository
  • Loading branch information
Chetan Reddy committed Jun 5, 2009
1 parent 791ea8a commit 1691de1
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 28 deletions.
18 changes: 18 additions & 0 deletions CHANGES
@@ -1,6 +1,24 @@
-*- coding: utf-8 -*-
Changes with APR-util 1.3.7

*) SECURITY:
Fix a denial of service attack against the apr_xml_* interface
using the "billion laughs" entity expansion technique.
[Joe Orton]

Changes with APR-util 1.3.6

*) Minor build and bug fixes.

Changes with APR-util 1.3.5

*) SECURITY: CVE-2009-0023 (cve.mitre.org)
Fix underflow in apr_strmatch_precompile.
[Matthew Palmer <mpalmer debian.org>]

*) Fix off by one overflow in apr_brigade_vprintf.
[C. Michael Pilato <cmpilato collab.net>]

*) APR_LDAP_SIZELIMIT should prefer LDAP_DEFAULT_LIMIT/-1 when the
SDK supports it, but in the absence of LDAP_DEFAULT_LIMIT (and
LDAP_NO_LIMIT/0) it is not safe to use a literal -1.
Expand Down
8 changes: 5 additions & 3 deletions STATUS
@@ -1,11 +1,13 @@
APACHE PORTABLE RUNTIME APR-UTIL LIBRARY STATUS: -*- coding: utf-8 -*-
Last modified at [$Date: 2009-01-03 12:59:38 -0500 (Sat, 03 Jan 2009) $]
Last modified at [$Date: 2009-06-03 12:08:37 -0400 (Wed, 03 Jun 2009) $]

Releases:

2.0.0 : in development on trunk/
2.0.0 : EOL - merged into apr/trunk/
1.4.0 : in development on branches/1.4.x/
1.3.5 : in maintenance on branches/1.3.x/
1.3.7 : tagged June 3, 2009
1.3.6 : not released
1.3.5 : not released
1.3.4 : released August 15, 2008
1.3.3 : not released
1.3.2 : released June 23, 2008
Expand Down
3 changes: 0 additions & 3 deletions buckets/apr_brigade.c
Expand Up @@ -689,9 +689,6 @@ APU_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b,
return -1;
}

/* tack on null terminator to remaining string */
*(vd.vbuff.curpos) = '\0';

/* write out what remains in the buffer */
return apr_brigade_write(b, flush, ctx, buf, vd.vbuff.curpos - buf);
}
Expand Down
4 changes: 2 additions & 2 deletions include/apu_version.h
Expand Up @@ -59,14 +59,14 @@
* The Patch Level never includes API changes, simply bug fixes.
* Reset to 0 when upgrading APR_MINOR_VERSION
*/
#define APU_PATCH_VERSION 5
#define APU_PATCH_VERSION 7

/**
* The symbol APU_IS_DEV_VERSION is only defined for internal,
* "development" copies of APU. It is undefined for released versions
* of APU.
*/
#define APU_IS_DEV_VERSION
/* #undef APU_IS_DEV_VERSION */


#if defined(APU_IS_DEV_VERSION) || defined(DOXYGEN)
Expand Down
6 changes: 3 additions & 3 deletions strmatch/apr_strmatch.c
Expand Up @@ -74,7 +74,7 @@ static const char *match_boyer_moore_horspool_nocase(
}
s_tmp--;
}
s_next += shift[apr_tolower(*s_next)];
s_next += shift[(unsigned char)apr_tolower(*s_next)];
}
return NULL;
}
Expand Down Expand Up @@ -103,13 +103,13 @@ APU_DECLARE(const apr_strmatch_pattern *) apr_strmatch_precompile(
if (case_sensitive) {
pattern->compare = match_boyer_moore_horspool;
for (i = 0; i < pattern->length - 1; i++) {
shift[(int)s[i]] = pattern->length - i - 1;
shift[(unsigned char)s[i]] = pattern->length - i - 1;
}
}
else {
pattern->compare = match_boyer_moore_horspool_nocase;
for (i = 0; i < pattern->length - 1; i++) {
shift[apr_tolower(s[i])] = pattern->length - i - 1;
shift[(unsigned char)apr_tolower(s[i])] = pattern->length - i - 1;
}
}
pattern->context = shift;
Expand Down
18 changes: 10 additions & 8 deletions test/Makefile.in
Expand Up @@ -61,17 +61,19 @@ check: $(TESTALL_COMPONENTS) $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE)
progfailed=""; \
for prog in $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE); do \
if test "$$prog" = 'dbd'; then \
for driver in @apu_dbd_tests@; do \
@apr_shlibpath_var@="`echo "../dbd/.libs:../ldap/.libs:$$@apr_shlibpath_var@" | sed -e 's/::*$$//'`" \
./$$prog $$driver; \
status=$$?; \
if test $$status != 0; then \
teststatus=$$status; \
progfailed="$$progfailed '$$prog $$driver'"; \
for driver in none @apu_dbd_tests@; do \
if test "$$driver" != 'none'; then \
@apr_shlibpath_var@="`echo "../dbm/.libs:../dbd/.libs:../ldap/.libs:$$@apr_shlibpath_var@" | sed -e 's/::*$$//'`" \
./$$prog $$driver; \
status=$$?; \
if test $$status != 0; then \
teststatus=$$status; \
progfailed="$$progfailed '$$prog $$driver'"; \
fi; \
fi; \
done; \
else \
@apr_shlibpath_var@="`echo "../dbd/.libs:../ldap/.libs:$$@apr_shlibpath_var@" | sed -e 's/::*$$//'`" \
@apr_shlibpath_var@="`echo "../dbm/.libs:../dbd/.libs:../ldap/.libs:$$@apr_shlibpath_var@" | sed -e 's/::*$$//'`" \
./$$prog; \
status=$$?; \
if test $$status != 0; then \
Expand Down
36 changes: 36 additions & 0 deletions test/data/billion-laughs.xml
@@ -0,0 +1,36 @@
<?xml version="1.0"?>
<!DOCTYPE billion [
<!ELEMENT billion (#PCDATA)>
<!ENTITY laugh0 "ha">
<!ENTITY laugh1 "&laugh0;&laugh0;">
<!ENTITY laugh2 "&laugh1;&laugh1;">
<!ENTITY laugh3 "&laugh2;&laugh2;">
<!ENTITY laugh4 "&laugh3;&laugh3;">
<!ENTITY laugh5 "&laugh4;&laugh4;">
<!ENTITY laugh6 "&laugh5;&laugh5;">
<!ENTITY laugh7 "&laugh6;&laugh6;">
<!ENTITY laugh8 "&laugh7;&laugh7;">
<!ENTITY laugh9 "&laugh8;&laugh8;">
<!ENTITY laugh10 "&laugh9;&laugh9;">
<!ENTITY laugh11 "&laugh10;&laugh10;">
<!ENTITY laugh12 "&laugh11;&laugh11;">
<!ENTITY laugh13 "&laugh12;&laugh12;">
<!ENTITY laugh14 "&laugh13;&laugh13;">
<!ENTITY laugh15 "&laugh14;&laugh14;">
<!ENTITY laugh16 "&laugh15;&laugh15;">
<!ENTITY laugh17 "&laugh16;&laugh16;">
<!ENTITY laugh18 "&laugh17;&laugh17;">
<!ENTITY laugh19 "&laugh18;&laugh18;">
<!ENTITY laugh20 "&laugh19;&laugh19;">
<!ENTITY laugh21 "&laugh20;&laugh20;">
<!ENTITY laugh22 "&laugh21;&laugh21;">
<!ENTITY laugh23 "&laugh22;&laugh22;">
<!ENTITY laugh24 "&laugh23;&laugh23;">
<!ENTITY laugh25 "&laugh24;&laugh24;">
<!ENTITY laugh26 "&laugh25;&laugh25;">
<!ENTITY laugh27 "&laugh26;&laugh26;">
<!ENTITY laugh28 "&laugh27;&laugh27;">
<!ENTITY laugh29 "&laugh28;&laugh28;">
<!ENTITY laugh30 "&laugh29;&laugh29;">
]>
<billion>&laugh30;</billion>
26 changes: 22 additions & 4 deletions test/testxml.c
Expand Up @@ -36,8 +36,7 @@ static apr_status_t create_dummy_file_error(abts_case *tc, apr_pool_t *p,
return rv;

rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<maryx>"
"<had a=\"little\"/><lamb its='fleece "
"was white as snow' />\n", *fd);
"<had a=\"little\"/><lamb/>\n", *fd);
ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

for (i = 0; i < 5000; i++) {
Expand Down Expand Up @@ -75,7 +74,7 @@ static apr_status_t create_dummy_file(abts_case *tc, apr_pool_t *p,

for (i = 0; i < 5000; i++) {
rv = apr_file_puts("<hmm roast=\"lamb\" "
"for=\"dinner\">yummy</hmm>\n", *fd);
"for=\"dinner &lt;&gt;&#x3D;\">yummy</hmm>\n", *fd);
ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
}

Expand Down Expand Up @@ -103,7 +102,7 @@ static void dump_xml(abts_case *tc, apr_xml_elem *e, int level)
a = e->attr;
ABTS_PTR_NOTNULL(tc, a);
ABTS_STR_EQUAL(tc, "for", a->name);
ABTS_STR_EQUAL(tc, "dinner", a->value);
ABTS_STR_EQUAL(tc, "dinner <>=", a->value);
a = a->next;
ABTS_PTR_NOTNULL(tc, a);
ABTS_STR_EQUAL(tc, "roast", a->name);
Expand Down Expand Up @@ -149,11 +148,30 @@ static void test_xml_parser(abts_case *tc, void *data)
ABTS_TRUE(tc, rv != APR_SUCCESS);
}

static void test_billion_laughs(abts_case *tc, void *data)
{
apr_file_t *fd;
apr_xml_parser *parser;
apr_xml_doc *doc;
apr_status_t rv;

rv = apr_file_open(&fd, "data/billion-laughs.xml",
APR_FOPEN_READ, 0, p);
apr_assert_success(tc, "open billion-laughs.xml", rv);

/* Don't test for return value; if it returns, chances are the bug
* is fixed or the machine has insane amounts of RAM. */
apr_xml_parse_file(p, &parser, &doc, fd, 2000);

apr_file_close(fd);
}

abts_suite *testxml(abts_suite *suite)
{
suite = ADD_SUITE(suite);

abts_run_test(suite, test_xml_parser, NULL);
abts_run_test(suite, test_billion_laughs, NULL);

return suite;
}
32 changes: 32 additions & 0 deletions xml/apr_xml.c
Expand Up @@ -347,6 +347,25 @@ static apr_status_t cleanup_parser(void *ctx)
return APR_SUCCESS;
}

#if XML_MAJOR_VERSION > 1
/* Stop the parser if an entity declaration is hit. */
static void entity_declaration(void *userData, const XML_Char *entityName,
int is_parameter_entity, const XML_Char *value,
int value_length, const XML_Char *base,
const XML_Char *systemId, const XML_Char *publicId,
const XML_Char *notationName)
{
apr_xml_parser *parser = userData;

XML_StopParser(parser->xp, XML_FALSE);
}
#else
/* A noop default_handler. */
static void default_handler(void *userData, const XML_Char *s, int len)
{
}
#endif

APU_DECLARE(apr_xml_parser *) apr_xml_parser_create(apr_pool_t *pool)
{
apr_xml_parser *parser = apr_pcalloc(pool, sizeof(*parser));
Expand All @@ -372,6 +391,19 @@ APU_DECLARE(apr_xml_parser *) apr_xml_parser_create(apr_pool_t *pool)
XML_SetElementHandler(parser->xp, start_handler, end_handler);
XML_SetCharacterDataHandler(parser->xp, cdata_handler);

/* Prevent the "billion laughs" attack against expat by disabling
* internal entity expansion. With 2.x, forcibly stop the parser
* if an entity is declared - this is safer and a more obvious
* failure mode. With older versions, installing a noop
* DefaultHandler means that internal entities will be expanded as
* the empty string, which is also sufficient to prevent the
* attack. */
#if XML_MAJOR_VERSION > 1
XML_SetEntityDeclHandler(parser->xp, entity_declaration);
#else
XML_SetDefaultHandler(parser->xp, default_handler);
#endif

return parser;
}

Expand Down
5 changes: 0 additions & 5 deletions xml/expat/Makefile.in
Expand Up @@ -52,8 +52,6 @@ oldincludedir = /usr/include
top_builddir = .


AUTOCONF = autoconf

INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
Expand Down Expand Up @@ -98,9 +96,6 @@ config.status: configure
$(SHELL) configure ; \
fi

configure: configure.in
$(AUTOCONF)

config.h: config.h.in config.status
CONFIG_FILES= CONFIG_HEADERS=$(CONFIG_HEADERS) \
$(SHELL) ./config.status
Expand Down

0 comments on commit 1691de1

Please sign in to comment.