summaryrefslogtreecommitdiff
path: root/test/ruby/test_hash.rb
AgeCommit message (Collapse)Author
2025-05-24merge revision(s) 056497319658cbefe22351c6ec5c9fa6e4df72bd: [Backport #21357]nagachika
[Bug #21357] Fix crash in Hash#merge with block Prior to https://github.com/ruby/ruby/commit/49b306ecb9e2e9e06e0b1590bacc5f4b38169c3c the `optional_arg` passed from `rb_hash_update_block_i` to `tbl_update` was a hash value (i.e. a VALUE). After that commit it changed to an `update_call_args`. If the block sets or changes the value, `tbl_update_modify` will set the `arg.value` back to an actual value and we won't crash. But in the case where the block returns the original value we end up calling `RB_OBJ_WRITTEN` with the `update_call_args` which is not expected and may crash. `arg.value` appears to only be used to pass to `RB_OBJ_WRITTEN` (others who need the `update_call_args` get it from `arg.arg`), so I don't think it needs to be set to anything upfront. And `tbl_update_modify` will set the `arg.value` in the cases we need the write barrier.
2025-05-24merge revision(s) 49b306ecb9e2e9e06e0b1590bacc5f4b38169c3c: [Backport #21333]nagachika
[Bug #21333] Prohibit hash modification inside Hash#update block
2025-05-17merge revision(s) 7793b59c8d2a13c124fe276e11723db23facce04: [Backport #21331]nagachika
[Bug #21331] Prohibit hash modification during stlike loop
2025-03-08Replace tombstone when converting AR to ST hashJohn Hawthorn
[Bug #21170] st_table reserves -1 as a special hash value to indicate that an entry has been deleted. So that that's a valid value to be returned from the hash function, do_hash replaces -1 with 0 so that it is not mistaken for the sentinel. Previously, when upgrading an AR table to an ST table, rb_st_add_direct_with_hash was used which did not perform the same conversion, this could lead to a hash in a broken state where one if its entries which was supposed to exist being marked as a tombstone. The hash could then become further corrupted when the ST table required resizing as the falsely tombstoned entry would be skipped but it would be counted in num entries, leading to an uninitialized entry at index 15. In most cases this will be really rare, unless using a very poorly implemented custom hash function. This also adds two debug assertions, one that st_add_direct_with_hash does not receive the reserved hash value, and a second in rebuild_table_with, which ensures that after we rebuild/compact a table it contains the expected number of elements. Co-authored-by: Alan Wu <alanwu@ruby-lang.org>
2024-05-28merge revision(s) f36a71e26995b69ff72bc132bbcf40ad89571414: [Backport #20307]Takashi Kokubun
[Bug #20307] Fix `Hash#update` to make frozen copy of string keys
2024-02-01merge revision(s) 6c252912af4981f016a9abdb4c1689307a4f1d2f: [Backport #20145]NARUSE, Yui
Memory leak when duplicating identhash [Bug #20145] Before this commit, both copy_compare_by_id and hash_copy will create a copy of the ST table, so the ST table created in copy_compare_by_id will be leaked. h = { 1 => 2 }.compare_by_identity 10.times do 1_000_000.times do h.select { false } end puts `ps -o rss= -p #{$$}` end Before: 110736 204352 300272 395520 460704 476736 542000 604704 682624 770528 After: 15504 16048 16144 16256 16320 16320 16752 16752 16752 16752 --- hash.c | 10 +++++++++- test/ruby/test_hash.rb | 10 ++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-)
2023-12-15add a testKoichi Sasada
proposed at https://bugs.ruby-lang.org/issues/20050#note-5
2023-12-13Fix memory leak in Hash#compare_by_identityAlan Wu
We didn't free the old ST before overwriting it which caused a leak. Found with RUBY_FREE_ON_EXIT. Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2023-11-21Do not change hash type in Hash#assocNobuyoshi Nakada
2023-11-21Raise an exception when Hash#compare_by_identity during its iterationYusuke Endoh
2023-11-15No need to save `$VERBOSE`Nobuyoshi Nakada
2023-11-15Separate tests for Hash only from tests for Hash and its subclassesNobuyoshi Nakada
2023-11-11[Bug #19969] Compact st_table after deleted if possibleNobuyoshi Nakada
2023-09-23Fix memory leak in Hash#rehash for ST hashesPeter Zhu
We need to free the old ST table in Hash#rehash. Co-authored-by: Adam Hess <adamhess1991@gmail.com>
2023-06-29Fix memory leak in Hash#replacePeter Zhu
Hash#replace can leak memory if the receiver has an ST table. Notes: Merged: https://github.com/ruby/ruby/pull/8001
2023-06-29Add memory leak test for allocating ST hashesPeter Zhu
Test for commit f0d08d11dcd404f3146c0d71d6ff743bbc6e7193.
2023-05-23Fix crash when replacing ST hash with AR hashPeter Zhu
With VWA, AR hashes are much larger than ST hashes. Hash#replace attempts to directly copy the contents of AR hashes into ST hashes so there will be memory corruption caused by writing past the end of memory. This commit changes it so that if a ST hash is being replaced with an AR hash it will insert each element into the ST hash. Notes: Merged: https://github.com/ruby/ruby/pull/7846
2023-04-11hash.c: Fix hash_iter_lev_dec corrupting shapeJean Boussier
[Bug #19589] When decrementing `iter_lev` from `65` to `64` the flags would be corrupted, causing the shape_id to be invalid. Notes: Merged: https://github.com/ruby/ruby/pull/7686
2022-08-04Fix inconsistency with opt_aref_withJohn Hawthorn
opt_aref_with is an optimized instruction for accessing a Hash using a non-frozen string key (ie. from a file without frozen_string_literal). It attempts to avoid allocating the string, and instead silently using a frozen string (hash string keys are always fstrings). Because this is just an optimization, it should be invisible to the user. However, previously this optimization was could be seen via hashes with default procs. For example, previously: h = Hash.new { |h, k| k.frozen? } str = "foo" h[str] # false h["foo"] # true when optimizations enabled This commit checks that the Hash doesn't have a default proc when using opt_aref_with. Notes: Merged: https://github.com/ruby/ruby/pull/6196
2022-06-10Make method id explicit in rb_exec_recursive_outerJohn Hawthorn
Previously, because opt_aref and opt_aset don't push a frame, when they would call rb_hash to determine the hash value of the key, the initial level of recursion would incorrectly use the method id at the top of the stack instead of "hash". This commit replaces rb_exec_recursive_outer with rb_exec_recursive_outer_mid, which takes an explicit method id, so that we can make the hash calculation behave consistently. rb_exec_recursive_outer was documented as being internal, so I believe this should be okay to change. Notes: Merged: https://github.com/ruby/ruby/pull/6004
2022-02-10st.c: Do not clear entries_bound when calling Hash#shift for empty hashYusuke Endoh
tab->entries_bound is used to check if the bins are full in rebuild_table_if_necessary. Hash#shift against an empty hash assigned 0 to tab->entries_bound, but didn't clear the bins. Thus, the table is not rebuilt even when the bins are full. Attempting to add a new element into full-bin hash gets stuck. This change stops clearing tab->entries_bound in Hash#shift. [Bug #18578] Notes: Merged: https://github.com/ruby/ruby/pull/5539
2022-01-14Make Hash#shift return nil for empty hashJeremy Evans
Fixes [Bug #16908] Notes: Merged: https://github.com/ruby/ruby/pull/5360
2021-09-11Add documentation and tests for keyword argument value omissionShugo Maeda
[Feature #14579]
2021-09-11Another test for [Feature #14579]Nobuyoshi Nakada
The value of the dynamic key cannot be omitted for now.
2021-09-11Allow value omission in Hash literalsShugo Maeda
`{x:, y:}` is a syntax sugar of `{x: x, y: y}`.
2021-08-29Free previously used tables [Bug #18134]Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4788
2021-08-19Remove old warning aged nearly 8 yearsNobuyoshi Nakada
2021-07-15Copy hash compare_by_identity setting in more casesJeremy Evans
This makes the compare_by_identity setting always copied for the following methods: * except * merge * reject * select * slice * transform_values Some of these methods did not copy the setting, or only copied the setting if the receiver was not empty. Fixes [Bug #17757] Co-authored-by: Kenichi Kamiya <kachick1@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/4616 Merged-By: jeremyevans <code@jeremyevans.net>
2021-07-08Split test of Hash.[] and add assertion for default value/procNobuyoshi Nakada
For a73f13c9070a5189947641638398cbffb8d012d8.
2021-03-28Keep non evaluated keys in `Hash#transform_keys!` [Bug #17735]Kenichi Kamiya
Notes: Merged: https://github.com/ruby/ruby/pull/4294 Merged-By: nobu <nobu@ruby-lang.org>
2021-03-22Hash#transform_values! ensures receiver modifiable in block [Bug #17736]Kenichi Kamiya
Notes: Merged: https://github.com/ruby/ruby/pull/4302 Merged-By: nobu <nobu@ruby-lang.org>
2021-03-21Ensure the receiver hash modifiable before updating [Bug #17736]Nobuyoshi Nakada
Close https://github.com/ruby/ruby/pull/4298 Notes: Merged: https://github.com/ruby/ruby/pull/4299
2021-03-21Add Hash#{update, merge!} test to ensure receiver modifiable in blockKenichi Kamiya
Notes: Merged: https://github.com/ruby/ruby/pull/4299
2021-03-20Some Hash destructive methods ensure the receiver modifiable [Bug #17736]Kenichi Kamiya
refs: * https://bugs.ruby-lang.org/issues/17736 * https://github.com/ruby/ruby/pull/4296 This commit aims to cover following methods * Hash#select! * Hash#filter! * Hash#keep_if * Hash#reject! * Hash#delete_if I think these are not all. --- * Ensure the receiver is modifiable or not * Assert the receiver is not modified Notes: Merged: https://github.com/ruby/ruby/pull/4297
2021-03-18Avoid rehashing in Hash#replace/dup/initialize_copy [Bug #16996]Marc-Andre Lafortune
2021-03-18Avoid rehashing in Hash#select/reject [Bug #16996]Marc-Andre Lafortune
2020-12-31Make any hash values fixable [Bug #17488]Nobuyoshi Nakada
As hnum is an unsigned st_index_t, the result of RSHIFT may not be in the fixable range. Co-authored-by: NeoCat <neocat@neocat.jp>
2020-12-17test/ruby: suppress some warningsYusuke Endoh
follow up to 9908177857a28633d6279c43a1ad4dfedcb98596
2020-12-17test/ruby: Check warning messages at a finer granularityNobuyoshi Nakada
Instead of suppressing all warnings wholly in each test scripts by setting `$VERBOSE` to `nil` in `setup` methods. Notes: Merged: https://github.com/ruby/ruby/pull/3925 Merged-By: nobu <nobu@ruby-lang.org>
2020-09-21Make hash returned by Hash#transform_values not have a defaultJeremy Evans
This sets an explicit default of nil. There is probably a better approach of removing the default. Fixes [Bug #17181] Notes: Merged: https://github.com/ruby/ruby/pull/3563
2020-06-18Add Hash#except ENV#except [Feature #15822]Timo Schilling
2020-03-16`Proc` made by `Hash#to_proc` should be a lambda [Bug #12671]Yusuke Endoh
Like `Symbol#to_proc` (f0b815dc670b61eba1daaa67a8613ac431d32b16)
2020-03-16hash.c: Do not use the fast path (rb_yield_values) for lambda blocksYusuke Endoh
As a semantics, Hash#each yields a 2-element array (pairs of keys and values). So, `{ a: 1 }.each(&->(k, v) { })` should raise an exception due to lambda's arity check. However, the optimization that avoids Array allocation by using rb_yield_values for blocks whose arity is more than 1 (introduced at b9d29603375d17c3d1d609d9662f50beaec61fa1 and some commits), seemed to overlook the lambda case, and wrongly allowed the code above to work. This change experimentally attempts to make it strict; now the code above raises an ArgumentError. This is an incompatible change; if the compatibility issue is bigger than our expectation, it may be reverted (until Ruby 3.0 release). [Bug #12706]
2020-03-07check ar_table after `#hash` callKoichi Sasada
ar_table can be converted to st_table just after `ar_do_hash()` function which calls `#hash` method. We need to check the representation to detect this mutation. [Bug #16676]
2020-02-25should count only string.Koichi Sasada
This code can generate CC objects so we only need to count existing String objects.
2020-01-19Fix typo s/test_ruby2_keywords_hash!/test_ruby2_keywords_hash/Ryuta Kamizono
In #2818, `Hash.ruby2_keywords!` has renamed to `Hash.ruby2_keywords_hash`. Notes: Merged: https://github.com/ruby/ruby/pull/2849
2020-01-17hash.c: Add a feature to manipulate ruby2_keywords flagYusuke Endoh
It was found that a feature to check and add ruby2_keywords flag to an existing Hash is needed when arguments are serialized and deserialized. It is possible to do the same without explicit APIs, but it would be good to provide them as a core feature. https://github.com/rails/rails/pull/38105#discussion_r361863767 Hash.ruby2_keywords_hash?(hash) checks if hash is flagged or not. Hash.ruby2_keywords_hash(hash) returns a duplicated hash that has a ruby2_keywords flag, [Bug #16486] Notes: Merged: https://github.com/ruby/ruby/pull/2818
2020-01-10Hash#transform_values should return a plain new HashNobuyoshi Nakada
[Bug #16498]
2019-12-26Transform hash keys by a hash [Feature #16274]Nobuyoshi Nakada
2019-11-18Deprecate taint/trust and related methods, and make the methods no-opsJeremy Evans
This removes the related tests, and puts the related specs behind version guards. This affects all code in lib, including some libraries that may want to support older versions of Ruby. Notes: Merged: https://github.com/ruby/ruby/pull/2476