From a1b9743e1816c5269029e8ae2e21e8950c411f5c Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Sat, 6 Mar 2010 23:21:27 -0500 Subject: [PATCH] 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. --- glib/gmem.c | 8 ------ glib/gmem.h | 83 ++++++++++++++++++++++++++----------------------------------- 2 files changed, 35 insertions(+), 56 deletions(-) diff --git a/glib/gmem.c b/glib/gmem.c index 76cfad1..36e04dd 100644 --- a/glib/gmem.c +++ b/glib/gmem.c @@ -37,14 +37,6 @@ #include "glib.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" #define MEM_PROFILE_TABLE_SIZE 4096 diff --git a/glib/gmem.h b/glib/gmem.h index fc5d95d..78950d5 100644 --- a/glib/gmem.h +++ b/glib/gmem.h @@ -76,67 +76,54 @@ gpointer g_try_realloc_n (gpointer mem, gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT; -/* avoid the overflow check if we can determine at compile-time that no - * overflow happens. */ +/* Optimise: avoid the call to the (slower) _n function if we can + * determine at compile-time that no overflow happens. + */ #if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__) -# define _G_MALLOC_N(n_blocks, n_block_bytes, func_1, func_n) \ - (__extension__ ({ \ - gsize __a = (gsize) (n_blocks); \ - gsize __b = (gsize) (n_block_bytes); \ +# define _G_NEW(struct_type, n_structs, func) \ + (struct_type *) (__extension__ ({ \ + gsize __n = (gsize) (n_structs); \ gpointer __p; \ - if (__builtin_constant_p (__a) && __a == 1) \ - __p = func_1 (__b); \ - else if (__builtin_constant_p (__b) && __b == 1) \ - __p = func_1 (__a); \ - else if (__builtin_constant_p (__a) && \ - __builtin_constant_p (__b) && \ - __a <= G_MAXSIZE / __b) \ - __p = func_1 (__a * __b); \ + if (sizeof (struct_type) == 1) \ + __p = g_##func (__n); \ + else if (__builtin_constant_p (__n) && \ + __n <= G_MAXSIZE / sizeof (struct_type)) \ + __p = g_##func (__n * sizeof (struct_type)); \ else \ - __p = func_n (__a, __b); \ + __p = g_##func##_n (__n, sizeof (struct_type)); \ __p; \ })) -# define _G_REALLOC_N(mem, n_blocks, n_block_bytes, func_1, func_n) \ - (__extension__ ({ \ - gsize __a = (gsize) (n_blocks); \ - gsize __b = (gsize) (n_block_bytes); \ +# define _G_RENEW(struct_type, mem, n_structs, func) \ + (struct_type *) (__extension__ ({ \ + gsize __n = (gsize) (n_structs); \ gpointer __p = (gpointer) (mem); \ - if (__builtin_constant_p (__a) && __a == 1) \ - __p = func_1 (__p, __b); \ - else if (__builtin_constant_p (__b) && __b == 1) \ - __p = func_1 (__p, __a); \ - else if (__builtin_constant_p (__a) && \ - __builtin_constant_p (__b) && \ - __a <= G_MAXSIZE / __b) \ - __p = func_1 (__p, __a * __b); \ + if (sizeof (struct_type) == 1) \ + __p = g_##func (__p, __n); \ + else if (__builtin_constant_p (__n) && \ + __n <= G_MAXSIZE / sizeof (struct_type)) \ + __p = g_##func (__p, __n * sizeof (struct_type)); \ else \ - __p = func_n (__p, __a, __b); \ + __p = g_##func##_n (__p, __n, sizeof (struct_type));\ __p; \ })) -# define g_malloc_n(n_blocks,n_block_bytes) _G_MALLOC_N (n_blocks, n_block_bytes, g_malloc, g_malloc_n) -# 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) -# 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_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) -#endif +#else +/* Unoptimised version: always call the _n() function. */ -/* Convenience memory allocators - */ +#define _G_NEW(struct_type, n_structs, func) \ + ((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 -#define _G_NEW(struct_type, n_structs, _g_malloc_n) \ - ((struct_type *) _g_malloc_n ((n_structs), sizeof (struct_type))) -#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) +#define g_new(struct_type, n_structs) _G_NEW (struct_type, n_structs, malloc) +#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_try_new0(struct_type, n_structs) _G_NEW (struct_type, n_structs, try_malloc0) +#define g_try_renew(struct_type, mem, n_structs) _G_RENEW (struct_type, mem, n_structs, try_realloc) /* Memory allocation virtualization for debugging purposes -- 2.7.4