From c695536cc8ea4be69849394b0c64c974d52c603a Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Fri, 20 Dec 2024 17:42:53 +0900 Subject: [PATCH] use `st_update` to prevent table extension to prevent the following scenario: 1. `delete_unique_str()` can be called while GC (sweeping) 2. it calls `st_insert()` to decrement the counter 3. `st_insert()` can try to extend the table even if the key exists 4. `xmalloc` while GC and cause BUG --- ext/objspace/object_tracing.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ext/objspace/object_tracing.c b/ext/objspace/object_tracing.c index a52dff736e..0156642ef2 100644 --- a/ext/objspace/object_tracing.c +++ b/ext/objspace/object_tracing.c @@ -53,6 +53,14 @@ make_unique_str(st_table *tbl, const char *str, long len) } } +static int +delete_unique_str_dec(st_data_t *key, st_data_t *value, st_data_t arg, int existing) +{ + assert(existing); + *value = arg; + return ST_CONTINUE; +} + static void delete_unique_str(st_table *tbl, const char *str) { @@ -66,7 +74,7 @@ delete_unique_str(st_table *tbl, const char *str) ruby_xfree((char *)n); } else { - st_insert(tbl, (st_data_t)str, n-1); + st_update(tbl, (st_data_t)str, delete_unique_str_dec, (st_data_t)(n-1)); } } }