On Friday, June 17, 2011 08:35:35 PM Ilias Lazaridis wrote:
> On 18 =C9=EF=FD=ED, 02:30, Yukihiro Matsumoto <m... / ruby-lang.org> wrote:
> > Hi,
> >=20
> > In message "Re: RFC - One word alias for require_relative"
> >=20
> >     on Sat, 18 Jun 2011 06:40:36 +0900, Ilias Lazaridis=20
<il... / lazaridis.com> writes:
[snip]
> > |I like the word "involve" more, but as "require!" reminds clearly the
> > |original "require", it's the first choice.
> >=20
> > Unfortunately the general rule for the "!" in the method name, at
> > least in the standard library, is that it means "more dangerous than
> > the version without bang".  Since require! does not follow this rule,
> > and not worthy to change the rule.  So it's no chance to have require!
> > in the standard library.
>=20
> I've read somewhere that it's a security risk to have the local
> directory in the library path (which "require" accesses). Thus
> "require_relative" became necessary.
>=20
> require_relative *has* the local directory in it's "path",

We've been over this, and I honestly thought you understood last time.

require_relative is relative to the directory containing the current file.=
=20
That is,

  require_relative 'foo'

is equivalent to this:

  require File.join(File.dirname(__FILE__), 'foo')

The security risk you are talking about is from the working directory. That=
=20
is, if require! worked in the "dangerous" way you seem to think it would, i=
t=20
would then be equivalent to this:

  require File.join(Dir.pwd, 'foo')

These are different. They often, but not always, point to the same file, an=
d=20
(surprisingly) you acknowledged this and admitted your mistake.

Now, requiring relative to the working directory is a security risk. As I'v=
e=20
explained (to you!) before: Suppose I put a ruby script in my PATH, to use =
as=20
a command. It has 'require "foo"' in it. If I then cd into some untrusted=20
directory and run my command, some clever user could have put a malicious=20
foo.rb file in that directory. It doesn't have to be me, either -- suppose =
my=20
Ruby script is setuid root. Now any user can create, at their leisure, a=20
malicious Ruby script with the name of one of the libraries required by thi=
s=20
script, and run it, and now they've rooted my machine.

This isn't even particularly far-fetched. I realize it doesn't apply to you=
,=20
being on Windows and all, but this is a use case Ruby fits particularly wel=
l.

By contrast, requiring relative to the current file isn't dangerous at all.=
=20
Unless the attacker has write access to the directory you've installed the=
=20
script into, they can't inject anything.

So, sorry, it's not dangerous in any sense that would suggest a bang method=
=2E=20
It's just different, and it's different in that it's, well, relative to the=
=20
current file. I wonder how we would name a method that is different in that=
=20
it's _relative_ to something. Hmm...

> It is "more
> powerful than the version without bang" - and thus "more dangerous".

Nope, "more powerful" isn't what's meant by "more dangerous".

It's also not necessarily true here. The standard system require is pretty=
=20
powerful -- require_relative can only require relative to the current file,=
=20
while the system require can require relative to a configurable list of=20
directories. Seems like the system require is more powerful to me.

An example of something which is "more dangerous" -- in DataMapper, there a=
re=20
bang versions of save, update, delete, etc, which bypass validations in ord=
er=20
to be more efficient (often resulting in only executing a single line of SQ=
L=20
instead of having to load each record and perform validations before=20
saving/deleting). And of course, you should be familiar with things like=20
Array#sort vs Array#sort! -- one modifies the original array, the other=20
creates a copy first, and is thus safer if you don't know who might have th=
e=20
original array.

> But even if not, the "!" rule could be extended

Didn't Matz have something to say about that? I think he did:

On Friday, June 17, 2011 06:30:32 PM Yukihiro Matsumoto wrote:
> Since require! does not follow this rule,
> and not worthy to change the rule.  So it's no chance to have require!
> in the standard library.

Not worthy to change the rule. But even if we change it to this (if this is=
n't=20
already a fair description):

> "!" for "flat" functions (e.g. "flat" Kernel functions which do not
> operate strictly on an object) is used to indicate:
>  * "you should know what you do, possible risks" (=3D more dangerous),
> or
>  * "more powerful implementation", (essentially this means: more
> dangerous).

require_relative is neither riskier, nor more powerful, nor more dangerous,=
=20
and there's no particular reason you need to know what you're doing with it=
=20
more than with require.

It's. Just. Different.
That's all.

And the way in which it's different is described by the current name.