Merge branch '3465-gresource-error-allocations' into 'main'

gresource: Reduce allocations in g_resources_*() functions

Closes #3465

See merge request GNOME/glib!4242
This commit is contained in:
Philip Withnall
2024-09-17 13:34:06 +00:00
4 changed files with 205 additions and 71 deletions

View File

@@ -401,6 +401,55 @@ test_resource_data_empty (void)
g_clear_error (&local_error);
}
static void
test_resource_data_corrupt_compression (void)
{
GFile *resource_file = NULL;
GBytes *resource_bytes = NULL, *corrupt_bytes = NULL, *data_bytes = NULL;
guint8 *corrupt_data = NULL;
GResource *resource = NULL;
GError *local_error = NULL;
g_test_summary ("Test error handling for corrupt GResource files (specifically, corrupt zlib compression).");
resource_file = g_file_new_for_path (g_test_get_filename (G_TEST_BUILT, "test6.gresource", NULL));
resource_bytes = g_file_load_bytes (resource_file, NULL, NULL, &local_error);
g_assert_no_error (local_error);
g_clear_object (&resource_file);
/* Test loading the resource normally, to check it works. */
resource = g_resource_new_from_data (resource_bytes, &local_error);
g_assert_no_error (local_error);
data_bytes = g_resource_lookup_data (resource, "/test-corrupt-compression.txt",
G_RESOURCE_LOOKUP_FLAGS_NONE, &local_error);
g_assert_no_error (local_error);
g_assert_nonnull (data_bytes);
g_clear_pointer (&data_bytes, g_bytes_unref);
g_clear_pointer (&resource, g_resource_unref);
/* Modify the data to zero out bytes 0x90 to 0x100. These are comfortably
* within the compressed file data, so should break that while not breaking
* the GVDB header. */
corrupt_data = g_memdup2 (g_bytes_get_data (resource_bytes, NULL), g_bytes_get_size (resource_bytes));
memset (corrupt_data + 0x90, 0, 0x10);
corrupt_bytes = g_bytes_new_take (g_steal_pointer (&corrupt_data), g_bytes_get_size (resource_bytes));
resource = g_resource_new_from_data (corrupt_bytes, &local_error);
g_assert_no_error (local_error);
g_bytes_unref (corrupt_bytes);
data_bytes = g_resource_lookup_data (resource, "/test-corrupt-compression.txt",
G_RESOURCE_LOOKUP_FLAGS_NONE, &local_error);
g_assert_error (local_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_INTERNAL);
g_assert_null (data_bytes);
g_clear_error (&local_error);
g_clear_pointer (&resource_bytes, g_bytes_unref);
g_clear_pointer (&resource, g_resource_unref);
}
static void
test_resource_registered (void)
{
@@ -553,6 +602,20 @@ test_resource_registered (void)
g_assert_false (found);
g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
g_clear_error (&error);
data = g_resources_lookup_data ("/test1.txt",
G_RESOURCE_LOOKUP_FLAGS_NONE,
&error);
g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
g_assert_null (data);
g_clear_error (&error);
in = g_resources_open_stream ("/test1.txt",
G_RESOURCE_LOOKUP_FLAGS_NONE,
&error);
g_assert_error (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND);
g_assert_null (in);
g_clear_error (&error);
}
static void
@@ -1021,26 +1084,65 @@ test_overlay (void)
{
if (g_test_subprocess ())
{
GError *error = NULL;
gboolean res;
gsize size;
char *overlay;
char *path;
GError *error = NULL;
gboolean res;
gsize size;
char *overlay;
char *path;
GInputStream *in = NULL;
char buffer[128];
GBytes *data = NULL;
char *expected_overlay_data = NULL;
size_t expected_overlay_size = 0;
path = g_test_build_filename (G_TEST_DIST, "test1.overlay", NULL);
overlay = g_strconcat ("/auto_loaded/test1.txt=", path, NULL);
path = g_test_build_filename (G_TEST_DIST, "test1.overlay", NULL);
res = g_file_get_contents (path, &expected_overlay_data, &expected_overlay_size, NULL);
g_assert (res);
g_setenv ("G_RESOURCE_OVERLAYS", overlay, TRUE);
res = g_resources_get_info ("/auto_loaded/test1.txt", 0, &size, NULL, &error);
g_assert_true (res);
g_assert_no_error (error);
/* test1.txt is 6 bytes, test1.overlay is 23 */
g_assert_cmpint (size, ==, 23);
overlay = g_strconcat ("/auto_loaded/test1.txt=", path, NULL);
g_setenv ("G_RESOURCE_OVERLAYS", overlay, TRUE);
g_free (overlay);
g_free (path);
/* Test getting its info. */
res = g_resources_get_info ("/auto_loaded/test1.txt", 0, &size, NULL, &error);
g_assert_true (res);
g_assert_no_error (error);
/* test1.txt is 6 bytes, test1.overlay is 23 */
g_assert_cmpuint (size, ==, expected_overlay_size);
return;
/* Test it as a stream too. */
in = g_resources_open_stream ("/auto_loaded/test1.txt",
G_RESOURCE_LOOKUP_FLAGS_NONE,
&error);
g_assert_no_error (error);
g_assert_nonnull (in);
res = g_input_stream_read_all (in, buffer, sizeof (buffer) - 1,
&size,
NULL, &error);
g_assert_no_error (error);
g_assert_true (res);
g_assert_cmpuint (size, ==, expected_overlay_size);
g_input_stream_close (in, NULL, &error);
g_assert_no_error (error);
g_clear_object (&in);
/* Test data lookup. */
data = g_resources_lookup_data ("/auto_loaded/test1.txt",
G_RESOURCE_LOOKUP_FLAGS_NONE,
&error);
g_assert_nonnull (data);
g_assert_no_error (error);
size = g_bytes_get_size (data);
g_assert_cmpuint (size, ==, expected_overlay_size);
g_assert_cmpstr (g_bytes_get_data (data, NULL), ==, expected_overlay_data);
g_bytes_unref (data);
g_free (overlay);
g_free (path);
g_free (expected_overlay_data);
return;
}
g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDERR);
g_test_trap_assert_passed ();
@@ -1085,6 +1187,7 @@ main (int argc,
g_test_add_func ("/resource/data", test_resource_data);
g_test_add_func ("/resource/data_unaligned", test_resource_data_unaligned);
g_test_add_func ("/resource/data-corrupt", test_resource_data_corrupt);
g_test_add_func ("/resource/data-corrupt-compression", test_resource_data_corrupt_compression);
g_test_add_func ("/resource/data-empty", test_resource_data_empty);
g_test_add_func ("/resource/registered", test_resource_registered);
g_test_add_func ("/resource/manual", test_resource_manual);