Bug #4487
closedrequire_relative fails in an eval'ed file
Added by rogerdpack (Roger Pack) over 14 years ago. Updated almost 8 years ago.
Description
=begin
Hello all.
$cat eval_me1.rb
eval(File.read('eval_me2.rb'), binding, File.expand_path('./eval_me2.rb'))
$cat eval_me2.rb
require_relative 'eval_me1.rb'
$ ruby eval_me1.rb
C:/dev/ruby/faster_require/spec/eval_me2.rb:1:in require_relative': cannot infer basepath (LoadError) from C:/dev/ruby/faster_require/spec/eval_me2.rb:1:in
'
from eval_me1.rb:1:in eval' from eval_me1.rb:1:in
'
I suppose was assuming that if eval included a filename, then require_relative would work from within it. Perhaps I am mistaken?
Thanks!
-r
=end
Updated by naruse (Yui NARUSE) over 14 years ago
Actions
#1
[ruby-core:37465]
- Status changed from Open to Assigned
- Assignee set to mame (Yusuke Endoh)
Updated by mame (Yusuke Endoh) over 14 years ago
Actions
#2
[ruby-core:37785]
- ruby -v changed from ruby 1.9.3dev (2011-03-04 trunk 31024) [i386-mingw32] to -
Hello,
 $cat eval_me1.rb
 eval(File.read('eval_me2.rb'), binding, File.expand_path('./eval_me2.rb'))
 $cat eval_me2.rb
 require_relative 'eval_me1.rb'
 $ ruby eval_me1.rb
 C:/dev/ruby/faster_require/spec/eval_me2.rb:1:inrequire_relative': cannot infer basepath (LoadError)     from C:/dev/ruby/faster_require/spec/eval_me2.rb:1:in
'
    from eval_me1.rb:1:ineval'     from eval_me1.rb:1:in
'I suppose was assuming that if eval included a filename, then require_relative would work from within it. Perhaps I am mistaken?
I think your expectation is reasonable, though I personally dislike
the eval's feature to fake filepath.
The following patch makes require_relative use the given file path.
I'm afraid if I should include this patch in 1.9.3 because I can't
estimate the impact of this patch. What do you think?
diff --git a/vm_eval.c b/vm_eval.c
index 7df7f5f..3710401 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -1007,7 +1007,7 @@ eval_string_with_cref(VALUE self, VALUE src,
VALUE scope, NODE cref, const char
/ make eval iseq */
th->parse_in_eval++;
th->mild_compile_error++;
- iseqval
Updated by mame (Yusuke Endoh) over 14 years ago
Actions
#3
[ruby-core:37791]
- Assignee changed from mame (Yusuke Endoh) to matz (Yukihiro Matsumoto)
Updated by LTe (Piotr Niełacny) over 13 years ago
Actions
#4
[ruby-core:46196]
=begin
If in irb we can execute
(({load("file.rb")}))
why we can't
(({require_relative("file")}))
Ruby just return exception (LoadError: cannot infer basepath). Unfortunately, this is a 'lie' because ruby can recognize basepath.
=end
Updated by shyouhei (Shyouhei Urabe) over 13 years ago
Actions
#5
[ruby-core:46197]
=begin
@LTe sorry, I can't get it. load loads from $LOAD_PATH, while require_relative requires from relative path. They are different.
=end
Updated by LTe (Piotr Niełacny) over 13 years ago
Actions
#6
[ruby-core:46221]
@shyouhei (Shyouhei Urabe) yes I agree but load method tries to load file from relative path. When load method can't find file in relative path it loads from $LOAD_PATH. The same can be done by require_relative (recognize path).
Updated by shyouhei (Shyouhei Urabe) over 13 years ago
Actions
#7
[ruby-core:46226]
=begin
@LTe I'd rather ask you "require_relative loads something relative from WHAT?"
Obviously it is not relative from your mind :)
Current require_relative loads relative from where the require_relative command is written. So when in IRB sessions, it fails to infer where it is beacuse the command is written in a non-file (console).
OTOH load loads from process PWD, which is possible in IRB.
So the point is, if you want require_relative to work on an IRB session, you have to define "from where require_relative should search relativeness".
=end
Updated by Eregon (Benoit Daloze) over 13 years ago
Actions
#8
[ruby-core:46228]
shyouhei (Shyouhei Urabe) wrote:
Current require_relative loads relative from where the require_relative command is written. So when in IRB sessions, it fails to infer where it is beacuse the command is written in a non-file (console).
OTOH load loads from process PWD, which is possible in IRB.
So the point is, if you want require_relative to work on an IRB session, you have to define "from where require_relative should search relativeness".
From the process current working directory I guess, especially since you almost always launch IRB from a terminal.
Personally I'm doing require './myfile'
which is not the most elegant, but if you don't have completion in IRB, that's shorter to type.
Otherwise, there's always the option to do irb -I.
and use plain require
.
Updated by naruse (Yui NARUSE) over 13 years ago
Actions
#9
[ruby-core:46230]
Eregon (Benoit Daloze) wrote:
shyouhei (Shyouhei Urabe) wrote:
Current require_relative loads relative from where the require_relative command is written. So when in IRB sessions, it fails to infer where it is beacuse the command is written in a non-file (console).
OTOH load loads from process PWD, which is possible in IRB.
So the point is, if you want require_relative to work on an IRB session, you have to define "from where require_relative should search relativeness".
From the process current working directory I guess, especially since you almost always launch IRB from a terminal.
Personally I'm doing
require './myfile'
which is not the most elegant, but if you don't have completion in IRB, that's shorter to type.Otherwise, there's always the option to do
irb -I.
and use plainrequire
.
require_relative is introduced to avoid accidentally require a malicious file on the current working directory.
So it can't be acceptable.
Use require or load on such case.
Updated by shyouhei (Shyouhei Urabe) over 13 years ago
Actions
#10
[ruby-core:46231]
naruse (Yui NARUSE) wrote:
require_relative is introduced to avoid accidentally require a malicious file on the current working directory.
So it can't be acceptable.
Use require or load on such case.
I'm not pretty sure about this. Is there a chance for a (proposed behaviour of) require_relative to require a malicious file on the current directory?
Because you are on an IRB session and intentionally emitting require_relative (not require), I doubt the danger you say.
Updated by naruse (Yui NARUSE) over 13 years ago
Actions
#11
[ruby-core:46232]
shyouhei (Shyouhei Urabe) wrote:
naruse (Yui NARUSE) wrote:
require_relative is introduced to avoid accidentally require a malicious file on the current working directory.
So it can't be acceptable.
Use require or load on such case.I'm not pretty sure about this. Is there a chance for a (proposed behaviour of) require_relative to require a malicious file on the current directory?
Because you are on an IRB session and intentionally emitting require_relative (not require), I doubt the danger you say.
- irb is not the only user of eval.
- A user won't always use require_relative intentionally.
- There is a suitable another way: require './myfile'
With those reason, I don't think require_relative should be changed.
Updated by Eregon (Benoit Daloze) over 13 years ago
Actions
#12
[ruby-core:46233]
naruse (Yui NARUSE) wrote:
Eregon (Benoit Daloze) wrote:
From the process current working directory I guess, especially since you almost always launch IRB from a terminal.
require_relative is introduced to avoid accidentally require a malicious file on the current working directory.
So it can't be acceptable.
Use require or load on such case.
I see, you're right.
Indeed, with this in mind I think it's not worth changing, and the actual require_relative behavior is clearer (relative to "this file" directory, if there is no accurate "this file", just #raise).
Updated by ko1 (Koichi Sasada) over 13 years ago
Actions
#13
[ruby-core:46414]
- Assignee changed from matz (Yukihiro Matsumoto) to mame (Yusuke Endoh)
mame-san, please ask matz.
Updated by mame (Yusuke Endoh) over 12 years ago
Actions
#14
[ruby-core:51804]
- Subject changed from require_relative fails in an eval'ed file to require_relative fails in an eval'ed file
- Assignee changed from mame (Yusuke Endoh) to matz (Yukihiro Matsumoto)
- Target version set to 2.6
Updated by Conrad.Irwin (Conrad Irwin) over 12 years ago
Actions
#15
[ruby-core:53659]
This bug also affects pry: https://github.com/pry/pry/issues/880. Our use-case is slightly different because we are doing TOPLEVEL_BINDING.eval("some code", "/absolute/path.rb").
I think that when an absolute path is set in eval, then require_relative should use it.
Updated by julik (Julik Tarkhanov) about 10 years ago
Actions
#16
This is actually very pertinent for Rack as well, because currently config.ru does not support require_relative which is very counterintuitive.
Updated by mame (Yusuke Endoh) almost 8 years ago
Actions
#17
[ruby-core:84123]
- Status changed from Assigned to Closed
Now, it works. I'm unsure who changed the behavior... Anyway, closing.