From 97ad335e4b4f2e366bf3c642d6cdbbc5a117f5bb Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Thu, 14 Jan 2021 20:07:47 +0000 Subject: [PATCH] Fix OOM when using large ArchiveSizeMax values Read from the file descriptor in 32kB chunks rather than allocating a huge buffer upfront. --- libfwupdplugin/fu-common.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/libfwupdplugin/fu-common.c b/libfwupdplugin/fu-common.c index 5ca316499..d2adb1410 100644 --- a/libfwupdplugin/fu-common.c +++ b/libfwupdplugin/fu-common.c @@ -269,7 +269,8 @@ GBytes * fu_common_get_contents_fd (gint fd, gsize count, GError **error) { #ifdef HAVE_GIO_UNIX - g_autoptr(GBytes) blob = NULL; + guint8 tmp[0x8000] = { 0x0 }; + g_autoptr(GByteArray) buf = g_byte_array_new (); g_autoptr(GError) error_local = NULL; g_autoptr(GInputStream) stream = NULL; @@ -287,15 +288,31 @@ fu_common_get_contents_fd (gint fd, gsize count, GError **error) /* read the entire fd to a data blob */ stream = g_unix_input_stream_new (fd, TRUE); - blob = g_input_stream_read_bytes (stream, count, NULL, &error_local); - if (blob == NULL) { - g_set_error_literal (error, + + /* read from stream in 32kB chunks */ + while (TRUE) { + gssize sz; + sz = g_input_stream_read (stream, tmp, sizeof(tmp), NULL, &error_local); + if (sz == 0) + break; + if (sz < 0) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INVALID_FILE, + error_local->message); + return NULL; + } + g_byte_array_append (buf, tmp, sz); + if (buf->len > count) { + g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, - error_local->message); - return NULL; + "cannot read from fd: 0x%x > 0x%x", + buf->len, (guint) count); + return NULL; + } } - return g_steal_pointer (&blob); + return g_byte_array_free_to_bytes (g_steal_pointer (&buf)); #else g_set_error_literal (error, FWUPD_ERROR,