From 6cc784a12707d517139481a0a67ca84a02eb4690 Mon Sep 17 00:00:00 2001 From: Hiroshi Shirosaki Date: Mon, 19 Nov 2012 22:25:22 +0900 Subject: [PATCH] Fix cache validity check of require If #pop or #shift has been called against $: or $", the array will be still shared with the snapshot. We check array length for cache validity. --- array.c | 11 +++++++---- test/ruby/test_require.rb | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/array.c b/array.c index 25fd829..9371ef7 100644 --- a/array.c +++ b/array.c @@ -351,13 +351,16 @@ rb_ary_frozen_p(VALUE ary) e.g. rb_ary_replace) and check later whether the array has been modified from the snapshot. The snapshot is cheap, though if something does modify the array it will pay the cost of copying - it. */ + it. If Array#pop or Array#shift has been called, the array will + be still shared with the snapshot, but the array length will + differ. */ VALUE rb_ary_shared_with_p(VALUE ary1, VALUE ary2) { - if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) - && !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) - && RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared) { + if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) && + !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) && + RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared && + RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) { return Qtrue; } return Qfalse; diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb index 36d7c78..f112140 100644 --- a/test/ruby/test_require.rb +++ b/test/ruby/test_require.rb @@ -545,4 +545,35 @@ class TestRequire < Test::Unit::TestCase } } end + + def assert_require_with_shared_array(add, del) + bug7383 = '[ruby-core:49518]' + Dir.mktmpdir {|tmp| + Dir.chdir(tmp) { + open("foo.rb", "w") {} + Dir.mkdir("a") + open(File.join("a", "bar.rb"), "w") {} + assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7383) + $:.#{add} "#{tmp}" + $:.#{add} "#{tmp}/a" + require "foo" + $:.#{del} + # Expanded load path cache should be rebuilt. + begin + require "bar" + rescue LoadError + p :ok + end + INPUT + } + } + end + + def test_require_with_array_pop + assert_require_with_shared_array("push", "pop") + end + + def test_require_with_array_shift + assert_require_with_shared_array("unshift", "shift") + end end -- 1.7.10.2 (Apple Git-33)