Subject: 23.4; move-file-to-trash bug in files.el.gz with patch

From: David Casperson <[email-masked]>
Date: Tue, 20 Mar 2012 19:51:34 -0700

1.  Create a file whose name is not a legal regular expression, e.g.,
    =E2=80=9C~/[=E2=80=9C.=20
2.  Provoke move-to-trash, for instance
    M-x eval-expression
    (move-file-to-trash (expand-file-name =E2=80=9C~/[=E2=80=9C))

The problem comes from using file-names as regular expressions without
quoting.  Here is a potential patch.  You may use and copy-left as you
see fit.=20=20

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
*** files-original.el	Wed Jan 11 04:35:01 2012
--- files.el	Tue Mar 20 19:37:20 2012
***************
*** 6239,6248 ****
  	 ;; If `trash-directory' is non-nil, move the file there.
  	 (let* ((trash-dir   (expand-file-name trash-directory))
  		(fn          (directory-file-name (expand-file-name filename)))
  		(new-fn      (expand-file-name (file-name-nondirectory fn)
  					       trash-dir)))
  	   ;; We can't trash a parent directory of trash-directory.
! 	   (if (string-match fn trash-dir)
  	       (error "Trash directory `%s' is a subdirectory of `%s'"
  		      trash-dir filename))
  	   (unless (file-directory-p trash-dir)
--- 6239,6249 ----
  	 ;; If `trash-directory' is non-nil, move the file there.
  	 (let* ((trash-dir   (expand-file-name trash-directory))
  		(fn          (directory-file-name (expand-file-name filename)))
+                 (fn-pattern  (regexp-quote fn))
  		(new-fn      (expand-file-name (file-name-nondirectory fn)
  					       trash-dir)))
  	   ;; We can't trash a parent directory of trash-directory.
! 	   (if (string-match fn-pattern trash-dir)
  	       (error "Trash directory `%s' is a subdirectory of `%s'"
  		      trash-dir filename))
  	   (unless (file-directory-p trash-dir)
***************
*** 6267,6283 ****
  					"~/.local/share"))))
  		(trash-files-dir (expand-file-name "files" xdg-data-dir))
  		(trash-info-dir (expand-file-name "info" xdg-data-dir))
! 		(fn (directory-file-name (expand-file-name filename))))
=20=20
  	   ;; Check if we have permissions to delete.
  	   (unless (file-writable-p (directory-file-name
  				     (file-name-directory fn)))
  	     (error "Cannot move %s to trash: Permission denied" filename))
  	   ;; The trashed file cannot be the trash dir or its parent.
! 	   (if (string-match fn trash-files-dir)
  	       (error "The trash directory %s is a subdirectory of %s"
  		      trash-files-dir filename))
! 	   (if (string-match fn trash-info-dir)
  	       (error "The trash directory %s is a subdirectory of %s"
  		      trash-info-dir filename))
=20=20
--- 6268,6285 ----
  					"~/.local/share"))))
  		(trash-files-dir (expand-file-name "files" xdg-data-dir))
  		(trash-info-dir (expand-file-name "info" xdg-data-dir))
! 		(fn (directory-file-name (expand-file-name filename)))
!                 (fn-pattern (regexp-quote fn)))
=20=20
  	   ;; Check if we have permissions to delete.
  	   (unless (file-writable-p (directory-file-name
  				     (file-name-directory fn)))
  	     (error "Cannot move %s to trash: Permission denied" filename))
  	   ;; The trashed file cannot be the trash dir or its parent.
! 	   (if (string-match fn-pattern trash-files-dir)
  	       (error "The trash directory %s is a subdirectory of %s"
  		      trash-files-dir filename))
! 	   (if (string-match fn-pattern trash-info-dir)
  	       (error "The trash directory %s is a subdirectory of %s"
  		      trash-info-dir filename))
=20=20
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D

HTH,
David Casperson

In GNU Emacs 23.4.1 (x86_64-apple-darwin, NS apple-appkit-1038.36)
of 2012-01-29 on bob.porkrind.org
Windowing system distributor `Apple', version 10.3.1138
configured using `configure  '--host=3Dx86_64-apple-darwin' '--build=3Di686=
-apple-darwin' '--with-ns' 'build_alias=3Di686-apple-darwin' 'host_alias=3D=
x86_64-apple-darwin' 'CC=3Dgcc -mmacosx-version-min=3D10.5''

Important settings:
  value of $LC_ALL: nil
  value of $LC_COLLATE: nil
  value of $LC_CTYPE: nil
  value of $LC_MESSAGES: nil
  value of $LC_MONETARY: nil
  value of $LC_NUMERIC: nil
  value of $LC_TIME: nil
  value of $LANG: nil
  value of $XMODIFIERS: nil
  locale-coding-system: nil
  default enable-multibyte-characters: t

Major mode: Text

Minor modes in effect:
  diff-auto-refine-mode: t
  shell-dirtrack-mode: t
  msb-mode: t
  server-mode: t
  tooltip-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  blink-cursor-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  temp-buffer-resize-mode: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t

Recent input:
<tab> l <tab> <return> C-x C-f M-p f i l <tab> s <tab>=20
<return> C-s m o v e - f C-w C-w C-w C-s C-s C-s C-s=20
C-s C-l C-a C-SPC C-M-f C-f C-w C-o C-n C-n C-SPC C-M-f=20
C-f M-w C-o C-y C-x C-s M-` C-g M-x m a n <return>=20
d i f f <return> C-o C-v C-v C-v C-v C-v C-v C-v C-o=20
C-x C-j C-x 4 b f i <tab> ? l <tab> <return> C-x C-j=20
C M-p M-b M-b M-b M-f - o r i g i n a l <return> C-o=20
C-o g C-x <escape> <escape> M-p C-g C M-p C-g C-o g=20
p m m ! <return> g d x y e s <return> M-! i d f f <backspace>=20
<backspace> <backspace> <backspace> d i f f SPC - C=20
3 SPC C-x 9 r f i l e <tab> s <tab> - <tab> <return>=20
SPC f i l e s . e <tab> <return> C-o C-v C-v C-v C-o=20
p f C-x 1 C-s m o v e C-g C-s ( d e f u n SPC m o v=20
e C-a C-n C-f C-f C-f C-SPC C-n C-a C-w C-x C-s C-n=20
C-n C-n C-n C-n C-n C-n C-n C-n C-n C-e M-z " C-x C-s=20
C-x C-j C-x <escape> <escape> M-p <return> p o C-s=20
C-s C-a C-n C-SPC C-n C-n C-n C-n C-n C-n C-n C-n C-n=20
C-n C-n C-n M-w C-o C-n f C-a C-p C-p C-p C-p C-p C-p=20
C-p C-p C-p C-p C-y C-M-k C-k C-x C-s C-o C-v C-o C-x=20
<escape> <escape> <return> C-o C-v C-v C-x C-s C-g=20
C-x C-w f i l e s - d i f f . t x t <return> M-x r=20
e p o r <tab> <return>

Recent messages:
Saving file /Users/casper/Library/emacs/lisp/Files/files.el...
Wrote /Users/casper/Library/emacs/lisp/Files/files.el
Directory has changed on disk; type g to update Dired
Mark saved where search started
Mark set [2 times]
Saving file /Users/casper/Library/emacs/lisp/Files/files.el...
Wrote /Users/casper/Library/emacs/lisp/Files/files.el
Quit
Saving file /Users/casper/Library/emacs/lisp/Files/files-diff.txt...
Wrote /Users/casper/Library/emacs/lisp/Files/files-diff.txt

Load-path shadows:
/Users/casper/Library/emacs/lisp/progmodes/Prolog/bruda/prolog hides /Appli=
cations/Emacs.app/Contents/Resources/lisp/progmodes/prolog
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/xsd-regexp hides /Applicat=
ions/Emacs.app/Contents/Resources/lisp/nxml/xsd-regexp
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/xmltok hides /Applications=
/Emacs.app/Contents/Resources/lisp/nxml/xmltok
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-xsd hides /Application=
s/Emacs.app/Contents/Resources/lisp/nxml/rng-xsd
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-valid hides /Applicati=
ons/Emacs.app/Contents/Resources/lisp/nxml/rng-valid
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-util hides /Applicatio=
ns/Emacs.app/Contents/Resources/lisp/nxml/rng-util
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-uri hides /Application=
s/Emacs.app/Contents/Resources/lisp/nxml/rng-uri
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-pttrn hides /Applicati=
ons/Emacs.app/Contents/Resources/lisp/nxml/rng-pttrn
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-parse hides /Applicati=
ons/Emacs.app/Contents/Resources/lisp/nxml/rng-parse
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-nxml hides /Applicatio=
ns/Emacs.app/Contents/Resources/lisp/nxml/rng-nxml
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-match hides /Applicati=
ons/Emacs.app/Contents/Resources/lisp/nxml/rng-match
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-maint hides /Applicati=
ons/Emacs.app/Contents/Resources/lisp/nxml/rng-maint
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-loc hides /Application=
s/Emacs.app/Contents/Resources/lisp/nxml/rng-loc
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-dt hides /Applications=
/Emacs.app/Contents/Resources/lisp/nxml/rng-dt
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/rng-cmpct hides /Applicati=
ons/Emacs.app/Contents/Resources/lisp/nxml/rng-cmpct
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-util hides /Applicati=
ons/Emacs.app/Contents/Resources/lisp/nxml/nxml-util
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-uchnm hides /Applicat=
ions/Emacs.app/Contents/Resources/lisp/nxml/nxml-uchnm
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-rap hides /Applicatio=
ns/Emacs.app/Contents/Resources/lisp/nxml/nxml-rap
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-parse hides /Applicat=
ions/Emacs.app/Contents/Resources/lisp/nxml/nxml-parse
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-outln hides /Applicat=
ions/Emacs.app/Contents/Resources/lisp/nxml/nxml-outln
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-ns hides /Application=
s/Emacs.app/Contents/Resources/lisp/nxml/nxml-ns
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-mode hides /Applicati=
ons/Emacs.app/Contents/Resources/lisp/nxml/nxml-mode
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-maint hides /Applicat=
ions/Emacs.app/Contents/Resources/lisp/nxml/nxml-maint
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-glyph hides /Applicat=
ions/Emacs.app/Contents/Resources/lisp/nxml/nxml-glyph
/Users/casper/Library/emacs/lisp/Modes/nxml-mode/nxml-enc hides /Applicatio=
ns/Emacs.app/Contents/Resources/lisp/nxml/nxml-enc
/Applications/Emacs.app/Contents/Resources/lisp/uniquify hides /Users/caspe=
r/Library/emacs/lisp/Files/uniquify
/Applications/Emacs.app/Contents/Resources/lisp/files hides /Users/casper/L=
ibrary/emacs/lisp/Files/files
/Users/casper/Library/emacs/lisp/slinks hides /Users/casper/Library/emacs/l=
isp/Obsolete/slinks
/Users/casper/Library/emacs/lisp/Modes/filladapt hides /Users/casper/Librar=
y/emacs/lisp/Obsolete/filladapt
/Applications/Emacs.app/Contents/Resources/lisp/emacs-lisp/rx hides /Users/=
casper/Library/emacs/lisp/Regexps/rx
/Users/casper/Library/emacs/lisp/Files/temp2 hides /Users/casper/Library/em=
acs/lisp/Scratch Work/temp2
/Users/casper/Library/emacs/lisp/TeX/one-sentence-regions hides /Users/casp=
er/Library/emacs/lisp/Tweaks/one-sentence-regions
/Users/casper/Library/emacs/lisp/aldor-hooks hides /Users/casper/Library/em=
acs/lisp/progmodes/aldor-hooks
/Users/casper/Library/emacs/lisp/Dired/dired-smart-view hides /Users/casper=
/Library/emacs/lisp/Dired/in-progress/dired-smart-view
/Users/casper/Library/emacs/lisp/Dired/dired-after-readin-overlay hides /Us=
ers/casper/Library/emacs/lisp/Dired/in-progress/dired-after-readin-overlay
/Users/casper/Library/emacs/lisp/Dired/dired-hide-dot-files hides /Users/ca=
sper/Library/emacs/lisp/Dired/obsolete/dired-hide-dot-files
/Applications/Emacs.app/Contents/Resources/lisp/textmodes/underline hides /=
Users/casper/Library/emacs/lisp/Obsolete/junk-maybe/underline
/Applications/Emacs.app/Contents/Resources/lisp/obsolete/resume hides /User=
s/casper/Library/emacs/lisp/Obsolete/junk-maybe/resume
/Users/casper/Library/emacs/lisp/Dired/dired-fix hides /Users/casper/Librar=
y/emacs/lisp/Obsolete/junk-maybe/dired-fix
/Users/casper/Library/emacs/lisp/Obsolete/junk-maybe/cmutex hides /Users/ca=
sper/Library/emacs/lisp/Obsolete/old/cmutex
/Users/casper/Library/emacs/lisp/Obsolete/junk-maybe/cmushell hides /Users/=
casper/Library/emacs/lisp/Obsolete/old/cmushell
/Users/casper/Library/emacs/lisp/progmodes/C/c-cut-region-to-file hides /Us=
ers/casper/Library/emacs/lisp/progmodes/C++/c-cut-region-to-file
/Users/casper/Library/emacs/lisp/progmodes/eiffel-mode hides /Users/casper/=
Library/emacs/lisp/progmodes/Eiffel/eiffel-mode
/Applications/Emacs.app/Contents/Resources/lisp/progmodes/ruby-mode hides /=
Users/casper/Library/emacs/lisp/progmodes/Ruby/ruby-mode
/Users/casper/Library/emacs/lisp/progmodes/C/c-cut-region-to-file hides /Us=
ers/casper/Library/emacs/lisp/progmodes/c-common/c-cut-region-to-file
/Applications/Emacs.app/Contents/Resources/lisp/cedet/pulse hides /Users/ca=
sper/Library/emacs/lisp/progmodes/cedet-1.0/common/pulse
/Applications/Emacs.app/Contents/Resources/lisp/cedet/mode-local hides /Use=
rs/casper/Library/emacs/lisp/progmodes/cedet-1.0/common/mode-local
/Applications/Emacs.app/Contents/Resources/lisp/cedet/inversion hides /User=
s/casper/Library/emacs/lisp/progmodes/cedet-1.0/common/inversion
/Applications/Emacs.app/Contents/Resources/lisp/ezimage hides /Users/casper=
/Library/emacs/lisp/progmodes/cedet-1.0/common/ezimage
/Applications/Emacs.app/Contents/Resources/lisp/cedet/data-debug hides /Use=
rs/casper/Library/emacs/lisp/progmodes/cedet-1.0/common/data-debug
/Applications/Emacs.app/Contents/Resources/lisp/cedet/cedet hides /Users/ca=
sper/Library/emacs/lisp/progmodes/cedet-1.0/common/cedet
/Applications/Emacs.app/Contents/Resources/lisp/cedet/cedet-idutils hides /=
Users/casper/Library/emacs/lisp/progmodes/cedet-1.0/common/cedet-idutils
/Applications/Emacs.app/Contents/Resources/lisp/cedet/cedet-global hides /U=
sers/casper/Library/emacs/lisp/progmodes/cedet-1.0/common/cedet-global
/Applications/Emacs.app/Contents/Resources/lisp/cedet/cedet-files hides /Us=
ers/casper/Library/emacs/lisp/progmodes/cedet-1.0/common/cedet-files
/Applications/Emacs.app/Contents/Resources/lisp/cedet/cedet-cscope hides /U=
sers/casper/Library/emacs/lisp/progmodes/cedet-1.0/common/cedet-cscope
/Applications/Emacs.app/Contents/Resources/lisp/cedet/ede hides /Users/casp=
er/Library/emacs/lisp/progmodes/cedet-1.0/ede/ede
/Applications/Emacs.app/Contents/Resources/lisp/emacs-lisp/eieio hides /Use=
rs/casper/Library/emacs/lisp/progmodes/cedet-1.0/eieio/eieio
/Applications/Emacs.app/Contents/Resources/lisp/emacs-lisp/eieio-speedbar h=
ides /Users/casper/Library/emacs/lisp/progmodes/cedet-1.0/eieio/eieio-speed=
bar
/Applications/Emacs.app/Contents/Resources/lisp/emacs-lisp/eieio-opt hides =
/Users/casper/Library/emacs/lisp/progmodes/cedet-1.0/eieio/eieio-opt
/Applications/Emacs.app/Contents/Resources/lisp/emacs-lisp/eieio-datadebug =
hides /Users/casper/Library/emacs/lisp/progmodes/cedet-1.0/eieio/eieio-data=
debug
/Applications/Emacs.app/Contents/Resources/lisp/emacs-lisp/eieio-custom hid=
es /Users/casper/Library/emacs/lisp/progmodes/cedet-1.0/eieio/eieio-custom
/Applications/Emacs.app/Contents/Resources/lisp/emacs-lisp/eieio-comp hides=
/Users/casper/Library/emacs/lisp/progmodes/cedet-1.0/eieio/eieio-comp
/Applications/Emacs.app/Contents/Resources/lisp/emacs-lisp/eieio-base hides=
/Users/casper/Library/emacs/lisp/progmodes/cedet-1.0/eieio/eieio-base
/Applications/Emacs.app/Contents/Resources/lisp/emacs-lisp/chart hides /Use=
rs/casper/Library/emacs/lisp/progmodes/cedet-1.0/eieio/chart
/Applications/Emacs.app/Contents/Resources/lisp/cedet/semantic hides /Users=
/casper/Library/emacs/lisp/progmodes/cedet-1.0/semantic/semantic
/Applications/Emacs.app/Contents/Resources/lisp/speedbar hides /Users/caspe=
r/Library/emacs/lisp/progmodes/cedet-1.0/speedbar/speedbar
/Applications/Emacs.app/Contents/Resources/lisp/sb-image hides /Users/caspe=
r/Library/emacs/lisp/progmodes/cedet-1.0/speedbar/sb-image
/Applications/Emacs.app/Contents/Resources/lisp/dframe hides /Users/casper/=
Library/emacs/lisp/progmodes/cedet-1.0/speedbar/dframe
/Applications/Emacs.app/Contents/Resources/lisp/cedet/srecode hides /Users/=
casper/Library/emacs/lisp/progmodes/cedet-1.0/srecode/srecode

Features:
(shadow sort mail-extr message ecomplete rfc822 mml mml-sec
password-cache mm-decode mm-bodies mm-encode mailcap mail-parse rfc2231
rfc2047 rfc2045 qp ietf-drums mailabbrev nnheader gnus-util netrc
time-date mm-util mail-prsvr gmm-utils mailheader canlock sha1 hex-util
hashcash mail-utils emacsbug tabify man assoc tmm electric jka-compr
find-func vc-dispatcher vc-svn magit diff-mode log-edit easy-mmode
pcvs-util add-log multi-isearch iso-transl find-dired dired-mac-open
pico-server-done-function osx-osascript longlines mail-reply-mode
derived ansi-color shell compile comint ring my-zap-to-char change-case
rect dabbrev cc-def cc-common-def skeleton cc-mode cc-fonts cc-menus
cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs arc-mode
archive-mode dired-create-directory-fix wdired
dired-up-directory-and-remove-buffer mule-util help-mode view dired-x
dired-aux dired-mac-fix dired-follow-mac-link dired-delete-file-fix
dired-fix dired regexp-opt eldoc file-mode-tools buff-menu-aux msb-fix
msb cedet nxml-enc paren mic-paren diminish save-file-name-history cl
cl-19 insert color-insert swap-volume rx customized-find-file
dired-mac-init edmacro kmacro cus-edit wid-edit filladapt prolog
sh-script executable uniquify advice help-fns advice-preload server
cus-start cus-load tooltip ediff-hook vc-hooks lisp-float-type mwheel
ns-win easymenu tool-bar dnd fontset image fringe lisp-mode register
page menu-bar rfn-eshadow timer select scroll-bar mldrag mouse jit-lock
font-lock syntax facemenu font-core frame cham georgian utf-8-lang
misc-lang vietnamese tibetan thai tai-viet lao korean japanese hebrew
greek romanian slovak czech european ethiopic indian cyrillic chinese
case-table epa-hook jka-cmpr-hook help simple abbrev loaddefs button
minibuffer faces cus-face files text-properties overlay md5 base64
format env code-pages mule custom widget hashtable-print-readable
backquote make-network-process ns multi-tty emacs)