From 417b25a2d5d5b71800c6ae77ebc37cefe893be53 Mon Sep 17 00:00:00 2001 From: Azure Linux Security Servicing Account Date: Sun, 30 Aug 2026 20:26:43 +0000 Subject: [PATCH 1/2] Patch emacs for CVE-2026-79992 --- SPECS/emacs/CVE-2026-79992.patch | 324 +++++++++++++++++++++++++++++++ SPECS/emacs/emacs.spec | 6 +- 2 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 SPECS/emacs/CVE-2026-79992.patch diff --git a/SPECS/emacs/CVE-2026-79992.patch b/SPECS/emacs/CVE-2026-79992.patch new file mode 100644 index 00000000000..3bce92d7e69 --- /dev/null +++ b/SPECS/emacs/CVE-2026-79992.patch @@ -0,0 +1,324 @@ +From f39b1124616c17ff8eaf6330aa466b16c51e8eeb Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Sun, 30 Aug 2026 20:19:33 +0000 +Subject: [PATCH] Restrict Tramp user name + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://cgit.git.savannah.gnu.org/cgit/emacs.git/patch/?id=f3e7104d05bdb8e32ba13bf75604108ad88536dc +--- + doc/misc/tramp.texi | 4 ++- + lisp/net/tramp-gvfs.el | 26 ++++++++------ + lisp/net/tramp-rclone.el | 4 +-- + lisp/net/tramp-smb.el | 4 +-- + lisp/net/tramp.el | 4 ++- + test/lisp/net/tramp-tests.el | 69 ++++++++++++++++++++++++++++++++++++ + 6 files changed, 94 insertions(+), 17 deletions(-) + +diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi +index 0bed7db..4573218 100644 +--- a/doc/misc/tramp.texi ++++ b/doc/misc/tramp.texi +@@ -3420,7 +3420,9 @@ brackets @file{@value{ipv6prefix}} and @file{@value{ipv6postfix}}. + By default, @value{tramp} will use the current local user name as the + remote user name for log in to the remote host. Specifying a + different name using the proper syntax will override this default +-behavior: @file{@trampfn{method,user@@host,path/to/file}}. ++behavior: @file{@trampfn{method,user@@host,path/to/file}}. The user ++name can also be taken from an environment variable, like ++@file{@trampfn{method,@env{$MY_REMOTE_USER}@@host,path/to/file}}. + + @file{@trampfn{ssh,daniel@@melancholia,.emacs}} is for file + @file{.emacs} in @code{daniel}'s home directory on the host, +diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el +index 2ccba85..f1662d2 100644 +--- a/lisp/net/tramp-gvfs.el ++++ b/lisp/net/tramp-gvfs.el +@@ -1202,7 +1202,7 @@ file names." + (tramp-compat-rx bos "/" (+ (not "/")) (group "/.." (? "/"))) + localname) + (setq localname (replace-match "/" t t localname 1))) +- (when (string-match (rx bol "/.." (? "/")) localname) ++ (when (string-match (rx bos "/.." (? "/")) localname) + (setq localname (replace-match "/" t t localname)))) + ;; There might be a double slash. Remove this. + (while (string-match "//" localname) +@@ -1296,7 +1296,7 @@ If FILE-SYSTEM is non-nil, return file system attributes." + (with-parsed-tramp-file-name filename nil + (setq localname (tramp-compat-file-name-unquote localname)) + (if (or (and (string-match-p +- (rx bol (| "afp" (: "dav" (? "s")) "smb") eol) method) ++ (rx bos (| "afp" (: "dav" (? "s")) "smb") eos) method) + (string-match-p + (tramp-compat-rx bol (? "/") (+ (not "/")) eol) localname)) + (string-equal localname "/")) +@@ -1332,7 +1332,11 @@ If FILE-SYSTEM is non-nil, return file system attributes." + (lambda (x) + (unibyte-string (string-to-number (match-string 1 x) 16))) + res-symlink-target) +- 'utf-8))) ++ 'utf-8)) ++ ;; If the resulting localname looks remote, we must quote it ++ ;; for security reasons. ++ (when (tramp-tramp-file-p res-symlink-target) ++ (setq res-symlink-target (file-name-quote res-symlink-target 'top)))) + ;; ... number links + (setq res-numlinks + (string-to-number +@@ -1763,7 +1767,7 @@ ID-FORMAT valid values are `string' and `integer'." + We cannot use `url-host', because `url-generic-parse-url' returns + a downcased host name only." + (and (stringp url) +- (string-match (rx bol (+ alnum) "://" (group (+ (not (any "/:"))))) url) ++ (string-match (rx bos (+ alnum) "://" (group (+ (not (any "/:"))))) url) + (match-string 1 url))) + + +@@ -1899,7 +1903,7 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and + (cadr (assoc "ssl" (cadr mount-spec))))) + (uri (tramp-gvfs-dbus-byte-array-to-string + (cadr (assoc "uri" (cadr mount-spec)))))) +- (when (string-match (rx bol (group (| "afp" "smb"))) method) ++ (when (string-match (rx bos (group (| "afp" "smb"))) method) + (setq method (match-string 1 method))) + (when (and (string-equal "dav" method) (string-equal "true" ssl)) + (setq method "davs")) +@@ -1999,7 +2003,7 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and + (or + (cadr (assoc "share" (cadr mount-spec))) + (cadr (assoc "volume" (cadr mount-spec))))))) +- (when (string-match (rx bol (group (| "afp" "smb"))) method) ++ (when (string-match (rx bos (group (| "afp" "smb"))) method) + (setq method (match-string 1 method))) + (when (and (string-equal "dav" method) (string-equal "true" ssl)) + (setq method "davs")) +@@ -2058,7 +2062,7 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and + (defun tramp-gvfs-mount-spec-entry (key value) + "Construct a mount-spec entry to be used in a mount_spec. + It was \"a(say)\", but has changed to \"a{sv})\"." +- (if (string-match-p (rx bol "(aya{sv})") tramp-gvfs-mountlocation-signature) ++ (if (string-match-p (rx bos "(aya{sv})") tramp-gvfs-mountlocation-signature) + (list :dict-entry key + (list :variant (tramp-gvfs-dbus-string-to-byte-array value))) + (list :struct key (tramp-gvfs-dbus-string-to-byte-array value)))) +@@ -2080,7 +2084,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"." + (tramp-compat-rx bol (? "/") (group (+ (not "/")))) + localname) + (match-string 1 localname))) +- (ssl (if (string-match-p (rx bol (| "davs" "nextcloud")) method) ++ (ssl (if (string-match-p (rx bos (| "davs" "nextcloud")) method) + "true" "false")) + (mount-spec + `(:array +@@ -2089,7 +2093,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"." + (list (tramp-gvfs-mount-spec-entry "type" "smb-share") + (tramp-gvfs-mount-spec-entry "server" host) + (tramp-gvfs-mount-spec-entry "share" share))) +- ((string-match-p (rx bol (| "davs" "nextcloud")) method) ++ ((string-match-p (rx bos (| "davs" "nextcloud")) method) + (list (tramp-gvfs-mount-spec-entry "type" "dav") + (tramp-gvfs-mount-spec-entry "host" host) + (tramp-gvfs-mount-spec-entry "ssl" ssl))) +@@ -2103,7 +2107,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"." + ((string-equal "nextcloud" method) + (list (tramp-gvfs-mount-spec-entry "type" "owncloud") + (tramp-gvfs-mount-spec-entry "host" host))) +- ((string-match-p (rx bol "http") method) ++ ((string-match-p (rx bos "http") method) + (list (tramp-gvfs-mount-spec-entry "type" "http") + (tramp-gvfs-mount-spec-entry + "uri" +@@ -2120,7 +2124,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"." + ,@(when port + (list (tramp-gvfs-mount-spec-entry "port" port))))) + (mount-pref +- (if (and (string-match-p (rx bol "dav") method) ++ (if (and (string-match-p (rx bos "dav") method) + (string-match + (tramp-compat-rx bol (? "/") (+ (not "/"))) localname)) + (match-string 0 localname) +diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el +index 6ebd17d..3aa63db 100644 +--- a/lisp/net/tramp-rclone.el ++++ b/lisp/net/tramp-rclone.el +@@ -188,7 +188,7 @@ arguments to pass to the OPERATION." + (delq nil + (mapcar + (lambda (line) +- (when (string-match (rx bol (group (+ (not blank))) ":" eol) line) ++ (when (string-match (rx bos (group (+ (not blank))) ":" eos) line) + `(nil ,(match-string 1 line)))) + (tramp-process-lines nil tramp-rclone-program "listremotes"))))) + +@@ -362,7 +362,7 @@ file names." + (tramp-rclone-maybe-open-connection v) + ;; TODO: This shall be handled by `expand-file-name'. + (setq localname +- (replace-regexp-in-string (rx bol ".") "" (or localname ""))) ++ (replace-regexp-in-string (rx bos ".") "" (or localname ""))) + (format "%s%s" (tramp-fuse-mounted-p v) localname))) + ;; It is a local file name. + filename)) +diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el +index 6d5697a..2536e7f 100644 +--- a/lisp/net/tramp-smb.el ++++ b/lisp/net/tramp-smb.el +@@ -1650,7 +1650,7 @@ VEC or USER, or if there is no home directory, return nil." + (save-match-data + (let ((localname (tramp-file-name-unquote-localname vec))) + (when (string-match +- (tramp-compat-rx bol (? "/") (group (+ (not "/"))) "/") localname) ++ (tramp-compat-rx bos (? "/") (group (+ (not "/"))) "/") localname) + (match-string 1 localname))))) + + (defun tramp-smb-get-localname (vec) +@@ -1671,7 +1671,7 @@ If VEC has no cifs capabilities, exchange \"/\" by \"\\\\\"." + (match-string 1 localname)) + ;; There is just a share. + (if (string-match +- (tramp-compat-rx bol (? "/") (group (+ (not "/"))) eol) localname) ++ (tramp-compat-rx bos (? "/") (group (+ (not "/"))) eos) localname) + (match-string 1 localname) + ""))) + +diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el +index 2d6db31..5f15652 100644 +--- a/lisp/net/tramp.el ++++ b/lisp/net/tramp.el +@@ -1735,6 +1735,8 @@ default values are used." + (hop (match-string (nth 5 tramp-file-name-structure) name)) + domain port v) + (when user ++ (while (string-match (rx bos "$" (group (+ (any "_" alnum))) eos) user) ++ (setq user (getenv (match-string 1 user)))) + (when (string-match tramp-user-with-domain-regexp user) + (setq domain (match-string 2 user) + user (match-string 1 user)))) +@@ -2753,9 +2755,9 @@ Fall back to normal file name handler if no Tramp file name handler exists." + ;; `file-remote-p' is called for everything, even for symbolic + ;; links which look remote. We don't want to get an error. + (non-essential (or non-essential (eq operation 'file-remote-p)))) ++ (setq filename (tramp-replace-environment-variables filename)) + (if (tramp-tramp-file-p filename) + (save-match-data +- (setq filename (tramp-replace-environment-variables filename)) + (with-parsed-tramp-file-name filename nil + (let ((current-connection tramp-current-connection) + (foreign +diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el +index 465afa8..124c0fc 100644 +--- a/test/lisp/net/tramp-tests.el ++++ b/test/lisp/net/tramp-tests.el +@@ -330,6 +330,7 @@ Also see `ignore'." + (should (tramp-tramp-file-p "/method:user@:")) + (should (tramp-tramp-file-p "/method:user@host:")) + (should (tramp-tramp-file-p "/method:user@email@host:")) ++ (should (tramp-tramp-file-p "/method:$USER@host:")) + + ;; Using a port. + (should (tramp-tramp-file-p "/method:host#1234:")) +@@ -418,6 +419,7 @@ Also see `ignore'." + (should (tramp-tramp-file-p "/user@:")) + (should (tramp-tramp-file-p "/user@host:")) + (should (tramp-tramp-file-p "/user@email@host:")) ++ (should (tramp-tramp-file-p "/$USER@host:")) + + ;; Using a port. + (should (tramp-tramp-file-p "/host#1234:")) +@@ -472,6 +474,7 @@ Also see `ignore'." + (should (tramp-tramp-file-p "/[method/user@]")) + (should (tramp-tramp-file-p "/[method/user@host]")) + (should (tramp-tramp-file-p "/[method/user@email@host]")) ++ (should (tramp-tramp-file-p "/[method/$USER@host]")) + + ;; Using a port. + (should (tramp-tramp-file-p "/[method/host#1234]")) +@@ -652,6 +655,28 @@ Also see `ignore'." + (should (string-equal + (file-remote-p "/method:user@email@host:" 'hop) nil)) + ++ ;; Expand environment variable. It can be cascaded. ++ (with-environment-variables ++ (("REMOTE_USER" "$REMOTE_USER1") ("REMOTE_USER1" "remote-user")) ++ (should (string-equal ++ (file-remote-p "/method:$REMOTE_USER@host:") ++ (format "/%s:%s@%s:" "method" "remote-user" "host"))) ++ (should ++ (string-equal ++ (file-remote-p "/method:$REMOTE_USER@host:" 'method) "method")) ++ (should ++ (string-equal ++ (file-remote-p "/method:$REMOTE_USER@host:" 'user) "remote-user")) ++ (should ++ (string-equal ++ (file-remote-p "/method:$REMOTE_USER@host:" 'host) "host")) ++ (should ++ (string-equal ++ (file-remote-p "/method:$REMOTE_USER@host:" 'localname) "")) ++ (should ++ (string-equal ++ (file-remote-p "/method:$REMOTE_USER@host:" 'hop) nil))) ++ + ;; Expand `tramp-default-method' and `tramp-default-user'. + (should + (string-equal +@@ -1131,6 +1156,28 @@ Also see `ignore'." + (should (string-equal + (file-remote-p "/user@email@host:" 'hop) nil)) + ++ ;; Expand environment variable. It can be cascaded. ++ (with-environment-variables ++ (("REMOTE_USER" "$REMOTE_USER1") ("REMOTE_USER1" "remote-user")) ++ (should (string-equal ++ (file-remote-p "/$REMOTE_USER@host:") ++ (format "/%s@%s:" "remote-user" "host"))) ++ (should ++ (string-equal ++ (file-remote-p "/$REMOTE_USER@host:" 'method) "default-method")) ++ (should ++ (string-equal ++ (file-remote-p "/$REMOTE_USER@host:" 'user) "remote-user")) ++ (should ++ (string-equal ++ (file-remote-p "/$REMOTE_USER@host:" 'host) "host")) ++ (should ++ (string-equal ++ (file-remote-p "/$REMOTE_USER@host:" 'localname) "")) ++ (should ++ (string-equal ++ (file-remote-p "/$REMOTE_USER@host:" 'hop) nil))) ++ + ;; Expand `tramp-default-method' and `tramp-default-user'. + (should (string-equal + (file-remote-p "/host#1234:") +@@ -1583,6 +1630,28 @@ Also see `ignore'." + (should (string-equal + (file-remote-p "/[method/user@email@host]" 'hop) nil)) + ++ ;; Expand environment variable. It can be cascaded. ++ (with-environment-variables ++ (("REMOTE_USER" "$REMOTE_USER1") ("REMOTE_USER1" "remote-user")) ++ (should (string-equal ++ (file-remote-p "/[method/$REMOTE_USER@host]") ++ (format "/[%s/%s@%s]" "method" "remote-user" "host"))) ++ (should ++ (string-equal ++ (file-remote-p "/[method/$REMOTE_USER@host]" 'method) "method")) ++ (should ++ (string-equal ++ (file-remote-p "/[method/$REMOTE_USER@host]" 'user) "remote-user")) ++ (should ++ (string-equal ++ (file-remote-p "/[method/$REMOTE_USER@host]" 'host) "host")) ++ (should ++ (string-equal ++ (file-remote-p "/[method/$REMOTE_USER@host]" 'localname) "")) ++ (should ++ (string-equal ++ (file-remote-p "/[method/$REMOTE_USER@host]" 'hop) nil))) ++ + ;; Expand `tramp-default-method' and `tramp-default-user'. + (should (string-equal + (file-remote-p "/[/host#1234]") +-- +2.45.4 + diff --git a/SPECS/emacs/emacs.spec b/SPECS/emacs/emacs.spec index 332863e164b..2b6215fdfee 100644 --- a/SPECS/emacs/emacs.spec +++ b/SPECS/emacs/emacs.spec @@ -1,7 +1,7 @@ Summary: GNU Emacs text editor Name: emacs Version: 29.4 -Release: 4%{?dist} +Release: 5%{?dist} License: GPLv3+ AND CC0-1.0 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -13,6 +13,7 @@ Source2: default.el Patch0: CVE-2025-1244.patch Patch1: CVE-2024-53920.patch Patch2: CVE-2026-6861.patch +Patch3: CVE-2026-79992.patch BuildRequires: gcc BuildRequires: glibc-devel BuildRequires: gnutls-devel @@ -131,6 +132,9 @@ rm -f *-filelist {common,el}-*-files %dir %{_datadir}/emacs/site-lisp/site-start.d %changelog +* Sun Aug 30 2026 Azure Linux Security Servicing Account - 29.4-5 +- Patch for CVE-2026-79992 + * Wed Apr 29 2026 Azure Linux Security Servicing Account - 29.4-4 - Patch for CVE-2026-6861 From 44df4ba3219f5fae4d16803c3158bff6b2cb7c2e Mon Sep 17 00:00:00 2001 From: Durga Jagadeesh Palli Date: Mon, 31 Aug 2026 12:21:03 +0000 Subject: [PATCH 2/2] update patch --- SPECS/emacs/CVE-2026-79992.patch | 224 +++++++++++++------------------ 1 file changed, 91 insertions(+), 133 deletions(-) diff --git a/SPECS/emacs/CVE-2026-79992.patch b/SPECS/emacs/CVE-2026-79992.patch index 3bce92d7e69..c84061e1ea3 100644 --- a/SPECS/emacs/CVE-2026-79992.patch +++ b/SPECS/emacs/CVE-2026-79992.patch @@ -5,14 +5,14 @@ Subject: [PATCH] Restrict Tramp user name Signed-off-by: Azure Linux Security Servicing Account Upstream-reference: AI Backport of https://cgit.git.savannah.gnu.org/cgit/emacs.git/patch/?id=f3e7104d05bdb8e32ba13bf75604108ad88536dc + --- - doc/misc/tramp.texi | 4 ++- - lisp/net/tramp-gvfs.el | 26 ++++++++------ - lisp/net/tramp-rclone.el | 4 +-- - lisp/net/tramp-smb.el | 4 +-- - lisp/net/tramp.el | 4 ++- - test/lisp/net/tramp-tests.el | 69 ++++++++++++++++++++++++++++++++++++ - 6 files changed, 94 insertions(+), 17 deletions(-) + doc/misc/tramp.texi | 4 +++- + lisp/net/tramp-gvfs.el | 36 ++++++++++++++++++++---------------- + lisp/net/tramp-rclone.el | 4 ++-- + lisp/net/tramp-smb.el | 6 +++--- + lisp/net/tramp.el | 16 ++++++++++++---- + 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 0bed7db..4573218 100644 @@ -30,7 +30,7 @@ index 0bed7db..4573218 100644 @file{@trampfn{ssh,daniel@@melancholia,.emacs}} is for file @file{.emacs} in @code{daniel}'s home directory on the host, diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el -index 2ccba85..f1662d2 100644 +index 2ccba85..5081a81 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1202,7 +1202,7 @@ file names." @@ -42,15 +42,18 @@ index 2ccba85..f1662d2 100644 (setq localname (replace-match "/" t t localname)))) ;; There might be a double slash. Remove this. (while (string-match "//" localname) -@@ -1296,7 +1296,7 @@ If FILE-SYSTEM is non-nil, return file system attributes." +@@ -1296,9 +1296,9 @@ If FILE-SYSTEM is non-nil, return file system attributes." (with-parsed-tramp-file-name filename nil (setq localname (tramp-compat-file-name-unquote localname)) (if (or (and (string-match-p - (rx bol (| "afp" (: "dav" (? "s")) "smb") eol) method) + (rx bos (| "afp" (: "dav" (? "s")) "smb") eos) method) (string-match-p - (tramp-compat-rx bol (? "/") (+ (not "/")) eol) localname)) +- (tramp-compat-rx bol (? "/") (+ (not "/")) eol) localname)) ++ (tramp-compat-rx bos (? "/") (+ (not "/")) eos) localname)) (string-equal localname "/")) + (tramp-gvfs-get-root-attributes filename) + (assoc @@ -1332,7 +1332,11 @@ If FILE-SYSTEM is non-nil, return file system attributes." (lambda (x) (unibyte-string (string-to-number (match-string 1 x) 16))) @@ -64,6 +67,15 @@ index 2ccba85..f1662d2 100644 ;; ... number links (setq res-numlinks (string-to-number +@@ -1755,7 +1759,7 @@ ID-FORMAT valid values are `string' and `integer'." + "Retrieve file name from D-Bus OBJECT-PATH." + (dbus-unescape-from-identifier + (replace-regexp-in-string +- (tramp-compat-rx bol (* nonl) "/" (group (+ (not "/"))) eol) "\\1" ++ (tramp-compat-rx bos (* nonl) "/" (group (+ (not "/"))) eos) "\\1" + object-path))) + + (defun tramp-gvfs-url-host (url) @@ -1763,7 +1767,7 @@ ID-FORMAT valid values are `string' and `integer'." We cannot use `url-host', because `url-generic-parse-url' returns a downcased host name only." @@ -91,6 +103,15 @@ index 2ccba85..f1662d2 100644 (setq method (match-string 1 method))) (when (and (string-equal "dav" method) (string-equal "true" ssl)) (setq method "davs")) +@@ -2032,7 +2036,7 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and + (string-equal host (tramp-file-name-host vec)) + (string-equal port (tramp-file-name-port vec)) + (string-match-p +- (tramp-compat-rx bol "/" (literal (or share ""))) ++ (tramp-compat-rx bos "/" (literal (or share ""))) + (tramp-file-name-unquote-localname vec))) + ;; Set mountpoint and location. + (tramp-set-file-property vec "/" "fuse-mountpoint" fuse-mountpoint) @@ -2058,7 +2062,7 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and (defun tramp-gvfs-mount-spec-entry (key value) "Construct a mount-spec entry to be used in a mount_spec. @@ -100,8 +121,12 @@ index 2ccba85..f1662d2 100644 (list :dict-entry key (list :variant (tramp-gvfs-dbus-string-to-byte-array value))) (list :struct key (tramp-gvfs-dbus-string-to-byte-array value)))) -@@ -2080,7 +2084,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"." - (tramp-compat-rx bol (? "/") (group (+ (not "/")))) +@@ -2077,10 +2081,10 @@ It was \"a(say)\", but has changed to \"a{sv})\"." + (tramp-media-device-port media) (tramp-file-name-port vec))) + (localname (tramp-file-name-unquote-localname vec)) + (share (when (string-match +- (tramp-compat-rx bol (? "/") (group (+ (not "/")))) ++ (tramp-compat-rx bos (? "/") (group (+ (not "/")))) localname) (match-string 1 localname))) - (ssl (if (string-match-p (rx bol (| "davs" "nextcloud")) method) @@ -127,15 +152,18 @@ index 2ccba85..f1662d2 100644 (list (tramp-gvfs-mount-spec-entry "type" "http") (tramp-gvfs-mount-spec-entry "uri" -@@ -2120,7 +2124,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"." +@@ -2120,9 +2124,9 @@ It was \"a(say)\", but has changed to \"a{sv})\"." ,@(when port (list (tramp-gvfs-mount-spec-entry "port" port))))) (mount-pref - (if (and (string-match-p (rx bol "dav") method) + (if (and (string-match-p (rx bos "dav") method) (string-match - (tramp-compat-rx bol (? "/") (+ (not "/"))) localname)) +- (tramp-compat-rx bol (? "/") (+ (not "/"))) localname)) ++ (tramp-compat-rx bos (? "/") (+ (not "/"))) localname)) (match-string 0 localname) + (tramp-gvfs-get-remote-prefix vec)))) + diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el index 6ebd17d..3aa63db 100644 --- a/lisp/net/tramp-rclone.el @@ -159,7 +187,7 @@ index 6ebd17d..3aa63db 100644 ;; It is a local file name. filename)) diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el -index 6d5697a..2536e7f 100644 +index 6d5697a..d07b81d 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -1650,7 +1650,7 @@ VEC or USER, or if there is no home directory, return nil." @@ -171,6 +199,15 @@ index 6d5697a..2536e7f 100644 (match-string 1 localname))))) (defun tramp-smb-get-localname (vec) +@@ -1661,7 +1661,7 @@ If VEC has no cifs capabilities, exchange \"/\" by \"\\\\\"." + (setq + localname + (if (string-match +- (tramp-compat-rx bol (? "/") (+ (not "/")) (group "/" (* nonl))) ++ (tramp-compat-rx bos (? "/") (+ (not "/")) (group "/" (* nonl))) + localname) + ;; There is a share, separated by "/". + (if (not (tramp-smb-get-cifs-capabilities vec)) @@ -1671,7 +1671,7 @@ If VEC has no cifs capabilities, exchange \"/\" by \"\\\\\"." (match-string 1 localname)) ;; There is just a share. @@ -181,10 +218,36 @@ index 6d5697a..2536e7f 100644 ""))) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el -index 2d6db31..5f15652 100644 +index 2d6db31..66c8d95 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el -@@ -1735,6 +1735,8 @@ default values are used." +@@ -931,11 +931,11 @@ Used in `tramp-make-tramp-file-name'.") + + (defun tramp-build-prefix-regexp () + "Return `tramp-prefix-regexp'." +- (tramp-compat-rx bol (literal (tramp-build-prefix-format)))) ++ (tramp-compat-rx bos (literal (tramp-build-prefix-format)))) + + (defvar tramp-prefix-regexp nil ; Initialized when defining `tramp-syntax'! + "Regexp matching the very beginning of Tramp file names. +-Should always start with \"^\". Derived from `tramp-prefix-format'.") ++Should always start with \"\\\\=`\". Derived from `tramp-prefix-format'.") + + (defconst tramp-method-regexp-alist + `((default . ,(tramp-compat-rx +@@ -976,7 +976,10 @@ Used in `tramp-make-tramp-file-name'.") + "Regexp matching delimiter between method and user or host names. + Derived from `tramp-postfix-method-format'.") + +-(defconst tramp-user-regexp (rx (+ (not (any "/:|" blank)))) ++(defconst tramp-user-regexp ++ (rx (| (+ (not (any "/\\^$?*:;|[]{}()<>`'\"" blank))) ++ ;; Environment variable. ++ (: "$" (+ (any "_" alnum))))) + "Regexp matching user names.") + + (defconst tramp-prefix-domain-format "%" +@@ -1735,6 +1738,8 @@ default values are used." (hop (match-string (nth 5 tramp-file-name-structure) name)) domain port v) (when user @@ -193,7 +256,7 @@ index 2d6db31..5f15652 100644 (when (string-match tramp-user-with-domain-regexp user) (setq domain (match-string 2 user) user (match-string 1 user)))) -@@ -2753,9 +2755,9 @@ Fall back to normal file name handler if no Tramp file name handler exists." +@@ -2753,9 +2758,9 @@ Fall back to normal file name handler if no Tramp file name handler exists." ;; `file-remote-p' is called for everything, even for symbolic ;; links which look remote. We don't want to get an error. (non-essential (or non-essential (eq operation 'file-remote-p)))) @@ -204,121 +267,16 @@ index 2d6db31..5f15652 100644 (with-parsed-tramp-file-name filename nil (let ((current-connection tramp-current-connection) (foreign -diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el -index 465afa8..124c0fc 100644 ---- a/test/lisp/net/tramp-tests.el -+++ b/test/lisp/net/tramp-tests.el -@@ -330,6 +330,7 @@ Also see `ignore'." - (should (tramp-tramp-file-p "/method:user@:")) - (should (tramp-tramp-file-p "/method:user@host:")) - (should (tramp-tramp-file-p "/method:user@email@host:")) -+ (should (tramp-tramp-file-p "/method:$USER@host:")) - - ;; Using a port. - (should (tramp-tramp-file-p "/method:host#1234:")) -@@ -418,6 +419,7 @@ Also see `ignore'." - (should (tramp-tramp-file-p "/user@:")) - (should (tramp-tramp-file-p "/user@host:")) - (should (tramp-tramp-file-p "/user@email@host:")) -+ (should (tramp-tramp-file-p "/$USER@host:")) - - ;; Using a port. - (should (tramp-tramp-file-p "/host#1234:")) -@@ -472,6 +474,7 @@ Also see `ignore'." - (should (tramp-tramp-file-p "/[method/user@]")) - (should (tramp-tramp-file-p "/[method/user@host]")) - (should (tramp-tramp-file-p "/[method/user@email@host]")) -+ (should (tramp-tramp-file-p "/[method/$USER@host]")) - - ;; Using a port. - (should (tramp-tramp-file-p "/[method/host#1234]")) -@@ -652,6 +655,28 @@ Also see `ignore'." - (should (string-equal - (file-remote-p "/method:user@email@host:" 'hop) nil)) - -+ ;; Expand environment variable. It can be cascaded. -+ (with-environment-variables -+ (("REMOTE_USER" "$REMOTE_USER1") ("REMOTE_USER1" "remote-user")) -+ (should (string-equal -+ (file-remote-p "/method:$REMOTE_USER@host:") -+ (format "/%s:%s@%s:" "method" "remote-user" "host"))) -+ (should -+ (string-equal -+ (file-remote-p "/method:$REMOTE_USER@host:" 'method) "method")) -+ (should -+ (string-equal -+ (file-remote-p "/method:$REMOTE_USER@host:" 'user) "remote-user")) -+ (should -+ (string-equal -+ (file-remote-p "/method:$REMOTE_USER@host:" 'host) "host")) -+ (should -+ (string-equal -+ (file-remote-p "/method:$REMOTE_USER@host:" 'localname) "")) -+ (should -+ (string-equal -+ (file-remote-p "/method:$REMOTE_USER@host:" 'hop) nil))) -+ - ;; Expand `tramp-default-method' and `tramp-default-user'. - (should - (string-equal -@@ -1131,6 +1156,28 @@ Also see `ignore'." - (should (string-equal - (file-remote-p "/user@email@host:" 'hop) nil)) - -+ ;; Expand environment variable. It can be cascaded. -+ (with-environment-variables -+ (("REMOTE_USER" "$REMOTE_USER1") ("REMOTE_USER1" "remote-user")) -+ (should (string-equal -+ (file-remote-p "/$REMOTE_USER@host:") -+ (format "/%s@%s:" "remote-user" "host"))) -+ (should -+ (string-equal -+ (file-remote-p "/$REMOTE_USER@host:" 'method) "default-method")) -+ (should -+ (string-equal -+ (file-remote-p "/$REMOTE_USER@host:" 'user) "remote-user")) -+ (should -+ (string-equal -+ (file-remote-p "/$REMOTE_USER@host:" 'host) "host")) -+ (should -+ (string-equal -+ (file-remote-p "/$REMOTE_USER@host:" 'localname) "")) -+ (should -+ (string-equal -+ (file-remote-p "/$REMOTE_USER@host:" 'hop) nil))) -+ - ;; Expand `tramp-default-method' and `tramp-default-user'. - (should (string-equal - (file-remote-p "/host#1234:") -@@ -1583,6 +1630,28 @@ Also see `ignore'." - (should (string-equal - (file-remote-p "/[method/user@email@host]" 'hop) nil)) - -+ ;; Expand environment variable. It can be cascaded. -+ (with-environment-variables -+ (("REMOTE_USER" "$REMOTE_USER1") ("REMOTE_USER1" "remote-user")) -+ (should (string-equal -+ (file-remote-p "/[method/$REMOTE_USER@host]") -+ (format "/[%s/%s@%s]" "method" "remote-user" "host"))) -+ (should -+ (string-equal -+ (file-remote-p "/[method/$REMOTE_USER@host]" 'method) "method")) -+ (should -+ (string-equal -+ (file-remote-p "/[method/$REMOTE_USER@host]" 'user) "remote-user")) -+ (should -+ (string-equal -+ (file-remote-p "/[method/$REMOTE_USER@host]" 'host) "host")) -+ (should -+ (string-equal -+ (file-remote-p "/[method/$REMOTE_USER@host]" 'localname) "")) -+ (should -+ (string-equal -+ (file-remote-p "/[method/$REMOTE_USER@host]" 'hop) nil))) -+ - ;; Expand `tramp-default-method' and `tramp-default-user'. - (should (string-equal - (file-remote-p "/[/host#1234]") +@@ -6352,6 +6357,9 @@ to cache the result. Return the modified ATTR." + (caar attr)) + (decode-coding-string + (match-string 1 (caar attr)) 'utf-8)))) ++ ;; Quote remote-like symlink. ++ (when (and (stringp (car attr)) (tramp-tramp-file-p (car attr))) ++ (setcar attr (file-name-quote (car attr) 'top))) + ;; Set file's gid change bit. + (setcar + (nthcdr 9 attr) -- 2.45.4