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