[前][次][番号順一覧][スレッド一覧]

ruby-changes:62559

From: Peter <ko1@a...>
Date: Wed, 12 Aug 2020 17:54:32 +0900 (JST)
Subject: [ruby-changes:62559] 166cacc505 (master): Fix corruption in ARGF.inplace

https://git.ruby-lang.org/ruby.git/commit/?id=166cacc505

From 166cacc505e5a0d807712e9cb5b6919a7d190a6e Mon Sep 17 00:00:00 2001
From: Peter Zhu <peter@p...>
Date: Wed, 12 Aug 2020 04:54:09 -0400
Subject: Fix corruption in ARGF.inplace

Extension string stored in `ARGF.inplace` is created using an api
designed for C string constants to create a Ruby string that
points at another Ruby string. When the original string is swept,
the extension string gets corrupted.

Reproduction script (on MacOS):

```ruby
#!/usr/bin/ruby -pi.bak

BEGIN {
  GC.start(full_mark: true)
  arr = []
  1000000.times do |x|
    arr << "fooo#{x}"
  end
}

puts "hello"
```

Co-Authored-By: Matt Valentine-House <31869+eightbitraptor@u...>

diff --git a/io.c b/io.c
index 2760e6c..5e4fdd5 100644
--- a/io.c
+++ b/io.c
@@ -12988,7 +12988,7 @@ opt_i_set(VALUE val, ID id, VALUE *var) https://github.com/ruby/ruby/blob/trunk/io.c#L12988
 void
 ruby_set_inplace_mode(const char *suffix)
 {
-    ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_fstring_cstr(suffix);
+    ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_str_new(suffix, strlen(suffix));
 }
 
 /*
diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb
index 277fa36..4734d5b 100644
--- a/test/ruby/test_argf.rb
+++ b/test/ruby/test_argf.rb
@@ -387,6 +387,21 @@ class TestArgf < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_argf.rb#L387
     assert_equal("foo", File.read(name+suffix))
   end
 
+  def test_inplace_bug_17117
+    assert_in_out_err(["-", @t1.path], "#{<<~"{#"}#{<<~'};'}")
+    {#
+      #!/usr/bin/ruby -pi.bak
+      BEGIN {
+        GC.start
+        arr = []
+        1000000.times { |x| arr << "fooo#{x}" }
+      }
+      puts "hello"
+    };
+    assert_equal("hello\n1\nhello\n2\n", File.read(@t1.path))
+    assert_equal("1\n2\n", File.read("#{@t1.path}.bak"))
+  end
+
   def test_encoding
     ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
       {#
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]