Skip to content

Commit

Permalink
merge revision(s) d2520b7: [Backport #19439]
Browse files Browse the repository at this point in the history
	Marshal.load: restore instance variables on Regexp

	[Bug #19439]

	The instance variables were restore on the Regexp source,
	not the regexp itself.

	Unfortunately we have a bit of a chicken and egg problem.

	The source holds the encoding, and the encoding need to be set on
	the source to be able to instantiate the Regexp.

	So the instance variables have to be read on the `source`.
	To correct this we transfert the instance variables after
	instantiating the Regexp.

	The only way to avoid this would be to read the instance variable
	twice and rewind.
	---
	 marshal.c                             | 20 ++++++++++++++++++--
	 spec/ruby/core/marshal/shared/load.rb | 11 +++++++++++
	 2 files changed, 29 insertions(+), 2 deletions(-)
  • Loading branch information
nurse committed Mar 8, 2023
1 parent 59eb180 commit 4e4a4e4
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 3 deletions.
20 changes: 18 additions & 2 deletions marshal.c
Expand Up @@ -1803,6 +1803,20 @@ r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
return r_object_for(arg, partial, ivp, extmod, type);
}

static int
r_move_ivar(st_data_t k, st_data_t v, st_data_t d)
{
ID key = (ID)k;
VALUE value = (VALUE)v;
VALUE dest = (VALUE)d;

if (rb_is_instance_id(key)) {
rb_ivar_set(dest, key, value);
return ST_DELETE;
}
return ST_CONTINUE;
}

static VALUE
r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type)
{
Expand All @@ -1826,7 +1840,6 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int typ
case TYPE_IVAR:
{
int ivar = TRUE;

v = r_object0(arg, true, &ivar, extmod);
if (ivar) r_ivar(v, NULL, arg);
v = r_leave(v, arg, partial);
Expand Down Expand Up @@ -2019,7 +2032,10 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int typ
}
rb_str_set_len(str, dst - ptr);
}
v = r_entry0(rb_reg_new_str(str, options), idx, arg);
VALUE regexp = rb_reg_new_str(str, options);
rb_ivar_foreach(str, r_move_ivar, regexp);

v = r_entry0(regexp, idx, arg);
v = r_leave(v, arg, partial);
}
break;
Expand Down
11 changes: 11 additions & 0 deletions spec/ruby/core/marshal/shared/load.rb
Expand Up @@ -720,6 +720,17 @@
new_obj_metaclass_ancestors[@num_self_class, 3].should ==
[Meths, UserRegexp, Regexp]
end

ruby_bug "#19439", ""..."3.3" do
it "restore the regexp instance variables" do
obj = Regexp.new("hello")
obj.instance_variable_set(:@regexp_ivar, [42])

new_obj = Marshal.send(@method, "\x04\bI/\nhello\x00\a:\x06EF:\x11@regexp_ivar[\x06i/")
new_obj.instance_variables.should == [:@regexp_ivar]
new_obj.instance_variable_get(:@regexp_ivar).should == [42]
end
end
end

describe "for a Float" do
Expand Down
2 changes: 1 addition & 1 deletion version.h
Expand Up @@ -11,7 +11,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 1
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 37
#define RUBY_PATCHLEVEL 38

#include "ruby/version.h"
#include "ruby/internal/abi.h"
Expand Down

0 comments on commit 4e4a4e4

Please sign in to comment.