diff -u subversion-1.5.1dfsg1/debian/changelog subversion-1.5.1dfsg1/debian/changelog --- subversion-1.5.1dfsg1/debian/changelog +++ subversion-1.5.1dfsg1/debian/changelog @@ -1,3 +1,9 @@ +subversion (1.5.1dfsg1-1ubuntu2.1~hardy1) hardy-backports; urgency=low + + * Backported security fix from intrepid (LP: #411849) + + -- Arnd Hannemann Mon, 17 Aug 2009 18:48:17 +0200 + subversion (1.5.1dfsg1-1ubuntu2~hardy2) hardy-backports; urgency=low * Switched libneon-gnutls-dev to libneon-dev to diff -u subversion-1.5.1dfsg1/debian/patches/series subversion-1.5.1dfsg1/debian/patches/series --- subversion-1.5.1dfsg1/debian/patches/series +++ subversion-1.5.1dfsg1/debian/patches/series @@ -23,0 +24 @@ +fix-binary-diff-security only in patch2: unchanged: --- subversion-1.5.1dfsg1.orig/debian/patches/fix-binary-diff-security +++ subversion-1.5.1dfsg1/debian/patches/fix-binary-diff-security @@ -0,0 +1,212 @@ +Description: backported upstream fixes for binary diff vulnerability. (CVE-2009-2411) + +Index: subversion-1.5.1dfsg1/subversion/libsvn_delta/svndiff.c +=================================================================== +--- subversion-1.5.1dfsg1.orig/subversion/libsvn_delta/svndiff.c 2009-08-06 09:01:25.000000000 -0700 ++++ subversion-1.5.1dfsg1/subversion/libsvn_delta/svndiff.c 2009-08-06 09:01:39.000000000 -0700 +@@ -55,10 +55,23 @@ + apr_pool_t *pool; + }; + ++/* This is at least as big as the largest size of an integer that ++ encode_int can generate; it is sufficient for creating buffers for ++ it to write into. This assumes that integers are at most 64 bits, ++ and so 10 bytes (with 7 bits of information each) are sufficient to ++ represent them. */ ++#define MAX_ENCODED_INT_LEN 10 ++/* This is at least as big as the largest size for a single instruction. */ ++#define MAX_INSTRUCTION_LEN (2*MAX_ENCODED_INT_LEN+1) ++/* This is at least as big as the largest possible instructions ++ section: in theory, the instructions could be SVN_DELTA_WINDOW_SIZE ++ 1-byte copy-from-source instructions (though this is very unlikely). */ ++#define MAX_INSTRUCTION_SECTION_LEN (SVN_DELTA_WINDOW_SIZE*MAX_INSTRUCTION_LEN) + + /* Encode VAL into the buffer P using the variable-length svndiff + integer format. Return the incremented value of P after the +- encoded bytes have been written. ++ encoded bytes have been written. P must point to a buffer of size ++ at least MAX_ENCODED_INT_LEN. + + This encoding uses the high bit of each byte as a continuation bit + and the other seven bits as data bits. High-order data bits are +@@ -91,6 +104,8 @@ + n++; + } + ++ assert(n <= MAX_ENCODED_INT_LEN); ++ + /* Encode the remaining bytes; n is always the number of bytes + coming after the one we're encoding. */ + while (--n >= 0) +@@ -107,7 +122,7 @@ + static void + append_encoded_int(svn_stringbuf_t *header, svn_filesize_t val) + { +- char buf[128], *p; ++ char buf[MAX_ENCODED_INT_LEN], *p; + + p = encode_int(buf, val); + svn_stringbuf_appendbytes(header, buf, p - buf); +@@ -163,7 +178,7 @@ + svn_stringbuf_t *i1 = svn_stringbuf_create("", pool); + svn_stringbuf_t *header = svn_stringbuf_create("", pool); + const svn_string_t *newdata; +- char ibuf[128], *ip; ++ char ibuf[MAX_INSTRUCTION_LEN], *ip; + const svn_txdelta_op_t *op; + apr_size_t len; + +@@ -341,6 +356,8 @@ + const unsigned char *p, + const unsigned char *end) + { ++ if (p + MAX_ENCODED_INT_LEN < end) ++ end = p + MAX_ENCODED_INT_LEN; + /* Decode bytes until we're done. */ + *val = 0; + while (p < end) +@@ -360,6 +377,8 @@ + const unsigned char *p, + const unsigned char *end) + { ++ if (p + MAX_ENCODED_INT_LEN < end) ++ end = p + MAX_ENCODED_INT_LEN; + /* Decode bytes until we're done. */ + *val = 0; + while (p < end) +@@ -377,7 +396,7 @@ + data is not compressed. */ + + static svn_error_t * +-zlib_decode(svn_stringbuf_t *in, svn_stringbuf_t *out) ++zlib_decode(svn_stringbuf_t *in, svn_stringbuf_t *out, apr_size_t limit) + { + apr_size_t len; + char *oldplace = in->data; +@@ -385,6 +404,13 @@ + /* First thing in the string is the original length. */ + in->data = (char *)decode_size(&len, (unsigned char *)in->data, + (unsigned char *)in->data+in->len); ++ if (in->data == NULL) ++ return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL, ++ _("Decompression of svndiff data failed: no size")); ++ if (len > limit) ++ return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL, ++ _("Decompression of svndiff data failed: " ++ "size too large")); + /* We need to subtract the size of the encoded original length off the + * still remaining input length. */ + in->len -= (in->data - oldplace); +@@ -482,10 +508,10 @@ + return svn_error_createf + (SVN_ERR_SVNDIFF_INVALID_OPS, NULL, + _("Invalid diff stream: insn %d cannot be decoded"), n); +- else if (op.length <= 0) ++ else if (op.length == 0) + return svn_error_createf + (SVN_ERR_SVNDIFF_INVALID_OPS, NULL, +- _("Invalid diff stream: insn %d has non-positive length"), n); ++ _("Invalid diff stream: insn %d has length zero"), n); + else if (op.length > tview_len - tpos) + return svn_error_createf + (SVN_ERR_SVNDIFF_INVALID_OPS, NULL, +@@ -494,7 +520,8 @@ + switch (op.action_code) + { + case svn_txdelta_source: +- if (op.length > sview_len - op.offset) ++ if (op.length > sview_len - op.offset || ++ op.offset > sview_len) + return svn_error_createf + (SVN_ERR_SVNDIFF_INVALID_OPS, NULL, + _("Invalid diff stream: " +@@ -560,11 +587,11 @@ + + instin = svn_stringbuf_ncreate((const char *)data, insend - data, pool); + instout = svn_stringbuf_create("", pool); +- SVN_ERR(zlib_decode(instin, instout)); ++ SVN_ERR(zlib_decode(instin, instout, MAX_INSTRUCTION_SECTION_LEN)); + + ndin = svn_stringbuf_ncreate((const char *)insend, newlen, pool); + ndout = svn_stringbuf_create("", pool); +- SVN_ERR(zlib_decode(ndin, ndout)); ++ SVN_ERR(zlib_decode(ndin, ndout, SVN_DELTA_WINDOW_SIZE)); + + newlen = ndout->len; + data = (unsigned char *)instout->data; +@@ -680,6 +707,14 @@ + if (p == NULL) + return SVN_NO_ERROR; + ++ if (tview_len > SVN_DELTA_WINDOW_SIZE || ++ sview_len > SVN_DELTA_WINDOW_SIZE || ++ /* for svndiff1, newlen includes the original length */ ++ newlen > SVN_DELTA_WINDOW_SIZE + MAX_ENCODED_INT_LEN || ++ inslen > MAX_INSTRUCTION_SECTION_LEN) ++ return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, ++ _("Svndiff contains a too-large window")); ++ + /* Check for integer overflow. */ + if (sview_offset < 0 || inslen + newlen < inslen + || sview_len + tview_len < sview_len +@@ -836,6 +871,14 @@ + SVN_ERR(read_one_size(inslen, stream)); + SVN_ERR(read_one_size(newlen, stream)); + ++ if (*tview_len > SVN_DELTA_WINDOW_SIZE || ++ *sview_len > SVN_DELTA_WINDOW_SIZE || ++ /* for svndiff1, newlen includes the original length */ ++ *newlen > SVN_DELTA_WINDOW_SIZE + MAX_ENCODED_INT_LEN || ++ *inslen > MAX_INSTRUCTION_SECTION_LEN) ++ return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, ++ _("Svndiff contains a too-large window")); ++ + /* Check for integer overflow. */ + if (*sview_offset < 0 || *inslen + *newlen < *inslen + || *sview_len + *tview_len < *sview_len +Index: subversion-1.5.1dfsg1/subversion/libsvn_delta/text_delta.c +=================================================================== +--- subversion-1.5.1dfsg1.orig/subversion/libsvn_delta/text_delta.c 2009-08-06 09:01:30.000000000 -0700 ++++ subversion-1.5.1dfsg1/subversion/libsvn_delta/text_delta.c 2009-08-06 09:01:39.000000000 -0700 +@@ -498,7 +498,7 @@ + /* Functions for applying deltas. */ + + /* Ensure that BUF has enough space for VIEW_LEN bytes. */ +-static APR_INLINE void ++static APR_INLINE svn_error_t * + size_buffer(char **buf, apr_size_t *buf_size, + apr_size_t view_len, apr_pool_t *pool) + { +@@ -507,8 +507,13 @@ + *buf_size *= 2; + if (*buf_size < view_len) + *buf_size = view_len; ++ if (APR_ALIGN_DEFAULT(*buf_size) < *buf_size) ++ return svn_error_create(SVN_ERR_SVNDIFF_INVALID_OPS, NULL, ++ "Diff stream resulted in invalid buffer size."); + *buf = apr_palloc(pool, *buf_size); + } ++ ++ return SVN_NO_ERROR; + } + + +@@ -609,7 +614,7 @@ + >= ab->sbuf_offset + ab->sbuf_len))); + + /* Make sure there's enough room in the target buffer. */ +- size_buffer(&ab->tbuf, &ab->tbuf_size, window->tview_len, ab->pool); ++ SVN_ERR(size_buffer(&ab->tbuf, &ab->tbuf_size, window->tview_len, ab->pool)); + + /* Prepare the source buffer for reading from the input stream. */ + if (window->sview_offset != ab->sbuf_offset +@@ -618,7 +623,8 @@ + char *old_sbuf = ab->sbuf; + + /* Make sure there's enough room. */ +- size_buffer(&ab->sbuf, &ab->sbuf_size, window->sview_len, ab->pool); ++ SVN_ERR(size_buffer(&ab->sbuf, &ab->sbuf_size, window->sview_len, ++ ab->pool)); + + /* If the existing view overlaps with the new view, copy the + * overlap to the beginning of the new buffer. */