Subject: bug#70914: 29.3; Crashes often on Windows

From: Eli Zaretskii <[email-masked]>
Date: Wed, 22 May 2024 14:24:26 +0300

> Date: Wed, 22 May 2024 06:12:17 +0000 (UTC)
> From: Hannes Domani <[email-masked]>
> Cc: Eli Zaretskii <[email-masked]>, Corwin Brust <[email-masked]>, 
> 	"[email-masked]" <[email-masked]>
> 
> >     get_volume_info: name="d:/profiles/%s"
> >     get_volume_info: name="//"
> >
> >     Thread 1 received signal SIGSEGV, Segmentation fault.
> >     [Switching to Thread 27916.0x5a7c]
> >     0x0000000000000000 in ?? ()
> 
> Whoa, the result is very different from what I expected, but we found the
> culprit.
> 
> @Eli
> 
> Not sure where this "//" path is coming from, but parse_root() does
> not handle it correctly, it will look for 2 additional slashes after
> them for some reason (?)

It wants to find the UNC \\server\share part of the file name, because
otherwise we get an invalid root of a filesystem.  For example, the
call to GetVolumeInformationW with a name like "\\" (or anything that
doesn't include a valid server and share after the 2 leading
backslashes) will fail, and we will not be able to know what
filesystem features the corresponding volume supports.

> buf first ignore the null-delimiter with 'name++',
> before the 'while ( *name )' check:

Right.  I guess no one ever called us with such invalid file names, or
at least they didn't complain here.

> The 'root_len' it returns to get_volume_info() then likely overflows
> 'temp' in the following strncpy() call:
> 
>       strncpy (temp, name, root_len);
> 
> As a quick fix I suggest changing the if() to something like:
> 
>       if (!*name || (IS_DIRECTORY_SEP (*name) && --slashes == 0))

Right, done.

However, I would still like to figure out how come such a name winds
up here.  So Simen, please edit w32.c to add

  if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])
      && name[2] == '\0')
    emacs_abort ();

at the very beginning of parse_root, rebuild Emacs, then run Emacs
under GDB with a breakpoint in emacs_abort, and when the breakpoint
breaks, please show the full backtrace, including the Lisp backtrace,
like this:

  (gdb) thread 1
  (gdb) source /path/to/emacs/src/.gdbinit
  (gdb) bt

where "/path/to/emacs/src/" is the full absolute file name of the
Emacs src directory, in the tree from which you build Emacs.  It
should show the C backtrace and also the Lisp backtrace (because
the .gdbinit file includes some magic to make that happen).

My guess is that some package you are using does something
inappropriate for Windows which yields this "//" file name.  But I
prefer not to guess.