CVE-2009-0847 (1.6.x) asn1buf_imbed incorrect length validatin
authorTom Yu <tlyu@mit.edu>
Wed, 8 Apr 2009 01:22:57 +0000 (01:22 +0000)
committerTom Yu <tlyu@mit.edu>
Wed, 8 Apr 2009 01:22:57 +0000 (01:22 +0000)
pull up rxxxx from trunk

asn1buf_imbed() can perform pointer arithmetic that causes the "bound"
pointer of the subbuffer to be less than the "next" pointer.  This can
lead to malloc() failure or crash.

In asn1buf_imbed(), check the length before doing arithmetic to set
subbuf->bound.  In asn1buf_remove_octetstring() and
asn1buf_remove_charstring(), check for invalid buffer pointers before
executing an unsigned length check against a (casted to size_t)
negative number.

ticket: 6447
tags: pullup
target_version: 1.6.4
version_fixed: 1.6.4

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@22180 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/asn.1/asn1buf.c

index 8baac24240496cfa07f045d135e9ffe854d24954..587cccc21fb7683a760bf610408d5b7d8d02e466 100644 (file)
@@ -78,11 +78,11 @@ asn1_error_code asn1buf_wrap_data(asn1buf *buf, const krb5_data *code)
 
 asn1_error_code asn1buf_imbed(asn1buf *subbuf, const asn1buf *buf, const unsigned int length, const int indef)
 {
+  if (buf->next > buf->bound + 1) return ASN1_OVERRUN;
   subbuf->base = subbuf->next = buf->next;
   if (!indef) {
+      if (length > (size_t)(buf->bound + 1 - buf->next)) return ASN1_OVERRUN;
       subbuf->bound = subbuf->base + length - 1;
-      if (subbuf->bound > buf->bound)
-         return ASN1_OVERRUN;
   } else /* constructed indefinite */
       subbuf->bound = buf->bound;
   return 0;
@@ -200,6 +200,7 @@ asn1_error_code asn1buf_remove_octetstring(asn1buf *buf, const unsigned int len,
 {
   int i;
 
+  if (buf->next > buf->bound + 1) return ASN1_OVERRUN;
   if (len > buf->bound + 1 - buf->next) return ASN1_OVERRUN;
   if (len == 0) {
       *s = 0;
@@ -218,6 +219,7 @@ asn1_error_code asn1buf_remove_charstring(asn1buf *buf, const unsigned int len,
 {
   int i;
 
+  if (buf->next > buf->bound + 1) return ASN1_OVERRUN;
   if (len > buf->bound + 1 - buf->next) return ASN1_OVERRUN;
   if (len == 0) {
       *s = 0;