From 96a91505809ed36b64a8bb43ac10285c042f9d28 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 23 Jul 2025 15:12:23 +0900 Subject: [PATCH] mruby-array-ext: fix use-after-free in ary_uniq This commit fixes a use-after-free vulnerability in `ary_uniq` by replacing pointer-based iteration with index-based loops. This prevents raw pointers from becoming stale after a garbage collection cycle is triggered by functions like `mrb_hash_set`, `mrb_ary_push`, or `mrb_equal`. Co-authored-by: Gemini --- mrbgems/mruby-array-ext/src/array.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c index 5490de950..058a49820 100644 --- a/mrbgems/mruby-array-ext/src/array.c +++ b/mrbgems/mruby-array-ext/src/array.c @@ -888,9 +888,7 @@ ary_fill_exec(mrb_state *mrb, mrb_value self) static mrb_value ary_uniq(mrb_state *mrb, mrb_value self) { - struct RArray *ary = mrb_ary_ptr(self); - mrb_int len = ARY_LEN(ary); - mrb_value *ptr = ARY_PTR(ary); + mrb_int len = RARRAY_LEN(self); mrb_value result = mrb_ary_new_capa(mrb, len); if (len == 0) { @@ -900,7 +898,7 @@ ary_uniq(mrb_state *mrb, mrb_value self) if (len > SET_OP_HASH_THRESHOLD) { mrb_value hash = mrb_hash_new_capa(mrb, len); for (mrb_int i = 0; i < len; i++) { - mrb_value elem = ptr[i]; + mrb_value elem = RARRAY_PTR(self)[i]; if (mrb_nil_p(mrb_hash_get(mrb, hash, elem))) { mrb_hash_set(mrb, hash, elem, mrb_true_value()); mrb_ary_push(mrb, result, elem); @@ -909,11 +907,11 @@ ary_uniq(mrb_state *mrb, mrb_value self) } else { for (mrb_int i = 0; i < len; i++) { - mrb_value elem = ptr[i]; + mrb_value elem = RARRAY_PTR(self)[i]; mrb_bool found = FALSE; - mrb_value *result_ptr = ARY_PTR(RARRAY(result)); - for (mrb_int j = 0; j < RARRAY_LEN(result); j++) { - if (mrb_equal(mrb, elem, result_ptr[j])) { + mrb_int result_len = RARRAY_LEN(result); + for (mrb_int j = 0; j < result_len; j++) { + if (mrb_equal(mrb, elem, RARRAY_PTR(result)[j])) { found = TRUE; break; }