mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
Bug 608196 - Overflow-safe g_new family
Remove the macros for the g_malloc_n family -- calls directly to those functions now always go directly to those functions. Reimplement the macros for g_new and friends. Remove the branch that checked for calling g_new() with a constant n_structs == 1. With the struct size always known this case will now be caught under the case that does the inline multiplication and the multiplication by 1 will be optimised away.
This commit is contained in:
parent
01ef92178b
commit
a1b9743e18
@ -37,14 +37,6 @@
|
|||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
#include "gthreadprivate.h"
|
#include "gthreadprivate.h"
|
||||||
|
|
||||||
/* Undef the macros before including galias.h */
|
|
||||||
#undef g_malloc_n
|
|
||||||
#undef g_malloc0_n
|
|
||||||
#undef g_realloc_n
|
|
||||||
#undef g_try_malloc_n
|
|
||||||
#undef g_try_malloc0_n
|
|
||||||
#undef g_try_realloc_n
|
|
||||||
|
|
||||||
#include "galias.h"
|
#include "galias.h"
|
||||||
|
|
||||||
#define MEM_PROFILE_TABLE_SIZE 4096
|
#define MEM_PROFILE_TABLE_SIZE 4096
|
||||||
|
85
glib/gmem.h
85
glib/gmem.h
@ -76,67 +76,54 @@ gpointer g_try_realloc_n (gpointer mem,
|
|||||||
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
|
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
|
||||||
/* avoid the overflow check if we can determine at compile-time that no
|
/* Optimise: avoid the call to the (slower) _n function if we can
|
||||||
* overflow happens. */
|
* determine at compile-time that no overflow happens.
|
||||||
|
*/
|
||||||
#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
|
#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
|
||||||
# define _G_MALLOC_N(n_blocks, n_block_bytes, func_1, func_n) \
|
# define _G_NEW(struct_type, n_structs, func) \
|
||||||
(__extension__ ({ \
|
(struct_type *) (__extension__ ({ \
|
||||||
gsize __a = (gsize) (n_blocks); \
|
gsize __n = (gsize) (n_structs); \
|
||||||
gsize __b = (gsize) (n_block_bytes); \
|
|
||||||
gpointer __p; \
|
gpointer __p; \
|
||||||
if (__builtin_constant_p (__a) && __a == 1) \
|
if (sizeof (struct_type) == 1) \
|
||||||
__p = func_1 (__b); \
|
__p = g_##func (__n); \
|
||||||
else if (__builtin_constant_p (__b) && __b == 1) \
|
else if (__builtin_constant_p (__n) && \
|
||||||
__p = func_1 (__a); \
|
__n <= G_MAXSIZE / sizeof (struct_type)) \
|
||||||
else if (__builtin_constant_p (__a) && \
|
__p = g_##func (__n * sizeof (struct_type)); \
|
||||||
__builtin_constant_p (__b) && \
|
|
||||||
__a <= G_MAXSIZE / __b) \
|
|
||||||
__p = func_1 (__a * __b); \
|
|
||||||
else \
|
else \
|
||||||
__p = func_n (__a, __b); \
|
__p = g_##func##_n (__n, sizeof (struct_type)); \
|
||||||
__p; \
|
__p; \
|
||||||
}))
|
}))
|
||||||
# define _G_REALLOC_N(mem, n_blocks, n_block_bytes, func_1, func_n) \
|
# define _G_RENEW(struct_type, mem, n_structs, func) \
|
||||||
(__extension__ ({ \
|
(struct_type *) (__extension__ ({ \
|
||||||
gsize __a = (gsize) (n_blocks); \
|
gsize __n = (gsize) (n_structs); \
|
||||||
gsize __b = (gsize) (n_block_bytes); \
|
|
||||||
gpointer __p = (gpointer) (mem); \
|
gpointer __p = (gpointer) (mem); \
|
||||||
if (__builtin_constant_p (__a) && __a == 1) \
|
if (sizeof (struct_type) == 1) \
|
||||||
__p = func_1 (__p, __b); \
|
__p = g_##func (__p, __n); \
|
||||||
else if (__builtin_constant_p (__b) && __b == 1) \
|
else if (__builtin_constant_p (__n) && \
|
||||||
__p = func_1 (__p, __a); \
|
__n <= G_MAXSIZE / sizeof (struct_type)) \
|
||||||
else if (__builtin_constant_p (__a) && \
|
__p = g_##func (__p, __n * sizeof (struct_type)); \
|
||||||
__builtin_constant_p (__b) && \
|
|
||||||
__a <= G_MAXSIZE / __b) \
|
|
||||||
__p = func_1 (__p, __a * __b); \
|
|
||||||
else \
|
else \
|
||||||
__p = func_n (__p, __a, __b); \
|
__p = g_##func##_n (__p, __n, sizeof (struct_type));\
|
||||||
__p; \
|
__p; \
|
||||||
}))
|
}))
|
||||||
|
|
||||||
# define g_malloc_n(n_blocks,n_block_bytes) _G_MALLOC_N (n_blocks, n_block_bytes, g_malloc, g_malloc_n)
|
#else
|
||||||
# define g_malloc0_n(n_blocks,n_block_bytes) _G_MALLOC_N (n_blocks, n_block_bytes, g_malloc0, g_malloc0_n)
|
|
||||||
# define g_realloc_n(mem,n_blocks,n_block_bytes) _G_REALLOC_N (mem, n_blocks, n_block_bytes, g_realloc, g_realloc_n)
|
/* Unoptimised version: always call the _n() function. */
|
||||||
# define g_try_malloc_n(n_blocks,n_block_bytes) _G_MALLOC_N (n_blocks, n_block_bytes, g_try_malloc, g_try_malloc_n)
|
|
||||||
# define g_try_malloc0_n(n_blocks,n_block_bytes) _G_MALLOC_N (n_blocks, n_block_bytes, g_try_malloc0, g_try_malloc0_n)
|
#define _G_NEW(struct_type, n_structs, func) \
|
||||||
# define g_try_realloc_n(mem,n_blocks,n_block_bytes) _G_REALLOC_N (mem, n_blocks, n_block_bytes, g_try_realloc, g_try_realloc_n)
|
((struct_type *) g_##func##_n ((n_structs), sizeof (struct_type)))
|
||||||
|
#define _G_RENEW(struct_type, mem, n_structs, func) \
|
||||||
|
((struct_type *) g_##func##_n (mem, (n_structs), sizeof (struct_type)))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define g_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc)
|
||||||
/* Convenience memory allocators
|
#define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc0)
|
||||||
*/
|
#define g_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, realloc)
|
||||||
|
#define g_try_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, try_malloc)
|
||||||
#define _G_NEW(struct_type, n_structs, _g_malloc_n) \
|
#define g_try_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, try_malloc0)
|
||||||
((struct_type *) _g_malloc_n ((n_structs), sizeof (struct_type)))
|
#define g_try_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, try_realloc)
|
||||||
#define _G_RENEW(struct_type, mem, n_structs, _g_realloc_n) \
|
|
||||||
((struct_type *) _g_realloc_n ((mem), (n_structs), sizeof (struct_type)))
|
|
||||||
|
|
||||||
#define g_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, g_malloc_n)
|
|
||||||
#define g_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, g_malloc0_n)
|
|
||||||
#define g_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, g_realloc_n)
|
|
||||||
#define g_try_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, g_try_malloc_n)
|
|
||||||
#define g_try_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, g_try_malloc0_n)
|
|
||||||
#define g_try_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, g_try_realloc_n)
|
|
||||||
|
|
||||||
|
|
||||||
/* Memory allocation virtualization for debugging purposes
|
/* Memory allocation virtualization for debugging purposes
|
||||||
|
Loading…
Reference in New Issue
Block a user