Bug 23153 - gas: distinct input and output files are not properly detected on not-fully-emulated POSIX platforms
Summary: gas: distinct input and output files are not properly detected on not-fully-e...
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.31
: P2 critical
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-05-09 12:52 UTC by Pekka Seppänen
Modified: 2018-05-14 15:07 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Proposed patch (241 bytes, patch)
2018-05-09 14:42 UTC, Nick Clifton
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Pekka Seppänen 2018-05-09 12:52:10 UTC
As of commit 67f846b59b32f3d704c601669409c2584383fea9 gas tries to use simple heuristics to determine if the given input and output files are distinct (at gas/as.c).

The files are stat()'d and then the `st_ino' members compared. The logic is sound on 100% POSIX conforming platforms, however, the same cannot be said for e.g. MinGW. MinGW uses a zero `st_ino' for any (existing) file (based on a quick search this is by design, so not likely to change anytime soon). Thus, if all input and output files exist, gas will spit out "The input and output files must be distinct", which is not true.

As a funny side-effect, even if the input and output file are determined as ``non-distinct'', something within the GCC chain still removes the output file. So, any even invocation will fail, while any odd invocation will succeed -- which is utterly confusing unless one takes a look at the source code and is aware of the POSIX internals at some level.

Anyway, this commit effectively hinders any platform that does not supply an unique `st_ino' for a given file. Given that gas has been working just fine (and it ain't a filesystem utility), right out-of-the-box, for a long time without this, be it a native or a cross-compiling build, I see that this commit causes much, much more harm than good.

(Cygwin is not affected by this, as it appears to emulate an unique `st_ino'.)
Comment 1 Nick Clifton 2018-05-09 14:42:46 UTC
Created attachment 11001 [details]
Proposed patch

Hi Pekka,

  Please could you try out the uploaded patch and let me know if it solves
  the problem ?

Cheers
  Nick
Comment 2 Pekka Seppänen 2018-05-14 07:20:41 UTC
Hi Nick,

My apologies for a late response; The patch appears to work just fine as expected.

However, it just occured to me that IEEE Std 1003.1 (2016 edition), i.e. the POSIX specs, state that ``The st_ino and st_dev fields taken together uniquely identify the file within the system'' (pg. 392), so I guess the attached patch shouldn't be applied but one that fails only if the st_dev is the same, too (and has the non-POSIX compliant quirk workaround enabled way or another).

By the way, the GCC folks simply do not do any stat()s for MinGW targets (so any compliant system does not get the zero serial number ignored).
Comment 3 Nick Clifton 2018-05-14 11:19:43 UTC
Hi Pekka,

> so I guess the
> attached patch shouldn't be applied but one that fails only if the st_dev is
> the same, too

Can you confirm that MingW always returns 0 for the st_dev field as well ?
(I assume that it does, but I would like to make sure).  If so then I
will apply the patch modified as you suggest.

Cheers
  Nick
Comment 4 Pekka Seppänen 2018-05-14 11:39:16 UTC
(In reply to Nick Clifton from comment #3)
> Hi Pekka,
> 
> Can you confirm that MingW always returns 0 for the st_dev field as well ?
> (I assume that it does, but I would like to make sure).  If so then I
> will apply the patch modified as you suggest.
> 

No, MinGW populates the st_dev field with some apparently non-random value (i.e. might be zero or not, but it's not always zero). I didn't check from what it acquires or derives that value, but it's neither always zero nor the same what Cygwin's stat() will return.

Only the st_ino is always zero, which is indeed a bit shame.
Comment 5 Nick Clifton 2018-05-14 12:03:04 UTC
Hi Pekka,

> No, MinGW populates the st_dev field with some apparently non-random value

In which case I will go with the original patch.  I know that technically
a valid file might have an inode of 0, but I think that in practice this
will never happen since most file systems do not use inode 0, (at least not for ordinary files).  Or if they do, it is for a special purpose, such as marking
that the file has been deleted.

Cheers
  Nick
Comment 6 Sourceware Commits 2018-05-14 12:06:28 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c3533c4c7c5db84b27e4dc8994a3c3a893077c03

commit c3533c4c7c5db84b27e4dc8994a3c3a893077c03
Author: Nick Clifton <nickc@redhat.com>
Date:   Mon May 14 13:05:02 2018 +0100

    Fix a problem in the assembler when checking for overlapping input and output files on non-POSIX compliant systems.
    
    	PR 23153
    	* as.c (main): When checking for an output file that is also an
    	input file, also check that the inode is not zero.
Comment 7 Nick Clifton 2018-05-14 12:07:20 UTC
Patch applied.
Comment 8 Florian Weimer 2018-05-14 13:43:58 UTC
(In reply to Nick Clifton from comment #5)
> Hi Pekka,
> 
> > No, MinGW populates the st_dev field with some apparently non-random value
> 
> In which case I will go with the original patch.  I know that technically
> a valid file might have an inode of 0, but I think that in practice this
> will never happen since most file systems do not use inode 0, (at least not
> for ordinary files).  Or if they do, it is for a special purpose, such as
> marking that the file has been deleted.

On XFS, inode 0 can be used for regular files created by applications.  Only newer versions have code in them to avoid inode 0.  Some old applications have comments that inode 0 indicates a deleted directory entry, but this appears to be an invention and not something that has ever occurred in practice.
Comment 9 Nick Clifton 2018-05-14 15:02:02 UTC
(In reply to Florian Weimer from comment #8)
 
> On XFS, inode 0 can be used for regular files created by applications.  Only
> newer versions have code in them to avoid inode 0.  Some old applications
> have comments that inode 0 indicates a deleted directory entry, but this
> appears to be an invention and not something that has ever occurred in
> practice.

My assumption is that even if inode 0 is valid for the filesystem it is extremely unlikely that this value will just happen to be used for an assembler input file,
and extremely unlucky if this file is then used as the output from the assembler too.  So basically, it is not worth worrying about.
Comment 10 Florian Weimer 2018-05-14 15:07:42 UTC
(In reply to Nick Clifton from comment #9)
> My assumption is that even if inode 0 is valid for the filesystem it is
> extremely unlikely that this value will just happen to be used for an
> assembler input file,
> and extremely unlucky if this file is then used as the output from the
> assembler too.  So basically, it is not worth worrying about.

Agreed.  If this safety check does not kick in because the input and output files are the same and have inode 0, then this is not a huge problem.

I just wanted to point out that inode number 0 is *not* special on most systems because that's a common misconception.