summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <[email protected]>2023-06-29 09:21:11 -0400
committerPeter Zhu <[email protected]>2023-06-29 11:16:50 -0400
commitf0d08d11dcd404f3146c0d71d6ff743bbc6e7193 ()
tree82e6bb0fff741e124915c7a2f6aabe54a484ee71
parentdf2b3a29987e9353596af76ed77f35d7366d654e (diff)
Fix memory when copying ST tables
st_copy allocates a st_table, which is not needed for hashes since it is allocated by VWA and embedded, so this causes a memory . The following script demonstrates the issue: ```ruby 20.times do 100_000.times do {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9} end puts `ps -o rss= -p #{$$}` end ```
Notes: Merged: https://.com/ruby/ruby/pull/8000
-rw-r--r--hash.c7
-rw-r--r--include/ruby/st.h2
-rw-r--r--parser_st.c2
-rw-r--r--parser_st.h1
-rw-r--r--st.c34
5 files changed, 33 insertions, 13 deletions
@@ -1482,7 +1482,9 @@ hash_copy(VALUE ret, VALUE hash)
else {
HASH_ASSERT(sizeof(st_table) <= sizeof(ar_table));
- RHASH_ST_TABLE_SET(ret, st_copy(RHASH_ST_TABLE(hash)));
rb_gc_writebarrier_remember(ret);
}
return ret;
@@ -1776,7 +1778,8 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
}
else {
hash = hash_alloc(klass);
- hash_copy(hash, tmp);
return hash;
}
}
@@ -162,6 +162,8 @@ void rb_st_cleanup_safe(st_table *, st_data_t);
#define st_cleanup_safe rb_st_cleanup_safe
void rb_st_clear(st_table *);
#define st_clear rb_st_clear
st_table *rb_st_copy(st_table *);
#define st_copy rb_st_copy
CONSTFUNC(int rb_st_numcmp(st_data_t, st_data_t));
@@ -109,6 +109,8 @@ nonempty_memcpy(void *dest, const void *src, size_t n)
#define st_add_direct rb_parser_st_add_direct
#undef st_insert2
#define st_insert2 rb_parser_st_insert2
#undef st_copy
#define st_copy rb_parser_st_copy
#undef st_delete_safe
@@ -137,6 +137,7 @@ void rb_parser_st_add_direct(parser_st_table *, parser_st_data_t, parser_st_data
void rb_parser_st_free_table(parser_st_table *);
void rb_parser_st_cleanup_safe(parser_st_table *, parser_st_data_t);
void rb_parser_st_clear(parser_st_table *);
parser_st_table *rb_parser_st_copy(parser_st_table *);
CONSTFUNC(int rb_parser_st_numcmp(parser_st_data_t, parser_st_data_t));
CONSTFUNC(parser_st_index_t rb_parser_st_numhash(parser_st_data_t));
@@ -1228,17 +1228,10 @@ st_insert2(st_table *tab, st_data_t key, st_data_t value,
return 1;
}
-/* Create and return a copy of table OLD_TAB. */
st_table *
-st_copy(st_table *old_tab)
{
- st_table *new_tab;
-
- new_tab = (st_table *) malloc(sizeof(st_table));
-#ifndef RUBY
- if (new_tab == NULL)
- return NULL;
-#endif
*new_tab = *old_tab;
if (old_tab->bins == NULL)
new_tab->bins = NULL;
@@ -1246,7 +1239,6 @@ st_copy(st_table *old_tab)
new_tab->bins = (st_index_t *) malloc(bins_size(old_tab));
#ifndef RUBY
if (new_tab->bins == NULL) {
- free(new_tab);
return NULL;
}
#endif
@@ -1255,7 +1247,6 @@ st_copy(st_table *old_tab)
* sizeof(st_table_entry));
#ifndef RUBY
if (new_tab->entries == NULL) {
- st_free_table(new_tab);
return NULL;
}
#endif
@@ -1263,6 +1254,27 @@ st_copy(st_table *old_tab)
get_allocated_entries(old_tab));
if (old_tab->bins != NULL)
MEMCPY(new_tab->bins, old_tab->bins, char, bins_size(old_tab));
return new_tab;
}