diff --git a/0001-girepository-Actually-verify-header-of-loaded-typeli.patch b/0001-girepository-Actually-verify-header-of-loaded-typeli.patch new file mode 100644 index 0000000..fd67dbc --- /dev/null +++ b/0001-girepository-Actually-verify-header-of-loaded-typeli.patch @@ -0,0 +1,409 @@ +From 05ffd85793207a40264a701de609614ba6e32d44 Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Wed, 14 Jul 2010 11:59:11 -0400 +Subject: [PATCH] [girepository] Actually verify header of loaded typelibs in g_irepository_require + +Take a GError * for typelib loading code, validate the header. This +fixes bizarre errors from gjs where g_irepository_require would happily +load old typelibs. +--- + girepository/girepository.c | 4 +- + girepository/girmodule.c | 8 +++- + girepository/gitypelib.c | 71 +++++++++++++++++++++++-------- + girepository/gitypelib.h | 13 ++++-- + tools/compiler.c | 4 +- + tools/generate.c | 96 ++++++------------------------------------- + 6 files changed, 87 insertions(+), 109 deletions(-) + +diff --git a/girepository/girepository.c b/girepository/girepository.c +index ba6756e..ef3d6d2 100644 +--- a/girepository/girepository.c ++++ b/girepository/girepository.c +@@ -1221,7 +1221,9 @@ g_irepository_require (GIRepository *repository, + goto out; + } + +- typelib = g_typelib_new_from_mapped_file (mfile); ++ typelib = g_typelib_new_from_mapped_file (mfile, error); ++ if (!typelib) ++ goto out; + header = (Header *) typelib->data; + typelib_namespace = g_typelib_get_string (typelib, header->namespace); + typelib_version = g_typelib_get_string (typelib, header->nsversion); +diff --git a/girepository/girmodule.c b/girepository/girmodule.c +index 1c62319..066d516 100644 +--- a/girepository/girmodule.c ++++ b/girepository/girmodule.c +@@ -206,6 +206,7 @@ GTypelib * + g_ir_module_build_typelib (GIrModule *module, + GList *modules) + { ++ GError *error = NULL; + GTypelib *typelib; + gsize length; + guint i; +@@ -434,7 +435,12 @@ g_ir_module_build_typelib (GIrModule *module, + data = g_realloc (data, offset2); + header = (Header*) data; + length = header->size = offset2; +- typelib = g_typelib_new_from_memory (data, length); ++ typelib = g_typelib_new_from_memory (data, length, &error); ++ if (!typelib) ++ { ++ g_error ("error building typelib: %s", ++ error->message); ++ } + + g_hash_table_destroy (strings); + g_hash_table_destroy (types); +diff --git a/girepository/gitypelib.c b/girepository/gitypelib.c +index 0741bcb..5469e8b 100644 +--- a/girepository/gitypelib.c ++++ b/girepository/gitypelib.c +@@ -260,30 +260,30 @@ validate_name (GTypelib *typelib, + return TRUE; + } + ++/* Fast path sanity check, operates on a memory blob */ + static gboolean +-validate_header (ValidateContext *ctx, +- GError **error) ++validate_header_basic (const guint8 *memory, ++ gsize len, ++ GError **error) + { +- GTypelib *typelib = ctx->typelib; +- Header *header; ++ Header *header = (Header *)memory; + +- if (typelib->len < sizeof (Header)) ++ if (len < sizeof (Header)) + { + g_set_error (error, + G_TYPELIB_ERROR, + G_TYPELIB_ERROR_INVALID, +- "The buffer is too short"); ++ "The specified typelib length %" G_GSIZE_FORMAT " is too short", ++ len); + return FALSE; + } + +- header = (Header *)typelib->data; +- + if (strncmp (header->magic, G_IR_MAGIC, 16) != 0) + { + g_set_error (error, + G_TYPELIB_ERROR, + G_TYPELIB_ERROR_INVALID_HEADER, +- "Magic string not found"); ++ "Invalid magic header"); + return FALSE; + + } +@@ -293,7 +293,7 @@ validate_header (ValidateContext *ctx, + g_set_error (error, + G_TYPELIB_ERROR, + G_TYPELIB_ERROR_INVALID_HEADER, +- "Version mismatch; expected 3, found %d", ++ "Typelib version mismatch; expected 3, found %d", + header->major_version); + return FALSE; + +@@ -308,12 +308,13 @@ validate_header (ValidateContext *ctx, + return FALSE; + } + +- if (header->size != typelib->len) ++ if (header->size != len) + { + g_set_error (error, + G_TYPELIB_ERROR, + G_TYPELIB_ERROR_INVALID_HEADER, +- "Typelib size mismatch"); ++ "Typelib size %" G_GSIZE_FORMAT " does not match %" G_GSIZE_FORMAT, ++ header->size, len); + return FALSE; + } + +@@ -378,9 +379,24 @@ validate_header (ValidateContext *ctx, + return FALSE; + } + +- if (!validate_name (typelib, "namespace", typelib->data, header->namespace, error)) ++ return TRUE; ++} ++ ++static gboolean ++validate_header (ValidateContext *ctx, ++ GError **error) ++{ ++ GTypelib *typelib = ctx->typelib; ++ ++ if (!validate_header_basic (typelib->data, typelib->len, error)) + return FALSE; + ++ { ++ Header *header = (Header*)typelib->data; ++ if (!validate_name (typelib, "namespace", typelib->data, header->namespace, error)) ++ return FALSE; ++ } ++ + return TRUE; + } + +@@ -2056,6 +2072,7 @@ _g_typelib_ensure_open (GTypelib *typelib) + * g_typelib_new_from_memory: + * @memory: address of memory chunk containing the typelib + * @len: length of memory chunk containing the typelib ++ * @error: a #GError + * + * Creates a new #GTypelib from a memory location. The memory block + * pointed to by @typelib will be automatically g_free()d when the +@@ -2064,10 +2081,15 @@ _g_typelib_ensure_open (GTypelib *typelib) + * Return value: the new #GTypelib + **/ + GTypelib * +-g_typelib_new_from_memory (guchar *memory, gsize len) ++g_typelib_new_from_memory (guint8 *memory, ++ gsize len, ++ GError **error) + { + GTypelib *meta; + ++ if (!validate_header_basic (memory, len, error)) ++ return NULL; ++ + meta = g_slice_new0 (GTypelib); + meta->data = memory; + meta->len = len; +@@ -2081,16 +2103,22 @@ g_typelib_new_from_memory (guchar *memory, gsize len) + * g_typelib_new_from_const_memory: + * @memory: address of memory chunk containing the typelib + * @len: length of memory chunk containing the typelib ++ * @error: A #GError + * + * Creates a new #GTypelib from a memory location. + * + * Return value: the new #GTypelib + **/ + GTypelib * +-g_typelib_new_from_const_memory (const guchar *memory, gsize len) ++g_typelib_new_from_const_memory (const guchar *memory, ++ gsize len, ++ GError **error) + { + GTypelib *meta; + ++ if (!validate_header_basic (memory, len, error)) ++ return NULL; ++ + meta = g_slice_new0 (GTypelib); + meta->data = (guchar *) memory; + meta->len = len; +@@ -2103,21 +2131,28 @@ g_typelib_new_from_const_memory (const guchar *memory, gsize len) + /** + * g_typelib_new_from_mapped_file: + * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed ++ * @error: a #GError + * + * Creates a new #GTypelib from a #GMappedFile. + * + * Return value: the new #GTypelib + **/ + GTypelib * +-g_typelib_new_from_mapped_file (GMappedFile *mfile) ++g_typelib_new_from_mapped_file (GMappedFile *mfile, ++ GError **error) + { + GTypelib *meta; ++ guint8 *data = (guint8 *) g_mapped_file_get_contents (mfile); ++ gsize len = g_mapped_file_get_length (mfile); ++ ++ if (!validate_header_basic (data, len, error)) ++ return NULL; + + meta = g_slice_new0 (GTypelib); + meta->mfile = mfile; + meta->owns_memory = FALSE; +- meta->data = (guchar *) g_mapped_file_get_contents (mfile); +- meta->len = g_mapped_file_get_length (mfile); ++ meta->data = data; ++ meta->len = len; + + return meta; + } +diff --git a/girepository/gitypelib.h b/girepository/gitypelib.h +index 5d5eda5..0a61008 100644 +--- a/girepository/gitypelib.h ++++ b/girepository/gitypelib.h +@@ -34,11 +34,14 @@ G_BEGIN_DECLS + + typedef struct _GTypelib GTypelib; + +-GTypelib * g_typelib_new_from_memory (guchar *memory, +- gsize len); +-GTypelib * g_typelib_new_from_const_memory (const guchar *memory, +- gsize len); +-GTypelib * g_typelib_new_from_mapped_file (GMappedFile *mfile); ++GTypelib * g_typelib_new_from_memory (guint8 *memory, ++ gsize len, ++ GError **error); ++GTypelib * g_typelib_new_from_const_memory (const guint8 *memory, ++ gsize len, ++ GError **error); ++GTypelib * g_typelib_new_from_mapped_file (GMappedFile *mfile, ++ GError **error); + void g_typelib_free (GTypelib *typelib); + + gboolean g_typelib_symbol (GTypelib *typelib, +diff --git a/tools/compiler.c b/tools/compiler.c +index e6cddb8..d066428 100644 +--- a/tools/compiler.c ++++ b/tools/compiler.c +@@ -54,6 +54,7 @@ format_output (GTypelib *typelib) + + result = g_string_sized_new (6 * typelib->len); + ++ g_string_append_printf (result, "/* GENERATED CODE - DO NOT EDIT */\n"); + g_string_append_printf (result, "#include \n"); + g_string_append_printf (result, "#include \n\n"); + +@@ -84,7 +85,8 @@ format_output (GTypelib *typelib) + "register_typelib (void)\n" + "{\n" + "\tGTypelib *typelib;\n" +- "\ttypelib = g_typelib_new_from_const_memory (_G_TYPELIB, _G_TYPELIB_SIZE);\n" ++ "\ttypelib = g_typelib_new_from_const_memory (_G_TYPELIB, _G_TYPELIB_SIZE, NULL);\n" ++ "\tg_assert (typelib != NULL);\n" + "\tg_irepository_load_typelib (NULL, typelib, G_IREPOSITORY_LOAD_FLAG_LAZY, NULL);\n" + "}\n\n"); + } +diff --git a/tools/generate.c b/tools/generate.c +index cd1fedc..b456901 100644 +--- a/tools/generate.c ++++ b/tools/generate.c +@@ -29,45 +29,6 @@ + #include "girepository.h" + #include "gitypelib-internal.h" + +-static const guchar * +-load_typelib (const gchar *filename, +- GModule **dlhandle, +- gsize *len) +-{ +- guchar *typelib; +- gsize *typelib_size; +- GModule *handle; +- +- handle = g_module_open (filename, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY); +- if (handle == NULL) +- { +- g_printerr ("Could not load typelib from '%s': %s\n", +- filename, g_module_error ()); +- return NULL; +- } +- +- if (!g_module_symbol (handle, "_G_TYPELIB", (gpointer *) &typelib)) +- { +- g_printerr ("Could not load typelib from '%s': %s\n", +- filename, g_module_error ()); +- return NULL; +- } +- +- if (!g_module_symbol (handle, "_G_TYPELIB_SIZE", (gpointer *) &typelib_size)) +- { +- g_printerr ("Could not load typelib from '%s': %s\n", +- filename, g_module_error ()); +- return NULL; +- } +- +- *len = *typelib_size; +- +- if (dlhandle) +- *dlhandle = handle; +- +- return typelib; +-} +- + int + main (int argc, char *argv[]) + { +@@ -114,62 +75,31 @@ main (int argc, char *argv[]) + + for (i = 0; input[i]; i++) + { +- GModule *dlhandle = NULL; +- const guchar *typelib; +- gsize len; ++ GError *error = NULL; + const char *namespace; ++ GMappedFile *mfile; ++ GTypelib *typelib; + +- if (!shlib) +- { +- if (!g_file_get_contents (input[i], (gchar **)&typelib, &len, &error)) +- { +- g_fprintf (stderr, "failed to read '%s': %s\n", +- input[i], error->message); +- g_clear_error (&error); +- continue; +- } +- } +- else +- { +- typelib = load_typelib (input[i], &dlhandle, &len); +- if (!typelib) +- { +- g_fprintf (stderr, "failed to load typelib from '%s'\n", +- input[i]); +- continue; +- } +- } ++ mfile = g_mapped_file_new (input[i], FALSE, &error); ++ if (!mfile) ++ g_error ("failed to read '%s': %s", input[i], error->message); + + if (input[i + 1] && output) + needs_prefix = TRUE; + else + needs_prefix = FALSE; + +- data = g_typelib_new_from_const_memory (typelib, len); +- { +- GError *error = NULL; +- if (!g_typelib_validate (data, &error)) { +- g_printerr ("typelib not valid: %s\n", error->message); +- g_clear_error (&error); +- return 1; +- } +- } +- namespace = g_irepository_load_typelib (g_irepository_get_default (), data, 0, ++ typelib = g_typelib_new_from_mapped_file (mfile, &error); ++ if (!typelib) ++ g_error ("failed to create typelib '%s': %s", input[i], error->message); ++ ++ namespace = g_irepository_load_typelib (g_irepository_get_default (), typelib, 0, + &error); + if (namespace == NULL) +- { +- g_printerr ("failed to load typelib: %s\n", error->message); +- return 1; +- } +- ++ g_error ("failed to load typelib: %s", error->message); ++ + gir_writer_write (output, namespace, needs_prefix, show_all); + +- if (dlhandle) +- { +- g_module_close (dlhandle); +- dlhandle = NULL; +- } +- + /* when writing to stdout, stop after the first module */ + if (input[i + 1] && !output) + { +-- +1.7.1.1 + diff --git a/gobject-introspection.spec b/gobject-introspection.spec index 4a04db4..484cc7c 100644 --- a/gobject-introspection.spec +++ b/gobject-introspection.spec @@ -3,7 +3,7 @@ Name: gobject-introspection Version: 0.9.2 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Introspection system for GObject-based libraries Group: Development/Libraries @@ -11,6 +11,7 @@ License: GPLv2+, LGPLv2+, MIT URL: http://live.gnome.org/GObjectIntrospection #VCS: git:git://git.gnome.org/gobject-introspection Source0: gobject-introspection-0.9.2.tar.gz +Patch0: 0001-girepository-Actually-verify-header-of-loaded-typeli.patch Obsoletes: gir-repository @@ -52,6 +53,7 @@ Libraries and headers for gobject-introspection %prep %setup -q -n gobject-introspection-0.9.2 +%patch1 -p1 %build (if ! test -x configure; then NOCONFIGURE=1 ./autogen.sh; CONFIGFLAGS=--enable-gtk-doc; fi; @@ -94,6 +96,9 @@ find $RPM_BUILD_ROOT -type f -name "*.a" -exec rm -f {} ';' %{_datadir}/gtk-doc/html/gi/* %changelog +* Wed Jul 14 2010 Colin Walters - 0.9.2-3 +- Backport patch from upstream for better errors + * Mon Jul 12 2010 Colin Walters - 0.9.2-1 - New upstream (unstable series) release; requires rebuilds