зеркало из https://github.com/github/putty.git
135 строки
2.9 KiB
C
135 строки
2.9 KiB
C
/*
|
|
* PuTTY's memory allocation wrappers.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
|
|
#include "defs.h"
|
|
#include "puttymem.h"
|
|
#include "misc.h"
|
|
|
|
void *safemalloc(size_t factor1, size_t factor2, size_t addend)
|
|
{
|
|
if (factor1 > SIZE_MAX / factor2)
|
|
goto fail;
|
|
size_t product = factor1 * factor2;
|
|
|
|
if (addend > SIZE_MAX)
|
|
goto fail;
|
|
if (product > SIZE_MAX - addend)
|
|
goto fail;
|
|
size_t size = product + addend;
|
|
|
|
if (size == 0)
|
|
size = 1;
|
|
|
|
void *p;
|
|
#ifdef MINEFIELD
|
|
p = minefield_c_malloc(size);
|
|
#else
|
|
p = malloc(size);
|
|
#endif
|
|
|
|
if (!p)
|
|
goto fail;
|
|
|
|
return p;
|
|
|
|
fail:
|
|
out_of_memory();
|
|
}
|
|
|
|
void *saferealloc(void *ptr, size_t n, size_t size)
|
|
{
|
|
void *p;
|
|
|
|
if (n > INT_MAX / size) {
|
|
p = NULL;
|
|
} else {
|
|
size *= n;
|
|
if (!ptr) {
|
|
#ifdef MINEFIELD
|
|
p = minefield_c_malloc(size);
|
|
#else
|
|
p = malloc(size);
|
|
#endif
|
|
} else {
|
|
#ifdef MINEFIELD
|
|
p = minefield_c_realloc(ptr, size);
|
|
#else
|
|
p = realloc(ptr, size);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (!p)
|
|
out_of_memory();
|
|
|
|
return p;
|
|
}
|
|
|
|
void safefree(void *ptr)
|
|
{
|
|
if (ptr) {
|
|
#ifdef MINEFIELD
|
|
minefield_c_free(ptr);
|
|
#else
|
|
free(ptr);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void *safegrowarray(void *ptr, size_t *allocated, size_t eltsize,
|
|
size_t oldlen, size_t extralen, bool secret)
|
|
{
|
|
/* The largest value we can safely multiply by eltsize */
|
|
assert(eltsize > 0);
|
|
size_t maxsize = (~(size_t)0) / eltsize;
|
|
|
|
size_t oldsize = *allocated;
|
|
|
|
/* Range-check the input values */
|
|
assert(oldsize <= maxsize);
|
|
assert(oldlen <= maxsize);
|
|
assert(extralen <= maxsize - oldlen);
|
|
|
|
/* If the size is already enough, don't bother doing anything! */
|
|
if (oldsize > oldlen + extralen)
|
|
return ptr;
|
|
|
|
/* Find out how much we need to grow the array by. */
|
|
size_t increment = (oldlen + extralen) - oldsize;
|
|
|
|
/* Invent a new size. We want to grow the array by at least
|
|
* 'increment' elements; by at least a fixed number of bytes (to
|
|
* get things started when sizes are small); and by some constant
|
|
* factor of its old size (to avoid repeated calls to this
|
|
* function taking quadratic time overall). */
|
|
if (increment < 256 / eltsize)
|
|
increment = 256 / eltsize;
|
|
if (increment < oldsize / 16)
|
|
increment = oldsize / 16;
|
|
|
|
/* But we also can't grow beyond maxsize. */
|
|
size_t maxincr = maxsize - oldsize;
|
|
if (increment > maxincr)
|
|
increment = maxincr;
|
|
|
|
size_t newsize = oldsize + increment;
|
|
void *toret;
|
|
if (secret) {
|
|
toret = safemalloc(newsize, eltsize, 0);
|
|
if (oldsize) {
|
|
memcpy(toret, ptr, oldsize * eltsize);
|
|
smemclr(ptr, oldsize * eltsize);
|
|
sfree(ptr);
|
|
}
|
|
} else {
|
|
toret = saferealloc(ptr, newsize, eltsize);
|
|
}
|
|
*allocated = newsize;
|
|
return toret;
|
|
}
|