+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
******************************************************************************
-* 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.
#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
* 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);
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<initialCapacity) {
+ initialCapacity = maxCapacity;
+ }
+ if (initialCapacity > (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) {
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;
}
}