From 893cc758c30bd39899e6ef0fe6f960756968a42d Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 2 Nov 2025 21:18:18 +0900 Subject: [PATCH] Added the `kh_is_end()` macro function The primary reason is to fix an issue that occurs when an element is removed from the khash data during the `KHASH_FOREACH()` loop. If the value of `kh_end()` becomes smaller than `k` during the loop, it will repeat a meaningless internal loop until an integer overflow occurs. --- include/mruby/khash.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/mruby/khash.h b/include/mruby/khash.h index c713e4e70..4b846177d 100644 --- a/include/mruby/khash.h +++ b/include/mruby/khash.h @@ -407,6 +407,7 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; #define kh_value(name, h, x) (kh_vals_##name(h)[x]) #define kh_begin(h) (khint_t)(0) #define kh_end(h) ((h)->n_buckets == 0 ? (h)->size : (h)->n_buckets) +#define kh_is_end(h, i) ((i) >= kh_end(h)) #define kh_size(h) ((h)->size) #define kh_n_buckets(h) ((h)->n_buckets) @@ -448,7 +449,7 @@ MRB_END_DECL */ #define KHASH_FOREACH(name, kh, k) \ if (kh) \ - for (khiter_t k = kh_begin(kh); k != kh_end(kh); k++) \ + for (khiter_t k = kh_begin(kh); !kh_is_end(kh, k); k++) \ if (kh_exist(name, kh, k)) #endif /* MRUBY_KHASH_H */