Subject: bug#56443: 28.1; Mac segmentation fault with ffap

From: Daniel Martín <[email-masked]>
Date: Fri, 08 Jul 2022 11:54:04 +0200

Eli Zaretskii <[email-masked]> writes:

>
> That's not NULL, that's nil (which is represented as zero).
>
> But I don't understand how could that happen, because
> Ffile_name_case_insensitive_p checks the argument for validity:
>
>   DEFUN ("file-name-case-insensitive-p", Ffile_name_case_insensitive_p,
> 	 Sfile_name_case_insensitive_p, 1, 1, 0,
> 	 doc: /* Return t if file FILENAME is on a case-insensitive filesystem.
>   Return nil if FILENAME does not exist or is not on a case-insensitive
>   filesystem, or if there was trouble determining whether the filesystem
>   is case-insensitive.  */)
>     (Lisp_Object filename)
>   {
>     Lisp_Object handler;
>
>     CHECK_STRING (filename);  <<<<<<<<<<<<<<<<<<<<<<<<<<<<
>     filename = Fexpand_file_name (filename, Qnil);
>
> So it seems like expand-file-name returned nil in this case?
>
> Can someone step through the code, including stepping into
> Fexpand_file_name, and see  how we get that nil in this case?
>
> (I tried to reproduce on my system, which is not a Mac, but I don't
> see any nil filenames in that case.)

Apparently it comes from the "parent" variable, which is the result of
the file_name_directory call:

Process 61514 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x000000010064fefc emacs`Ffile_name_case_insensitive_p(filename=0x000000011534dc44) at fileio.c:2608:18
   2605		 (impossible?).  */
   2606	      if (!NILP (Fstring_equal (parent, filename)))
   2607		return Qnil;
-> 2608	      filename = parent;
   2609	    }
   2610	}
   2611
Target 0: (emacs) stopped.
(lldb) fr v parent
(Lisp_Object) parent = NULL

Is the following expression the correct way to manually interpret the
Lisp_Object as a Lisp_String?  (where $ptr is the memory address of
"filename" in this scenario):

(char *) ((struct Lisp_String *)$ptr)->u.s.data

That prints an empty string in LLDB.

BTW, I don't really understand the semantics of
file-name-case-insensitive-p.  The docstring says that it returns nil if
the file is not found, but these calls return t on my system:

(file-name-case-insensitive-p "")
(file-name-case-insensitive-p "FileThatDoesNotExist")

Does that make sense?