diff --git a/buf.c b/buf.c index 24368d379f82370b34c1710bebbe6a92a5bcfdfa..c7e51005fe4b43f3bb6d2f7991354da78cb9f0a1 100644 --- a/buf.c +++ b/buf.c @@ -30,6 +30,10 @@ #include /* 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,7 +172,7 @@ xmlBufCreateSize(size_t size) { ret->error = 0; ret->buffer = NULL; ret->alloc = xmlBufferAllocScheme; - ret->size = (size ? size+2 : 0); /* +1 for ending null */ + ret->size = (size ? size+1 : 0); /* +1 for ending null */ ret->compat_size = (int) ret->size; if (ret->size){ ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar)); @@ -442,23 +448,18 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) { 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); - /* - * 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 (len > SIZE_MAX - buf->use) + return(0); + + 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 +745,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 +773,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 +787,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 +805,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) break; default: - newSize = size+10; + newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10); break; } @@ -866,7 +871,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 +893,10 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) { 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 +1032,7 @@ xmlBufCat(xmlBufPtr buf, const xmlChar *str) { */ 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); } /** diff --git a/tree.c b/tree.c index c707f598e8d5b33de934757fada92ff1c6c57000..35fe2f3db5277dd392e616852a24ae8bef23bc31 100644 --- a/tree.c +++ b/tree.c @@ -7095,6 +7095,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"); @@ -7102,7 +7104,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) { @@ -7162,6 +7164,8 @@ xmlBufferCreateStatic(void *mem, size_t size) { if ((mem == NULL) || (size == 0)) return(NULL); + if (size > UINT_MAX) + return(NULL); ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); if (ret == NULL) { @@ -7309,28 +7313,23 @@ xmlBufferShrink(xmlBufferPtr buf, unsigned int len) { */ 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; @@ -7457,7 +7456,10 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) case XML_BUFFER_ALLOC_IO: case XML_BUFFER_ALLOC_DOUBLEIT: /*take care of empty case*/ - newSize = (buf->size ? buf->size : 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"); @@ -7467,7 +7469,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) } 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) @@ -7485,7 +7487,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) break; default: - newSize = size+10; + newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10); break; } @@ -7571,8 +7573,10 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) { 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; @@ -7685,29 +7689,7 @@ xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) { */ 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); } /**