Fix OOM when using large ArchiveSizeMax values

Read from the file descriptor in 32kB chunks rather than allocating a huge
buffer upfront.
This commit is contained in:
Richard Hughes 2021-01-14 20:07:47 +00:00
parent 60441f96a5
commit 97ad335e4b

View File

@ -269,7 +269,8 @@ GBytes *
fu_common_get_contents_fd (gint fd, gsize count, GError **error) fu_common_get_contents_fd (gint fd, gsize count, GError **error)
{ {
#ifdef HAVE_GIO_UNIX #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(GError) error_local = NULL;
g_autoptr(GInputStream) stream = 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 */ /* read the entire fd to a data blob */
stream = g_unix_input_stream_new (fd, TRUE); stream = g_unix_input_stream_new (fd, TRUE);
blob = g_input_stream_read_bytes (stream, count, NULL, &error_local);
if (blob == NULL) { /* read from stream in 32kB chunks */
g_set_error_literal (error, 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,
FWUPD_ERROR_INVALID_FILE, FWUPD_ERROR_INVALID_FILE,
error_local->message); "cannot read from fd: 0x%x > 0x%x",
return NULL; buf->len, (guint) count);
return NULL;
}
} }
return g_steal_pointer (&blob); return g_byte_array_free_to_bytes (g_steal_pointer (&buf));
#else #else
g_set_error_literal (error, g_set_error_literal (error,
FWUPD_ERROR, FWUPD_ERROR,