diff options
| author | Benoit Daloze <eregontp@gmail.com> | 2025-11-05 11:13:09 +0100 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2025-12-02 17:27:38 +0000 |
| commit | d3907245d7928279fcffd1af2903d16b2dbb2d29 (patch) | |
| tree | 3664a14e3480cd167ff197cd8323ef505f6252f8 | |
| parent | 17bcd71e4218994bfb6c2d398fa784ccd74d2f2c (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.rb | 3 | ||||
| -rw-r--r-- | ext/psych/psych_to_ruby.c | 9 |
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); } |
