summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoss Lagerwall <rosslagerwall@gmail.com>2014-10-29 22:12:39 +0000
committerRoss Lagerwall <rosslagerwall@gmail.com>2014-10-30 20:15:47 +0000
commit226c292b6ab95014648e9fc0a082bb6c26eeccc8 (patch)
tree32e6d2ae33ba87e6d8c11888ee95d54867ec2dac
parent5a6f13d16f38ea0a6c9d48332b7e3932b7f3b7d4 (diff)
downloadglib-226c292b6ab95014648e9fc0a082bb6c26eeccc8.tar.gz
gio: Prevent hang writing to a large GMemoryBuffer
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 buffers on 64 bit machines. https://bugzilla.gnome.org/show_bug.cgi?id=727988
-rw-r--r--gio/gdbusmessage.c18
1 files changed, 8 insertions, 10 deletions
diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c
index 5ad86940f..766609ec8 100644
--- a/gio/gdbusmessage.c
+++ b/gio/gdbusmessage.c
@@ -204,12 +204,12 @@ g_memory_buffer_read_uint64 (GMemoryBuffer *mbuf)
#define MIN_ARRAY_SIZE 128
-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;
@@ -261,12 +261,10 @@ g_memory_buffer_write (GMemoryBuffer *mbuf,
TODO: This wastes a lot of memory at large buffer sizes.
Figure out a more rational allocation strategy. */
new_size = g_nearest_pow (mbuf->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 < mbuf->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)
return FALSE;
new_size = MAX (new_size, MIN_ARRAY_SIZE);