aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--enumerator.c3
-rw-r--r--file.c7
-rw-r--r--include/ruby/intern.h3
-rw-r--r--io.c3
-rw-r--r--object.c1
-rw-r--r--random.c11
-rw-r--r--re.c12
-rw-r--r--struct.c6
-rw-r--r--test/ruby/test_object.rb32
-rw-r--r--time.c3
11 files changed, 58 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 2eff9f5e80..909f2e4fc2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Tue Jun 5 20:13:15 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_obj_init_copy): should check if trusted too.
+
Tue Jun 5 19:59:13 2012 Tanaka Akira <akr@fsij.org>
* process.c (strtok): declaration removed because it is not used.
diff --git a/enumerator.c b/enumerator.c
index e62eabf61f..f01ddd51e6 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -373,6 +373,7 @@ enumerator_init_copy(VALUE obj, VALUE orig)
{
struct enumerator *ptr0, *ptr1;
+ if (!OBJ_INIT_COPY(obj, orig)) return obj;
ptr0 = enumerator_ptr(orig);
if (ptr0->fib) {
/* Fibers cannot be copied */
@@ -1146,6 +1147,8 @@ generator_init_copy(VALUE obj, VALUE orig)
{
struct generator *ptr0, *ptr1;
+ if (!OBJ_INIT_COPY(obj, orig)) return obj;
+
ptr0 = generator_ptr(orig);
TypedData_Get_Struct(obj, struct generator, &generator_data_type, ptr1);
diff --git a/file.c b/file.c
index 846f3147f9..6fc64a4739 100644
--- a/file.c
+++ b/file.c
@@ -4470,12 +4470,7 @@ rb_stat_init_copy(VALUE copy, VALUE orig)
{
struct stat *nst;
- if (copy == orig) return orig;
- rb_check_frozen(copy);
- /* need better argument type check */
- if (!rb_obj_is_instance_of(orig, rb_obj_class(copy))) {
- rb_raise(rb_eTypeError, "wrong argument class");
- }
+ if (!OBJ_INIT_COPY(copy, orig)) return copy;
if (DATA_PTR(copy)) {
xfree(DATA_PTR(copy));
DATA_PTR(copy) = 0;
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 9690964ac8..a3d583c2ea 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -252,6 +252,9 @@ rb_check_trusted_inline(VALUE obj)
#define rb_check_trusted(obj) rb_check_trusted_inline(obj)
#endif
+#define OBJ_INIT_COPY(obj, orig) \
+ ((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1))
+
/* eval.c */
int rb_sourceline(void);
const char *rb_sourcefile(void);
diff --git a/io.c b/io.c
index 3d4fe54848..f24bfbb5b0 100644
--- a/io.c
+++ b/io.c
@@ -6387,7 +6387,7 @@ rb_io_init_copy(VALUE dest, VALUE io)
off_t pos;
io = rb_io_get_io(io);
- if (dest == io) return dest;
+ if (!OBJ_INIT_COPY(dest, io)) return dest;
GetOpenFile(io, orig);
MakeOpenFile(dest, fptr);
@@ -7286,6 +7286,7 @@ argf_initialize(VALUE argf, VALUE argv)
static VALUE
argf_initialize_copy(VALUE argf, VALUE orig)
{
+ if (!OBJ_INIT_COPY(argf, orig)) return argf;
ARGF = argf_of(orig);
ARGF.argv = rb_obj_dup(ARGF.argv);
if (ARGF.inplace) {
diff --git a/object.c b/object.c
index dbb8db63dd..1177466d7f 100644
--- a/object.c
+++ b/object.c
@@ -342,6 +342,7 @@ rb_obj_init_copy(VALUE obj, VALUE orig)
{
if (obj == orig) return obj;
rb_check_frozen(obj);
+ rb_check_trusted(obj);
if (TYPE(obj) != TYPE(orig) || rb_obj_class(obj) != rb_obj_class(orig)) {
rb_raise(rb_eTypeError, "initialize_copy should take same class object");
}
diff --git a/random.c b/random.c
index 9dbcbd1d62..d05fe6d9c6 100644
--- a/random.c
+++ b/random.c
@@ -596,9 +596,14 @@ random_get_seed(VALUE obj)
static VALUE
random_copy(VALUE obj, VALUE orig)
{
- rb_random_t *rnd1 = get_rnd(obj);
- rb_random_t *rnd2 = get_rnd(orig);
- struct MT *mt = &rnd1->mt;
+ rb_random_t *rnd1, *rnd2;
+ struct MT *mt;
+
+ if (!OBJ_INIT_COPY(obj, orig)) return obj;
+
+ rnd1 = get_rnd(obj);
+ rnd2 = get_rnd(orig);
+ mt = &rnd1->mt;
*rnd1 = *rnd2;
mt->next = mt->state + numberof(mt->state) - mt->left + 1;
diff --git a/re.c b/re.c
index 500173d3cb..4191d5bcb8 100644
--- a/re.c
+++ b/re.c
@@ -939,11 +939,8 @@ match_init_copy(VALUE obj, VALUE orig)
{
struct rmatch *rm;
- if (obj == orig) return obj;
+ if (!OBJ_INIT_COPY(obj, orig)) return obj;
- if (!rb_obj_is_instance_of(orig, rb_obj_class(obj))) {
- rb_raise(rb_eTypeError, "wrong argument class");
- }
RMATCH(obj)->str = RMATCH(orig)->str;
RMATCH(obj)->regexp = RMATCH(orig)->regexp;
@@ -3260,12 +3257,7 @@ rb_reg_init_copy(VALUE copy, VALUE re)
const char *s;
long len;
- if (copy == re) return copy;
- rb_check_frozen(copy);
- /* need better argument type check */
- if (!rb_obj_is_instance_of(re, rb_obj_class(copy))) {
- rb_raise(rb_eTypeError, "wrong argument type");
- }
+ if (!OBJ_INIT_COPY(copy, re)) return copy;
rb_reg_check(re);
s = RREGEXP_SRC_PTR(re);
len = RREGEXP_SRC_LEN(re);
diff --git a/struct.c b/struct.c
index 8168f62bb1..91d562b97c 100644
--- a/struct.c
+++ b/struct.c
@@ -606,11 +606,7 @@ rb_struct_to_h(VALUE s)
VALUE
rb_struct_init_copy(VALUE copy, VALUE s)
{
- if (copy == s) return copy;
- rb_check_frozen(copy);
- if (!rb_obj_is_instance_of(s, rb_obj_class(copy))) {
- rb_raise(rb_eTypeError, "wrong argument class");
- }
+ if (!OBJ_INIT_COPY(copy, s)) return copy;
if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
rb_raise(rb_eTypeError, "struct size mismatch");
}
diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb
index d63886a81e..70dcd04201 100644
--- a/test/ruby/test_object.rb
+++ b/test/ruby/test_object.rb
@@ -764,4 +764,36 @@ class TestObject < Test::Unit::TestCase
assert_equal((eval("raise #{code}") rescue $!.inspect), out.chomp, bug5473)
end
end
+
+ def assert_not_initialize_copy
+ a = yield
+ b = yield
+ assert_nothing_raised("copy") {a.instance_eval {initialize_copy(b)}}
+ c = a.dup.freeze
+ assert_raise(RuntimeError, "frozen") {c.instance_eval {initialize_copy(b)}}
+ d = a.dup.trust
+ assert_raise(SecurityError, "untrust") do
+ proc {
+ $SAFE = 4
+ d.instance_eval {initialize_copy(b)}
+ }.call
+ end
+ [a, b, c, d]
+ end
+
+ def test_bad_initialize_copy
+ assert_not_initialize_copy {Object.new}
+ assert_not_initialize_copy {[].to_enum}
+ assert_not_initialize_copy {Enumerator::Generator.new {}}
+ assert_not_initialize_copy {Enumerator::Yielder.new {}}
+ assert_not_initialize_copy {File.stat(__FILE__)}
+ assert_not_initialize_copy {open(__FILE__)}.each(&:close)
+ assert_not_initialize_copy {ARGF.class.new}
+ assert_not_initialize_copy {Random.new}
+ assert_not_initialize_copy {//}
+ assert_not_initialize_copy {/.*/.match("foo")}
+ st = Struct.new(:foo)
+ assert_not_initialize_copy {st.new}
+ assert_not_initialize_copy {Time.now}
+ end
end
diff --git a/time.c b/time.c
index b0a2be2455..0d771d2715 100644
--- a/time.c
+++ b/time.c
@@ -3425,8 +3425,7 @@ time_init_copy(VALUE copy, VALUE time)
{
struct time_object *tobj, *tcopy;
- if (copy == time) return copy;
- time_modify(copy);
+ if (!OBJ_INIT_COPY(copy, time)) return copy;
GetTimeval(time, tobj);
GetTimeval(copy, tcopy);
MEMCPY(tcopy, tobj, struct time_object, 1);