summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-04-04 06:46:53 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-04-04 06:46:53 +0000
commit9f87297c21e2e375990166214327634b212e50fb (patch)
treeea6a848e51d294fe2f43fc99566a4a8217a7945f
parent80748440654f93d40a97d0f4fb287f5d268c7cfd (diff)
enum.c: avoid inadvertent symbol creation
* enum.c (enum_inject): avoid inadvertent symbol creation. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40097 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog4
-rw-r--r--enum.c20
-rw-r--r--test/-ext-/symbol/test_inadvertent_creation.rb6
3 files changed, 27 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index f63bb4878d..3e702766bd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Thu Apr 4 15:46:48 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (enum_inject): avoid inadvertent symbol creation.
+
Thu Apr 4 14:37:07 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* thread.c (rb_thread_aref): avoid inadvertent symbol creation.
diff --git a/enum.c b/enum.c
index 18983bb36d..25c41c969a 100644
--- a/enum.c
+++ b/enum.c
@@ -17,6 +17,10 @@
#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[1 - 2*!(expr)]
+#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
+
+VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
+
VALUE rb_mEnumerable;
static ID id_next;
@@ -527,6 +531,7 @@ static VALUE
inject_op_i(VALUE i, VALUE p, int argc, VALUE *argv)
{
NODE *memo = RNODE(p);
+ VALUE name;
ENUM_WANT_SVALUE();
@@ -534,8 +539,14 @@ inject_op_i(VALUE i, VALUE p, int argc, VALUE *argv)
memo->u2.argc = 1;
memo->u1.value = i;
}
+ else if (SYMBOL_P(name = memo->u3.value)) {
+ memo->u1.value = rb_funcall(memo->u1.value, SYM2ID(name), 1, i);
+ }
else {
- memo->u1.value = rb_funcall(memo->u1.value, memo->u3.id, 1, i);
+ VALUE args[2];
+ args[0] = name;
+ args[1] = i;
+ memo->u1.value = rb_f_send(numberof(args), args, memo->u1.value);
}
return Qnil;
}
@@ -589,6 +600,7 @@ enum_inject(int argc, VALUE *argv, VALUE obj)
NODE *memo;
VALUE init, op;
VALUE (*iter)(VALUE, VALUE, int, VALUE*) = inject_i;
+ ID id;
switch (rb_scan_args(argc, argv, "02", &init, &op)) {
case 0:
@@ -597,7 +609,8 @@ enum_inject(int argc, VALUE *argv, VALUE obj)
if (rb_block_given_p()) {
break;
}
- op = (VALUE)rb_to_id(init);
+ id = rb_check_id(&init);
+ op = id ? ID2SYM(id) : init;
argc = 0;
init = Qnil;
iter = inject_op_i;
@@ -606,7 +619,8 @@ enum_inject(int argc, VALUE *argv, VALUE obj)
if (rb_block_given_p()) {
rb_warning("given block not used");
}
- op = (VALUE)rb_to_id(op);
+ id = rb_check_id(&op);
+ if (id) op = ID2SYM(id);
iter = inject_op_i;
break;
}
diff --git a/test/-ext-/symbol/test_inadvertent_creation.rb b/test/-ext-/symbol/test_inadvertent_creation.rb
index 96a0dafc4b..247a42cab3 100644
--- a/test/-ext-/symbol/test_inadvertent_creation.rb
+++ b/test/-ext-/symbol/test_inadvertent_creation.rb
@@ -187,5 +187,11 @@ module Test_Symbol
assert_not_send([Thread.current, :thread_variable?, name])
assert_not_send([Bug::Symbol, :interned?, name])
end
+
+ def test_enumerable_inject_op
+ name = noninterned_name
+ assert_raise(NoMethodError) {[1, 2].inject(name)}
+ assert_not_send([Bug::Symbol, :interned?, name])
+ end
end
end