summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2024-05-04 22:17:04 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2024-05-12 13:57:15 +0900
commit8b9b150512b7b9514143a6b971992c9a539ead2f (patch)
tree0fb4bfcae1e1e4c6a3938c785998bcd52c7e3aa2
parentd9e6e6fb60ae71f5288f54f0d34fad1e8806cf67 (diff)
[Bug #20481] Check for unmarshaling ivar
Prohibit setting instance variables of existing classes and modules via link.
-rw-r--r--marshal.c15
-rw-r--r--test/ruby/test_marshal.rb6
2 files changed, 18 insertions, 3 deletions
diff --git a/marshal.c b/marshal.c
index e26c600ca2..83134371fa 100644
--- a/marshal.c
+++ b/marshal.c
@@ -1696,6 +1696,11 @@ r_copy_ivar(VALUE v, VALUE data)
return v;
}
+#define override_ivar_error(type, str) \
+ rb_raise(rb_eTypeError, \
+ "can't override instance variable of "type" '%"PRIsVALUE"'", \
+ (str))
+
static void
r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg)
{
@@ -1703,6 +1708,12 @@ r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg)
len = r_long(arg);
if (len > 0) {
+ if (RB_TYPE_P(obj, T_MODULE)) {
+ override_ivar_error("module", rb_mod_name(obj));
+ }
+ else if (RB_TYPE_P(obj, T_CLASS)) {
+ override_ivar_error("class", rb_class_name(obj));
+ }
do {
VALUE sym = r_symbol(arg);
VALUE val = r_object(arg);
@@ -1795,9 +1806,7 @@ append_extmod(VALUE obj, VALUE extmod)
#define prohibit_ivar(type, str) do { \
if (!ivp || !*ivp) break; \
- rb_raise(rb_eTypeError, \
- "can't override instance variable of "type" '%"PRIsVALUE"'", \
- (str)); \
+ override_ivar_error(type, str); \
} while (0)
static VALUE r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type);
diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb
index 69e92488f2..bcd8892f23 100644
--- a/test/ruby/test_marshal.rb
+++ b/test/ruby/test_marshal.rb
@@ -571,12 +571,18 @@ class TestMarshal < Test::Unit::TestCase
assert_raise(TypeError) {Marshal.load("\x04\x08Ic\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")}
assert_raise(TypeError) {Marshal.load("\x04\x08IM\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")}
assert_not_operator(TestClass, :instance_variable_defined?, :@ivar_bug)
+
+ assert_raise(TypeError) {Marshal.load("\x04\x08[\x07c\x1bTestMarshal::TestClassI@\x06\x06:\x0e@ivar_bug\"\x08bug")}
+ assert_not_operator(TestClass, :instance_variable_defined?, :@ivar_bug)
end
def test_module_ivar
assert_raise(TypeError) {Marshal.load("\x04\x08Im\x1cTestMarshal::TestModule\x06:\x0e@ivar_bug\"\x08bug")}
assert_raise(TypeError) {Marshal.load("\x04\x08IM\x1cTestMarshal::TestModule\x06:\x0e@ivar_bug\"\x08bug")}
assert_not_operator(TestModule, :instance_variable_defined?, :@ivar_bug)
+
+ assert_raise(TypeError) {Marshal.load("\x04\x08[\x07m\x1cTestMarshal::TestModuleI@\x06\x06:\x0e@ivar_bug\"\x08bug")}
+ assert_not_operator(TestModule, :instance_variable_defined?, :@ivar_bug)
end
class TestForRespondToFalse