summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2022-11-09 09:23:45 -0800
committerJeremy Evans <code@jeremyevans.net>2023-03-24 10:55:13 -0700
commitd3197def882b47e7c57cdddfe8d62f62fef9d3f7 (patch)
tree52ab45b683bcc6e7f718dbdca1007d5a82928ed9 /hash.c
parent35e9b5348d91eff13d2bdc487003f46a19586d42 (diff)
downloadruby-d3197def882b47e7c57cdddfe8d62f62fef9d3f7.tar.gz
Do not copy compare_by_identity flag for non-empty hashes in Hash.[]
It wasn't copied for empty hashes, and Hash.[] doesn't copy the default value, so copying the compare_by_identity flag does not make sense. Partially Fixes [Bug #19113]
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/hash.c b/hash.c
index c9f741f2ec..40866509d1 100644
--- a/hash.c
+++ b/hash.c
@@ -1801,6 +1801,8 @@ rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
return hash;
}
+static VALUE rb_hash_to_a(VALUE hash);
+
/*
* call-seq:
* Hash[] -> new_empty_hash
@@ -1844,12 +1846,22 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
if (argc == 1) {
tmp = rb_hash_s_try_convert(Qnil, argv[0]);
if (!NIL_P(tmp)) {
- hash = hash_alloc(klass);
- hash_copy(hash, tmp);
- return hash;
+ if (!RHASH_EMPTY_P(tmp) && rb_hash_compare_by_id_p(tmp)) {
+ /* hash_copy for non-empty hash will copy compare_by_identity
+ flag, but we don't want it copied. Work around by
+ converting hash to flattened array and using that. */
+ tmp = rb_hash_to_a(tmp);
+ }
+ else {
+ hash = hash_alloc(klass);
+ hash_copy(hash, tmp);
+ return hash;
+ }
+ }
+ else {
+ tmp = rb_check_array_type(argv[0]);
}
- tmp = rb_check_array_type(argv[0]);
if (!NIL_P(tmp)) {
long i;