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

ruby-changes:18688

From: mame <ko1@a...>
Date: Sat, 29 Jan 2011 03:00:24 +0900 (JST)
Subject: [ruby-changes:18688] Ruby:r30713 (trunk): * constant.h, variable.c: to ensure compatibility, rb_const_get_* must

mame	2011-01-29 02:57:27 +0900 (Sat, 29 Jan 2011)

  New Revision: 30713

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=30713

  Log:
    * constant.h, variable.c: to ensure compatibility, rb_const_get_* must
      not raise an exception even when the constant is private.  Instead,
      rb_public_const_get_* and rb_public_const_defined_* are introduced,
      which raise an exception when the referring constant is private.
      see [ruby-core:32912].
    
    * vm_insnhelper.c (vm_get_ev_const): use rb_public_const_get_* instead
      of rb_const_get_* to follow the constant visibility when user code
      refers a constant.
    
    * test/ruby/test_marshal.rb (test_marshal_private_class): add a test.
      This test had failed because of incompatibility of rb_const_get.

  Modified files:
    trunk/ChangeLog
    trunk/constant.h
    trunk/test/ruby/test_marshal.rb
    trunk/variable.c
    trunk/vm_insnhelper.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 30712)
+++ ChangeLog	(revision 30713)
@@ -1,3 +1,18 @@
+Sat Jan 29 01:19:17 2011  Yusuke Endoh  <mame@t...>
+
+	* constant.h, variable.c: to ensure compatibility, rb_const_get_* must
+	  not raise an exception even when the constant is private.  Instead,
+	  rb_public_const_get_* and rb_public_const_defined_* are introduced,
+	  which raise an exception when the referring constant is private.
+	  see [ruby-core:32912].
+    
+	* vm_insnhelper.c (vm_get_ev_const): use rb_public_const_get_* instead
+	  of rb_const_get_* to follow the constant visibility when user code
+	  refers a constant.
+
+	* test/ruby/test_marshal.rb (test_marshal_private_class): add a test.
+	  This test had failed because of incompatibility of rb_const_get.
+
 Sat Jan 29 00:30:44 2011  Yusuke Endoh  <mame@t...>
 
 	* variable.c (set_const_visibility): fix typo.  a patch from Tomoyuki
Index: variable.c
===================================================================
--- variable.c	(revision 30712)
+++ variable.c	(revision 30713)
@@ -1575,7 +1575,7 @@
 }
 
 static VALUE
-rb_const_get_0(VALUE klass, ID id, int exclude, int recurse)
+rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
 {
     VALUE value, tmp;
     int mod_retry = 0;
@@ -1587,7 +1587,7 @@
 	st_data_t data;
 	while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) {
 	    rb_const_entry_t *ce = (rb_const_entry_t *)data;
-	    if (ce->flag == CONST_PRIVATE) {
+	    if (visibility && ce->flag == CONST_PRIVATE) {
 		rb_name_error(id, "private constant %s::%s referenced", rb_class2name(klass), rb_id2name(id));
 	    }
 	    value = ce->value;
@@ -1620,21 +1620,39 @@
 VALUE
 rb_const_get_from(VALUE klass, ID id)
 {
-    return rb_const_get_0(klass, id, TRUE, TRUE);
+    return rb_const_get_0(klass, id, TRUE, TRUE, FALSE);
 }
 
 VALUE
 rb_const_get(VALUE klass, ID id)
 {
-    return rb_const_get_0(klass, id, FALSE, TRUE);
+    return rb_const_get_0(klass, id, FALSE, TRUE, FALSE);
 }
 
 VALUE
 rb_const_get_at(VALUE klass, ID id)
 {
-    return rb_const_get_0(klass, id, TRUE, FALSE);
+    return rb_const_get_0(klass, id, TRUE, FALSE, FALSE);
 }
 
+VALUE
+rb_public_const_get_from(VALUE klass, ID id)
+{
+    return rb_const_get_0(klass, id, TRUE, TRUE, TRUE);
+}
+
+VALUE
+rb_public_const_get(VALUE klass, ID id)
+{
+    return rb_const_get_0(klass, id, FALSE, TRUE, TRUE);
+}
+
+VALUE
+rb_public_const_get_at(VALUE klass, ID id)
+{
+    return rb_const_get_0(klass, id, TRUE, FALSE, TRUE);
+}
+
 /*
  *  call-seq:
  *     remove_const(sym)   -> obj
@@ -1781,7 +1799,7 @@
 }
 
 static int
-rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse)
+rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
 {
     st_data_t value;
     VALUE tmp;
@@ -1791,8 +1809,12 @@
   retry:
     while (tmp) {
 	if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) {
-	    if (((rb_const_entry_t*)value)->value == Qundef && !autoload_node((VALUE)klass, id, 0))
+	    rb_const_entry_t *ce = (rb_const_entry_t *)value;
+	    if (visibility && ce->flag == CONST_PRIVATE) {
 		return (int)Qfalse;
+	    }
+	    if (ce->value == Qundef && !autoload_node((VALUE)klass, id, 0))
+		return (int)Qfalse;
 	    return (int)Qtrue;
 	}
 	if (!recurse && klass != rb_cObject) break;
@@ -1809,21 +1831,39 @@
 int
 rb_const_defined_from(VALUE klass, ID id)
 {
-    return rb_const_defined_0(klass, id, TRUE, TRUE);
+    return rb_const_defined_0(klass, id, TRUE, TRUE, FALSE);
 }
 
 int
 rb_const_defined(VALUE klass, ID id)
 {
-    return rb_const_defined_0(klass, id, FALSE, TRUE);
+    return rb_const_defined_0(klass, id, FALSE, TRUE, FALSE);
 }
 
 int
 rb_const_defined_at(VALUE klass, ID id)
 {
-    return rb_const_defined_0(klass, id, TRUE, FALSE);
+    return rb_const_defined_0(klass, id, TRUE, FALSE, FALSE);
 }
 
+int
+rb_public_const_defined_from(VALUE klass, ID id)
+{
+    return rb_const_defined_0(klass, id, TRUE, TRUE, TRUE);
+}
+
+int
+rb_public_const_defined(VALUE klass, ID id)
+{
+    return rb_const_defined_0(klass, id, FALSE, TRUE, TRUE);
+}
+
+int
+rb_public_const_defined_at(VALUE klass, ID id)
+{
+    return rb_const_defined_0(klass, id, TRUE, FALSE, TRUE);
+}
+
 void
 check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest)
 {
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 30712)
+++ vm_insnhelper.c	(revision 30713)
@@ -1199,19 +1199,19 @@
 	}
 
 	if (is_defined) {
-	    return rb_const_defined(klass, id);
+	    return rb_public_const_defined(klass, id);
 	}
 	else {
-	    return rb_const_get(klass, id);
+	    return rb_public_const_get(klass, id);
 	}
     }
     else {
 	vm_check_if_namespace(orig_klass);
 	if (is_defined) {
-	    return rb_const_defined_from(orig_klass, id);
+	    return rb_public_const_defined_from(orig_klass, id);
 	}
 	else {
-	    return rb_const_get_from(orig_klass, id);
+	    return rb_public_const_get_from(orig_klass, id);
 	}
     }
 }
Index: test/ruby/test_marshal.rb
===================================================================
--- test/ruby/test_marshal.rb	(revision 30712)
+++ test/ruby/test_marshal.rb	(revision 30713)
@@ -454,5 +454,19 @@
     o2 = Marshal.load(m)
     assert_equal(o1, o2)
   end
+
+  class PrivateClass
+    def initialize(foo)
+      @foo = foo
+    end
+    attr_reader :foo
+  end
+  private_constant :PrivateClass
   
+  def test_marshal_private_class
+    o1 = PrivateClass.new("test")
+    o2 = Marshal.load(Marshal.dump(o1))
+    assert_equal(o1.class, o2.class)
+    assert_equal(o1.foo, o2.foo)
+  end
 end
Index: constant.h
===================================================================
--- constant.h	(revision 30712)
+++ constant.h	(revision 30713)
@@ -24,5 +24,11 @@
 VALUE rb_mod_private_constant(int argc, VALUE *argv, VALUE obj);
 VALUE rb_mod_public_constant(int argc, VALUE *argv, VALUE obj);
 void rb_free_const_table(st_table *tbl);
+VALUE rb_public_const_get(VALUE klass, ID id);
+VALUE rb_public_const_get_at(VALUE klass, ID id);
+VALUE rb_public_const_get_from(VALUE klass, ID id);
+int rb_public_const_defined(VALUE klass, ID id);
+int rb_public_const_defined_at(VALUE klass, ID id);
+int rb_public_const_defined_from(VALUE klass, ID id);
 
 #endif /* CONSTANT_H */

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

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