diff --git a/0001-as-app-desktop-don-t-deference-invalid-lists.patch b/0001-as-app-desktop-don-t-deference-invalid-lists.patch new file mode 100644 index 0000000..d9d736b --- /dev/null +++ b/0001-as-app-desktop-don-t-deference-invalid-lists.patch @@ -0,0 +1,54 @@ +From 628474b5b3a82e779447e296c3e019fe913800ff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Tue, 23 Jan 2018 14:32:25 +0100 +Subject: [PATCH 1/2] as-app-desktop: don't deference invalid lists + +Malformed .desktop files might causes crashes when +returned lists are NULL. +--- + libappstream-glib/as-app-desktop.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/libappstream-glib/as-app-desktop.c b/libappstream-glib/as-app-desktop.c +index 1f12683..fadf4ab 100644 +--- a/libappstream-glib/as-app-desktop.c ++++ b/libappstream-glib/as-app-desktop.c +@@ -236,7 +236,7 @@ as_app_parse_file_key (AsApp *app, + G_KEY_FILE_DESKTOP_GROUP, + key, + NULL, NULL); +- for (i = 0; list[i] != NULL; i++) { ++ for (i = 0; list != NULL && list[i] != NULL; i++) { + const gchar *category_blacklist[] = { + "X-GNOME-Settings-Panel", + "X-Unity-Settings-Panel", +@@ -271,7 +271,7 @@ as_app_parse_file_key (AsApp *app, + G_KEY_FILE_DESKTOP_GROUP, + key, + NULL, NULL); +- for (i = 0; list[i] != NULL; i++) { ++ for (i = 0; list != NULL && list[i] != NULL; i++) { + g_auto(GStrv) kw_split = NULL; + kw_split = g_strsplit (list[i], ",", -1); + for (j = 0; kw_split[j] != NULL; j++) { +@@ -291,7 +291,7 @@ as_app_parse_file_key (AsApp *app, + key, + locale, + NULL, NULL); +- for (i = 0; list[i] != NULL; i++) { ++ for (i = 0; list != NULL && list[i] != NULL; i++) { + g_auto(GStrv) kw_split = NULL; + kw_split = g_strsplit (list[i], ",", -1); + for (j = 0; kw_split[j] != NULL; j++) { +@@ -306,7 +306,7 @@ as_app_parse_file_key (AsApp *app, + G_KEY_FILE_DESKTOP_GROUP, + key, + NULL, NULL); +- for (i = 0; list[i] != NULL; i++) ++ for (i = 0; list != NULL && list[i] != NULL; i++) + as_app_add_mimetype (app, list[i]); + + } else if (g_strcmp0 (key, "X-AppInstall-Package") == 0) { +-- +2.14.3 + diff --git a/0002-Fix-an-invalid-read-when-using-as_app_parse_data-fro.patch b/0002-Fix-an-invalid-read-when-using-as_app_parse_data-fro.patch new file mode 100644 index 0000000..444c032 --- /dev/null +++ b/0002-Fix-an-invalid-read-when-using-as_app_parse_data-fro.patch @@ -0,0 +1,206 @@ +From 2dd6f02296f82cba60c1523d361d8250d9f43539 Mon Sep 17 00:00:00 2001 +From: Richard Hughes +Date: Wed, 24 Jan 2018 19:33:41 +0000 +Subject: [PATCH 2/2] Fix an invalid read when using as_app_parse_data() from + Python + +Using GObject Introspection we were creating an object using GLib.Bytes.new(buf) +where buf was a python str object. This created a GBytes object with no +trailing NUL char but we were expecting a NUL-terminated string when both doing +fnmatch() and also processing the XML. Support this by guarding fnmatch and +also by using the string length when using the GMarkupParseContext. +--- + libappstream-glib/as-app.c | 14 +++++++-- + libappstream-glib/as-node.c | 65 +++++++++++++++++++++++++++------------- + libappstream-glib/as-node.h | 4 +++ + libappstream-glib/as-self-test.c | 18 +++++++++++ + 4 files changed, 79 insertions(+), 22 deletions(-) + +diff --git a/libappstream-glib/as-app.c b/libappstream-glib/as-app.c +index bdf4d24..474af29 100644 +--- a/libappstream-glib/as-app.c ++++ b/libappstream-glib/as-app.c +@@ -6047,6 +6047,16 @@ as_app_parse_appdata_guess_project_group (AsApp *app) + } + } + ++static int ++as_utils_fnmatch (const gchar *pattern, const gchar *text, gsize text_sz, gint flags) ++{ ++ if (text_sz != -1 && text[text_sz-1] != '\0') { ++ g_autofree gchar *text_with_nul = g_strndup (text, text_sz); ++ return fnmatch (pattern, text_with_nul, flags); ++ } ++ return fnmatch (pattern, text, flags); ++} ++ + /** + * as_app_parse_data: + * @app: a #AsApp instance. +@@ -6078,13 +6088,13 @@ as_app_parse_data (AsApp *app, GBytes *data, guint32 flags, GError **error) + priv->problems |= AS_APP_PROBLEM_NO_XML_HEADER; + + /* check for copyright */ +- if (fnmatch ("**", data_raw, 0) != 0) ++ if (as_utils_fnmatch ("**", data_raw, len, 0) != 0) + priv->problems |= AS_APP_PROBLEM_NO_COPYRIGHT_INFO; + + /* parse */ + if (flags & AS_APP_PARSE_FLAG_KEEP_COMMENTS) + from_xml_flags |= AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS; +- root = as_node_from_xml (data_raw, from_xml_flags, error); ++ root = as_node_from_bytes (data, from_xml_flags, error); + if (root == NULL) + return FALSE; + +diff --git a/libappstream-glib/as-node.c b/libappstream-glib/as-node.c +index 36b4ae1..f8199a9 100644 +--- a/libappstream-glib/as-node.c ++++ b/libappstream-glib/as-node.c +@@ -783,22 +783,10 @@ as_node_passthrough_cb (GMarkupParseContext *context, + } + } + +-/** +- * as_node_from_xml: (skip) +- * @data: XML data +- * @flags: #AsNodeFromXmlFlags, e.g. %AS_NODE_FROM_XML_FLAG_NONE +- * @error: A #GError or %NULL +- * +- * Parses XML data into a DOM tree. +- * +- * Returns: (transfer none): A populated #AsNode tree +- * +- * Since: 0.1.0 +- **/ +-AsNode * +-as_node_from_xml (const gchar *data, +- AsNodeFromXmlFlags flags, +- GError **error) ++static AsNode * ++as_node_from_xml_internal (const gchar *data, gssize data_sz, ++ AsNodeFromXmlFlags flags, ++ GError **error) + { + AsNodeToXmlHelper helper; + AsNode *root = NULL; +@@ -822,10 +810,7 @@ as_node_from_xml (const gchar *data, + G_MARKUP_PREFIX_ERROR_POSITION, + &helper, + NULL); +- ret = g_markup_parse_context_parse (ctx, +- data, +- -1, +- &error_local); ++ ret = g_markup_parse_context_parse (ctx, data, data_sz, &error_local); + if (!ret) { + g_set_error_literal (error, + AS_NODE_ERROR, +@@ -847,6 +832,46 @@ as_node_from_xml (const gchar *data, + return root; + } + ++/** ++ * as_node_from_bytes: (skip) ++ * @bytes: a #GBytes ++ * @flags: #AsNodeFromXmlFlags, e.g. %AS_NODE_FROM_XML_FLAG_NONE ++ * @error: A #GError or %NULL ++ * ++ * Parses XML data into a DOM tree. ++ * ++ * Returns: (transfer none): A populated #AsNode tree ++ * ++ * Since: 0.7.6 ++ **/ ++AsNode * ++as_node_from_bytes (GBytes *bytes, AsNodeFromXmlFlags flags, GError **error) ++{ ++ gsize sz = 0; ++ const gchar *buf; ++ g_return_val_if_fail (bytes != NULL, NULL); ++ buf = g_bytes_get_data (bytes, &sz); ++ return as_node_from_xml_internal (buf, (gssize) sz, flags, error); ++} ++ ++/** ++ * as_node_from_xml: (skip) ++ * @data: XML data ++ * @flags: #AsNodeFromXmlFlags, e.g. %AS_NODE_FROM_XML_FLAG_NONE ++ * @error: A #GError or %NULL ++ * ++ * Parses XML data into a DOM tree. ++ * ++ * Returns: (transfer none): A populated #AsNode tree ++ * ++ * Since: 0.1.0 ++ **/ ++AsNode * ++as_node_from_xml (const gchar *data, AsNodeFromXmlFlags flags, GError **error) ++{ ++ return as_node_from_xml_internal (data, -1, flags, error); ++} ++ + /** + * as_node_to_file: (skip) + * @root: A populated #AsNode tree +diff --git a/libappstream-glib/as-node.h b/libappstream-glib/as-node.h +index e3fe936..913c1c8 100644 +--- a/libappstream-glib/as-node.h ++++ b/libappstream-glib/as-node.h +@@ -164,6 +164,10 @@ GNode *as_node_from_xml (const gchar *data, + AsNodeFromXmlFlags flags, + GError **error) + G_GNUC_WARN_UNUSED_RESULT; ++GNode *as_node_from_bytes (GBytes *bytes, ++ AsNodeFromXmlFlags flags, ++ GError **error) ++ G_GNUC_WARN_UNUSED_RESULT; + GNode *as_node_from_file (GFile *file, + AsNodeFromXmlFlags flags, + GCancellable *cancellable, +diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c +index 7b3b6df..cde6fda 100644 +--- a/libappstream-glib/as-self-test.c ++++ b/libappstream-glib/as-self-test.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + + #include "as-app-private.h" +@@ -5472,6 +5473,22 @@ as_test_utils_unique_id_hash_safe_func (void) + g_assert (found == NULL); + } + ++static void ++as_test_app_parse_data_func (void) ++{ ++ const gchar *data = "\n" ++ "\n\n "; ++ gboolean ret; ++ g_autoptr(GBytes) blob = NULL; ++ g_autoptr(AsApp) app = as_app_new (); ++ g_autoptr(GError) error = NULL; ++ ++ blob = g_bytes_new (data, strlen (data)); ++ ret = as_app_parse_data (app, blob, AS_APP_PARSE_FLAG_NONE, &error); ++ g_assert_no_error (error); ++ g_assert (ret); ++} ++ + static void + as_test_ref_string_func (void) + { +@@ -5546,6 +5563,7 @@ main (int argc, char **argv) + g_test_add_func ("/AppStream/app{validate-file-bad}", as_test_app_validate_file_bad_func); + g_test_add_func ("/AppStream/app{validate-meta-bad}", as_test_app_validate_meta_bad_func); + g_test_add_func ("/AppStream/app{validate-intltool}", as_test_app_validate_intltool_func); ++ g_test_add_func ("/AppStream/app{parse-data}", as_test_app_parse_data_func); + g_test_add_func ("/AppStream/app{parse-file:desktop}", as_test_app_parse_file_desktop_func); + g_test_add_func ("/AppStream/app{no-markup}", as_test_app_no_markup_func); + g_test_add_func ("/AppStream/app{subsume}", as_test_app_subsume_func); +-- +2.14.3 + diff --git a/libappstream-glib.spec b/libappstream-glib.spec index 147a3a6..318734e 100644 --- a/libappstream-glib.spec +++ b/libappstream-glib.spec @@ -6,11 +6,15 @@ Summary: Library for AppStream metadata Name: libappstream-glib Version: 0.7.5 -Release: 1%{?dist} +Release: 2%{?dist} License: LGPLv2+ URL: http://people.freedesktop.org/~hughsient/appstream-glib/ Source0: http://people.freedesktop.org/~hughsient/appstream-glib/releases/appstream-glib-%{version}.tar.xz +# from upstream git master +Patch0: 0001-as-app-desktop-don-t-deference-invalid-lists.patch +Patch1: 0002-Fix-an-invalid-read-when-using-as_app_parse_data-fro.patch + BuildRequires: glib2-devel >= %{glib2_version} BuildRequires: docbook-utils BuildRequires: gtk-doc @@ -83,6 +87,8 @@ GLib headers and libraries for appstream-builder. %prep %setup -q -n appstream-glib-%{version} +%patch0 -p1 -b .crash1 +%patch1 -p1 -b .crash2 %build %meson \ @@ -148,6 +154,9 @@ GLib headers and libraries for appstream-builder. %{_datadir}/gir-1.0/AppStreamBuilder-1.0.gir %changelog +* Wed Jan 24 2018 Richard Hughes 0.7.5-2 +- Backport two crash fixes from master. + * Mon Jan 22 2018 Richard Hughes 0.7.5-1 - New upstream release - Add more GObject Introspection annotations for Python