[glib] GResource – Create an internal copy of the GBytes if it is not pointer aligned



commit 7b60708204354da877f7eda5150631223bba42f2
Author: Sebastian Dröge <sebastian centricular com>
Date:   Mon Nov 13 11:47:06 2017 +0100

    GResource – Create an internal copy of the GBytes if it is not pointer aligned
    
    https://bugzilla.gnome.org/show_bug.cgi?id=790030

 gio/gresource.c       |   14 +++++++++++++-
 gio/tests/resources.c |   31 +++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletions(-)
---
diff --git a/gio/gresource.c b/gio/gresource.c
index ed0e474..f38de86 100644
--- a/gio/gresource.c
+++ b/gio/gresource.c
@@ -525,7 +525,8 @@ g_resource_new_from_table (GvdbTable *table)
  * to register it with g_resources_register().
  *
  * Note: @data must be backed by memory that is at least pointer aligned.
- * Otherwise this function will fail and exit the process.
+ * Otherwise this function will internally create a copy of the memory since
+ * GLib 2.56, or in older versions fail and exit the process.
  *
  * Returns: (transfer full): a new #GResource, or %NULL on error
  *
@@ -536,6 +537,14 @@ g_resource_new_from_data (GBytes  *data,
                           GError **error)
 {
   GvdbTable *table;
+  gboolean unref_data = FALSE;
+
+  if (((guintptr) g_bytes_get_data (data, NULL)) % sizeof (gpointer) != 0)
+    {
+      data = g_bytes_new (g_bytes_get_data (data, NULL),
+                          g_bytes_get_size (data));
+      unref_data = TRUE;
+    }
 
   table = gvdb_table_new_from_data (g_bytes_get_data (data, NULL),
                                     g_bytes_get_size (data),
@@ -545,6 +554,9 @@ g_resource_new_from_data (GBytes  *data,
                                     (GDestroyNotify)g_bytes_unref,
                                     error);
 
+  if (unref_data)
+    g_bytes_unref (data);
+
   if (table == NULL)
     return NULL;
 
diff --git a/gio/tests/resources.c b/gio/tests/resources.c
index b002325..22ce7c6 100644
--- a/gio/tests/resources.c
+++ b/gio/tests/resources.c
@@ -181,6 +181,36 @@ test_resource_data (void)
 }
 
 static void
+test_resource_data_unaligned (void)
+{
+  GResource *resource;
+  GError *error = NULL;
+  gboolean loaded_file;
+  char *content, *content_copy;
+  gsize content_size;
+  GBytes *data;
+
+  loaded_file = g_file_get_contents (g_test_get_filename (G_TEST_BUILT, "test.gresource", NULL),
+                                     &content, &content_size, NULL);
+  g_assert (loaded_file);
+
+  content_copy = g_new (char, content_size + 1);
+  memcpy (content_copy + 1, content, content_size);
+
+  data = g_bytes_new_with_free_func (content_copy + 1, content_size,
+                                     (GDestroyNotify) g_free, content_copy);
+  g_free (content);
+  resource = g_resource_new_from_data (data, &error);
+  g_bytes_unref (data);
+  g_assert (resource != NULL);
+  g_assert_no_error (error);
+
+  test_resource (resource);
+
+  g_resource_unref (resource);
+}
+
+static void
 test_resource_registered (void)
 {
   GResource *resource;
@@ -644,6 +674,7 @@ main (int   argc,
 
   g_test_add_func ("/resource/file", test_resource_file);
   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/registered", test_resource_registered);
   g_test_add_func ("/resource/manual", test_resource_manual);
   g_test_add_func ("/resource/manual2", test_resource_manual2);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]