Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.5:Update
libxml2.30542
libxml2-CVE-2022-29824.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File libxml2-CVE-2022-29824.patch of Package libxml2.30542
From 2554a2408e09f13652049e5ffb0d26196b02ebab Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer <wellnhofer@aevum.de> Date: Tue, 8 Mar 2022 20:10:02 +0100 Subject: [PATCH] [CVE-2022-29824] Fix integer overflows in xmlBuf and xmlBuffer In several places, the code handling string buffers didn't check for integer overflow or used wrong types for buffer sizes. This could result in out-of-bounds writes or other memory errors when working on large, multi-gigabyte buffers. Thanks to Felix Wilhelm for the report. --- buf.c | 86 +++++++++++++++++++++++----------------------------------- tree.c | 72 ++++++++++++++++++------------------------------ 2 files changed, 61 insertions(+), 97 deletions(-) Index: libxml2-2.9.7/buf.c =================================================================== --- libxml2-2.9.7.orig/buf.c +++ libxml2-2.9.7/buf.c @@ -30,6 +30,10 @@ #include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */ #include "buf.h" +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t) -1) +#endif + #define WITH_BUFFER_COMPAT /** @@ -156,6 +160,8 @@ xmlBufPtr xmlBufCreateSize(size_t size) { xmlBufPtr ret; + if (size == SIZE_MAX) + return(NULL); ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf)); if (ret == NULL) { xmlBufMemoryError(NULL, "creating buffer"); @@ -166,8 +172,8 @@ xmlBufCreateSize(size_t size) { ret->error = 0; ret->buffer = NULL; ret->alloc = xmlBufferAllocScheme; - ret->size = (size ? size+2 : 0); /* +1 for ending null */ - ret->compat_size = (int) ret->size; + ret->size = (size ? size + 1 : 0); /* +1 for ending null */ + ret->compat_size = (ret->size > INT_MAX ? INT_MAX : ret->size); if (ret->size){ ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar)); if (ret->content == NULL) { @@ -442,23 +448,17 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t CHECK_COMPAT(buf) if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0); - if (buf->use + len < buf->size) + if (len < buf->size - buf->use) return(buf->size - buf->use); + if (len > SIZE_MAX - buf->use) + return(0); - /* - * Windows has a BIG problem on realloc timing, so we try to double - * the buffer size (if that's enough) (bug 146697) - * Apparently BSD too, and it's probably best for linux too - * On an embedded system this may be something to change - */ -#if 1 - if (buf->size > (size_t) len) - size = buf->size * 2; - else - size = buf->use + len + 100; -#else - size = buf->use + len + 100; -#endif + if (buf->size > (size_t) len) { + size = buf->size > SIZE_MAX / 2 ? SIZE_MAX : buf->size * 2; + } else { + size = buf->use + len; + size = size > SIZE_MAX - 100 ? SIZE_MAX : size + 100; + } if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) { /* @@ -744,7 +744,7 @@ xmlBufIsEmpty(const xmlBufPtr buf) int xmlBufResize(xmlBufPtr buf, size_t size) { - unsigned int newSize; + size_t newSize; xmlChar* rebuf = NULL; size_t start_buf; @@ -772,9 +772,13 @@ xmlBufResize(xmlBufPtr buf, size_t size) case XML_BUFFER_ALLOC_IO: case XML_BUFFER_ALLOC_DOUBLEIT: /*take care of empty case*/ - newSize = (buf->size ? buf->size*2 : size + 10); + if (buf->size == 0) { + newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10); + } else { + newSize = buf->size; + } while (size > newSize) { - if (newSize > UINT_MAX / 2) { + if (newSize > SIZE_MAX / 2) { xmlBufMemoryError(buf, "growing buffer"); return 0; } @@ -782,15 +786,15 @@ xmlBufResize(xmlBufPtr buf, size_t size) } break; case XML_BUFFER_ALLOC_EXACT: - newSize = size+10; + newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10); break; case XML_BUFFER_ALLOC_HYBRID: if (buf->use < BASE_BUFFER_SIZE) newSize = size; else { - newSize = buf->size * 2; + newSize = buf->size; while (size > newSize) { - if (newSize > UINT_MAX / 2) { + if (newSize > SIZE_MAX / 2) { xmlBufMemoryError(buf, "growing buffer"); return 0; } @@ -800,7 +804,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) break; default: - newSize = size+10; + newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10); break; } @@ -866,7 +870,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) */ int xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) { - unsigned int needSize; + size_t needSize; if ((str == NULL) || (buf == NULL) || (buf->error)) return -1; @@ -888,8 +892,10 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar * if (len < 0) return -1; if (len == 0) return 0; - needSize = buf->use + len + 2; - if (needSize > buf->size){ + if ((size_t) len >= buf->size - buf->use) { + if ((size_t) len >= SIZE_MAX - buf->use) + return(-1); + needSize = buf->use + len + 1; if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) { /* * Used to provide parsing limits @@ -1025,31 +1031,7 @@ xmlBufCat(xmlBufPtr buf, const xmlChar * */ int xmlBufCCat(xmlBufPtr buf, const char *str) { - const char *cur; - - if ((buf == NULL) || (buf->error)) - return(-1); - CHECK_COMPAT(buf) - if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1; - if (str == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufCCat: str == NULL\n"); -#endif - return -1; - } - for (cur = str;*cur != 0;cur++) { - if (buf->use + 10 >= buf->size) { - if (!xmlBufResize(buf, buf->use+10)){ - xmlBufMemoryError(buf, "growing buffer"); - return XML_ERR_NO_MEMORY; - } - } - buf->content[buf->use++] = *cur; - } - buf->content[buf->use] = 0; - UPDATE_COMPAT(buf) - return 0; + return xmlBufCat(buf, (const xmlChar *) str); } /** Index: libxml2-2.9.7/tree.c =================================================================== --- libxml2-2.9.7.orig/tree.c +++ libxml2-2.9.7/tree.c @@ -7049,6 +7049,8 @@ xmlBufferPtr xmlBufferCreateSize(size_t size) { xmlBufferPtr ret; + if (size >= UINT_MAX) + return(NULL); ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); if (ret == NULL) { xmlTreeErrMemory("creating buffer"); @@ -7056,7 +7058,7 @@ xmlBufferCreateSize(size_t size) { } ret->use = 0; ret->alloc = xmlBufferAllocScheme; - ret->size = (size ? size+2 : 0); /* +1 for ending null */ + ret->size = (size ? size + 1 : 0); /* +1 for ending null */ if (ret->size){ ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar)); if (ret->content == NULL) { @@ -7116,6 +7118,8 @@ xmlBufferCreateStatic(void *mem, size_t if ((mem == NULL) || (size == 0)) return(NULL); + if (size > UINT_MAX) + return(NULL); ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); if (ret == NULL) { @@ -7263,28 +7267,23 @@ xmlBufferShrink(xmlBufferPtr buf, unsign */ int xmlBufferGrow(xmlBufferPtr buf, unsigned int len) { - int size; + unsigned int size; xmlChar *newbuf; if (buf == NULL) return(-1); if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0); - if (len + buf->use < buf->size) return(0); + if (len < buf->size - buf->use) + return(0); + if (len > UINT_MAX - buf->use) + return(-1); - /* - * Windows has a BIG problem on realloc timing, so we try to double - * the buffer size (if that's enough) (bug 146697) - * Apparently BSD too, and it's probably best for linux too - * On an embedded system this may be something to change - */ -#if 1 - if (buf->size > len) - size = buf->size * 2; - else - size = buf->use + len + 100; -#else - size = buf->use + len + 100; -#endif + if (buf->size > (size_t) len) { + size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2; + } else { + size = buf->use + len; + size = size > UINT_MAX - 100 ? UINT_MAX : size + 100; + } if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { size_t start_buf = buf->content - buf->contentIO; @@ -7406,7 +7405,10 @@ xmlBufferResize(xmlBufferPtr buf, unsign case XML_BUFFER_ALLOC_IO: case XML_BUFFER_ALLOC_DOUBLEIT: /*take care of empty case*/ - newSize = (buf->size ? buf->size*2 : size + 10); + if (buf->size == 0) + newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10); + else + newSize = buf->size; while (size > newSize) { if (newSize > UINT_MAX / 2) { xmlTreeErrMemory("growing buffer"); @@ -7416,7 +7418,7 @@ xmlBufferResize(xmlBufferPtr buf, unsign } break; case XML_BUFFER_ALLOC_EXACT: - newSize = size+10; + newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);; break; case XML_BUFFER_ALLOC_HYBRID: if (buf->use < BASE_BUFFER_SIZE) @@ -7434,7 +7436,7 @@ xmlBufferResize(xmlBufferPtr buf, unsign break; default: - newSize = size+10; + newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);; break; } @@ -7520,8 +7522,10 @@ xmlBufferAdd(xmlBufferPtr buf, const xml if (len < 0) return -1; if (len == 0) return 0; - needSize = buf->use + len + 2; - if (needSize > buf->size){ + if ((unsigned) len >= buf->size - buf->use) { + if ((unsigned) len >= UINT_MAX - buf->use) + return XML_ERR_NO_MEMORY; + needSize = buf->use + len + 1; if (!xmlBufferResize(buf, needSize)){ xmlTreeErrMemory("growing buffer"); return XML_ERR_NO_MEMORY; @@ -7634,29 +7638,7 @@ xmlBufferCat(xmlBufferPtr buf, const xml */ int xmlBufferCCat(xmlBufferPtr buf, const char *str) { - const char *cur; - - if (buf == NULL) - return(-1); - if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1; - if (str == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferCCat: str == NULL\n"); -#endif - return -1; - } - for (cur = str;*cur != 0;cur++) { - if (buf->use + 10 >= buf->size) { - if (!xmlBufferResize(buf, buf->use+10)){ - xmlTreeErrMemory("growing buffer"); - return XML_ERR_NO_MEMORY; - } - } - buf->content[buf->use++] = *cur; - } - buf->content[buf->use] = 0; - return 0; + return xmlBufferCat(buf, (const xmlChar *) str); } /**
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor