Skip to content

Commit f1523d2

Browse files
committed
Squashed commit of the following:
commit 2d7d545c4c4bfce7fdcbcbe9baaeb437915742f0 Merge: 625a1249 b178914 Author: Yukihiro "Matz" Matsumoto <matz@ruby.or.jp> Date: Fri Jun 5 14:35:13 2020 +0900 Merge branch 'fix-mrb_open-with-nomem' of https://github.com/dearblue/mruby into dearblue-fix-mrb_open-with-nomem commit b178914 Author: dearblue <dearblue@users.noreply.github.com> Date: Sat Jan 19 22:22:44 2019 +0900 Fix invalid pointer free inside other heap's block 1. `e = mrb_obj_alloc(...)` 2. `e->stack = mrb->c->stack` (`mrb->c->stack` is anywhere in the range `stbase...stend`) 3. And raised exception by `mrb_malloc()`! 4. `mrb_free(e->stack)` by GC part (wrong free) commit 52e3d5d Author: dearblue <dearblue@users.noreply.github.com> Date: Sat Jan 19 21:55:36 2019 +0900 Fix memory leak for temporary symbols when out of memory commit 4c5499b Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 11:42:07 2019 +0900 Fix uninitialized pointer dereference for debug section commit 8e99316 Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 11:41:09 2019 +0900 Fix memory leak for temporary filenames when out of memory commit 8b42257 Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 10:57:51 2019 +0900 Fix memory leak for irep when out of memory commit 6b35ebf Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 10:55:50 2019 +0900 Fix uninitialized pointer dereference when do not finished initializing irep commit 2531f26 Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 10:48:15 2019 +0900 Fix NULL pointer dereference when do not finished initializing irep commit e2d6896 Author: dearblue <dearblue@users.noreply.github.com> Date: Sat Jan 19 12:54:19 2019 +0900 Fix memory leak for irep when out of memory by `mrb_proc_new()` commit b6214ff Author: dearblue <dearblue@users.noreply.github.com> Date: Sat Jan 19 12:53:07 2019 +0900 Fix memory leak for `khash_t` in `kh_init_size()` when out of memory by `kh_alloc()` commit 19162dd Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 02:15:07 2019 +0900 Fix memory leak for symbol string when out of memory in `kh_put()` commit 15e6729 Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 02:12:24 2019 +0900 Fix keep wrong symbol index when out of memory commit 3f8e2b3 Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 02:08:13 2019 +0900 Fix keep wrong symbol capacity when out of memory commit a3cfe75 Author: dearblue <dearblue@users.noreply.github.com> Date: Sat Jan 19 10:11:37 2019 +0900 Fix NULL pointer dereference `mrb->c` by `mark_context()` commit d9c7b6b Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 15:25:09 2019 +0900 Fix protect exception for print error message commit 1006427 Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 11:59:02 2019 +0900 Protect exception for mruby core initialization commit 7a04183 Author: dearblue <dearblue@users.noreply.github.com> Date: Fri Jan 18 20:38:27 2019 +0900 Fix memory leak for string object when out of memory The `mrb_str_pool()` function has a path to call `malloc()` twice. If occurs `NoMemoryError` exception in second `malloc()`, first `malloc()` pointer is not freed. commit fef1c15 Author: dearblue <dearblue@users.noreply.github.com> Date: Sat Jan 19 13:05:09 2019 +0900 Fix stack overflow when out of memory As a result of this change, no backtrace information is set for NoMemoryError (`mrb->nomem_err`). Detailes: When generating a backtrace, called `mrb_intern_lit()`, `mrb_str_new_cstr()` and `mrb_obj_iv_set()` function with `exc_debug_info()` function in `src/error.c`. If a `NoMemoryError` exception occurs at this time, the `exc_debug_info()` function will be called again, and in the same way `NoMemoryError` exception raised will result in an infinite loop to occurs stack overflow (and SIGSEGV). commit da7d7f8 Author: dearblue <dearblue@users.noreply.github.com> Date: Sun Jan 20 12:00:38 2019 +0900 Fix NULL pointer dereference `mrb->nomem_err` when not initialized Add internal functions (not `static`): * `mrb_raise_nomemory()` * `mrb_core_init_abort()`
1 parent 00f6271 commit f1523d2

File tree

9 files changed

+236
-49
lines changed

9 files changed

+236
-49
lines changed

include/mruby/khash.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0};
7373
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \
7474
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \
7575
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \
76+
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h); \
7677
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \
7778
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \
7879
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
@@ -95,24 +96,36 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
9596
__hash_equal: hash comparation function
9697
*/
9798
#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
98-
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
99+
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb); \
100+
int kh_alloc_simple_##name(mrb_state *mrb, kh_##name##_t *h) \
99101
{ \
100102
khint_t sz = h->n_buckets; \
101103
size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \
102-
uint8_t *p = (uint8_t*)mrb_malloc(mrb, sizeof(uint8_t)*sz/4+len*sz); \
104+
uint8_t *p = (uint8_t*)mrb_malloc_simple(mrb, sizeof(uint8_t)*sz/4+len*sz); \
105+
if (!p) { return 1; } \
103106
h->size = h->n_occupied = 0; \
104107
h->keys = (khkey_t *)p; \
105108
h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \
106109
h->ed_flags = p+len*sz; \
107110
kh_fill_flags(h->ed_flags, 0xaa, sz/4); \
111+
return 0; \
112+
} \
113+
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
114+
{ \
115+
if (kh_alloc_simple_##name(mrb, h)) { \
116+
mrb_raise_nomemory(mrb); \
117+
} \
108118
} \
109119
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
110120
kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
111121
if (size < KHASH_MIN_SIZE) \
112122
size = KHASH_MIN_SIZE; \
113123
khash_power2(size); \
114124
h->n_buckets = size; \
115-
kh_alloc_##name(mrb, h); \
125+
if (kh_alloc_simple_##name(mrb, h)) { \
126+
mrb_free(mrb, h); \
127+
mrb_raise_nomemory(mrb); \
128+
} \
116129
return h; \
117130
} \
118131
kh_##name##_t *kh_init_##name(mrb_state *mrb) { \
@@ -171,12 +184,16 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
171184
mrb_free(mrb, old_keys); \
172185
} \
173186
} \
174-
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
187+
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h) \
175188
{ \
176-
khint_t k, del_k, step = 0; \
177189
if (h->n_occupied >= khash_upper_bound(h)) { \
178190
kh_resize_##name(mrb, h, h->n_buckets*2); \
179191
} \
192+
} \
193+
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
194+
{ \
195+
khint_t k, del_k, step = 0; \
196+
kh_put_prepare_##name(mrb, h); \
180197
k = __hash_func(mrb,key) & khash_mask(h); \
181198
del_k = kh_end(h); \
182199
while (!__ac_isempty(h->ed_flags, k)) { \
@@ -239,6 +256,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
239256
#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h)
240257
#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h)
241258
#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s)
259+
#define kh_put_prepare(name, mrb, h) kh_put_prepare_##name(mrb, h)
242260
#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL)
243261
#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r)
244262
#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k)

src/debug.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,14 @@ mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d)
204204

205205
if (!d) { return; }
206206

207-
for (i = 0; i < d->flen; ++i) {
208-
mrb_assert(d->files[i]);
209-
mrb_free(mrb, d->files[i]->lines.ptr);
210-
mrb_free(mrb, d->files[i]);
207+
if (d->files) {
208+
for (i = 0; i < d->flen; ++i) {
209+
if (d->files[i]) {
210+
mrb_free(mrb, d->files[i]->lines.ptr);
211+
mrb_free(mrb, d->files[i]);
212+
}
213+
}
214+
mrb_free(mrb, d->files);
211215
}
212-
mrb_free(mrb, d->files);
213216
mrb_free(mrb, d);
214217
}

src/error.c

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,16 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc)
185185
}
186186
}
187187

188+
static mrb_noreturn void
189+
exc_throw(mrb_state *mrb, mrb_value exc)
190+
{
191+
if (!mrb->jmp) {
192+
mrb_p(mrb, exc);
193+
abort();
194+
}
195+
MRB_THROW(mrb->jmp);
196+
}
197+
188198
MRB_API mrb_noreturn void
189199
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
190200
{
@@ -197,11 +207,7 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc)
197207
}
198208
mrb_exc_set(mrb, exc);
199209
}
200-
if (!mrb->jmp) {
201-
mrb_p(mrb, exc);
202-
abort();
203-
}
204-
MRB_THROW(mrb->jmp);
210+
exc_throw(mrb, exc);
205211
}
206212

207213
MRB_API mrb_noreturn void
@@ -550,6 +556,52 @@ mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max)
550556
#undef FMT
551557
}
552558

559+
void mrb_core_init_printabort(void);
560+
561+
int
562+
mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state *, void *), void *opaque)
563+
{
564+
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
565+
struct mrb_jmpbuf c_jmp;
566+
int err = 1;
567+
568+
MRB_TRY(&c_jmp) {
569+
mrb->jmp = &c_jmp;
570+
body(mrb, opaque);
571+
err = 0;
572+
} MRB_CATCH(&c_jmp) {
573+
if (mrb->exc) {
574+
mrb_p(mrb, mrb_obj_value(mrb->exc));
575+
mrb->exc = NULL;
576+
}
577+
else {
578+
mrb_core_init_printabort();
579+
}
580+
} MRB_END_EXC(&c_jmp);
581+
582+
mrb->jmp = prev_jmp;
583+
584+
return err;
585+
}
586+
587+
mrb_noreturn void
588+
mrb_core_init_abort(mrb_state *mrb)
589+
{
590+
mrb->exc = NULL;
591+
exc_throw(mrb, mrb_nil_value());
592+
}
593+
594+
mrb_noreturn void
595+
mrb_raise_nomemory(mrb_state *mrb)
596+
{
597+
if (mrb->nomem_err) {
598+
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
599+
}
600+
else {
601+
mrb_core_init_abort(mrb);
602+
}
603+
}
604+
553605
void
554606
mrb_init_exception(mrb_state *mrb)
555607
{

src/gc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ gettimeofday_time(void)
201201

202202
#define objects(p) ((RVALUE *)p->objects)
203203

204+
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb);
205+
204206
MRB_API void*
205207
mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
206208
{
@@ -224,12 +226,12 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len)
224226
if (len == 0) return p2;
225227
if (p2 == NULL) {
226228
if (mrb->gc.out_of_memory) {
227-
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
229+
mrb_raise_nomemory(mrb);
228230
/* mrb_panic(mrb); */
229231
}
230232
else {
231233
mrb->gc.out_of_memory = TRUE;
232-
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
234+
mrb_raise_nomemory(mrb);
233235
}
234236
}
235237
else {
@@ -1294,6 +1296,7 @@ mrb_full_gc(mrb_state *mrb)
12941296
{
12951297
mrb_gc *gc = &mrb->gc;
12961298

1299+
if (!mrb->c) return;
12971300
if (gc->disabled || gc->iterating) return;
12981301

12991302
GC_INVOKE_TIME_REPORT("mrb_full_gc()");

0 commit comments

Comments
 (0)