Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gvfs for openSUSE:Factory checked in at 2026-03-01 22:14:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gvfs (Old) and /work/SRC/openSUSE:Factory/.gvfs.new.29461 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gvfs" Sun Mar 1 22:14:10 2026 rev:205 rq:1335553 version:1.58.2 Changes: -------- --- /work/SRC/openSUSE:Factory/gvfs/gvfs.changes 2026-02-03 21:26:34.912240740 +0100 +++ /work/SRC/openSUSE:Factory/.gvfs.new.29461/gvfs.changes 2026-03-01 22:14:39.429549896 +0100 @@ -1,0 +2,16 @@ +Sat Feb 28 09:41:46 UTC 2026 - Dominique Leuenberger <[email protected]> + +- Update to version 1.58.2: + + client: Fix use-after-free when creating async proxy failed + + daemon: Fix race on subscribers list when on thread + + ftp: Validate fe_size when parsing symlink target + + ftp: Check localtime() return value before use + + CVE-2026-28295: ftp: Use control connection address for PASV + data + + CVE-2026-28296: ftp: Reject paths containing CR/LF characters + + gphoto2: Use g_try_realloc() instead of g_realloc() + + cdda: Reject path traversal in mount URI host + + client: Fail when URI has invalid UTF-8 chars + + Some other fixes + +------------------------------------------------------------------- Old: ---- gvfs-1.58.1.obscpio New: ---- gvfs-1.58.2.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gvfs.spec ++++++ --- /var/tmp/diff_new_pack.bfRxDl/_old 2026-03-01 22:14:40.641599709 +0100 +++ /var/tmp/diff_new_pack.bfRxDl/_new 2026-03-01 22:14:40.641599709 +0100 @@ -19,7 +19,7 @@ %bcond_without cdda %bcond_without onedrive Name: gvfs -Version: 1.58.1 +Version: 1.58.2 Release: 0 Summary: Virtual File System functionality for GLib License: GPL-3.0-only AND LGPL-2.0-or-later ++++++ _service ++++++ --- /var/tmp/diff_new_pack.bfRxDl/_old 2026-03-01 22:14:40.685601518 +0100 +++ /var/tmp/diff_new_pack.bfRxDl/_new 2026-03-01 22:14:40.689601682 +0100 @@ -3,7 +3,7 @@ <service name="obs_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://gitlab.gnome.org/GNOME/gvfs.git</param> - <param name="revision">1.58.1</param> + <param name="revision">1.58.2</param> <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param> <param name="versionrewrite-pattern">(.*)\+0</param> <param name="versionrewrite-replacement">\1</param> ++++++ gvfs-1.58.1.obscpio -> gvfs-1.58.2.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/NEWS new/gvfs-1.58.2/NEWS --- old/gvfs-1.58.1/NEWS 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/NEWS 2026-02-28 09:23:14.000000000 +0100 @@ -1,3 +1,16 @@ +Major changes in 1.58.2 +======================= +* client: Fix use-after-free when creating async proxy failed (Ondrej Holy) +* daemon: Fix race on subscribers list when on thread (Ondrej Holy) +* ftp: Validate fe_size when parsing symlink target (Ondrej Holy) +* ftp: Check localtime() return value before use (Ondrej Holy) +* CVE-2026-28295: ftp: Use control connection address for PASV data (Ondrej Holy) +* CVE-2026-28296: ftp: Reject paths containing CR/LF characters (Ondrej Holy) +* gphoto2: Use g_try_realloc() instead of g_realloc() (Ondrej Holy) +* cdda: Reject path traversal in mount URI host (Ondrej Holy) +* client: Fail when URI has invalid UTF-8 chars (Ondrej Holy) +* Some other fixes (correctmost, Ondrej Holy) + Major changes in 1.58.1 ======================= * cdda: Fix duration of last track for some media (Bastien Nocera) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/client/gdaemonfile.c new/gvfs-1.58.2/client/gdaemonfile.c --- old/gvfs-1.58.1/client/gdaemonfile.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/client/gdaemonfile.c 2026-02-28 09:23:14.000000000 +0100 @@ -409,6 +409,13 @@ if (path2_out) *path2_out = NULL; + if (!g_mount_spec_get_is_valid (daemon_file1->mount_spec) || + (daemon_file2 && !g_mount_spec_get_is_valid (daemon_file2->mount_spec))) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, _("Filename contains invalid characters.")); + return NULL; + } + retry: proxy = NULL; mount_info2 = NULL; @@ -642,7 +649,7 @@ { GDaemonFile *daemon_file = g_task_get_source_object (data->task); - g_mount_info_unref (data->mount_info); + g_clear_pointer (&data->mount_info, g_mount_info_unref); _g_daemon_vfs_get_mount_info_async (daemon_file->mount_spec, daemon_file->path, async_got_mount_info, @@ -694,6 +701,14 @@ GDaemonFile *daemon_file = G_DAEMON_FILE (file); AsyncProxyCreate *data; + if (!g_mount_spec_get_is_valid (daemon_file->mount_spec)) + { + g_task_return_error (task, g_error_new_literal (G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, + _("Filename contains invalid characters."))); + g_object_unref (task); + return; + } + data = g_new0 (AsyncProxyCreate, 1); data->task = task; data->callback = callback; @@ -1988,6 +2003,16 @@ task = g_task_new (location, cancellable, callback, user_data); g_task_set_source_tag (task, g_daemon_file_mount_enclosing_volume); + if (!g_mount_spec_get_is_valid (G_DAEMON_FILE (location)->mount_spec)) + { + g_task_return_error (task, + g_error_new_literal (G_IO_ERROR, + G_IO_ERROR_INVALID_FILENAME, + _("Filename contains invalid characters."))); + g_object_unref (task); + return; + } + data = g_new0 (MountData, 1); if (mount_operation) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/client/gvfsuriutils.c new/gvfs-1.58.2/client/gvfsuriutils.c --- old/gvfs-1.58.1/client/gvfsuriutils.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/client/gvfsuriutils.c 2026-02-28 09:23:14.000000000 +0100 @@ -163,7 +163,7 @@ authority_end - authority_start, "@"); if (userinfo_end) { - char *p; + const char *p; host_start = userinfo_end + 1; userinfo_start = authority_start; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/common/gmountspec.c new/gvfs-1.58.2/common/gmountspec.c --- old/gvfs-1.58.1/common/gmountspec.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/common/gmountspec.c 2026-02-28 09:23:14.000000000 +0100 @@ -50,7 +50,8 @@ spec->ref_count = 1; spec->items = g_array_new (FALSE, TRUE, sizeof (GMountSpecItem)); spec->mount_prefix = g_strdup ("/"); - + spec->is_valid = TRUE; + if (type != NULL) g_mount_spec_set (spec, "type", type); @@ -67,6 +68,7 @@ spec = g_new0 (GMountSpec, 1); spec->ref_count = 1; spec->items = items; + spec->is_valid = TRUE; if (mount_prefix == NULL) spec->mount_prefix = g_strdup ("/"); else @@ -128,6 +130,9 @@ item.key = g_strdup (key); item.value = value; + if (!g_utf8_validate (value, -1, NULL)) + spec->is_valid = FALSE; + g_array_append_val (spec->items, item); } @@ -168,6 +173,8 @@ { g_free (item->value); item->value = value_copy; + if (!g_utf8_validate (value_copy, -1, NULL)) + spec->is_valid = FALSE; return; } } @@ -215,7 +222,9 @@ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i); g_mount_spec_set (copy, item->key, item->value); } - + + copy->is_valid = spec->is_valid; + return copy; } @@ -431,7 +440,13 @@ { return g_mount_spec_get (spec, "type"); } - + +gboolean +g_mount_spec_get_is_valid (GMountSpec *spec) +{ + return spec->is_valid; +} + char * g_mount_spec_to_string (GMountSpec *spec) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/common/gmountspec.h new/gvfs-1.58.2/common/gmountspec.h --- old/gvfs-1.58.1/common/gmountspec.h 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/common/gmountspec.h 2026-02-28 09:23:14.000000000 +0100 @@ -38,6 +38,7 @@ GArray *items; char *mount_prefix; gboolean is_unique; + gboolean is_valid; } GMountSpec; GMountSpec *g_mount_spec_new (const char *type); @@ -74,6 +75,7 @@ const char *g_mount_spec_get (GMountSpec *spec, const char *key); const char *g_mount_spec_get_type (GMountSpec *spec); +gboolean g_mount_spec_get_is_valid (GMountSpec *spec); char * g_mount_spec_to_string (GMountSpec *spec); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/ParseFTPList.c new/gvfs-1.58.2/daemon/ParseFTPList.c --- old/gvfs-1.58.1/daemon/ParseFTPList.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/ParseFTPList.c 2026-02-28 09:23:14.000000000 +0100 @@ -135,9 +135,12 @@ { guint64 seconds; time_t t; + struct tm *tm; sscanf(p+1, "%"G_GUINT64_FORMAT, &seconds); t = seconds; - result->fe_time = *localtime (&t); + tm = localtime (&t); + if (tm != NULL) + result->fe_time = *tm; } } } @@ -1155,8 +1158,13 @@ if (!state->now_time) { + struct tm *tm; state->now_time = time (NULL); - state->now_tm = *localtime (&state->now_time); + tm = localtime (&state->now_time); + if (tm != NULL) + state->now_tm = *tm; + else + memset (&state->now_tm, 0, sizeof (state->now_tm)); } result->fe_time.tm_year = state->now_tm.tm_year; @@ -1191,7 +1199,8 @@ This can give proper result for cases like "aaa -> bbb -> ccc". */ guint32 fe_size = atoi(result->fe_size); - if (result->fe_fnlen > (fe_size + 4) && + if (fe_size <= result->fe_fnlen - 4 && + result->fe_fnlen > (fe_size + 4) && strncmp(result->fe_fname + result->fe_fnlen - fe_size - 4 , " -> ", 4) == 0) { result->fe_lname = result->fe_fname + (result->fe_fnlen - fe_size); @@ -1631,8 +1640,13 @@ result->fe_time.tm_min = atoi(p+3); if (!state->now_time) { - state->now_time = time (NULL); - state->now_tm = *localtime (&state->now_time); + struct tm *tm; + state->now_time = time (NULL); + tm = localtime (&state->now_time); + if (tm != NULL) + state->now_tm = *tm; + else + memset (&state->now_tm, 0, sizeof (state->now_tm)); } result->fe_time.tm_year = state->now_tm.tm_year; if ( (( state->now_tm.tm_mon << 4) + state->now_tm.tm_mday) < diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsbackendcdda.c new/gvfs-1.58.2/daemon/gvfsbackendcdda.c --- old/gvfs-1.58.1/daemon/gvfsbackendcdda.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsbackendcdda.c 2026-02-28 09:23:14.000000000 +0100 @@ -394,7 +394,7 @@ */ host = g_mount_spec_get (mount_spec, "host"); //g_warning ("tm host=%s", host); - if (host == NULL) + if (host == NULL || strstr (host, "..") != NULL) { g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, _("No drive specified")); g_vfs_job_failed_from_error (G_VFS_JOB (job), error); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsbackendftp.c new/gvfs-1.58.2/daemon/gvfsbackendftp.c --- old/gvfs-1.58.1/daemon/gvfsbackendftp.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsbackendftp.c 2026-02-28 09:23:14.000000000 +0100 @@ -63,9 +63,8 @@ * GVfsFtpMethod: * @G_VFS_FTP_METHOD_UNKNOWN: method has not yet been determined * @G_VFS_FTP_METHOD_EPSV: use EPSV command - * @G_VFS_FTP_METHOD_PASV: use PASV command - * @G_VFS_FTP_METHOD_PASV_ADDR: use PASV command, but ignore the returned - * address and only use it's port + * @G_VFS_FTP_METHOD_PASV: use PASV command, but ignore the returned address + * and only use it's port (bounce attack prevention) * @G_VFS_FTP_METHOD_EPRT: use the EPRT command * @G_VFS_FTP_METHOD_PORT: use the PORT command * @@ -872,9 +871,14 @@ error_550_permission_or_not_found, NULL }; - g_vfs_ftp_task_setup_data_connection (&task); - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + g_vfs_ftp_task_setup_data_connection (&task); g_vfs_ftp_task_send_and_check (&task, G_VFS_FTP_PASS_100 | G_VFS_FTP_FAIL_200, open_read_handlers, @@ -993,7 +997,13 @@ GFileInfo *info; GVfsFtpFile *file; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + info = g_vfs_ftp_dir_cache_lookup_file (ftp->dir_cache, &task, file, FALSE); if (info) { @@ -1023,7 +1033,13 @@ GVfsFtpTask task = G_VFS_FTP_TASK_INIT (ftp, G_VFS_JOB (job)); GVfsFtpFile *file; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + do_start_write (&task, flags, "APPE %s", g_vfs_ftp_file_get_ftp_path (file)); g_vfs_ftp_dir_cache_purge_file (ftp->dir_cache, file); g_vfs_ftp_file_free (file); @@ -1045,14 +1061,25 @@ static const GVfsFtpErrorFunc rnfr_handlers[] = { error_550_permission_or_not_found, NULL }; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } if (make_backup) { GFileInfo *info; char *backup_path = g_strconcat (filename, "~", NULL); - backupfile = g_vfs_ftp_file_new_from_gvfs (ftp, backup_path); + backupfile = g_vfs_ftp_file_new_from_gvfs (ftp, backup_path, &task.error); g_free (backup_path); + if (backupfile == NULL) + { + g_vfs_ftp_file_free (file); + g_vfs_ftp_task_done (&task); + return; + } info = g_vfs_ftp_dir_cache_lookup_file (ftp->dir_cache, &task, file, FALSE); @@ -1122,7 +1149,7 @@ stream = g_vfs_ftp_connection_get_data_stream (conn); filename = g_object_get_data (G_OBJECT (stream), "g-vfs-backend-ftp-filename"); - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, NULL); g_vfs_ftp_task_give_connection (&task, handle); g_vfs_ftp_task_close_data_connection (&task); @@ -1174,8 +1201,14 @@ GVfsFtpTask task = G_VFS_FTP_TASK_INIT (ftp, G_VFS_JOB (job)); GVfsFtpFile *file; GFileInfo *real; - - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + real = g_vfs_ftp_dir_cache_lookup_file (ftp->dir_cache, &task, file, @@ -1258,7 +1291,12 @@ GVfsFtpTask task = G_VFS_FTP_TASK_INIT (ftp, G_VFS_JOB (job)); GVfsFtpFile *file; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_MODE) == 0 && g_vfs_backend_ftp_has_feature (ftp, G_VFS_FTP_FEATURE_CHMOD)) @@ -1339,7 +1377,13 @@ GVfsFtpFile *dir; GList *list, *walk; - dir = g_vfs_ftp_file_new_from_gvfs (ftp, dirname); + dir = g_vfs_ftp_file_new_from_gvfs (ftp, dirname, &task.error); + if (dir == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + list = g_vfs_ftp_dir_cache_lookup_dir (ftp->dir_cache, &task, dir, @@ -1381,9 +1425,22 @@ GVfsFtpTask task = G_VFS_FTP_TASK_INIT (ftp, G_VFS_JOB (job)); GVfsFtpFile *original, *dir, *now; - original = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + original = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (original == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + dir = g_vfs_ftp_file_new_parent (original); now = g_vfs_ftp_file_new_child (dir, display_name, &task.error); + if (now == NULL) + { + g_vfs_ftp_file_free (original); + g_vfs_ftp_file_free (dir); + g_vfs_ftp_task_done (&task); + return; + } /* Rename a directory that has been "opened" by CWD may fail, so cd to root first */ g_vfs_ftp_task_try_cd (&task, ftp->root); @@ -1416,7 +1473,13 @@ /* We try file deletion first. If that fails, we try directory deletion. * The file-first-then-directory order has been decided by coin-toss. */ - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + response = g_vfs_ftp_task_send (&task, G_VFS_FTP_PASS_500, "DELE %s", g_vfs_ftp_file_get_ftp_path (file)); @@ -1464,7 +1527,13 @@ GVfsFtpFile *file; static const GVfsFtpErrorFunc make_directory_handlers[] = { error_550_exists, error_550_parent_not_found, NULL }; - file = g_vfs_ftp_file_new_from_gvfs (ftp, filename); + file = g_vfs_ftp_file_new_from_gvfs (ftp, filename, &task.error); + if (file == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + g_vfs_ftp_task_send_and_check (&task, 0, make_directory_handlers, @@ -1495,6 +1564,21 @@ static const GVfsFtpErrorFunc rnfr_handlers[] = { error_550_permission_or_not_found, NULL }; + srcfile = g_vfs_ftp_file_new_from_gvfs (ftp, source, &task.error); + if (srcfile == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + + destfile = g_vfs_ftp_file_new_from_gvfs (ftp, destination, &task.error); + if (destfile == NULL) + { + g_vfs_ftp_file_free (srcfile); + g_vfs_ftp_task_done (&task); + return; + } + /* FIXME: what about G_FILE_COPY_NOFOLLOW_SYMLINKS and G_FILE_COPY_ALL_METADATA? */ if (flags & G_FILE_COPY_BACKUP) @@ -1522,8 +1606,6 @@ return; } - srcfile = g_vfs_ftp_file_new_from_gvfs (ftp, source); - destfile = g_vfs_ftp_file_new_from_gvfs (ftp, destination); if (g_vfs_ftp_task_try_cd (&task, destfile)) { char *basename = g_path_get_basename (source); @@ -1662,8 +1744,14 @@ GOutputStream *output; goffset total_size = 0; guint64 mtime = 0; - - src = g_vfs_ftp_file_new_from_gvfs (ftp, source); + + src = g_vfs_ftp_file_new_from_gvfs (ftp, source, &task.error); + if (src == NULL) + { + g_vfs_ftp_task_done (&task); + return; + } + dest = g_file_new_for_path (local_path); if (remove_source && (flags & G_FILE_COPY_NO_FALLBACK_FOR_MOVE)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsbackendftp.h new/gvfs-1.58.2/daemon/gvfsbackendftp.h --- old/gvfs-1.58.1/daemon/gvfsbackendftp.h 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsbackendftp.h 2026-02-28 09:23:14.000000000 +0100 @@ -62,7 +62,6 @@ G_VFS_FTP_METHOD_ANY = 0, G_VFS_FTP_METHOD_EPSV, G_VFS_FTP_METHOD_PASV, - G_VFS_FTP_METHOD_PASV_ADDR, G_VFS_FTP_METHOD_EPRT, G_VFS_FTP_METHOD_PORT } GVfsFtpMethod; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsbackendgoogle.c new/gvfs-1.58.2/daemon/gvfsbackendgoogle.c --- old/gvfs-1.58.1/daemon/gvfsbackendgoogle.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsbackendgoogle.c 2026-02-28 09:23:14.000000000 +0100 @@ -1221,11 +1221,11 @@ /* ---------------------------------------------------------------------------------------------------- */ -static char * +static const char * get_extension_offset (const char *title) { - gchar *end; - gchar *end2; + const gchar *end; + const gchar *end2; end = strrchr (title, '.'); @@ -1257,7 +1257,7 @@ const gchar *id; const gchar *title; gchar *extension = NULL; - gchar *extension_offset; + const gchar *extension_offset; gchar *ret_val = NULL; gchar *title_without_extension = NULL; @@ -1276,7 +1276,7 @@ if (extension_offset != NULL && extension_offset != title_without_extension) { extension = g_strdup (extension_offset); - *extension_offset = '\0'; + title_without_extension[extension_offset - title_without_extension] = '\0'; } id = gdata_entry_get_id (entry); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsbackendgphoto2.c new/gvfs-1.58.2/daemon/gvfsbackendgphoto2.c --- old/gvfs-1.58.1/daemon/gvfsbackendgphoto2.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsbackendgphoto2.c 2026-02-28 09:23:14.000000000 +0100 @@ -259,7 +259,7 @@ gboolean is_dirty; } WriteHandle; -/* how much more memory to ask for when using g_realloc() when writing a file */ +/* how much more memory to ask for when using g_try_realloc() when writing a file */ #define WRITE_INCREMENT 4096 typedef struct { @@ -2857,8 +2857,20 @@ if (handle->cursor + buffer_size > handle->allocated_size) { unsigned long int new_allocated_size; + gchar *new_data; + new_allocated_size = ((handle->cursor + buffer_size) / WRITE_INCREMENT + 1) * WRITE_INCREMENT; - handle->data = g_realloc (handle->data, new_allocated_size); + new_data = g_try_realloc (handle->data, new_allocated_size); + if (new_data == NULL) + { + g_vfs_job_failed_literal (G_VFS_JOB (job), + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Error writing file")); + return; + } + + handle->data = g_steal_pointer (&new_data); handle->allocated_size = new_allocated_size; g_debug (" allocated_size is now %ld bytes)\n", handle->allocated_size); } @@ -2936,8 +2948,20 @@ if (size > handle->allocated_size) { unsigned long int new_allocated_size; + gchar *new_data; + new_allocated_size = (size / WRITE_INCREMENT + 1) * WRITE_INCREMENT; - handle->data = g_realloc (handle->data, new_allocated_size); + new_data = g_try_realloc (handle->data, new_allocated_size); + if (new_data == NULL) + { + g_vfs_job_failed_literal (G_VFS_JOB (job), + G_IO_ERROR, + G_IO_ERROR_FAILED, + _("Error writing file")); + return; + } + + handle->data = g_steal_pointer (&new_data); handle->allocated_size = new_allocated_size; g_debug (" allocated_size is now %ld bytes)\n", handle->allocated_size); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsbackendlocaltest.c new/gvfs-1.58.2/daemon/gvfsbackendlocaltest.c --- old/gvfs-1.58.1/daemon/gvfsbackendlocaltest.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsbackendlocaltest.c 2026-02-28 09:23:14.000000000 +0100 @@ -368,11 +368,14 @@ if (info2) { g_file_info_copy_into (info2, info); g_object_unref (info2); - g_object_unref (file); inject_error (backend, G_VFS_JOB (job), GVFS_JOB_QUERY_INFO); g_print ("(II) try_query_info success. \n"); } else g_print ("(EE) try_query_info failed. \n"); + + if (file) { + g_object_unref (file); + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsbackendsftp.c new/gvfs-1.58.2/daemon/gvfsbackendsftp.c --- old/gvfs-1.58.1/daemon/gvfsbackendsftp.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsbackendsftp.c 2026-02-28 09:23:14.000000000 +0100 @@ -805,8 +805,8 @@ get_hostname_from_line (const gchar *buffer, gchar **hostname_out) { - gchar *startpos; - gchar *endpos; + const gchar *startpos; + const gchar *endpos; /* Parse a line that looks like: "username@hostname's password:". */ @@ -828,9 +828,9 @@ gchar **hostname_out, gchar **fingerprint_out) { - gchar *pos; - gchar *startpos; - gchar *endpos; + const gchar *pos; + const gchar *startpos; + const gchar *endpos; gchar *hostname = NULL; gchar *fingerprint = NULL; @@ -886,7 +886,8 @@ gchar **hostname_out, gchar **ip_address_out) { - char *startpos, *endpos, *hostname; + const char *startpos, *endpos; + char *hostname; /* Parse a line that looks like: * Warning: the ECDSA/RSA host key for 'hostname' differs from the key for the IP address '...' @@ -982,7 +983,8 @@ static char * get_object_from_password_line (const char *password_line) { - char *chr, *ptr, *object = NULL; + const char *chr, *ptr; + char *object = NULL; if (g_str_has_prefix (password_line, "Enter passphrase for key")) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsbackendsmbbrowse.c new/gvfs-1.58.2/daemon/gvfsbackendsmbbrowse.c --- old/gvfs-1.58.1/daemon/gvfsbackendsmbbrowse.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsbackendsmbbrowse.c 2026-02-28 09:23:14.000000000 +0100 @@ -491,7 +491,7 @@ { BrowseEntry *entry, *found; GList *l; - char *end; + const char *end; int len; char *normalized; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsftpdircache.c new/gvfs-1.58.2/daemon/gvfsftpdircache.c --- old/gvfs-1.58.1/daemon/gvfsftpdircache.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsftpdircache.c 2026-02-28 09:23:14.000000000 +0100 @@ -254,7 +254,7 @@ link = g_vfs_ftp_file_copy (file); do { target = g_file_info_get_symlink_target (info); - if (target == NULL) + if (target == NULL || target[0] == '\0') { /* This happens when bad servers don't report a symlink target. * We now want to figure out if this is a directory or regular file, @@ -519,6 +519,7 @@ g_file_info_set_name (info, tmp); g_free (tmp); + g_file_info_set_is_symlink (info, FALSE); gvfs_file_info_populate_default (info, g_vfs_ftp_file_get_gvfs_path (file), G_FILE_TYPE_DIRECTORY); g_file_info_set_is_hidden (info, TRUE); @@ -537,6 +538,7 @@ g_file_info_set_name (info, tmp); g_free (tmp); + g_file_info_set_is_symlink (info, FALSE); gvfs_file_info_populate_default (info, g_vfs_ftp_file_get_gvfs_path (file), G_FILE_TYPE_REGULAR); g_file_info_set_size (info, g_ascii_strtoull (reply[0] + 4, NULL, 0)); @@ -713,7 +715,12 @@ { char *link; - link = g_strndup (result.fe_lname, result.fe_lnlen); + /* Malformed listing may leave fe_lname NULL / fe_lnlen 0 */ + if (result.fe_lname != NULL && result.fe_lnlen > 0) + link = g_strndup (result.fe_lname, result.fe_lnlen); + else + link = g_strdup (""); + g_file_info_set_symlink_target (info, link); g_file_info_set_is_symlink (info, TRUE); g_free (link); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsftpfile.c new/gvfs-1.58.2/daemon/gvfsftpfile.c --- old/gvfs-1.58.1/daemon/gvfsftpfile.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsftpfile.c 2026-02-28 09:23:14.000000000 +0100 @@ -68,19 +68,29 @@ * g_vfs_ftp_file_new_from_gvfs: * @ftp: the ftp backend this file is to be used on * @gvfs_path: gvfs path to create the file from + * @error: location to take an eventual error or %NULL * - * Constructs a new #GVfsFtpFile representing the given gvfs path. + * Constructs a new #GVfsFtpFile representing the given gvfs path. If the + * display name is invalid, @error is set and %NULL is returned. * - * Returns: a new file + * Returns: a new file or %NULL on error **/ GVfsFtpFile * -g_vfs_ftp_file_new_from_gvfs (GVfsBackendFtp *ftp, const char *gvfs_path) +g_vfs_ftp_file_new_from_gvfs (GVfsBackendFtp *ftp, const char *gvfs_path, GError **error) { GVfsFtpFile *file; g_return_val_if_fail (G_VFS_IS_BACKEND_FTP (ftp), NULL); g_return_val_if_fail (gvfs_path != NULL, NULL); + if (strpbrk (gvfs_path, "\r\n") != NULL) + { + g_set_error_literal (error, + G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, + _("Filename contains invalid characters.")); + return NULL; + } + file = g_slice_new (GVfsFtpFile); file->backend = g_object_ref (ftp); file->gvfs_path = g_strdup (gvfs_path); @@ -136,7 +146,7 @@ return g_vfs_ftp_file_copy (file); dirname = g_path_get_dirname (file->gvfs_path); - dir = g_vfs_ftp_file_new_from_gvfs (file->backend, dirname); + dir = g_vfs_ftp_file_new_from_gvfs (file->backend, dirname, NULL); g_free (dirname); return dir; @@ -163,7 +173,7 @@ g_return_val_if_fail (parent != NULL, NULL); g_return_val_if_fail (display_name != NULL, NULL); - if (strpbrk (display_name, "/\r\n")) + if (strchr (display_name, '/') != NULL) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, @@ -172,7 +182,7 @@ } new_path = g_strconcat (parent->gvfs_path, parent->gvfs_path[1] == 0 ? "" : "/", display_name, NULL); - child = g_vfs_ftp_file_new_from_gvfs (parent->backend, new_path); + child = g_vfs_ftp_file_new_from_gvfs (parent->backend, new_path, error); g_free (new_path); return child; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsftpfile.h new/gvfs-1.58.2/daemon/gvfsftpfile.h --- old/gvfs-1.58.1/daemon/gvfsftpfile.h 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsftpfile.h 2026-02-28 09:23:14.000000000 +0100 @@ -27,9 +27,9 @@ G_BEGIN_DECLS - GVfsFtpFile * g_vfs_ftp_file_new_from_gvfs (GVfsBackendFtp * ftp, - const char * gvfs_path); + const char * gvfs_path, + GError ** error); GVfsFtpFile * g_vfs_ftp_file_new_from_ftp (GVfsBackendFtp * ftp, const char * ftp_path); GVfsFtpFile * g_vfs_ftp_file_new_parent (const GVfsFtpFile * file); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsftptask.c new/gvfs-1.58.2/daemon/gvfsftptask.c --- old/gvfs-1.58.1/daemon/gvfsftptask.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsftptask.c 2026-02-28 09:23:14.000000000 +0100 @@ -795,20 +795,29 @@ { GSocketAddress *old, *new; GInetSocketAddress *old_inet; + GInetAddress *old_addr; old = g_vfs_ftp_connection_get_address (task->conn, &task->error); if (old == NULL) return NULL; g_assert (G_IS_INET_SOCKET_ADDRESS (old)); old_inet = G_INET_SOCKET_ADDRESS (old); + old_addr = g_inet_socket_address_get_address (old_inet); - new = g_object_new (G_TYPE_INET_SOCKET_ADDRESS, - "address", g_inet_socket_address_get_address (old_inet), - "port", port, - "flowinfo", g_inet_socket_address_get_flowinfo (old_inet), - "scope-id", g_inet_socket_address_get_scope_id (old_inet), - NULL); + if (g_inet_address_get_family (old_addr) == G_SOCKET_FAMILY_IPV6) + new = g_object_new (G_TYPE_INET_SOCKET_ADDRESS, + "address", old_addr, + "port", port, + "flowinfo", g_inet_socket_address_get_flowinfo (old_inet), + "scope-id", g_inet_socket_address_get_scope_id (old_inet), + NULL); + else + new = g_object_new (G_TYPE_INET_SOCKET_ADDRESS, + "address", old_addr, + "port", port, + NULL); + g_object_unref (old); return new; } @@ -858,7 +867,7 @@ static GVfsFtpMethod g_vfs_ftp_task_setup_data_connection_pasv (GVfsFtpTask *task, GVfsFtpMethod method) { - guint ip1, ip2, ip3, ip4, port1, port2; + guint port1, port2; char **reply; const char *s; GSocketAddress *addr; @@ -874,10 +883,8 @@ */ for (s = reply[0]; *s; s++) { - if (sscanf (s, "%u,%u,%u,%u,%u,%u", - &ip1, &ip2, &ip3, &ip4, - &port1, &port2) == 6) - break; + if (sscanf (s, "%*u,%*u,%*u,%*u,%u,%u", &port1, &port2) == 2) + break; } if (*s == 0) { @@ -888,52 +895,16 @@ } g_strfreev (reply); - if (method == G_VFS_FTP_METHOD_PASV || method == G_VFS_FTP_METHOD_ANY) - { - guint8 ip[4]; - GInetAddress *inet_addr; - - ip[0] = ip1; - ip[1] = ip2; - ip[2] = ip3; - ip[3] = ip4; - inet_addr = g_inet_address_new_from_bytes (ip, G_SOCKET_FAMILY_IPV4); - addr = g_inet_socket_address_new (inet_addr, port1 << 8 | port2); - g_object_unref (inet_addr); - - success = g_vfs_ftp_connection_open_data_connection (task->conn, - addr, - task->cancellable, - &task->error); - g_object_unref (addr); - if (success) - return G_VFS_FTP_METHOD_PASV; - if (g_vfs_ftp_task_is_in_error (task) && method != G_VFS_FTP_METHOD_ANY) - return G_VFS_FTP_METHOD_ANY; - - g_vfs_ftp_task_clear_error (task); - } - - if (method == G_VFS_FTP_METHOD_PASV_ADDR || method == G_VFS_FTP_METHOD_ANY) - { - /* Workaround code: - * Various ftp servers aren't setup correctly when behind a NAT. They report - * their own IP address (like 10.0.0.4) and not the address in front of the - * NAT. But this is likely the same address that we connected to with our - * command connetion. So if the address given by PASV fails, we fall back - * to the address of the command stream. - */ - addr = g_vfs_ftp_task_create_remote_address (task, port1 << 8 | port2); - if (addr == NULL) - return G_VFS_FTP_METHOD_ANY; - success = g_vfs_ftp_connection_open_data_connection (task->conn, - addr, - task->cancellable, - &task->error); - g_object_unref (addr); - if (success) - return G_VFS_FTP_METHOD_PASV_ADDR; - } + addr = g_vfs_ftp_task_create_remote_address (task, port1 << 8 | port2); + if (addr == NULL) + return G_VFS_FTP_METHOD_ANY; + success = g_vfs_ftp_connection_open_data_connection (task->conn, + addr, + task->cancellable, + &task->error); + g_object_unref (addr); + if (success) + return G_VFS_FTP_METHOD_PASV; return G_VFS_FTP_METHOD_ANY; } @@ -1129,7 +1100,6 @@ [G_VFS_FTP_METHOD_ANY] = g_vfs_ftp_task_setup_data_connection_any, [G_VFS_FTP_METHOD_EPSV] = g_vfs_ftp_task_setup_data_connection_epsv, [G_VFS_FTP_METHOD_PASV] = g_vfs_ftp_task_setup_data_connection_pasv, - [G_VFS_FTP_METHOD_PASV_ADDR] = g_vfs_ftp_task_setup_data_connection_pasv, [G_VFS_FTP_METHOD_EPRT] = g_vfs_ftp_task_setup_data_connection_eprt, [G_VFS_FTP_METHOD_PORT] = g_vfs_ftp_task_setup_data_connection_port }; @@ -1160,7 +1130,6 @@ [G_VFS_FTP_METHOD_ANY] = "any", [G_VFS_FTP_METHOD_EPSV] = "EPSV", [G_VFS_FTP_METHOD_PASV] = "PASV", - [G_VFS_FTP_METHOD_PASV_ADDR] = "PASV with workaround", [G_VFS_FTP_METHOD_EPRT] = "EPRT", [G_VFS_FTP_METHOD_PORT] = "PORT" }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/daemon/gvfsmonitor.c new/gvfs-1.58.2/daemon/gvfsmonitor.c --- old/gvfs-1.58.1/daemon/gvfsmonitor.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/daemon/gvfsmonitor.c 2026-02-28 09:23:14.000000000 +0100 @@ -57,6 +57,7 @@ GMountSpec *mount_spec; char *object_path; GList *subscribers; + GMutex subscribers_lock; }; /* atomic */ @@ -64,6 +65,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (GVfsMonitor, g_vfs_monitor, G_TYPE_OBJECT) +/* Must be called with monitor->priv->subscribers_lock held. */ static void unsubscribe (Subscriber *subscriber); static void @@ -81,12 +83,15 @@ monitor->priv->backend = NULL; + g_mutex_lock (&monitor->priv->subscribers_lock); + while (monitor->priv->subscribers != NULL) { subscriber = monitor->priv->subscribers->data; unsubscribe (subscriber); } + g_mutex_unlock (&monitor->priv->subscribers_lock); g_object_unref (G_OBJECT (monitor)); } @@ -108,6 +113,8 @@ g_mount_spec_unref (monitor->priv->mount_spec); g_free (monitor->priv->object_path); + + g_mutex_clear (&monitor->priv->subscribers_lock); if (G_OBJECT_CLASS (g_vfs_monitor_parent_class)->finalize) (*G_OBJECT_CLASS (g_vfs_monitor_parent_class)->finalize) (object); @@ -130,6 +137,8 @@ id = g_atomic_int_add (&path_counter, 1); monitor->priv->object_path = g_strdup_printf (OBJ_PATH_PREFIX"%d", id); + + g_mutex_init (&monitor->priv->subscribers_lock); } static gboolean @@ -164,7 +173,13 @@ GError *error, Subscriber *subscriber) { + GVfsMonitor *monitor = subscriber->monitor; + + g_object_ref (monitor); /* Keep alive during possible last remove */ + g_mutex_lock (&monitor->priv->subscribers_lock); unsubscribe (subscriber); + g_mutex_unlock (&monitor->priv->subscribers_lock); + g_object_unref (monitor); } static gboolean @@ -183,7 +198,9 @@ g_signal_connect (subscriber->connection, "closed", G_CALLBACK (subscriber_connection_closed), subscriber); + g_mutex_lock (&monitor->priv->subscribers_lock); monitor->priv->subscribers = g_list_prepend (monitor->priv->subscribers, subscriber); + g_mutex_unlock (&monitor->priv->subscribers_lock); gvfs_dbus_monitor_complete_subscribe (object, invocation); @@ -200,6 +217,8 @@ GList *l; g_object_ref (monitor); /* Keep alive during possible last remove */ + g_mutex_lock (&monitor->priv->subscribers_lock); + for (l = monitor->priv->subscribers; l != NULL; l = l->next) { subscriber = l->data; @@ -213,6 +232,8 @@ break; } } + + g_mutex_unlock (&monitor->priv->subscribers_lock); g_object_unref (monitor); gvfs_dbus_monitor_complete_unsubscribe (object, invocation); @@ -350,6 +371,8 @@ GList *l; Subscriber *subscriber; + g_mutex_lock (&monitor->priv->subscribers_lock); + for (l = monitor->priv->subscribers; l != NULL; l = l->next) { EmitEventData *data; @@ -370,4 +393,6 @@ (GAsyncReadyCallback) got_proxy_cb, data); } + + g_mutex_unlock (&monitor->priv->subscribers_lock); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/meson.build new/gvfs-1.58.2/meson.build --- old/gvfs-1.58.1/meson.build 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/meson.build 2026-02-28 09:23:14.000000000 +0100 @@ -1,6 +1,6 @@ project( 'gvfs', 'c', - version: '1.58.1', + version: '1.58.2', license: 'LGPL2+', default_options: [ 'buildtype=debugoptimized', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gvfs-1.58.1/metadata/metatree.c new/gvfs-1.58.2/metadata/metatree.c --- old/gvfs-1.58.1/metadata/metatree.c 2026-01-31 06:06:48.000000000 +0100 +++ new/gvfs-1.58.2/metadata/metatree.c 2026-02-28 09:23:14.000000000 +0100 @@ -2946,13 +2946,14 @@ static char * mountinfo_unescape (const char *escaped) { + const char *p; char *res, *s; char c; gsize len; - s = strchr (escaped, ' '); - if (s) - len = s - escaped; + p = strchr (escaped, ' '); + if (p) + len = p - escaped; else len = strlen (escaped); res = malloc (len + 1); ++++++ gvfs.obsinfo ++++++ --- /var/tmp/diff_new_pack.bfRxDl/_old 2026-03-01 22:14:41.665641796 +0100 +++ /var/tmp/diff_new_pack.bfRxDl/_new 2026-03-01 22:14:41.669641960 +0100 @@ -1,5 +1,5 @@ name: gvfs -version: 1.58.1 -mtime: 1769836008 -commit: ccc115dbc973f2b5146289c95f3357766347bad4 +version: 1.58.2 +mtime: 1772266994 +commit: e6a4bf609bfbef0dc25fa41050963bdceed9be44
