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 <gemini@google.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-07-23 15:12:23 +09:00
parent 48d9113b68
commit 96a9150580
+6 -8
View File
@@ -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;
}