summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2025-11-05 11:13:09 +0100
committergit <svn-admin@ruby-lang.org>2025-12-02 17:27:38 +0000
commitd3907245d7928279fcffd1af2903d16b2dbb2d29 (patch)
tree3664a14e3480cd167ff197cd8323ef505f6252f8
parent17bcd71e4218994bfb6c2d398fa784ccd74d2f2c (diff)
[ruby/psych] Fix usage of rb_struct_initialize() to pass an Array of members values and not a Hash
* rb_struct_initialize() does not accept a Hash, and it's very brittle to pass `[{...}]` and to rely on that C function using rb_keyword_given_p(). It basically worked accidentally, by having **members in the caller of the caller. Such logic when Struct#initialize is defined in Ruby (as in TruffleRuby) is basically impossible to implement, because it's incorrectly treating positional arguments as keyword arguments. * rb_struct_initialize() is used in CRuby to set members of Data instances in marshal.c (there is no rb_data_initialize() yet). There, the code passes an Array of members values for Data (and for Struct which are not `keyword_init: true`): https://github.com/ruby/ruby/blob/48c7f349f68846e10d60ae77ad299a38ee014479/marshal.c#L2150-L2176 So we should do the same in psych. * Rename to init_data since it's only used for Data. * See https://github.com/ruby/psych/pull/692#discussion_r2483947279. https://github.com/ruby/psych/commit/3550148378
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb3
-rw-r--r--ext/psych/psych_to_ruby.c9
2 files changed, 5 insertions, 7 deletions
diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index 580a74e9fb..2814ce1a69 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -219,7 +219,8 @@ module Psych
revive_data_members(members, o)
end
data ||= allocate_anon_data(o, members)
- init_struct(data, **members)
+ values = data.members.map { |m| members[m] }
+ init_data(data, values)
data.freeze
data
diff --git a/ext/psych/psych_to_ruby.c b/ext/psych/psych_to_ruby.c
index d473a5f840..53a038270c 100644
--- a/ext/psych/psych_to_ruby.c
+++ b/ext/psych/psych_to_ruby.c
@@ -24,12 +24,9 @@ static VALUE path2class(VALUE self, VALUE path)
return rb_path_to_class(path);
}
-static VALUE init_struct(VALUE self, VALUE data, VALUE attrs)
+static VALUE init_data(VALUE self, VALUE data, VALUE values)
{
- VALUE args = rb_ary_new2(1);
- rb_ary_push(args, attrs);
- rb_struct_initialize(data, args);
-
+ rb_struct_initialize(data, values);
return data;
}
@@ -42,7 +39,7 @@ void Init_psych_to_ruby(void)
VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject);
cPsychVisitorsToRuby = rb_define_class_under(visitors, "ToRuby", visitor);
- rb_define_private_method(cPsychVisitorsToRuby, "init_struct", init_struct, 2);
+ rb_define_private_method(cPsychVisitorsToRuby, "init_data", init_data, 2);
rb_define_private_method(cPsychVisitorsToRuby, "build_exception", build_exception, 2);
rb_define_private_method(class_loader, "path2class", path2class, 1);
}