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

ruby-changes:68177

From: Jean <ko1@a...>
Date: Thu, 30 Sep 2021 23:50:45 +0900 (JST)
Subject: [ruby-changes:68177] 529fc204af (master): marshal.c: don't call the proc with partially initialized objects. (#4866)

https://git.ruby-lang.org/ruby.git/commit/?id=529fc204af

From 529fc204af84f825f98f83c34b004acbaa802615 Mon Sep 17 00:00:00 2001
From: Jean byroot Boussier <jean.boussier+github@s...>
Date: Thu, 30 Sep 2021 16:50:31 +0200
Subject: marshal.c: don't call the proc with partially initialized objects.
 (#4866)

For cyclic objects, it requires to keep a st_table of the partially
initialized objects.
---
 marshal.c                             | 75 ++++++++++++++++++++---------------
 spec/ruby/core/marshal/shared/load.rb | 75 ++++++++++++++++++++---------------
 test/ruby/test_marshal.rb             | 12 ++++++
 3 files changed, 97 insertions(+), 65 deletions(-)

diff --git a/marshal.c b/marshal.c
index f8110da5c6..1643d84d72 100644
--- a/marshal.c
+++ b/marshal.c
@@ -1156,6 +1156,7 @@ struct load_arg { https://github.com/ruby/ruby/blob/trunk/marshal.c#L1156
     long offset;
     st_table *symbols;
     st_table *data;
+    st_table *partial_objects;
     VALUE proc;
     st_table *compat_tbl;
 };
@@ -1182,6 +1183,7 @@ mark_load_arg(void *ptr) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1183
         return;
     rb_mark_tbl(p->symbols);
     rb_mark_tbl(p->data);
+    rb_mark_tbl(p->partial_objects);
     rb_mark_hash(p->compat_tbl);
 }
 
@@ -1535,6 +1537,7 @@ r_entry0(VALUE v, st_index_t num, struct load_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1537
         st_lookup(arg->compat_tbl, v, &real_obj);
     }
     st_insert(arg->data, num, real_obj);
+    st_insert(arg->partial_objects, (st_data_t)real_obj, Qtrue);
     return v;
 }
 
@@ -1565,10 +1568,15 @@ r_post_proc(VALUE v, struct load_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1568
 }
 
 static VALUE
-r_leave(VALUE v, struct load_arg *arg)
+r_leave(VALUE v, struct load_arg *arg, bool partial)
 {
     v = r_fixup_compat(v, arg);
-    v = r_post_proc(v, arg);
+    if (!partial) {
+	st_data_t data;
+	st_data_t key = (st_data_t)v;
+	st_delete(arg->partial_objects, &key, &data);
+	v = r_post_proc(v, arg);
+    }
     return v;
 }
 
@@ -1695,7 +1703,7 @@ append_extmod(VALUE obj, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1703
     } while (0)
 
 static VALUE
-r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
+r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
 {
     VALUE v = Qnil;
     int type = r_byte(arg);
@@ -1709,18 +1717,18 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1717
 	    rb_raise(rb_eArgError, "dump format error (unlinked)");
 	}
 	v = (VALUE)link;
-	v = r_post_proc(v, arg);
+	if (!st_lookup(arg->partial_objects, (st_data_t)v, &link)) {
+	    v = r_post_proc(v, arg);
+	}
 	break;
 
       case TYPE_IVAR:
         {
 	    int ivar = TRUE;
 
-	    v = r_object0(arg, &ivar, extmod);
+	    v = r_object0(arg, true, &ivar, extmod);
 	    if (ivar) r_ivar(v, NULL, arg);
-	    if (RB_TYPE_P(v, T_STRING)) {
-	        v = r_leave(v, arg);
-	    }
+	    v = r_leave(v, arg, partial);
 	}
 	break;
 
@@ -1733,7 +1741,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1741
 	    if (RB_TYPE_P(m, T_CLASS)) { /* prepended */
 		VALUE c;
 
-		v = r_object0(arg, 0, Qnil);
+		v = r_object0(arg, true, 0, Qnil);
 		c = CLASS_OF(v);
 		if (c != m || FL_TEST(c, FL_SINGLETON)) {
 		    rb_raise(rb_eArgError,
@@ -1750,7 +1758,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1758
 		must_be_module(m, path);
 		rb_ary_push(extmod, m);
 
-		v = r_object0(arg, 0, extmod);
+		v = r_object0(arg, true, 0, extmod);
 		while (RARRAY_LEN(extmod) > 0) {
 		    m = rb_ary_pop(extmod);
 		    rb_extend_object(v, m);
@@ -1766,7 +1774,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1774
 	    if (FL_TEST(c, FL_SINGLETON)) {
 		rb_raise(rb_eTypeError, "singleton can't be loaded");
 	    }
-	    v = r_object0(arg, 0, extmod);
+	    v = r_object0(arg, partial, 0, extmod);
 	    if (rb_special_const_p(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) {
                 goto format_error;
 	    }
@@ -1784,17 +1792,17 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1792
 
       case TYPE_NIL:
 	v = Qnil;
-	v = r_leave(v, arg);
+	v = r_leave(v, arg, false);
 	break;
 
       case TYPE_TRUE:
 	v = Qtrue;
-	v = r_leave(v, arg);
+	v = r_leave(v, arg, false);
 	break;
 
       case TYPE_FALSE:
 	v = Qfalse;
-	v = r_leave(v, arg);
+	v = r_leave(v, arg, false);
 	break;
 
       case TYPE_FIXNUM:
@@ -1802,7 +1810,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1810
 	    long i = r_long(arg);
 	    v = LONG2FIX(i);
 	}
-	v = r_leave(v, arg);
+	v = r_leave(v, arg, false);
 	break;
 
       case TYPE_FLOAT:
@@ -1827,7 +1835,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1835
 	    }
 	    v = DBL2NUM(d);
 	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
+            v = r_leave(v, arg, false);
 	}
 	break;
 
@@ -1844,15 +1852,13 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1852
                 INTEGER_PACK_LITTLE_ENDIAN | (sign == '-' ? INTEGER_PACK_NEGATIVE : 0));
 	    rb_str_resize(data, 0L);
 	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
+            v = r_leave(v, arg, false);
 	}
 	break;
 
       case TYPE_STRING:
 	v = r_entry(r_string(arg), arg);
-	if (!ivp) {
-	    v = r_leave(v, arg);
-	}
+	v = r_leave(v, arg, partial);
 	break;
 
       case TYPE_REGEXP:
@@ -1887,7 +1893,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1893
 		rb_str_set_len(str, dst - ptr);
 	    }
 	    v = r_entry0(rb_reg_new_str(str, options), idx, arg);
-	    v = r_leave(v, arg);
+	    v = r_leave(v, arg, partial);
 	}
 	break;
 
@@ -1902,7 +1908,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1908
 		rb_ary_push(v, r_object(arg));
 		arg->readable--;
 	    }
-            v = r_leave(v, arg);
+            v = r_leave(v, arg, partial);
 	    arg->readable++;
 	}
 	break;
@@ -1925,7 +1931,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1931
 	    if (type == TYPE_HASH_DEF) {
 		RHASH_SET_IFNONE(v, r_object(arg));
 	    }
-            v = r_leave(v, arg);
+            v = r_leave(v, arg, partial);
 	}
 	break;
 
@@ -1977,7 +1983,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L1983
 		}
 	    }
             rb_struct_initialize(v, values);
-            v = r_leave(v, arg);
+            v = r_leave(v, arg, partial);
 	    arg->readable += 2;
 	}
 	break;
@@ -2004,7 +2010,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L2010
 		marshal_compat_t *compat = (marshal_compat_t*)d;
 		v = compat->loader(klass, v);
 	    }
-	    v = r_post_proc(v, arg);
+	    if (!partial) v = r_post_proc(v, arg);
 	}
         break;
 
@@ -2046,7 +2052,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L2052
 	    }
 	    v = r_entry0(v, idx, arg);
 	    r_ivar(v, NULL, arg);
-	    v = r_leave(v, arg);
+	    v = r_leave(v, arg, partial);
 	}
 	break;
 
@@ -2067,9 +2073,9 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L2073
 			 "class %"PRIsVALUE" needs to have instance method `_load_data'",
 			 name);
 	    }
-	    r = r_object0(arg, 0, extmod);
+	    r = r_object0(arg, partial, 0, extmod);
 	    load_funcall(arg, v, s_load_data, 1, &r);
-	    v = r_leave(v, arg);
+	    v = r_leave(v, arg, partial);
 	}
 	break;
 
@@ -2080,7 +2086,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L2086
 	    v = rb_path_to_class(str);
 	    prohibit_ivar("class/module", str);
 	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
+            v = r_leave(v, arg, partial);
 	}
 	break;
 
@@ -2091,7 +2097,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L2097
 	    v = path2class(str);
 	    prohibit_ivar("class", str);
 	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
+            v = r_leave(v, arg, partial);
 	}
 	break;
 
@@ -2102,7 +2108,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L2108
 	    v = path2module(str);
 	    prohibit_ivar("module", str);
 	    v = r_entry(v, arg);
-            v = r_leave(v, arg);
+            v = r_leave(v, arg, partial);
 	}
 	break;
 
@@ -2115,7 +2121,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L2121
 	    v = r_symreal(arg, 0);
 	}
 	v = rb_str_intern(v);
-	v = r_leave(v, arg);
+	v = r_leave(v, arg, partial);
 	break;
 
       case TYPE_SYMLINK:
@@ -2137,7 +2143,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) https://github.com/ruby/ruby/blob/trunk/marshal.c#L2143
 static VALUE
 r_object(struct load_arg *arg)
 {
-    return r_object0(arg, 0, Qnil);
+    return r_object0(arg, false, 0, Qnil);
 }
 
 static void
@@ -2155,6 +2161,8 @@ clear_load_arg(struct load_arg *arg) https://github.com/ruby/ruby/blob/trunk/marshal.c#L2161
     arg->symbols = 0;
     st_free_table(arg->data);
     arg->data = 0;
+    st_free_table(arg->partial_objects);
+    arg->partial_objects = 0;
     if (arg->compat_tbl) {
 	st_free_table(arg->compat_tbl);
 	arg->compat_tbl = 0;
@@ -2209,6 +2217,7 @@ rb_marshal_load_with_proc(VALUE port, VALUE proc) https://github.com/ruby/rub (... truncated)

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

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