summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKOBAYASHI Shuji <[email protected]>2019-04-24 21:05:44 +0900
committerKOBAYASHI Shuji <[email protected]>2019-04-24 21:05:44 +0900
commit4720648137f2698cceb635c251475dec645cd598 (patch)
tree535584bbc083956801dd6c8c702c8dfe8c4c44d9
parent163a6d01e035f16b15d3b08c0dfddd2caec09f9b (diff)
downloadmruby-4720648137f2698cceb635c251475dec645cd598.tar.gz
mruby-4720648137f2698cceb635c251475dec645cd598.zip
Fix modiying class variable to frozen class/module
-rw-r--r--mrbgems/mruby-metaprog/test/metaprog.rb8
-rw-r--r--src/variable.c2
-rw-r--r--test/t/class.rb19
3 files changed, 28 insertions, 1 deletions
diff --git a/mrbgems/mruby-metaprog/test/metaprog.rb b/mrbgems/mruby-metaprog/test/metaprog.rb
index 1262c9945..0abeb90a6 100644
--- a/mrbgems/mruby-metaprog/test/metaprog.rb
+++ b/mrbgems/mruby-metaprog/test/metaprog.rb
@@ -171,7 +171,6 @@ assert('Module#class_variable_set', '15.2.2.4.18') do
@@foo
end
end
-
assert_equal 99, Test4ClassVariableSet.class_variable_set(:@@cv, 99)
assert_equal 101, Test4ClassVariableSet.class_variable_set(:@@foo, 101)
assert_true Test4ClassVariableSet.class_variables.include? :@@cv
@@ -180,6 +179,13 @@ assert('Module#class_variable_set', '15.2.2.4.18') do
%w[@@ @@1 @@x= @x @ x 1].each do |n|
assert_raise(NameError) { Test4ClassVariableSet.class_variable_set(n, 1) }
end
+
+ m = Module.new.freeze
+ assert_raise(FrozenError) { m.class_variable_set(:@@cv, 1) }
+
+ parent = Class.new{ class_variable_set(:@@a, nil) }.freeze
+ child = Class.new(parent)
+ assert_raise(FrozenError) { child.class_variable_set(:@@a, 1) }
end
assert('Module#class_variables', '15.2.2.4.19') do
diff --git a/src/variable.c b/src/variable.c
index 983fe52f7..c4c9d369f 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -671,6 +671,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
iv_tbl *t = c->iv;
if (iv_get(mrb, t, sym, NULL)) {
+ mrb_check_frozen(mrb, c);
iv_put(mrb, t, sym, v);
mrb_write_barrier(mrb, (struct RBasic*)c);
return;
@@ -698,6 +699,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
c = cls;
}
+ mrb_check_frozen(mrb, c);
if (!c->iv) {
c->iv = iv_new(mrb);
}
diff --git a/test/t/class.rb b/test/t/class.rb
index 290ecf74a..0c95677fc 100644
--- a/test/t/class.rb
+++ b/test/t/class.rb
@@ -433,6 +433,25 @@ assert('overriding class variable with a module (#3235)') do
end
end
+assert('class variable for frozen class/module') do
+ module CVarForFrozenModule
+ freeze
+ assert_raise(FrozenError) { @@cv = 1 }
+ end
+
+ class CVarForFrozenClassA
+ @@a = nil
+ freeze
+ end
+ class CVarForFrozenClassB < CVarForFrozenClassA
+ def a=(v)
+ @@a = v
+ end
+ end
+ b = CVarForFrozenClassB.new
+ assert_raise(FrozenError) { b.a = 1 }
+end
+
assert('class with non-class/module outer raises TypeError') do
assert_raise(TypeError) { class 0::C1; end }
assert_raise(TypeError) { class []::C2; end }