Compare commits
No commits in common. "c8" and "c8-beta" have entirely different histories.
@ -1,83 +0,0 @@
|
|||||||
From d9fec76b594fccc6eda3ce04a74beae1c8b8c1d2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ondrej Holy <oholy@redhat.com>
|
|
||||||
Date: Fri, 12 Jul 2024 11:14:10 +0200
|
|
||||||
Subject: [PATCH] gfile: Add support for x-gvfs-trash mount option
|
|
||||||
|
|
||||||
Currently, the trash functionality is disabled for system internal mounts.
|
|
||||||
That might be a problem in some cases. The `x-gvfs-notrash` mount option
|
|
||||||
allows disabling the trash functionality for certain mounts. Let's add
|
|
||||||
support for the `x-gvfs-trash` mount option to allow the opposite.
|
|
||||||
|
|
||||||
See: https://issues.redhat.com/browse/RHEL-46828
|
|
||||||
---
|
|
||||||
gio/gfile.c | 7 +++++--
|
|
||||||
gio/glocalfile.c | 22 +++++++++++++---------
|
|
||||||
2 files changed, 18 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gfile.c b/gio/gfile.c
|
|
||||||
index 4f9b9c6750..5ac73c03e8 100644
|
|
||||||
--- a/gio/gfile.c
|
|
||||||
+++ b/gio/gfile.c
|
|
||||||
@@ -4744,10 +4744,13 @@ g_file_delete_finish (GFile *file,
|
|
||||||
*
|
|
||||||
* Sends @file to the "Trashcan", if possible. This is similar to
|
|
||||||
* deleting it, but the user can recover it before emptying the trashcan.
|
|
||||||
- * Not all file systems support trashing, so this call can return the
|
|
||||||
+ * Trashing is disabled for system mounts by default (see
|
|
||||||
+ * g_unix_mount_is_system_internal()), so this call can return the
|
|
||||||
* %G_IO_ERROR_NOT_SUPPORTED error. Since GLib 2.66, the `x-gvfs-notrash` unix
|
|
||||||
- * mount option can be used to disable g_file_trash() support for certain
|
|
||||||
+ * mount option can be used to disable g_file_trash() support for particular
|
|
||||||
* mounts, the %G_IO_ERROR_NOT_SUPPORTED error will be returned in that case.
|
|
||||||
+ * Since 2.82, the `x-gvfs-trash` unix mount option can be used to enable
|
|
||||||
+ * g_file_trash() support for particular system mounts.
|
|
||||||
*
|
|
||||||
* If @cancellable is not %NULL, then the operation can be cancelled by
|
|
||||||
* triggering the cancellable object from another thread. If the operation
|
|
||||||
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
|
|
||||||
index 7b70c614c6..ac918d25e3 100644
|
|
||||||
--- a/gio/glocalfile.c
|
|
||||||
+++ b/gio/glocalfile.c
|
|
||||||
@@ -1807,10 +1807,6 @@ ignore_trash_mount (GUnixMountEntry *mount)
|
|
||||||
{
|
|
||||||
GUnixMountPoint *mount_point = NULL;
|
|
||||||
const gchar *mount_options;
|
|
||||||
- gboolean retval = TRUE;
|
|
||||||
-
|
|
||||||
- if (g_unix_mount_is_system_internal (mount))
|
|
||||||
- return TRUE;
|
|
||||||
|
|
||||||
mount_options = g_unix_mount_get_options (mount);
|
|
||||||
if (mount_options == NULL)
|
|
||||||
@@ -1819,15 +1815,23 @@ ignore_trash_mount (GUnixMountEntry *mount)
|
|
||||||
NULL);
|
|
||||||
if (mount_point != NULL)
|
|
||||||
mount_options = g_unix_mount_point_get_options (mount_point);
|
|
||||||
+
|
|
||||||
+ g_clear_pointer (&mount_point, g_unix_mount_point_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (mount_options == NULL ||
|
|
||||||
- strstr (mount_options, "x-gvfs-notrash") == NULL)
|
|
||||||
- retval = FALSE;
|
|
||||||
+ if (mount_options != NULL)
|
|
||||||
+ {
|
|
||||||
+ if (strstr (mount_options, "x-gvfs-trash") != NULL)
|
|
||||||
+ return FALSE;
|
|
||||||
+
|
|
||||||
+ if (strstr (mount_options, "x-gvfs-notrash") != NULL)
|
|
||||||
+ return TRUE;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- g_clear_pointer (&mount_point, g_unix_mount_point_free);
|
|
||||||
+ if (g_unix_mount_is_system_internal (mount))
|
|
||||||
+ return TRUE;
|
|
||||||
|
|
||||||
- return retval;
|
|
||||||
+ return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
--
|
|
||||||
GitLab
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,45 +0,0 @@
|
|||||||
From 25833cefda24c60af913d6f2d532b5afd608b821 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Michael Catanzaro <mcatanzaro@redhat.com>
|
|
||||||
Date: Thu, 19 Sep 2024 18:35:53 +0100
|
|
||||||
Subject: [PATCH] gsocks4aproxy: Fix a single byte buffer overflow in connect
|
|
||||||
messages
|
|
||||||
|
|
||||||
`SOCKS4_CONN_MSG_LEN` failed to account for the length of the final nul
|
|
||||||
byte in the connect message, which is an addition in SOCKSv4a vs
|
|
||||||
SOCKSv4.
|
|
||||||
|
|
||||||
This means that the buffer for building and transmitting the connect
|
|
||||||
message could be overflowed if the username and hostname are both
|
|
||||||
`SOCKS4_MAX_LEN` (255) bytes long.
|
|
||||||
|
|
||||||
Proxy configurations are normally statically configured, so the username
|
|
||||||
is very unlikely to be near its maximum length, and hence this overflow
|
|
||||||
is unlikely to be triggered in practice.
|
|
||||||
|
|
||||||
(Commit message by Philip Withnall, diagnosis and fix by Michael
|
|
||||||
Catanzaro.)
|
|
||||||
|
|
||||||
Fixes: #3461
|
|
||||||
---
|
|
||||||
gio/gsocks4aproxy.c | 4 ++--
|
|
||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gsocks4aproxy.c b/gio/gsocks4aproxy.c
|
|
||||||
index 3dad118eb7..b3146d08fd 100644
|
|
||||||
--- a/gio/gsocks4aproxy.c
|
|
||||||
+++ b/gio/gsocks4aproxy.c
|
|
||||||
@@ -79,9 +79,9 @@ g_socks4a_proxy_init (GSocks4aProxy *proxy)
|
|
||||||
* +----+----+----+----+----+----+----+----+----+----+....+----+------+....+------+
|
|
||||||
* | VN | CD | DSTPORT | DSTIP | USERID |NULL| HOST | | NULL |
|
|
||||||
* +----+----+----+----+----+----+----+----+----+----+....+----+------+....+------+
|
|
||||||
- * 1 1 2 4 variable 1 variable
|
|
||||||
+ * 1 1 2 4 variable 1 variable 1
|
|
||||||
*/
|
|
||||||
-#define SOCKS4_CONN_MSG_LEN (9 + SOCKS4_MAX_LEN * 2)
|
|
||||||
+#define SOCKS4_CONN_MSG_LEN (10 + SOCKS4_MAX_LEN * 2)
|
|
||||||
static gint
|
|
||||||
set_connect_msg (guint8 *msg,
|
|
||||||
const gchar *hostname,
|
|
||||||
--
|
|
||||||
GitLab
|
|
||||||
|
|
||||||
@ -1,124 +0,0 @@
|
|||||||
From 115b2b74d93ba1c61d842baba3612938a5bfb759 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Philip Withnall <pwithnall@gnome.org>
|
|
||||||
Date: Thu, 13 Nov 2025 18:27:22 +0000
|
|
||||||
Subject: [PATCH] gconvert: Error out if g_escape_uri_string() would overflow
|
|
||||||
|
|
||||||
If the string to escape contains a very large number of unacceptable
|
|
||||||
characters (which would need escaping), the calculation of the length of
|
|
||||||
the escaped string could overflow, leading to a potential write off the
|
|
||||||
end of the newly allocated string.
|
|
||||||
|
|
||||||
In addition to that, the number of unacceptable characters was counted
|
|
||||||
in a signed integer, which would overflow to become negative, making it
|
|
||||||
easier for an attacker to craft an input string which would cause an
|
|
||||||
out-of-bounds write.
|
|
||||||
|
|
||||||
Fix that by validating the allocation length, and using an unsigned
|
|
||||||
integer to count the number of unacceptable characters.
|
|
||||||
|
|
||||||
Spotted by treeplus. Thanks to the Sovereign Tech Resilience programme
|
|
||||||
from the Sovereign Tech Agency. ID: #YWH-PGM9867-134
|
|
||||||
|
|
||||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
|
||||||
|
|
||||||
Fixes: #3827
|
|
||||||
---
|
|
||||||
glib/gconvert.c | 36 +++++++++++++++++++++++++-----------
|
|
||||||
1 file changed, 25 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/glib/gconvert.c b/glib/gconvert.c
|
|
||||||
index 50286478c..066c391d6 100644
|
|
||||||
--- a/glib/gconvert.c
|
|
||||||
+++ b/glib/gconvert.c
|
|
||||||
@@ -1386,8 +1386,9 @@ static const gchar hex[16] = "0123456789ABCDEF";
|
|
||||||
/* Note: This escape function works on file: URIs, but if you want to
|
|
||||||
* escape something else, please read RFC-2396 */
|
|
||||||
static gchar *
|
|
||||||
-g_escape_uri_string (const gchar *string,
|
|
||||||
- UnsafeCharacterSet mask)
|
|
||||||
+g_escape_uri_string (const gchar *string,
|
|
||||||
+ UnsafeCharacterSet mask,
|
|
||||||
+ GError **error)
|
|
||||||
{
|
|
||||||
#define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
|
|
||||||
|
|
||||||
@@ -1395,7 +1396,7 @@ g_escape_uri_string (const gchar *string,
|
|
||||||
gchar *q;
|
|
||||||
gchar *result;
|
|
||||||
int c;
|
|
||||||
- gint unacceptable;
|
|
||||||
+ size_t unacceptable;
|
|
||||||
UnsafeCharacterSet use_mask;
|
|
||||||
|
|
||||||
g_return_val_if_fail (mask == UNSAFE_ALL
|
|
||||||
@@ -1412,7 +1413,14 @@ g_escape_uri_string (const gchar *string,
|
|
||||||
if (!ACCEPTABLE (c))
|
|
||||||
unacceptable++;
|
|
||||||
}
|
|
||||||
-
|
|
||||||
+
|
|
||||||
+ if (unacceptable >= (G_MAXSIZE - (p - string)) / 2)
|
|
||||||
+ {
|
|
||||||
+ g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
|
|
||||||
+ _("The URI is too long"));
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
result = g_malloc (p - string + unacceptable * 2 + 1);
|
|
||||||
|
|
||||||
use_mask = mask;
|
|
||||||
@@ -1437,12 +1445,13 @@ g_escape_uri_string (const gchar *string,
|
|
||||||
|
|
||||||
|
|
||||||
static gchar *
|
|
||||||
-g_escape_file_uri (const gchar *hostname,
|
|
||||||
- const gchar *pathname)
|
|
||||||
+g_escape_file_uri (const gchar *hostname,
|
|
||||||
+ const gchar *pathname,
|
|
||||||
+ GError **error)
|
|
||||||
{
|
|
||||||
char *escaped_hostname = NULL;
|
|
||||||
- char *escaped_path;
|
|
||||||
- char *res;
|
|
||||||
+ char *escaped_path = NULL;
|
|
||||||
+ char *res = NULL;
|
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
|
||||||
char *p, *backslash;
|
|
||||||
@@ -1463,10 +1472,14 @@ g_escape_file_uri (const gchar *hostname,
|
|
||||||
|
|
||||||
if (hostname && *hostname != '\0')
|
|
||||||
{
|
|
||||||
- escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST);
|
|
||||||
+ escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST, error);
|
|
||||||
+ if (escaped_hostname == NULL)
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH);
|
|
||||||
+ escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH, error);
|
|
||||||
+ if (escaped_path == NULL)
|
|
||||||
+ goto out;
|
|
||||||
|
|
||||||
res = g_strconcat ("file://",
|
|
||||||
(escaped_hostname) ? escaped_hostname : "",
|
|
||||||
@@ -1474,6 +1487,7 @@ g_escape_file_uri (const gchar *hostname,
|
|
||||||
escaped_path,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
+out:
|
|
||||||
#ifdef G_OS_WIN32
|
|
||||||
g_free ((char *) pathname);
|
|
||||||
#endif
|
|
||||||
@@ -1793,7 +1807,7 @@ g_filename_to_uri (const gchar *filename,
|
|
||||||
hostname = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- escaped_uri = g_escape_file_uri (hostname, filename);
|
|
||||||
+ escaped_uri = g_escape_file_uri (hostname, filename, error);
|
|
||||||
|
|
||||||
return escaped_uri;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.52.0
|
|
||||||
|
|
||||||
@ -1,433 +0,0 @@
|
|||||||
From 6c2178a3bc216a6cc765fc6ba3b0e6d22ce5af7e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Emmanuel Fleury <emmanuel.fleury@u-bordeaux.fr>
|
|
||||||
Date: Mon, 4 Feb 2019 13:31:28 +0100
|
|
||||||
Subject: [PATCH 1/3] Fixing various warnings in glib/gstring.c
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
In file included from glib/glibconfig.h:9,
|
|
||||||
from glib/gtypes.h:32,
|
|
||||||
from glib/gstring.h:32,
|
|
||||||
from glib/gstring.c:37:
|
|
||||||
glib/gstring.c: In function ‘g_string_insert_len’:
|
|
||||||
glib/gstring.c:441:31: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
^~
|
|
||||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
|
||||||
#define G_LIKELY(expr) (expr)
|
|
||||||
^~~~
|
|
||||||
glib/gstring.c:441:5: note: in expansion of macro ‘g_return_val_if_fail’
|
|
||||||
g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
^~~~~~~~~~~~~~~~~~~~
|
|
||||||
glib/gstring.c:458:15: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
if (pos < string->len)
|
|
||||||
^
|
|
||||||
glib/gstring.c:462:18: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘gssize’ {aka ‘long int’} [-Werror=sign-compare]
|
|
||||||
if (offset < pos)
|
|
||||||
^
|
|
||||||
In file included from glib/glibconfig.h:9,
|
|
||||||
from glib/gtypes.h:32,
|
|
||||||
from glib/gstring.h:32,
|
|
||||||
from glib/gstring.c:37:
|
|
||||||
glib/gmacros.h:351:26: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘long unsigned int’ [-Werror=sign-compare]
|
|
||||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|
||||||
^
|
|
||||||
glib/gstring.c:464:22: note: in expansion of macro ‘MIN’
|
|
||||||
precount = MIN (len, pos - offset);
|
|
||||||
^~~
|
|
||||||
glib/gmacros.h:351:35: error: operand of ?: changes signedness from ‘gssize’ {aka ‘long int’} to ‘long unsigned int’ due to unsignedness of other operand [-Werror=sign-compare]
|
|
||||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|
||||||
^~~
|
|
||||||
glib/gstring.c:464:22: note: in expansion of macro ‘MIN’
|
|
||||||
precount = MIN (len, pos - offset);
|
|
||||||
^~~
|
|
||||||
glib/gstring.c:469:15: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
if (len > precount)
|
|
||||||
^
|
|
||||||
glib/gstring.c:481:15: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
if (pos < string->len)
|
|
||||||
^
|
|
||||||
In file included from glib/glibconfig.h:9,
|
|
||||||
from glib/gtypes.h:32,
|
|
||||||
from glib/gstring.h:32,
|
|
||||||
from glib/gstring.c:37:
|
|
||||||
glib/gstring.c: In function ‘g_string_insert_c’:
|
|
||||||
glib/gstring.c:782:31: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
^~
|
|
||||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
|
||||||
#define G_LIKELY(expr) (expr)
|
|
||||||
^~~~
|
|
||||||
glib/gstring.c:782:5: note: in expansion of macro ‘g_return_val_if_fail’
|
|
||||||
g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
^~~~~~~~~~~~~~~~~~~~
|
|
||||||
glib/gstring.c:785:11: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
if (pos < string->len)
|
|
||||||
^
|
|
||||||
In file included from glib/glibconfig.h:9,
|
|
||||||
from glib/gtypes.h:32,
|
|
||||||
from glib/gstring.h:32,
|
|
||||||
from glib/gstring.c:37:
|
|
||||||
glib/gstring.c: In function ‘g_string_insert_unichar’:
|
|
||||||
glib/gstring.c:857:31: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
^~
|
|
||||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
|
||||||
#define G_LIKELY(expr) (expr)
|
|
||||||
^~~~
|
|
||||||
glib/gstring.c:857:5: note: in expansion of macro ‘g_return_val_if_fail’
|
|
||||||
g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
^~~~~~~~~~~~~~~~~~~~
|
|
||||||
glib/gstring.c:860:11: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
if (pos < string->len)
|
|
||||||
^
|
|
||||||
In file included from glib/glibconfig.h:9,
|
|
||||||
from glib/gtypes.h:32,
|
|
||||||
from glib/gstring.h:32,
|
|
||||||
from glib/gstring.c:37:
|
|
||||||
glib/gstring.c: In function ‘g_string_erase’:
|
|
||||||
glib/gstring.c:969:29: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
^~
|
|
||||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
|
||||||
#define G_LIKELY(expr) (expr)
|
|
||||||
^~~~
|
|
||||||
glib/gstring.c:969:3: note: in expansion of macro ‘g_return_val_if_fail’
|
|
||||||
g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
^~~~~~~~~~~~~~~~~~~~
|
|
||||||
glib/gstring.c:975:39: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
g_return_val_if_fail (pos + len <= string->len, string);
|
|
||||||
^~
|
|
||||||
glib/gmacros.h:455:25: note: in definition of macro ‘G_LIKELY’
|
|
||||||
#define G_LIKELY(expr) (expr)
|
|
||||||
^~~~
|
|
||||||
glib/gstring.c:975:7: note: in expansion of macro ‘g_return_val_if_fail’
|
|
||||||
g_return_val_if_fail (pos + len <= string->len, string);
|
|
||||||
^~~~~~~~~~~~~~~~~~~~
|
|
||||||
glib/gstring.c:977:21: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
|
|
||||||
if (pos + len < string->len)
|
|
||||||
^
|
|
||||||
---
|
|
||||||
glib/gstring.c | 82 +++++++++++++++++++++++++++++++-------------------
|
|
||||||
1 file changed, 51 insertions(+), 31 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/glib/gstring.c b/glib/gstring.c
|
|
||||||
index 966502019..f5bfeb0ed 100644
|
|
||||||
--- a/glib/gstring.c
|
|
||||||
+++ b/glib/gstring.c
|
|
||||||
@@ -426,6 +426,8 @@ g_string_insert_len (GString *string,
|
|
||||||
const gchar *val,
|
|
||||||
gssize len)
|
|
||||||
{
|
|
||||||
+ gsize len_unsigned, pos_unsigned;
|
|
||||||
+
|
|
||||||
g_return_val_if_fail (string != NULL, NULL);
|
|
||||||
g_return_val_if_fail (len == 0 || val != NULL, string);
|
|
||||||
|
|
||||||
@@ -434,11 +436,15 @@ g_string_insert_len (GString *string,
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
len = strlen (val);
|
|
||||||
+ len_unsigned = len;
|
|
||||||
|
|
||||||
if (pos < 0)
|
|
||||||
- pos = string->len;
|
|
||||||
+ pos_unsigned = string->len;
|
|
||||||
else
|
|
||||||
- g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
+ {
|
|
||||||
+ pos_unsigned = pos;
|
|
||||||
+ g_return_val_if_fail (pos_unsigned <= string->len, string);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* Check whether val represents a substring of string.
|
|
||||||
* This test probably violates chapter and verse of the C standards,
|
|
||||||
@@ -450,45 +456,48 @@ g_string_insert_len (GString *string,
|
|
||||||
gsize offset = val - string->str;
|
|
||||||
gsize precount = 0;
|
|
||||||
|
|
||||||
- g_string_maybe_expand (string, len);
|
|
||||||
+ g_string_maybe_expand (string, len_unsigned);
|
|
||||||
val = string->str + offset;
|
|
||||||
/* At this point, val is valid again. */
|
|
||||||
|
|
||||||
/* Open up space where we are going to insert. */
|
|
||||||
- if (pos < string->len)
|
|
||||||
- memmove (string->str + pos + len, string->str + pos, string->len - pos);
|
|
||||||
+ if (pos_unsigned < string->len)
|
|
||||||
+ memmove (string->str + pos_unsigned + len_unsigned,
|
|
||||||
+ string->str + pos_unsigned, string->len - pos_unsigned);
|
|
||||||
|
|
||||||
/* Move the source part before the gap, if any. */
|
|
||||||
- if (offset < pos)
|
|
||||||
+ if (offset < pos_unsigned)
|
|
||||||
{
|
|
||||||
- precount = MIN (len, pos - offset);
|
|
||||||
- memcpy (string->str + pos, val, precount);
|
|
||||||
+ precount = MIN (len_unsigned, pos_unsigned - offset);
|
|
||||||
+ memcpy (string->str + pos_unsigned, val, precount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move the source part after the gap, if any. */
|
|
||||||
- if (len > precount)
|
|
||||||
- memcpy (string->str + pos + precount,
|
|
||||||
- val + /* Already moved: */ precount + /* Space opened up: */ len,
|
|
||||||
- len - precount);
|
|
||||||
+ if (len_unsigned > precount)
|
|
||||||
+ memcpy (string->str + pos_unsigned + precount,
|
|
||||||
+ val + /* Already moved: */ precount +
|
|
||||||
+ /* Space opened up: */ len_unsigned,
|
|
||||||
+ len_unsigned - precount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
- g_string_maybe_expand (string, len);
|
|
||||||
+ g_string_maybe_expand (string, len_unsigned);
|
|
||||||
|
|
||||||
/* If we aren't appending at the end, move a hunk
|
|
||||||
* of the old string to the end, opening up space
|
|
||||||
*/
|
|
||||||
- if (pos < string->len)
|
|
||||||
- memmove (string->str + pos + len, string->str + pos, string->len - pos);
|
|
||||||
+ if (pos_unsigned < string->len)
|
|
||||||
+ memmove (string->str + pos_unsigned + len_unsigned,
|
|
||||||
+ string->str + pos_unsigned, string->len - pos_unsigned);
|
|
||||||
|
|
||||||
/* insert the new string */
|
|
||||||
- if (len == 1)
|
|
||||||
- string->str[pos] = *val;
|
|
||||||
+ if (len_unsigned == 1)
|
|
||||||
+ string->str[pos_unsigned] = *val;
|
|
||||||
else
|
|
||||||
- memcpy (string->str + pos, val, len);
|
|
||||||
+ memcpy (string->str + pos_unsigned, val, len_unsigned);
|
|
||||||
}
|
|
||||||
|
|
||||||
- string->len += len;
|
|
||||||
+ string->len += len_unsigned;
|
|
||||||
|
|
||||||
string->str[string->len] = 0;
|
|
||||||
|
|
||||||
@@ -772,6 +781,8 @@ g_string_insert_c (GString *string,
|
|
||||||
gssize pos,
|
|
||||||
gchar c)
|
|
||||||
{
|
|
||||||
+ gsize pos_unsigned;
|
|
||||||
+
|
|
||||||
g_return_val_if_fail (string != NULL, NULL);
|
|
||||||
|
|
||||||
g_string_maybe_expand (string, 1);
|
|
||||||
@@ -779,13 +790,15 @@ g_string_insert_c (GString *string,
|
|
||||||
if (pos < 0)
|
|
||||||
pos = string->len;
|
|
||||||
else
|
|
||||||
- g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
+ g_return_val_if_fail ((gsize) pos <= string->len, string);
|
|
||||||
+ pos_unsigned = pos;
|
|
||||||
|
|
||||||
/* If not just an append, move the old stuff */
|
|
||||||
- if (pos < string->len)
|
|
||||||
- memmove (string->str + pos + 1, string->str + pos, string->len - pos);
|
|
||||||
+ if (pos_unsigned < string->len)
|
|
||||||
+ memmove (string->str + pos_unsigned + 1,
|
|
||||||
+ string->str + pos_unsigned, string->len - pos_unsigned);
|
|
||||||
|
|
||||||
- string->str[pos] = c;
|
|
||||||
+ string->str[pos_unsigned] = c;
|
|
||||||
|
|
||||||
string->len += 1;
|
|
||||||
|
|
||||||
@@ -854,10 +867,10 @@ g_string_insert_unichar (GString *string,
|
|
||||||
if (pos < 0)
|
|
||||||
pos = string->len;
|
|
||||||
else
|
|
||||||
- g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
+ g_return_val_if_fail ((gsize) pos <= string->len, string);
|
|
||||||
|
|
||||||
/* If not just an append, move the old stuff */
|
|
||||||
- if (pos < string->len)
|
|
||||||
+ if ((gsize) pos < string->len)
|
|
||||||
memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
|
|
||||||
|
|
||||||
dest = string->str + pos;
|
|
||||||
@@ -964,21 +977,28 @@ g_string_erase (GString *string,
|
|
||||||
gssize pos,
|
|
||||||
gssize len)
|
|
||||||
{
|
|
||||||
+ gsize len_unsigned, pos_unsigned;
|
|
||||||
+
|
|
||||||
g_return_val_if_fail (string != NULL, NULL);
|
|
||||||
g_return_val_if_fail (pos >= 0, string);
|
|
||||||
- g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
+ pos_unsigned = pos;
|
|
||||||
+
|
|
||||||
+ g_return_val_if_fail (pos_unsigned <= string->len, string);
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
- len = string->len - pos;
|
|
||||||
+ len_unsigned = string->len - pos_unsigned;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
- g_return_val_if_fail (pos + len <= string->len, string);
|
|
||||||
+ len_unsigned = len;
|
|
||||||
+ g_return_val_if_fail (pos_unsigned + len_unsigned <= string->len, string);
|
|
||||||
|
|
||||||
- if (pos + len < string->len)
|
|
||||||
- memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
|
|
||||||
+ if (pos_unsigned + len_unsigned < string->len)
|
|
||||||
+ memmove (string->str + pos_unsigned,
|
|
||||||
+ string->str + pos_unsigned + len_unsigned,
|
|
||||||
+ string->len - (pos_unsigned + len_unsigned));
|
|
||||||
}
|
|
||||||
|
|
||||||
- string->len -= len;
|
|
||||||
+ string->len -= len_unsigned;
|
|
||||||
|
|
||||||
string->str[string->len] = 0;
|
|
||||||
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
|
|
||||||
From 101afb01778659cb7051b3cb33d55dc965c8dc7e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Michael Catanzaro <mcatanzaro@redhat.com>
|
|
||||||
Date: Thu, 10 Apr 2025 10:57:20 -0500
|
|
||||||
Subject: [PATCH 2/3] gstring: carefully handle gssize parameters
|
|
||||||
|
|
||||||
Wherever we use gssize to allow passing -1, we need to ensure we don't
|
|
||||||
overflow the value by assigning a gsize to it without checking if the
|
|
||||||
size exceeds the maximum gssize. The safest way to do this is to just
|
|
||||||
use normal gsize everywhere instead and use gssize only for the
|
|
||||||
parameter.
|
|
||||||
|
|
||||||
Our computers don't have enough RAM to write tests for this. I tried
|
|
||||||
forcing string->len to high values for test purposes, but this isn't
|
|
||||||
valid and will just cause out of bounds reads/writes due to
|
|
||||||
string->allocated_len being unexpectedly small, so I don't think we can
|
|
||||||
test this easily.
|
|
||||||
---
|
|
||||||
glib/gstring.c | 36 +++++++++++++++++++++++-------------
|
|
||||||
1 file changed, 23 insertions(+), 13 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/glib/gstring.c b/glib/gstring.c
|
|
||||||
index f5bfeb0ed..84a98da25 100644
|
|
||||||
--- a/glib/gstring.c
|
|
||||||
+++ b/glib/gstring.c
|
|
||||||
@@ -435,8 +435,9 @@ g_string_insert_len (GString *string,
|
|
||||||
return string;
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
- len = strlen (val);
|
|
||||||
- len_unsigned = len;
|
|
||||||
+ len_unsigned = strlen (val);
|
|
||||||
+ else
|
|
||||||
+ len_unsigned = len;
|
|
||||||
|
|
||||||
if (pos < 0)
|
|
||||||
pos_unsigned = string->len;
|
|
||||||
@@ -788,10 +789,12 @@ g_string_insert_c (GString *string,
|
|
||||||
g_string_maybe_expand (string, 1);
|
|
||||||
|
|
||||||
if (pos < 0)
|
|
||||||
- pos = string->len;
|
|
||||||
+ pos_unsigned = string->len;
|
|
||||||
else
|
|
||||||
- g_return_val_if_fail ((gsize) pos <= string->len, string);
|
|
||||||
- pos_unsigned = pos;
|
|
||||||
+ {
|
|
||||||
+ pos_unsigned = pos;
|
|
||||||
+ g_return_val_if_fail (pos_unsigned <= string->len, string);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* If not just an append, move the old stuff */
|
|
||||||
if (pos_unsigned < string->len)
|
|
||||||
@@ -824,6 +827,7 @@ g_string_insert_unichar (GString *string,
|
|
||||||
gssize pos,
|
|
||||||
gunichar wc)
|
|
||||||
{
|
|
||||||
+ gsize pos_unsigned;
|
|
||||||
gint charlen, first, i;
|
|
||||||
gchar *dest;
|
|
||||||
|
|
||||||
@@ -865,15 +869,18 @@ g_string_insert_unichar (GString *string,
|
|
||||||
g_string_maybe_expand (string, charlen);
|
|
||||||
|
|
||||||
if (pos < 0)
|
|
||||||
- pos = string->len;
|
|
||||||
+ pos_unsigned = string->len;
|
|
||||||
else
|
|
||||||
- g_return_val_if_fail ((gsize) pos <= string->len, string);
|
|
||||||
+ {
|
|
||||||
+ pos_unsigned = pos;
|
|
||||||
+ g_return_val_if_fail (pos_unsigned <= string->len, string);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* If not just an append, move the old stuff */
|
|
||||||
- if ((gsize) pos < string->len)
|
|
||||||
- memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
|
|
||||||
+ if (pos_unsigned < string->len)
|
|
||||||
+ memmove (string->str + pos_unsigned + charlen, string->str + pos_unsigned, string->len - pos_unsigned);
|
|
||||||
|
|
||||||
- dest = string->str + pos;
|
|
||||||
+ dest = string->str + pos_unsigned;
|
|
||||||
/* Code copied from g_unichar_to_utf() */
|
|
||||||
for (i = charlen - 1; i > 0; --i)
|
|
||||||
{
|
|
||||||
@@ -931,6 +938,7 @@ g_string_overwrite_len (GString *string,
|
|
||||||
const gchar *val,
|
|
||||||
gssize len)
|
|
||||||
{
|
|
||||||
+ gssize len_unsigned;
|
|
||||||
gsize end;
|
|
||||||
|
|
||||||
g_return_val_if_fail (string != NULL, NULL);
|
|
||||||
@@ -942,14 +950,16 @@ g_string_overwrite_len (GString *string,
|
|
||||||
g_return_val_if_fail (pos <= string->len, string);
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
- len = strlen (val);
|
|
||||||
+ len_unsigned = strlen (val);
|
|
||||||
+ else
|
|
||||||
+ len_unsigned = len;
|
|
||||||
|
|
||||||
- end = pos + len;
|
|
||||||
+ end = pos + len_unsigned;
|
|
||||||
|
|
||||||
if (end > string->len)
|
|
||||||
g_string_maybe_expand (string, end - string->len);
|
|
||||||
|
|
||||||
- memcpy (string->str + pos, val, len);
|
|
||||||
+ memcpy (string->str + pos, val, len_unsigned);
|
|
||||||
|
|
||||||
if (end > string->len)
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
|
|
||||||
From 789c240db9738cae37ee77f7e135e5dbc39ab3ca Mon Sep 17 00:00:00 2001
|
|
||||||
From: Peter Bloomfield <peterbloomfield@bellsouth.net>
|
|
||||||
Date: Fri, 11 Apr 2025 05:52:33 +0000
|
|
||||||
Subject: [PATCH 3/3] gstring: Make len_unsigned unsigned
|
|
||||||
|
|
||||||
---
|
|
||||||
glib/gstring.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/glib/gstring.c b/glib/gstring.c
|
|
||||||
index 84a98da25..7379517f5 100644
|
|
||||||
--- a/glib/gstring.c
|
|
||||||
+++ b/glib/gstring.c
|
|
||||||
@@ -938,7 +938,7 @@ g_string_overwrite_len (GString *string,
|
|
||||||
const gchar *val,
|
|
||||||
gssize len)
|
|
||||||
{
|
|
||||||
- gssize len_unsigned;
|
|
||||||
+ gsize len_unsigned;
|
|
||||||
gsize end;
|
|
||||||
|
|
||||||
g_return_val_if_fail (string != NULL, NULL);
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
@ -1,126 +0,0 @@
|
|||||||
From a07f759373d888c837a780cb93f14542b029e19c Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Rebecca N. Palmer" <rebecca_palmer@zoho.com>
|
|
||||||
Date: Fri, 11 Oct 2024 09:38:52 +0100
|
|
||||||
Subject: [PATCH 1/2] gdatetime test: Do not assume PST8PDT was always exactly
|
|
||||||
-8/-7
|
|
||||||
|
|
||||||
In newer tzdata, it is an alias for America/Los_Angeles, which has a
|
|
||||||
slightly different meaning: DST did not exist there before 1883. As a
|
|
||||||
result, we can no longer hard-code the knowledge that interval 0 is
|
|
||||||
standard time and interval 1 is summer time, and instead we need to look
|
|
||||||
up the correct intervals from known timestamps.
|
|
||||||
|
|
||||||
Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/3502
|
|
||||||
Bug-Debian: https://bugs.debian.org/1084190
|
|
||||||
[smcv: expand commit message, fix whitespace]
|
|
||||||
Signed-off-by: Simon McVittie <smcv@debian.org>
|
|
||||||
---
|
|
||||||
glib/tests/gdatetime.c | 23 +++++++++++++++++------
|
|
||||||
1 file changed, 17 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c
|
|
||||||
index 5a2190d5f..80098bab3 100644
|
|
||||||
--- a/glib/tests/gdatetime.c
|
|
||||||
+++ b/glib/tests/gdatetime.c
|
|
||||||
@@ -2096,6 +2096,7 @@ test_posix_parse (void)
|
|
||||||
{
|
|
||||||
GTimeZone *tz;
|
|
||||||
GDateTime *gdt1, *gdt2;
|
|
||||||
+ gint i1, i2;
|
|
||||||
|
|
||||||
tz = g_time_zone_new ("PST");
|
|
||||||
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "UTC");
|
|
||||||
@@ -2111,14 +2112,24 @@ test_posix_parse (void)
|
|
||||||
|
|
||||||
/* This fails rules_from_identifier on Unix (though not on Windows)
|
|
||||||
* but passes anyway because PST8PDT is a zone name.
|
|
||||||
+ *
|
|
||||||
+ * Intervals i1 and i2 (rather than 0 and 1) are needed because in
|
|
||||||
+ * recent tzdata, PST8PDT may be an alias for America/Los_Angeles,
|
|
||||||
+ * and hence be aware that DST has not always existed.
|
|
||||||
+ * https://bugs.debian.org/1084190
|
|
||||||
*/
|
|
||||||
tz = g_time_zone_new ("PST8PDT");
|
|
||||||
- g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 0), ==, "PST");
|
|
||||||
- g_assert_cmpint (g_time_zone_get_offset (tz, 0), ==, - 8 * 3600);
|
|
||||||
- g_assert (!g_time_zone_is_dst (tz, 0));
|
|
||||||
- g_assert_cmpstr (g_time_zone_get_abbreviation (tz, 1), ==, "PDT");
|
|
||||||
- g_assert_cmpint (g_time_zone_get_offset (tz, 1), ==,- 7 * 3600);
|
|
||||||
- g_assert (g_time_zone_is_dst (tz, 1));
|
|
||||||
+ g_assert_nonnull (tz);
|
|
||||||
+ /* a date in winter = non-DST */
|
|
||||||
+ i1 = g_time_zone_find_interval (tz, G_TIME_TYPE_STANDARD, 0);
|
|
||||||
+ /* approximately 6 months in seconds, i.e. a date in summer = DST */
|
|
||||||
+ i2 = g_time_zone_find_interval (tz, G_TIME_TYPE_DAYLIGHT, 15000000);
|
|
||||||
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, i1), ==, "PST");
|
|
||||||
+ g_assert_cmpint (g_time_zone_get_offset (tz, i1), ==, - 8 * 3600);
|
|
||||||
+ g_assert (!g_time_zone_is_dst (tz, i1));
|
|
||||||
+ g_assert_cmpstr (g_time_zone_get_abbreviation (tz, i2), ==, "PDT");
|
|
||||||
+ g_assert_cmpint (g_time_zone_get_offset (tz, i2), ==,- 7 * 3600);
|
|
||||||
+ g_assert (g_time_zone_is_dst (tz, i2));
|
|
||||||
g_time_zone_unref (tz);
|
|
||||||
|
|
||||||
tz = g_time_zone_new ("PST8PDT6:32:15");
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
|
|
||||||
From d1e564d6d4f478c9e0b163763ed2b199dfafd500 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Simon McVittie <smcv@debian.org>
|
|
||||||
Date: Fri, 18 Oct 2024 11:03:19 +0100
|
|
||||||
Subject: [PATCH 2/2] gdatetime test: Try to make PST8PDT test more obviously
|
|
||||||
correct
|
|
||||||
|
|
||||||
Instead of using timestamp 0 as a magic number (in this case interpreted
|
|
||||||
as 1970-01-01T00:00:00-08:00), calculate a timestamp from a recent
|
|
||||||
year/month/day in winter, in this case 2024-01-01T00:00:00-08:00.
|
|
||||||
|
|
||||||
Similarly, instead of using a timestamp 15 million seconds later
|
|
||||||
(1970-06-23T15:40:00-07:00), calculate a timestamp from a recent
|
|
||||||
year/month/day in summer, in this case 2024-07-01T00:00:00-07:00.
|
|
||||||
|
|
||||||
Signed-off-by: Simon McVittie <smcv@debian.org>
|
|
||||||
---
|
|
||||||
glib/tests/gdatetime.c | 15 +++++++--------
|
|
||||||
1 file changed, 7 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c
|
|
||||||
index 80098bab3..d0755e722 100644
|
|
||||||
--- a/glib/tests/gdatetime.c
|
|
||||||
+++ b/glib/tests/gdatetime.c
|
|
||||||
@@ -2112,18 +2112,15 @@ test_posix_parse (void)
|
|
||||||
|
|
||||||
/* This fails rules_from_identifier on Unix (though not on Windows)
|
|
||||||
* but passes anyway because PST8PDT is a zone name.
|
|
||||||
- *
|
|
||||||
- * Intervals i1 and i2 (rather than 0 and 1) are needed because in
|
|
||||||
- * recent tzdata, PST8PDT may be an alias for America/Los_Angeles,
|
|
||||||
- * and hence be aware that DST has not always existed.
|
|
||||||
- * https://bugs.debian.org/1084190
|
|
||||||
*/
|
|
||||||
tz = g_time_zone_new ("PST8PDT");
|
|
||||||
g_assert_nonnull (tz);
|
|
||||||
/* a date in winter = non-DST */
|
|
||||||
- i1 = g_time_zone_find_interval (tz, G_TIME_TYPE_STANDARD, 0);
|
|
||||||
- /* approximately 6 months in seconds, i.e. a date in summer = DST */
|
|
||||||
- i2 = g_time_zone_find_interval (tz, G_TIME_TYPE_DAYLIGHT, 15000000);
|
|
||||||
+ gdt1 = g_date_time_new (tz, 2024, 1, 1, 0, 0, 0);
|
|
||||||
+ i1 = g_time_zone_find_interval (tz, G_TIME_TYPE_STANDARD, g_date_time_to_unix (gdt1));
|
|
||||||
+ /* a date in summer = DST */
|
|
||||||
+ gdt2 = g_date_time_new (tz, 2024, 7, 1, 0, 0, 0);
|
|
||||||
+ i2 = g_time_zone_find_interval (tz, G_TIME_TYPE_DAYLIGHT, g_date_time_to_unix (gdt2));
|
|
||||||
g_assert_cmpstr (g_time_zone_get_abbreviation (tz, i1), ==, "PST");
|
|
||||||
g_assert_cmpint (g_time_zone_get_offset (tz, i1), ==, - 8 * 3600);
|
|
||||||
g_assert (!g_time_zone_is_dst (tz, i1));
|
|
||||||
@@ -2131,6 +2128,8 @@ test_posix_parse (void)
|
|
||||||
g_assert_cmpint (g_time_zone_get_offset (tz, i2), ==,- 7 * 3600);
|
|
||||||
g_assert (g_time_zone_is_dst (tz, i2));
|
|
||||||
g_time_zone_unref (tz);
|
|
||||||
+ g_date_time_unref (gdt1);
|
|
||||||
+ g_date_time_unref (gdt2);
|
|
||||||
|
|
||||||
tz = g_time_zone_new ("PST8PDT6:32:15");
|
|
||||||
#ifdef G_OS_WIN32
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
@ -1,401 +0,0 @@
|
|||||||
From b43d2e06834a9779801f9a68904ae73a26578f01 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Philip Withnall <withnall@endlessm.com>
|
|
||||||
Date: Sat, 21 Sep 2019 10:45:36 +0200
|
|
||||||
Subject: [PATCH 1/2] gatomic: Add various casts to use of g_atomic_*()s to fix
|
|
||||||
warnings
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
When compiling GLib with `-Wsign-conversion`, we get various warnings
|
|
||||||
about the atomic calls. A lot of these were fixed by
|
|
||||||
3ad375a629c91a27d0165a31f0ed298fd553de0a, but some remain. Fix them by
|
|
||||||
adding appropriate casts at the call sites.
|
|
||||||
|
|
||||||
Note that `g_atomic_int_{and,or,xor}()` actually all operate on `guint`s
|
|
||||||
rather than `gint`s (which is what the rest of the `g_atomic_int_*()`
|
|
||||||
functions operate on). I can’t find any written reasoning for this, but
|
|
||||||
assume that it’s because signedness is irrelevant when you’re using an
|
|
||||||
integer as a bit field. It’s unfortunate that they’re named a
|
|
||||||
`g_atomic_int_*()` rather than `g_atomic_uint_*()` functions.
|
|
||||||
|
|
||||||
Tested by compiling GLib as:
|
|
||||||
```
|
|
||||||
CFLAGS=-Wsign-conversion jhbuild make -ac |& grep atomic
|
|
||||||
```
|
|
||||||
|
|
||||||
I’m not going to add `-Wsign-conversion` to the set of default warnings
|
|
||||||
for building GLib, because it mostly produces false positives throughout
|
|
||||||
the rest of GLib.
|
|
||||||
|
|
||||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
|
||||||
|
|
||||||
Fixes: #1565
|
|
||||||
---
|
|
||||||
gio/gdbusconnection.c | 8 ++++----
|
|
||||||
gio/gdbusnamewatching.c | 4 ++--
|
|
||||||
gio/tests/gdbus-threading.c | 2 +-
|
|
||||||
glib/gbitlock.c | 2 +-
|
|
||||||
glib/gquark.c | 2 +-
|
|
||||||
glib/gthread-posix.c | 2 +-
|
|
||||||
glib/gthreadpool.c | 10 +++++-----
|
|
||||||
glib/tests/atomic.c | 20 ++++++++++----------
|
|
||||||
8 files changed, 25 insertions(+), 25 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
|
||||||
index 117c8df35..1c1f0cf3d 100644
|
|
||||||
--- a/gio/gdbusconnection.c
|
|
||||||
+++ b/gio/gdbusconnection.c
|
|
||||||
@@ -3127,7 +3127,7 @@ g_dbus_connection_add_filter (GDBusConnection *connection,
|
|
||||||
|
|
||||||
CONNECTION_LOCK (connection);
|
|
||||||
data = g_new0 (FilterData, 1);
|
|
||||||
- data->id = g_atomic_int_add (&_global_filter_id, 1); /* TODO: overflow etc. */
|
|
||||||
+ data->id = (guint) g_atomic_int_add (&_global_filter_id, 1); /* TODO: overflow etc. */
|
|
||||||
data->ref_count = 1;
|
|
||||||
data->filter_function = filter_function;
|
|
||||||
data->user_data = user_data;
|
|
||||||
@@ -3482,7 +3482,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
|
||||||
subscriber.callback = callback;
|
|
||||||
subscriber.user_data = user_data;
|
|
||||||
subscriber.user_data_free_func = user_data_free_func;
|
|
||||||
- subscriber.id = g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
|
|
||||||
+ subscriber.id = (guint) g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
|
|
||||||
subscriber.context = g_main_context_ref_thread_default ();
|
|
||||||
|
|
||||||
/* see if we've already have this rule */
|
|
||||||
@@ -5172,7 +5172,7 @@ g_dbus_connection_register_object (GDBusConnection *connection,
|
|
||||||
}
|
|
||||||
|
|
||||||
ei = g_new0 (ExportedInterface, 1);
|
|
||||||
- ei->id = g_atomic_int_add (&_global_registration_id, 1); /* TODO: overflow etc. */
|
|
||||||
+ ei->id = (guint) g_atomic_int_add (&_global_registration_id, 1); /* TODO: overflow etc. */
|
|
||||||
ei->eo = eo;
|
|
||||||
ei->user_data = user_data;
|
|
||||||
ei->user_data_free_func = user_data_free_func;
|
|
||||||
@@ -6832,7 +6832,7 @@ g_dbus_connection_register_subtree (GDBusConnection *connection,
|
|
||||||
|
|
||||||
es->vtable = _g_dbus_subtree_vtable_copy (vtable);
|
|
||||||
es->flags = flags;
|
|
||||||
- es->id = g_atomic_int_add (&_global_subtree_registration_id, 1); /* TODO: overflow etc. */
|
|
||||||
+ es->id = (guint) g_atomic_int_add (&_global_subtree_registration_id, 1); /* TODO: overflow etc. */
|
|
||||||
es->user_data = user_data;
|
|
||||||
es->user_data_free_func = user_data_free_func;
|
|
||||||
es->context = g_main_context_ref_thread_default ();
|
|
||||||
diff --git a/gio/gdbusnamewatching.c b/gio/gdbusnamewatching.c
|
|
||||||
index dad8e75ec..01ee6e762 100644
|
|
||||||
--- a/gio/gdbusnamewatching.c
|
|
||||||
+++ b/gio/gdbusnamewatching.c
|
|
||||||
@@ -603,7 +603,7 @@ g_bus_watch_name (GBusType bus_type,
|
|
||||||
|
|
||||||
client = g_new0 (Client, 1);
|
|
||||||
client->ref_count = 1;
|
|
||||||
- client->id = g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
|
|
||||||
+ client->id = (guint) g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
|
|
||||||
client->name = g_strdup (name);
|
|
||||||
client->flags = flags;
|
|
||||||
client->name_appeared_handler = name_appeared_handler;
|
|
||||||
@@ -665,7 +665,7 @@ guint g_bus_watch_name_on_connection (GDBusConnection *connection,
|
|
||||||
|
|
||||||
client = g_new0 (Client, 1);
|
|
||||||
client->ref_count = 1;
|
|
||||||
- client->id = g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
|
|
||||||
+ client->id = (guint) g_atomic_int_add (&next_global_id, 1); /* TODO: uh oh, handle overflow */
|
|
||||||
client->name = g_strdup (name);
|
|
||||||
client->flags = flags;
|
|
||||||
client->name_appeared_handler = name_appeared_handler;
|
|
||||||
diff --git a/gio/tests/gdbus-threading.c b/gio/tests/gdbus-threading.c
|
|
||||||
index 3e4dc92e5..13ff15bab 100644
|
|
||||||
--- a/gio/tests/gdbus-threading.c
|
|
||||||
+++ b/gio/tests/gdbus-threading.c
|
|
||||||
@@ -514,7 +514,7 @@ test_threaded_singleton (void)
|
|
||||||
/* We want to be the last ref, so let it finish setting up */
|
|
||||||
for (j = 0; j < 100; j++)
|
|
||||||
{
|
|
||||||
- guint r = g_atomic_int_get (&G_OBJECT (c)->ref_count);
|
|
||||||
+ guint r = (guint) g_atomic_int_get (&G_OBJECT (c)->ref_count);
|
|
||||||
|
|
||||||
if (r == 1)
|
|
||||||
break;
|
|
||||||
diff --git a/glib/gbitlock.c b/glib/gbitlock.c
|
|
||||||
index 46e5f7d06..23024d08c 100644
|
|
||||||
--- a/glib/gbitlock.c
|
|
||||||
+++ b/glib/gbitlock.c
|
|
||||||
@@ -224,7 +224,7 @@ g_bit_lock (volatile gint *address,
|
|
||||||
guint mask = 1u << lock_bit;
|
|
||||||
guint v;
|
|
||||||
|
|
||||||
- v = g_atomic_int_get (address);
|
|
||||||
+ v = (guint) g_atomic_int_get (address);
|
|
||||||
if (v & mask)
|
|
||||||
{
|
|
||||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
|
||||||
diff --git a/glib/gquark.c b/glib/gquark.c
|
|
||||||
index c4d12b870..df12ff69a 100644
|
|
||||||
--- a/glib/gquark.c
|
|
||||||
+++ b/glib/gquark.c
|
|
||||||
@@ -262,7 +262,7 @@ g_quark_to_string (GQuark quark)
|
|
||||||
gchar **strings;
|
|
||||||
gint seq_id;
|
|
||||||
|
|
||||||
- seq_id = g_atomic_int_get (&quark_seq_id);
|
|
||||||
+ seq_id = (guint) g_atomic_int_get (&quark_seq_id);
|
|
||||||
strings = g_atomic_pointer_get (&quarks);
|
|
||||||
|
|
||||||
if (quark < seq_id)
|
|
||||||
diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c
|
|
||||||
index 5fff51477..aca9208cc 100644
|
|
||||||
--- a/glib/gthread-posix.c
|
|
||||||
+++ b/glib/gthread-posix.c
|
|
||||||
@@ -1396,7 +1396,7 @@ void
|
|
||||||
g_cond_wait (GCond *cond,
|
|
||||||
GMutex *mutex)
|
|
||||||
{
|
|
||||||
- guint sampled = g_atomic_int_get (&cond->i[0]);
|
|
||||||
+ guint sampled = (guint) g_atomic_int_get (&cond->i[0]);
|
|
||||||
|
|
||||||
g_mutex_unlock (mutex);
|
|
||||||
syscall (__NR_futex, &cond->i[0], (gsize) FUTEX_WAIT_PRIVATE, (gsize) sampled, NULL);
|
|
||||||
diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c
|
|
||||||
index dd7289370..7d75245b0 100644
|
|
||||||
--- a/glib/gthreadpool.c
|
|
||||||
+++ b/glib/gthreadpool.c
|
|
||||||
@@ -145,7 +145,7 @@ g_thread_pool_wait_for_new_pool (void)
|
|
||||||
gint last_wakeup_thread_serial;
|
|
||||||
gboolean have_relayed_thread_marker = FALSE;
|
|
||||||
|
|
||||||
- local_max_unused_threads = g_atomic_int_get (&max_unused_threads);
|
|
||||||
+ local_max_unused_threads = (guint) g_atomic_int_get (&max_unused_threads);
|
|
||||||
local_max_idle_time = g_atomic_int_get (&max_idle_time);
|
|
||||||
last_wakeup_thread_serial = g_atomic_int_get (&wakeup_thread_serial);
|
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ g_thread_pool_wait_for_new_pool (void)
|
|
||||||
DEBUG_MSG (("thread %p updating to new limits.",
|
|
||||||
g_thread_self ()));
|
|
||||||
|
|
||||||
- local_max_unused_threads = g_atomic_int_get (&max_unused_threads);
|
|
||||||
+ local_max_unused_threads = (guint) g_atomic_int_get (&max_unused_threads);
|
|
||||||
local_max_idle_time = g_atomic_int_get (&max_idle_time);
|
|
||||||
last_wakeup_thread_serial = local_wakeup_thread_serial;
|
|
||||||
|
|
||||||
@@ -893,7 +893,7 @@ g_thread_pool_get_max_unused_threads (void)
|
|
||||||
guint
|
|
||||||
g_thread_pool_get_num_unused_threads (void)
|
|
||||||
{
|
|
||||||
- return g_atomic_int_get (&unused_threads);
|
|
||||||
+ return (guint) g_atomic_int_get (&unused_threads);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -1016,7 +1016,7 @@ g_thread_pool_set_max_idle_time (guint interval)
|
|
||||||
|
|
||||||
g_atomic_int_set (&max_idle_time, interval);
|
|
||||||
|
|
||||||
- i = g_atomic_int_get (&unused_threads);
|
|
||||||
+ i = (guint) g_atomic_int_get (&unused_threads);
|
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
g_atomic_int_inc (&wakeup_thread_serial);
|
|
||||||
@@ -1052,5 +1052,5 @@ g_thread_pool_set_max_idle_time (guint interval)
|
|
||||||
guint
|
|
||||||
g_thread_pool_get_max_idle_time (void)
|
|
||||||
{
|
|
||||||
- return g_atomic_int_get (&max_idle_time);
|
|
||||||
+ return (guint) g_atomic_int_get (&max_idle_time);
|
|
||||||
}
|
|
||||||
diff --git a/glib/tests/atomic.c b/glib/tests/atomic.c
|
|
||||||
index 35fa705a4..856df12d2 100644
|
|
||||||
--- a/glib/tests/atomic.c
|
|
||||||
+++ b/glib/tests/atomic.c
|
|
||||||
@@ -27,7 +27,7 @@ test_types (void)
|
|
||||||
cspp = &csp;
|
|
||||||
|
|
||||||
g_atomic_int_set (&u, 5);
|
|
||||||
- u2 = g_atomic_int_get (&u);
|
|
||||||
+ u2 = (guint) g_atomic_int_get (&u);
|
|
||||||
g_assert_cmpint (u2, ==, 5);
|
|
||||||
res = g_atomic_int_compare_and_exchange (&u, 6, 7);
|
|
||||||
g_assert (!res);
|
|
||||||
@@ -62,13 +62,13 @@ test_types (void)
|
|
||||||
res = g_atomic_int_dec_and_test (&s);
|
|
||||||
g_assert (!res);
|
|
||||||
g_assert_cmpint (s, ==, 6);
|
|
||||||
- s2 = g_atomic_int_and (&s, 5);
|
|
||||||
+ s2 = (gint) g_atomic_int_and (&s, 5);
|
|
||||||
g_assert_cmpint (s2, ==, 6);
|
|
||||||
g_assert_cmpint (s, ==, 4);
|
|
||||||
- s2 = g_atomic_int_or (&s, 8);
|
|
||||||
+ s2 = (gint) g_atomic_int_or (&s, 8);
|
|
||||||
g_assert_cmpint (s2, ==, 4);
|
|
||||||
g_assert_cmpint (s, ==, 12);
|
|
||||||
- s2 = g_atomic_int_xor (&s, 4);
|
|
||||||
+ s2 = (gint) g_atomic_int_xor (&s, 4);
|
|
||||||
g_assert_cmpint (s2, ==, 12);
|
|
||||||
g_assert_cmpint (s, ==, 8);
|
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ test_types (void)
|
|
||||||
res = g_atomic_pointer_compare_and_exchange (&gs, 0, 0);
|
|
||||||
g_assert (res);
|
|
||||||
g_assert (gs == 0);
|
|
||||||
- gs2 = g_atomic_pointer_add (&gs, 5);
|
|
||||||
+ gs2 = (gsize) g_atomic_pointer_add (&gs, 5);
|
|
||||||
g_assert (gs2 == 0);
|
|
||||||
g_assert (gs == 5);
|
|
||||||
gs2 = g_atomic_pointer_and (&gs, 6);
|
|
||||||
@@ -127,7 +127,7 @@ test_types (void)
|
|
||||||
#undef g_atomic_pointer_xor
|
|
||||||
|
|
||||||
g_atomic_int_set ((gint*)&u, 5);
|
|
||||||
- u2 = g_atomic_int_get ((gint*)&u);
|
|
||||||
+ u2 = (guint) g_atomic_int_get ((gint*)&u);
|
|
||||||
g_assert_cmpint (u2, ==, 5);
|
|
||||||
res = g_atomic_int_compare_and_exchange ((gint*)&u, 6, 7);
|
|
||||||
g_assert (!res);
|
|
||||||
@@ -161,13 +161,13 @@ test_types (void)
|
|
||||||
res = g_atomic_int_dec_and_test (&s);
|
|
||||||
g_assert (!res);
|
|
||||||
g_assert_cmpint (s, ==, 6);
|
|
||||||
- s2 = g_atomic_int_and ((guint*)&s, 5);
|
|
||||||
+ s2 = (gint) g_atomic_int_and ((guint*)&s, 5);
|
|
||||||
g_assert_cmpint (s2, ==, 6);
|
|
||||||
g_assert_cmpint (s, ==, 4);
|
|
||||||
- s2 = g_atomic_int_or ((guint*)&s, 8);
|
|
||||||
+ s2 = (gint) g_atomic_int_or ((guint*)&s, 8);
|
|
||||||
g_assert_cmpint (s2, ==, 4);
|
|
||||||
g_assert_cmpint (s, ==, 12);
|
|
||||||
- s2 = g_atomic_int_xor ((guint*)&s, 4);
|
|
||||||
+ s2 = (gint) g_atomic_int_xor ((guint*)&s, 4);
|
|
||||||
g_assert_cmpint (s2, ==, 12);
|
|
||||||
g_assert_cmpint (s, ==, 8);
|
|
||||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
|
||||||
@@ -196,7 +196,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
|
||||||
res = g_atomic_pointer_compare_and_exchange (&gs, 0, 0);
|
|
||||||
g_assert (res);
|
|
||||||
g_assert (gs == 0);
|
|
||||||
- gs2 = g_atomic_pointer_add (&gs, 5);
|
|
||||||
+ gs2 = (gsize) g_atomic_pointer_add (&gs, 5);
|
|
||||||
g_assert (gs2 == 0);
|
|
||||||
g_assert (gs == 5);
|
|
||||||
gs2 = g_atomic_pointer_and (&gs, 6);
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
|
|
||||||
From 5d6ced6a7fc6dbbc891992a7d16cd465f2ff1290 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Philip Withnall <pwithnall@endlessos.org>
|
|
||||||
Date: Wed, 22 Feb 2023 12:19:16 +0000
|
|
||||||
Subject: [PATCH 2/2] gdbusconnection: Rearrange refcount handling of
|
|
||||||
map_method_serial_to_task
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
It already implicitly held a strong ref on its `GTask` values, but
|
|
||||||
didn’t have a free function set so that they would be automatically
|
|
||||||
unreffed on removal from the map.
|
|
||||||
|
|
||||||
This meant that the functions handling removals from the map,
|
|
||||||
`on_worker_closed()` (via `cancel_method_on_close()`) and
|
|
||||||
`send_message_with_reply_cleanup()` had to call unref once more than
|
|
||||||
they would otherwise.
|
|
||||||
|
|
||||||
In `send_message_with_reply_cleanup()`, this behaviour depended on
|
|
||||||
whether it was called with `remove == TRUE`. If not, it was `(transfer
|
|
||||||
none)` not `(transfer full)`. This led to bugs in its callers.
|
|
||||||
|
|
||||||
For example, this led to a direct leak in `cancel_method_on_close()`, as
|
|
||||||
it needed to remove tasks from `map_method_serial_to_task`, but called
|
|
||||||
`send_message_with_reply_cleanup(remove = FALSE)` and erroneously didn’t
|
|
||||||
call unref an additional time.
|
|
||||||
|
|
||||||
Try and simplify it all by setting a `GDestroyNotify` on
|
|
||||||
`map_method_serial_to_task`’s values, and making the refcount handling
|
|
||||||
of `send_message_with_reply_cleanup()` not be conditional on its
|
|
||||||
arguments.
|
|
||||||
|
|
||||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
|
||||||
|
|
||||||
Helps: #1264
|
|
||||||
---
|
|
||||||
gio/gdbusconnection.c | 18 ++++++++++--------
|
|
||||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
|
||||||
index 1c1f0cf3d..63f37ca4b 100644
|
|
||||||
--- a/gio/gdbusconnection.c
|
|
||||||
+++ b/gio/gdbusconnection.c
|
|
||||||
@@ -433,7 +433,7 @@ struct _GDBusConnection
|
|
||||||
GDBusConnectionFlags flags;
|
|
||||||
|
|
||||||
/* Map used for managing method replies, protected by @lock */
|
|
||||||
- GHashTable *map_method_serial_to_task; /* guint32 -> GTask* */
|
|
||||||
+ GHashTable *map_method_serial_to_task; /* guint32 -> owned GTask* */
|
|
||||||
|
|
||||||
/* Maps used for managing signal subscription, protected by @lock */
|
|
||||||
GHashTable *map_rule_to_signal_data; /* match rule (gchar*) -> SignalData */
|
|
||||||
@@ -1067,7 +1067,7 @@ g_dbus_connection_init (GDBusConnection *connection)
|
|
||||||
g_mutex_init (&connection->lock);
|
|
||||||
g_mutex_init (&connection->init_lock);
|
|
||||||
|
|
||||||
- connection->map_method_serial_to_task = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
||||||
+ connection->map_method_serial_to_task = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
|
|
||||||
|
|
||||||
connection->map_rule_to_signal_data = g_hash_table_new (g_str_hash,
|
|
||||||
g_str_equal);
|
|
||||||
@@ -1759,7 +1759,7 @@ send_message_data_free (SendMessageData *data)
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
-/* can be called from any thread with lock held; @task is (transfer full) */
|
|
||||||
+/* can be called from any thread with lock held; @task is (transfer none) */
|
|
||||||
static void
|
|
||||||
send_message_with_reply_cleanup (GTask *task, gboolean remove)
|
|
||||||
{
|
|
||||||
@@ -1789,13 +1789,11 @@ send_message_with_reply_cleanup (GTask *task, gboolean remove)
|
|
||||||
GUINT_TO_POINTER (data->serial));
|
|
||||||
g_warn_if_fail (removed);
|
|
||||||
}
|
|
||||||
-
|
|
||||||
- g_object_unref (task);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
-/* Called from GDBus worker thread with lock held; @task is (transfer full). */
|
|
||||||
+/* Called from GDBus worker thread with lock held; @task is (transfer none). */
|
|
||||||
static void
|
|
||||||
send_message_data_deliver_reply_unlocked (GTask *task,
|
|
||||||
GDBusMessage *reply)
|
|
||||||
@@ -1813,7 +1811,7 @@ send_message_data_deliver_reply_unlocked (GTask *task,
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* Called from a user thread, lock is not held */
|
|
||||||
+/* Called from a user thread, lock is not held; @task is (transfer none) */
|
|
||||||
static void
|
|
||||||
send_message_data_deliver_error (GTask *task,
|
|
||||||
GQuark domain,
|
|
||||||
@@ -1830,7 +1828,10 @@ send_message_data_deliver_error (GTask *task,
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Hold a ref on @task as send_message_with_reply_cleanup() will remove it
|
|
||||||
+ * from the task map and could end up dropping the last reference */
|
|
||||||
g_object_ref (task);
|
|
||||||
+
|
|
||||||
send_message_with_reply_cleanup (task, TRUE);
|
|
||||||
CONNECTION_UNLOCK (connection);
|
|
||||||
|
|
||||||
@@ -2363,7 +2364,8 @@ on_worker_message_about_to_be_sent (GDBusWorker *worker,
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* called with connection lock held, in GDBusWorker thread */
|
|
||||||
+/* called with connection lock held, in GDBusWorker thread
|
|
||||||
+ * @key, @value and @user_data are (transfer none) */
|
|
||||||
static gboolean
|
|
||||||
cancel_method_on_close (gpointer key, gpointer value, gpointer user_data)
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
@ -1,780 +0,0 @@
|
|||||||
From c53784092c2d69c4a1d916bb22235ffb8f0b5bad Mon Sep 17 00:00:00 2001
|
|
||||||
From: Philip Withnall <withnall@endlessm.com>
|
|
||||||
Date: Fri, 17 Jan 2020 16:11:06 +0000
|
|
||||||
Subject: [PATCH 1/5] gdbusconnection: Allocate SignalSubscriber structs
|
|
||||||
individually
|
|
||||||
|
|
||||||
The `SignalSubscriber` structs contain the callback and `user_data` of each
|
|
||||||
subscriber to a signal, along with the `guint id` token held by that
|
|
||||||
subscriber to identify their subscription. There are one or more
|
|
||||||
`SignalSubscriber` structs for a given signal match rule, which is
|
|
||||||
represented as a `SignalData` struct.
|
|
||||||
|
|
||||||
Previously, the `SignalSubscriber` structs were stored in a `GArray` in
|
|
||||||
the `SignalData` struct, to reduce the number of allocations needed
|
|
||||||
when subscribing to a signal.
|
|
||||||
|
|
||||||
However, this means that a `SignalSubscriber` struct cannot have a
|
|
||||||
lifetime which exceeds the `SignalData` which contains it. In order to
|
|
||||||
fix the race in #978, one thread needs to be able to unsubscribe from a
|
|
||||||
signal (destroying the `SignalData` struct) while zero or more other
|
|
||||||
threads are in the process of calling the callbacks from a previous
|
|
||||||
emission of that signal (using the callback and `user_data` from zero or
|
|
||||||
more `SignalSubscriber` structs). Multiple threads could be calling
|
|
||||||
callbacks because callbacks are invoked in the `GMainContext` which
|
|
||||||
originally made a subscription, and GDBus supports subscribing to a
|
|
||||||
signal from multiple threads. In that case, the callbacks are dispatched
|
|
||||||
to multiple threads.
|
|
||||||
|
|
||||||
In order to allow the `SignalSubscriber` structs to outlive the
|
|
||||||
`SignalData` which contained their old match rule, store them in a
|
|
||||||
`GPtrArray` in the `SignalData` struct, and refcount them individually.
|
|
||||||
|
|
||||||
This commit in itself should make no functional changes to how GDBus
|
|
||||||
works, but will allow following commits to do so.
|
|
||||||
|
|
||||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
|
||||||
|
|
||||||
Helps: #978
|
|
||||||
---
|
|
||||||
gio/gdbusconnection.c | 105 +++++++++++++++++++++++++-----------------
|
|
||||||
1 file changed, 63 insertions(+), 42 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
|
||||||
index 63f37ca4b..170057682 100644
|
|
||||||
--- a/gio/gdbusconnection.c
|
|
||||||
+++ b/gio/gdbusconnection.c
|
|
||||||
@@ -3229,18 +3229,9 @@ typedef struct
|
|
||||||
gchar *object_path;
|
|
||||||
gchar *arg0;
|
|
||||||
GDBusSignalFlags flags;
|
|
||||||
- GArray *subscribers;
|
|
||||||
+ GPtrArray *subscribers; /* (owned) (element-type SignalSubscriber) */
|
|
||||||
} SignalData;
|
|
||||||
|
|
||||||
-typedef struct
|
|
||||||
-{
|
|
||||||
- GDBusSignalCallback callback;
|
|
||||||
- gpointer user_data;
|
|
||||||
- GDestroyNotify user_data_free_func;
|
|
||||||
- guint id;
|
|
||||||
- GMainContext *context;
|
|
||||||
-} SignalSubscriber;
|
|
||||||
-
|
|
||||||
static void
|
|
||||||
signal_data_free (SignalData *signal_data)
|
|
||||||
{
|
|
||||||
@@ -3251,10 +3242,37 @@ signal_data_free (SignalData *signal_data)
|
|
||||||
g_free (signal_data->member);
|
|
||||||
g_free (signal_data->object_path);
|
|
||||||
g_free (signal_data->arg0);
|
|
||||||
- g_array_free (signal_data->subscribers, TRUE);
|
|
||||||
+ g_ptr_array_unref (signal_data->subscribers);
|
|
||||||
g_free (signal_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
+typedef struct
|
|
||||||
+{
|
|
||||||
+ gatomicrefcount ref_count;
|
|
||||||
+ GDBusSignalCallback callback;
|
|
||||||
+ gpointer user_data;
|
|
||||||
+ GDestroyNotify user_data_free_func;
|
|
||||||
+ guint id;
|
|
||||||
+ GMainContext *context;
|
|
||||||
+} SignalSubscriber;
|
|
||||||
+
|
|
||||||
+static SignalSubscriber *
|
|
||||||
+signal_subscriber_ref (SignalSubscriber *subscriber)
|
|
||||||
+{
|
|
||||||
+ g_atomic_ref_count_inc (&subscriber->ref_count);
|
|
||||||
+ return subscriber;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+signal_subscriber_unref (SignalSubscriber *subscriber)
|
|
||||||
+{
|
|
||||||
+ if (g_atomic_ref_count_dec (&subscriber->ref_count))
|
|
||||||
+ {
|
|
||||||
+ g_main_context_unref (subscriber->context);
|
|
||||||
+ g_free (subscriber);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static gchar *
|
|
||||||
args_to_rule (const gchar *sender,
|
|
||||||
const gchar *interface_name,
|
|
||||||
@@ -3440,7 +3458,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
|
||||||
{
|
|
||||||
gchar *rule;
|
|
||||||
SignalData *signal_data;
|
|
||||||
- SignalSubscriber subscriber;
|
|
||||||
+ SignalSubscriber *subscriber;
|
|
||||||
GPtrArray *signal_data_array;
|
|
||||||
const gchar *sender_unique_name;
|
|
||||||
|
|
||||||
@@ -3481,17 +3499,19 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
|
||||||
else
|
|
||||||
sender_unique_name = "";
|
|
||||||
|
|
||||||
- subscriber.callback = callback;
|
|
||||||
- subscriber.user_data = user_data;
|
|
||||||
- subscriber.user_data_free_func = user_data_free_func;
|
|
||||||
- subscriber.id = (guint) g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
|
|
||||||
- subscriber.context = g_main_context_ref_thread_default ();
|
|
||||||
+ subscriber = g_new0 (SignalSubscriber, 1);
|
|
||||||
+ subscriber->ref_count = 1;
|
|
||||||
+ subscriber->callback = callback;
|
|
||||||
+ subscriber->user_data = user_data;
|
|
||||||
+ subscriber->user_data_free_func = user_data_free_func;
|
|
||||||
+ subscriber->id = (guint) g_atomic_int_add (&_global_subscriber_id, 1); /* TODO: overflow etc. */
|
|
||||||
+ subscriber->context = g_main_context_ref_thread_default ();
|
|
||||||
|
|
||||||
/* see if we've already have this rule */
|
|
||||||
signal_data = g_hash_table_lookup (connection->map_rule_to_signal_data, rule);
|
|
||||||
if (signal_data != NULL)
|
|
||||||
{
|
|
||||||
- g_array_append_val (signal_data->subscribers, subscriber);
|
|
||||||
+ g_ptr_array_add (signal_data->subscribers, subscriber);
|
|
||||||
g_free (rule);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
@@ -3505,8 +3525,8 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
|
||||||
signal_data->object_path = g_strdup (object_path);
|
|
||||||
signal_data->arg0 = g_strdup (arg0);
|
|
||||||
signal_data->flags = flags;
|
|
||||||
- signal_data->subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
|
|
||||||
- g_array_append_val (signal_data->subscribers, subscriber);
|
|
||||||
+ signal_data->subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
|
||||||
+ g_ptr_array_add (signal_data->subscribers, subscriber);
|
|
||||||
|
|
||||||
g_hash_table_insert (connection->map_rule_to_signal_data,
|
|
||||||
signal_data->rule,
|
|
||||||
@@ -3536,12 +3556,12 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
|
||||||
|
|
||||||
out:
|
|
||||||
g_hash_table_insert (connection->map_id_to_signal_data,
|
|
||||||
- GUINT_TO_POINTER (subscriber.id),
|
|
||||||
+ GUINT_TO_POINTER (subscriber->id),
|
|
||||||
signal_data);
|
|
||||||
|
|
||||||
CONNECTION_UNLOCK (connection);
|
|
||||||
|
|
||||||
- return subscriber.id;
|
|
||||||
+ return subscriber->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------------- */
|
|
||||||
@@ -3551,7 +3571,7 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
|
||||||
static void
|
|
||||||
unsubscribe_id_internal (GDBusConnection *connection,
|
|
||||||
guint subscription_id,
|
|
||||||
- GArray *out_removed_subscribers)
|
|
||||||
+ GPtrArray *out_removed_subscribers)
|
|
||||||
{
|
|
||||||
SignalData *signal_data;
|
|
||||||
GPtrArray *signal_data_array;
|
|
||||||
@@ -3567,16 +3587,19 @@ unsubscribe_id_internal (GDBusConnection *connection,
|
|
||||||
|
|
||||||
for (n = 0; n < signal_data->subscribers->len; n++)
|
|
||||||
{
|
|
||||||
- SignalSubscriber *subscriber;
|
|
||||||
+ SignalSubscriber *subscriber = signal_data->subscribers->pdata[n];
|
|
||||||
|
|
||||||
- subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, n));
|
|
||||||
if (subscriber->id != subscription_id)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
+ /* It’s OK to rearrange the array order using the ‘fast’ #GPtrArray
|
|
||||||
+ * removal functions, since we’re going to exit the loop below anyway — we
|
|
||||||
+ * never move on to the next element. Secondly, subscription IDs are
|
|
||||||
+ * guaranteed to be unique. */
|
|
||||||
g_warn_if_fail (g_hash_table_remove (connection->map_id_to_signal_data,
|
|
||||||
GUINT_TO_POINTER (subscription_id)));
|
|
||||||
- g_array_append_val (out_removed_subscribers, *subscriber);
|
|
||||||
- g_array_remove_index (signal_data->subscribers, n);
|
|
||||||
+ g_ptr_array_add (out_removed_subscribers, signal_subscriber_ref (subscriber));
|
|
||||||
+ g_ptr_array_remove_index_fast (signal_data->subscribers, n);
|
|
||||||
|
|
||||||
if (signal_data->subscribers->len == 0)
|
|
||||||
{
|
|
||||||
@@ -3634,13 +3657,13 @@ void
|
|
||||||
g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
|
||||||
guint subscription_id)
|
|
||||||
{
|
|
||||||
- GArray *subscribers;
|
|
||||||
+ GPtrArray *subscribers;
|
|
||||||
guint n;
|
|
||||||
|
|
||||||
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
|
|
||||||
g_return_if_fail (check_initialized (connection));
|
|
||||||
|
|
||||||
- subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
|
|
||||||
+ subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
|
||||||
|
|
||||||
CONNECTION_LOCK (connection);
|
|
||||||
unsubscribe_id_internal (connection,
|
|
||||||
@@ -3654,15 +3677,15 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
|
||||||
/* call GDestroyNotify without lock held */
|
|
||||||
for (n = 0; n < subscribers->len; n++)
|
|
||||||
{
|
|
||||||
- SignalSubscriber *subscriber;
|
|
||||||
- subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
|
|
||||||
+ SignalSubscriber *subscriber = subscribers->pdata[n];
|
|
||||||
call_destroy_notify (subscriber->context,
|
|
||||||
subscriber->user_data_free_func,
|
|
||||||
subscriber->user_data);
|
|
||||||
- g_main_context_unref (subscriber->context);
|
|
||||||
+ subscriber->user_data_free_func = NULL;
|
|
||||||
+ subscriber->user_data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- g_array_free (subscribers, TRUE);
|
|
||||||
+ g_ptr_array_unref (subscribers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------------- */
|
|
||||||
@@ -3852,12 +3875,10 @@ schedule_callbacks (GDBusConnection *connection,
|
|
||||||
|
|
||||||
for (m = 0; m < signal_data->subscribers->len; m++)
|
|
||||||
{
|
|
||||||
- SignalSubscriber *subscriber;
|
|
||||||
+ SignalSubscriber *subscriber = signal_data->subscribers->pdata[m];
|
|
||||||
GSource *idle_source;
|
|
||||||
SignalInstance *signal_instance;
|
|
||||||
|
|
||||||
- subscriber = &(g_array_index (signal_data->subscribers, SignalSubscriber, m));
|
|
||||||
-
|
|
||||||
signal_instance = g_new0 (SignalInstance, 1);
|
|
||||||
signal_instance->subscription_id = subscriber->id;
|
|
||||||
signal_instance->callback = subscriber->callback;
|
|
||||||
@@ -3930,7 +3951,7 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
|
||||||
GHashTableIter iter;
|
|
||||||
gpointer key;
|
|
||||||
GArray *ids;
|
|
||||||
- GArray *subscribers;
|
|
||||||
+ GPtrArray *subscribers;
|
|
||||||
guint n;
|
|
||||||
|
|
||||||
ids = g_array_new (FALSE, FALSE, sizeof (guint));
|
|
||||||
@@ -3941,7 +3962,7 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
|
||||||
g_array_append_val (ids, subscription_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
- subscribers = g_array_new (FALSE, FALSE, sizeof (SignalSubscriber));
|
|
||||||
+ subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
|
||||||
for (n = 0; n < ids->len; n++)
|
|
||||||
{
|
|
||||||
guint subscription_id = g_array_index (ids, guint, n);
|
|
||||||
@@ -3954,15 +3975,15 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
|
||||||
/* call GDestroyNotify without lock held */
|
|
||||||
for (n = 0; n < subscribers->len; n++)
|
|
||||||
{
|
|
||||||
- SignalSubscriber *subscriber;
|
|
||||||
- subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
|
|
||||||
+ SignalSubscriber *subscriber = subscribers->pdata[n];
|
|
||||||
call_destroy_notify (subscriber->context,
|
|
||||||
subscriber->user_data_free_func,
|
|
||||||
subscriber->user_data);
|
|
||||||
- g_main_context_unref (subscriber->context);
|
|
||||||
+ subscriber->user_data_free_func = NULL;
|
|
||||||
+ subscriber->user_data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- g_array_free (subscribers, TRUE);
|
|
||||||
+ g_ptr_array_unref (subscribers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------------- */
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
|
|
||||||
From d21d9fb02496f21864e4175d08b5f55416e832e6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Philip Withnall <withnall@endlessm.com>
|
|
||||||
Date: Fri, 17 Jan 2020 19:52:46 +0000
|
|
||||||
Subject: [PATCH 2/5] gdbusconnection: Tidy up destroy notification for signal
|
|
||||||
subscriptions
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Tie the destruction of the `user_data` to the destruction of the
|
|
||||||
`SignalSubscriber` struct. This is tidier, and ensures that the fields
|
|
||||||
in `SignalSubscriber` are all immutable after being set, so the
|
|
||||||
structure can safely be used across threads without locking.
|
|
||||||
|
|
||||||
It doesn’t matter which thread we call `call_destroy_notify()` in, since
|
|
||||||
it always defers calling `user_data_free_func` to the user-provided
|
|
||||||
`GMainContext`.
|
|
||||||
|
|
||||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
|
||||||
|
|
||||||
Helps: #978
|
|
||||||
---
|
|
||||||
gio/gdbusconnection.c | 32 +++++++++-----------------------
|
|
||||||
1 file changed, 9 insertions(+), 23 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
|
||||||
index 170057682..2dba09fcc 100644
|
|
||||||
--- a/gio/gdbusconnection.c
|
|
||||||
+++ b/gio/gdbusconnection.c
|
|
||||||
@@ -3248,6 +3248,7 @@ signal_data_free (SignalData *signal_data)
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
+ /* All fields are immutable after construction. */
|
|
||||||
gatomicrefcount ref_count;
|
|
||||||
GDBusSignalCallback callback;
|
|
||||||
gpointer user_data;
|
|
||||||
@@ -3268,6 +3269,14 @@ signal_subscriber_unref (SignalSubscriber *subscriber)
|
|
||||||
{
|
|
||||||
if (g_atomic_ref_count_dec (&subscriber->ref_count))
|
|
||||||
{
|
|
||||||
+ /* Destroy the user data. It doesn’t matter which thread
|
|
||||||
+ * signal_subscriber_unref() is called in (or whether it’s called with a
|
|
||||||
+ * lock held), as call_destroy_notify() always defers to the next
|
|
||||||
+ * #GMainContext iteration. */
|
|
||||||
+ call_destroy_notify (subscriber->context,
|
|
||||||
+ subscriber->user_data_free_func,
|
|
||||||
+ subscriber->user_data);
|
|
||||||
+
|
|
||||||
g_main_context_unref (subscriber->context);
|
|
||||||
g_free (subscriber);
|
|
||||||
}
|
|
||||||
@@ -3658,7 +3667,6 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
|
||||||
guint subscription_id)
|
|
||||||
{
|
|
||||||
GPtrArray *subscribers;
|
|
||||||
- guint n;
|
|
||||||
|
|
||||||
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
|
|
||||||
g_return_if_fail (check_initialized (connection));
|
|
||||||
@@ -3674,17 +3682,6 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
|
||||||
/* invariant */
|
|
||||||
g_assert (subscribers->len == 0 || subscribers->len == 1);
|
|
||||||
|
|
||||||
- /* call GDestroyNotify without lock held */
|
|
||||||
- for (n = 0; n < subscribers->len; n++)
|
|
||||||
- {
|
|
||||||
- SignalSubscriber *subscriber = subscribers->pdata[n];
|
|
||||||
- call_destroy_notify (subscriber->context,
|
|
||||||
- subscriber->user_data_free_func,
|
|
||||||
- subscriber->user_data);
|
|
||||||
- subscriber->user_data_free_func = NULL;
|
|
||||||
- subscriber->user_data = NULL;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
g_ptr_array_unref (subscribers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -3972,17 +3969,6 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
|
||||||
}
|
|
||||||
g_array_free (ids, TRUE);
|
|
||||||
|
|
||||||
- /* call GDestroyNotify without lock held */
|
|
||||||
- for (n = 0; n < subscribers->len; n++)
|
|
||||||
- {
|
|
||||||
- SignalSubscriber *subscriber = subscribers->pdata[n];
|
|
||||||
- call_destroy_notify (subscriber->context,
|
|
||||||
- subscriber->user_data_free_func,
|
|
||||||
- subscriber->user_data);
|
|
||||||
- subscriber->user_data_free_func = NULL;
|
|
||||||
- subscriber->user_data = NULL;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
g_ptr_array_unref (subscribers);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
|
|
||||||
From 5b7c9398a67ad274cb8faef8bf45461540a7198e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Philip Withnall <withnall@endlessm.com>
|
|
||||||
Date: Fri, 17 Jan 2020 19:38:55 +0000
|
|
||||||
Subject: [PATCH 3/5] gdbusconnection: Fix race when emitting D-Bus signal
|
|
||||||
callbacks
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Instead of storing a copy of the `callback` and `user_data` from a
|
|
||||||
`SignalSubscriber` in a `SignalInstance` struct (which is the closure
|
|
||||||
for signal callback data as it’s sent from the D-Bus worker thread to
|
|
||||||
the thread which originally subscribed to a signal), store a strong
|
|
||||||
reference to the `SignalSubscriber` struct itself.
|
|
||||||
|
|
||||||
This keeps the `SignalSubscriber` alive until the emission is
|
|
||||||
complete, which ensures that the `user_data` is not freed prematurely.
|
|
||||||
It also slightly reduces the allocation size of `SignalInstance` (not
|
|
||||||
that it matters).
|
|
||||||
|
|
||||||
This is threadsafe because the fields in `SignalSubscriber` are all
|
|
||||||
immutable after construction.
|
|
||||||
|
|
||||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
|
||||||
|
|
||||||
Helps: #978
|
|
||||||
---
|
|
||||||
gio/gdbusconnection.c | 27 ++++++++++++---------------
|
|
||||||
1 file changed, 12 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
|
||||||
index 2dba09fcc..4cae53b29 100644
|
|
||||||
--- a/gio/gdbusconnection.c
|
|
||||||
+++ b/gio/gdbusconnection.c
|
|
||||||
@@ -3689,9 +3689,7 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
- guint subscription_id;
|
|
||||||
- GDBusSignalCallback callback;
|
|
||||||
- gpointer user_data;
|
|
||||||
+ SignalSubscriber *subscriber; /* (owned) */
|
|
||||||
GDBusMessage *message;
|
|
||||||
GDBusConnection *connection;
|
|
||||||
const gchar *sender;
|
|
||||||
@@ -3723,7 +3721,7 @@ emit_signal_instance_in_idle_cb (gpointer data)
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
g_print ("in emit_signal_instance_in_idle_cb (id=%d sender=%s path=%s interface=%s member=%s params=%s)\n",
|
|
||||||
- signal_instance->subscription_id,
|
|
||||||
+ signal_instance->subscriber->id,
|
|
||||||
signal_instance->sender,
|
|
||||||
signal_instance->path,
|
|
||||||
signal_instance->interface,
|
|
||||||
@@ -3735,18 +3733,18 @@ emit_signal_instance_in_idle_cb (gpointer data)
|
|
||||||
CONNECTION_LOCK (signal_instance->connection);
|
|
||||||
has_subscription = FALSE;
|
|
||||||
if (g_hash_table_lookup (signal_instance->connection->map_id_to_signal_data,
|
|
||||||
- GUINT_TO_POINTER (signal_instance->subscription_id)) != NULL)
|
|
||||||
+ GUINT_TO_POINTER (signal_instance->subscriber->id)) != NULL)
|
|
||||||
has_subscription = TRUE;
|
|
||||||
CONNECTION_UNLOCK (signal_instance->connection);
|
|
||||||
|
|
||||||
if (has_subscription)
|
|
||||||
- signal_instance->callback (signal_instance->connection,
|
|
||||||
- signal_instance->sender,
|
|
||||||
- signal_instance->path,
|
|
||||||
- signal_instance->interface,
|
|
||||||
- signal_instance->member,
|
|
||||||
- parameters,
|
|
||||||
- signal_instance->user_data);
|
|
||||||
+ signal_instance->subscriber->callback (signal_instance->connection,
|
|
||||||
+ signal_instance->sender,
|
|
||||||
+ signal_instance->path,
|
|
||||||
+ signal_instance->interface,
|
|
||||||
+ signal_instance->member,
|
|
||||||
+ parameters,
|
|
||||||
+ signal_instance->subscriber->user_data);
|
|
||||||
|
|
||||||
g_variant_unref (parameters);
|
|
||||||
|
|
||||||
@@ -3758,6 +3756,7 @@ signal_instance_free (SignalInstance *signal_instance)
|
|
||||||
{
|
|
||||||
g_object_unref (signal_instance->message);
|
|
||||||
g_object_unref (signal_instance->connection);
|
|
||||||
+ signal_subscriber_unref (signal_instance->subscriber);
|
|
||||||
g_free (signal_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -3877,9 +3876,7 @@ schedule_callbacks (GDBusConnection *connection,
|
|
||||||
SignalInstance *signal_instance;
|
|
||||||
|
|
||||||
signal_instance = g_new0 (SignalInstance, 1);
|
|
||||||
- signal_instance->subscription_id = subscriber->id;
|
|
||||||
- signal_instance->callback = subscriber->callback;
|
|
||||||
- signal_instance->user_data = subscriber->user_data;
|
|
||||||
+ signal_instance->subscriber = signal_subscriber_ref (subscriber);
|
|
||||||
signal_instance->message = g_object_ref (message);
|
|
||||||
signal_instance->connection = g_object_ref (connection);
|
|
||||||
signal_instance->sender = sender;
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
|
|
||||||
From a13bbdc1dc0cd4ec16c3e75d0cc1c07eb791b3bc Mon Sep 17 00:00:00 2001
|
|
||||||
From: Philip Withnall <withnall@endlessm.com>
|
|
||||||
Date: Fri, 17 Jan 2020 19:56:58 +0000
|
|
||||||
Subject: [PATCH 4/5] gdbusconnection: Tidy up unsubscription code
|
|
||||||
|
|
||||||
This just removes a now-redundant intermediate array. This means that
|
|
||||||
the `SignalSubscriber` instances are now potentially freed a little
|
|
||||||
sooner, inside the locked segment, but they are already careful to only
|
|
||||||
call their `user_data_free_func` in the right thread. So that should not
|
|
||||||
deadlock.
|
|
||||||
|
|
||||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
|
||||||
|
|
||||||
Helps: #978
|
|
||||||
---
|
|
||||||
gio/gdbusconnection.c | 33 +++++++++++----------------------
|
|
||||||
1 file changed, 11 insertions(+), 22 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
|
||||||
index 4cae53b29..4d99f8570 100644
|
|
||||||
--- a/gio/gdbusconnection.c
|
|
||||||
+++ b/gio/gdbusconnection.c
|
|
||||||
@@ -3576,15 +3576,16 @@ g_dbus_connection_signal_subscribe (GDBusConnection *connection,
|
|
||||||
/* ---------------------------------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* called in any thread */
|
|
||||||
-/* must hold lock when calling this (except if connection->finalizing is TRUE) */
|
|
||||||
-static void
|
|
||||||
+/* must hold lock when calling this (except if connection->finalizing is TRUE)
|
|
||||||
+ * returns the number of removed subscribers */
|
|
||||||
+static guint
|
|
||||||
unsubscribe_id_internal (GDBusConnection *connection,
|
|
||||||
- guint subscription_id,
|
|
||||||
- GPtrArray *out_removed_subscribers)
|
|
||||||
+ guint subscription_id)
|
|
||||||
{
|
|
||||||
SignalData *signal_data;
|
|
||||||
GPtrArray *signal_data_array;
|
|
||||||
guint n;
|
|
||||||
+ guint n_removed = 0;
|
|
||||||
|
|
||||||
signal_data = g_hash_table_lookup (connection->map_id_to_signal_data,
|
|
||||||
GUINT_TO_POINTER (subscription_id));
|
|
||||||
@@ -3607,7 +3608,7 @@ unsubscribe_id_internal (GDBusConnection *connection,
|
|
||||||
* guaranteed to be unique. */
|
|
||||||
g_warn_if_fail (g_hash_table_remove (connection->map_id_to_signal_data,
|
|
||||||
GUINT_TO_POINTER (subscription_id)));
|
|
||||||
- g_ptr_array_add (out_removed_subscribers, signal_subscriber_ref (subscriber));
|
|
||||||
+ n_removed++;
|
|
||||||
g_ptr_array_remove_index_fast (signal_data->subscribers, n);
|
|
||||||
|
|
||||||
if (signal_data->subscribers->len == 0)
|
|
||||||
@@ -3649,7 +3650,7 @@ unsubscribe_id_internal (GDBusConnection *connection,
|
|
||||||
g_assert_not_reached ();
|
|
||||||
|
|
||||||
out:
|
|
||||||
- ;
|
|
||||||
+ return n_removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -3666,23 +3667,17 @@ void
|
|
||||||
g_dbus_connection_signal_unsubscribe (GDBusConnection *connection,
|
|
||||||
guint subscription_id)
|
|
||||||
{
|
|
||||||
- GPtrArray *subscribers;
|
|
||||||
+ guint n_subscribers_removed G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */;
|
|
||||||
|
|
||||||
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
|
|
||||||
g_return_if_fail (check_initialized (connection));
|
|
||||||
|
|
||||||
- subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
|
||||||
-
|
|
||||||
CONNECTION_LOCK (connection);
|
|
||||||
- unsubscribe_id_internal (connection,
|
|
||||||
- subscription_id,
|
|
||||||
- subscribers);
|
|
||||||
+ n_subscribers_removed = unsubscribe_id_internal (connection, subscription_id);
|
|
||||||
CONNECTION_UNLOCK (connection);
|
|
||||||
|
|
||||||
/* invariant */
|
|
||||||
- g_assert (subscribers->len == 0 || subscribers->len == 1);
|
|
||||||
-
|
|
||||||
- g_ptr_array_unref (subscribers);
|
|
||||||
+ g_assert (n_subscribers_removed == 0 || n_subscribers_removed == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------------- */
|
|
||||||
@@ -3945,7 +3940,6 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
|
||||||
GHashTableIter iter;
|
|
||||||
gpointer key;
|
|
||||||
GArray *ids;
|
|
||||||
- GPtrArray *subscribers;
|
|
||||||
guint n;
|
|
||||||
|
|
||||||
ids = g_array_new (FALSE, FALSE, sizeof (guint));
|
|
||||||
@@ -3956,17 +3950,12 @@ purge_all_signal_subscriptions (GDBusConnection *connection)
|
|
||||||
g_array_append_val (ids, subscription_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
- subscribers = g_ptr_array_new_with_free_func ((GDestroyNotify) signal_subscriber_unref);
|
|
||||||
for (n = 0; n < ids->len; n++)
|
|
||||||
{
|
|
||||||
guint subscription_id = g_array_index (ids, guint, n);
|
|
||||||
- unsubscribe_id_internal (connection,
|
|
||||||
- subscription_id,
|
|
||||||
- subscribers);
|
|
||||||
+ unsubscribe_id_internal (connection, subscription_id);
|
|
||||||
}
|
|
||||||
g_array_free (ids, TRUE);
|
|
||||||
-
|
|
||||||
- g_ptr_array_unref (subscribers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------------- */
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
|
|
||||||
From 0ec439aab1da5df011bed6a1a317439efacb6c25 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Philip Withnall <withnall@endlessm.com>
|
|
||||||
Date: Fri, 17 Jan 2020 20:00:22 +0000
|
|
||||||
Subject: [PATCH 5/5] gdbusnameowning: Fix race between connection shutdown and
|
|
||||||
NameLost
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
As with all D-Bus signal subscriptions, it’s possible for a signal
|
|
||||||
callback to be invoked in one thread (T1) while another thread (T2) is
|
|
||||||
unsubscribing from that signal. In this case, T1 is the main thread, and
|
|
||||||
T2 is the D-Bus connection worker thread which is unsubscribing all
|
|
||||||
signals as it’s in the process of closing.
|
|
||||||
|
|
||||||
Due to this possibility, all `user_data` for signal callbacks needs to
|
|
||||||
be referenced outside the lifecycle of the code which
|
|
||||||
subscribes/unsubscribes the signal. In other words, it’s not safe to
|
|
||||||
subscribe to a signal, store the subscription ID in a struct,
|
|
||||||
unsubscribe from the signal when freeing the struct, and dereference the
|
|
||||||
struct in the signal callback. The data passed to the signal callback
|
|
||||||
has to have its own strong reference.
|
|
||||||
|
|
||||||
Instead, it’s safe to subscribe to a signal and add a strong reference
|
|
||||||
to the struct, store the subscription ID in that struct, and unsubscribe
|
|
||||||
from the signal when the last external reference to your struct is
|
|
||||||
dropped. That unsubscription should break the refcount cycle between the
|
|
||||||
signal connection and the struct, and allow the struct to be completely
|
|
||||||
freed. Only with that approach is it safe to dereference the struct in
|
|
||||||
the signal callback, if there’s any possibility that the signal might be
|
|
||||||
unsubscribed from a separate thread.
|
|
||||||
|
|
||||||
The tests need specific additional main loop cycles to completely emit
|
|
||||||
the NameLost signal callback. Ideally they need refactoring, but this
|
|
||||||
will do (1000 test cycles passed).
|
|
||||||
|
|
||||||
Signed-off-by: Philip Withnall <withnall@endlessm.com>
|
|
||||||
|
|
||||||
Fixes: #978
|
|
||||||
---
|
|
||||||
gio/gdbusnameowning.c | 15 ++++++++++-----
|
|
||||||
gio/tests/gdbus-names.c | 11 ++++++++++-
|
|
||||||
2 files changed, 20 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gdbusnameowning.c b/gio/gdbusnameowning.c
|
|
||||||
index 2c2714db2..00554c16a 100644
|
|
||||||
--- a/gio/gdbusnameowning.c
|
|
||||||
+++ b/gio/gdbusnameowning.c
|
|
||||||
@@ -366,7 +366,12 @@ request_name_cb (GObject *source_object,
|
|
||||||
connection = g_object_ref (client->connection);
|
|
||||||
G_UNLOCK (lock);
|
|
||||||
|
|
||||||
- /* start listening to NameLost and NameAcquired messages */
|
|
||||||
+ /* Start listening to NameLost and NameAcquired messages. We hold
|
|
||||||
+ * references to the Client in the signal closures, since it’s possible
|
|
||||||
+ * for a signal to be in-flight after unsubscribing the signal handler.
|
|
||||||
+ * This creates a reference count cycle, but that’s explicitly broken by
|
|
||||||
+ * disconnecting the signal handlers before calling client_unref() in
|
|
||||||
+ * g_bus_unown_name(). */
|
|
||||||
if (connection != NULL)
|
|
||||||
{
|
|
||||||
client->name_lost_subscription_id =
|
|
||||||
@@ -378,8 +383,8 @@ request_name_cb (GObject *source_object,
|
|
||||||
client->name,
|
|
||||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
||||||
on_name_lost_or_acquired,
|
|
||||||
- client,
|
|
||||||
- NULL);
|
|
||||||
+ client_ref (client),
|
|
||||||
+ (GDestroyNotify) client_unref);
|
|
||||||
client->name_acquired_subscription_id =
|
|
||||||
g_dbus_connection_signal_subscribe (connection,
|
|
||||||
"org.freedesktop.DBus",
|
|
||||||
@@ -389,8 +394,8 @@ request_name_cb (GObject *source_object,
|
|
||||||
client->name,
|
|
||||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
||||||
on_name_lost_or_acquired,
|
|
||||||
- client,
|
|
||||||
- NULL);
|
|
||||||
+ client_ref (client),
|
|
||||||
+ (GDestroyNotify) client_unref);
|
|
||||||
g_object_unref (connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diff --git a/gio/tests/gdbus-names.c b/gio/tests/gdbus-names.c
|
|
||||||
index 648b54774..b42ba2141 100644
|
|
||||||
--- a/gio/tests/gdbus-names.c
|
|
||||||
+++ b/gio/tests/gdbus-names.c
|
|
||||||
@@ -189,6 +189,7 @@ test_bus_own_name (void)
|
|
||||||
* Stop owning the name - this should invoke our free func
|
|
||||||
*/
|
|
||||||
g_bus_unown_name (id);
|
|
||||||
+ g_main_loop_run (loop);
|
|
||||||
g_assert_cmpint (data.num_free_func, ==, 2);
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -330,6 +331,7 @@ test_bus_own_name (void)
|
|
||||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
|
||||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
|
||||||
g_bus_unown_name (id2);
|
|
||||||
+ g_main_loop_run (loop);
|
|
||||||
g_assert_cmpint (data2.num_bus_acquired, ==, 0);
|
|
||||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
|
||||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
|
||||||
@@ -355,6 +357,7 @@ test_bus_own_name (void)
|
|
||||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
|
||||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
|
||||||
g_bus_unown_name (id2);
|
|
||||||
+ g_main_loop_run (loop);
|
|
||||||
g_assert_cmpint (data2.num_bus_acquired, ==, 0);
|
|
||||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
|
||||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
|
||||||
@@ -365,6 +368,7 @@ test_bus_own_name (void)
|
|
||||||
*/
|
|
||||||
data.expect_null_connection = FALSE;
|
|
||||||
g_bus_unown_name (id);
|
|
||||||
+ g_main_loop_run (loop);
|
|
||||||
g_assert_cmpint (data.num_bus_acquired, ==, 1);
|
|
||||||
g_assert_cmpint (data.num_acquired, ==, 1);
|
|
||||||
g_assert_cmpint (data.num_free_func, ==, 4);
|
|
||||||
@@ -418,6 +422,7 @@ test_bus_own_name (void)
|
|
||||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
|
||||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
|
||||||
g_bus_unown_name (id2);
|
|
||||||
+ g_main_loop_run (loop);
|
|
||||||
g_assert_cmpint (data2.num_bus_acquired, ==, 0);
|
|
||||||
g_assert_cmpint (data2.num_acquired, ==, 0);
|
|
||||||
g_assert_cmpint (data2.num_lost, ==, 1);
|
|
||||||
@@ -450,8 +455,9 @@ test_bus_own_name (void)
|
|
||||||
g_assert_cmpint (data2.num_bus_acquired, ==, 0);
|
|
||||||
/* ok, make owner2 release the name - then wait for owner to automagically reacquire it */
|
|
||||||
g_bus_unown_name (id2);
|
|
||||||
- g_assert_cmpint (data2.num_free_func, ==, 1);
|
|
||||||
g_main_loop_run (loop);
|
|
||||||
+ g_main_loop_run (loop);
|
|
||||||
+ g_assert_cmpint (data2.num_free_func, ==, 1);
|
|
||||||
g_assert_cmpint (data.num_acquired, ==, 2);
|
|
||||||
g_assert_cmpint (data.num_lost, ==, 1);
|
|
||||||
|
|
||||||
@@ -466,6 +472,7 @@ test_bus_own_name (void)
|
|
||||||
g_assert_cmpint (data.num_acquired, ==, 2);
|
|
||||||
g_assert_cmpint (data.num_lost, ==, 2);
|
|
||||||
g_bus_unown_name (id);
|
|
||||||
+ g_main_loop_run (loop);
|
|
||||||
g_assert_cmpint (data.num_free_func, ==, 5);
|
|
||||||
|
|
||||||
g_object_unref (c);
|
|
||||||
@@ -648,6 +655,7 @@ test_bus_watch_name (void)
|
|
||||||
|
|
||||||
/* unown the name */
|
|
||||||
g_bus_unown_name (owner_id);
|
|
||||||
+ g_main_loop_run (loop);
|
|
||||||
g_assert_cmpint (data.num_acquired, ==, 1);
|
|
||||||
g_assert_cmpint (data.num_free_func, ==, 2);
|
|
||||||
|
|
||||||
@@ -707,6 +715,7 @@ test_bus_watch_name (void)
|
|
||||||
g_assert_cmpint (data.num_free_func, ==, 1);
|
|
||||||
|
|
||||||
g_bus_unown_name (owner_id);
|
|
||||||
+ g_main_loop_run (loop);
|
|
||||||
g_assert_cmpint (data.num_free_func, ==, 2);
|
|
||||||
|
|
||||||
session_bus_down ();
|
|
||||||
--
|
|
||||||
2.50.0
|
|
||||||
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
From f3eecc88f4f45b128c963d695a61b230d2665db5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Philip Withnall <pwithnall@gnome.org>
|
|
||||||
Date: Mon, 3 Feb 2025 18:27:21 +0000
|
|
||||||
Subject: [PATCH] gdbusconnection: Prevent sending a serial of zero on overflow
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
It finally happened: someone managed to keep a process alive long
|
|
||||||
enough, and using a single `GDBusConnection`, to overflow the
|
|
||||||
`last_serial` counter in the connection and send an invalid message with
|
|
||||||
serial of zero (which is disallowed by the D-Bus specification).
|
|
||||||
|
|
||||||
Avoid that happening in future by skipping serials of zero on overflow,
|
|
||||||
and wrapping straight back around to 1.
|
|
||||||
|
|
||||||
This looks a little more confusing than it is, because `last_serial` is
|
|
||||||
pre-incremented on use, so to skip zero, we explicitly set it to zero.
|
|
||||||
This is exactly what happens when the `GDBusConnection` is initialised
|
|
||||||
anyway.
|
|
||||||
|
|
||||||
I can’t think of a way to add a unit test for this — there is no way to
|
|
||||||
affect the value of `last_serial` except by sending messages (each one
|
|
||||||
increments it), and in order to get it to overflow by sending messages
|
|
||||||
at 1kHz, the test would have to run for 49 days.
|
|
||||||
|
|
||||||
Instead, I tested this manually by temporarily modifying
|
|
||||||
`GDBusConnection` to initialise `last_serial` to `G_MAXUINT32 - 3`, then
|
|
||||||
checked that the unit tests all still passed, and that the overflow code
|
|
||||||
was being executed.
|
|
||||||
|
|
||||||
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
|
|
||||||
|
|
||||||
Fixes: #3592
|
|
||||||
---
|
|
||||||
gio/gdbusconnection.c | 17 +++++++++++++++--
|
|
||||||
1 file changed, 15 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
|
||||||
index b4cdc7e..45d7861 100644
|
|
||||||
--- a/gio/gdbusconnection.c
|
|
||||||
+++ b/gio/gdbusconnection.c
|
|
||||||
@@ -1790,9 +1790,22 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection,
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL)
|
|
||||||
- serial_to_use = g_dbus_message_get_serial (message);
|
|
||||||
+ {
|
|
||||||
+ serial_to_use = g_dbus_message_get_serial (message);
|
|
||||||
+ }
|
|
||||||
else
|
|
||||||
- serial_to_use = ++connection->last_serial; /* TODO: handle overflow */
|
|
||||||
+ {
|
|
||||||
+ /* The serial_to_use must not be zero, as per
|
|
||||||
+ * https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages. */
|
|
||||||
+ if (connection->last_serial == G_MAXUINT32)
|
|
||||||
+ connection->last_serial = 1;
|
|
||||||
+ else
|
|
||||||
+ connection->last_serial++;
|
|
||||||
+
|
|
||||||
+ serial_to_use = connection->last_serial;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ g_assert (serial_to_use != 0);
|
|
||||||
|
|
||||||
switch (blob[0])
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.47.3
|
|
||||||
|
|
||||||
@ -1,510 +0,0 @@
|
|||||||
From 21ca525a8729c6b64133b00b3e382a2ce5478a9a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Christian Hergert <chergert@redhat.com>
|
|
||||||
Date: Fri, 21 Nov 2025 12:31:13 -0800
|
|
||||||
Subject: [PATCH 1/5] gio/gunixmounts: mark some file-system types as system
|
|
||||||
|
|
||||||
Since this list was originally created, more file system types have
|
|
||||||
become commonly used and would benefit from being marked as a system
|
|
||||||
file-system type.
|
|
||||||
|
|
||||||
This was found while tracking down some performance issues in
|
|
||||||
gnome-settings-daemon trash handling.
|
|
||||||
---
|
|
||||||
gio/gunixmounts.c | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
|
|
||||||
index 3514e2e8e..7d7b82980 100644
|
|
||||||
--- a/gio/gunixmounts.c
|
|
||||||
+++ b/gio/gunixmounts.c
|
|
||||||
@@ -306,6 +306,8 @@ g_unix_is_system_fs_type (const char *fs_type)
|
|
||||||
"auto",
|
|
||||||
"autofs",
|
|
||||||
"autofs4",
|
|
||||||
+ "binfmt_misc",
|
|
||||||
+ "bpf",
|
|
||||||
"cgroup",
|
|
||||||
"configfs",
|
|
||||||
"cxfs",
|
|
||||||
@@ -314,6 +316,7 @@ g_unix_is_system_fs_type (const char *fs_type)
|
|
||||||
"devpts",
|
|
||||||
"devtmpfs",
|
|
||||||
"ecryptfs",
|
|
||||||
+ "efivarfs",
|
|
||||||
"fdescfs",
|
|
||||||
"fusectl",
|
|
||||||
"gfs",
|
|
||||||
@@ -342,6 +345,7 @@ g_unix_is_system_fs_type (const char *fs_type)
|
|
||||||
"selinuxfs",
|
|
||||||
"sysfs",
|
|
||||||
"tmpfs",
|
|
||||||
+ "tracefs",
|
|
||||||
"usbfs",
|
|
||||||
"zfs",
|
|
||||||
NULL
|
|
||||||
--
|
|
||||||
2.52.0
|
|
||||||
|
|
||||||
|
|
||||||
From b5525b89de94b2a84f4f77603f4cd5eae7c27b1b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ondrej Holy <oholy@redhat.com>
|
|
||||||
Date: Mon, 1 Dec 2025 15:36:02 +0100
|
|
||||||
Subject: [PATCH 2/5] gio/gunixmounts: Mark more file systems as system
|
|
||||||
internal
|
|
||||||
|
|
||||||
The commit f1a90a67 updated list of system internal file systems.
|
|
||||||
I think we can add a few more file systems (i.e. `cgroups2`,
|
|
||||||
`fuse.gvfsd-fuse`, `fuse.portal`) and `/bin/efi` path. This is to
|
|
||||||
improve performance of `gvfsd-trash`, `gsd-houskeeping` and similar.
|
|
||||||
|
|
||||||
Related: https://gitlab.gnome.org/GNOME/gvfs/-/issues/814
|
|
||||||
---
|
|
||||||
gio/gunixmounts.c | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
|
|
||||||
index 7d7b82980..f9c3f9fec 100644
|
|
||||||
--- a/gio/gunixmounts.c
|
|
||||||
+++ b/gio/gunixmounts.c
|
|
||||||
@@ -227,6 +227,7 @@ g_unix_is_mount_path_system_internal (const char *mount_path)
|
|
||||||
*/
|
|
||||||
"/", /* we already have "Filesystem root" in Nautilus */
|
|
||||||
"/bin",
|
|
||||||
+ "/bin/efi",
|
|
||||||
"/boot",
|
|
||||||
"/compat/linux/proc",
|
|
||||||
"/compat/linux/sys",
|
|
||||||
@@ -309,6 +310,7 @@ g_unix_is_system_fs_type (const char *fs_type)
|
|
||||||
"binfmt_misc",
|
|
||||||
"bpf",
|
|
||||||
"cgroup",
|
|
||||||
+ "cgroup2",
|
|
||||||
"configfs",
|
|
||||||
"cxfs",
|
|
||||||
"debugfs",
|
|
||||||
@@ -318,6 +320,8 @@ g_unix_is_system_fs_type (const char *fs_type)
|
|
||||||
"ecryptfs",
|
|
||||||
"efivarfs",
|
|
||||||
"fdescfs",
|
|
||||||
+ "fuse.gvfsd-fuse",
|
|
||||||
+ "fuse.portal",
|
|
||||||
"fusectl",
|
|
||||||
"gfs",
|
|
||||||
"gfs2",
|
|
||||||
--
|
|
||||||
2.52.0
|
|
||||||
|
|
||||||
|
|
||||||
From e8e7229a72b92844c9928dde48cfa8c660cfe658 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ondrej Holy <oholy@redhat.com>
|
|
||||||
Date: Wed, 3 Dec 2025 10:02:15 +0100
|
|
||||||
Subject: [PATCH 3/5] gio/gunixmounts: Replace /bin/efi with /boot/efi
|
|
||||||
|
|
||||||
The commit 06e9f2c0 added `/bin/efi` instead of `/boot/efi` to the
|
|
||||||
list of system internal mount paths by mistake. Let's fix it.
|
|
||||||
---
|
|
||||||
gio/gunixmounts.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
|
|
||||||
index f9c3f9fec..a35e9fc43 100644
|
|
||||||
--- a/gio/gunixmounts.c
|
|
||||||
+++ b/gio/gunixmounts.c
|
|
||||||
@@ -227,8 +227,8 @@ g_unix_is_mount_path_system_internal (const char *mount_path)
|
|
||||||
*/
|
|
||||||
"/", /* we already have "Filesystem root" in Nautilus */
|
|
||||||
"/bin",
|
|
||||||
- "/bin/efi",
|
|
||||||
"/boot",
|
|
||||||
+ "/boot/efi",
|
|
||||||
"/compat/linux/proc",
|
|
||||||
"/compat/linux/sys",
|
|
||||||
"/dev",
|
|
||||||
--
|
|
||||||
2.52.0
|
|
||||||
|
|
||||||
|
|
||||||
From b761e2b3917a6cef5814717c06c19b9bd835096e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Christian Hergert <chergert@redhat.com>
|
|
||||||
Date: Fri, 21 Nov 2025 18:54:33 -0800
|
|
||||||
Subject: [PATCH 4/5] gio/unixmounts: use bsearch() to check for set inclusion
|
|
||||||
|
|
||||||
This turns out to be about 17% faster than the previous set comparisons
|
|
||||||
on large (in the thousands) /proc/mounts configurations. It does require
|
|
||||||
that we keep the lists sorted but ended up faster than gperf hashing.
|
|
||||||
---
|
|
||||||
gio/gunixmounts.c | 61 +++++++++++++++++++++++++----------------------
|
|
||||||
1 file changed, 32 insertions(+), 29 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
|
|
||||||
index a35e9fc43..ae4174d4f 100644
|
|
||||||
--- a/gio/gunixmounts.c
|
|
||||||
+++ b/gio/gunixmounts.c
|
|
||||||
@@ -39,6 +39,7 @@
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <gstdio.h>
|
|
||||||
@@ -194,16 +195,17 @@ static guint64 mount_poller_time = 0;
|
|
||||||
#define endmntent(f) fclose(f)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+static int
|
|
||||||
+compare_str (const char * key,
|
|
||||||
+ const char * const *element)
|
|
||||||
+{
|
|
||||||
+ return strcmp (key, *element);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static gboolean
|
|
||||||
-is_in (const char *value, const char *set[])
|
|
||||||
+is_in (const char *value, const char *set[], gsize set_size)
|
|
||||||
{
|
|
||||||
- int i;
|
|
||||||
- for (i = 0; set[i] != NULL; i++)
|
|
||||||
- {
|
|
||||||
- if (strcmp (set[i], value) == 0)
|
|
||||||
- return TRUE;
|
|
||||||
- }
|
|
||||||
- return FALSE;
|
|
||||||
+ return bsearch (value, set, set_size, sizeof (char *), (GCompareFunc)compare_str) != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -221,11 +223,12 @@ is_in (const char *value, const char *set[])
|
|
||||||
gboolean
|
|
||||||
g_unix_is_mount_path_system_internal (const char *mount_path)
|
|
||||||
{
|
|
||||||
+ /* keep sorted for bsearch */
|
|
||||||
const char *ignore_mountpoints[] = {
|
|
||||||
/* Includes all FHS 2.3 toplevel dirs and other specialized
|
|
||||||
* directories that we want to hide from the user.
|
|
||||||
*/
|
|
||||||
- "/", /* we already have "Filesystem root" in Nautilus */
|
|
||||||
+ "/", /* we already have "Filesystem root" in Nautilus */
|
|
||||||
"/bin",
|
|
||||||
"/boot",
|
|
||||||
"/boot/efi",
|
|
||||||
@@ -241,11 +244,15 @@ g_unix_is_mount_path_system_internal (const char *mount_path)
|
|
||||||
"/live/image",
|
|
||||||
"/media",
|
|
||||||
"/mnt",
|
|
||||||
+ "/net",
|
|
||||||
"/opt",
|
|
||||||
+ "/proc",
|
|
||||||
"/rescue",
|
|
||||||
"/root",
|
|
||||||
"/sbin",
|
|
||||||
+ "/sbin",
|
|
||||||
"/srv",
|
|
||||||
+ "/sys",
|
|
||||||
"/tmp",
|
|
||||||
"/usr",
|
|
||||||
"/usr/X11R6",
|
|
||||||
@@ -262,16 +269,16 @@ g_unix_is_mount_path_system_internal (const char *mount_path)
|
|
||||||
"/var/mail",
|
|
||||||
"/var/run",
|
|
||||||
"/var/tmp", /* https://bugzilla.redhat.com/show_bug.cgi?id=335241 */
|
|
||||||
- "/proc",
|
|
||||||
- "/sbin",
|
|
||||||
- "/net",
|
|
||||||
- "/sys",
|
|
||||||
- NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
- if (is_in (mount_path, ignore_mountpoints))
|
|
||||||
+ if (is_in (mount_path, ignore_mountpoints, G_N_ELEMENTS (ignore_mountpoints)))
|
|
||||||
return TRUE;
|
|
||||||
-
|
|
||||||
+
|
|
||||||
+ /* Kept separate from sorted list as they may vary */
|
|
||||||
+ if (g_str_equal ("/var", mount_path) ||
|
|
||||||
+ g_str_equal ("/run", mount_path))
|
|
||||||
+ return TRUE;
|
|
||||||
+
|
|
||||||
if (g_str_has_prefix (mount_path, "/dev/") ||
|
|
||||||
g_str_has_prefix (mount_path, "/proc/") ||
|
|
||||||
g_str_has_prefix (mount_path, "/sys/"))
|
|
||||||
@@ -301,14 +308,13 @@ g_unix_is_mount_path_system_internal (const char *mount_path)
|
|
||||||
gboolean
|
|
||||||
g_unix_is_system_fs_type (const char *fs_type)
|
|
||||||
{
|
|
||||||
+ /* keep sorted for bsearch */
|
|
||||||
const char *ignore_fs[] = {
|
|
||||||
"adfs",
|
|
||||||
"afs",
|
|
||||||
"auto",
|
|
||||||
"autofs",
|
|
||||||
"autofs4",
|
|
||||||
- "binfmt_misc",
|
|
||||||
- "bpf",
|
|
||||||
"cgroup",
|
|
||||||
"cgroup2",
|
|
||||||
"configfs",
|
|
||||||
@@ -318,7 +324,6 @@ g_unix_is_system_fs_type (const char *fs_type)
|
|
||||||
"devpts",
|
|
||||||
"devtmpfs",
|
|
||||||
"ecryptfs",
|
|
||||||
- "efivarfs",
|
|
||||||
"fdescfs",
|
|
||||||
"fuse.gvfsd-fuse",
|
|
||||||
"fuse.portal",
|
|
||||||
@@ -349,15 +354,13 @@ g_unix_is_system_fs_type (const char *fs_type)
|
|
||||||
"selinuxfs",
|
|
||||||
"sysfs",
|
|
||||||
"tmpfs",
|
|
||||||
- "tracefs",
|
|
||||||
"usbfs",
|
|
||||||
- "zfs",
|
|
||||||
- NULL
|
|
||||||
+ "zfs"
|
|
||||||
};
|
|
||||||
|
|
||||||
g_return_val_if_fail (fs_type != NULL && *fs_type != '\0', FALSE);
|
|
||||||
|
|
||||||
- return is_in (fs_type, ignore_fs);
|
|
||||||
+ return is_in (fs_type, ignore_fs, G_N_ELEMENTS (ignore_fs));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -379,19 +382,19 @@ g_unix_is_system_fs_type (const char *fs_type)
|
|
||||||
gboolean
|
|
||||||
g_unix_is_system_device_path (const char *device_path)
|
|
||||||
{
|
|
||||||
+ /* keep sorted for bsearch */
|
|
||||||
const char *ignore_devices[] = {
|
|
||||||
- "none",
|
|
||||||
- "sunrpc",
|
|
||||||
- "devpts",
|
|
||||||
- "nfsd",
|
|
||||||
"/dev/loop",
|
|
||||||
"/dev/vn",
|
|
||||||
- NULL
|
|
||||||
+ "devpts",
|
|
||||||
+ "nfsd",
|
|
||||||
+ "none",
|
|
||||||
+ "sunrpc",
|
|
||||||
};
|
|
||||||
|
|
||||||
g_return_val_if_fail (device_path != NULL && *device_path != '\0', FALSE);
|
|
||||||
|
|
||||||
- return is_in (device_path, ignore_devices);
|
|
||||||
+ return is_in (device_path, ignore_devices, G_N_ELEMENTS (ignore_devices));
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
--
|
|
||||||
2.52.0
|
|
||||||
|
|
||||||
|
|
||||||
From b9914374503531d5e9773716b865863fa04f6dca Mon Sep 17 00:00:00 2001
|
|
||||||
From: Christian Hergert <chergert@gnome.org>
|
|
||||||
Date: Tue, 6 Jan 2026 10:56:59 -0800
|
|
||||||
Subject: [PATCH 5/5] gio/unixmounts: test that mounts are in sorted order
|
|
||||||
|
|
||||||
---
|
|
||||||
gio/gunixmounts-private.h | 69 +++++++++++++++++++++++++++++++++++++++
|
|
||||||
gio/gunixmounts.c | 51 ++---------------------------
|
|
||||||
gio/tests/unix-mounts.c | 24 ++++++++++++++
|
|
||||||
3 files changed, 95 insertions(+), 49 deletions(-)
|
|
||||||
create mode 100644 gio/gunixmounts-private.h
|
|
||||||
|
|
||||||
diff --git a/gio/gunixmounts-private.h b/gio/gunixmounts-private.h
|
|
||||||
new file mode 100644
|
|
||||||
index 000000000..196e81aca
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/gio/gunixmounts-private.h
|
|
||||||
@@ -0,0 +1,69 @@
|
|
||||||
+/* GIO - GLib Input, Output and Streaming Library
|
|
||||||
+ *
|
|
||||||
+ * Copyright 2006-2007 Red Hat, Inc.
|
|
||||||
+ * Copyright 2026 Christian Hergert
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
+ *
|
|
||||||
+ * 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 <http://www.gnu.org/licenses/>.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#pragma once
|
|
||||||
+
|
|
||||||
+/* keep sorted for bsearch */
|
|
||||||
+static const char *system_mount_paths[] = {
|
|
||||||
+ /* Includes all FHS 2.3 toplevel dirs and other specialized
|
|
||||||
+ * directories that we want to hide from the user.
|
|
||||||
+ */
|
|
||||||
+ "/", /* we already have "Filesystem root" in Nautilus */
|
|
||||||
+ "/bin",
|
|
||||||
+ "/boot",
|
|
||||||
+ "/compat/linux/proc",
|
|
||||||
+ "/compat/linux/sys",
|
|
||||||
+ "/dev",
|
|
||||||
+ "/etc",
|
|
||||||
+ "/home",
|
|
||||||
+ "/lib",
|
|
||||||
+ "/lib64",
|
|
||||||
+ "/libexec",
|
|
||||||
+ "/live/cow",
|
|
||||||
+ "/live/image",
|
|
||||||
+ "/media",
|
|
||||||
+ "/mnt",
|
|
||||||
+ "/net",
|
|
||||||
+ "/opt",
|
|
||||||
+ "/proc",
|
|
||||||
+ "/rescue",
|
|
||||||
+ "/root",
|
|
||||||
+ "/sbin",
|
|
||||||
+ "/sbin",
|
|
||||||
+ "/srv",
|
|
||||||
+ "/sys",
|
|
||||||
+ "/tmp",
|
|
||||||
+ "/usr",
|
|
||||||
+ "/usr/X11R6",
|
|
||||||
+ "/usr/local",
|
|
||||||
+ "/usr/obj",
|
|
||||||
+ "/usr/ports",
|
|
||||||
+ "/usr/src",
|
|
||||||
+ "/usr/xobj",
|
|
||||||
+ "/var",
|
|
||||||
+ "/var/crash",
|
|
||||||
+ "/var/local",
|
|
||||||
+ "/var/log",
|
|
||||||
+ "/var/log/audit", /* https://bugzilla.redhat.com/show_bug.cgi?id=333041 */
|
|
||||||
+ "/var/mail",
|
|
||||||
+ "/var/run",
|
|
||||||
+ "/var/tmp", /* https://bugzilla.redhat.com/show_bug.cgi?id=335241 */
|
|
||||||
+};
|
|
||||||
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
|
|
||||||
index ae4174d4f..ca806abaf 100644
|
|
||||||
--- a/gio/gunixmounts.c
|
|
||||||
+++ b/gio/gunixmounts.c
|
|
||||||
@@ -65,6 +65,7 @@
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "gunixmounts.h"
|
|
||||||
+#include "gunixmounts-private.h"
|
|
||||||
#include "glocalfileprivate.h"
|
|
||||||
#include "gfile.h"
|
|
||||||
#include "gfilemonitor.h"
|
|
||||||
@@ -223,55 +224,7 @@ is_in (const char *value, const char *set[], gsize set_size)
|
|
||||||
gboolean
|
|
||||||
g_unix_is_mount_path_system_internal (const char *mount_path)
|
|
||||||
{
|
|
||||||
- /* keep sorted for bsearch */
|
|
||||||
- const char *ignore_mountpoints[] = {
|
|
||||||
- /* Includes all FHS 2.3 toplevel dirs and other specialized
|
|
||||||
- * directories that we want to hide from the user.
|
|
||||||
- */
|
|
||||||
- "/", /* we already have "Filesystem root" in Nautilus */
|
|
||||||
- "/bin",
|
|
||||||
- "/boot",
|
|
||||||
- "/boot/efi",
|
|
||||||
- "/compat/linux/proc",
|
|
||||||
- "/compat/linux/sys",
|
|
||||||
- "/dev",
|
|
||||||
- "/etc",
|
|
||||||
- "/home",
|
|
||||||
- "/lib",
|
|
||||||
- "/lib64",
|
|
||||||
- "/libexec",
|
|
||||||
- "/live/cow",
|
|
||||||
- "/live/image",
|
|
||||||
- "/media",
|
|
||||||
- "/mnt",
|
|
||||||
- "/net",
|
|
||||||
- "/opt",
|
|
||||||
- "/proc",
|
|
||||||
- "/rescue",
|
|
||||||
- "/root",
|
|
||||||
- "/sbin",
|
|
||||||
- "/sbin",
|
|
||||||
- "/srv",
|
|
||||||
- "/sys",
|
|
||||||
- "/tmp",
|
|
||||||
- "/usr",
|
|
||||||
- "/usr/X11R6",
|
|
||||||
- "/usr/local",
|
|
||||||
- "/usr/obj",
|
|
||||||
- "/usr/ports",
|
|
||||||
- "/usr/src",
|
|
||||||
- "/usr/xobj",
|
|
||||||
- "/var",
|
|
||||||
- "/var/crash",
|
|
||||||
- "/var/local",
|
|
||||||
- "/var/log",
|
|
||||||
- "/var/log/audit", /* https://bugzilla.redhat.com/show_bug.cgi?id=333041 */
|
|
||||||
- "/var/mail",
|
|
||||||
- "/var/run",
|
|
||||||
- "/var/tmp", /* https://bugzilla.redhat.com/show_bug.cgi?id=335241 */
|
|
||||||
- };
|
|
||||||
-
|
|
||||||
- if (is_in (mount_path, ignore_mountpoints, G_N_ELEMENTS (ignore_mountpoints)))
|
|
||||||
+ if (is_in (mount_path, system_mount_paths, G_N_ELEMENTS (system_mount_paths)))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/* Kept separate from sorted list as they may vary */
|
|
||||||
diff --git a/gio/tests/unix-mounts.c b/gio/tests/unix-mounts.c
|
|
||||||
index 67b8c8d98..4c1f69a01 100644
|
|
||||||
--- a/gio/tests/unix-mounts.c
|
|
||||||
+++ b/gio/tests/unix-mounts.c
|
|
||||||
@@ -28,6 +28,8 @@
|
|
||||||
#include <gio/gio.h>
|
|
||||||
#include <gio/gunixmounts.h>
|
|
||||||
|
|
||||||
+#include "../gunixmounts-private.h"
|
|
||||||
+
|
|
||||||
static void
|
|
||||||
test_is_system_fs_type (void)
|
|
||||||
{
|
|
||||||
@@ -48,6 +50,27 @@ test_is_system_device_path (void)
|
|
||||||
g_assert_false (g_unix_is_system_device_path ("/"));
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void
|
|
||||||
+test_system_mount_paths_sorted (void)
|
|
||||||
+{
|
|
||||||
+ size_t i;
|
|
||||||
+ size_t n_paths = G_N_ELEMENTS (system_mount_paths);
|
|
||||||
+
|
|
||||||
+ for (i = 1; i < n_paths; i++)
|
|
||||||
+ {
|
|
||||||
+ int cmp = strcmp (system_mount_paths[i - 1], system_mount_paths[i]);
|
|
||||||
+ if (cmp > 0)
|
|
||||||
+ {
|
|
||||||
+ g_fprintf (stderr, "system_mount_paths array is not sorted: "
|
|
||||||
+ "\"%s\" should come before \"%s\"",
|
|
||||||
+ system_mount_paths[i - 1],
|
|
||||||
+ system_mount_paths[i]);
|
|
||||||
+ g_test_fail ();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int
|
|
||||||
main (int argc,
|
|
||||||
char *argv[])
|
|
||||||
@@ -58,6 +81,7 @@ main (int argc,
|
|
||||||
|
|
||||||
g_test_add_func ("/unix-mounts/is-system-fs-type", test_is_system_fs_type);
|
|
||||||
g_test_add_func ("/unix-mounts/is-system-device-path", test_is_system_device_path);
|
|
||||||
+ g_test_add_func ("/unix-mounts/system-mount-paths-sorted", test_system_mount_paths_sorted);
|
|
||||||
|
|
||||||
return g_test_run ();
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.52.0
|
|
||||||
|
|
||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
Name: glib2
|
Name: glib2
|
||||||
Version: 2.56.4
|
Version: 2.56.4
|
||||||
Release: 168%{?dist}
|
Release: 163%{?dist}
|
||||||
Summary: A library of handy utility functions
|
Summary: A library of handy utility functions
|
||||||
|
|
||||||
License: LGPLv2+
|
License: LGPLv2+
|
||||||
@ -33,9 +33,6 @@ BuildRequires: pkgconfig(zlib)
|
|||||||
BuildRequires: automake autoconf libtool
|
BuildRequires: automake autoconf libtool
|
||||||
BuildRequires: gtk-doc
|
BuildRequires: gtk-doc
|
||||||
BuildRequires: python3-devel
|
BuildRequires: python3-devel
|
||||||
# For testsuite
|
|
||||||
BuildRequires: desktop-file-utils
|
|
||||||
BuildRequires: shared-mime-info
|
|
||||||
|
|
||||||
# for GIO content-type support
|
# for GIO content-type support
|
||||||
Recommends: shared-mime-info
|
Recommends: shared-mime-info
|
||||||
@ -128,40 +125,6 @@ Patch22: 54.patch
|
|||||||
# Also: https://gitlab.gnome.org/GNOME/glib/-/commit/d0821da5244fd08c756a5f84ec0d3063c72d1ac6
|
# Also: https://gitlab.gnome.org/GNOME/glib/-/commit/d0821da5244fd08c756a5f84ec0d3063c72d1ac6
|
||||||
Patch23: 1549.patch
|
Patch23: 1549.patch
|
||||||
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4155
|
|
||||||
Patch24: 4155.patch
|
|
||||||
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4281
|
|
||||||
Patch25: CVE-2024-52533.patch
|
|
||||||
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4588
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4592
|
|
||||||
Patch26: CVE-2025-4373.patch
|
|
||||||
|
|
||||||
# Contains commits from:
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1121
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3291
|
|
||||||
Patch27: gdbus-conflict-reduction.patch
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1332
|
|
||||||
Patch28: gdbus-signal-race.patch
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4038
|
|
||||||
Patch29: CVE-2024-34397.patch
|
|
||||||
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4356
|
|
||||||
Patch30: gdatetime-test.patch
|
|
||||||
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4470
|
|
||||||
Patch31: gdbusconnection-serial-number-overflow.patch
|
|
||||||
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4914
|
|
||||||
Patch32: CVE-2025-13601.patch
|
|
||||||
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4916
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4918
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4930
|
|
||||||
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4931
|
|
||||||
Patch33: gunixmount-improvements.patch
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
GLib is the low-level core library that forms the basis for projects
|
GLib is the low-level core library that forms the basis for projects
|
||||||
such as GTK+ and GNOME. It provides data structure handling for C,
|
such as GTK+ and GNOME. It provides data structure handling for C,
|
||||||
@ -276,9 +239,6 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
|
|||||||
%transfiletriggerpostun -- %{_datadir}/glib-2.0/schemas
|
%transfiletriggerpostun -- %{_datadir}/glib-2.0/schemas
|
||||||
glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
|
glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
|
||||||
|
|
||||||
%check
|
|
||||||
make %{?_smp_mflags} check
|
|
||||||
|
|
||||||
%files -f glib20.lang
|
%files -f glib20.lang
|
||||||
%license COPYING
|
%license COPYING
|
||||||
%doc AUTHORS NEWS README
|
%doc AUTHORS NEWS README
|
||||||
@ -362,30 +322,6 @@ make %{?_smp_mflags} check
|
|||||||
%{_datadir}/installed-tests
|
%{_datadir}/installed-tests
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Tue Jan 20 2026 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-168
|
|
||||||
- Add patch for CVE-2025-13601
|
|
||||||
- Fix GUnixMount issues
|
|
||||||
- Enable testsuite during RPM check phase
|
|
||||||
|
|
||||||
* Wed Sep 17 2025 RHEL Packaging Agent <jotnar@redhat.com> - 2.56.4-167
|
|
||||||
- gdbusconnection: Prevent sending a serial of zero on overflow
|
|
||||||
- Resolves: RHEL-114086
|
|
||||||
|
|
||||||
* Fri Jul 11 2025 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-166
|
|
||||||
- Add patches for CVE-2024-34397, CVE-2024-52533, CVE-2025-4373
|
|
||||||
- Update GDateTime test for new tzdata
|
|
||||||
- Resolves: RHEL-67084
|
|
||||||
- Resolves: RHEL-94286
|
|
||||||
- Resolves: RHEL-94848
|
|
||||||
|
|
||||||
* Thu Sep 26 2024 Ondrej Holy <oholy@redhat.com> - 2.56.4-165
|
|
||||||
- Add support for x-gvfs-trash mount option
|
|
||||||
- Resolves: RHEL-46828
|
|
||||||
|
|
||||||
* Tue Feb 13 2024 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-164
|
|
||||||
- Revert GUnixMountMonitor changes (it depends on functionality not in RHEL 8)
|
|
||||||
- Resolves: RHEL-23636
|
|
||||||
|
|
||||||
* Thu Feb 01 2024 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-163
|
* Thu Feb 01 2024 Michael Catanzaro <mcatanzaro@redhat.com> - 2.56.4-163
|
||||||
- Backport GUnixMountMonitor port to libmnt_monitor
|
- Backport GUnixMountMonitor port to libmnt_monitor
|
||||||
- Make GUnixMountMonitor thread-safe
|
- Make GUnixMountMonitor thread-safe
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user