diff options
author | Ross Lagerwall <rosslagerwall@gmail.com> | 2014-10-29 22:05:32 +0000 |
---|---|---|
committer | Ross Lagerwall <rosslagerwall@gmail.com> | 2014-10-30 20:15:47 +0000 |
commit | 5a6f13d16f38ea0a6c9d48332b7e3932b7f3b7d4 (patch) | |
tree | 78b7d8404dcc02339d6630f4767d987e85e3275e | |
parent | b3e3ed73864143e732c4d65441eaec086a3ab83e (diff) | |
download | glib-5a6f13d16f38ea0a6c9d48332b7e3932b7f3b7d4.tar.gz |
gio: Prevent hang writing to a large GMemoryOutputStream
Fix a hang due to overflow by using unsigned numbers and explicitly
checking if the number overflows to zero. This also fixes the previous
logic which assigned an int which may be negative to an unsigned number
resulting in sign extension and strange results.
Use gsize rather than int to allow for large streams on 64 bit machines.
https://bugzilla.gnome.org/show_bug.cgi?id=727988
-rw-r--r-- | gio/gmemoryoutputstream.c | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/gio/gmemoryoutputstream.c b/gio/gmemoryoutputstream.c index 9c83b7db6..a89701d60 100644 --- a/gio/gmemoryoutputstream.c +++ b/gio/gmemoryoutputstream.c @@ -594,12 +594,12 @@ array_resize (GMemoryOutputStream *ostream, return TRUE; } -static gint -g_nearest_pow (gint num) +static gsize +g_nearest_pow (gsize num) { - gint n = 1; + gsize n = 1; - while (n < num) + while (n < num && n > 0) n <<= 1; return n; @@ -639,12 +639,10 @@ g_memory_output_stream_write (GOutputStream *stream, * much memory. */ new_size = g_nearest_pow (priv->pos + count); - /* Check for overflow again. We have only checked if - pos + count > G_MAXSIZE, but it only catches the case of writing - more than 4GiB total on a 32-bit system. There's still the problem - of g_nearest_pow overflowing above 0x7fffffff, so we're - effectively limited to 2GiB. */ - if (new_size < priv->len) + /* Check for overflow again. We have checked if + pos + count > G_MAXSIZE, but now check if g_nearest_pow () has + overflowed */ + if (new_size == 0) goto overflow; new_size = MAX (new_size, MIN_ARRAY_SIZE); |