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

ruby-changes:56314

From: Nobuyoshi <ko1@a...>
Date: Mon, 1 Jul 2019 16:25:56 +0900 (JST)
Subject: [ruby-changes:56314] Nobuyoshi Nakada: 78ee2c2453 (master): marshal.c: check instance variable count

https://git.ruby-lang.org/ruby.git/commit/?id=78ee2c2453

From 78ee2c245331e353e218b8fac9ca722a2bcd8fea Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Mon, 1 Jul 2019 16:20:03 +0900
Subject: marshal.c: check instance variable count

* marshal.c (w_ivar_each): ensure that no instance variable was
  removed while dumping other instance variables.  [Bug #15968]

diff --git a/marshal.c b/marshal.c
index c89ef96..9ac8847 100644
--- a/marshal.c
+++ b/marshal.c
@@ -258,7 +258,7 @@ class2path(VALUE klass) https://github.com/ruby/ruby/blob/trunk/marshal.c#L258
 
 int ruby_marshal_write_long(long x, char *buf);
 static void w_long(long, struct dump_arg*);
-static void w_encoding(VALUE encname, struct dump_call_arg *arg);
+static int w_encoding(VALUE encname, struct dump_call_arg *arg);
 static VALUE encoding_name(VALUE obj, struct dump_arg *arg);
 
 static void
@@ -626,7 +626,7 @@ encoding_name(VALUE obj, struct dump_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L626
     }
 }
 
-static void
+static int
 w_encoding(VALUE encname, struct dump_call_arg *arg)
 {
     int limit = arg->limit;
@@ -636,11 +636,13 @@ w_encoding(VALUE encname, struct dump_call_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L636
       case Qtrue:
 	w_symbol(ID2SYM(rb_intern("E")), arg->arg);
 	w_object(encname, arg->arg, limit);
+        return 1;
       case Qnil:
-	return;
+	return 0;
     }
     w_symbol(ID2SYM(rb_id_encoding()), arg->arg);
     w_object(encname, arg->arg, limit);
+    return 1;
 }
 
 static st_index_t
@@ -670,13 +672,17 @@ w_ivar_each(VALUE obj, st_index_t num, struct dump_call_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L672
     struct w_ivar_arg ivarg = {arg, num};
     if (!num) return;
     rb_ivar_foreach(obj, w_obj_each, (st_data_t)&ivarg);
+    if (ivarg.num_ivar) {
+        rb_raise(rb_eRuntimeError, "instance variable removed from %"PRIsVALUE" instance",
+                 CLASS_OF(arg->obj));
+    }
 }
 
 static void
 w_ivar(st_index_t num, VALUE ivobj, VALUE encname, struct dump_call_arg *arg)
 {
     w_long(num, arg->arg);
-    w_encoding(encname, arg);
+    num -= w_encoding(encname, arg);
     if (ivobj != Qundef) {
         w_ivar_each(ivobj, num, arg);
     }
diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb
index 0565a1c..f6d84d1 100644
--- a/test/ruby/test_marshal.rb
+++ b/test/ruby/test_marshal.rb
@@ -795,7 +795,11 @@ class TestMarshal < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_marshal.rb#L795
       end
 
       def marshal_dump
-        self.foo.baz = :problem
+        if self.foo.baz
+          self.foo.remove_instance_variable(:@baz)
+        else
+          self.foo.baz = :problem
+        end
         {foo: self.foo}
       end
 
@@ -811,4 +815,12 @@ class TestMarshal < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_marshal.rb#L815
       Marshal.dump(obj)
     end
   end
+
+  def test_marshal_dump_removing_instance_variable
+    obj = Bug15968.new
+    obj.baz = :Bug15968
+    assert_raise_with_message(RuntimeError, /instance variable removed/) do
+      Marshal.dump(obj)
+    end
+  end
 end
-- 
cgit v0.10.2


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

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