mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-09 10:20:07 +00:00
array: Don't overflow array size
Copy what gcc's libstdc++ does for vectors to avoid overflows: 1. Define a max size macro and assert against it Note that we don't assert but actually check, because this needs to abort even if assertions are disabled. 2. Don't do fancy math to compute new capacity. Just size *= 2 instead and be careful about overflow.
This commit is contained in:
parent
eb24e3548f
commit
4814c5f653
@ -41,8 +41,10 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||||
#define GDK_ARRAY_REAL_SIZE(_size) ((_size) + 1)
|
#define GDK_ARRAY_REAL_SIZE(_size) ((_size) + 1)
|
||||||
|
#define GDK_ARRAY_MAX_SIZE (G_MAXSIZE / sizeof (_T_) - 1)
|
||||||
#else
|
#else
|
||||||
#define GDK_ARRAY_REAL_SIZE(_size) (_size)
|
#define GDK_ARRAY_REAL_SIZE(_size) (_size)
|
||||||
|
#define GDK_ARRAY_MAX_SIZE (G_MAXSIZE / sizeof (_T_))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* make this readable */
|
/* make this readable */
|
||||||
@ -177,18 +179,23 @@ G_GNUC_UNUSED static inline void
|
|||||||
gdk_array(reserve) (GdkArray *self,
|
gdk_array(reserve) (GdkArray *self,
|
||||||
gsize n)
|
gsize n)
|
||||||
{
|
{
|
||||||
gsize new_size, size;
|
gsize new_capacity, size, capacity;
|
||||||
|
|
||||||
if (n <= gdk_array(get_capacity) (self))
|
if (G_UNLIKELY (n > GDK_ARRAY_MAX_SIZE))
|
||||||
return;
|
g_error ("requesting array size of %zu, but maximum size is %zu", n, GDK_ARRAY_MAX_SIZE);
|
||||||
|
|
||||||
|
capacity = gdk_array(get_capacity) (self);
|
||||||
|
if (n <= capacity)
|
||||||
|
return;
|
||||||
|
|
||||||
size = gdk_array(get_size) (self);
|
size = gdk_array(get_size) (self);
|
||||||
new_size = ((gsize) 1) << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
|
/* capacity * 2 can overflow, that's why we MAX() */
|
||||||
|
new_capacity = MAX (GDK_ARRAY_REAL_SIZE (n), capacity * 2);
|
||||||
|
|
||||||
#ifdef GDK_ARRAY_PREALLOC
|
#ifdef GDK_ARRAY_PREALLOC
|
||||||
if (self->start == self->preallocated)
|
if (self->start == self->preallocated)
|
||||||
{
|
{
|
||||||
self->start = g_new (_T_, new_size);
|
self->start = g_new (_T_, new_capacity);
|
||||||
memcpy (self->start, self->preallocated, sizeof (_T_) * GDK_ARRAY_REAL_SIZE (size));
|
memcpy (self->start, self->preallocated, sizeof (_T_) * GDK_ARRAY_REAL_SIZE (size));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -196,15 +203,15 @@ gdk_array(reserve) (GdkArray *self,
|
|||||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||||
if (self->start == NULL)
|
if (self->start == NULL)
|
||||||
{
|
{
|
||||||
self->start = g_new (_T_, new_size);
|
self->start = g_new (_T_, new_capacity);
|
||||||
*self->start = *(_T_[1]) { 0 };
|
*self->start = *(_T_[1]) { 0 };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
self->start = g_renew (_T_, self->start, new_size);
|
self->start = g_renew (_T_, self->start, new_capacity);
|
||||||
|
|
||||||
self->end = self->start + size;
|
self->end = self->start + size;
|
||||||
self->end_allocation = self->start + new_size;
|
self->end_allocation = self->start + new_capacity;
|
||||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||||
self->end_allocation--;
|
self->end_allocation--;
|
||||||
#endif
|
#endif
|
||||||
@ -312,6 +319,7 @@ gdk_array(get) (const GdkArray *self,
|
|||||||
#undef gdk_array_paste
|
#undef gdk_array_paste
|
||||||
#undef gdk_array
|
#undef gdk_array
|
||||||
#undef GDK_ARRAY_REAL_SIZE
|
#undef GDK_ARRAY_REAL_SIZE
|
||||||
|
#undef GDK_ARRAY_MAX_SIZE
|
||||||
|
|
||||||
#undef GDK_ARRAY_BY_VALUE
|
#undef GDK_ARRAY_BY_VALUE
|
||||||
#undef GDK_ARRAY_ELEMENT_TYPE
|
#undef GDK_ARRAY_ELEMENT_TYPE
|
||||||
|
@ -110,6 +110,7 @@ gdk_array(test_splice) (void)
|
|||||||
#undef gdk_array_paste
|
#undef gdk_array_paste
|
||||||
#undef gdk_array
|
#undef gdk_array
|
||||||
#undef GDK_ARRAY_REAL_SIZE
|
#undef GDK_ARRAY_REAL_SIZE
|
||||||
|
#undef GDK_ARRAY_MAX_SIZE
|
||||||
|
|
||||||
#undef GDK_ARRAY_ELEMENT_TYPE
|
#undef GDK_ARRAY_ELEMENT_TYPE
|
||||||
#undef GDK_ARRAY_NAME
|
#undef GDK_ARRAY_NAME
|
||||||
|
Loading…
Reference in New Issue
Block a user