[ruby-core:116140] [Ruby master Bug#20175] Broken File.dirname(__FILE__) in eval blocks

Issue #20175 has been reported by kiskoza (Zsolt Kozaroczy). ---------------------------------------- Bug #20175: Broken File.dirname(__FILE__) in eval blocks https://bugs.ruby-lang.org/issues/20175 * Author: kiskoza (Zsolt Kozaroczy) * Status: Open * Priority: Normal * ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- Since #19755 eval use caller location by default, however, it broke `File.dirname(__FILE__)` in some cases. ```ruby # eval.rb eval('puts file: __FILE__, dirname: File.dirname(__FILE__)') ``` Up to Ruby 3.2.2 it gave back the same results, even if it wasn't technically correct in some cases ```bash ## Ruby 3.2.2 ruby eval.rb # {:file=>"(eval)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval)", :dirname=>"."} cd folder && ruby ../eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ruby /Codes/eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ``` In Ruby 3.3.0 (introduced in commit:43a5c19135), it gives back different paths, trying to point to the right directory, but it has the `(eval at ` prefix which makes it broken for codes expecting a valid path. ```bash ## Ruby 3.3.0 ruby eval.rb # {:file=>"(eval at eval.rb:1)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval at ./eval.rb:1)", :dirname=>"(eval at ."} # Broken path cd folder && ruby ../eval.rb # {:file=>"(eval at ../eval.rb:1)", :dirname=>"(eval at .."} # This one is trying to point to the right directory, but it has a broken syntax ruby /Codes/eval.rb # {:file=>"(eval at /Codes/eval.rb:1)", :dirname=>"(eval at /Codes"} # This one is trying to point to the right directory, but it has a broken syntax ``` I was able to reproduce it on current master as well. -- https://bugs.ruby-lang.org/

Issue #20175 has been updated by mame (Yusuke Endoh). Changing `__FILE__` is an intended change, so it is basically unavoidable. I think it is very accidental that `File.dirname("(eval)")` returns `"."`. Please do not depend on it. You may want to replace `File.dirname(__FILE__)` with `__dir__`. If it is difficult for some reason, please elaborate on the context. ---------------------------------------- Bug #20175: Broken File.dirname(__FILE__) in eval blocks https://bugs.ruby-lang.org/issues/20175#change-106150 * Author: kiskoza (Zsolt Kozaroczy) * Status: Open * Priority: Normal * ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- Since #19755 eval use caller location by default, however, it broke `File.dirname(__FILE__)` in some cases. ```ruby # eval.rb eval('puts file: __FILE__, dirname: File.dirname(__FILE__)') ``` Up to Ruby 3.2.2 it gave back the same results, even if it wasn't technically correct in some cases ```bash ## Ruby 3.2.2 ruby eval.rb # {:file=>"(eval)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval)", :dirname=>"."} cd folder && ruby ../eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ruby /Codes/eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ``` In Ruby 3.3.0 (introduced in commit:43a5c19135), it gives back different paths, trying to point to the right directory, but it has the `(eval at ` prefix which makes it broken for codes expecting a valid path. ```bash ## Ruby 3.3.0 ruby eval.rb # {:file=>"(eval at eval.rb:1)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval at ./eval.rb:1)", :dirname=>"(eval at ."} # Broken path cd folder && ruby ../eval.rb # {:file=>"(eval at ../eval.rb:1)", :dirname=>"(eval at .."} # This one is trying to point to the right directory, but it has a broken syntax ruby /Codes/eval.rb # {:file=>"(eval at /Codes/eval.rb:1)", :dirname=>"(eval at /Codes"} # This one is trying to point to the right directory, but it has a broken syntax ``` I was able to reproduce it on current master as well. -- https://bugs.ruby-lang.org/

Issue #20175 has been updated by nobu (Nobuyoshi Nakada). mame (Yusuke Endoh) wrote in #note-1:
You may want to replace `File.dirname(__FILE__)` with `__dir__`.
Note that `__dir__` will return `nil` not a string in that case. ---------------------------------------- Bug #20175: Broken File.dirname(__FILE__) in eval blocks https://bugs.ruby-lang.org/issues/20175#change-106153 * Author: kiskoza (Zsolt Kozaroczy) * Status: Open * Priority: Normal * ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- Since #19755 eval use caller location by default, however, it broke `File.dirname(__FILE__)` in some cases. ```ruby # eval.rb eval('puts file: __FILE__, dirname: File.dirname(__FILE__)') ``` Up to Ruby 3.2.2 it gave back the same results, even if it wasn't technically correct in some cases ```bash ## Ruby 3.2.2 ruby eval.rb # {:file=>"(eval)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval)", :dirname=>"."} cd folder && ruby ../eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ruby /Codes/eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ``` In Ruby 3.3.0 (introduced in commit:43a5c19135), it gives back different paths, trying to point to the right directory, but it has the `(eval at ` prefix which makes it broken for codes expecting a valid path. ```bash ## Ruby 3.3.0 ruby eval.rb # {:file=>"(eval at eval.rb:1)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval at ./eval.rb:1)", :dirname=>"(eval at ."} # Broken path cd folder && ruby ../eval.rb # {:file=>"(eval at ../eval.rb:1)", :dirname=>"(eval at .."} # This one is trying to point to the right directory, but it has a broken syntax ruby /Codes/eval.rb # {:file=>"(eval at /Codes/eval.rb:1)", :dirname=>"(eval at /Codes"} # This one is trying to point to the right directory, but it has a broken syntax ``` I was able to reproduce it on current master as well. -- https://bugs.ruby-lang.org/

Issue #20175 has been updated by kiskoza (Zsolt Kozaroczy). I see why `__FILE__` was an intended change, I'm going to change all my codes inside eval that depends on its value, thanks for pointing it out. However, as `__dir__` returns nil instead of a string, it requires some changes to replace `File.dirname(__FILE__)` with `__dir__`. Is it a viable option to return the already known directory inside evals? The change should be something like this: ```diff diff --git a/vm_eval.c b/vm_eval.c --- a/vm_eval.c +++ b/vm_eval.c @@ -2545,7 +2545,8 @@ rb_current_realfilepath(void) const char *const ptr = RSTRING_PTR(path); if (ptr[len - 1] == ')' && memcmp(ptr, "("EVAL_LOCATION_MARK, EVAL_LOCATION_MARK_LEN+1) == 0) { - return Qnil; + VALUE implicit_path = rb_str_substr(path, 1 + EVAL_LOCATION_MARK_LEN, len - 1); + return implicit_path; } } ``` and then the output would be this: ```ruby # eval.rb eval('puts file: __FILE__, dir: __dir__') ``` ```bash ruby /Codes/eval.rb # {:file=>"(eval at /Codes/eval.rb:1)", :dir=>"/Codes"} ``` ---------------------------------------- Bug #20175: Broken File.dirname(__FILE__) in eval blocks https://bugs.ruby-lang.org/issues/20175#change-106156 * Author: kiskoza (Zsolt Kozaroczy) * Status: Open * Priority: Normal * ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- Since #19755 eval use caller location by default, however, it broke `File.dirname(__FILE__)` in some cases. ```ruby # eval.rb eval('puts file: __FILE__, dirname: File.dirname(__FILE__)') ``` Up to Ruby 3.2.2 it gave back the same results, even if it wasn't technically correct in some cases ```bash ## Ruby 3.2.2 ruby eval.rb # {:file=>"(eval)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval)", :dirname=>"."} cd folder && ruby ../eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ruby /Codes/eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ``` In Ruby 3.3.0 (introduced in commit:43a5c19135), it gives back different paths, trying to point to the right directory, but it has the `(eval at ` prefix which makes it broken for codes expecting a valid path. ```bash ## Ruby 3.3.0 ruby eval.rb # {:file=>"(eval at eval.rb:1)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval at ./eval.rb:1)", :dirname=>"(eval at ."} # Broken path cd folder && ruby ../eval.rb # {:file=>"(eval at ../eval.rb:1)", :dirname=>"(eval at .."} # This one is trying to point to the right directory, but it has a broken syntax ruby /Codes/eval.rb # {:file=>"(eval at /Codes/eval.rb:1)", :dirname=>"(eval at /Codes"} # This one is trying to point to the right directory, but it has a broken syntax ``` I was able to reproduce it on current master as well. -- https://bugs.ruby-lang.org/

Issue #20175 has been updated by mame (Yusuke Endoh). `__dir__ || "." ` is good enough? ---------------------------------------- Bug #20175: Broken File.dirname(__FILE__) in eval blocks https://bugs.ruby-lang.org/issues/20175#change-106157 * Author: kiskoza (Zsolt Kozaroczy) * Status: Open * Priority: Normal * ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux] * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- Since #19755 eval use caller location by default, however, it broke `File.dirname(__FILE__)` in some cases. ```ruby # eval.rb eval('puts file: __FILE__, dirname: File.dirname(__FILE__)') ``` Up to Ruby 3.2.2 it gave back the same results, even if it wasn't technically correct in some cases ```bash ## Ruby 3.2.2 ruby eval.rb # {:file=>"(eval)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval)", :dirname=>"."} cd folder && ruby ../eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ruby /Codes/eval.rb # {:file=>"(eval)", :dirname=>"."} # This one is not pointing to the right directory, but still returns a valid path ``` In Ruby 3.3.0 (introduced in commit:43a5c19135), it gives back different paths, trying to point to the right directory, but it has the `(eval at ` prefix which makes it broken for codes expecting a valid path. ```bash ## Ruby 3.3.0 ruby eval.rb # {:file=>"(eval at eval.rb:1)", :dirname=>"."} ruby ./eval.rb # {:file=>"(eval at ./eval.rb:1)", :dirname=>"(eval at ."} # Broken path cd folder && ruby ../eval.rb # {:file=>"(eval at ../eval.rb:1)", :dirname=>"(eval at .."} # This one is trying to point to the right directory, but it has a broken syntax ruby /Codes/eval.rb # {:file=>"(eval at /Codes/eval.rb:1)", :dirname=>"(eval at /Codes"} # This one is trying to point to the right directory, but it has a broken syntax ``` I was able to reproduce it on current master as well. -- https://bugs.ruby-lang.org/
participants (3)
-
kiskoza (Zsolt Kozaroczy)
-
mame (Yusuke Endoh)
-
nobu (Nobuyoshi Nakada)