unlink() on "~" removes the home directory

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

unlink() on "~" removes the home directory

Gábor Csárdi
!!! DON'T TRY THE CODE IN THIS EMAIL AT HOME !!!

Well, unlink() does what it is supposed to do, so you could argue that
there is nothing wrong with it. Also, nobody would call unlink() on
"~", right?

The situation is not so simple, however. E.g. if you happen to have a
directory called "~", and you iterate over all files and directories
to selectively remove some of them, then your code might end up
calling unlink on the local "~" directory, and then your home is gone.

But you would not create a directory named "~", that is just asking
for trouble. Well, surely, _intentionally_ you would not do that.
Unintentionally, you might. E.g. something like this is enough:

# Create a subpath within a base directory
badfun <- function(base = ".", path) {
  dir.create(file.path(base, path), recursive = TRUE, showWarnings = FALSE)
}
badfun(path = "~/foo")

(If you did run this, be very careful how you remove the directory called "~"!)

A real example is `R CMD build` which deletes the home directory of
the current user if the root of the package contains a non-empty "~"
directory. Luckily this is now fixed in R-devel, so R 4.0.0 will do
better. (R 3.6.3 will not.) See
https://github.com/wch/r-source/commit/1d4f7aa1dac427ea2213d1f7cd7b5c16e896af22

I have seen several bug reports about various packages (that call R
CMD build) removing the home directory, so this indeed happens in
practice to a number of people. The commit above will fix `R CMD
build`, but it would be great to "fix" this in general.

It seems pretty hard to prevent users from creating of a "~"
directory. But preventing unlink() from deleting "~" does not actually
seem too hard. If unlink() could just refuse removing "~" (when expand
= TRUE), that would be great. It seems to me that the current behavior
is very-very rarely intended, and its consequences are potentially
disastrous.

If unlink("~", recursive = TRUE) errors, you can still remove a local
"~" file/dir with unlink("./~", ...). And you can still remove your
home directory if you really want to do that, with
unlink(path.expand("~"), ...). So no functionality is lost.

Also, if anyone is aware of packages/functions that tend to create "~"
directories or files, please let me know.

I would be happy to submit a patch for the new unlink("~") behavior.

Thanks,
Gabor

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: unlink() on "~" removes the home directory

Hervé Pagès-2
On 2/26/20 14:47, Gábor Csárdi wrote:
> !!! DON'T TRY THE CODE IN THIS EMAIL AT HOME !!!

Ok I'll try it at work on my boss's computer, sounds a lot safer.

H.

>
> Well, unlink() does what it is supposed to do, so you could argue that
> there is nothing wrong with it. Also, nobody would call unlink() on
> "~", right?
>
> The situation is not so simple, however. E.g. if you happen to have a
> directory called "~", and you iterate over all files and directories
> to selectively remove some of them, then your code might end up
> calling unlink on the local "~" directory, and then your home is gone.
>
> But you would not create a directory named "~", that is just asking
> for trouble. Well, surely, _intentionally_ you would not do that.
> Unintentionally, you might. E.g. something like this is enough:
>
> # Create a subpath within a base directory
> badfun <- function(base = ".", path) {
>    dir.create(file.path(base, path), recursive = TRUE, showWarnings = FALSE)
> }
> badfun(path = "~/foo")
>
> (If you did run this, be very careful how you remove the directory called "~"!)
>
> A real example is `R CMD build` which deletes the home directory of
> the current user if the root of the package contains a non-empty "~"
> directory. Luckily this is now fixed in R-devel, so R 4.0.0 will do
> better. (R 3.6.3 will not.) See
> https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_wch_r-2Dsource_commit_1d4f7aa1dac427ea2213d1f7cd7b5c16e896af22&d=DwICAg&c=eRAMFD45gAfqt84VtBcfhQ&r=BK7q3XeAvimeWdGbWY_wJYbW0WYiZvSXAJJKaaPhzWA&m=C3VCGF44o7jATPOlC8aZhaT4YGU1JtcOixJKZgu6KyI&s=iWNt-0G2gZa99bnOqNBMOHph0NyVoJdsIwuA07GhJZQ&e=
>
> I have seen several bug reports about various packages (that call R
> CMD build) removing the home directory, so this indeed happens in
> practice to a number of people. The commit above will fix `R CMD
> build`, but it would be great to "fix" this in general.
>
> It seems pretty hard to prevent users from creating of a "~"
> directory. But preventing unlink() from deleting "~" does not actually
> seem too hard. If unlink() could just refuse removing "~" (when expand
> = TRUE), that would be great. It seems to me that the current behavior
> is very-very rarely intended, and its consequences are potentially
> disastrous.
>
> If unlink("~", recursive = TRUE) errors, you can still remove a local
> "~" file/dir with unlink("./~", ...). And you can still remove your
> home directory if you really want to do that, with
> unlink(path.expand("~"), ...). So no functionality is lost.
>
> Also, if anyone is aware of packages/functions that tend to create "~"
> directories or files, please let me know.
>
> I would be happy to submit a patch for the new unlink("~") behavior.
>
> Thanks,
> Gabor
>
> ______________________________________________
> [hidden email] mailing list
> https://urldefense.proofpoint.com/v2/url?u=https-3A__stat.ethz.ch_mailman_listinfo_r-2Ddevel&d=DwICAg&c=eRAMFD45gAfqt84VtBcfhQ&r=BK7q3XeAvimeWdGbWY_wJYbW0WYiZvSXAJJKaaPhzWA&m=C3VCGF44o7jATPOlC8aZhaT4YGU1JtcOixJKZgu6KyI&s=FeZWU9uN-HwDNkSBOmbYXiGqu8q8-U6DI-ddyUn7HHw&e=
>

--
Hervé Pagès

Program in Computational Biology
Division of Public Health Sciences
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N, M1-B514
P.O. Box 19024
Seattle, WA 98109-1024

E-mail: [hidden email]
Phone:  (206) 667-5791
Fax:    (206) 667-1319

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: unlink() on "~" removes the home directory

Tomas Kalibera
In reply to this post by Gábor Csárdi
To clarify, these issues are about deleting the contents of the home
directory, not the directory itself, which cannot be deleted by ordinary
users on today's systems. Unfortunately this has to be fixed in the code
that calls unlink(), such code must be aware of the expansions. The "R
CMD build" case as you write has been fixed, if anyone finds any other
instance of this problem in base R, please report, it will be fixed as
well. The new argument "expand" has been added to unlink() to make these
fixes easier.

A variation on what you propose: tilde ("~") is now treated the same way
as "." and ".." have already been by unlink(), which means it will never
be considered for deletion (not even with expand=TRUE). There are still
a number of ways to delete the contents of one's home directory,
including tilde expansion with user name, with directory separators,
etc.  This special treatment of "~" will prevent only one pattern of the
problem. One should always be careful when recursively/programmatically
deleting files.

Also, the new behavior can cause trouble in some cases when a file or
directory named tilde exists, but hopefully not as bad as deleting the
contents of user home directory. In principle, such file can still be
deleted from R using a combination of tilde and wildcards with wildcard
expansion enabled.

Best
Tomas

On 2/26/20 11:47 PM, Gábor Csárdi wrote:

> !!! DON'T TRY THE CODE IN THIS EMAIL AT HOME !!!
>
> Well, unlink() does what it is supposed to do, so you could argue that
> there is nothing wrong with it. Also, nobody would call unlink() on
> "~", right?
>
> The situation is not so simple, however. E.g. if you happen to have a
> directory called "~", and you iterate over all files and directories
> to selectively remove some of them, then your code might end up
> calling unlink on the local "~" directory, and then your home is gone.
>
> But you would not create a directory named "~", that is just asking
> for trouble. Well, surely, _intentionally_ you would not do that.
> Unintentionally, you might. E.g. something like this is enough:
>
> # Create a subpath within a base directory
> badfun <- function(base = ".", path) {
>    dir.create(file.path(base, path), recursive = TRUE, showWarnings = FALSE)
> }
> badfun(path = "~/foo")
>
> (If you did run this, be very careful how you remove the directory called "~"!)
>
> A real example is `R CMD build` which deletes the home directory of
> the current user if the root of the package contains a non-empty "~"
> directory. Luckily this is now fixed in R-devel, so R 4.0.0 will do
> better. (R 3.6.3 will not.) See
> https://github.com/wch/r-source/commit/1d4f7aa1dac427ea2213d1f7cd7b5c16e896af22
>
> I have seen several bug reports about various packages (that call R
> CMD build) removing the home directory, so this indeed happens in
> practice to a number of people. The commit above will fix `R CMD
> build`, but it would be great to "fix" this in general.
>
> It seems pretty hard to prevent users from creating of a "~"
> directory. But preventing unlink() from deleting "~" does not actually
> seem too hard. If unlink() could just refuse removing "~" (when expand
> = TRUE), that would be great. It seems to me that the current behavior
> is very-very rarely intended, and its consequences are potentially
> disastrous.
>
> If unlink("~", recursive = TRUE) errors, you can still remove a local
> "~" file/dir with unlink("./~", ...). And you can still remove your
> home directory if you really want to do that, with
> unlink(path.expand("~"), ...). So no functionality is lost.
>
> Also, if anyone is aware of packages/functions that tend to create "~"
> directories or files, please let me know.
>
> I would be happy to submit a patch for the new unlink("~") behavior.
>
> Thanks,
> Gabor
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: unlink() on "~" removes the home directory

Gábor Csárdi
Thanks,

I saw the commit, and it seems like a great fix to me!

Best,
Gabor

On Mon, Mar 23, 2020 at 5:04 PM Tomas Kalibera <[hidden email]> wrote:

>
> To clarify, these issues are about deleting the contents of the home
> directory, not the directory itself, which cannot be deleted by ordinary
> users on today's systems. Unfortunately this has to be fixed in the code
> that calls unlink(), such code must be aware of the expansions. The "R
> CMD build" case as you write has been fixed, if anyone finds any other
> instance of this problem in base R, please report, it will be fixed as
> well. The new argument "expand" has been added to unlink() to make these
> fixes easier.
>
> A variation on what you propose: tilde ("~") is now treated the same way
> as "." and ".." have already been by unlink(), which means it will never
> be considered for deletion (not even with expand=TRUE). There are still
> a number of ways to delete the contents of one's home directory,
> including tilde expansion with user name, with directory separators,
> etc.  This special treatment of "~" will prevent only one pattern of the
> problem. One should always be careful when recursively/programmatically
> deleting files.
>
> Also, the new behavior can cause trouble in some cases when a file or
> directory named tilde exists, but hopefully not as bad as deleting the
> contents of user home directory. In principle, such file can still be
> deleted from R using a combination of tilde and wildcards with wildcard
> expansion enabled.
>
> Best
> Tomas
>
> On 2/26/20 11:47 PM, Gábor Csárdi wrote:
> > !!! DON'T TRY THE CODE IN THIS EMAIL AT HOME !!!
> >
> > Well, unlink() does what it is supposed to do, so you could argue that
> > there is nothing wrong with it. Also, nobody would call unlink() on
> > "~", right?
> >
> > The situation is not so simple, however. E.g. if you happen to have a
> > directory called "~", and you iterate over all files and directories
> > to selectively remove some of them, then your code might end up
> > calling unlink on the local "~" directory, and then your home is gone.
> >
> > But you would not create a directory named "~", that is just asking
> > for trouble. Well, surely, _intentionally_ you would not do that.
> > Unintentionally, you might. E.g. something like this is enough:
> >
> > # Create a subpath within a base directory
> > badfun <- function(base = ".", path) {
> >    dir.create(file.path(base, path), recursive = TRUE, showWarnings = FALSE)
> > }
> > badfun(path = "~/foo")
> >
> > (If you did run this, be very careful how you remove the directory called "~"!)
> >
> > A real example is `R CMD build` which deletes the home directory of
> > the current user if the root of the package contains a non-empty "~"
> > directory. Luckily this is now fixed in R-devel, so R 4.0.0 will do
> > better. (R 3.6.3 will not.) See
> > https://github.com/wch/r-source/commit/1d4f7aa1dac427ea2213d1f7cd7b5c16e896af22
> >
> > I have seen several bug reports about various packages (that call R
> > CMD build) removing the home directory, so this indeed happens in
> > practice to a number of people. The commit above will fix `R CMD
> > build`, but it would be great to "fix" this in general.
> >
> > It seems pretty hard to prevent users from creating of a "~"
> > directory. But preventing unlink() from deleting "~" does not actually
> > seem too hard. If unlink() could just refuse removing "~" (when expand
> > = TRUE), that would be great. It seems to me that the current behavior
> > is very-very rarely intended, and its consequences are potentially
> > disastrous.
> >
> > If unlink("~", recursive = TRUE) errors, you can still remove a local
> > "~" file/dir with unlink("./~", ...). And you can still remove your
> > home directory if you really want to do that, with
> > unlink(path.expand("~"), ...). So no functionality is lost.
> >
> > Also, if anyone is aware of packages/functions that tend to create "~"
> > directories or files, please let me know.
> >
> > I would be happy to submit a patch for the new unlink("~") behavior.
> >
> > Thanks,
> > Gabor
> >
> > ______________________________________________
> > [hidden email] mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
>
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel