Hello,

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-2807

The diff below addresses multiple integer overflows in
libxml2 on 64-bit platforms.
Build fine on i386 but i can't get my hands on any
64-bit build machine. So please test, comment, commit.

The patch has been derived from the following Patchset:

http://git.gnome.org/browse/libxml2/commit/?id=459eeb9dc752d5185f57ff6b135027f11981a626
http://git.gnome.org/browse/libxml2/commit/?id=4f9fdc709c4861c390cd84e2ed1fd878b3442e28


Index: Makefile
===================================================================
RCS file: /cvs/ports/textproc/libxml/Makefile,v
retrieving revision 1.145
diff -u -p -r1.145 Makefile
--- Makefile    5 Aug 2012 00:16:50 -0000       1.145
+++ Makefile    9 Aug 2012 08:14:33 -0000
@@ -6,7 +6,7 @@ COMMENT-python=         Python bindings for lib
 VERSION=               2.7.8
 DISTNAME=              libxml2-${VERSION}
 PKGNAME-main=          libxml-${VERSION}
-REVISION-main =                6
+REVISION-main =                7
 REVISION-python =      3
 PKGNAME-python=                py-libxml-${VERSION}
 SHARED_LIBS=           xml2    13.0
Index: patches/patch-entities_c
===================================================================
RCS file: patches/patch-entities_c
diff -N patches/patch-entities_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-entities_c    9 Aug 2012 08:14:33 -0000
@@ -0,0 +1,94 @@
+$OpenBSD$
+
+From 4f9fdc709c4861c390cd84e2ed1fd878b3442e28 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veill...@redhat.com>
+Date: Wed, 18 Jul 2012 03:38:17 +0000
+Subject: Fix entities local buffers size problems
+
+--- entities.c.orig    Tue Oct 12 08:25:32 2010
++++ entities.c Thu Aug  9 09:19:08 2012
+@@ -528,13 +528,13 @@ xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
+  * Macro used to grow the current buffer.
+  */
+ #define growBufferReentrant() {                                               
\
+-    buffer_size *= 2;                                                 \
+-    buffer = (xmlChar *)                                              \
+-              xmlRealloc(buffer, buffer_size * sizeof(xmlChar));      \
+-    if (buffer == NULL) {                                             \
+-        xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");\
+-      return(NULL);                                                   \
+-    }                                                                 \
++    xmlChar *tmp;                                                       \
++    size_t new_size = buffer_size *= 2;                                 \
++    if (new_size < buffer_size) goto mem_error;                         \
++    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                   \
++    if (tmp == NULL) goto mem_error;                                    \
++    buffer = tmp;                                                     \
++    buffer_size = new_size;                                           \
+ }
+ 
+ 
+@@ -555,7 +555,7 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlCha
+     const xmlChar *cur = input;
+     xmlChar *buffer = NULL;
+     xmlChar *out = NULL;
+-    int buffer_size = 0;
++    size_t buffer_size = 0;
+     int html = 0;
+ 
+     if (input == NULL) return(NULL);
+@@ -574,8 +574,8 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlCha
+     out = buffer;
+ 
+     while (*cur != '\0') {
+-        if (out - buffer > buffer_size - 100) {
+-          int indx = out - buffer;
++        size_t indx = out - buffer;
++        if (indx + 100 > buffer_size) {
+ 
+           growBufferReentrant();
+           out = &buffer[indx];
+@@ -692,6 +692,11 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlCha
+     }
+     *out = 0;
+     return(buffer);
++
++mem_error:
++    xmlEntitiesErrMemory("xmlEncodeEntitiesReentrant: realloc failed");
++    xmlFree(buffer);
++    return(NULL);
+ }
+ 
+ /**
+@@ -709,7 +714,7 @@ xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, 
+     const xmlChar *cur = input;
+     xmlChar *buffer = NULL;
+     xmlChar *out = NULL;
+-    int buffer_size = 0;
++    size_t buffer_size = 0;
+     if (input == NULL) return(NULL);
+ 
+     /*
+@@ -724,8 +729,8 @@ xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, 
+     out = buffer;
+ 
+     while (*cur != '\0') {
+-        if (out - buffer > buffer_size - 10) {
+-          int indx = out - buffer;
++        size_t indx = out - buffer;
++        if (indx + 10 > buffer_size) {
+ 
+           growBufferReentrant();
+           out = &buffer[indx];
+@@ -774,6 +779,11 @@ xmlEncodeSpecialChars(xmlDocPtr doc ATTRIBUTE_UNUSED, 
+     }
+     *out = 0;
+     return(buffer);
++
++mem_error:
++    xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
++    xmlFree(buffer);
++    return(NULL);
+ }
+ 
+ /**
Index: patches/patch-parser_c
===================================================================
RCS file: /cvs/ports/textproc/libxml/patches/patch-parser_c,v
retrieving revision 1.5
diff -u -p -r1.5 patch-parser_c
--- patches/patch-parser_c      23 Jan 2012 10:17:49 -0000      1.5
+++ patches/patch-parser_c      9 Aug 2012 08:14:33 -0000
@@ -1,5 +1,10 @@
 $OpenBSD: patch-parser_c,v 1.5 2012/01/23 10:17:49 ajacoutot Exp $
 
+From 459eeb9dc752d5185f57ff6b135027f11981a626 Mon Sep 17 00:00:00 2001
+From: Daniel Veillard <veill...@redhat.com>
+Date: Tue, 17 Jul 2012 08:19:17 +0000
+Subject: Fix parser local buffers size problems
+
 From 5bd3c061823a8499b27422aee04ea20aae24f03e Mon Sep 17 00:00:00 2001
 From: Daniel Veillard <veill...@redhat.com>
 Date: Fri, 16 Dec 2011 10:53:35 +0000
@@ -10,54 +15,253 @@ From: Chris Evans <scarybea...@gmail.com
 Date: Wed, 14 Dec 2011 08:18:25 +0000
 Subject: Make sure the parser returns when getting a Stop order
 
---- parser.c.orig      Mon Jan 23 08:11:49 2012
-+++ parser.c   Mon Jan 23 08:11:54 2012
-@@ -4949,7 +4949,8 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
-                   (ctxt->sax->processingInstruction != NULL))
-                   ctxt->sax->processingInstruction(ctxt->userData,
-                                                    target, NULL);
--              ctxt->instate = state;
-+              if (ctxt->instate != XML_PARSER_EOF)
-+                  ctxt->instate = state;
-               return;
+--- parser.c.orig      Thu Aug  9 09:44:34 2012
++++ parser.c   Thu Aug  9 09:48:23 2012
+@@ -40,6 +40,7 @@
+ #endif
+ 
+ #include <stdlib.h>
++#include <limits.h>
+ #include <string.h>
+ #include <stdarg.h>
+ #include <libxml/xmlmemory.h>
+@@ -114,10 +115,10 @@ xmlCreateEntityParserCtxtInternal(const xmlChar *URL, 
+  * parser option.
+  */
+ static int
+-xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size,
++xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
+                      xmlEntityPtr ent)
+ {
+-    unsigned long consumed = 0;
++    size_t consumed = 0;
+ 
+     if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
+         return (0);
+@@ -2580,15 +2581,17 @@ xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
+ 
+ /*
+  * Macro used to grow the current buffer.
++ * buffer##_size is expected to be a size_t
++ * mem_error: is expected to handle memory allocation failures
+  */
+ #define growBuffer(buffer, n) {                                               
\
+     xmlChar *tmp;                                                     \
+-    buffer##_size *= 2;                                                       
\
+-    buffer##_size += n;                                                       
\
+-    tmp = (xmlChar *)                                                 \
+-              xmlRealloc(buffer, buffer##_size * sizeof(xmlChar));    \
++    size_t new_size = buffer##_size * 2 + n;                            \
++    if (new_size < buffer##_size) goto mem_error;                       \
++    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
+     if (tmp == NULL) goto mem_error;                                  \
+     buffer = tmp;                                                     \
++    buffer##_size = new_size;                                           \
+ }
+ 
+ /**
+@@ -2614,14 +2617,14 @@ xmlChar *
+ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
+                     int what, xmlChar end, xmlChar  end2, xmlChar end3) {
+     xmlChar *buffer = NULL;
+-    int buffer_size = 0;
++    size_t buffer_size = 0;
++    size_t nbchars = 0;
+ 
+     xmlChar *current = NULL;
+     xmlChar *rep = NULL;
+     const xmlChar *last;
+     xmlEntityPtr ent;
+     int c,l;
+-    int nbchars = 0;
+ 
+     if ((ctxt == NULL) || (str == NULL) || (len < 0))
+       return(NULL);
+@@ -2638,7 +2641,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, cons
+      * allocate a translation buffer.
+      */
+     buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
+-    buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
++    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
+     if (buffer == NULL) goto mem_error;
+ 
+     /*
+@@ -2658,7 +2661,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, cons
+           if (val != 0) {
+               COPY_BUF(0,buffer,nbchars,val);
            }
-           buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
-@@ -5029,7 +5030,8 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
+-          if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
++          if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+               growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+           }
+       } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
+@@ -2676,7 +2679,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, cons
+               (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
+               if (ent->content != NULL) {
+                   COPY_BUF(0,buffer,nbchars,ent->content[0]);
+-                  if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
++                  if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+                       growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+                   }
+               } else {
+@@ -2693,8 +2696,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, cons
+                   current = rep;
+                   while (*current != 0) { /* non input consuming loop */
+                       buffer[nbchars++] = *current++;
+-                      if (nbchars >
+-                          buffer_size - XML_PARSER_BUFFER_SIZE) {
++                      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+                           if (xmlParserEntityCheck(ctxt, nbchars, ent))
+                               goto int_error;
+                           growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+@@ -2708,7 +2710,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, cons
+               const xmlChar *cur = ent->name;
+ 
+               buffer[nbchars++] = '&';
+-              if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
++              if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
+                   growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+               }
+               for (;i > 0;i--)
+@@ -2736,8 +2738,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, cons
+                   current = rep;
+                   while (*current != 0) { /* non input consuming loop */
+                       buffer[nbchars++] = *current++;
+-                      if (nbchars >
+-                          buffer_size - XML_PARSER_BUFFER_SIZE) {
++                      if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
+                           if (xmlParserEntityCheck(ctxt, nbchars, ent))
+                               goto int_error;
+                           growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+@@ -2750,8 +2751,8 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, cons
        } else {
-           xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
+           COPY_BUF(l,buffer,nbchars,c);
+           str += l;
+-          if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
+-            growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
++          if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
++              growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
+           }
        }
--      ctxt->instate = state;
-+      if (ctxt->instate != XML_PARSER_EOF)
-+          ctxt->instate = state;
-     }
- }
+       if (str < last)
+@@ -3755,8 +3756,8 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+     xmlChar limit = 0;
+     xmlChar *buf = NULL;
+     xmlChar *rep = NULL;
+-    int len = 0;
+-    int buf_size = 0;
++    size_t len = 0;
++    size_t buf_size = 0;
+     int c, l, in_space = 0;
+     xmlChar *current = NULL;
+     xmlEntityPtr ent;
+@@ -3778,7 +3779,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+      * allocate a translation buffer.
+      */
+     buf_size = XML_PARSER_BUFFER_SIZE;
+-    buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar));
++    buf = (xmlChar *) xmlMallocAtomic(buf_size);
+     if (buf == NULL) goto mem_error;
  
-@@ -9588,6 +9590,8 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
-     else
-       name = xmlParseStartTag(ctxt);
- #endif /* LIBXML_SAX1_ENABLED */
-+    if (ctxt->instate == XML_PARSER_EOF)
-+      return;
-     if (name == NULL) {
-       spacePop(ctxt);
-         return;
-@@ -10967,6 +10971,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int termina
-               else
-                   name = xmlParseStartTag(ctxt);
- #endif /* LIBXML_SAX1_ENABLED */
-+              if (ctxt->instate == XML_PARSER_EOF)
-+                  goto done;
-               if (name == NULL) {
-                   spacePop(ctxt);
-                   ctxt->instate = XML_PARSER_EOF;
-@@ -11153,7 +11159,9 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int termina
-                 else
-                   xmlParseEndTag1(ctxt, 0);
- #endif /* LIBXML_SAX1_ENABLED */
--              if (ctxt->nameNr == 0) {
-+              if (ctxt->instate == XML_PARSER_EOF) {
-+                  /* Nothing */
-+              } else if (ctxt->nameNr == 0) {
-                   ctxt->instate = XML_PARSER_EPILOG;
-               } else {
-                   ctxt->instate = XML_PARSER_CONTENT;
+     /*
+@@ -3795,7 +3796,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+ 
+               if (val == '&') {
+                   if (ctxt->replaceEntities) {
+-                      if (len > buf_size - 10) {
++                      if (len + 10 > buf_size) {
+                           growBuffer(buf, 10);
+                       }
+                       buf[len++] = '&';
+@@ -3804,7 +3805,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+                        * The reparsing will be done in xmlStringGetNodeList()
+                        * called by the attribute() function in SAX.c
+                        */
+-                      if (len > buf_size - 10) {
++                      if (len + 10 > buf_size) {
+                           growBuffer(buf, 10);
+                       }
+                       buf[len++] = '&';
+@@ -3814,7 +3815,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+                       buf[len++] = ';';
+                   }
+               } else if (val != 0) {
+-                  if (len > buf_size - 10) {
++                  if (len + 10 > buf_size) {
+                       growBuffer(buf, 10);
+                   }
+                   len += xmlCopyChar(0, &buf[len], val);
+@@ -3826,7 +3827,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+                   ctxt->nbentities += ent->owner;
+               if ((ent != NULL) &&
+                   (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
+-                  if (len > buf_size - 10) {
++                  if (len + 10 > buf_size) {
+                       growBuffer(buf, 10);
+                   }
+                   if ((ctxt->replaceEntities == 0) &&
+@@ -3854,7 +3855,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+                                     current++;
+                                 } else
+                                     buf[len++] = *current++;
+-                              if (len > buf_size - 10) {
++                              if (len + 10 > buf_size) {
+                                   growBuffer(buf, 10);
+                               }
+                           }
+@@ -3862,7 +3863,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+                           rep = NULL;
+                       }
+                   } else {
+-                      if (len > buf_size - 10) {
++                      if (len + 10 > buf_size) {
+                           growBuffer(buf, 10);
+                       }
+                       if (ent->content != NULL)
+@@ -3890,7 +3891,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+                    * Just output the reference
+                    */
+                   buf[len++] = '&';
+-                  while (len > buf_size - i - 10) {
++                  while (len + i + 10 > buf_size) {
+                       growBuffer(buf, i + 10);
+                   }
+                   for (;i > 0;i--)
+@@ -3903,7 +3904,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+               if ((len != 0) || (!normalize)) {
+                   if ((!normalize) || (!in_space)) {
+                       COPY_BUF(l,buf,len,0x20);
+-                      while (len > buf_size - 10) {
++                      while (len + 10 > buf_size) {
+                           growBuffer(buf, 10);
+                       }
+                   }
+@@ -3912,7 +3913,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+           } else {
+               in_space = 0;
+               COPY_BUF(l,buf,len,c);
+-              if (len > buf_size - 10) {
++              if (len + 10 > buf_size) {
+                   growBuffer(buf, 10);
+               }
+           }
+@@ -3937,7 +3938,18 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *at
+         }
+     } else
+       NEXT;
+-    if (attlen != NULL) *attlen = len;
++
++    /*
++     * There we potentially risk an overflow, don't allow attribute value of
++     * lenght more than INT_MAX it is a very reasonnable assumption !
++     */
++    if (len >= INT_MAX) {
++        xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
++                       "AttValue lenght too long\n");
++        goto mem_error;
++    }
++
++    if (attlen != NULL) *attlen = (int) len;
+     return(buf);
+ 
+ mem_error:



cheers

Sebastian Trahm

Reply via email to