From 33b9338fb03ff58960f4a2df339314846a3ae6e5 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 16 Nov 2024 07:46:24 +0000 Subject: [PATCH] converteroutputstream: Raise error for data at end When a conversion is finished, the code would return 0 from its write vfunc. This is disallowed by the API of g_output_stream_write() and causes g_output_stream_splice() as used by g_converter_convert_bytes() to turn into an infinite loop. Instead, raise a G_IO_ERROR_MESSAGE_TOO_LARGE error so that the calling code can decide how to deal with it. Testcase included. Closes #3532 --- gio/gconverteroutputstream.c | 6 +++++- gio/tests/converter.c | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/gio/gconverteroutputstream.c b/gio/gconverteroutputstream.c index 1877b0e4e..37dbadee4 100644 --- a/gio/gconverteroutputstream.c +++ b/gio/gconverteroutputstream.c @@ -422,7 +422,11 @@ write_internal (GOutputStream *stream, return -1; if (priv->finished) - return 0; + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_MESSAGE_TOO_LARGE, + _("Unexpected data after end of conversion")); + return -1; + } /* Convert as much as possible */ if (buffer_data_size (&priv->output_buffer) > 0) diff --git a/gio/tests/converter.c b/gio/tests/converter.c index 3795a5d09..db7e0c3af 100644 --- a/gio/tests/converter.c +++ b/gio/tests/converter.c @@ -23,6 +23,46 @@ #include #include +static void +test_extra_bytes_at_end (void) +{ + char data[1024]; + gsize size; + GBytes *bytes; + GConverter *converter; + GError *error = NULL; + GBytes *result; + + /* Create some simple data to encode */ + data[0] = 0; + bytes = g_bytes_new_static (data, 1); + + /* encode the data */ + converter = G_CONVERTER (g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, 9)); + result = g_converter_convert_bytes (converter, bytes, &error); + g_assert_no_error (error); + g_assert_nonnull (result); + g_bytes_unref (bytes); + g_clear_object (&converter); + + /* Append a 0 byte to the encoded data */ + size = g_bytes_get_size (result); + g_assert_cmpuint (size, <, G_N_ELEMENTS (data)); /* just to be very sure */ + memcpy (data, g_bytes_get_data (result, NULL), size); + data[size] = 0; + bytes = g_bytes_new_static (data, size + 1); + g_bytes_unref (result); + + /* Decompress the just compressed bytes with the extra 0 */ + converter = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP)); + result = g_converter_convert_bytes (converter, bytes, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_MESSAGE_TOO_LARGE); + g_assert_null (result); + g_clear_error (&error); + + g_object_unref (converter); + g_bytes_unref (bytes); +} static void test_convert_bytes (void) @@ -63,6 +103,7 @@ main (int argc, g_test_init (&argc, &argv, NULL); g_test_add_func ("/converter/bytes", test_convert_bytes); + g_test_add_func ("/converter/extra-bytes-at-end", test_extra_bytes_at_end); return g_test_run(); }