commit 29d52d051413bbf1d58098ffd210228d4547dae9 Author: overweight <5324761+overweight@user.noreply.gitee.com> Date: Mon Sep 30 10:40:42 2019 -0400 Package init diff --git a/CVE-2019-12450.patch b/CVE-2019-12450.patch new file mode 100644 index 0000000..7f349ae --- /dev/null +++ b/CVE-2019-12450.patch @@ -0,0 +1,53 @@ +From d8f8f4d637ce43f8699ba94c9b7648beda0ca174 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Thu, 23 May 2019 10:41:53 +0200 +Subject: [PATCH] gfile: Limit access to files when copying + +file_copy_fallback creates new files with default permissions and +set the correct permissions after the operation is finished. This +might cause that the files can be accessible by more users during +the operation than expected. Use G_FILE_CREATE_PRIVATE for the new +files to limit access to those files. +--- + gio/gfile.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/gio/gfile.c b/gio/gfile.c +index 24b136d80..74b58047c 100644 +--- a/gio/gfile.c ++++ b/gio/gfile.c +@@ -3284,12 +3284,12 @@ file_copy_fallback (GFile *source, + out = (GOutputStream*)_g_local_file_output_stream_replace (_g_local_file_get_filename (G_LOCAL_FILE (destination)), + FALSE, NULL, + flags & G_FILE_COPY_BACKUP, +- G_FILE_CREATE_REPLACE_DESTINATION, +- info, ++ G_FILE_CREATE_REPLACE_DESTINATION | ++ G_FILE_CREATE_PRIVATE, info, + cancellable, error); + else + out = (GOutputStream*)_g_local_file_output_stream_create (_g_local_file_get_filename (G_LOCAL_FILE (destination)), +- FALSE, 0, info, ++ FALSE, G_FILE_CREATE_PRIVATE, info, + cancellable, error); + } + else if (flags & G_FILE_COPY_OVERWRITE) +@@ -3297,12 +3297,13 @@ file_copy_fallback (GFile *source, + out = (GOutputStream *)g_file_replace (destination, + NULL, + flags & G_FILE_COPY_BACKUP, +- G_FILE_CREATE_REPLACE_DESTINATION, ++ G_FILE_CREATE_REPLACE_DESTINATION | ++ G_FILE_CREATE_PRIVATE, + cancellable, error); + } + else + { +- out = (GOutputStream *)g_file_create (destination, 0, cancellable, error); ++ out = (GOutputStream *)g_file_create (destination, G_FILE_CREATE_PRIVATE, cancellable, error); + } + + if (!out) +-- +2.22.0 + diff --git a/CVE-2019-13012.patch b/CVE-2019-13012.patch new file mode 100644 index 0000000..4ece9c9 --- /dev/null +++ b/CVE-2019-13012.patch @@ -0,0 +1,23 @@ +diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c +index a37978e..580a0b0 100644 +--- a/gio/gkeyfilesettingsbackend.c ++++ b/gio/gkeyfilesettingsbackend.c +@@ -89,7 +89,8 @@ g_keyfile_settings_backend_keyfile_write (GKeyfileSettingsBackend *kfsb) + + contents = g_key_file_to_data (kfsb->keyfile, &length, NULL); + g_file_replace_contents (kfsb->file, contents, length, NULL, FALSE, +- G_FILE_CREATE_REPLACE_DESTINATION, ++ G_FILE_CREATE_REPLACE_DESTINATION | ++ G_FILE_CREATE_PRIVATE, + NULL, NULL, NULL); + + compute_checksum (kfsb->digest, contents, length); +@@ -640,7 +641,7 @@ g_keyfile_settings_backend_new (const gchar *filename, + + kfsb->file = g_file_new_for_path (filename); + kfsb->dir = g_file_get_parent (kfsb->file); +- g_file_make_directory_with_parents (kfsb->dir, NULL, NULL); ++ g_mkdir_with_parents (g_file_peek_path (kfsb->dir), 0700); + + kfsb->file_monitor = g_file_monitor (kfsb->file, 0, NULL, NULL); + kfsb->dir_monitor = g_file_monitor (kfsb->dir, 0, NULL, NULL); diff --git a/Fixing-missing-initializer-in-g_static_rec_mutex_ini.patch b/Fixing-missing-initializer-in-g_static_rec_mutex_ini.patch new file mode 100644 index 0000000..72615b8 --- /dev/null +++ b/Fixing-missing-initializer-in-g_static_rec_mutex_ini.patch @@ -0,0 +1,37 @@ +From 4cd8fccc11f732ac76bf522562e06fc90ae82144 Mon Sep 17 00:00:00 2001 +From: Emmanuel Fleury +Date: Sun, 27 Jan 2019 03:10:37 +0100 +Subject: [PATCH 547/682] Fixing missing initializer in + g_static_rec_mutex_init() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +glib/deprecated/gthread-deprecated.c: In function ‘g_static_rec_mutex_init’: +glib/deprecated/gthread-deprecated.c:657:3: error: missing initializer for field ‘depth’ of ‘GStaticRecMutex’ {aka ‘const struct _GStaticRecMutex’} [-Werror=missing-field-initializers] + static const GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT; + ^~~~~~ +In file included from glib/deprecated/gthread-deprecated.c:30: +glib/deprecated/gthread.h:161:9: note: ‘depth’ declared here + guint depth; + ^~~~~ +--- + glib/deprecated/gthread.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/glib/deprecated/gthread.h b/glib/deprecated/gthread.h +index d0814a875..9e1c2ff56 100644 +--- a/glib/deprecated/gthread.h ++++ b/glib/deprecated/gthread.h +@@ -171,7 +171,7 @@ struct _GStaticRecMutex + } unused; + }; + +-#define G_STATIC_REC_MUTEX_INIT { G_STATIC_MUTEX_INIT } ++#define G_STATIC_REC_MUTEX_INIT { G_STATIC_MUTEX_INIT, 0, { 0 } } + GLIB_DEPRECATED_IN_2_32_FOR(g_rec_mutex_init) + void g_static_rec_mutex_init (GStaticRecMutex *mutex); + +-- +2.19.1 + diff --git a/bookmarkfile-Don-t-move-an-item-if-the-uri-has-not-c.patch b/bookmarkfile-Don-t-move-an-item-if-the-uri-has-not-c.patch new file mode 100644 index 0000000..33024f6 --- /dev/null +++ b/bookmarkfile-Don-t-move-an-item-if-the-uri-has-not-c.patch @@ -0,0 +1,35 @@ +From 821d28024bf2bc4287163f5001fb902820933e37 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Mon, 5 Nov 2018 17:15:32 -0600 +Subject: [PATCH 230/682] bookmarkfile: Don't move an item if the uri has not + changed + +This was causing a crash, because we were first removing an item, freeing +both the instance itself and the key, and then trying to reuse those. + +So, in this case, instead of reassigning an item, we can just return TRUE +as we have already the item at the right place, while it's not needed to +update the modified timestamp, since no modification happened in reality. + +Fixes #1588 +--- + glib/gbookmarkfile.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/glib/gbookmarkfile.c b/glib/gbookmarkfile.c +index ffd7ea0b1..f75f261b1 100644 +--- a/glib/gbookmarkfile.c ++++ b/glib/gbookmarkfile.c +@@ -3584,6 +3584,9 @@ g_bookmark_file_move_item (GBookmarkFile *bookmark, + + if (new_uri && new_uri[0] != '\0') + { ++ if (g_strcmp0 (old_uri, new_uri) == 0) ++ return TRUE; ++ + if (g_bookmark_file_has_item (bookmark, new_uri)) + { + if (!g_bookmark_file_remove_item (bookmark, new_uri, error)) +-- +2.19.1 + diff --git a/g_timeout_-_seconds-don-t-overflow-for-large-interva.patch b/g_timeout_-_seconds-don-t-overflow-for-large-interva.patch new file mode 100644 index 0000000..0377545 --- /dev/null +++ b/g_timeout_-_seconds-don-t-overflow-for-large-interva.patch @@ -0,0 +1,82 @@ +From 4ff3734ff5748cbc53f7b89c7148a4e3daba3230 Mon Sep 17 00:00:00 2001 +From: Will Thompson +Date: Mon, 26 Nov 2018 16:04:10 +0000 +Subject: [PATCH 307/682] g_timeout_*_seconds: don't overflow for large + intervals + +Previously, the `guint interval` parameter, measured in seconds, was +multiplied by 1000 and stored in another `guint` field. For intervals +greater than (G_MAXUINT / 1000) seconds, this would overflow; the +timeout would fire much sooner than intended. + +Since GTimeoutSource already keeps track of whether it was created at +millisecond or second resolution, always store the passed interval +directly. We later convert the interval to microseconds, stored in a +gint64, so can move the `* 1000` to there. + +The eagle-eyed reader might notice that there is no obvious guarantee +that the source's expiration time in microseconds won't overflow the +gint64, but I don't think this is a new problem. Previously, the +monotonic time would have to reach (2 ** 63 - 2 ** 32) microseconds for +this overflow to occur; now it would have to reach approximately (2 ** +63 - 2 ** 42) microseconds. Both of these are 292.47 millennia to 5 +significant figures. + +Fixes #1600. +--- + glib/gmain.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/glib/gmain.c b/glib/gmain.c +index 5e849b9ac..347882551 100644 +--- a/glib/gmain.c ++++ b/glib/gmain.c +@@ -315,6 +315,7 @@ struct _GMainLoop + struct _GTimeoutSource + { + GSource source; ++ /* Measured in seconds if 'seconds' is TRUE, or milliseconds otherwise. */ + guint interval; + gboolean seconds; + }; +@@ -4615,8 +4616,6 @@ g_timeout_set_expiration (GTimeoutSource *timeout_source, + { + gint64 expiration; + +- expiration = current_time + (guint64) timeout_source->interval * 1000; +- + if (timeout_source->seconds) + { + gint64 remainder; +@@ -4638,6 +4637,8 @@ g_timeout_set_expiration (GTimeoutSource *timeout_source, + timer_perturb = 0; + } + ++ expiration = current_time + (guint64) timeout_source->interval * 1000 * 1000; ++ + /* We want the microseconds part of the timeout to land on the + * 'timer_perturb' mark, but we need to make sure we don't try to + * set the timeout in the past. We do this by ensuring that we +@@ -4653,6 +4654,10 @@ g_timeout_set_expiration (GTimeoutSource *timeout_source, + expiration -= remainder; + expiration += timer_perturb; + } ++ else ++ { ++ expiration = current_time + (guint64) timeout_source->interval * 1000; ++ } + + g_source_set_ready_time ((GSource *) timeout_source, expiration); + } +@@ -4735,7 +4740,7 @@ g_timeout_source_new_seconds (guint interval) + GSource *source = g_source_new (&g_timeout_funcs, sizeof (GTimeoutSource)); + GTimeoutSource *timeout_source = (GTimeoutSource *)source; + +- timeout_source->interval = 1000 * interval; ++ timeout_source->interval = interval; + timeout_source->seconds = TRUE; + + g_timeout_set_expiration (timeout_source, g_get_monotonic_time ()); +-- +2.19.1 + diff --git a/gbase64-Allow-g_base64_encode-NULL-0-and-g_base64_de.patch b/gbase64-Allow-g_base64_encode-NULL-0-and-g_base64_de.patch new file mode 100644 index 0000000..c30e36a --- /dev/null +++ b/gbase64-Allow-g_base64_encode-NULL-0-and-g_base64_de.patch @@ -0,0 +1,125 @@ +From ff76f6920e36f5befff270ba318bc612d1585839 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Wed, 27 Feb 2019 10:26:47 +0000 +Subject: [PATCH 638/682] gbase64: Allow g_base64_encode (NULL, 0) and + g_base64_decode ("", *) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Relax a precondition in g_base64_encode_step() to allow this. It’s valid +to base64 encode an empty string, as per RFC 4648. + +Similarly for g_base64_decode(), although calling it with a NULL string +has never been allowed. Instead, clarify the case of calling it with an +empty string. + +This includes a unit test. + +Signed-off-by: Philip Withnall + +Fixes: #1698 +--- + glib/gbase64.c | 8 ++++---- + glib/tests/base64.c | 39 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 43 insertions(+), 4 deletions(-) + +diff --git a/glib/gbase64.c b/glib/gbase64.c +index d3416e310..baddae098 100644 +--- a/glib/gbase64.c ++++ b/glib/gbase64.c +@@ -100,7 +100,7 @@ g_base64_encode_step (const guchar *in, + char *outptr; + const guchar *inptr; + +- g_return_val_if_fail (in != NULL, 0); ++ g_return_val_if_fail (in != NULL || len == 0, 0); + g_return_val_if_fail (out != NULL, 0); + g_return_val_if_fail (state != NULL, 0); + g_return_val_if_fail (save != NULL, 0); +@@ -244,7 +244,7 @@ g_base64_encode_close (gboolean break_lines, + + /** + * g_base64_encode: +- * @data: (array length=len) (element-type guint8): the binary data to encode ++ * @data: (array length=len) (element-type guint8) (nullable): the binary data to encode + * @len: the length of @data + * + * Encode a sequence of binary data into its Base-64 stringified +@@ -334,7 +334,7 @@ g_base64_decode_step (const gchar *in, + unsigned int v; + int i; + +- g_return_val_if_fail (in != NULL, 0); ++ g_return_val_if_fail (in != NULL || len == 0, 0); + g_return_val_if_fail (out != NULL, 0); + g_return_val_if_fail (state != NULL, 0); + g_return_val_if_fail (save != NULL, 0); +@@ -390,7 +390,7 @@ g_base64_decode_step (const gchar *in, + + /** + * g_base64_decode: +- * @text: zero-terminated string with base64 text to decode ++ * @text: (not nullable): zero-terminated string with base64 text to decode + * @out_len: (out): The length of the decoded data is written here + * + * Decode a sequence of Base-64 encoded text into binary data. Note +diff --git a/glib/tests/base64.c b/glib/tests/base64.c +index 86875a29b..6091d1eed 100644 +--- a/glib/tests/base64.c ++++ b/glib/tests/base64.c +@@ -406,6 +406,42 @@ test_base64_decode_smallblock (gconstpointer blocksize_p) + } + } + ++/* Test that calling g_base64_encode (NULL, 0) returns correct output. This is ++ * as per the first test vector in RFC 4648 §10. ++ * https://tools.ietf.org/html/rfc4648#section-10 */ ++static void ++test_base64_encode_empty (void) ++{ ++ gchar *encoded = NULL; ++ ++ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1698"); ++ ++ encoded = g_base64_encode (NULL, 0); ++ g_assert_cmpstr (encoded, ==, ""); ++ g_free (encoded); ++ ++ encoded = g_base64_encode ((const guchar *) "", 0); ++ g_assert_cmpstr (encoded, ==, ""); ++ g_free (encoded); ++} ++ ++/* Test that calling g_base64_decode ("", *) returns correct output. This is ++ * as per the first test vector in RFC 4648 §10. Note that calling ++ * g_base64_decode (NULL, *) is not allowed. ++ * https://tools.ietf.org/html/rfc4648#section-10 */ ++static void ++test_base64_decode_empty (void) ++{ ++ guchar *decoded = NULL; ++ gsize decoded_len; ++ ++ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1698"); ++ ++ decoded = g_base64_decode ("", &decoded_len); ++ g_assert_cmpstr ((gchar *) decoded, ==, ""); ++ g_assert_cmpuint (decoded_len, ==, 0); ++ g_free (decoded); ++} + + int + main (int argc, char *argv[]) +@@ -455,5 +491,8 @@ main (int argc, char *argv[]) + g_test_add_data_func ("/base64/incremental/smallblock/4", GINT_TO_POINTER(4), + test_base64_decode_smallblock); + ++ g_test_add_func ("/base64/encode/empty", test_base64_encode_empty); ++ g_test_add_func ("/base64/decode/empty", test_base64_decode_empty); ++ + return g_test_run (); + } +-- +2.19.1 + diff --git a/gbase64-Fix-an-impossible-condition.patch b/gbase64-Fix-an-impossible-condition.patch new file mode 100644 index 0000000..d76335d --- /dev/null +++ b/gbase64-Fix-an-impossible-condition.patch @@ -0,0 +1,40 @@ +From f9dfddf8eb4952fc5e0a77fffeff70c7cea37b68 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Wed, 27 Feb 2019 10:27:43 +0000 +Subject: [PATCH 639/682] gbase64: Fix an impossible condition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +len is unsigned, so it’s not possible for it to be less than zero. + +Signed-off-by: Philip Withnall +--- + glib/gbase64.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/glib/gbase64.c b/glib/gbase64.c +index baddae098..ef6a39832 100644 +--- a/glib/gbase64.c ++++ b/glib/gbase64.c +@@ -105,7 +105,7 @@ g_base64_encode_step (const guchar *in, + g_return_val_if_fail (state != NULL, 0); + g_return_val_if_fail (save != NULL, 0); + +- if (len <= 0) ++ if (len == 0) + return 0; + + inptr = in; +@@ -339,7 +339,7 @@ g_base64_decode_step (const gchar *in, + g_return_val_if_fail (state != NULL, 0); + g_return_val_if_fail (save != NULL, 0); + +- if (len <= 0) ++ if (len == 0) + return 0; + + inend = (const guchar *)in+len; +-- +2.19.1 + diff --git a/gdate-Use-longest-matching-month-name-in-g_date_set_.patch b/gdate-Use-longest-matching-month-name-in-g_date_set_.patch new file mode 100644 index 0000000..9fa9445 --- /dev/null +++ b/gdate-Use-longest-matching-month-name-in-g_date_set_.patch @@ -0,0 +1,135 @@ +From ba18822f358c49f15435197dba7c11f6753396f1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= +Date: Tue, 30 Oct 2018 00:00:00 +0000 +Subject: [PATCH 258/682] gdate: Use longest matching month name in + g_date_set_parse + +There are languages where a name of one month is a substring of another. +Instead of stopping search on the first match use the month that +constitutes the longest match. + +Fixes #1343. +--- + glib/gdate.c | 75 ++++++++++++++++++++--------------------------- + glib/tests/date.c | 34 +++++++++++++++++++++ + 2 files changed, 65 insertions(+), 44 deletions(-) + +diff --git a/glib/gdate.c b/glib/gdate.c +index 4925818b3..5457a3b8c 100644 +--- a/glib/gdate.c ++++ b/glib/gdate.c +@@ -931,6 +931,27 @@ struct _GDateParseTokens { + + typedef struct _GDateParseTokens GDateParseTokens; + ++static inline gboolean ++update_month_match (gsize *longest, ++ const gchar *haystack, ++ const gchar *needle) ++{ ++ gsize length; ++ ++ if (needle == NULL) ++ return FALSE; ++ ++ length = strlen (needle); ++ if (*longest >= length) ++ return FALSE; ++ ++ if (strstr (haystack, needle) == NULL) ++ return FALSE; ++ ++ *longest = length; ++ return TRUE; ++} ++ + #define NUM_LEN 10 + + /* HOLDS: g_date_global_lock */ +@@ -978,6 +999,7 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt) + + if (pt->num_ints < 3) + { ++ gsize longest = 0; + gchar *casefold; + gchar *normalized; + +@@ -985,8 +1007,7 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt) + normalized = g_utf8_normalize (casefold, -1, G_NORMALIZE_ALL); + g_free (casefold); + +- i = 1; +- while (i < 13) ++ for (i = 1; i < 13; ++i) + { + /* Here month names may be in a genitive case if the language + * grammatical rules require it. +@@ -997,60 +1018,26 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt) + * genitive case here so they use nominative everywhere. + * For example, English always uses "January". + */ +- if (long_month_names[i] != NULL) +- { +- const gchar *found = strstr (normalized, long_month_names[i]); +- +- if (found != NULL) +- { +- pt->month = i; +- break; +- } +- } ++ if (update_month_match (&longest, normalized, long_month_names[i])) ++ pt->month = i; + + /* Here month names will be in a nominative case. + * Examples of how January may look in some languages: + * Catalan: "gener", Croatian: "Siječanj", Polish: "styczeń", + * Upper Sorbian: "Januar". + */ +- if (long_month_names_alternative[i] != NULL) +- { +- const gchar *found = strstr (normalized, long_month_names_alternative[i]); +- +- if (found != NULL) +- { +- pt->month = i; +- break; +- } +- } ++ if (update_month_match (&longest, normalized, long_month_names_alternative[i])) ++ pt->month = i; + + /* Differences between abbreviated nominative and abbreviated + * genitive month names are visible in very few languages but + * let's handle them. + */ +- if (short_month_names[i] != NULL) +- { +- const gchar *found = strstr (normalized, short_month_names[i]); +- +- if (found != NULL) +- { +- pt->month = i; +- break; +- } +- } ++ if (update_month_match (&longest, normalized, short_month_names[i])) ++ pt->month = i; + +- if (short_month_names_alternative[i] != NULL) +- { +- const gchar *found = strstr (normalized, short_month_names_alternative[i]); +- +- if (found != NULL) +- { +- pt->month = i; +- break; +- } +- } +- +- ++i; ++ if (update_month_match (&longest, normalized, short_month_names_alternative[i])) ++ pt->month = i; + } + + g_free (normalized); diff --git a/gdatetime-Fix-formatting-of-time-zones-offsets-in-ra.patch b/gdatetime-Fix-formatting-of-time-zones-offsets-in-ra.patch new file mode 100644 index 0000000..1556e8f --- /dev/null +++ b/gdatetime-Fix-formatting-of-time-zones-offsets-in-ra.patch @@ -0,0 +1,104 @@ +From 54c394a73f95eb225fd748aef9a7205d45ff16fc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= +Date: Wed, 31 Oct 2018 00:00:00 +0000 +Subject: [PATCH 205/682] gdatetime: Fix formatting of time zones offsets in + range -01:00 to +00:00 + +Formatting code for `%z` specifier incorrectly assumed that sign of +offset from UTC can be recovered from the number of hours alone, which +is not true for offsets between -01:00 and +00:00. + +Extract and format sign separately to avoid the problem. + +Issue #1337. +--- + glib/gdatetime.c | 17 +++++++++++------ + glib/tests/gdatetime.c | 22 ++++++++++++++++++++++ + 2 files changed, 33 insertions(+), 6 deletions(-) + +diff --git a/glib/gdatetime.c b/glib/gdatetime.c +index 1bd916587..32fd501aa 100644 +--- a/glib/gdatetime.c ++++ b/glib/gdatetime.c +@@ -2721,34 +2721,39 @@ format_z (GString *outstr, + gint hours; + gint minutes; + gint seconds; ++ gchar sign = offset >= 0 ? '+' : '-'; + ++ offset = ABS (offset); + hours = offset / 3600; +- minutes = ABS (offset) / 60 % 60; +- seconds = ABS (offset) % 60; ++ minutes = offset / 60 % 60; ++ seconds = offset % 60; + + switch (colons) + { + case 0: +- g_string_append_printf (outstr, "%+03d%02d", ++ g_string_append_printf (outstr, "%c%02d%02d", ++ sign, + hours, + minutes); + break; + + case 1: +- g_string_append_printf (outstr, "%+03d:%02d", ++ g_string_append_printf (outstr, "%c%02d:%02d", ++ sign, + hours, + minutes); + break; + + case 2: +- g_string_append_printf (outstr, "%+03d:%02d:%02d", ++ g_string_append_printf (outstr, "%c%02d:%02d:%02d", ++ sign, + hours, + minutes, + seconds); + break; + + case 3: +- g_string_append_printf (outstr, "%+03d", hours); ++ g_string_append_printf (outstr, "%c%02d", sign, hours); + + if (minutes != 0 || seconds != 0) + { +diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c +index a028f6d20..f4000d96c 100644 +--- a/glib/tests/gdatetime.c ++++ b/glib/tests/gdatetime.c +@@ -1986,6 +1986,28 @@ test_z (void) + g_free (p); + g_date_time_unref (dt); + g_time_zone_unref (tz); ++ ++ tz = g_time_zone_new ("-00:15"); ++ dt = g_date_time_new (tz, 1, 1, 1, 0, 0, 0); ++ ++ p = g_date_time_format (dt, "%z"); ++ g_assert_cmpstr (p, ==, "-0015"); ++ g_free (p); ++ ++ p = g_date_time_format (dt, "%:z"); ++ g_assert_cmpstr (p, ==, "-00:15"); ++ g_free (p); ++ ++ p = g_date_time_format (dt, "%::z"); ++ g_assert_cmpstr (p, ==, "-00:15:00"); ++ g_free (p); ++ ++ p = g_date_time_format (dt, "%:::z"); ++ g_assert_cmpstr (p, ==, "-00:15"); ++ g_free (p); ++ ++ g_date_time_unref (dt); ++ g_time_zone_unref (tz); + } + + #pragma GCC diagnostic push +-- +2.19.1 + diff --git a/gdatetime-Store-intermediate-result-of-g_date_time_f.patch b/gdatetime-Store-intermediate-result-of-g_date_time_f.patch new file mode 100644 index 0000000..66a0636 --- /dev/null +++ b/gdatetime-Store-intermediate-result-of-g_date_time_f.patch @@ -0,0 +1,568 @@ +From bc59892b1af2a8f4374a1ad2054ff9444151732b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= +Date: Fri, 30 Nov 2018 00:00:00 +0000 +Subject: [PATCH 320/682] gdatetime: Store intermediate result of + g_date_time_format in UTF-8 + +In date time formatting routine, instead of converting from UTF-8 to +locale charset and then from locale charset to UTF-8, store all +intermediate result in UTF-8. + +This solves the issue where user provided UTF-8 format string might be +unrepresentable in the current locale charset. + +Fixes issue #1605. +--- + glib/gdatetime.c | 320 +++++++++++++++++++++-------------------- + glib/tests/gdatetime.c | 18 +++ + 2 files changed, 179 insertions(+), 159 deletions(-) + +diff --git a/glib/gdatetime.c b/glib/gdatetime.c +index 32fd501aa..6afe14438 100644 +--- a/glib/gdatetime.c ++++ b/glib/gdatetime.c +@@ -4,6 +4,7 @@ + * Copyright (C) 2010 Thiago Santos + * Copyright (C) 2010 Emmanuele Bassi + * Copyright © 2010 Codethink Limited ++ * Copyright © 2018 Tomasz Miąsko + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as +@@ -2771,6 +2772,51 @@ format_z (GString *outstr, + return TRUE; + } + ++#ifdef HAVE_LANGINFO_OUTDIGIT ++/** Initializes the array with UTF-8 encoded alternate digits suibtable for use ++ * in current locale. Returns NULL when current locale does not use alternate ++ * digits or there was an error converting them to UTF-8. ++ */ ++static const gchar * const * ++initialize_alt_digits (void) ++{ ++ guint i; ++ gsize digit_len; ++ gchar *digit; ++ const gchar *locale_digit; ++#define N_DIGITS 10 ++#define MAX_UTF8_ENCODING_LEN 4 ++ static gchar buffer[N_DIGITS * (MAX_UTF8_ENCODING_LEN + 1 /* null separator */)]; ++#undef N_DIGITS ++#undef MAX_UTF8_ENCODING_LEN ++ gchar *buffer_end = buffer; ++ static const gchar *alt_digits[10]; ++ ++ for (i = 0; i != 10; ++i) ++ { ++ locale_digit = nl_langinfo (_NL_CTYPE_OUTDIGIT0_MB + i); ++ ++ if (g_strcmp0 (locale_digit, "") == 0) ++ return NULL; ++ ++ digit = g_locale_to_utf8 (locale_digit, -1, NULL, &digit_len, NULL); ++ if (digit == NULL) ++ return NULL; ++ ++ g_assert (digit_len < buffer + sizeof (buffer) - buffer_end); ++ ++ alt_digits[i] = buffer_end; ++ buffer_end = g_stpcpy (buffer_end, digit); ++ /* skip trailing null byte */ ++ buffer_end += 1; ++ ++ g_free (digit); ++ } ++ ++ return alt_digits; ++} ++#endif /* HAVE_LANGINFO_OUTDIGIT */ ++ + static void + format_number (GString *str, + gboolean use_alt_digits, +@@ -2781,7 +2827,7 @@ format_number (GString *str, + const gchar *ascii_digits[10] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" + }; +- const gchar **digits = ascii_digits; ++ const gchar * const *digits = ascii_digits; + const gchar *tmp[10]; + gint i = 0; + +@@ -2790,17 +2836,16 @@ format_number (GString *str, + #ifdef HAVE_LANGINFO_OUTDIGIT + if (use_alt_digits) + { +- static const gchar *alt_digits[10]; ++ static const gchar * const *alt_digits = NULL; + static gsize initialised; +- /* 2^32 has 10 digits */ + + if G_UNLIKELY (g_once_init_enter (&initialised)) + { +-#define DO_DIGIT(n) \ +- alt_digits[n] = nl_langinfo (_NL_CTYPE_OUTDIGIT## n ##_MB) +- DO_DIGIT(0); DO_DIGIT(1); DO_DIGIT(2); DO_DIGIT(3); DO_DIGIT(4); +- DO_DIGIT(5); DO_DIGIT(6); DO_DIGIT(7); DO_DIGIT(8); DO_DIGIT(9); +-#undef DO_DIGIT ++ alt_digits = initialize_alt_digits (); ++ ++ if (alt_digits == NULL) ++ alt_digits = ascii_digits; ++ + g_once_init_leave (&initialised, TRUE); + } + +@@ -2833,7 +2878,6 @@ format_ampm (GDateTime *datetime, + { + const gchar *ampm; + gchar *tmp = NULL, *ampm_dup; +- gsize len; + + ampm = GET_AMPM (datetime); + +@@ -2844,104 +2888,107 @@ format_ampm (GDateTime *datetime, + { + /* This assumes that locale encoding can't have embedded NULs */ + ampm = tmp = g_locale_to_utf8 (ampm, -1, NULL, NULL, NULL); +- if (!tmp) ++ if (tmp == NULL) + return FALSE; + } + if (uppercase) + ampm_dup = g_utf8_strup (ampm, -1); + else + ampm_dup = g_utf8_strdown (ampm, -1); +- len = strlen (ampm_dup); +- if (!locale_is_utf8 && GET_AMPM_IS_LOCALE) +- { +- g_free (tmp); +- tmp = g_locale_from_utf8 (ampm_dup, -1, NULL, &len, NULL); +- g_free (ampm_dup); +- if (!tmp) +- return FALSE; +- ampm_dup = tmp; +- } +- g_string_append_len (outstr, ampm_dup, len); ++ g_free (tmp); ++ ++ g_string_append (outstr, ampm_dup); + g_free (ampm_dup); + + return TRUE; + } + +-static gboolean g_date_time_format_locale (GDateTime *datetime, +- const gchar *format, +- GString *outstr, +- gboolean locale_is_utf8); ++static gboolean g_date_time_format_utf8 (GDateTime *datetime, ++ const gchar *format, ++ GString *outstr, ++ gboolean locale_is_utf8); + + /* g_date_time_format() subroutine that takes a locale-encoded format +- * string and produces a locale-encoded date/time string. ++ * string and produces a UTF-8 encoded date/time string. + */ + static gboolean +-g_date_time_locale_format_locale (GDateTime *datetime, +- const gchar *format, +- GString *outstr, +- gboolean locale_is_utf8) ++g_date_time_format_locale (GDateTime *datetime, ++ const gchar *locale_format, ++ GString *outstr, ++ gboolean locale_is_utf8) + { + gchar *utf8_format; + gboolean success; + + if (locale_is_utf8) +- return g_date_time_format_locale (datetime, format, outstr, +- locale_is_utf8); ++ return g_date_time_format_utf8 (datetime, locale_format, outstr, locale_is_utf8); + +- utf8_format = g_locale_to_utf8 (format, -1, NULL, NULL, NULL); +- if (!utf8_format) ++ utf8_format = g_locale_to_utf8 (locale_format, -1, NULL, NULL, NULL); ++ if (utf8_format == NULL) + return FALSE; + +- success = g_date_time_format_locale (datetime, utf8_format, outstr, +- locale_is_utf8); ++ success = g_date_time_format_utf8 (datetime, utf8_format, outstr, ++ locale_is_utf8); + g_free (utf8_format); + return success; + } + +-/* g_date_time_format() subroutine that takes a UTF-8 format +- * string and produces a locale-encoded date/time string. ++static inline gboolean ++string_append (GString *string, ++ const gchar *s, ++ gboolean s_is_utf8) ++{ ++ gchar *utf8; ++ gsize utf8_len; ++ ++ if (s_is_utf8) ++ { ++ g_string_append (string, s); ++ } ++ else ++ { ++ utf8 = g_locale_to_utf8 (s, -1, NULL, &utf8_len, NULL); ++ if (utf8 == NULL) ++ return FALSE; ++ g_string_append_len (string, utf8, utf8_len); ++ g_free (utf8); ++ } ++ ++ return TRUE; ++} ++ ++/* g_date_time_format() subroutine that takes a UTF-8 encoded format ++ * string and produces a UTF-8 encoded date/time string. + */ + static gboolean +-g_date_time_format_locale (GDateTime *datetime, +- const gchar *format, +- GString *outstr, +- gboolean locale_is_utf8) ++g_date_time_format_utf8 (GDateTime *datetime, ++ const gchar *utf8_format, ++ GString *outstr, ++ gboolean locale_is_utf8) + { + guint len; + guint colons; +- gchar *tmp; +- gsize tmp_len; + gunichar c; + gboolean alt_digits = FALSE; + gboolean pad_set = FALSE; ++ gboolean name_is_utf8; + const gchar *pad = ""; + const gchar *name; + const gchar *tz; + +- while (*format) ++ while (*utf8_format) + { +- len = strcspn (format, "%"); ++ len = strcspn (utf8_format, "%"); + if (len) +- { +- if (locale_is_utf8) +- g_string_append_len (outstr, format, len); +- else +- { +- tmp = g_locale_from_utf8 (format, len, NULL, &tmp_len, NULL); +- if (!tmp) +- return FALSE; +- g_string_append_len (outstr, tmp, tmp_len); +- g_free (tmp); +- } +- } ++ g_string_append_len (outstr, utf8_format, len); + +- format += len; +- if (!*format) ++ utf8_format += len; ++ if (!*utf8_format) + break; + +- g_assert (*format == '%'); +- format++; +- if (!*format) ++ g_assert (*utf8_format == '%'); ++ utf8_format++; ++ if (!*utf8_format) + break; + + colons = 0; +@@ -2949,91 +2996,67 @@ g_date_time_format_locale (GDateTime *datetime, + pad_set = FALSE; + + next_mod: +- c = g_utf8_get_char (format); +- format = g_utf8_next_char (format); ++ c = g_utf8_get_char (utf8_format); ++ utf8_format = g_utf8_next_char (utf8_format); + switch (c) + { + case 'a': + name = WEEKDAY_ABBR (datetime); + if (g_strcmp0 (name, "") == 0) + return FALSE; +- if (!locale_is_utf8 && !WEEKDAY_ABBR_IS_LOCALE) +- { +- tmp = g_locale_from_utf8 (name, -1, NULL, &tmp_len, NULL); +- if (!tmp) +- return FALSE; +- g_string_append_len (outstr, tmp, tmp_len); +- g_free (tmp); +- } +- else +- { +- g_string_append (outstr, name); +- } ++ ++ name_is_utf8 = locale_is_utf8 || !WEEKDAY_ABBR_IS_LOCALE; ++ ++ if (!string_append (outstr, name, name_is_utf8)) ++ return FALSE; ++ + break; + case 'A': + name = WEEKDAY_FULL (datetime); + if (g_strcmp0 (name, "") == 0) + return FALSE; +- if (!locale_is_utf8 && !WEEKDAY_FULL_IS_LOCALE) +- { +- tmp = g_locale_from_utf8 (name, -1, NULL, &tmp_len, NULL); +- if (!tmp) +- return FALSE; +- g_string_append_len (outstr, tmp, tmp_len); +- g_free (tmp); +- } +- else +- { +- g_string_append (outstr, name); +- } ++ ++ name_is_utf8 = locale_is_utf8 || !WEEKDAY_FULL_IS_LOCALE; ++ ++ if (!string_append (outstr, name, name_is_utf8)) ++ return FALSE; ++ + break; + case 'b': + name = alt_digits ? MONTH_ABBR_STANDALONE (datetime) + : MONTH_ABBR_WITH_DAY (datetime); + if (g_strcmp0 (name, "") == 0) + return FALSE; +- if (!locale_is_utf8 && +- ((alt_digits && !MONTH_ABBR_STANDALONE_IS_LOCALE) || +- (!alt_digits && !MONTH_ABBR_WITH_DAY_IS_LOCALE))) +- { +- tmp = g_locale_from_utf8 (name, -1, NULL, &tmp_len, NULL); +- if (!tmp) +- return FALSE; +- g_string_append_len (outstr, tmp, tmp_len); +- g_free (tmp); +- } +- else +- { +- g_string_append (outstr, name); +- } ++ ++ name_is_utf8 = locale_is_utf8 || ++ ((alt_digits && !MONTH_ABBR_STANDALONE_IS_LOCALE) || ++ (!alt_digits && !MONTH_ABBR_WITH_DAY_IS_LOCALE)); ++ ++ if (!string_append (outstr, name, name_is_utf8)) ++ return FALSE; ++ + break; + case 'B': + name = alt_digits ? MONTH_FULL_STANDALONE (datetime) + : MONTH_FULL_WITH_DAY (datetime); + if (g_strcmp0 (name, "") == 0) + return FALSE; +- if (!locale_is_utf8 && +- ((alt_digits && !MONTH_FULL_STANDALONE_IS_LOCALE) || +- (!alt_digits && !MONTH_FULL_WITH_DAY_IS_LOCALE))) +- { +- tmp = g_locale_from_utf8 (name, -1, NULL, &tmp_len, NULL); +- if (!tmp) +- return FALSE; +- g_string_append_len (outstr, tmp, tmp_len); +- g_free (tmp); +- } +- else +- { +- g_string_append (outstr, name); +- } ++ ++ name_is_utf8 = locale_is_utf8 || ++ ((alt_digits && !MONTH_FULL_STANDALONE_IS_LOCALE) || ++ (!alt_digits && !MONTH_FULL_WITH_DAY_IS_LOCALE)); ++ ++ if (!string_append (outstr, name, name_is_utf8)) ++ return FALSE; ++ + break; + case 'c': + { + if (g_strcmp0 (PREFERRED_DATE_TIME_FMT, "") == 0) + return FALSE; +- if (!g_date_time_locale_format_locale (datetime, PREFERRED_DATE_TIME_FMT, +- outstr, locale_is_utf8)) +- return FALSE; ++ if (!g_date_time_format_locale (datetime, PREFERRED_DATE_TIME_FMT, ++ outstr, locale_is_utf8)) ++ return FALSE; + } + break; + case 'C': +@@ -3067,20 +3090,14 @@ g_date_time_format_locale (GDateTime *datetime, + : MONTH_ABBR_WITH_DAY (datetime); + if (g_strcmp0 (name, "") == 0) + return FALSE; +- if (!locale_is_utf8 && +- ((alt_digits && !MONTH_ABBR_STANDALONE_IS_LOCALE) || +- (!alt_digits && !MONTH_ABBR_WITH_DAY_IS_LOCALE))) +- { +- tmp = g_locale_from_utf8 (name, -1, NULL, &tmp_len, NULL); +- if (!tmp) +- return FALSE; +- g_string_append_len (outstr, tmp, tmp_len); +- g_free (tmp); +- } +- else +- { +- g_string_append (outstr, name); +- } ++ ++ name_is_utf8 = locale_is_utf8 || ++ ((alt_digits && !MONTH_ABBR_STANDALONE_IS_LOCALE) || ++ (!alt_digits && !MONTH_ABBR_WITH_DAY_IS_LOCALE)); ++ ++ if (!string_append (outstr, name, name_is_utf8)) ++ return FALSE; ++ + break; + case 'H': + format_number (outstr, alt_digits, pad_set ? pad : "0", 2, +@@ -3128,8 +3145,8 @@ g_date_time_format_locale (GDateTime *datetime, + { + if (g_strcmp0 (PREFERRED_12HR_TIME_FMT, "") == 0) + return FALSE; +- if (!g_date_time_locale_format_locale (datetime, PREFERRED_12HR_TIME_FMT, +- outstr, locale_is_utf8)) ++ if (!g_date_time_format_locale (datetime, PREFERRED_12HR_TIME_FMT, ++ outstr, locale_is_utf8)) + return FALSE; + } + break; +@@ -3170,8 +3187,8 @@ g_date_time_format_locale (GDateTime *datetime, + { + if (g_strcmp0 (PREFERRED_DATE_FMT, "") == 0) + return FALSE; +- if (!g_date_time_locale_format_locale (datetime, PREFERRED_DATE_FMT, +- outstr, locale_is_utf8)) ++ if (!g_date_time_format_locale (datetime, PREFERRED_DATE_FMT, ++ outstr, locale_is_utf8)) + return FALSE; + } + break; +@@ -3179,8 +3196,8 @@ g_date_time_format_locale (GDateTime *datetime, + { + if (g_strcmp0 (PREFERRED_TIME_FMT, "") == 0) + return FALSE; +- if (!g_date_time_locale_format_locale (datetime, PREFERRED_TIME_FMT, +- outstr, locale_is_utf8)) ++ if (!g_date_time_format_locale (datetime, PREFERRED_TIME_FMT, ++ outstr, locale_is_utf8)) + return FALSE; + } + break; +@@ -3202,16 +3219,7 @@ g_date_time_format_locale (GDateTime *datetime, + break; + case 'Z': + tz = g_date_time_get_timezone_abbreviation (datetime); +- tmp = NULL; +- tmp_len = strlen (tz); +- if (!locale_is_utf8) +- { +- tz = tmp = g_locale_from_utf8 (tz, -1, NULL, &tmp_len, NULL); +- if (!tmp) +- return FALSE; +- } +- g_string_append_len (outstr, tz, tmp_len); +- g_free (tmp); ++ g_string_append (outstr, tz); + break; + case '%': + g_string_append_c (outstr, '%'); +@@ -3230,7 +3238,7 @@ g_date_time_format_locale (GDateTime *datetime, + goto next_mod; + case ':': + /* Colons are only allowed before 'z' */ +- if (*format && *format != 'z' && *format != ':') ++ if (*utf8_format && *utf8_format != 'z' && *utf8_format != ':') + return FALSE; + colons++; + goto next_mod; +@@ -3355,7 +3363,6 @@ g_date_time_format (GDateTime *datetime, + const gchar *format) + { + GString *outstr; +- gchar *utf8; + gboolean locale_is_utf8 = g_get_charset (NULL); + + g_return_val_if_fail (datetime != NULL, NULL); +@@ -3364,18 +3371,13 @@ g_date_time_format (GDateTime *datetime, + + outstr = g_string_sized_new (strlen (format) * 2); + +- if (!g_date_time_format_locale (datetime, format, outstr, locale_is_utf8)) ++ if (!g_date_time_format_utf8 (datetime, format, outstr, locale_is_utf8)) + { + g_string_free (outstr, TRUE); + return NULL; + } + +- if (locale_is_utf8) +- return g_string_free (outstr, FALSE); +- +- utf8 = g_locale_to_utf8 (outstr->str, outstr->len, NULL, NULL, NULL); +- g_string_free (outstr, TRUE); +- return utf8; ++ return g_string_free (outstr, FALSE); + } + + +diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c +index 09f84cb21..1a46cf55a 100644 +--- a/glib/tests/gdatetime.c ++++ b/glib/tests/gdatetime.c +@@ -1525,6 +1525,23 @@ test_non_utf8_printf (void) + g_free (oldlocale); + } + ++/* Checks that it is possible to use format string that ++ * is unrepresentable in current locale charset. */ ++static void ++test_format_unrepresentable (void) ++{ ++ gchar *oldlocale = g_strdup (setlocale (LC_ALL, NULL)); ++ setlocale (LC_ALL, "POSIX"); ++ ++ TEST_PRINTF ("ąśćł", "ąśćł"); ++ ++ /* We are using Unicode ratio symbol here, which is outside ASCII. */ ++ TEST_PRINTF_TIME (23, 15, 0, "%H∶%M", "23∶15"); ++ ++ setlocale (LC_ALL, oldlocale); ++ g_free (oldlocale); ++} ++ + static void + test_modifiers (void) + { +@@ -2493,6 +2510,7 @@ main (gint argc, + g_test_add_func ("/GDateTime/now", test_GDateTime_now); + g_test_add_func ("/GDateTime/printf", test_GDateTime_printf); + g_test_add_func ("/GDateTime/non_utf8_printf", test_non_utf8_printf); ++ g_test_add_func ("/GDateTime/format_unrepresentable", test_format_unrepresentable); + g_test_add_func ("/GDateTime/strftime", test_strftime); + g_test_add_func ("/GDateTime/strftime/error_handling", test_GDateTime_strftime_error_handling); + g_test_add_func ("/GDateTime/modifiers", test_modifiers); +-- +2.19.1 + diff --git a/gdbus-Avoid-printing-null-strings.patch b/gdbus-Avoid-printing-null-strings.patch new file mode 100644 index 0000000..1323726 --- /dev/null +++ b/gdbus-Avoid-printing-null-strings.patch @@ -0,0 +1,71 @@ +From 566e1d61a500267c7849ad0b2552feec9c9a29a6 Mon Sep 17 00:00:00 2001 +From: Ernestas Kulik +Date: Tue, 29 Jan 2019 09:50:46 +0100 +Subject: [PATCH 539/682] gdbus: Avoid printing null strings +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This mostly affects the 2.56 branch, but, given that GCC 9 is being +stricter about passing null string pointers to printf-like functions, it +might make sense to proactively fix such calls. + +gdbusauth.c: In function '_g_dbus_auth_run_server': +gdbusauth.c:1302:11: error: '%s' directive argument is null +[-Werror=format-overflow=] + 1302 | debug_print ("SERVER: WaitingForBegin, read '%s'", + line); + | + +gdbusmessage.c: In function ‘g_dbus_message_to_blob’: +gdbusmessage.c:2730:30: error: ‘%s’ directive argument is null [-Werror=format-overflow=] + 2730 | tupled_signature_str = g_strdup_printf ("(%s)", signature_str); + | +--- + gio/gdbusauth.c | 2 +- + gio/gdbusmessage.c | 5 ++--- + 2 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c +index 1f8ea8057..752ec23fc 100644 +--- a/gio/gdbusauth.c ++++ b/gio/gdbusauth.c +@@ -1272,9 +1272,9 @@ _g_dbus_auth_run_server (GDBusAuth *auth, + &line_length, + cancellable, + error); +- debug_print ("SERVER: WaitingForBegin, read '%s'", line); + if (line == NULL) + goto out; ++ debug_print ("SERVER: WaitingForBegin, read '%s'", line); + if (g_strcmp0 (line, "BEGIN") == 0) + { + /* YAY, done! */ +diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c +index 3221b925d..3a1a1f9e9 100644 +--- a/gio/gdbusmessage.c ++++ b/gio/gdbusmessage.c +@@ -2731,7 +2731,6 @@ g_dbus_message_to_blob (GDBusMessage *message, + if (message->body != NULL) + { + gchar *tupled_signature_str; +- tupled_signature_str = g_strdup_printf ("(%s)", signature_str); + if (signature == NULL) + { + g_set_error (error, +@@ -2739,10 +2738,10 @@ g_dbus_message_to_blob (GDBusMessage *message, + G_IO_ERROR_INVALID_ARGUMENT, + _("Message body has signature “%s” but there is no signature header"), + signature_str); +- g_free (tupled_signature_str); + goto out; + } +- else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0) ++ tupled_signature_str = g_strdup_printf ("(%s)", signature_str); ++ if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0) + { + g_set_error (error, + G_IO_ERROR, +-- +2.19.1 + diff --git a/gdbus-Fix-a-potential-use-after-free-on-connection-c.patch b/gdbus-Fix-a-potential-use-after-free-on-connection-c.patch new file mode 100644 index 0000000..e33fa1c --- /dev/null +++ b/gdbus-Fix-a-potential-use-after-free-on-connection-c.patch @@ -0,0 +1,43 @@ +From 067992f8dedd11651e624921129cd0ffb099180f Mon Sep 17 00:00:00 2001 +From: Christoph Reiter +Date: Thu, 14 Feb 2019 04:16:18 +0100 +Subject: [PATCH 605/682] gdbus: Fix a potential use-after-free on connection + close. Fixes #1686 + +512e9b3b34d added a call to schedule_pending_close() in the read +callback after the reference to the worker is already gone. In case this was +the last reference to the worker this resulted in a use-after-free. + +6f3d57d2ee2 made this more likely to happen because on connection close +the worker cancel action is now async while the reference to the worker +gets dropped right away. + +Move the call to schedule_pending_close() before the unref. + +Fixes #1686 +--- + gio/gdbusprivate.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c +index c2a04ae12..1e8e1d64b 100644 +--- a/gio/gdbusprivate.c ++++ b/gio/gdbusprivate.c +@@ -809,11 +809,11 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream, + out: + g_mutex_unlock (&worker->read_lock); + +- /* gives up the reference acquired when calling g_input_stream_read_async() */ +- _g_dbus_worker_unref (worker); +- + /* check if there is any pending close */ + schedule_pending_close (worker); ++ ++ /* gives up the reference acquired when calling g_input_stream_read_async() */ ++ _g_dbus_worker_unref (worker); + } + + /* called in private thread shared by all GDBusConnection instances (with read-lock held) */ +-- +2.19.1 + diff --git a/gdbus-codegen-make-interface-info-header-body-not-cr.patch b/gdbus-codegen-make-interface-info-header-body-not-cr.patch new file mode 100644 index 0000000..3b893bd --- /dev/null +++ b/gdbus-codegen-make-interface-info-header-body-not-cr.patch @@ -0,0 +1,99 @@ +From faa3c319ba4021372a3bcc1829f357007419124e Mon Sep 17 00:00:00 2001 +From: Will Thompson +Date: Wed, 5 Dec 2018 21:32:05 +0000 +Subject: [PATCH 331/682] gdbus-codegen: make --interface-info-{header,body} + not crash + +Since 1217b1bc4f242c14d6eabbee0c688c320eab2e4d, LICENSE_STR has taken two +parameters, not one. Without this change, running either mode fails +with a traceback like: + + Traceback (most recent call last): + File "../gdbus-codegen", line 55, in + sys.exit(codegen_main.codegen_main()) + File ".../codegen_main.py", line 294, in codegen_main + gen.generate() + File ".../codegen.py", line 896, in generate + self.generate_body_preamble() + File ".../codegen.py", line 682, in generate_body_preamble + self.outfile.write(LICENSE_STR.format(config.VERSION)) + IndexError: tuple index out of range + +8916874ee6f3ff0f887dbe1eda55c23c2c0097ee, which introduced these flags, +was actually merged after that commit, but I assume it was written +beforehand. +--- + gio/gdbus-2.0/codegen/codegen.py | 12 ++++++++---- + gio/gdbus-2.0/codegen/codegen_main.py | 2 ++ + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py +index 9d2b904c7..9220176a8 100644 +--- a/gio/gdbus-2.0/codegen/codegen.py ++++ b/gio/gdbus-2.0/codegen/codegen.py +@@ -619,17 +619,19 @@ class HeaderCodeGenerator: + # ---------------------------------------------------------------------------------------------------- + + class InterfaceInfoHeaderCodeGenerator: +- def __init__(self, ifaces, namespace, header_name, use_pragma, outfile): ++ def __init__(self, ifaces, namespace, header_name, input_files_basenames, use_pragma, outfile): + self.ifaces = ifaces + self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) + self.header_guard = header_name.upper().replace('.', '_').replace('-', '_').replace('/', '_').replace(':', '_') ++ self.input_files_basenames = input_files_basenames + self.use_pragma = use_pragma + self.outfile = outfile + + # ---------------------------------------------------------------------------------------------------- + + def generate_header_preamble(self): +- self.outfile.write(LICENSE_STR.format(config.VERSION)) ++ basenames = ', '.join(self.input_files_basenames) ++ self.outfile.write(LICENSE_STR.format(config.VERSION, basenames)) + self.outfile.write('\n') + + if self.use_pragma: +@@ -670,16 +672,18 @@ class InterfaceInfoHeaderCodeGenerator: + # ---------------------------------------------------------------------------------------------------- + + class InterfaceInfoBodyCodeGenerator: +- def __init__(self, ifaces, namespace, header_name, outfile): ++ def __init__(self, ifaces, namespace, header_name, input_files_basenames, outfile): + self.ifaces = ifaces + self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace) + self.header_name = header_name ++ self.input_files_basenames = input_files_basenames + self.outfile = outfile + + # ---------------------------------------------------------------------------------------------------- + + def generate_body_preamble(self): +- self.outfile.write(LICENSE_STR.format(config.VERSION)) ++ basenames = ', '.join(self.input_files_basenames) ++ self.outfile.write(LICENSE_STR.format(config.VERSION, basenames)) + self.outfile.write('\n') + self.outfile.write('#ifdef HAVE_CONFIG_H\n' + '# include "config.h"\n' +diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py +index 03de1d107..880ff3932 100644 +--- a/gio/gdbus-2.0/codegen/codegen_main.py ++++ b/gio/gdbus-2.0/codegen/codegen_main.py +@@ -281,6 +281,7 @@ def codegen_main(): + gen = codegen.InterfaceInfoHeaderCodeGenerator(all_ifaces, + args.c_namespace, + header_name, ++ input_files_basenames, + args.pragma_once, + outfile) + gen.generate() +@@ -290,6 +291,7 @@ def codegen_main(): + gen = codegen.InterfaceInfoBodyCodeGenerator(all_ifaces, + args.c_namespace, + header_name, ++ input_files_basenames, + outfile) + gen.generate() + +-- +2.19.1 + diff --git a/gdbusmessage-Fix-check-on-upper-limit-of-message-siz.patch b/gdbusmessage-Fix-check-on-upper-limit-of-message-siz.patch new file mode 100644 index 0000000..81459f2 --- /dev/null +++ b/gdbusmessage-Fix-check-on-upper-limit-of-message-siz.patch @@ -0,0 +1,121 @@ +From 31b0ba18c190d2508ac4266e5e2e4cf167fada4c Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Mon, 28 Jan 2019 14:36:42 +0000 +Subject: [PATCH 533/682] gdbusmessage: Fix check on upper limit of message + size + +There was a typo in the figure checked against. Add a unit test. + +Signed-off-by: Philip Withnall + +https://gitlab.gnome.org/GNOME/glib/issues/1642 +--- + gio/gdbusmessage.c | 2 +- + gio/tests/gdbus-message.c | 72 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 72 insertions(+), 2 deletions(-) + +diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c +index b9f32e921..3221b925d 100644 +--- a/gio/gdbusmessage.c ++++ b/gio/gdbusmessage.c +@@ -1984,7 +1984,7 @@ g_dbus_message_bytes_needed (guchar *blob, + "Unable to determine message blob length - given blob is malformed"); + } + +- if (ret > (2<<27)) ++ if (ret > (1<<27)) + { + g_set_error (error, + G_IO_ERROR, +diff --git a/gio/tests/gdbus-message.c b/gio/tests/gdbus-message.c +index 278ccc474..5cb141d94 100644 +--- a/gio/tests/gdbus-message.c ++++ b/gio/tests/gdbus-message.c +@@ -141,6 +141,74 @@ message_copy (void) + + /* ---------------------------------------------------------------------------------------------------- */ + ++/* Test g_dbus_message_bytes_needed() returns correct results for a variety of ++ * arbitrary binary inputs.*/ ++static void ++message_bytes_needed (void) ++{ ++ const struct ++ { ++ const guint8 blob[16]; ++ gssize expected_bytes_needed; ++ } ++ vectors[] = ++ { ++ /* Little endian with header rounding */ ++ { { 'l', 0, 0, 1, /* endianness, message type, flags, protocol version */ ++ 50, 0, 0, 0, /* body length */ ++ 1, 0, 0, 0, /* message serial */ ++ 7, 0, 0, 0 /* header length */}, 74 }, ++ /* Little endian without header rounding */ ++ { { 'l', 0, 0, 1, /* endianness, message type, flags, protocol version */ ++ 50, 0, 0, 0, /* body length */ ++ 1, 0, 0, 0, /* message serial */ ++ 8, 0, 0, 0 /* header length */}, 74 }, ++ /* Big endian with header rounding */ ++ { { 'B', 0, 0, 1, /* endianness, message type, flags, protocol version */ ++ 0, 0, 0, 50, /* body length */ ++ 0, 0, 0, 1, /* message serial */ ++ 0, 0, 0, 7 /* header length */}, 74 }, ++ /* Big endian without header rounding */ ++ { { 'B', 0, 0, 1, /* endianness, message type, flags, protocol version */ ++ 0, 0, 0, 50, /* body length */ ++ 0, 0, 0, 1, /* message serial */ ++ 0, 0, 0, 8 /* header length */}, 74 }, ++ /* Invalid endianness */ ++ { { '!', 0, 0, 1, /* endianness, message type, flags, protocol version */ ++ 0, 0, 0, 50, /* body length */ ++ 0, 0, 0, 1, /* message serial */ ++ 0, 0, 0, 8 /* header length */}, -1 }, ++ /* Oversized */ ++ { { 'l', 0, 0, 1, /* endianness, message type, flags, protocol version */ ++ 0, 0, 0, 0x08, /* body length (128MiB) */ ++ 1, 0, 0, 0, /* message serial */ ++ 7, 0, 0, 0 /* header length */}, -1 }, ++ }; ++ gsize i; ++ ++ for (i = 0; i < G_N_ELEMENTS (vectors); i++) ++ { ++ gssize bytes_needed; ++ GError *local_error = NULL; ++ ++ g_test_message ("Vector: %" G_GSIZE_FORMAT, i); ++ ++ bytes_needed = g_dbus_message_bytes_needed ((guchar *) vectors[i].blob, ++ G_N_ELEMENTS (vectors[i].blob), ++ &local_error); ++ ++ if (vectors[i].expected_bytes_needed < 0) ++ g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT); ++ else ++ g_assert_no_error (local_error); ++ g_assert_cmpint (bytes_needed, ==, vectors[i].expected_bytes_needed); ++ ++ g_clear_error (&local_error); ++ } ++} ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ + int + main (int argc, + char *argv[]) +@@ -151,6 +219,8 @@ main (int argc, + + g_test_add_func ("/gdbus/message/lock", message_lock); + g_test_add_func ("/gdbus/message/copy", message_copy); +- return g_test_run(); ++ g_test_add_func ("/gdbus/message/bytes-needed", message_bytes_needed); ++ ++ return g_test_run (); + } + +-- +2.19.1 + diff --git a/gdbusproxy-make-g-name-owner-property-useful-with-un.patch b/gdbusproxy-make-g-name-owner-property-useful-with-un.patch new file mode 100644 index 0000000..f951baa --- /dev/null +++ b/gdbusproxy-make-g-name-owner-property-useful-with-un.patch @@ -0,0 +1,307 @@ +From 47be0f7a233e673a74566e9fb668955cc76fbdab Mon Sep 17 00:00:00 2001 +From: Cosimo Cecchi +Date: Wed, 6 Dec 2017 10:34:17 -0800 +Subject: [PATCH 244/682] gdbusproxy: make g-name-owner property useful with + unique names + +Currently, GDBusProxy:g-name-owner only notifies changes to the unique +name owner of the remote object in case the proxy was constructed for a +well-known name. +That sounds like an artificial restriction, and it's convenient to +connect to notify::g-name-owner if a proxy instance has already been +created for an unique name, instead of additionally using +g_bus_watch_name() to track the owner. + +To fix this, always connect to NameOwnerChanged after the proxy is +initialized, instead of only doing so when the proxy was constructed for +a well-known name. + +https://bugzilla.gnome.org/show_bug.cgi?id=791316 +https://gitlab.gnome.org/GNOME/glib/issues/1310 +--- + gio/gdbusproxy.c | 5 +- + gio/tests/Makefile.am | 2 + + gio/tests/gdbus-proxy-unique-name.c | 215 ++++++++++++++++++++++++++++ + gio/tests/meson.build | 1 + + 4 files changed, 220 insertions(+), 3 deletions(-) + create mode 100644 gio/tests/gdbus-proxy-unique-name.c + +diff --git a/gio/gdbusproxy.c b/gio/gdbusproxy.c +index 6d84deced..9cfb82d70 100644 +--- a/gio/gdbusproxy.c ++++ b/gio/gdbusproxy.c +@@ -59,8 +59,7 @@ + * well-known name, the property cache is flushed when the name owner + * vanishes and reloaded when a name owner appears. + * +- * If a #GDBusProxy is used for a well-known name, the owner of the +- * name is tracked and can be read from ++ * The unique name owner of the proxy's name is tracked and can be read from + * #GDBusProxy:g-name-owner. Connect to the #GObject::notify signal to + * get notified of changes. Additionally, only signals and property + * changes emitted from the current name owner are considered and +@@ -1769,7 +1768,7 @@ async_initable_init_first (GAsyncInitable *initable) + (GDestroyNotify) signal_subscription_unref); + } + +- if (proxy->priv->name != NULL && !g_dbus_is_unique_name (proxy->priv->name)) ++ if (proxy->priv->name != NULL) + { + proxy->priv->name_owner_changed_subscription_id = + g_dbus_connection_signal_subscribe (proxy->priv->connection, +diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am +index b8a414954..8efb1eaa0 100644 +--- a/gio/tests/Makefile.am ++++ b/gio/tests/Makefile.am +@@ -449,6 +449,7 @@ test_programs += \ + gdbus-peer \ + gdbus-proxy \ + gdbus-proxy-threads \ ++ gdbus-proxy-unique-name \ + gdbus-proxy-well-known-name \ + gdbus-test-codegen \ + gdbus-test-codegen-old \ +@@ -483,6 +484,7 @@ gdbus_introspection_SOURCES = $(gdbus_sessionbus_sources) gdbus-int + gdbus_names_SOURCES = $(gdbus_sessionbus_sources) gdbus-names.c + gdbus_proxy_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy.c + gdbus_proxy_threads_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy-threads.c ++gdbus_proxy_unique_name_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy-unique-name.c + gdbus_proxy_well_known_name_SOURCES = $(gdbus_sessionbus_sources) gdbus-proxy-well-known-name.c + gdbus_test_codegen_SOURCES = $(gdbus_sessionbus_sources) gdbus-test-codegen.c + nodist_gdbus_test_codegen_SOURCES = gdbus-test-codegen-generated.c gdbus-test-codegen-generated.h +diff --git a/gio/tests/gdbus-proxy-unique-name.c b/gio/tests/gdbus-proxy-unique-name.c +new file mode 100644 +index 000000000..eacb0219c +--- /dev/null ++++ b/gio/tests/gdbus-proxy-unique-name.c +@@ -0,0 +1,215 @@ ++/* GLib testing framework examples and tests ++ * ++ * Copyright (C) 2008-2010 Red Hat, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General ++ * Public License along with this library; if not, see . ++ * ++ * Author: Cosimo Cecchi ++ */ ++ ++#include ++#include ++#include ++ ++#include "gdbus-tests.h" ++ ++/* all tests rely on a shared mainloop */ ++static GMainLoop *loop = NULL; ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ ++static void ++proxy_new_cb (GObject *source_object, ++ GAsyncResult *res, ++ gpointer user_data) ++{ ++ GDBusProxy **ret = user_data; ++ GError *error; ++ ++ error = NULL; ++ *ret = g_dbus_proxy_new_finish (res, &error); ++ g_assert_no_error (error); ++ g_assert_nonnull (ret); ++ ++ g_main_loop_quit (loop); ++} ++ ++static void ++test_proxy_unique_name (void) ++{ ++ GDBusProxy *wp; ++ GDBusProxy *p; ++ GDBusProxy *ap; ++ GDBusConnection *c; ++ GError *error; ++ gchar *name_owner; ++ gchar **property_names; ++ GVariant *variant; ++ GVariant *result; ++ char *unique_name; ++ ++ session_bus_up (); ++ ++ error = NULL; ++ c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); ++ g_assert_no_error (error); ++ g_assert_nonnull (c); ++ ++ /* use a proxy to the well-known name to set things up */ ++ wp = g_dbus_proxy_new_sync (c, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, /* GDBusInterfaceInfo* */ ++ "com.example.TestService", /* name */ ++ "/com/example/TestObject", /* object path */ ++ "com.example.Frob", /* interface name */ ++ NULL, /* GCancellable */ ++ &error); ++ g_assert_no_error (error); ++ ++ /* this is safe; testserver will exit once the bus goes away */ ++ g_assert_true (g_spawn_command_line_async (g_test_get_filename (G_TEST_BUILT, "gdbus-testserver", NULL), NULL)); ++ ++ /* check that we get the notify::g-name-owner signal */ ++ _g_assert_property_notify (wp, "g-name-owner"); ++ ++ /* now get the unique name of testserver's connection */ ++ unique_name = g_dbus_proxy_get_name_owner (wp); ++ ++ /* if we create another a proxy with the service being available, check that ++ * it has a name owner and properties ++ */ ++ error = NULL; ++ p = g_dbus_proxy_new_sync (c, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, /* GDBusInterfaceInfo* */ ++ unique_name, /* name */ ++ "/com/example/TestObject", /* object path */ ++ "com.example.Frob", /* interface name */ ++ NULL, /* GCancellable */ ++ &error); ++ g_assert_no_error (error); ++ name_owner = g_dbus_proxy_get_name_owner (p); ++ property_names = g_dbus_proxy_get_cached_property_names (p); ++ g_assert_true (g_dbus_is_unique_name (name_owner)); ++ g_assert_nonnull (property_names); ++ g_assert_cmpint (g_strv_length (property_names), >, 0); ++ g_free (name_owner); ++ g_strfreev (property_names); ++ ++ /* also for async: we should have a name owner and cached properties */ ++ g_dbus_proxy_new (c, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, /* GDBusInterfaceInfo* */ ++ unique_name, /* name */ ++ "/com/example/TestObject", /* object path */ ++ "com.example.Frob", /* interface name */ ++ NULL, /* GCancellable */ ++ (GAsyncReadyCallback) proxy_new_cb, ++ &ap); ++ g_main_loop_run (loop); ++ name_owner = g_dbus_proxy_get_name_owner (ap); ++ property_names = g_dbus_proxy_get_cached_property_names (ap); ++ g_assert_true (g_dbus_is_unique_name (name_owner)); ++ g_assert_nonnull (property_names); ++ g_assert_cmpint (g_strv_length (property_names), >, 0); ++ g_free (name_owner); ++ g_strfreev (property_names); ++ ++ /* Check property value is the initial value */ ++ variant = g_dbus_proxy_get_cached_property (p, "y"); ++ g_assert_nonnull (variant); ++ g_assert_cmpint (g_variant_get_byte (variant), ==, 1); ++ g_variant_unref (variant); ++ variant = g_dbus_proxy_get_cached_property (ap, "y"); ++ g_assert_nonnull (variant); ++ g_assert_cmpint (g_variant_get_byte (variant), ==, 1); ++ g_variant_unref (variant); ++ ++ /* Check that properties are updated on p */ ++ result = g_dbus_proxy_call_sync (p, ++ "FrobSetProperty", ++ g_variant_new ("(sv)", ++ "y", ++ g_variant_new_byte (42)), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ NULL, ++ &error); ++ g_assert_no_error (error); ++ g_assert_nonnull (result); ++ g_assert_cmpstr (g_variant_get_type_string (result), ==, "()"); ++ g_variant_unref (result); ++ _g_assert_signal_received (p, "g-properties-changed"); ++ variant = g_dbus_proxy_get_cached_property (p, "y"); ++ g_assert_nonnull (variant); ++ g_assert_cmpint (g_variant_get_byte (variant), ==, 42); ++ g_variant_unref (variant); ++ variant = g_dbus_proxy_get_cached_property (ap, "y"); ++ g_assert_nonnull (variant); ++ g_assert_cmpint (g_variant_get_byte (variant), ==, 42); ++ g_variant_unref (variant); ++ ++ /* Nuke the service and check that we get the signal and then don't ++ * have a name owner nor any cached properties ++ */ ++ result = g_dbus_proxy_call_sync (p, ++ "Quit", ++ NULL, ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ NULL, ++ &error); ++ g_assert_no_error (error); ++ g_assert_nonnull (result); ++ g_assert_cmpstr (g_variant_get_type_string (result), ==, "()"); ++ g_variant_unref (result); ++ /* and wait... */ ++ _g_assert_property_notify (p, "g-name-owner"); ++ /* now we shouldn't have a name owner nor any cached properties */ ++ g_assert_cmpstr (g_dbus_proxy_get_name_owner (p), ==, NULL); ++ g_assert_null (g_dbus_proxy_get_cached_property_names (p)); ++ g_assert_null (g_dbus_proxy_get_cached_property (p, "y")); ++ ++ g_object_unref (p); ++ g_object_unref (ap); ++ ++ g_object_unref (wp); ++ g_free (unique_name); ++ ++ g_object_unref (c); ++ ++ /* tear down bus */ ++ session_bus_down (); ++} ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ ++int ++main (int argc, ++ char *argv[]) ++{ ++ gint ret; ++ ++ g_test_init (&argc, &argv, NULL); ++ ++ /* all the tests rely on a shared main loop */ ++ loop = g_main_loop_new (NULL, FALSE); ++ ++ g_test_dbus_unset (); ++ ++ g_test_add_func ("/gdbus/proxy-unique-name", test_proxy_unique_name); ++ ++ ret = g_test_run(); ++ return ret; ++} +diff --git a/gio/tests/meson.build b/gio/tests/meson.build +index b71f61704..61c6be096 100644 +--- a/gio/tests/meson.build ++++ b/gio/tests/meson.build +@@ -221,6 +221,7 @@ if host_machine.system() != 'windows' + 'extra_sources' : extra_sources, + 'dependencies' : [dbus1_dep], + }, ++ 'gdbus-proxy-unique-name' : {'extra_sources' : extra_sources}, + 'gdbus-proxy-well-known-name' : {'extra_sources' : extra_sources}, + 'gdbus-test-codegen' : { + 'extra_sources' : [extra_sources, gdbus_test_codegen_generated], +-- +2.19.1 + diff --git a/gfile-Fix-leak-in-g_file_query_default_handler.patch b/gfile-Fix-leak-in-g_file_query_default_handler.patch new file mode 100644 index 0000000..d9f8809 --- /dev/null +++ b/gfile-Fix-leak-in-g_file_query_default_handler.patch @@ -0,0 +1,27 @@ +From 0a1730d7ea486d07a10b238d7f6fdaa41218c5e4 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Mon, 28 Jan 2019 15:18:37 +0100 +Subject: [PATCH 534/682] gfile: Fix leak in g_file_query_default_handler() + +Add missing `g_free (uri_scheme)` to fix leak when `uri_scheme[0]` +is equal to `\0`. +--- + gio/gfile.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/gio/gfile.c b/gio/gfile.c +index a5709a4cc..e6b468b55 100644 +--- a/gio/gfile.c ++++ b/gio/gfile.c +@@ -6851,6 +6851,8 @@ g_file_query_default_handler (GFile *file, + if (appinfo != NULL) + return appinfo; + } ++ else ++ g_free (uri_scheme); + + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, +-- +2.19.1 + diff --git a/gio-don-t-use-O_PATH-file-descriptors-with-OpenURI-p.patch b/gio-don-t-use-O_PATH-file-descriptors-with-OpenURI-p.patch new file mode 100644 index 0000000..7ffaef8 --- /dev/null +++ b/gio-don-t-use-O_PATH-file-descriptors-with-OpenURI-p.patch @@ -0,0 +1,55 @@ +From e244a78fbcbba3ab116f5a62f724a8f6cd926570 Mon Sep 17 00:00:00 2001 +From: James Henstridge +Date: Tue, 15 Jan 2019 15:59:46 +0800 +Subject: [PATCH 455/682] gio: don't use O_PATH file descriptors with OpenURI + portal + +This change relates to https://github.com/flatpak/xdg-desktop-portal/issues/167 + +The OpenURI portal requires the caller to pass a file descriptor as +proof of access for local files. Old versions required this file +descriptor to use the O_PATH mode. However, this does not prove access +since you can create O_PATH descriptors for files that you can't read. + +Since xdg-desktop-portal 1.0.1, regular file descriptors are also +accepted with O_PATH descriptors restricted to flatpaks for the +transition. +--- + gio/gopenuriportal.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/gio/gopenuriportal.c b/gio/gopenuriportal.c +index 38d60bf68..b798d7cd1 100644 +--- a/gio/gopenuriportal.c ++++ b/gio/gopenuriportal.c +@@ -31,9 +31,6 @@ + #include "gunixfdlist.h" + #endif + +-#ifndef O_PATH +-#define O_PATH 0 +-#endif + #ifndef O_CLOEXEC + #define O_CLOEXEC 0 + #else +@@ -107,7 +104,7 @@ g_openuri_portal_open_uri (const char *uri, + + path = g_file_get_path (file); + +- fd = g_open (path, O_PATH | O_CLOEXEC); ++ fd = g_open (path, O_RDONLY | O_CLOEXEC); + errsv = errno; + if (fd == -1) + { +@@ -318,7 +315,7 @@ g_openuri_portal_open_uri_async (const char *uri, + g_object_set_data (G_OBJECT (task), "open-file", GINT_TO_POINTER (TRUE)); + + path = g_file_get_path (file); +- fd = g_open (path, O_PATH | O_CLOEXEC); ++ fd = g_open (path, O_RDONLY | O_CLOEXEC); + errsv = errno; + if (fd == -1) + { +-- +2.19.1 + diff --git a/glib-2.58.1.tar.xz b/glib-2.58.1.tar.xz new file mode 100644 index 0000000..d1c06ac Binary files /dev/null and b/glib-2.58.1.tar.xz differ diff --git a/glib-compile-resources-Fix-a-minor-leak.patch b/glib-compile-resources-Fix-a-minor-leak.patch new file mode 100644 index 0000000..3d99d49 --- /dev/null +++ b/glib-compile-resources-Fix-a-minor-leak.patch @@ -0,0 +1,29 @@ +From 7321f240f914fa07f58c8789e219045d7282beae Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Fri, 22 Feb 2019 14:47:46 +0000 +Subject: [PATCH 623/682] glib-compile-resources: Fix a minor leak + +Spotted by oss-fuzz using asan. + +oss-fuzz#13271 + +Signed-off-by: Philip Withnall +--- + gio/glib-compile-resources.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c +index f04ea488b..399c567d2 100644 +--- a/gio/glib-compile-resources.c ++++ b/gio/glib-compile-resources.c +@@ -999,6 +999,7 @@ main (int argc, char **argv) + + } + ++ g_free (base); + c_name = g_string_free (s, FALSE); + } + } +-- +2.19.1 + diff --git a/glib-compile-resources-Fix-size-allocation-for-compr.patch b/glib-compile-resources-Fix-size-allocation-for-compr.patch new file mode 100644 index 0000000..8501c31 --- /dev/null +++ b/glib-compile-resources-Fix-size-allocation-for-compr.patch @@ -0,0 +1,32 @@ +From 0985e70488cede2e856381fd2185d8aaf305b72d Mon Sep 17 00:00:00 2001 +From: vmlobanov78 +Date: Tue, 18 Sep 2018 10:34:23 +0000 +Subject: [PATCH 239/682] glib-compile-resources: Fix size allocation for + compressed streams +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The length of the stolen data from a memory output stream is given by +get_data_size() — get_size() can be larger, and hence cause unnecessary +overallocation. +--- + gio/glib-compile-resources.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c +index 6ce5aec4a..7e318b254 100644 +--- a/gio/glib-compile-resources.c ++++ b/gio/glib-compile-resources.c +@@ -483,7 +483,7 @@ end_element (GMarkupParseContext *context, + } + + g_free (data->content); +- data->content_size = g_memory_output_stream_get_size (G_MEMORY_OUTPUT_STREAM (out)); ++ data->content_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (out)); + data->content = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (out)); + + g_object_unref (compressor); +-- +2.19.1 + diff --git a/glib-compile-resources-Fixes-1675.patch b/glib-compile-resources-Fixes-1675.patch new file mode 100644 index 0000000..a911143 --- /dev/null +++ b/glib-compile-resources-Fixes-1675.patch @@ -0,0 +1,38 @@ +From 45655b8265349d8e94b7472b6deb54adb3a63f38 Mon Sep 17 00:00:00 2001 +From: Felix Potthast +Date: Wed, 20 Feb 2019 10:38:29 +0000 +Subject: [PATCH 614/682] glib-compile-resources: Fixes #1675 + +--- + gio/glib-compile-resources.c | 2 +- + gio/tests/111_digit_test.gresource.xml | 6 +++++ + gio/tests/meson.build | 25 ++++++++++++++++-- + gio/tests/resources.c | 35 ++++++++++++++++++++++++++ + 4 files changed, 65 insertions(+), 3 deletions(-) + create mode 100644 gio/tests/111_digit_test.gresource.xml + +diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c +index 60ccdbf81..f04ea488b 100644 +--- a/gio/glib-compile-resources.c ++++ b/gio/glib-compile-resources.c +@@ -992,7 +992,7 @@ main (int argc, char **argv) + { + const char *first = G_CSET_A_2_Z G_CSET_a_2_z "_"; + const char *rest = G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_"; +- if (strchr ((i == 0) ? first : rest, base[i]) != NULL) ++ if (strchr ((s->len == 0) ? first : rest, base[i]) != NULL) + g_string_append_c (s, base[i]); + else if (base[i] == '-') + g_string_append_c (s, '_'); +diff --git a/gio/tests/111_digit_test.gresource.xml b/gio/tests/111_digit_test.gresource.xml +new file mode 100644 +index 000000000..00efcc315 +--- /dev/null ++++ b/gio/tests/111_digit_test.gresource.xml +@@ -0,0 +1,6 @@ ++ ++ ++ ++ test1.txt ++ ++ diff --git a/glib-gcharset-fix-leaking-g_get_language_names_with_.patch b/glib-gcharset-fix-leaking-g_get_language_names_with_.patch new file mode 100644 index 0000000..cde9198 --- /dev/null +++ b/glib-gcharset-fix-leaking-g_get_language_names_with_.patch @@ -0,0 +1,69 @@ +From 1f6db2a5c5822a55a83bfdc830f1548908b3c75c Mon Sep 17 00:00:00 2001 +From: Mikhail Fludkov +Date: Thu, 20 Sep 2018 16:08:19 +0200 +Subject: [PATCH 079/682] glib/gcharset: fix leaking + g_get_language_names_with_category + +--- + glib/gcharset.c | 7 ++++--- + glib/tests/charset.c | 13 +++++++++++++ + 2 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/glib/gcharset.c b/glib/gcharset.c +index bfcd12590..a97b33a03 100644 +--- a/glib/gcharset.c ++++ b/glib/gcharset.c +@@ -576,15 +576,16 @@ g_get_language_names (void) + * + * g_get_language_names() returns g_get_language_names_with_category("LC_MESSAGES"). + * +- * Returns: (array zero-terminated=1) (transfer none): a %NULL-terminated array of strings owned by GLib +- * that must not be modified or freed. ++ * Returns: (array zero-terminated=1) (transfer none): a %NULL-terminated array of strings owned by ++ * the thread g_get_language_names_with_category was called from. ++ * It must not be modified or freed. It must be copied if planned to be used in another thread. + * + * Since: 2.58 + */ + const gchar * const * + g_get_language_names_with_category (const gchar *category_name) + { +- static GPrivate cache_private = G_PRIVATE_INIT ((void (*)(gpointer)) g_hash_table_remove_all); ++ static GPrivate cache_private = G_PRIVATE_INIT ((void (*)(gpointer)) g_hash_table_unref); + GHashTable *cache = g_private_get (&cache_private); + const gchar *languages; + GLanguageNamesCache *name_cache; +diff --git a/glib/tests/charset.c b/glib/tests/charset.c +index 0a1c8ce3f..363eedfd1 100644 +--- a/glib/tests/charset.c ++++ b/glib/tests/charset.c +@@ -59,6 +59,18 @@ test_language_names_with_category (void) + } + } + ++static void ++test_language_names_with_category_async (void) ++{ ++ g_thread_join (g_thread_new ( ++ NULL, (GThreadFunc)g_get_language_names_with_category, "LC_CTYPE")); ++ ++ /* g_get_language_names_with_category returns a pointer to a memory ++ which is owned by a thread it has been called from. The thread is dead now, ++ therefore returned pointer can't be used at this stage. ++ */ ++} ++ + int + main (int argc, char *argv[]) + { +@@ -67,6 +79,7 @@ main (int argc, char *argv[]) + g_test_bug_base ("http://bugs.gnome.org/"); + + g_test_add_func ("/charset/language_names_with_category", test_language_names_with_category); ++ g_test_add_func ("/charset/language_names_with_category_async", test_language_names_with_category_async); + + return g_test_run (); + } +-- +2.19.1 + diff --git a/glib2.spec b/glib2.spec new file mode 100644 index 0000000..c5c4f7e --- /dev/null +++ b/glib2.spec @@ -0,0 +1,182 @@ +Name: glib2 +Version: 2.58.1 +Release: 3 +Summary: The core library that forms the basis for projects such as GTK+ and GNOME +License: LGPLv2+ +URL: http://www.gtk.org +Source0: http://download.gnome.org/sources/glib/2.58/glib-%{version}.tar.xz + +Patch6000: gnetworkmonitornm-Set-a-GError-properly-on-an-error-.patch +Patch6001: glib-gcharset-fix-leaking-g_get_language_names_with_.patch +Patch6002: gtask-Check-an-error-hasn-t-been-returned-when-calli.patch +Patch6003: gmacros-Fix-G_-UN-LIKELY-to-not-mask-Wparentheses.patch +Patch6004: grefcount-add-missing-gatomic.h.patch +Patch6005: glocalfile-Fix-access-can-trash-if-parent-is-symlink.patch +Patch6006: gvariant-Fix-checking-arithmetic-for-tuple-element-e.patch +Patch6007: gmarkup-Fix-validation-of-element-names.patch +Patch6008: gdatetime-Fix-formatting-of-time-zones-offsets-in-ra.patch +Patch6009: gobject-genums.c-fix-flags-validation.patch +Patch6010: bookmarkfile-Don-t-move-an-item-if-the-uri-has-not-c.patch +Patch6011: gvariant-Realign-data-on-construction-if-it-s-not-pr.patch +Patch6012: glib-compile-resources-Fix-size-allocation-for-compr.patch +Patch6013: gdbusproxy-make-g-name-owner-property-useful-with-un.patch +Patch6014: gmessages-don-t-memoize-in-g_log_writer_is_journald.patch +Patch6015: gdate-Use-longest-matching-month-name-in-g_date_set_.patch +Patch6016: gmain-Make-GChildWatchSource-child_exited-field-atom.patch +Patch6017: gmain-Make-GUnixSignalWatchSource-pending-field-atom.patch +Patch6018: gspawn-Fix-g_spawn-deadlock-in-a-multi-threaded-prog.patch +Patch6019: gunixmounts-Don-t-treat-ZFS-as-a-system-internal-fs.patch +Patch6020: g_timeout_-_seconds-don-t-overflow-for-large-interva.patch +Patch6021: gdatetime-Store-intermediate-result-of-g_date_time_f.patch +Patch6022: gvariant-Fix-error-handling-for-parsing-Unicode-esca.patch +Patch6023: gdbus-codegen-make-interface-info-header-body-not-cr.patch +Patch6024: gtlscertificate-Fix-bug-in-PEM-private-key-parser.patch +Patch6025: gtask-Ensure-to-return-1-or-0-from-getters-rather-th.patch +Patch6026: list-store-Fix-overflow-issues.patch +Patch6027: gio-don-t-use-O_PATH-file-descriptors-with-OpenURI-p.patch +Patch6028: gdbusmessage-Fix-check-on-upper-limit-of-message-siz.patch +Patch6029: gfile-Fix-leak-in-g_file_query_default_handler.patch +Patch6030: gdbus-Avoid-printing-null-strings.patch +Patch6031: gsettingsbackend-Fix-a-minor-memory-leak.patch +Patch6032: Fixing-missing-initializer-in-g_static_rec_mutex_ini.patch +Patch6033: gobject-Change-assertions-to-read-values-via-atomics.patch +Patch6034: gvariant-parser-Add-explicit-unsigned-to-signed-cast.patch +Patch6035: gvariant-parser-Fix-parsing-of-G_MININT-values-in-GV.patch +Patch6036: gvariant-parser-Fix-error-handling-when-type-coalesc.patch +Patch6037: gsocketlistener-Fix-multiple-returns-of-GTask-when-a.patch +Patch6038: gdbus-Fix-a-potential-use-after-free-on-connection-c.patch +Patch6039: glib-compile-resources-Fixes-1675.patch +Patch6040: glib-compile-resources-Fix-a-minor-leak.patch +Patch6041: glocalfilemonitor-Fix-data-race-in-local-file-monito.patch +Patch6042: gbase64-Allow-g_base64_encode-NULL-0-and-g_base64_de.patch +Patch6043: gbase64-Fix-an-impossible-condition.patch +Patch6044: CVE-2019-12450.patch +Patch6045: CVE-2019-13012.patch + +BuildRequires: automake chrpath autoconf gtk-doc libtool gettext perl-interpreter gamin-devel +BUildRequires: glibc-devel python3-devel libattr-devel libselinux-devel systemtap-sdt-devel +BuildRequires: pkgconfig(libelf) pkgconfig(libffi) pkgconfig(libpcre) pkgconfig(mount) pkgconfig(zlib) +provides: glib2-fam +Obsoletes: glib2-fam + +Recommends: shared-mime-info + +%description +GLib is a bundle of three (formerly five) low-level system libraries +written in C and developed mainly by GNOME. GLib's code was separated +from GTK, so it can be used by software other than GNOME and has been +developed in parallel ever since. + +%package devel +Summary: Development and test files for the GLib library +Requires: %{name} = %{version}-%{release} +provides: glib2-static glib2-tests +Obsoletes: glib2-static glib2-tests + +%description devel +Development and test files for the GLib library. + +%package help +Summary: help document for the glib2 package +Buildarch: noarch +provides: glib2-doc +Obsoletes: glib2-doc + +%description help +help document for the glib2 package. + +%prep +%autosetup -n glib-%{version} -p1 + +%build +rm glib/pcre/*.[ch] +(if ! test -x configure; then NOCONFIGURE=1 ./autogen.sh; CONFIGFLAGS=--enable-gtk-doc; fi; + %configure $CONFIGFLAGS --disable-silent-rules --with-python=%{__python3} --with-pcre=system --enable-systemtap --enable-static --enable-installed-tests +) + +%make_build + +%install +%make_install +touch -r gio/gdbus-2.0/codegen/config.py.in $RPM_BUILD_ROOT/%{_datadir}/glib-2.0/codegen/config.py +touch -r gio/gdbus-2.0/codegen/config.py.in $RPM_BUILD_ROOT/%{_datadir}/glib-2.0/codegen/codegen_main.py +chrpath --delete $RPM_BUILD_ROOT%{_libdir}/*.so + +mv $RPM_BUILD_ROOT%{_bindir}/gio-querymodules $RPM_BUILD_ROOT%{_bindir}/gio-querymodules-%{__isa_bits} +touch $RPM_BUILD_ROOT%{_libdir}/gio/modules/giomodule.cache +chmod 644 $RPM_BUILD_ROOT%{_datadir}/bash-completion/completions/* +%find_lang glib20 + +%transfiletriggerin -- %{_libdir}/gio/modules +gio-querymodules-%{__isa_bits} %{_libdir}/gio/modules &> /dev/null || : + +%transfiletriggerpostun -- %{_libdir}/gio/modules +gio-querymodules-%{__isa_bits} %{_libdir}/gio/modules &> /dev/null || : + +%transfiletriggerin -- %{_datadir}/glib-2.0/schemas +glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : + +%transfiletriggerpostun -- %{_datadir}/glib-2.0/schemas +glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : + +%files -f glib20.lang +%doc AUTHORS NEWS README COPYING +%{_libdir}/*.so.* +%{_datadir}/bash-completion/completions/gapplication +%{_datadir}/bash-completion/completions/gdbus +%{_datadir}/bash-completion/completions/gio +%{_datadir}/bash-completion/completions/gsettings +%dir %{_datadir}/glib-2.0/schemas +%dir %{_libdir}/gio/modules +%ghost %{_libdir}/gio/modules/giomodule.cache +%{_bindir}/gio +%{_bindir}/gio-launch-desktop +%{_bindir}/gio-querymodules* +%{_bindir}/glib-compile-schemas +%{_bindir}/gsettings +%{_bindir}/gdbus +%{_bindir}/gapplication +%{_libdir}/gio/modules/libgiofam.so + +%files devel +%{_libdir}/lib*.so +%{_libdir}/glib-2.0 +%{_includedir}/* +%{_datadir}/aclocal/* +%{_libdir}/pkgconfig/* +%{_datadir}/glib-2.0/* +%{_datadir}/bash-completion/completions/gresource +%{_bindir}/glib-genmarshal +%{_bindir}/glib-gettextize +%{_bindir}/glib-mkenums +%{_bindir}/gobject-query +%{_bindir}/gtester +%{_bindir}/gdbus-codegen +%{_bindir}/glib-compile-resources +%{_bindir}/gresource +%{_datadir}/glib-2.0/codegen +%attr (0755, root, root) %{_bindir}/gtester-report +%{_datadir}/gdb/ +%{_datadir}/gettext/ +%{_datadir}/systemtap/ +%{_libdir}/*.a +%{_libexecdir}/installed-tests +%{_datadir}/installed-tests +%exclude %{_libdir}/*.la +%exclude %{_libdir}/gio/modules/*.{a,la} +%exclude %{_datadir}/glib-2.0/gdb/*.{pyc,pyo} +%exclude %{_datadir}/glib-2.0/codegen/*.{pyc,pyo} + +%files help +%{_mandir}/man1/* +%doc %{_datadir}/gtk-doc/html/* + +%changelog +* Wed Sep 25 2019 huzunhao - 2.58.1-3 +- Type:cves +- ID:CVE-2019-12450 CVE-2019-13012 +- SUG:restart +- DESC:fix CVE-2019-12450 CVE-2019-13012 + +* Thu Sep 19 2019 Lijin Yang - 2.58.1-2 +- Package init diff --git a/glocalfile-Fix-access-can-trash-if-parent-is-symlink.patch b/glocalfile-Fix-access-can-trash-if-parent-is-symlink.patch new file mode 100644 index 0000000..480ff28 --- /dev/null +++ b/glocalfile-Fix-access-can-trash-if-parent-is-symlink.patch @@ -0,0 +1,205 @@ +From 0f5017fb701b221846f04fa610c8429bbaa49136 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Thu, 13 Sep 2018 17:33:59 +0200 +Subject: [PATCH 152/682] glocalfile: Fix access::can-trash if parent is + symlink + +G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH can be set to a wrong value if +its parent dir is a symlink. This is because the find_mountpoint_for() +function tries to find mountpoint for a filepath and expands symlinks +only in parent dirs. But in this case the path is already parent dir +and needs to be expanded first... + +Closes: https://gitlab.gnome.org/GNOME/glib/issues/1522 +--- + gio/glocalfile.c | 104 +++++++++++++++++++++++++++++------------------ + 1 file changed, 65 insertions(+), 39 deletions(-) + +diff --git a/gio/glocalfile.c b/gio/glocalfile.c +index 30fa2281c..33b5ba3da 100644 +--- a/gio/glocalfile.c ++++ b/gio/glocalfile.c +@@ -109,7 +109,7 @@ G_DEFINE_TYPE_WITH_CODE (GLocalFile, g_local_file, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_FILE, + g_local_file_file_iface_init)) + +-static char *find_mountpoint_for (const char *file, dev_t dev); ++static char *find_mountpoint_for (const char *file, dev_t dev, gboolean resolve_basename_symlink); + + static void + g_local_file_finalize (GObject *object) +@@ -791,7 +791,7 @@ get_mount_info (GFileInfo *fs_info, + { + mount_info = 0; + +- mountpoint = find_mountpoint_for (path, buf.st_dev); ++ mountpoint = find_mountpoint_for (path, buf.st_dev, FALSE); + if (mountpoint == NULL) + mountpoint = g_strdup ("/"); + +@@ -886,7 +886,7 @@ get_volume_for_path (const char *path) + } + + static char * +-find_mountpoint_for (const char *file, dev_t dev) ++find_mountpoint_for (const char *file, dev_t dev, gboolean resolve_basename_symlink) + { + wchar_t *wpath; + char *utf8_path; +@@ -1132,7 +1132,7 @@ g_local_file_find_enclosing_mount (GFile *file, + if (g_lstat (local->filename, &buf) != 0) + goto error; + +- mountpoint = find_mountpoint_for (local->filename, buf.st_dev); ++ mountpoint = find_mountpoint_for (local->filename, buf.st_dev, FALSE); + if (mountpoint == NULL) + goto error; + +@@ -1584,12 +1584,51 @@ expand_symlink (const char *link) + } + + static char * +-get_parent (const char *path, +- dev_t *parent_dev) ++expand_symlinks (const char *path, ++ dev_t *dev) + { +- char *parent, *tmp; +- GStatBuf parent_stat; ++ char *tmp, *target; ++ GStatBuf target_stat; + int num_recursions; ++ ++ target = g_strdup (path); ++ ++ num_recursions = 0; ++ do ++ { ++ if (g_lstat (target, &target_stat) != 0) ++ { ++ g_free (target); ++ return NULL; ++ } ++ ++ if (S_ISLNK (target_stat.st_mode)) ++ { ++ tmp = target; ++ target = expand_symlink (target); ++ g_free (tmp); ++ } ++ ++ num_recursions++; ++ if (num_recursions > 12) ++ { ++ g_free (target); ++ return NULL; ++ } ++ } ++ while (S_ISLNK (target_stat.st_mode)); ++ ++ if (dev) ++ *dev = target_stat.st_dev; ++ ++ return target; ++} ++ ++static char * ++get_parent (const char *path, ++ dev_t *parent_dev) ++{ ++ char *parent, *res; + char *path_copy; + + path_copy = strip_trailing_slashes (path); +@@ -1604,32 +1643,10 @@ get_parent (const char *path, + } + g_free (path_copy); + +- num_recursions = 0; +- do { +- if (g_lstat (parent, &parent_stat) != 0) +- { +- g_free (parent); +- return NULL; +- } +- +- if (S_ISLNK (parent_stat.st_mode)) +- { +- tmp = parent; +- parent = expand_symlink (parent); +- g_free (tmp); +- } +- +- num_recursions++; +- if (num_recursions > 12) +- { +- g_free (parent); +- return NULL; +- } +- } while (S_ISLNK (parent_stat.st_mode)); ++ res = expand_symlinks (parent, parent_dev); ++ g_free (parent); + +- *parent_dev = parent_stat.st_dev; +- +- return parent; ++ return res; + } + + static char * +@@ -1656,13 +1673,22 @@ expand_all_symlinks (const char *path) + } + + static char * +-find_mountpoint_for (const char *file, +- dev_t dev) ++find_mountpoint_for (const char *file, ++ dev_t dev, ++ gboolean resolve_basename_symlink) + { + char *dir, *parent; + dev_t dir_dev, parent_dev; + +- dir = g_strdup (file); ++ if (resolve_basename_symlink) ++ { ++ dir = expand_symlinks (file, NULL); ++ if (dir == NULL) ++ return g_strdup (file); ++ } ++ else ++ dir = g_strdup (file); ++ + dir_dev = dev; + + while (1) +@@ -1693,7 +1719,7 @@ _g_local_file_find_topdir_for (const char *file) + if (dir == NULL) + return NULL; + +- mountpoint = find_mountpoint_for (dir, dir_dev); ++ mountpoint = find_mountpoint_for (dir, dir_dev, TRUE); + g_free (dir); + + return mountpoint; +@@ -1789,7 +1815,7 @@ _g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev) + if (dir_dev == home_dev) + return TRUE; + +- topdir = find_mountpoint_for (dirname, dir_dev); ++ topdir = find_mountpoint_for (dirname, dir_dev, TRUE); + if (topdir == NULL) + return FALSE; + +@@ -1856,7 +1882,7 @@ _g_local_file_is_lost_found_dir (const char *path, dev_t path_dev) + if (!g_str_has_suffix (path, "/lost+found")) + goto out; + +- mount_dir = find_mountpoint_for (path, path_dev); ++ mount_dir = find_mountpoint_for (path, path_dev, FALSE); + if (mount_dir == NULL) + goto out; + +-- +2.19.1 + diff --git a/glocalfilemonitor-Fix-data-race-in-local-file-monito.patch b/glocalfilemonitor-Fix-data-race-in-local-file-monito.patch new file mode 100644 index 0000000..a8e98b9 --- /dev/null +++ b/glocalfilemonitor-Fix-data-race-in-local-file-monito.patch @@ -0,0 +1,37 @@ +From 6336864171d0d14297de5af2aba0a5de00a8d257 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= +Date: Fri, 22 Feb 2019 00:00:00 +0000 +Subject: [PATCH 628/682] glocalfilemonitor: Fix data race in local file + monitor + +Ensure that source is attached to the context before it migth be used +from another thread, since otherwise operation on source are +unsynchronized and not thread-safe. + +In particular there was a data race between g_source_attach and +g_source_set_ready_time (used from g_file_monitor_source_handle_event). +--- + gio/glocalfilemonitor.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gio/glocalfilemonitor.c b/gio/glocalfilemonitor.c +index 8a4c4ec43..278d9a492 100644 +--- a/gio/glocalfilemonitor.c ++++ b/gio/glocalfilemonitor.c +@@ -788,11 +788,11 @@ g_local_file_monitor_start (GLocalFileMonitor *local_monitor, + #endif + } + ++ g_source_attach ((GSource *) source, context); ++ + G_LOCAL_FILE_MONITOR_GET_CLASS (local_monitor)->start (local_monitor, + source->dirname, source->basename, source->filename, + source); +- +- g_source_attach ((GSource *) source, context); + } + + static void +-- +2.19.1 + diff --git a/gmacros-Fix-G_-UN-LIKELY-to-not-mask-Wparentheses.patch b/gmacros-Fix-G_-UN-LIKELY-to-not-mask-Wparentheses.patch new file mode 100644 index 0000000..f4ba77f --- /dev/null +++ b/gmacros-Fix-G_-UN-LIKELY-to-not-mask-Wparentheses.patch @@ -0,0 +1,36 @@ +From 0e7ebf794fdbdeb2a156c2e2aebcd78725793dba Mon Sep 17 00:00:00 2001 +From: Mohammed Sadiq +Date: Thu, 4 Oct 2018 17:38:27 +0530 +Subject: [PATCH 139/682] gmacros: Fix G_[UN]LIKELY to not mask -Wparentheses + +A double paren forces the compiler to assume that the +statement is right. That may not be the case. + +This is essentially reverting b44fba25fbad89c105795a10a569fe422e4d1c44. +See https://bugzilla.gnome.org/show_bug.cgi?id=760215. + +It's more morth to allow find common mistakes (= instead of == +in conditionals) than masking them to make some rarely used +code work. +--- + glib/gmacros.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/glib/gmacros.h b/glib/gmacros.h +index 0432d9cad..8ef65dad2 100644 +--- a/glib/gmacros.h ++++ b/glib/gmacros.h +@@ -427,8 +427,8 @@ + _g_boolean_var_ = 0; \ + _g_boolean_var_; \ + }) +-#define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR((expr)), 1)) +-#define G_UNLIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR((expr)), 0)) ++#define G_LIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 1)) ++#define G_UNLIKELY(expr) (__builtin_expect (_G_BOOLEAN_EXPR(expr), 0)) + #else + #define G_LIKELY(expr) (expr) + #define G_UNLIKELY(expr) (expr) +-- +2.19.1 + diff --git a/gmain-Make-GChildWatchSource-child_exited-field-atom.patch b/gmain-Make-GChildWatchSource-child_exited-field-atom.patch new file mode 100644 index 0000000..7afe0c7 --- /dev/null +++ b/gmain-Make-GChildWatchSource-child_exited-field-atom.patch @@ -0,0 +1,66 @@ +From d2fd53df036af9a931a39b6d28d42fea9f6b5d18 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= +Date: Thu, 1 Nov 2018 00:00:00 +0000 +Subject: [PATCH 260/682] gmain: Make GChildWatchSource child_exited field + atomic + +Ensure synchronization between prepare / check of GChildWatchsource and +UNIX signal dispatcher by making operations on `child_exited` field +atomic. Use `child_exited` as publication flag for `child_status`. + +Issue #1312. +--- + glib/gmain.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/glib/gmain.c b/glib/gmain.c +index e1a680433..ad57b4927 100644 +--- a/glib/gmain.c ++++ b/glib/gmain.c +@@ -5107,7 +5107,7 @@ dispatch_unix_signals_unlocked (void) + { + GChildWatchSource *source = node->data; + +- if (!source->child_exited) ++ if (!g_atomic_int_get (&source->child_exited)) + { + pid_t pid; + do +@@ -5117,14 +5117,14 @@ dispatch_unix_signals_unlocked (void) + pid = waitpid (source->pid, &source->child_status, WNOHANG); + if (pid > 0) + { +- source->child_exited = TRUE; ++ g_atomic_int_set (&source->child_exited, TRUE); + wake_source ((GSource *) source); + } + else if (pid == -1 && errno == ECHILD) + { + g_warning ("GChildWatchSource: Exit status of a child process was requested but ECHILD was received by waitpid(). See the documentation of g_child_watch_source_new() for possible causes."); +- source->child_exited = TRUE; + source->child_status = 0; ++ g_atomic_int_set (&source->child_exited, TRUE); + wake_source ((GSource *) source); + } + } +@@ -5167,7 +5167,7 @@ g_child_watch_prepare (GSource *source, + + child_watch_source = (GChildWatchSource *) source; + +- return child_watch_source->child_exited; ++ return g_atomic_int_get (&child_watch_source->child_exited); + } + + static gboolean +@@ -5177,7 +5177,7 @@ g_child_watch_check (GSource *source) + + child_watch_source = (GChildWatchSource *) source; + +- return child_watch_source->child_exited; ++ return g_atomic_int_get (&child_watch_source->child_exited); + } + + static gboolean +-- +2.19.1 + diff --git a/gmain-Make-GUnixSignalWatchSource-pending-field-atom.patch b/gmain-Make-GUnixSignalWatchSource-pending-field-atom.patch new file mode 100644 index 0000000..4455669 --- /dev/null +++ b/gmain-Make-GUnixSignalWatchSource-pending-field-atom.patch @@ -0,0 +1,67 @@ +From 9e652f94d285b1722ea82a0465c6724eee346738 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= +Date: Thu, 1 Nov 2018 00:00:00 +0000 +Subject: [PATCH 261/682] gmain: Make GUnixSignalWatchSource pending field + atomic + +Ensure synchronization between prepare / check /dispatch of +GUnixSignalWatchSource and UNIX signal dispatcher by making operations +on `pending` field atomic. + +Issue #1312. +--- + glib/gmain.c | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +diff --git a/glib/gmain.c b/glib/gmain.c +index ad57b4927..07ec867bc 100644 +--- a/glib/gmain.c ++++ b/glib/gmain.c +@@ -5138,14 +5138,10 @@ dispatch_unix_signals_unlocked (void) + { + GUnixSignalWatchSource *source = node->data; + +- if (!source->pending) ++ if (pending[source->signum] && ++ g_atomic_int_compare_and_exchange (&source->pending, FALSE, TRUE)) + { +- if (pending[source->signum]) +- { +- source->pending = TRUE; +- +- wake_source ((GSource *) source); +- } ++ wake_source ((GSource *) source); + } + } + +@@ -5188,7 +5184,7 @@ g_unix_signal_watch_prepare (GSource *source, + + unix_signal_source = (GUnixSignalWatchSource *) source; + +- return unix_signal_source->pending; ++ return g_atomic_int_get (&unix_signal_source->pending); + } + + static gboolean +@@ -5198,7 +5194,7 @@ g_unix_signal_watch_check (GSource *source) + + unix_signal_source = (GUnixSignalWatchSource *) source; + +- return unix_signal_source->pending; ++ return g_atomic_int_get (&unix_signal_source->pending); + } + + static gboolean +@@ -5220,7 +5216,7 @@ g_unix_signal_watch_dispatch (GSource *source, + + again = (callback) (user_data); + +- unix_signal_source->pending = FALSE; ++ g_atomic_int_set (&unix_signal_source->pending, FALSE); + + return again; + } +-- +2.19.1 + diff --git a/gmarkup-Fix-validation-of-element-names.patch b/gmarkup-Fix-validation-of-element-names.patch new file mode 100644 index 0000000..4744b27 --- /dev/null +++ b/gmarkup-Fix-validation-of-element-names.patch @@ -0,0 +1,37 @@ +From 2187b1bec481b4d87310792c46d7d9ea59957f07 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Fri, 26 Oct 2018 23:21:46 +1300 +Subject: [PATCH 190/682] gmarkup: Fix validation of element names + +Previously, the element name validation only happened if a start_element +callback was specified on the context. Element name validation should be +unconditional. + +This was causing test-5.gmarkup to fail when run against the improved +tests in the following commit. + +Signed-off-by: Philip Withnall +--- + glib/gmarkup.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/glib/gmarkup.c b/glib/gmarkup.c +index f85c00ab4..7093a6790 100644 +--- a/glib/gmarkup.c ++++ b/glib/gmarkup.c +@@ -1050,8 +1050,10 @@ emit_start_element (GMarkupParseContext *context, + tmp_error = NULL; + start_name = current_element (context); + +- if (context->parser->start_element && +- name_validate (context, start_name, error)) ++ if (!name_validate (context, start_name, error)) ++ return; ++ ++ if (context->parser->start_element) + (* context->parser->start_element) (context, + start_name, + (const gchar **)attr_names, +-- +2.19.1 + diff --git a/gmessages-don-t-memoize-in-g_log_writer_is_journald.patch b/gmessages-don-t-memoize-in-g_log_writer_is_journald.patch new file mode 100644 index 0000000..3ac63c4 --- /dev/null +++ b/gmessages-don-t-memoize-in-g_log_writer_is_journald.patch @@ -0,0 +1,96 @@ +From f1175704b6c48672e480a7006f05944ad6a1e2f8 Mon Sep 17 00:00:00 2001 +From: Will Thompson +Date: Mon, 12 Nov 2018 11:20:49 +0000 +Subject: [PATCH 247/682] gmessages: don't memoize in + g_log_writer_is_journald() + +Previously, g_log_writer_is_journald() would cache the result for the +first (non-negative) FD it was called on, and return that result for +all future (non-negative) FDs. While unlikely, it's possible that +applications might call this function on something other than +fileno(stderr). + +Move the memoization into g_log_writer_default(), which always passes +fileno(stderr). + +Fixes #1589. +--- + glib/gmessages.c | 42 ++++++++++++++++++++++-------------------- + 1 file changed, 22 insertions(+), 20 deletions(-) + +diff --git a/glib/gmessages.c b/glib/gmessages.c +index 569fe2cf8..a43ff0e58 100644 +--- a/glib/gmessages.c ++++ b/glib/gmessages.c +@@ -2165,31 +2165,24 @@ g_log_writer_is_journald (gint output_fd) + /* FIXME: Use the new journal API for detecting whether we’re writing to the + * journal. See: https://github.com/systemd/systemd/issues/2473 + */ +- static gsize initialized; +- static gboolean fd_is_journal = FALSE; ++ union { ++ struct sockaddr_storage storage; ++ struct sockaddr sa; ++ struct sockaddr_un un; ++ } addr; ++ socklen_t addr_len; ++ int err; + + if (output_fd < 0) + return FALSE; + +- if (g_once_init_enter (&initialized)) +- { +- union { +- struct sockaddr_storage storage; +- struct sockaddr sa; +- struct sockaddr_un un; +- } addr; +- socklen_t addr_len = sizeof(addr); +- int err = getpeername (output_fd, &addr.sa, &addr_len); +- if (err == 0 && addr.storage.ss_family == AF_UNIX) +- fd_is_journal = g_str_has_prefix (addr.un.sun_path, "/run/systemd/journal/"); +- +- g_once_init_leave (&initialized, TRUE); +- } ++ addr_len = sizeof(addr); ++ err = getpeername (output_fd, &addr.sa, &addr_len); ++ if (err == 0 && addr.storage.ss_family == AF_UNIX) ++ return g_str_has_prefix (addr.un.sun_path, "/run/systemd/journal/"); ++#endif + +- return fd_is_journal; +-#else + return FALSE; +-#endif + } + + static void escape_string (GString *string); +@@ -2620,6 +2613,9 @@ g_log_writer_default (GLogLevelFlags log_level, + gsize n_fields, + gpointer user_data) + { ++ static gsize initialized = 0; ++ static gboolean stderr_is_journal = FALSE; ++ + g_return_val_if_fail (fields != NULL, G_LOG_WRITER_UNHANDLED); + g_return_val_if_fail (n_fields > 0, G_LOG_WRITER_UNHANDLED); + +@@ -2656,7 +2652,13 @@ g_log_writer_default (GLogLevelFlags log_level, + log_level |= G_LOG_FLAG_FATAL; + + /* Try logging to the systemd journal as first choice. */ +- if (g_log_writer_is_journald (fileno (stderr)) && ++ if (g_once_init_enter (&initialized)) ++ { ++ stderr_is_journal = g_log_writer_is_journald (fileno (stderr)); ++ g_once_init_leave (&initialized, TRUE); ++ } ++ ++ if (stderr_is_journal && + g_log_writer_journald (log_level, fields, n_fields, user_data) == + G_LOG_WRITER_HANDLED) + goto handled; +-- +2.19.1 + diff --git a/gnetworkmonitornm-Set-a-GError-properly-on-an-error-.patch b/gnetworkmonitornm-Set-a-GError-properly-on-an-error-.patch new file mode 100644 index 0000000..94128cf --- /dev/null +++ b/gnetworkmonitornm-Set-a-GError-properly-on-an-error-.patch @@ -0,0 +1,36 @@ +From c5761146bc063a2defd9934cd0151b5e5766ab73 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Thu, 13 Sep 2018 10:25:05 +0100 +Subject: [PATCH 066/682] gnetworkmonitornm: Set a GError properly on an error + handling path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +All the other initialisation failure paths set a GError, but this one +didn’t. Set a GError to avoid breaking the invariant that returning +FALSE should always have a GError set. + +Signed-off-by: Philip Withnall + +https://gitlab.gnome.org/GNOME/glib/issues/1523 +--- + gio/gnetworkmonitornm.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/gio/gnetworkmonitornm.c b/gio/gnetworkmonitornm.c +index 20a86571f..5bc8c925a 100644 +--- a/gio/gnetworkmonitornm.c ++++ b/gio/gnetworkmonitornm.c +@@ -309,6 +309,8 @@ g_network_monitor_nm_initable_init (GInitable *initable, + + if (!name_owner) + { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, ++ _("NetworkManager not running")); + g_object_unref (proxy); + return FALSE; + } +-- +2.19.1 + diff --git a/gobject-Change-assertions-to-read-values-via-atomics.patch b/gobject-Change-assertions-to-read-values-via-atomics.patch new file mode 100644 index 0000000..143dbc3 --- /dev/null +++ b/gobject-Change-assertions-to-read-values-via-atomics.patch @@ -0,0 +1,61 @@ +From 4631cd892da2ad7ea54912b7f20af33ee2c72744 Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Thu, 17 Nov 2016 15:43:26 -0500 +Subject: [PATCH 549/682] gobject: Change assertions to read values via atomics + +I'm trying to use `-fsanitize=thread` for OSTree, and some of +these issues seem to go into GLib. Also, the sanitizers work better if +the userspace libraries are built with them too. + +This fix is similar to +https://github.com/ostreedev/ostree/pull/582/commits/b6814bb37cacd7a36715cf91766eb760b1b33c66 + +Mixing atomic and non-atomic reads trips TSAN, so let's change the +assertions to operate on the local values returned from atomic +read/writes. + +Without this change I couldn't even *build* GLib with TSAN, since we +use gresources during compilation, which uses GSubprocess, which hits +this code. + +(Minor review fixes made by Philip Withnall .) + +https://gitlab.gnome.org/GNOME/glib/issues/1224 +--- + gobject/gobject.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gobject/gobject.c b/gobject/gobject.c +index 3f8ad9273..de61a0481 100644 +--- a/gobject/gobject.c ++++ b/gobject/gobject.c +@@ -3210,9 +3210,9 @@ gpointer + gint old_val; + + g_return_val_if_fail (G_IS_OBJECT (object), NULL); +- g_return_val_if_fail (object->ref_count > 0, NULL); + + old_val = g_atomic_int_add (&object->ref_count, 1); ++ g_return_val_if_fail (old_val > 0, NULL); + + if (old_val == 1 && OBJECT_HAS_TOGGLE_REF (object)) + toggle_refs_notify (object, FALSE); +@@ -3241,7 +3241,6 @@ g_object_unref (gpointer _object) + gint old_ref; + + g_return_if_fail (G_IS_OBJECT (object)); +- g_return_if_fail (object->ref_count > 0); + + /* here we want to atomically do: if (ref_count>1) { ref_count--; return; } */ + retry_atomic_decrement1: +@@ -3336,6 +3335,7 @@ g_object_unref (gpointer _object) + + /* decrement the last reference */ + old_ref = g_atomic_int_add (&object->ref_count, -1); ++ g_return_if_fail (old_ref > 0); + + TRACE (GOBJECT_OBJECT_UNREF(object,G_TYPE_FROM_INSTANCE(object),old_ref)); + +-- +2.19.1 + diff --git a/gobject-genums.c-fix-flags-validation.patch b/gobject-genums.c-fix-flags-validation.patch new file mode 100644 index 0000000..e27da35 --- /dev/null +++ b/gobject-genums.c-fix-flags-validation.patch @@ -0,0 +1,32 @@ +From 1d6c7843caebdeac72f80ecb0f9807afc853affc Mon Sep 17 00:00:00 2001 +From: Arthur Demchenkov +Date: Sun, 14 Oct 2018 05:03:42 +0300 +Subject: [PATCH 213/682] gobject/genums.c: fix flags validation + +gint -> glong conversion causes flags to be invalid if the highest bit +is set. + +Closes #1572 +--- + gobject/genums.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/gobject/genums.c b/gobject/genums.c +index 8212dd99d..aa27c6bb4 100644 +--- a/gobject/genums.c ++++ b/gobject/genums.c +@@ -152,7 +152,10 @@ value_flags_enum_collect_value (GValue *value, + GTypeCValue *collect_values, + guint collect_flags) + { +- value->data[0].v_long = collect_values[0].v_int; ++ if (G_VALUE_HOLDS_ENUM (value)) ++ value->data[0].v_long = collect_values[0].v_int; ++ else ++ value->data[0].v_ulong = (guint) collect_values[0].v_int; + + return NULL; + } +-- +2.19.1 + diff --git a/grefcount-add-missing-gatomic.h.patch b/grefcount-add-missing-gatomic.h.patch new file mode 100644 index 0000000..3b15497 --- /dev/null +++ b/grefcount-add-missing-gatomic.h.patch @@ -0,0 +1,37 @@ +From 09c149453ac969dedb1cb2d15d489d1dd81412bf Mon Sep 17 00:00:00 2001 +From: Fabrice Fontaine +Date: Sat, 13 Oct 2018 23:10:33 +0200 +Subject: [PATCH 150/682] grefcount: add missing gatomic.h +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Without gatomic.h, build fails on: +In file included from garcbox.c:24:0: +garcbox.c: In function ‘g_atomic_rc_box_acquire’: +grefcount.h:101:13: error: implicit declaration of function ‘g_atomic_int_get’; did you mean ‘__atomic_store’? [-Werror=implicit-function-declaration] + (void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \ + ^ +garcbox.c:292:3: note: in expansion of macro ‘g_atomic_ref_count_inc’ + g_atomic_ref_count_inc (&real_box->ref_count); + +Signed-off-by: Fabrice Fontaine +--- + glib/grefcount.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/glib/grefcount.h b/glib/grefcount.h +index dec9a5ffb..b6eced1b7 100644 +--- a/glib/grefcount.h ++++ b/glib/grefcount.h +@@ -23,6 +23,7 @@ + #error "Only can be included directly." + #endif + ++#include + #include + + G_BEGIN_DECLS +-- +2.19.1 + diff --git a/gsettingsbackend-Fix-a-minor-memory-leak.patch b/gsettingsbackend-Fix-a-minor-memory-leak.patch new file mode 100644 index 0000000..74ad25b --- /dev/null +++ b/gsettingsbackend-Fix-a-minor-memory-leak.patch @@ -0,0 +1,28 @@ +From caf5103d4befbaf7a2fdc01ef01484ae168e7657 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Wed, 23 Jan 2019 15:59:17 +0000 +Subject: [PATCH 545/682] gsettingsbackend: Fix a minor memory leak + +This never caused any problems because the default GSettingsBackend is +cached forever by GIOModule anyway. + +Signed-off-by: Philip Withnall +--- + gio/gsettingsbackend.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/gio/gsettingsbackend.c b/gio/gsettingsbackend.c +index ca9b908a5..18026ae56 100644 +--- a/gio/gsettingsbackend.c ++++ b/gio/gsettingsbackend.c +@@ -1052,5 +1052,7 @@ g_settings_backend_sync_default (void) + + if (class->sync) + class->sync (backend); ++ ++ g_object_unref (backend); + } + } +-- +2.19.1 + diff --git a/gsocketlistener-Fix-multiple-returns-of-GTask-when-a.patch b/gsocketlistener-Fix-multiple-returns-of-GTask-when-a.patch new file mode 100644 index 0000000..27eeb90 --- /dev/null +++ b/gsocketlistener-Fix-multiple-returns-of-GTask-when-a.patch @@ -0,0 +1,107 @@ +From 30ccfac9cf594c7bb224ff38ce109b442fb10a3c Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Fri, 8 Feb 2019 00:05:52 +0000 +Subject: [PATCH 575/682] gsocketlistener: Fix multiple returns of GTask when + accepting sockets + +When calling g_socket_listener_accept_socket_async() on a +GSocketListener with multiple sockets, the accept_ready() callback is +called for the first incoming connection on each socket. It will return +success/failure for the entire accept_socket_async() GTask, and then +free the GSources for listening for incoming connections on the other +sockets in the GSocketListener. The GSources are freed when the GTask is +finalised. + +However, if incoming connections arrive for multiple sockets within the +same GMainContext iteration, accept_ready() will be called multiple +times, and will call g_task_return_*() multiple times, before the GTask +is finalised. Calling g_task_return_*() multiple times is not allowed. + +Propagate the first success/failure, as before, but then ignore all +subsequent incoming connections until the GTask is finalised. + +Signed-off-by: Philip Withnall +--- + gio/gsocketlistener.c | 32 ++++++++++++++++++++++++++++---- + 1 file changed, 28 insertions(+), 4 deletions(-) + +diff --git a/gio/gsocketlistener.c b/gio/gsocketlistener.c +index ab17678a9..a2c879d9c 100644 +--- a/gio/gsocketlistener.c ++++ b/gio/gsocketlistener.c +@@ -773,6 +773,19 @@ g_socket_listener_accept (GSocketListener *listener, + return connection; + } + ++typedef struct ++{ ++ GList *sources; /* (element-type GSource) */ ++ gboolean returned_yet; ++} AcceptSocketAsyncData; ++ ++static void ++accept_socket_async_data_free (AcceptSocketAsyncData *data) ++{ ++ free_sources (data->sources); ++ g_free (data); ++} ++ + static gboolean + accept_ready (GSocket *accept_socket, + GIOCondition condition, +@@ -782,6 +795,12 @@ accept_ready (GSocket *accept_socket, + GError *error = NULL; + GSocket *socket; + GObject *source_object; ++ AcceptSocketAsyncData *data = g_task_get_task_data (task); ++ ++ /* Don’t call g_task_return_*() multiple times if we have multiple incoming ++ * connections in the same #GMainContext iteration. */ ++ if (data->returned_yet) ++ return G_SOURCE_REMOVE; + + socket = g_socket_accept (accept_socket, g_task_get_cancellable (task), &error); + if (socket) +@@ -798,8 +817,10 @@ accept_ready (GSocket *accept_socket, + g_task_return_error (task, error); + } + ++ data->returned_yet = TRUE; + g_object_unref (task); +- return FALSE; ++ ++ return G_SOURCE_REMOVE; + } + + /** +@@ -824,8 +845,8 @@ g_socket_listener_accept_socket_async (GSocketListener *listener, + gpointer user_data) + { + GTask *task; +- GList *sources; + GError *error = NULL; ++ AcceptSocketAsyncData *data = NULL; + + task = g_task_new (listener, cancellable, callback, user_data); + g_task_set_source_tag (task, g_socket_listener_accept_socket_async); +@@ -837,12 +858,15 @@ g_socket_listener_accept_socket_async (GSocketListener *listener, + return; + } + +- sources = add_sources (listener, ++ data = g_new0 (AcceptSocketAsyncData, 1); ++ data->returned_yet = FALSE; ++ data->sources = add_sources (listener, + accept_ready, + task, + cancellable, + g_main_context_get_thread_default ()); +- g_task_set_task_data (task, sources, (GDestroyNotify) free_sources); ++ g_task_set_task_data (task, g_steal_pointer (&data), ++ (GDestroyNotify) accept_socket_async_data_free); + } + + /** +-- +2.19.1 + diff --git a/gspawn-Fix-g_spawn-deadlock-in-a-multi-threaded-prog.patch b/gspawn-Fix-g_spawn-deadlock-in-a-multi-threaded-prog.patch new file mode 100644 index 0000000..74f1c87 --- /dev/null +++ b/gspawn-Fix-g_spawn-deadlock-in-a-multi-threaded-prog.patch @@ -0,0 +1,149 @@ +From f2917459f745bebf931bccd5cc2c33aa81ef4d12 Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Sat, 24 Nov 2018 13:22:57 +0100 +Subject: [PATCH 301/682] gspawn: Fix g_spawn deadlock in a multi-threaded + program on Linux + +opendir and closedir are not async-signal-safe, these may call malloc +under the hood and cause a deadlock in a multi-threaded program. +This only affected Linux when /proc is mounted, other systems use a +slower path that iterates through all potential file descriptors. +Fixes a long-standing problem (since GLib 2.14.2). + +Closes #945 and #1014 +--- + glib/gspawn.c | 94 +++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 65 insertions(+), 29 deletions(-) + +diff --git a/glib/gspawn.c b/glib/gspawn.c +index 23ade06ae..69d3fec10 100644 +--- a/glib/gspawn.c ++++ b/glib/gspawn.c +@@ -47,6 +47,10 @@ + #include + #endif /* HAVE_SYS_RESOURCE_H */ + ++#ifdef __linux__ ++#include /* for syscall and SYS_getdents64 */ ++#endif ++ + #include "gspawn.h" + #include "gspawn-private.h" + #include "gthread.h" +@@ -1125,6 +1129,44 @@ set_cloexec (void *data, gint fd) + } + + #ifndef HAVE_FDWALK ++#ifdef __linux__ ++struct linux_dirent64 ++{ ++ guint64 d_ino; /* 64-bit inode number */ ++ guint64 d_off; /* 64-bit offset to next structure */ ++ unsigned short d_reclen; /* Size of this dirent */ ++ unsigned char d_type; /* File type */ ++ char d_name[]; /* Filename (null-terminated) */ ++}; ++ ++static gint ++filename_to_fd (const char *p) ++{ ++ char c; ++ int fd = 0; ++ const int cutoff = G_MAXINT / 10; ++ const int cutlim = G_MAXINT % 10; ++ ++ if (*p == '\0') ++ return -1; ++ ++ while ((c = *p++) != '\0') ++ { ++ if (!g_ascii_isdigit (c)) ++ return -1; ++ c -= '0'; ++ ++ /* Check for overflow. */ ++ if (fd > cutoff || (fd == cutoff && c > cutlim)) ++ return -1; ++ ++ fd = fd * 10 + c; ++ } ++ ++ return fd; ++} ++#endif ++ + static int + fdwalk (int (*cb)(void *data, int fd), void *data) + { +@@ -1136,45 +1178,39 @@ fdwalk (int (*cb)(void *data, int fd), void *data) + struct rlimit rl; + #endif + +-#ifdef __linux__ +- DIR *d; +- +- if ((d = opendir("/proc/self/fd"))) { +- struct dirent *de; +- +- while ((de = readdir(d))) { +- glong l; +- gchar *e = NULL; +- +- if (de->d_name[0] == '.') +- continue; +- +- errno = 0; +- l = strtol(de->d_name, &e, 10); +- if (errno != 0 || !e || *e) +- continue; +- +- fd = (gint) l; ++#ifdef __linux__ ++ /* Avoid use of opendir/closedir since these are not async-signal-safe. */ ++ int dir_fd = open ("/proc/self/fd", O_RDONLY | O_DIRECTORY); ++ if (dir_fd >= 0) ++ { ++ char buf[4096]; ++ int pos, nread; ++ struct linux_dirent64 *de; + +- if ((glong) fd != l) +- continue; ++ while ((nread = syscall (SYS_getdents64, dir_fd, buf, sizeof(buf))) > 0) ++ { ++ for (pos = 0; pos < nread; pos += de->d_reclen) ++ { ++ de = (struct linux_dirent64 *)(buf + pos); + +- if (fd == dirfd(d)) +- continue; ++ fd = filename_to_fd (de->d_name); ++ if (fd < 0 || fd == dir_fd) ++ continue; + +- if ((res = cb (data, fd)) != 0) +- break; ++ if ((res = cb (data, fd)) != 0) ++ break; ++ } + } +- +- closedir(d); ++ ++ close (dir_fd); + return res; +- } ++ } + + /* If /proc is not mounted or not accessible we fall back to the old + * rlimit trick */ + + #endif +- ++ + #ifdef HAVE_SYS_RESOURCE_H + + if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) +-- +2.19.1 + diff --git a/gtask-Check-an-error-hasn-t-been-returned-when-calli.patch b/gtask-Check-an-error-hasn-t-been-returned-when-calli.patch new file mode 100644 index 0000000..d25324d --- /dev/null +++ b/gtask-Check-an-error-hasn-t-been-returned-when-calli.patch @@ -0,0 +1,96 @@ +From bea37709353533e4abb1c652a655f483e6f9aeac Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Wed, 21 Mar 2018 14:47:52 +0000 +Subject: [PATCH 121/682] =?UTF-8?q?gtask:=20Check=20an=20error=20hasn?= + =?UTF-8?q?=E2=80=99t=20been=20returned=20when=20calling=20g=5Ftask=5Fretu?= + =?UTF-8?q?rn*()?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These functions already check to see if a successful result has already +been returned; expand them to also check to see if an error has been +returned. + +We can’t just check GTask.result_set, as that’s actually an indicator +for whether the GTask.result member is filled — when +g_task_propagate_*() is called, it’s cleared again. We need a new state +bit. + +Signed-off-by: Philip Withnall + +https://gitlab.gnome.org/GNOME/glib/issues/1525 +--- + gio/gtask.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/gio/gtask.c b/gio/gtask.c +index 4087543e6..a31bd613a 100644 +--- a/gio/gtask.c ++++ b/gio/gtask.c +@@ -575,6 +575,7 @@ struct _GTask { + GDestroyNotify result_destroy; + gboolean had_error; + gboolean result_set; ++ gboolean ever_returned; + }; + + #define G_TASK_IS_THREADED(task) ((task)->task_func != NULL) +@@ -1176,6 +1177,9 @@ g_task_return (GTask *task, + { + GSource *source; + ++ if (type != G_TASK_RETURN_FROM_THREAD) ++ task->ever_returned = TRUE; ++ + if (type == G_TASK_RETURN_SUCCESS) + task->result_set = TRUE; + +@@ -1596,7 +1600,7 @@ g_task_return_pointer (GTask *task, + GDestroyNotify result_destroy) + { + g_return_if_fail (G_IS_TASK (task)); +- g_return_if_fail (task->result_set == FALSE); ++ g_return_if_fail (!task->ever_returned); + + task->result.pointer = result; + task->result_destroy = result_destroy; +@@ -1654,7 +1658,7 @@ g_task_return_int (GTask *task, + gssize result) + { + g_return_if_fail (G_IS_TASK (task)); +- g_return_if_fail (task->result_set == FALSE); ++ g_return_if_fail (!task->ever_returned); + + task->result.size = result; + +@@ -1709,7 +1713,7 @@ g_task_return_boolean (GTask *task, + gboolean result) + { + g_return_if_fail (G_IS_TASK (task)); +- g_return_if_fail (task->result_set == FALSE); ++ g_return_if_fail (!task->ever_returned); + + task->result.boolean = result; + +@@ -1772,7 +1776,7 @@ g_task_return_error (GTask *task, + GError *error) + { + g_return_if_fail (G_IS_TASK (task)); +- g_return_if_fail (task->result_set == FALSE); ++ g_return_if_fail (!task->ever_returned); + g_return_if_fail (error != NULL); + + task->error = error; +@@ -1833,7 +1837,7 @@ g_task_return_error_if_cancelled (GTask *task) + GError *error = NULL; + + g_return_val_if_fail (G_IS_TASK (task), FALSE); +- g_return_val_if_fail (task->result_set == FALSE, FALSE); ++ g_return_val_if_fail (!task->ever_returned, FALSE); + + if (g_cancellable_set_error_if_cancelled (task->cancellable, &error)) + { +-- +2.19.1 + diff --git a/gtask-Ensure-to-return-1-or-0-from-getters-rather-th.patch b/gtask-Ensure-to-return-1-or-0-from-getters-rather-th.patch new file mode 100644 index 0000000..99884d7 --- /dev/null +++ b/gtask-Ensure-to-return-1-or-0-from-getters-rather-th.patch @@ -0,0 +1,77 @@ +From ae381d795e178740915defb23a4e54eb7791d8c6 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Sat, 5 Jan 2019 07:51:14 +0000 +Subject: [PATCH 438/682] gtask: Ensure to return 1 or 0 from getters rather + than truthy ints +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since commit 290bb0dd, where various members of GTask were converted to +a bitfield, some of the getters: + • g_task_get_check_cancellable() + • g_task_get_return_on_cancel() + • g_task_get_completed() +have been returning truthy ints (zero or an arbitrary non-zero integer) +as boolean values, rather than the canonical boolean ints of 1 and 0. + +This broke the `yield` statement in Vala, whose generated C code +compares `g_task_get_completed (…) != TRUE`. i.e. Whether the +`completed` field has a value not equal to 1. + +Fix this by explicitly converting truthy ints to canonical boolean ints +in all getters. + +Signed-off-by: Philip Withnall + +https://gitlab.gnome.org/GNOME/glib/issues/1636 +--- + gio/gtask.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/gio/gtask.c b/gio/gtask.c +index a2f316d2e..aa98f752c 100644 +--- a/gio/gtask.c ++++ b/gio/gtask.c +@@ -1132,7 +1132,8 @@ g_task_get_check_cancellable (GTask *task) + { + g_return_val_if_fail (G_IS_TASK (task), FALSE); + +- return task->check_cancellable; ++ /* Convert from a bit field to a boolean. */ ++ return task->check_cancellable ? TRUE : FALSE; + } + + /** +@@ -1149,7 +1150,8 @@ g_task_get_return_on_cancel (GTask *task) + { + g_return_val_if_fail (G_IS_TASK (task), FALSE); + +- return task->return_on_cancel; ++ /* Convert from a bit field to a boolean. */ ++ return task->return_on_cancel ? TRUE : FALSE; + } + + /** +@@ -1952,7 +1954,8 @@ g_task_get_completed (GTask *task) + { + g_return_val_if_fail (G_IS_TASK (task), FALSE); + +- return task->completed; ++ /* Convert from a bit field to a boolean. */ ++ return task->completed ? TRUE : FALSE; + } + + /** +@@ -2055,7 +2058,7 @@ g_task_get_property (GObject *object, + switch ((GTaskProperty) prop_id) + { + case PROP_COMPLETED: +- g_value_set_boolean (value, task->completed); ++ g_value_set_boolean (value, g_task_get_completed (task)); + break; + } + } +-- +2.19.1 + diff --git a/gtlscertificate-Fix-bug-in-PEM-private-key-parser.patch b/gtlscertificate-Fix-bug-in-PEM-private-key-parser.patch new file mode 100644 index 0000000..783d5a4 --- /dev/null +++ b/gtlscertificate-Fix-bug-in-PEM-private-key-parser.patch @@ -0,0 +1,71 @@ +From feff178c3f5dadeff47228500a212a9be5688ba2 Mon Sep 17 00:00:00 2001 +From: Fredrik Ternerot +Date: Fri, 14 Dec 2018 11:46:27 +0100 +Subject: [PATCH 355/682] gtlscertificate: Fix bug in PEM private key parser + +Make sure to not go outside of PEM data buffer when looking for private +key. + +Also adding test case that triggers this bug. +--- + gio/gtlscertificate.c | 2 +- + gio/tests/tls-certificate.c | 13 +++++++++++-- + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/gio/gtlscertificate.c b/gio/gtlscertificate.c +index 9e497c58b..1ec48f118 100644 +--- a/gio/gtlscertificate.c ++++ b/gio/gtlscertificate.c +@@ -258,7 +258,7 @@ parse_private_key (const gchar *data, + } + } + +- end = g_strstr_len (start, data_len - (data - start), footer); ++ end = g_strstr_len (start, data_len - (start - data), footer); + if (!end) + { + g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE, +diff --git a/gio/tests/tls-certificate.c b/gio/tests/tls-certificate.c +index 4cc15d2d7..db2511f59 100644 +--- a/gio/tests/tls-certificate.c ++++ b/gio/tests/tls-certificate.c +@@ -36,14 +36,16 @@ pem_parser (const Reference *ref) + { + GTlsCertificate *cert; + gchar *pem; ++ gsize pem_len = 0; + gchar *parsed_cert_pem = NULL; + const gchar *parsed_key_pem = NULL; + GError *error = NULL; + + /* Check PEM parsing in certificate, private key order. */ +- g_file_get_contents (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert-key.pem", NULL), &pem, NULL, &error); ++ g_file_get_contents (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert-key.pem", NULL), &pem, &pem_len, &error); + g_assert_no_error (error); + g_assert (pem); ++ g_assert_cmpuint (pem_len, >=, 10); + + cert = g_tls_certificate_new_from_pem (pem, -1, &error); + g_assert_no_error (error); +@@ -61,10 +63,17 @@ pem_parser (const Reference *ref) + + g_object_unref (cert); + +- /* Make sure length is respected and parser detect invalid (truncated) PEM. */ ++ /* Make sure length is respected and parser detect invalid PEM ++ * when cert is truncated. */ + cert = g_tls_certificate_new_from_pem (pem, 10, &error); + g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE); + g_clear_error (&error); ++ ++ /* Make sure length is respected and parser detect invalid PEM ++ * when cert exists but key is truncated. */ ++ cert = g_tls_certificate_new_from_pem (pem, pem_len - 10, &error); ++ g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE); ++ g_clear_error (&error); + g_free (pem); + + /* Check PEM parsing in private key, certificate order */ +-- +2.19.1 + diff --git a/gunixmounts-Don-t-treat-ZFS-as-a-system-internal-fs.patch b/gunixmounts-Don-t-treat-ZFS-as-a-system-internal-fs.patch new file mode 100644 index 0000000..3e152c6 --- /dev/null +++ b/gunixmounts-Don-t-treat-ZFS-as-a-system-internal-fs.patch @@ -0,0 +1,35 @@ +From 624e99b9d6fa990a5b9afda771837aca7edadf8d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= +Date: Mon, 26 Nov 2018 12:27:59 +0000 +Subject: [PATCH 306/682] gunixmounts: Don't treat ZFS as a system internal fs + +ZFS was originally added to the list of system internal filesystems by +commit 4cafadc955d1c37118ca269ea22bbd37f8f2a2ce. + +The rationale from https://bugzilla.gnome.org/show_bug.cgi?id=542156 +doesn't seem very solid, and now we have x-gvfs-hide for this. + +Also, this may contribute for trash:/// ignoring `{zfs mount path}/.Trash/` + +So, remove zfs from the ignore_fs array. + +Closes https://gitlab.gnome.org/GNOME/glib/issues/1599 +--- + gio/gunixmounts.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c +index 3c32d0e89..cc905f2fc 100644 +--- a/gio/gunixmounts.c ++++ b/gio/gunixmounts.c +@@ -344,7 +344,6 @@ g_unix_is_system_fs_type (const char *fs_type) + "sysfs", + "tmpfs", + "usbfs", +- "zfs", + NULL + }; + +-- +2.19.1 + diff --git a/gvariant-Fix-checking-arithmetic-for-tuple-element-e.patch b/gvariant-Fix-checking-arithmetic-for-tuple-element-e.patch new file mode 100644 index 0000000..015d9c4 --- /dev/null +++ b/gvariant-Fix-checking-arithmetic-for-tuple-element-e.patch @@ -0,0 +1,97 @@ +From eb7c9adc3b2570f6b82110b52a24609d124f38de Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Thu, 16 Aug 2018 20:12:02 +0100 +Subject: [PATCH 160/682] gvariant: Fix checking arithmetic for tuple element + ends +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When checking whether a serialised GVariant tuple is in normal form, +it’s possible for `offset_ptr -= offset_size` to underflow and wrap +around, resulting in gvs_read_unaligned_le() reading memory outside the +serialised GVariant bounds. + +See §(Tuples) in gvariant-serialiser.c for the documentation on how +tuples are serialised. Briefly, all variable-length elements in the +tuple have an offset to their end stored in an array of offsets at the +end of the tuple. The width of each offset is in offset_size. offset_ptr +is added to the start of the serialised tuple to get the offset which is +currently being examined. The offset array is in reverse order compared +to the tuple elements, hence the subtraction. + +The bug can be triggered if a tuple contains a load of variable-length +elements, each of whose length is actually zero (i.e. empty arrays). + +Includes a unit test. + +oss-fuzz#9801 + +Signed-off-by: Philip Withnall +--- + glib/gvariant-serialiser.c | 3 +++ + glib/tests/gvariant.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 31 insertions(+) + +diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c +index 69f183121..96df54e23 100644 +--- a/glib/gvariant-serialiser.c ++++ b/glib/gvariant-serialiser.c +@@ -1065,6 +1065,9 @@ gvs_tuple_is_normal (GVariantSerialised value) + break; + + case G_VARIANT_MEMBER_ENDING_OFFSET: ++ if (offset_ptr < offset_size) ++ return FALSE; ++ + offset_ptr -= offset_size; + + if (offset_ptr < offset) +diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c +index de8e42d0b..a5095a380 100644 +--- a/glib/tests/gvariant.c ++++ b/glib/tests/gvariant.c +@@ -4631,6 +4631,30 @@ test_stack_dict_init (void) + g_variant_unref (variant); + } + ++/* Test checking arbitrary binary data for normal form. This time, it’s a tuple ++ * with invalid element ends. */ ++static void ++test_normal_checking_tuples (void) ++{ ++ const guint8 data[] = { ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, ++ 'a', '(', 'a', 'o', 'a', 'o', 'a', 'a', 'o', 'a', 'a', 'o', ')' ++ }; ++ gsize size = sizeof (data); ++ GVariant *variant = NULL; ++ GVariant *normal_variant = NULL; ++ ++ variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size, ++ FALSE, NULL, NULL); ++ g_assert_nonnull (variant); ++ ++ normal_variant = g_variant_get_normal_form (variant); ++ g_assert_nonnull (normal_variant); ++ ++ g_variant_unref (normal_variant); ++ g_variant_unref (variant); ++} ++ + int + main (int argc, char **argv) + { +@@ -4692,5 +4716,9 @@ main (int argc, char **argv) + + g_test_add_func ("/gvariant/stack-builder-init", test_stack_builder_init); + g_test_add_func ("/gvariant/stack-dict-init", test_stack_dict_init); ++ ++ g_test_add_func ("/gvariant/normal-checking/tuples", ++ test_normal_checking_tuples); ++ + return g_test_run (); + } +-- +2.19.1 + diff --git a/gvariant-Fix-error-handling-for-parsing-Unicode-esca.patch b/gvariant-Fix-error-handling-for-parsing-Unicode-esca.patch new file mode 100644 index 0000000..d37dbfe --- /dev/null +++ b/gvariant-Fix-error-handling-for-parsing-Unicode-esca.patch @@ -0,0 +1,76 @@ +From d2224b475d20b544cf782ce046183209d419a012 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Tue, 4 Dec 2018 12:55:21 +0000 +Subject: [PATCH 325/682] gvariant: Fix error handling for parsing Unicode + escapes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When parsing an escaped Unicode character in a text format GVariant +string, such as '\U0001F415', the code uses g_ascii_strtoull(). This, +unexpectedly, accepts minus signs, which can cause an assertion failure +when input like '\u-FF4' is presented for parsing. + +Validate that there are no leading sign characters when parsing. + +This shouldn’t be considered a security bug, because the GVariant text +format parser should not be used on untrusted input. + +oss-fuzz#11576 + +Signed-off-by: Philip Withnall +--- + glib/gvariant-parser.c | 20 +++++++++++++++++--- + glib/tests/gvariant.c | 20 ++++++++++++++++++-- + 2 files changed, 35 insertions(+), 5 deletions(-) + +diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c +index 44e341965..b860d42f4 100644 +--- a/glib/gvariant-parser.c ++++ b/glib/gvariant-parser.c +@@ -1528,6 +1528,8 @@ string_free (AST *ast) + g_slice_free (String, string); + } + ++/* Accepts exactly @length hexadecimal digits. No leading sign or `0x`/`0X` prefix allowed. ++ * No leading/trailing space allowed. */ + static gboolean + unicode_unescape (const gchar *src, + gint *src_ofs, +@@ -1538,8 +1540,9 @@ unicode_unescape (const gchar *src, + GError **error) + { + gchar buffer[9]; +- guint64 value; ++ guint64 value = 0; + gchar *end; ++ gsize n_valid_chars; + + (*src_ofs)++; + +@@ -1547,11 +1550,22 @@ unicode_unescape (const gchar *src, + strncpy (buffer, src + *src_ofs, length); + buffer[length] = '\0'; + +- value = g_ascii_strtoull (buffer, &end, 0x10); ++ for (n_valid_chars = 0; n_valid_chars < length; n_valid_chars++) ++ if (!g_ascii_isxdigit (buffer[n_valid_chars])) ++ break; ++ ++ if (n_valid_chars == length) ++ value = g_ascii_strtoull (buffer, &end, 0x10); + + if (value == 0 || end != buffer + length) + { +- parser_set_error (error, ref, NULL, ++ SourceRef escape_ref; ++ ++ escape_ref = *ref; ++ escape_ref.start += *src_ofs; ++ escape_ref.end = escape_ref.start + n_valid_chars; ++ ++ parser_set_error (error, &escape_ref, NULL, + G_VARIANT_PARSE_ERROR_INVALID_CHARACTER, + "invalid %d-character unicode escape", length); + return FALSE; diff --git a/gvariant-Realign-data-on-construction-if-it-s-not-pr.patch b/gvariant-Realign-data-on-construction-if-it-s-not-pr.patch new file mode 100644 index 0000000..5572c82 --- /dev/null +++ b/gvariant-Realign-data-on-construction-if-it-s-not-pr.patch @@ -0,0 +1,134 @@ +From 0f2a6c61c9c5e34d57293fb6987b21f3d1feb1cb Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Tue, 13 Feb 2018 13:29:23 +0000 +Subject: [PATCH 232/682] =?UTF-8?q?gvariant:=20Realign=20data=20on=20const?= + =?UTF-8?q?ruction=20if=20it=E2=80=99s=20not=20properly=20aligned?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Otherwise the GVariant would later fail internal alignment checks, +aborting the program. + +If unaligned data is provided to (for example) +g_variant_new_from_data(), it will copy the data into a new aligned +allocation. This is slow, but better than crashing. If callers want +better performance, they should provide aligned data in their call, and +it will not be copied or reallocated. + +Includes a unit test. + +Signed-off-by: Philip Withnall + +https://gitlab.gnome.org/GNOME/glib/issues/1342 +--- + glib/gvariant-core.c | 46 +++++++++++++++++++++++++++++++++++++++-- + glib/gvariant.c | 10 +++++++++ + glib/tests/gvariant.c | 48 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 102 insertions(+), 2 deletions(-) + +diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c +index 815bdf9e0..ef59c7049 100644 +--- a/glib/gvariant-core.c ++++ b/glib/gvariant-core.c +@@ -506,6 +506,10 @@ g_variant_alloc (const GVariantType *type, + * + * A reference is taken on @bytes. + * ++ * The data in @bytes must be aligned appropriately for the @type being loaded. ++ * Otherwise this function will internally create a copy of the memory (since ++ * GLib 2.60) or (in older versions) fail and exit the process. ++ * + * Returns: (transfer none): a new #GVariant with a floating reference + * + * Since: 2.36 +@@ -518,14 +522,50 @@ g_variant_new_from_bytes (const GVariantType *type, + GVariant *value; + guint alignment; + gsize size; ++ GBytes *owned_bytes = NULL; + + value = g_variant_alloc (type, TRUE, trusted); + +- value->contents.serialised.bytes = g_bytes_ref (bytes); +- + g_variant_type_info_query (value->type_info, + &alignment, &size); + ++ /* Ensure the alignment is correct. This is a huge performance hit if it’s ++ * not correct, but that’s better than aborting if a caller provides data ++ * with the wrong alignment (which is likely to happen very occasionally, and ++ * only cause an abort on some architectures — so is unlikely to be caught ++ * in testing). Callers can always actively ensure they use the correct ++ * alignment to avoid the performance hit. */ ++ if ((alignment & (gsize) g_bytes_get_data (bytes, NULL)) != 0) ++ { ++#ifdef HAVE_POSIX_MEMALIGN ++ gpointer aligned_data = NULL; ++ gsize aligned_size = g_bytes_get_size (bytes); ++ ++ /* posix_memalign() requires the alignment to be a multiple of ++ * sizeof(void*), and a power of 2. See g_variant_type_info_query() for ++ * details on the alignment format. */ ++ if (posix_memalign (&aligned_data, MAX (sizeof (void *), alignment + 1), ++ aligned_size) != 0) ++ g_error ("posix_memalign failed"); ++ ++ memcpy (aligned_data, g_bytes_get_data (bytes, NULL), aligned_size); ++ ++ bytes = owned_bytes = g_bytes_new_with_free_func (aligned_data, ++ aligned_size, ++ free, aligned_data); ++ aligned_data = NULL; ++#else ++ /* NOTE: there may be platforms that lack posix_memalign() and also ++ * have malloc() that returns non-8-aligned. if so, we need to try ++ * harder here. ++ */ ++ bytes = owned_bytes = g_bytes_new (g_bytes_get_data (bytes, NULL), ++ g_bytes_get_size (bytes)); ++#endif ++ } ++ ++ value->contents.serialised.bytes = g_bytes_ref (bytes); ++ + if (size && g_bytes_get_size (bytes) != size) + { + /* Creating a fixed-sized GVariant with a bytes of the wrong +@@ -543,6 +583,8 @@ g_variant_new_from_bytes (const GVariantType *type, + value->contents.serialised.data = g_bytes_get_data (bytes, &value->size); + } + ++ g_clear_pointer (&owned_bytes, g_bytes_unref); ++ + return value; + } + +diff --git a/glib/gvariant.c b/glib/gvariant.c +index d45b487ad..983d4704c 100644 +--- a/glib/gvariant.c ++++ b/glib/gvariant.c +@@ -307,6 +307,11 @@ + * Constructs a new trusted #GVariant instance from the provided data. + * This is used to implement g_variant_new_* for all the basic types. + * ++ * Note: @data must be backed by memory that is aligned appropriately for the ++ * @type being loaded. Otherwise this function will internally create a copy of ++ * the memory (since GLib 2.60) or (in older versions) fail and exit the ++ * process. ++ * + * Returns: a new floating #GVariant + */ + static GVariant * +@@ -5986,6 +5991,11 @@ g_variant_byteswap (GVariant *value) + * needed. The exact time of this call is unspecified and might even be + * before this function returns. + * ++ * Note: @data must be backed by memory that is aligned appropriately for the ++ * @type being loaded. Otherwise this function will internally create a copy of ++ * the memory (since GLib 2.60) or (in older versions) fail and exit the ++ * process. ++ * + * Returns: (transfer none): a new floating #GVariant of type @type + * + * Since: 2.24 diff --git a/gvariant-parser-Add-explicit-unsigned-to-signed-cast.patch b/gvariant-parser-Add-explicit-unsigned-to-signed-cast.patch new file mode 100644 index 0000000..5eb2f70 --- /dev/null +++ b/gvariant-parser-Add-explicit-unsigned-to-signed-cast.patch @@ -0,0 +1,62 @@ +From e3e4a09716bca4e748a0156ee8cc50adb5cf8ec5 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Sat, 19 Jan 2019 01:07:57 +0000 +Subject: [PATCH 482/682] gvariant-parser: Add explicit unsigned-to-signed + casts + +Rather than prefixing unsigned numbers with unary minus operators and +expecting the implicit cast to carry the correct value through, add an +explicit cast to a signed type before the unary minus is applied. + +In all four cases, an overflow check has already been done. + +Signed-off-by: Philip Withnall + +https://gitlab.gnome.org/GNOME/glib/issues/1655 +--- + glib/gvariant-parser.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c +index b860d42f4..2b02ec90f 100644 +--- a/glib/gvariant-parser.c ++++ b/glib/gvariant-parser.c +@@ -1921,7 +1921,7 @@ number_get_value (AST *ast, + case 'n': + if (abs_val - negative > G_MAXINT16) + return number_overflow (ast, type, error); +- return g_variant_new_int16 (negative ? -abs_val : abs_val); ++ return g_variant_new_int16 (negative ? -((gint16) abs_val) : abs_val); + + case 'q': + if (negative || abs_val > G_MAXUINT16) +@@ -1931,7 +1931,7 @@ number_get_value (AST *ast, + case 'i': + if (abs_val - negative > G_MAXINT32) + return number_overflow (ast, type, error); +- return g_variant_new_int32 (negative ? -abs_val : abs_val); ++ return g_variant_new_int32 (negative ? -((gint32) abs_val) : abs_val); + + case 'u': + if (negative || abs_val > G_MAXUINT32) +@@ -1941,7 +1941,7 @@ number_get_value (AST *ast, + case 'x': + if (abs_val - negative > G_MAXINT64) + return number_overflow (ast, type, error); +- return g_variant_new_int64 (negative ? -abs_val : abs_val); ++ return g_variant_new_int64 (negative ? -((gint64) abs_val) : abs_val); + + case 't': + if (negative) +@@ -1951,7 +1951,7 @@ number_get_value (AST *ast, + case 'h': + if (abs_val - negative > G_MAXINT32) + return number_overflow (ast, type, error); +- return g_variant_new_handle (negative ? -abs_val : abs_val); ++ return g_variant_new_handle (negative ? -((gint32) abs_val) : abs_val); + + default: + return ast_type_error (ast, type, error); +-- +2.19.1 + diff --git a/gvariant-parser-Fix-error-handling-when-type-coalesc.patch b/gvariant-parser-Fix-error-handling-when-type-coalesc.patch new file mode 100644 index 0000000..aa602f9 --- /dev/null +++ b/gvariant-parser-Fix-error-handling-when-type-coalesc.patch @@ -0,0 +1,88 @@ +From c927c59a8426be62f9e9b19e40c862f88b4c17be Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Tue, 5 Feb 2019 15:50:15 +0000 +Subject: [PATCH 563/682] gvariant-parser: Fix error handling when type + coalescing fails + +When parsing GVariant text format strings, we do a limited form of type +inference. The algorithm for type inference for nested array child types +is not complete, however (and making it complete, at least with a naive +implementation, would make it O(N^2), which is not worth it) and so some +text format arrays were triggering an assertion failure in the error +handling code. + +Fix that by making the error handling code a little more relaxed, in the +knowledge that our type inference algorithm is not complete. See the +comment added to the code. + +This includes a test case, provided by oss-fuzz. + +oss-fuzz#11578 + +Signed-off-by: Philip Withnall +--- + glib/gvariant-parser.c | 28 ++++++++++++++++++++++++++-- + glib/tests/gvariant.c | 1 + + 2 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c +index 2b02ec90f..3b4956a9c 100644 +--- a/glib/gvariant-parser.c ++++ b/glib/gvariant-parser.c +@@ -671,6 +671,20 @@ ast_array_get_pattern (AST **array, + gchar *pattern; + gint i; + ++ /* Find the pattern which applies to all children in the array, by l-folding a ++ * coalesce operation. This will not always work: for example, the GVariant: ++ * [[0], [], [nothing]] ++ * has patterns: ++ * MaMN, Ma*, Mam* ++ * which pairwise coalesce as: ++ * MaMN + Ma* = MaN ++ * MaN + Mam* = (doesn’t coalesce) ++ * ++ * However, the pattern MamN coalesces with all three child patterns. Finding ++ * this pattern would require trying all O(n_items^2) pairs, though, which is ++ * expensive. Just let it fail, and require the user to provide type ++ * annotations. ++ */ + pattern = ast_get_pattern (array[0], error); + + if (pattern == NULL) +@@ -705,8 +719,18 @@ ast_array_get_pattern (AST **array, + gchar *tmp2; + gchar *m; + +- /* if 'j' reaches 'i' then we failed to find the pair */ +- g_assert (j < i); ++ /* if 'j' reaches 'i' then we failed to find the pair, which can ++ * happen due to only trying pairwise coalesces in order rather ++ * than between all pairs (see above). so just report an error ++ * for i. */ ++ if (j >= i) ++ { ++ ast_set_error (array[i], error, NULL, ++ G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE, ++ "unable to find a common type"); ++ g_free (tmp); ++ return NULL; ++ } + + tmp2 = ast_get_pattern (array[j], NULL); + g_assert (tmp2 != NULL); +diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c +index 33caaf04a..80bc7caf4 100644 +--- a/glib/tests/gvariant.c ++++ b/glib/tests/gvariant.c +@@ -3943,6 +3943,7 @@ test_parse_failures (void) + "[4, 5, '']", "1-2,7-9:", "common type", + "[[4], [], ['']]", "1-4,10-14:", "common type", + "[[], [4], ['']]", "5-8,10-14:", "common type", ++ "[[0], [], [nothing]]", "10-19:", "common type", + "just", "4:", "expected value", + "nothing", "0-7:", "unable to infer", + "just [4, '']", "6-7,9-11:", "common type", +-- +2.19.1 + diff --git a/gvariant-parser-Fix-parsing-of-G_MININT-values-in-GV.patch b/gvariant-parser-Fix-parsing-of-G_MININT-values-in-GV.patch new file mode 100644 index 0000000..ba66e01 --- /dev/null +++ b/gvariant-parser-Fix-parsing-of-G_MININT-values-in-GV.patch @@ -0,0 +1,117 @@ +From 0fcd5ac89d442845254939870107cef40bafceef Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Tue, 5 Feb 2019 13:47:25 +0000 +Subject: [PATCH 562/682] gvariant-parser: Fix parsing of G_MININT* values in + GVariant text format +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +And add tests. + +There wasn’t actually a bug on x86_64 before, but it was making use of +undefined behaviour, and hence triggering ubsan warnings. Make the code +more explicit, and avoid undefined behaviour. + +oss-fuzz#12686 + +Signed-off-by: Philip Withnall +--- + glib/gvariant-parser.c | 8 ++++++++ + glib/tests/gvariant.c | 33 +++++++++++++++++++++++++++++++++ + 2 files changed, 41 insertions(+) + +diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c +index 2b02ec90f..ea1ca22e4 100644 +--- a/glib/gvariant-parser.c ++++ b/glib/gvariant-parser.c +@@ -1921,6 +1921,8 @@ number_get_value (AST *ast, + case 'n': + if (abs_val - negative > G_MAXINT16) + return number_overflow (ast, type, error); ++ if (negative && abs_val > G_MAXINT16) ++ return g_variant_new_int16 (G_MININT16); + return g_variant_new_int16 (negative ? -((gint16) abs_val) : abs_val); + + case 'q': +@@ -1931,6 +1933,8 @@ number_get_value (AST *ast, + case 'i': + if (abs_val - negative > G_MAXINT32) + return number_overflow (ast, type, error); ++ if (negative && abs_val > G_MAXINT32) ++ return g_variant_new_int32 (G_MININT32); + return g_variant_new_int32 (negative ? -((gint32) abs_val) : abs_val); + + case 'u': +@@ -1941,6 +1945,8 @@ number_get_value (AST *ast, + case 'x': + if (abs_val - negative > G_MAXINT64) + return number_overflow (ast, type, error); ++ if (negative && abs_val > G_MAXINT64) ++ return g_variant_new_int64 (G_MININT64); + return g_variant_new_int64 (negative ? -((gint64) abs_val) : abs_val); + + case 't': +@@ -1951,6 +1957,8 @@ number_get_value (AST *ast, + case 'h': + if (abs_val - negative > G_MAXINT32) + return number_overflow (ast, type, error); ++ if (negative && abs_val > G_MAXINT32) ++ return g_variant_new_handle (G_MININT32); + return g_variant_new_handle (negative ? -((gint32) abs_val) : abs_val); + + default: +diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c +index 33caaf04a..4a3aa771f 100644 +--- a/glib/tests/gvariant.c ++++ b/glib/tests/gvariant.c +@@ -4097,6 +4097,38 @@ test_parse_failures (void) + } + } + ++/* Test that parsing GVariant text format integers works at the boundaries of ++ * those integer types. We’re especially interested in the handling of the most ++ * negative numbers, since those can’t be represented in sign + absolute value ++ * form. */ ++static void ++test_parser_integer_bounds (void) ++{ ++ GVariant *value = NULL; ++ GError *local_error = NULL; ++ ++#define test_bound(TYPE, type, text, expected_value) \ ++ value = g_variant_parse (G_VARIANT_TYPE_##TYPE, text, NULL, NULL, &local_error); \ ++ g_assert_no_error (local_error); \ ++ g_assert_nonnull (value); \ ++ g_assert_true (g_variant_is_of_type (value, G_VARIANT_TYPE_##TYPE)); \ ++ g_assert_cmpint (g_variant_get_##type (value), ==, expected_value); \ ++ g_variant_unref (value) ++ ++ test_bound (BYTE, byte, "0", 0); ++ test_bound (BYTE, byte, "255", G_MAXUINT8); ++ test_bound (INT16, int16, "-32768", G_MININT16); ++ test_bound (INT16, int16, "32767", G_MAXINT16); ++ test_bound (INT32, int32, "-2147483648", G_MININT32); ++ test_bound (INT32, int32, "2147483647", G_MAXINT32); ++ test_bound (INT64, int64, "-9223372036854775808", G_MININT64); ++ test_bound (INT64, int64, "9223372036854775807", G_MAXINT64); ++ test_bound (HANDLE, handle, "-2147483648", G_MININT32); ++ test_bound (HANDLE, handle, "2147483647", G_MAXINT32); ++ ++#undef test_bound ++} ++ + static void + test_parse_bad_format_char (void) + { +@@ -5068,6 +5100,7 @@ main (int argc, char **argv) + g_test_add_func ("/gvariant/hashing", test_hashing); + g_test_add_func ("/gvariant/byteswap", test_gv_byteswap); + g_test_add_func ("/gvariant/parser", test_parses); ++ g_test_add_func ("/gvariant/parser/integer-bounds", test_parser_integer_bounds); + g_test_add_func ("/gvariant/parse-failures", test_parse_failures); + g_test_add_func ("/gvariant/parse-positional", test_parse_positional); + g_test_add_func ("/gvariant/parse/subprocess/bad-format-char", test_parse_bad_format_char); +-- +2.19.1 + diff --git a/list-store-Fix-overflow-issues.patch b/list-store-Fix-overflow-issues.patch new file mode 100644 index 0000000..f125cab --- /dev/null +++ b/list-store-Fix-overflow-issues.patch @@ -0,0 +1,36 @@ +From d8a0dcb11e92d3237f5f4e90a4916df518bdc53d Mon Sep 17 00:00:00 2001 +From: Matthias Clasen +Date: Sun, 6 Jan 2019 14:17:30 -0500 +Subject: [PATCH 441/682] list store: Fix overflow issues + +Check for over- and underflow when manipulating positions. + +This makes the sequence + g_list_model_get_item (store, 0); + g_list_model_get_item (store, -1u); +return NULL for the second call, as it should. + +Closes: #1639 +--- + gio/gliststore.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gio/gliststore.c b/gio/gliststore.c +index ae8e2c1d8..8d87159d5 100644 +--- a/gio/gliststore.c ++++ b/gio/gliststore.c +@@ -181,9 +181,9 @@ g_list_store_get_item (GListModel *list, + + if (store->last_position != -1u) + { +- if (store->last_position == position + 1) ++ if (position < G_MAXUINT && store->last_position == position + 1) + it = g_sequence_iter_prev (store->last_iter); +- else if (store->last_position == position - 1) ++ else if (position > 0 && store->last_position == position - 1) + it = g_sequence_iter_next (store->last_iter); + else if (store->last_position == position) + it = store->last_iter; +-- +2.19.1 +