mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-20 23:58:54 +02:00
Bug 608196 - Overflow-safe g_new family
New public API: g_malloc_n g_malloc0_n g_realloc_n g_try_malloc_n g_try_malloc0_n g_try_realloc_n
This commit is contained in:
@@ -853,6 +853,12 @@ g_realloc
|
|||||||
g_try_malloc
|
g_try_malloc
|
||||||
g_try_malloc0
|
g_try_malloc0
|
||||||
g_try_realloc
|
g_try_realloc
|
||||||
|
g_malloc_n
|
||||||
|
g_malloc0_n
|
||||||
|
g_realloc_n
|
||||||
|
g_try_malloc_n
|
||||||
|
g_try_malloc0_n
|
||||||
|
g_try_realloc_n
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
g_free
|
g_free
|
||||||
|
@@ -39,6 +39,7 @@ g_mem_set_vtable().
|
|||||||
Allocates @n_structs elements of type @struct_type.
|
Allocates @n_structs elements of type @struct_type.
|
||||||
The returned pointer is cast to a pointer to the given type.
|
The returned pointer is cast to a pointer to the given type.
|
||||||
If @n_structs is 0 it returns %NULL.
|
If @n_structs is 0 it returns %NULL.
|
||||||
|
Care is taken to avoid overflow when calculating the size of the allocated block.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Since the returned pointer is already casted to the right type,
|
Since the returned pointer is already casted to the right type,
|
||||||
@@ -56,6 +57,7 @@ so might hide memory allocation errors.
|
|||||||
Allocates @n_structs elements of type @struct_type, initialized to 0's.
|
Allocates @n_structs elements of type @struct_type, initialized to 0's.
|
||||||
The returned pointer is cast to a pointer to the given type.
|
The returned pointer is cast to a pointer to the given type.
|
||||||
If @n_structs is 0 it returns %NULL.
|
If @n_structs is 0 it returns %NULL.
|
||||||
|
Care is taken to avoid overflow when calculating the size of the allocated block.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Since the returned pointer is already casted to the right type,
|
Since the returned pointer is already casted to the right type,
|
||||||
@@ -73,6 +75,7 @@ so might hide memory allocation errors.
|
|||||||
Reallocates the memory pointed to by @mem, so that it now has space for
|
Reallocates the memory pointed to by @mem, so that it now has space for
|
||||||
@n_structs elements of type @struct_type. It returns the new address of
|
@n_structs elements of type @struct_type. It returns the new address of
|
||||||
the memory, which may have been moved.
|
the memory, which may have been moved.
|
||||||
|
Care is taken to avoid overflow when calculating the size of the allocated block.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@struct_type: the type of the elements to allocate
|
@struct_type: the type of the elements to allocate
|
||||||
@@ -86,7 +89,7 @@ the memory, which may have been moved.
|
|||||||
Attempts to allocate @n_structs elements of type @struct_type, and returns
|
Attempts to allocate @n_structs elements of type @struct_type, and returns
|
||||||
%NULL on failure. Contrast with g_new(), which aborts the program on failure.
|
%NULL on failure. Contrast with g_new(), which aborts the program on failure.
|
||||||
The returned pointer is cast to a pointer to the given type.
|
The returned pointer is cast to a pointer to the given type.
|
||||||
If @n_structs is 0 it returns %NULL.
|
The function returns %NULL when @n_structs is 0 of if an overflow occurs.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@struct_type: the type of the elements to allocate
|
@struct_type: the type of the elements to allocate
|
||||||
@@ -101,7 +104,7 @@ Attempts to allocate @n_structs elements of type @struct_type, initialized
|
|||||||
to 0's, and returns %NULL on failure. Contrast with g_new0(), which aborts
|
to 0's, and returns %NULL on failure. Contrast with g_new0(), which aborts
|
||||||
the program on failure.
|
the program on failure.
|
||||||
The returned pointer is cast to a pointer to the given type.
|
The returned pointer is cast to a pointer to the given type.
|
||||||
The function returns %NULL when @n_structs is 0.
|
The function returns %NULL when @n_structs is 0 of if an overflow occurs.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@struct_type: the type of the elements to allocate
|
@struct_type: the type of the elements to allocate
|
||||||
@@ -116,6 +119,7 @@ Attempts to reallocate the memory pointed to by @mem, so that it now has
|
|||||||
space for @n_structs elements of type @struct_type, and returns %NULL on
|
space for @n_structs elements of type @struct_type, and returns %NULL on
|
||||||
failure. Contrast with g_renew(), which aborts the program on failure.
|
failure. Contrast with g_renew(), which aborts the program on failure.
|
||||||
It returns the new address of the memory, which may have been moved.
|
It returns the new address of the memory, which may have been moved.
|
||||||
|
The function returns %NULL if an overflow occurs.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@struct_type: the type of the elements to allocate
|
@struct_type: the type of the elements to allocate
|
||||||
@@ -192,6 +196,80 @@ on failure. If @mem is %NULL, behaves the same as g_try_malloc().
|
|||||||
@Returns: the allocated memory, or %NULL.
|
@Returns: the allocated memory, or %NULL.
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ##### FUNCTION g_malloc_n ##### -->
|
||||||
|
<para>
|
||||||
|
This function is similar to g_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
but care is taken to detect possible overflow during multiplication.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
@n_blocks: the number of blocks to allocate
|
||||||
|
@n_block_bytes: the size of each block in bytes
|
||||||
|
@Returns: a pointer to the allocated memory
|
||||||
|
@Since: 2.24
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ##### FUNCTION g_malloc0_n ##### -->
|
||||||
|
<para>
|
||||||
|
This function is similar to g_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
but care is taken to detect possible overflow during multiplication.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
@n_blocks: the number of blocks to allocate
|
||||||
|
@n_block_bytes: the size of each block in bytes
|
||||||
|
@Returns: a pointer to the allocated memory
|
||||||
|
@Since: 2.24
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ##### FUNCTION g_realloc_n ##### -->
|
||||||
|
<para>
|
||||||
|
This function is similar to g_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
but care is taken to detect possible overflow during multiplication.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
@mem: the memory to reallocate
|
||||||
|
@n_blocks: the number of blocks to allocate
|
||||||
|
@n_block_bytes: the size of each block in bytes
|
||||||
|
@Returns: the new address of the allocated memory
|
||||||
|
@Since: 2.24
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ##### FUNCTION g_try_malloc_n ##### -->
|
||||||
|
<para>
|
||||||
|
This function is similar to g_try_malloc(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
but care is taken to detect possible overflow during multiplication.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
@n_blocks: the number of blocks to allocate
|
||||||
|
@n_block_bytes: the size of each block in bytes
|
||||||
|
@Returns: the allocated memory, or %NULL.
|
||||||
|
@Since: 2.24
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ##### FUNCTION g_try_malloc0_n ##### -->
|
||||||
|
<para>
|
||||||
|
This function is similar to g_try_malloc0(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
but care is taken to detect possible overflow during multiplication.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
@n_blocks: the number of blocks to allocate
|
||||||
|
@n_block_bytes: the size of each block in bytes
|
||||||
|
@Returns: the allocated memory, or %NULL
|
||||||
|
@Since: 2.24
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ##### FUNCTION g_try_realloc_n ##### -->
|
||||||
|
<para>
|
||||||
|
This function is similar to g_try_realloc(), allocating (@n_blocks * @n_block_bytes) bytes,
|
||||||
|
but care is taken to detect possible overflow during multiplication.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
@mem: previously-allocated memory, or %NULL.
|
||||||
|
@n_blocks: the number of blocks to allocate
|
||||||
|
@n_block_bytes: the size of each block in bytes
|
||||||
|
@Returns: the allocated memory, or %NULL.
|
||||||
|
@Since: 2.24
|
||||||
|
|
||||||
|
|
||||||
<!-- ##### FUNCTION g_free ##### -->
|
<!-- ##### FUNCTION g_free ##### -->
|
||||||
<para>
|
<para>
|
||||||
Frees the memory pointed to by @mem.
|
Frees the memory pointed to by @mem.
|
||||||
|
@@ -720,13 +720,19 @@ g_markup_collect_attributes
|
|||||||
g_free
|
g_free
|
||||||
g_malloc G_GNUC_MALLOC
|
g_malloc G_GNUC_MALLOC
|
||||||
g_malloc0 G_GNUC_MALLOC
|
g_malloc0 G_GNUC_MALLOC
|
||||||
|
g_malloc_n G_GNUC_MALLOC
|
||||||
|
g_malloc0_n G_GNUC_MALLOC
|
||||||
g_mem_is_system_malloc
|
g_mem_is_system_malloc
|
||||||
g_mem_profile
|
g_mem_profile
|
||||||
g_mem_set_vtable
|
g_mem_set_vtable
|
||||||
g_realloc
|
g_realloc
|
||||||
|
g_realloc_n
|
||||||
g_try_malloc G_GNUC_MALLOC
|
g_try_malloc G_GNUC_MALLOC
|
||||||
g_try_malloc0 G_GNUC_MALLOC
|
g_try_malloc0 G_GNUC_MALLOC
|
||||||
|
g_try_malloc_n G_GNUC_MALLOC
|
||||||
|
g_try_malloc0_n G_GNUC_MALLOC
|
||||||
g_try_realloc
|
g_try_realloc
|
||||||
|
g_try_realloc_n
|
||||||
#ifndef G_DISABLE_DEPRECATED
|
#ifndef G_DISABLE_DEPRECATED
|
||||||
g_allocator_free
|
g_allocator_free
|
||||||
g_allocator_new
|
g_allocator_new
|
||||||
|
95
glib/gmem.c
95
glib/gmem.c
@@ -203,11 +203,11 @@ g_try_malloc (gsize n_bytes)
|
|||||||
|
|
||||||
gpointer
|
gpointer
|
||||||
g_try_malloc0 (gsize n_bytes)
|
g_try_malloc0 (gsize n_bytes)
|
||||||
{
|
{
|
||||||
gpointer mem;
|
gpointer mem;
|
||||||
|
|
||||||
mem = g_try_malloc (n_bytes);
|
mem = g_try_malloc (n_bytes);
|
||||||
|
|
||||||
if (mem)
|
if (mem)
|
||||||
memset (mem, 0, n_bytes);
|
memset (mem, 0, n_bytes);
|
||||||
|
|
||||||
@@ -229,6 +229,97 @@ g_try_realloc (gpointer mem,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((a) > G_MAXSIZE / (b)))
|
||||||
|
|
||||||
|
#undef g_malloc_n
|
||||||
|
gpointer
|
||||||
|
g_malloc_n (gsize n_blocks,
|
||||||
|
gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (!g_mem_initialized))
|
||||||
|
g_mem_init_nomessage();
|
||||||
|
|
||||||
|
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
||||||
|
G_STRLOC, n_blocks, n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_malloc (n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef g_malloc0_n
|
||||||
|
gpointer
|
||||||
|
g_malloc0_n (gsize n_blocks,
|
||||||
|
gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (!g_mem_initialized))
|
||||||
|
g_mem_init_nomessage();
|
||||||
|
|
||||||
|
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
||||||
|
G_STRLOC, n_blocks, n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_malloc0 (n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef g_realloc_n
|
||||||
|
gpointer
|
||||||
|
g_realloc_n (gpointer mem,
|
||||||
|
gsize n_blocks,
|
||||||
|
gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (!g_mem_initialized))
|
||||||
|
g_mem_init_nomessage();
|
||||||
|
|
||||||
|
g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
|
||||||
|
G_STRLOC, n_blocks, n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_realloc (mem, n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef g_try_malloc_n
|
||||||
|
gpointer
|
||||||
|
g_try_malloc_n (gsize n_blocks,
|
||||||
|
gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_try_malloc (n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef g_try_malloc0_n
|
||||||
|
gpointer
|
||||||
|
g_try_malloc0_n (gsize n_blocks,
|
||||||
|
gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_try_malloc0 (n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef g_try_realloc_n
|
||||||
|
gpointer
|
||||||
|
g_try_realloc_n (gpointer mem,
|
||||||
|
gsize n_blocks,
|
||||||
|
gsize n_block_bytes)
|
||||||
|
{
|
||||||
|
if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_try_realloc (mem, n_blocks * n_block_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
fallback_calloc (gsize n_blocks,
|
fallback_calloc (gsize n_blocks,
|
||||||
gsize n_block_bytes)
|
gsize n_block_bytes)
|
||||||
|
92
glib/gmem.h
92
glib/gmem.h
@@ -48,40 +48,102 @@ typedef struct _GMemVTable GMemVTable;
|
|||||||
|
|
||||||
/* Memory allocation functions
|
/* Memory allocation functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void g_free (gpointer mem);
|
||||||
|
|
||||||
gpointer g_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
gpointer g_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||||
gpointer g_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
gpointer g_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||||
gpointer g_realloc (gpointer mem,
|
gpointer g_realloc (gpointer mem,
|
||||||
gsize n_bytes) G_GNUC_WARN_UNUSED_RESULT;
|
gsize n_bytes) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
void g_free (gpointer mem);
|
|
||||||
gpointer g_try_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
gpointer g_try_malloc (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||||
gpointer g_try_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
gpointer g_try_malloc0 (gsize n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
|
||||||
gpointer g_try_realloc (gpointer mem,
|
gpointer g_try_realloc (gpointer mem,
|
||||||
gsize n_bytes) G_GNUC_WARN_UNUSED_RESULT;
|
gsize n_bytes) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
gpointer g_malloc_n (gsize n_blocks,
|
||||||
|
gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
|
||||||
|
gpointer g_malloc0_n (gsize n_blocks,
|
||||||
|
gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
|
||||||
|
gpointer g_realloc_n (gpointer mem,
|
||||||
|
gsize n_blocks,
|
||||||
|
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
gpointer g_try_malloc_n (gsize n_blocks,
|
||||||
|
gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
|
||||||
|
gpointer g_try_malloc0_n (gsize n_blocks,
|
||||||
|
gsize n_block_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE2(1,2);
|
||||||
|
gpointer g_try_realloc_n (gpointer mem,
|
||||||
|
gsize n_blocks,
|
||||||
|
gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
|
||||||
|
/* avoid the overflow check 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); \
|
||||||
|
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); \
|
||||||
|
else \
|
||||||
|
__p = func_n (__a, __b); \
|
||||||
|
__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); \
|
||||||
|
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); \
|
||||||
|
else \
|
||||||
|
__p = func_n (__p, __a, __b); \
|
||||||
|
__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
|
||||||
|
|
||||||
|
|
||||||
/* Convenience memory allocators
|
/* Convenience memory allocators
|
||||||
*/
|
*/
|
||||||
#define g_new(struct_type, n_structs) \
|
|
||||||
((struct_type *) g_malloc (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
|
|
||||||
#define g_new0(struct_type, n_structs) \
|
|
||||||
((struct_type *) g_malloc0 (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
|
|
||||||
#define g_renew(struct_type, mem, n_structs) \
|
|
||||||
((struct_type *) g_realloc ((mem), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
|
|
||||||
|
|
||||||
#define g_try_new(struct_type, n_structs) \
|
#define _G_NEW(struct_type, n_structs, _g_malloc_n) \
|
||||||
((struct_type *) g_try_malloc (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
|
((struct_type *) _g_malloc_n ((n_structs), sizeof (struct_type)))
|
||||||
#define g_try_new0(struct_type, n_structs) \
|
#define _G_RENEW(struct_type, mem, n_structs, _g_realloc_n) \
|
||||||
((struct_type *) g_try_malloc0 (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
|
((struct_type *) _g_realloc_n ((mem), (n_structs), sizeof (struct_type)))
|
||||||
#define g_try_renew(struct_type, mem, n_structs) \
|
|
||||||
((struct_type *) g_try_realloc ((mem), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
|
#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
|
||||||
* g_mem_set_vtable() has to be the very first GLib function called
|
* g_mem_set_vtable() has to be the very first GLib function called
|
||||||
* if being used
|
* if being used
|
||||||
*/
|
*/
|
||||||
struct _GMemVTable
|
struct _GMemVTable {
|
||||||
{
|
|
||||||
gpointer (*malloc) (gsize n_bytes);
|
gpointer (*malloc) (gsize n_bytes);
|
||||||
gpointer (*realloc) (gpointer mem,
|
gpointer (*realloc) (gpointer mem,
|
||||||
gsize n_bytes);
|
gsize n_bytes);
|
||||||
|
@@ -50,6 +50,9 @@ hostutils_LDADD = $(progs_ldadd)
|
|||||||
TEST_PROGS += gvariant
|
TEST_PROGS += gvariant
|
||||||
gvariant_LDADD = $(progs_ldadd)
|
gvariant_LDADD = $(progs_ldadd)
|
||||||
|
|
||||||
|
TEST_PROGS += mem-overflow
|
||||||
|
mem_overflow_LDADD = $(progs_ldadd)
|
||||||
|
|
||||||
if OS_UNIX
|
if OS_UNIX
|
||||||
|
|
||||||
# some testing of gtester funcitonality
|
# some testing of gtester funcitonality
|
||||||
|
108
glib/tests/mem-overflow.c
Normal file
108
glib/tests/mem-overflow.c
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/* Unit tests for g
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This work is provided "as is"; redistribution and modification
|
||||||
|
* in whole or in part, in any medium, physical or electronic is
|
||||||
|
* permitted without restriction.
|
||||||
|
*
|
||||||
|
* This work is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* In no event shall the authors or contributors be liable for any
|
||||||
|
* direct, indirect, incidental, special, exemplary, or consequential
|
||||||
|
* damages (including, but not limited to, procurement of substitute
|
||||||
|
* goods or services; loss of use, data, or profits; or business
|
||||||
|
* interruption) however caused and on any theory of liability, whether
|
||||||
|
* in contract, strict liability, or tort (including negligence or
|
||||||
|
* otherwise) arising in any way out of the use of this software, even
|
||||||
|
* if advised of the possibility of such damage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "glib.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
mem_overflow (void)
|
||||||
|
{
|
||||||
|
gsize a = G_MAXSIZE / 10 + 10;
|
||||||
|
gsize b = 10;
|
||||||
|
gpointer p, q;
|
||||||
|
typedef char X[10];
|
||||||
|
|
||||||
|
#define CHECK_PASS(P) p = (P); g_assert (p == NULL);
|
||||||
|
#define CHECK_FAIL(P) p = (P); g_assert (p != NULL);
|
||||||
|
|
||||||
|
CHECK_PASS (g_try_malloc_n (a, a));
|
||||||
|
CHECK_PASS (g_try_malloc_n (a, b));
|
||||||
|
CHECK_PASS (g_try_malloc_n (b, a));
|
||||||
|
CHECK_FAIL (g_try_malloc_n (b, b));
|
||||||
|
|
||||||
|
CHECK_PASS (g_try_malloc0_n (a, a));
|
||||||
|
CHECK_PASS (g_try_malloc0_n (a, b));
|
||||||
|
CHECK_PASS (g_try_malloc0_n (b, a));
|
||||||
|
CHECK_FAIL (g_try_malloc0_n (b, b));
|
||||||
|
|
||||||
|
q = g_malloc (1);
|
||||||
|
CHECK_PASS (g_try_realloc_n (q, a, a));
|
||||||
|
CHECK_PASS (g_try_realloc_n (q, a, b));
|
||||||
|
CHECK_PASS (g_try_realloc_n (q, b, a));
|
||||||
|
CHECK_FAIL (g_try_realloc_n (q, b, b));
|
||||||
|
free (p);
|
||||||
|
|
||||||
|
CHECK_PASS (g_try_new (X, a));
|
||||||
|
CHECK_FAIL (g_try_new (X, b));
|
||||||
|
|
||||||
|
CHECK_PASS (g_try_new0 (X, a));
|
||||||
|
CHECK_FAIL (g_try_new0 (X, b));
|
||||||
|
|
||||||
|
q = g_try_malloc (1);
|
||||||
|
CHECK_PASS (g_try_renew (X, q, a));
|
||||||
|
CHECK_FAIL (g_try_renew (X, q, b));
|
||||||
|
free (p);
|
||||||
|
|
||||||
|
#undef CHECK_EQ
|
||||||
|
#undef CHECK_NEQ
|
||||||
|
|
||||||
|
#define CHECK_FAIL(P) if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) { p = (P); exit (0); } g_test_trap_assert_failed();
|
||||||
|
#define CHECK_PASS(P) if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) { p = (P); exit (0); } g_test_trap_assert_passed();
|
||||||
|
|
||||||
|
CHECK_FAIL (g_malloc_n (a, a));
|
||||||
|
CHECK_FAIL (g_malloc_n (a, b));
|
||||||
|
CHECK_FAIL (g_malloc_n (b, a));
|
||||||
|
CHECK_PASS (g_malloc_n (b, b));
|
||||||
|
|
||||||
|
CHECK_FAIL (g_malloc0_n (a, a));
|
||||||
|
CHECK_FAIL (g_malloc0_n (a, b));
|
||||||
|
CHECK_FAIL (g_malloc0_n (b, a));
|
||||||
|
CHECK_PASS (g_malloc0_n (b, b));
|
||||||
|
|
||||||
|
q = g_malloc (1);
|
||||||
|
CHECK_FAIL (g_realloc_n (q, a, a));
|
||||||
|
CHECK_FAIL (g_realloc_n (q, a, b));
|
||||||
|
CHECK_FAIL (g_realloc_n (q, b, a));
|
||||||
|
CHECK_PASS (g_realloc_n (q, b, b));
|
||||||
|
free (q);
|
||||||
|
|
||||||
|
CHECK_FAIL (g_new (X, a));
|
||||||
|
CHECK_PASS (g_new (X, b));
|
||||||
|
|
||||||
|
CHECK_FAIL (g_new0 (X, a));
|
||||||
|
CHECK_PASS (g_new0 (X, b));
|
||||||
|
|
||||||
|
q = g_malloc (1);
|
||||||
|
CHECK_FAIL (g_renew (X, q, a));
|
||||||
|
CHECK_PASS (g_renew (X, q, b));
|
||||||
|
free (q);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
|
g_test_add_func ("/mem/overflow", mem_overflow);
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
/* Unit tests for gstring
|
/* Unit tests for gprintf
|
||||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
*
|
*
|
||||||
* This work is provided "as is"; redistribution and modification
|
* This work is provided "as is"; redistribution and modification
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* Unit tests for gstring
|
/* Unit tests for grand
|
||||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
*
|
*
|
||||||
* This work is provided "as is"; redistribution and modification
|
* This work is provided "as is"; redistribution and modification
|
||||||
|
Reference in New Issue
Block a user