summaryrefslogtreecommitdiff
path: root/marshal.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2021-09-23 01:36:27 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-10-02 11:43:35 +0900
commitd08721465850a6e6954b43bbfebe2ed5a7256dec (patch)
tree4d7b76889e7e9f06f886ffb66ed614cfa6088332 /marshal.c
parent806e7947fec775ce27aa783ee00dbd8f52685db8 (diff)
downloadruby-d08721465850a6e6954b43bbfebe2ed5a7256dec.tar.gz
Restore Hash#compare_by_identity mode [Bug #18171]
Diffstat (limited to 'marshal.c')
-rw-r--r--marshal.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/marshal.c b/marshal.c
index 1643d84d72..acaa27a419 100644
--- a/marshal.c
+++ b/marshal.c
@@ -30,6 +30,7 @@
#include "internal/hash.h"
#include "internal/object.h"
#include "internal/struct.h"
+#include "internal/symbol.h"
#include "internal/util.h"
#include "internal/vm.h"
#include "ruby/io.h"
@@ -966,6 +967,10 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
case T_HASH:
w_uclass(obj, rb_cHash, arg);
+ if (rb_hash_compare_by_id_p(obj)) {
+ w_byte(TYPE_UCLASS, arg);
+ w_symbol(rb_sym_intern_ascii_cstr("Hash"), arg);
+ }
if (NIL_P(RHASH_IFNONE(obj))) {
w_byte(TYPE_HASH, arg);
}
@@ -1702,11 +1707,20 @@ append_extmod(VALUE obj, VALUE extmod)
(str)); \
} while (0)
+static VALUE r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type);
+
static VALUE
r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
{
- VALUE v = Qnil;
int type = r_byte(arg);
+ return r_object_for(arg, partial, ivp, extmod, type);
+}
+
+static VALUE
+r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type)
+{
+ VALUE (*hash_new_with_size)(st_index_t) = rb_hash_new_with_size;
+ VALUE v = Qnil;
long id;
st_data_t link;
@@ -1774,7 +1788,14 @@ r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
if (FL_TEST(c, FL_SINGLETON)) {
rb_raise(rb_eTypeError, "singleton can't be loaded");
}
- v = r_object0(arg, partial, 0, extmod);
+ type = r_byte(arg);
+ if ((c == rb_cHash) &&
+ /* Hack for compare_by_identify */
+ (type == TYPE_HASH || type == TYPE_HASH_DEF)) {
+ hash_new_with_size = rb_ident_hash_new_with_size;
+ goto type_hash;
+ }
+ v = r_object_for(arg, partial, 0, extmod, type);
if (rb_special_const_p(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) {
goto format_error;
}
@@ -1915,10 +1936,11 @@ r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
case TYPE_HASH:
case TYPE_HASH_DEF:
+ type_hash:
{
long len = r_long(arg);
- v = rb_hash_new_with_size(len);
+ v = hash_new_with_size(len);
v = r_entry(v, arg);
arg->readable += (len - 1) * 2;
while (len--) {