2000-12-12 10:33:13 +00:00
|
|
|
/*
|
|
|
|
* PuTTY memory-handling header.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef PUTTY_PUTTYMEM_H
|
|
|
|
#define PUTTY_PUTTYMEM_H
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
#include <stddef.h> /* for size_t */
|
|
|
|
#include <string.h> /* for memcpy() */
|
2001-04-28 09:24:19 +00:00
|
|
|
|
Move standalone parts of misc.c into utils.c.
misc.c has always contained a combination of things that are tied
tightly into the PuTTY code base (e.g. they use the conf system, or
work with our sockets abstraction) and things that are pure standalone
utility functions like nullstrcmp() which could quite happily be
dropped into any C program without causing a link failure.
Now the latter kind of standalone utility code lives in the new source
file utils.c, whose only external dependency is on memory.c (for snew,
sfree etc), which in turn requires the user to provide an
out_of_memory() function. So it should now be much easier to link test
programs that use PuTTY's low-level functions without also pulling in
half its bulky infrastructure.
In the process, I came across a memory allocation logging system
enabled by -DMALLOC_LOG that looks long since bit-rotted; in any case
we have much more advanced tools for that kind of thing these days,
like valgrind and Leak Sanitiser, so I've just removed it rather than
trying to transplant it somewhere sensible. (We can always pull it
back out of the version control history if really necessary, but I
haven't used it in at least a decade.)
The other slightly silly thing I did was to give bufchain a function
pointer field that points to queue_idempotent_callback(), and disallow
direct setting of the 'ic' field in favour of calling
bufchain_set_callback which will fill that pointer in too. That allows
the bufchain system to live in utils.c rather than misc.c, so that
programs can use it without also having to link in the callback system
or provide an annoying stub of that function. In fact that's just
allowed me to remove stubs of that kind from PuTTYgen and Pageant!
2019-01-03 08:44:11 +00:00
|
|
|
#include "defs.h"
|
2001-04-28 09:24:19 +00:00
|
|
|
|
2019-06-28 18:38:45 +00:00
|
|
|
#define smalloc(z) safemalloc(z,1,0)
|
2005-02-20 10:30:05 +00:00
|
|
|
#define snmalloc safemalloc
|
|
|
|
#define srealloc(y,z) saferealloc(y,z,1)
|
|
|
|
#define snrealloc saferealloc
|
2000-12-12 10:33:13 +00:00
|
|
|
#define sfree safefree
|
|
|
|
|
2019-06-28 18:38:45 +00:00
|
|
|
void *safemalloc(size_t factor1, size_t factor2, size_t addend);
|
2005-02-20 10:30:05 +00:00
|
|
|
void *saferealloc(void *, size_t, size_t);
|
2000-12-12 10:33:13 +00:00
|
|
|
void safefree(void *);
|
|
|
|
|
2003-03-29 16:14:26 +00:00
|
|
|
/*
|
|
|
|
* Direct use of smalloc within the code should be avoided where
|
2019-01-03 10:51:52 +00:00
|
|
|
* possible, in favour of these type-casting macros which ensure you
|
|
|
|
* don't mistakenly allocate enough space for one sort of structure
|
|
|
|
* and assign it to a different sort of pointer. sresize also uses
|
|
|
|
* TYPECHECK to verify that the _input_ pointer is a pointer to the
|
|
|
|
* correct type.
|
2003-03-29 16:14:26 +00:00
|
|
|
*/
|
2019-06-28 18:38:45 +00:00
|
|
|
#define snew(type) ((type *)snmalloc(1, sizeof(type), 0))
|
|
|
|
#define snewn(n, type) ((type *)snmalloc((n), sizeof(type), 0))
|
2019-01-03 10:51:52 +00:00
|
|
|
#define sresize(ptr, n, type) TYPECHECK((type *)0 == (ptr), \
|
|
|
|
((type *)snrealloc((ptr), (n), sizeof(type))))
|
2001-04-28 09:24:19 +00:00
|
|
|
|
2018-06-06 05:42:52 +00:00
|
|
|
/*
|
|
|
|
* For cases where you want to allocate a struct plus a subsidiary
|
|
|
|
* data buffer in one step, this macro lets you add a constant to the
|
|
|
|
* amount malloced.
|
|
|
|
*
|
|
|
|
* Since the return value is already cast to the struct type, a
|
|
|
|
* pointer to that many bytes of extra data can be conveniently
|
|
|
|
* obtained by simply adding 1 to the returned pointer!
|
|
|
|
* snew_plus_get_aux is a handy macro that does that and casts the
|
|
|
|
* result to void *, so you can assign it straight to wherever you
|
|
|
|
* wanted it.
|
|
|
|
*/
|
2019-06-28 18:38:45 +00:00
|
|
|
#define snew_plus(type, extra) ((type *)snmalloc(1, sizeof(type), (extra)))
|
2018-06-06 05:42:52 +00:00
|
|
|
#define snew_plus_get_aux(ptr) ((void *)((ptr) + 1))
|
|
|
|
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
/*
|
|
|
|
* Helper macros to deal with the common use case of growing an array.
|
|
|
|
*
|
|
|
|
* The common setup is that 'array' is a pointer to the first element
|
|
|
|
* of a dynamic array of some type, and 'size' represents the current
|
|
|
|
* allocated size of that array (in elements). Both of those macro
|
|
|
|
* parameters are implicitly written back to.
|
|
|
|
*
|
|
|
|
* Then sgrowarray(array, size, n) means: make sure the nth element of
|
|
|
|
* the array exists (i.e. the size is at least n+1). You call that
|
|
|
|
* before writing to the nth element, if you're looping round
|
|
|
|
* appending to the array.
|
|
|
|
*
|
|
|
|
* If you need to grow the array by more than one element, you can
|
|
|
|
* instead call sgrowarrayn(array, size, n, m), which will ensure the
|
|
|
|
* size of the array is at least n+m. (So sgrowarray is just the
|
|
|
|
* special case of that in which m == 1.)
|
|
|
|
*
|
|
|
|
* It's common to call sgrowarrayn with one of n,m equal to the
|
|
|
|
* previous logical length of the array, and the other equal to the
|
|
|
|
* new number of logical entries you want to add, so that n <= size on
|
|
|
|
* entry. But that's not actually a mandatory precondition: the two
|
|
|
|
* length parameters are just arbitrary integers that get added
|
|
|
|
* together with an initial check for overflow, and the semantics are
|
|
|
|
* simply 'make sure the array is big enough to take their sum, no
|
|
|
|
* matter how big it was to start with'.)
|
|
|
|
*
|
|
|
|
* Another occasionally useful idiom is to call sgrowarray with n ==
|
|
|
|
* size, i.e. sgrowarray(array, size, size). That just means: make
|
|
|
|
* array bigger by _some_ amount, I don't particularly mind how much.
|
|
|
|
* You might use that style if you were repeatedly calling an API
|
|
|
|
* function outside your control, which would either fill your buffer
|
|
|
|
* and return success, or else return a 'too big' error without
|
|
|
|
* telling you how much bigger it needed to be.
|
2019-03-01 19:25:47 +00:00
|
|
|
*
|
|
|
|
* The _nm variants of the macro set the 'private' flag in the
|
|
|
|
* underlying function, which forces array resizes to be done by a
|
|
|
|
* manual allocate/copy/free instead of realloc, with careful clearing
|
|
|
|
* of the previous memory block before we free it. This costs
|
|
|
|
* performance, but if the block contains important secrets such as
|
|
|
|
* private keys or passwords, it avoids the risk that a realloc that
|
|
|
|
* moves the memory block might leave a copy of the data visible in
|
|
|
|
* the freed memory at the previous location.
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
*/
|
|
|
|
void *safegrowarray(void *array, size_t *size, size_t eltsize,
|
2019-03-01 19:25:47 +00:00
|
|
|
size_t oldlen, size_t extralen, bool private);
|
|
|
|
|
|
|
|
/* The master macro wrapper, of which all others are special cases */
|
|
|
|
#define sgrowarray_general(array, size, n, m, priv) \
|
|
|
|
((array) = safegrowarray(array, &(size), sizeof(*array), n, m, priv))
|
|
|
|
|
|
|
|
/* The special-case macros that are easier to use in most situations */
|
|
|
|
#define sgrowarrayn( a, s, n, m) sgrowarray_general(a, s, n, m, false)
|
|
|
|
#define sgrowarray( a, s, n ) sgrowarray_general(a, s, n, 1, false)
|
|
|
|
#define sgrowarrayn_nm(a, s, n, m) sgrowarray_general(a, s, n, m, true )
|
|
|
|
#define sgrowarray_nm( a, s, n ) sgrowarray_general(a, s, n, 1, true )
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
|
Move standalone parts of misc.c into utils.c.
misc.c has always contained a combination of things that are tied
tightly into the PuTTY code base (e.g. they use the conf system, or
work with our sockets abstraction) and things that are pure standalone
utility functions like nullstrcmp() which could quite happily be
dropped into any C program without causing a link failure.
Now the latter kind of standalone utility code lives in the new source
file utils.c, whose only external dependency is on memory.c (for snew,
sfree etc), which in turn requires the user to provide an
out_of_memory() function. So it should now be much easier to link test
programs that use PuTTY's low-level functions without also pulling in
half its bulky infrastructure.
In the process, I came across a memory allocation logging system
enabled by -DMALLOC_LOG that looks long since bit-rotted; in any case
we have much more advanced tools for that kind of thing these days,
like valgrind and Leak Sanitiser, so I've just removed it rather than
trying to transplant it somewhere sensible. (We can always pull it
back out of the version control history if really necessary, but I
haven't used it in at least a decade.)
The other slightly silly thing I did was to give bufchain a function
pointer field that points to queue_idempotent_callback(), and disallow
direct setting of the 'ic' field in favour of calling
bufchain_set_callback which will fill that pointer in too. That allows
the bufchain system to live in utils.c rather than misc.c, so that
programs can use it without also having to link in the callback system
or provide an annoying stub of that function. In fact that's just
allowed me to remove stubs of that kind from PuTTYgen and Pageant!
2019-01-03 08:44:11 +00:00
|
|
|
/*
|
|
|
|
* This function is called by the innermost safemalloc/saferealloc
|
2022-01-22 15:38:53 +00:00
|
|
|
* functions when allocation fails. Usually it's provided by an
|
|
|
|
* implementation in utils, which ties it into an application's
|
|
|
|
* existing modalfatalbox() system, but standalone test applications
|
|
|
|
* can reimplement it some other way if they prefer.
|
Move standalone parts of misc.c into utils.c.
misc.c has always contained a combination of things that are tied
tightly into the PuTTY code base (e.g. they use the conf system, or
work with our sockets abstraction) and things that are pure standalone
utility functions like nullstrcmp() which could quite happily be
dropped into any C program without causing a link failure.
Now the latter kind of standalone utility code lives in the new source
file utils.c, whose only external dependency is on memory.c (for snew,
sfree etc), which in turn requires the user to provide an
out_of_memory() function. So it should now be much easier to link test
programs that use PuTTY's low-level functions without also pulling in
half its bulky infrastructure.
In the process, I came across a memory allocation logging system
enabled by -DMALLOC_LOG that looks long since bit-rotted; in any case
we have much more advanced tools for that kind of thing these days,
like valgrind and Leak Sanitiser, so I've just removed it rather than
trying to transplant it somewhere sensible. (We can always pull it
back out of the version control history if really necessary, but I
haven't used it in at least a decade.)
The other slightly silly thing I did was to give bufchain a function
pointer field that points to queue_idempotent_callback(), and disallow
direct setting of the 'ic' field in favour of calling
bufchain_set_callback which will fill that pointer in too. That allows
the bufchain system to live in utils.c rather than misc.c, so that
programs can use it without also having to link in the callback system
or provide an annoying stub of that function. In fact that's just
allowed me to remove stubs of that kind from PuTTYgen and Pageant!
2019-01-03 08:44:11 +00:00
|
|
|
*/
|
|
|
|
NORETURN void out_of_memory(void);
|
|
|
|
|
2019-02-28 18:50:13 +00:00
|
|
|
#ifdef MINEFIELD
|
|
|
|
/*
|
|
|
|
* Definitions for Minefield, PuTTY's own Windows-specific malloc
|
2022-01-22 15:38:53 +00:00
|
|
|
* debugger in the style of Electric Fence. Implemented in
|
|
|
|
* windows/utils/minefield.c, and referred to by the main malloc
|
|
|
|
* wrappers in memory.c.
|
2019-02-28 18:50:13 +00:00
|
|
|
*/
|
|
|
|
void *minefield_c_malloc(size_t size);
|
|
|
|
void minefield_c_free(void *p);
|
|
|
|
void *minefield_c_realloc(void *p, size_t size);
|
|
|
|
#endif
|
|
|
|
|
2000-12-12 10:33:13 +00:00
|
|
|
#endif
|