Comment #0 by leandro.lucarella — 2010-11-19T16:09:43Z
See this example:
$ mkdir x
$ echo 'void main() {}' > x/test.d
$ echo "my very important data that shouldn't be ereased" > test
$ ls test
test
$ cat test
my very important data that shouldn't be ereased
$ dmd -run x/test.d
$ ls test
ls: cannot access test: No such file or directory
$ cat test
cat: test: No such file or directory
I think this is a very serious bug. It's really unexpected that DMD removes the test file (I can understand why it happens, but it shouldn't). test.d being in another directory is just to point how much surprising could be that running a "script" in an unrelated directory removes files in the current directory.
If DMD wants to put D in the scripting world, this should be fixed ASAP, as no scripting language EVER will remove your files unexpectedly.
Comment #1 by andrej.mitrovich — 2012-12-18T12:35:00Z
Created attachment 1170
patch
Possible patch added. I don't have a Posix build system to test it, and there should be a test-script (possibly in shell) to verify it works ok.
Comment #2 by leandro.lucarella — 2013-01-07T10:46:33Z
Can you(In reply to comment #1)
> Created an attachment (id=1170) [details]
> patch
>
> Possible patch added. I don't have a Posix build system to test it, and there
> should be a test-script (possibly in shell) to verify it works ok.
Can you convert this into a pull request? It will make reviewing more easy.
I can write the test case based on the one in the report.
All your changes are POSIX only, is the overwriting not happening on Windows?
Also, is extremely unlikely, but you can still overwrite unintended files, a check to avoid overwriting anything should be done, but maybe that's much harder to do because you have to change how the file is opened, not just the filename.
Finally, any reason for declaring getuid() manually instead of including the appropriate headers?
Thanks for addressing this issue!
Comment #3 by andrej.mitrovich — 2013-01-07T12:31:42Z
(In reply to comment #2)
> Can you convert this into a pull request? It will make reviewing more easy.
I'll do it later tonight.
> All your changes are POSIX only, is the overwriting not happening on Windows?
No because executables on win32 always end with .exe. Even if you do "dmd -oftest", DMD will still append an .exe .
> Finally, any reason for declaring getuid() manually instead of including the
> appropriate headers?
The DMC header is unistd.h, but the front-end is also used by GDC and LDC, I don't know which headers they use for this function. It seemed easiest to just declare the function rather than to include an entire header (remember that includes are costly for compile-times in C++).
Comment #4 by andrej.mitrovich — 2013-01-07T13:14:03Z
Comment #5 by leandro.lucarella — 2013-01-08T07:31:29Z
(In reply to comment #3)
> (In reply to comment #2)
> > Can you convert this into a pull request? It will make reviewing more easy.
>
> I'll do it later tonight.
Thanks!
> > All your changes are POSIX only, is the overwriting not happening on Windows?
>
> No because executables on win32 always end with .exe. Even if you do "dmd
> -oftest", DMD will still append an .exe .
But you can accidentally overwrite another .exe file, maybe something you compiled before and now you want to do some temporary test without overwriting that file? I know it looks unlikely, but I think -run should never overwrite any files.
Anyway, your patch is certainly a progress :)
> > Finally, any reason for declaring getuid() manually instead of including the
> > appropriate headers?
>
> The DMC header is unistd.h, but the front-end is also used by GDC and LDC, I
> don't know which headers they use for this function. It seemed easiest to just
> declare the function rather than to include an entire header (remember that
> includes are costly for compile-times in C++).
POSIX says it is in unistd.h, so I guess we can trust different platforms to provide it in that header :)
http://pubs.opengroup.org/onlinepubs/009695299/functions/getuid.html
I will add these comments to the pull request too, just for convenience.
Comment #6 by andrej.mitrovich — 2013-01-08T08:34:15Z
(In reply to comment #5)
>> But you can accidentally overwrite another .exe file
I don't know of any compilers which warn you against this (it should probably be part of a build tool), I thought the enhancement was for when you can accidentally overwrite files which were not generated by the compiler (data files with no extension on posix, for example).
Comment #7 by ibuclaw — 2013-01-08T08:50:44Z
(In reply to comment #3)
> (In reply to comment #2)
> > Can you convert this into a pull request? It will make reviewing more easy.
>
> I'll do it later tonight.
>
> > All your changes are POSIX only, is the overwriting not happening on Windows?
>
> No because executables on win32 always end with .exe. Even if you do "dmd
> -oftest", DMD will still append an .exe .
>
> > Finally, any reason for declaring getuid() manually instead of including the
> > appropriate headers?
>
> The DMC header is unistd.h, but the front-end is also used by GDC and LDC, I
> don't know which headers they use for this function. It seemed easiest to just
> declare the function rather than to include an entire header (remember that
> includes are costly for compile-times in C++).
GDC ifdef's pretty much all of mars.c, so this doesn't affect me.
Comment #8 by leandro.lucarella — 2013-01-08T09:07:05Z
(In reply to comment #6)
> (In reply to comment #5)
> >> But you can accidentally overwrite another .exe file
>
> I don't know of any compilers which warn you against this (it should probably
> be part of a build tool), I thought the enhancement was for when you can
> accidentally overwrite files which were not generated by the compiler (data
> files with no extension on posix, for example).
And I'm not suggesting for DMD to check that when compiling normally. The thing is -run, to the user, is perceived as not generating any files, so it's really unexpected if any file gets removed after running dmd -run somescript.d.
Specially if dmd want to be taken seriously in the scripting world.
But maybe Alex Rønne Petersen is right, dmd -run is an incomplete feature and maybe it should be removed altogether because it might be too hard to do it right and there is already rdmd.
Comment #10 by leandro.lucarella — 2013-11-25T03:25:44Z
https://github.com/D-Programming-Language/dmd/pull/2731 was merged, so I guess this is fixed now. I won't close it because I'm not sure if DMD generate other temporary files (object files for example) that might unexpectedly overwrite other files in the current directory.
Comment #11 by code — 2013-11-30T16:57:19Z
Let's close it, overwriting normal compiler output files is an expected behavior IMO.
Comment #12 by leandro.lucarella — 2013-12-03T03:51:15Z
(In reply to comment #11)
> Let's close it, overwriting normal compiler output files is an expected
> behavior IMO.
No, not really, not in the case where the compiler is behaving as a script interpreter. What it I have a script called `something` and I have a D project that has a `something.d` module that gets compiled to `something.o`, and I want to use my `something` script in that project? If my `something.o` gets replaced by another `something.o` that has nothing to do with my project, the results will be really really ugly and hard to know what really happened.
I still don't know if DMD produces any .o or any other temporary files, maybe it doesn't, but I think we need confirmation before closing this issue.
Comment #13 by gassa — 2014-09-07T07:19:04Z
At least on Windows (both 32 and 64 bits), the overwrite behavior is still present.
To test that, I create p.d (just "void main () {}"), p.exe and p.obj.
Running any of
dmd -run p.d
and
dmd -m64 -run p.d
erases both my p.exe and my p.obj.
Comment #14 by dlang-bugzilla — 2014-09-07T08:00:17Z
I think the real solution here would be to deprecate and undocument the -run switch in favor of rdmd. All this redundant functionality (e.g. also -main and --main) can't be good.
Comment #15 by gassa — 2014-09-07T08:17:24Z
Also, "dmd -run" can't handle multiple source files, while "rdmd" manages to collect the missing pieces when given the file with main() as argument.
Comment #16 by dlang-bugzilla — 2016-10-14T15:09:24Z
(In reply to Ivan Kazmenko from comment #13)
> erases both my p.exe and my p.obj.
I certainly hope you're not complaining about the overwriting of the .obj file!
The attached patch is unacceptable, because:
1. /tmp might be mounted with noexec
2. /tmp might not exist on some systems (e.g. Android)
3. It creates a file with a predictable name, which is a security problem
4. It creates the file with default permissions - if the program contains sensitive data, it could be snooped by another user
(In reply to Leandro Lucarella from comment #12)
> What it I have a script called `something` and I have a D
> project that has a `something.d` module that gets compiled to `something.o`,
> and I want to use my `something` script in that project? If my `something.o`
> gets replaced by another `something.o` that has nothing to do with my
> project, the results will be really really ugly and hard to know what really
> happened.
"Don't do that".
Compilers will generally create object and executable files by replacing extensions on the main file. This applies to D, Rust, Go, Nim, probably others. Demanding that D conforms to your hypothetical convoluted project structure is out of line.
I am going to leave this open because Go does something interesting which we could copy: if the output file exists but it's a script, it produces the error:
---
go install command-line-arguments: build output "hello" already exists and is not an object file
---
We could implement that in DMD, I guess.
Comment #17 by edi33416 — 2016-11-03T12:41:31Z
I am marking this as resolved.
I've reproduced the steps from Leandro's report, but the issue is not present anymore; the test file containing very important data is not erased.
Then I tested the following piece of code:
// test.d
void main(string[] args) {
writeln(args[0]);
}
Running
$ dmd -run test.d
outputs: /tmp/dmd_runnUHV2q
As you can see, dmd -run now builds the code in /tmp/ and runs it from there.
All of the above have been tested using the following dmd version:
DMD64 D Compiler v2.073.0-devel-ab9d712