X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b75a7d8f3b4adbae880cab104ce2c6a50eee4db2..ef6cf650f4a75c3f97de06b51fa104f2069b9ea2:/icuSources/common/uvectr32.cpp?ds=inline diff --git a/icuSources/common/uvectr32.cpp b/icuSources/common/uvectr32.cpp index fcf5c9a7..f7a65250 100644 --- a/icuSources/common/uvectr32.cpp +++ b/icuSources/common/uvectr32.cpp @@ -1,7 +1,7 @@ /* ****************************************************************************** -* Copyright (C) 1999-2003, International Business Machines Corporation and * -* others. All Rights Reserved. * +* Copyright (C) 1999-2015, International Business Machines Corporation and +* others. All Rights Reserved. ****************************************************************************** * Date Name Description * 10/22/99 alan Creation. @@ -10,10 +10,11 @@ #include "uvectr32.h" #include "cmemory.h" +#include "putilimp.h" U_NAMESPACE_BEGIN -#define DEFUALT_CAPACITY 8 +#define DEFAULT_CAPACITY 8 /* * Constants for hinting whether a key is an integer @@ -21,19 +22,21 @@ U_NAMESPACE_BEGIN * token is assumed to be an integer. This is needed for iSeries */ -const char UVector32::fgClassID=0; +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector32) UVector32::UVector32(UErrorCode &status) : count(0), capacity(0), + maxCapacity(0), elements(NULL) { - _init(DEFUALT_CAPACITY, status); + _init(DEFAULT_CAPACITY, status); } UVector32::UVector32(int32_t initialCapacity, UErrorCode &status) : count(0), capacity(0), + maxCapacity(0), elements(0) { _init(initialCapacity, status); @@ -44,7 +47,13 @@ UVector32::UVector32(int32_t initialCapacity, UErrorCode &status) : void UVector32::_init(int32_t initialCapacity, UErrorCode &status) { // Fix bogus initialCapacity values; avoid malloc(0) if (initialCapacity < 1) { - initialCapacity = DEFUALT_CAPACITY; + initialCapacity = DEFAULT_CAPACITY; + } + if (maxCapacity>0 && maxCapacity (int32_t)(INT32_MAX / sizeof(int32_t))) { + initialCapacity = uprv_min(DEFAULT_CAPACITY, maxCapacity); } elements = (int32_t *)uprv_malloc(sizeof(int32_t)*initialCapacity); if (elements == 0) { @@ -187,23 +196,74 @@ int32_t UVector32::indexOf(int32_t key, int32_t startIndex) const { UBool UVector32::expandCapacity(int32_t minimumCapacity, UErrorCode &status) { + if (U_FAILURE(status)) { + return FALSE; + } + if (minimumCapacity < 0) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return FALSE; + } if (capacity >= minimumCapacity) { return TRUE; - } else { - int32_t newCap = capacity * 2; - if (newCap < minimumCapacity) { - newCap = minimumCapacity; - } - int32_t* newElems = (int32_t *)uprv_malloc(sizeof(int32_t)*newCap); - if (newElems == 0) { - status = U_MEMORY_ALLOCATION_ERROR; - return FALSE; - } - uprv_memcpy(newElems, elements, sizeof(elements[0]) * count); - uprv_free(elements); - elements = newElems; - capacity = newCap; - return TRUE; + } + if (maxCapacity>0 && minimumCapacity>maxCapacity) { + status = U_BUFFER_OVERFLOW_ERROR; + return FALSE; + } + if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check + status = U_ILLEGAL_ARGUMENT_ERROR; + return FALSE; + } + int32_t newCap = capacity * 2; + if (newCap < minimumCapacity) { + newCap = minimumCapacity; + } + if (maxCapacity > 0 && newCap > maxCapacity) { + newCap = maxCapacity; + } + if (newCap > (int32_t)(INT32_MAX / sizeof(int32_t))) { // integer overflow check + // We keep the original memory contents on bad minimumCapacity/maxCapacity. + status = U_ILLEGAL_ARGUMENT_ERROR; + return FALSE; + } + int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*newCap); + if (newElems == NULL) { + // We keep the original contents on the memory failure on realloc. + status = U_MEMORY_ALLOCATION_ERROR; + return FALSE; + } + elements = newElems; + capacity = newCap; + return TRUE; +} + +void UVector32::setMaxCapacity(int32_t limit) { + U_ASSERT(limit >= 0); + if (limit < 0) { + limit = 0; + } + if (limit > (int32_t)(INT32_MAX / sizeof(int32_t))) { // integer overflow check for realloc + // Something is very wrong, don't realloc, leave capacity and maxCapacity unchanged + return; + } + maxCapacity = limit; + if (capacity <= maxCapacity || maxCapacity == 0) { + // Current capacity is within the new limit. + return; + } + + // New maximum capacity is smaller than the current size. + // Realloc the storage to the new, smaller size. + int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*maxCapacity); + if (newElems == NULL) { + // Realloc to smaller failed. + // Just keep what we had. No need to call it a failure. + return; + } + elements = newElems; + capacity = maxCapacity; + if (count > capacity) { + count = capacity; } }