Pádraig Brady wrote:

> Jim Meyering wrote:
>> Nearly missed this one.
>> ls initializes a struct stat to all NUL bytes.
>> It calls stat or lstat on a dangling symlink, and that fails.
>> ls then tests stat.st_ino.
>>
>> Sometimes, it's 0, but sometimes it's the inode of the symlink,
>> possibly depending on how the package was configured/built or
>> the environment.
>> I haven't determined precisely what makes the difference,
>> but ls (from coreutils-7.6) built some way prints 0 as the inode
>> number, and other ways, it prints the inode of the dangling symlink.
>>
>>
>>>From f7db178fdff1ebb113841035b55b103e074b5f6f Mon Sep 17 00:00:00 2001
>> From: Jim Meyering <meyer...@redhat.com>
>> Date: Tue, 29 Sep 2009 07:28:01 +0200
>> Subject: [PATCH] ls: don't use an undefined struct stat after failed 
>> stat/lstat
>>
>> * src/ls.c (gobble_file): After a failed stat/lstat call,
>> clear the f->stat buffer, since the syscall may have modified it,
>> and we may need to know that stat.st_ino is zero.
>
> Well spotted. By the same token is this useful?

Well spotted yourself!
I should have remembered to use the stat_ok member.

I'll merge something like this into my patch.

Thanks!

diff --git a/src/ls.c b/src/ls.c
index dc2f86e..03ef9b0 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -2777,11 +2777,7 @@ gobble_file (char const *name, enum filetype type, ino_t 
inode,

       if (err != 0)
         {
-          /* The failed stat/lstat may have modified f->stat.  Clear it,
-             since we may use at least its st_ino member, e.g.,
-             when trying to print the inode of dangling symlink:
-             mkdir d; ln -s no-such d/s; ls -Li d  */
-          memset (&f->stat, 0, sizeof (f->stat));
+          f->stat.st_ino = 22;

           /* Failure to stat a command line argument leads to
              an exit status of 2.  For other files, stat failure
@@ -3569,9 +3565,9 @@ static char *
 format_inode (char *buf, size_t buflen, const struct fileinfo *f)
 {
   assert (INT_BUFSIZE_BOUND (uintmax_t) <= buflen);
-  return (f->stat.st_ino == NOT_AN_INODE_NUMBER
-          ? (char *) "?"
-          : umaxtostr (f->stat.st_ino, buf));
+  return (f->stat_ok && f->stat.st_ino != NOT_AN_INODE_NUMBER
+          ? umaxtostr (f->stat.st_ino, buf)
+          : (char *) "?");
 }

 /* Print information about F in long format.  */


Reply via email to