Sync with official PuTTY 0.81 source code
[TortoiseGit.git] / src / TortoisePlink / utils / memory.c
blob508cffaf3d3de08a7b7bcf00d03fbd615c63472b
1 /*
2 * PuTTY's memory allocation wrappers.
3 */
5 #ifdef ALLOCATION_ALIGNMENT
6 /* Before we include standard headers, define _ISOC11_SOURCE so that
7 * we get the declaration of aligned_alloc(). */
8 #define _ISOC11_SOURCE
9 #endif
11 #include <assert.h>
12 #include <stdlib.h>
13 #include <limits.h>
15 #include "defs.h"
16 #include "puttymem.h"
17 #include "misc.h"
19 void *safemalloc(size_t factor1, size_t factor2, size_t addend)
21 if (factor1 > SIZE_MAX / factor2)
22 goto fail;
23 size_t product = factor1 * factor2;
25 if (addend > SIZE_MAX)
26 goto fail;
27 if (product > SIZE_MAX - addend)
28 goto fail;
29 size_t size = product + addend;
31 if (size == 0)
32 size = 1;
34 void *p;
35 #ifdef MINEFIELD
36 p = minefield_c_malloc(size);
37 #elif defined ALLOCATION_ALIGNMENT
38 p = aligned_alloc(ALLOCATION_ALIGNMENT, size);
39 #else
40 p = malloc(size);
41 #endif
43 if (!p)
44 goto fail;
46 return p;
48 fail:
49 out_of_memory();
52 void *saferealloc(void *ptr, size_t n, size_t size)
54 void *p;
56 if (n > INT_MAX / size) {
57 p = NULL;
58 } else {
59 size *= n;
60 if (!ptr) {
61 #ifdef MINEFIELD
62 p = minefield_c_malloc(size);
63 #elif defined ALLOCATION_ALIGNMENT
64 p = aligned_alloc(ALLOCATION_ALIGNMENT, size);
65 #else
66 p = malloc(size);
67 #endif
68 } else {
69 #ifdef MINEFIELD
70 p = minefield_c_realloc(ptr, size);
71 #else
72 p = realloc(ptr, size);
73 #endif
77 if (!p)
78 out_of_memory();
80 return p;
83 void safefree(void *ptr)
85 if (ptr) {
86 #ifdef MINEFIELD
87 minefield_c_free(ptr);
88 #else
89 free(ptr);
90 #endif
94 void *safegrowarray(void *ptr, size_t *allocated, size_t eltsize,
95 size_t oldlen, size_t extralen, bool secret)
97 /* The largest value we can safely multiply by eltsize */
98 assert(eltsize > 0);
99 size_t maxsize = (~(size_t)0) / eltsize;
101 size_t oldsize = *allocated;
103 /* Range-check the input values */
104 assert(oldsize <= maxsize);
105 assert(oldlen <= maxsize);
106 assert(extralen <= maxsize - oldlen);
108 /* If the size is already enough, don't bother doing anything! */
109 if (oldsize > oldlen + extralen)
110 return ptr;
112 /* Find out how much we need to grow the array by. */
113 size_t increment = (oldlen + extralen) - oldsize;
115 /* Invent a new size. We want to grow the array by at least
116 * 'increment' elements; by at least a fixed number of bytes (to
117 * get things started when sizes are small); and by some constant
118 * factor of its old size (to avoid repeated calls to this
119 * function taking quadratic time overall). */
120 if (increment < 256 / eltsize)
121 increment = 256 / eltsize;
122 if (increment < oldsize / 16)
123 increment = oldsize / 16;
125 /* But we also can't grow beyond maxsize. */
126 size_t maxincr = maxsize - oldsize;
127 if (increment > maxincr)
128 increment = maxincr;
130 size_t newsize = oldsize + increment;
131 void *toret;
132 if (secret) {
133 toret = safemalloc(newsize, eltsize, 0);
134 if (oldsize) {
135 memcpy(toret, ptr, oldsize * eltsize);
136 smemclr(ptr, oldsize * eltsize);
137 sfree(ptr);
139 } else {
140 toret = saferealloc(ptr, newsize, eltsize);
142 *allocated = newsize;
143 return toret;