From unknown Sun Jun 22 22:46:00 2025 X-Loop: help-debbugs@gnu.org Subject: bug#33524: 27.0.50; Suspicious code in flymake-proc around temporary directories Resent-From: Philipp Stephani
Philipp Stephani <p.stephani2@gmail.com> writes:
Hi Phillipp,
> I've noticed that the temporary directory code in flymake-proc has=
> issues with remote filenames.=C2=A0 For example:
>
> $ emacs -Q -batch -l flymake-proc --eval=3D'(print (flymake-proc-c= reate-temp-with-folder-structure "/:/dir" nil))'
>
> "/tmp/:/dir"
>
> Clearly that's not what was intended.=C2=A0 Rather, this should cr= eate the
> directory structure on the remote machine.
I don't understand. "/:/dir" is not a remote file name, it is= a quoted
file name. See (info "(emacs) Quoted File Names") for a descripti= on.
Could you pls explain what you want to achieve? This would help to
understand your problem.
Philipp Stephani <p.stephani2@gmail.com= a>> writes:
Hi Philipp,
> Sorry for being imprecise. Yes, I mean quoted filenames. (It's
> possible that the issue also arises for true remote filenames, but I > haven't checked.)
"True remote filename" is still a wrong phrase. Quoted file names= and
remote file names play different games.
> You can easily reproduce user-facing problems. Assuming you have some<= br> > binary installed that would check Java files using the legacy backend:=
>
> $ touch /tmp/{a,b}.java
> $ emacs -Q -eval '(progn (add-hook (quote prog-mode-hook) (quote > flymake-mode)) (ediff "/:/tmp/a.java" "/:/tmp/b.java&qu= ot;))'
>
> And Emacs immediately hangs because it runs into the endless loop.
> Stacktrace in this case is
>
> Debugger entered--Lisp error: (quit)
>=C2=A0 =C2=A0display-warning((flymake flymake-proc) "Failed to del= ete dir /,
> error ignored" :error "*Flymake log*")
>=C2=A0 =C2=A0flymake--log-1(1 flymake-proc "Failed to delete dir %= s, error
> ignored" "/")
>=C2=A0 =C2=A0flymake-proc--safe-delete-directory("/")
>=C2=A0 =C2=A0flymake-proc--delete-temp-directory("/tmp/:/tmp/"= ;)
>=C2=A0 =C2=A0flymake-proc-simple-java-cleanup()
>=C2=A0 =C2=A0#f(compiled-function () #<bytecode 0x11a4ea9>)()
>=C2=A0 =C2=A0flymake-proc-legacy-flymake(#f(compiled-function (&res= t args)
> #<bytecode 0x11a4e51>))
>=C2=A0 =C2=A0flymake--run-backend(flymake-proc-legacy-flymake)
>=C2=A0 =C2=A0#f(compiled-function (backend) #<bytecode 0x117b195>= )
> (flymake-proc-legacy-flymake)
>=C2=A0 =C2=A0run-hook-wrapped(#f(compiled-function (backend) #<bytec= ode
> 0x117b195>) flymake-proc-legacy-flymake)
>=C2=A0 =C2=A0flymake-start((post-command) nil)
>=C2=A0 =C2=A0#f(compiled-function () #<bytecode 0x1180771>)()
>=C2=A0 =C2=A0set-window-buffer(nil #<buffer a.java>)
>=C2=A0 =C2=A0switch-to-buffer(#<buffer a.java>)
>=C2=A0 =C2=A0ediff-setup-windows-multiframe-compare(#<buffer a.java&= gt; #<buffer
> b.java> nil #<buffer *Ediff Control Panel*>)
>=C2=A0 =C2=A0ediff-setup-windows-multiframe(#<buffer a.java> #<= ;buffer b.java> nil
> #<buffer *Ediff Control Panel*>)
>=C2=A0 =C2=A0ediff-setup-windows-default(#<buffer a.java> #<bu= ffer b.java> nil
> #<buffer *Ediff Control Panel*>)
>=C2=A0 =C2=A0ediff-setup-windows(#<buffer a.java> #<buffer b.j= ava> nil #<buffer
> *Ediff Control Panel*>)
>=C2=A0 =C2=A0ediff-setup(#<buffer a.java> "/:/tmp/a.java&quo= t; #<buffer b.java>
> "/:/tmp/b.java" nil nil nil ((ediff-job-name . ediff-files))= nil)
>=C2=A0 =C2=A0ediff-files-internal("/:/tmp/a.java" "/:/tm= p/b.java" nil nil
> ediff-files)
>=C2=A0 =C2=A0ediff("/:/tmp/a.java" "/:/tmp/b.java")=
>=C2=A0 =C2=A0(progn (add-hook (quote prog-mode-hook) (quote flymake-mod= e)) (ediff
> "/:/tmp/a.java" "/:/tmp/b.java"))
>=C2=A0 =C2=A0eval((progn (add-hook (quote prog-mode-hook) (quote flymak= e-mode))
> (ediff "/:/tmp/a.java" "/:/tmp/b.java")))
>=C2=A0 =C2=A0command-line-1(("-f" "toggle-debug-on-quit&= quot; "-eval" "(progn
> (add-hook (quote prog-mode-hook) (quote flymake-mode)) (ediff
> \"/:/tmp/a.java\" \"/:/tmp/b.java\"))"))
>=C2=A0 =C2=A0command-line()
>=C2=A0 =C2=A0normal-top-level()
The following patch fixes this problem:
diff --git a/lisp/progmodes/flymake-proc.el b/lisp/progmodes/flymake-proc.e= l
index 8600be9b97..e969c5d992 100644
--- a/lisp/progmodes/flymake-proc.el
+++ b/lisp/progmodes/flymake-proc.el
@@ -874,7 +874,7 @@ flymake-proc-create-temp-with-folder-structure
=C2=A0 =C2=A0(unless (stringp file-name)
=C2=A0 =C2=A0 =C2=A0(error "Invalid file-name"))
-=C2=A0 (let* ((dir=C2=A0 =C2=A0 =C2=A0 =C2=A0(file-name-directory file-nam= e))
+=C2=A0 (let* ((dir=C2=A0 =C2=A0 =C2=A0 =C2=A0(file-name-directory (file-na= me-unquote file-name)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; Not sure what this slash-pos is all a= bout, but I guess it's just
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; trying to remove the leading / of abs= olute file names.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(slash-pos (string-match "/" di= r))
However, I don't know whether this is sufficient, because I don't k= now
why you use quoted file names in your example. Is this something which
shall be preserved in the temporary directory, created by flymake?
Jo=C3=A3o, do you have further remarks?
Best regards, Michael.