ruby-changes:50325
From: nagachika <ko1@a...>
Date: Sat, 17 Feb 2018 01:25:45 +0900 (JST)
Subject: [ruby-changes:50325] nagachika:r62440 (ruby_2_4): merge revision(s) 59983, 59984: [Backport #10222] [Backport #14372] [Backport #14424]
nagachika 2018-02-17 01:25:40 +0900 (Sat, 17 Feb 2018) New Revision: 62440 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62440 Log: merge revision(s) 59983,59984: [Backport #10222] [Backport #14372] [Backport #14424] file.c: rb_check_realpath * file.c (rb_check_realpath): returns real path which has no symbolic links. similar to rb_realpath except for returning Qnil if any parts did not exist. load.c: real path to load * load.c (rb_construct_expanded_load_path): expand load paths to real paths to get rid of duplicate loading from symbolic-linked directories. [Feature #10222] Modified directories: branches/ruby_2_4/ Modified files: branches/ruby_2_4/file.c branches/ruby_2_4/internal.h branches/ruby_2_4/load.c branches/ruby_2_4/test/ruby/test_exception.rb branches/ruby_2_4/test/ruby/test_require.rb branches/ruby_2_4/version.h Index: ruby_2_4/file.c =================================================================== --- ruby_2_4/file.c (revision 62439) +++ ruby_2_4/file.c (revision 62440) @@ -3757,8 +3757,29 @@ rb_file_s_absolute_path(int argc, const https://github.com/ruby/ruby/blob/trunk/ruby_2_4/file.c#L3757 return rb_file_absolute_path(argv[0], argc > 1 ? argv[1] : Qnil); } -static void -realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE loopcheck, int strict, int last) +#ifdef __native_client__ +VALUE +rb_realpath_internal(VALUE basedir, VALUE path, int strict) +{ + return path; +} + +VALUE +rb_check_realpath(VALUE basedir, VALUE path) +{ + return path; +} +#else +enum rb_realpath_mode { + RB_REALPATH_CHECK, + RB_REALPATH_DIR, + RB_REALPATH_STRICT, + RB_REALPATH_MODE_MAX +}; + +static int +realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, + VALUE loopcheck, enum rb_realpath_mode mode, int last) { const char *pend = unresolved + strlen(unresolved); rb_encoding *enc = rb_enc_get(*resolvedp); @@ -3799,6 +3820,10 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/ruby_2_4/file.c#L3820 checkval = rb_hash_aref(loopcheck, testpath); if (!NIL_P(checkval)) { if (checkval == ID2SYM(resolving)) { + if (mode == RB_REALPATH_CHECK) { + errno = ELOOP; + return -1; + } rb_syserr_fail_path(ELOOP, testpath); } else { @@ -3816,8 +3841,9 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/ruby_2_4/file.c#L3841 #endif if (ret == -1) { int e = errno; + if (mode == RB_REALPATH_CHECK) return -1; if (e == ENOENT) { - if (strict || !last || *unresolved_firstsep) + if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep) rb_syserr_fail_path(e, testpath); *resolvedp = testpath; break; @@ -3846,7 +3872,9 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/ruby_2_4/file.c#L3872 *resolvedp = link; *prefixlenp = link_prefixlen; } - realpath_rec(prefixlenp, resolvedp, link_names, loopcheck, strict, *unresolved_firstsep == '\0'); + if (realpath_rec(prefixlenp, resolvedp, link_names, + loopcheck, mode, !*unresolved_firstsep)) + return -1; RB_GC_GUARD(link_orig); rb_hash_aset(loopcheck, testpath, rb_str_dup_frozen(*resolvedp)); } @@ -3860,17 +3888,11 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/ruby_2_4/file.c#L3888 } } } + return 0; } -#ifdef __native_client__ -VALUE -rb_realpath_internal(VALUE basedir, VALUE path, int strict) -{ - return path; -} -#else -VALUE -rb_realpath_internal(VALUE basedir, VALUE path, int strict) +static VALUE +rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode) { long prefixlen; VALUE resolved; @@ -3937,11 +3959,16 @@ rb_realpath_internal(VALUE basedir, VALU https://github.com/ruby/ruby/blob/trunk/ruby_2_4/file.c#L3959 } loopcheck = rb_hash_new(); - if (curdir_names) - realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, 1, 0); - if (basedir_names) - realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, 1, 0); - realpath_rec(&prefixlen, &resolved, path_names, loopcheck, strict, 1); + if (curdir_names) { + if (realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, mode, 0)) + return Qnil; + } + if (basedir_names) { + if (realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, mode, 0)) + return Qnil; + } + if (realpath_rec(&prefixlen, &resolved, path_names, loopcheck, mode, 1)) + return Qnil; if (origenc != enc && rb_enc_str_asciionly_p(resolved)) rb_enc_associate(resolved, origenc); @@ -3949,6 +3976,20 @@ rb_realpath_internal(VALUE basedir, VALU https://github.com/ruby/ruby/blob/trunk/ruby_2_4/file.c#L3976 OBJ_TAINT(resolved); return resolved; } + +VALUE +rb_realpath_internal(VALUE basedir, VALUE path, int strict) +{ + const enum rb_realpath_mode mode = + strict ? RB_REALPATH_STRICT : RB_REALPATH_DIR; + return rb_check_realpath_internal(basedir, path, mode); +} + +VALUE +rb_check_realpath(VALUE basedir, VALUE path) +{ + return rb_check_realpath_internal(basedir, path, RB_REALPATH_CHECK); +} #endif /* Index: ruby_2_4/test/ruby/test_require.rb =================================================================== --- ruby_2_4/test/ruby/test_require.rb (revision 62439) +++ ruby_2_4/test/ruby/test_require.rb (revision 62440) @@ -809,4 +809,18 @@ class TestRequire < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_4/test/ruby/test_require.rb#L809 end; end end + + def test_symlink_load_path + Dir.mktmpdir {|tmp| + Dir.mkdir(File.join(tmp, "real")) + begin + File.symlink "real", File.join(tmp, "symlink") + rescue NotImplementedError, Errno::EACCES + skip "File.symlink is not implemented" + end + File.write(File.join(tmp, "real/a.rb"), "print __FILE__") + result = IO.popen([EnvUtil.rubybin, "-I#{tmp}/symlink", "-e", "require 'a.rb'"], &:read) + assert_operator(result, :end_with?, "/real/a.rb") + } + end end Index: ruby_2_4/test/ruby/test_exception.rb =================================================================== --- ruby_2_4/test/ruby/test_exception.rb (revision 62439) +++ ruby_2_4/test/ruby/test_exception.rb (revision 62440) @@ -983,7 +983,7 @@ $stderr = $stdout; raise "\x82\xa0"') do https://github.com/ruby/ruby/blob/trunk/ruby_2_4/test/ruby/test_exception.rb#L983 path = nil Tempfile.create(%w[circular .rb]) do |t| begin - path = t.path + path = File.realpath(t.path) basename = File.basename(path) t.puts "require '#{basename}'" t.close Index: ruby_2_4/internal.h =================================================================== --- ruby_2_4/internal.h (revision 62439) +++ ruby_2_4/internal.h (revision 62440) @@ -1051,6 +1051,7 @@ void rb_mark_end_proc(void); https://github.com/ruby/ruby/blob/trunk/ruby_2_4/internal.h#L1051 VALUE rb_home_dir_of(VALUE user, VALUE result); VALUE rb_default_home_dir(VALUE result); VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); +VALUE rb_check_realpath(VALUE basedir, VALUE path); void rb_file_const(const char*, VALUE); int rb_file_load_ok(const char *); VALUE rb_file_expand_path_fast(VALUE, VALUE); Index: ruby_2_4/load.c =================================================================== --- ruby_2_4/load.c (revision 62439) +++ ruby_2_4/load.c (revision 62440) @@ -85,7 +85,8 @@ rb_construct_expanded_load_path(enum exp https://github.com/ruby/ruby/blob/trunk/ruby_2_4/load.c#L85 if (is_string) rb_str_freeze(path); as_str = rb_get_path_check_convert(path, as_str, level); - expanded_path = rb_file_expand_path_fast(as_str, Qnil); + expanded_path = rb_check_realpath(Qnil, as_str); + if (NIL_P(expanded_path)) expanded_path = as_str; rb_str_freeze(expanded_path); rb_ary_push(ary, rb_fstring(expanded_path)); } Index: ruby_2_4/version.h =================================================================== --- ruby_2_4/version.h (revision 62439) +++ ruby_2_4/version.h (revision 62440) @@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_4/version.h#L1 #define RUBY_VERSION "2.4.4" #define RUBY_RELEASE_DATE "2018-02-17" -#define RUBY_PATCHLEVEL 238 +#define RUBY_PATCHLEVEL 239 #define RUBY_RELEASE_YEAR 2018 #define RUBY_RELEASE_MONTH 2 Index: ruby_2_4 =================================================================== --- ruby_2_4 (revision 62439) +++ ruby_2_4 (revision 62440) Property changes on: ruby_2_4 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /trunk:r59983-59984 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/