Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
da7d7f8
Fix NULL pointer dereference `mrb->nomem_err` when not initialized
dearblue Jan 20, 2019
fef1c15
Fix stack overflow when out of memory
dearblue Jan 19, 2019
7a04183
Fix memory leak for string object when out of memory
dearblue Jan 18, 2019
1006427
Protect exception for mruby core initialization
dearblue Jan 20, 2019
d9c7b6b
Fix protect exception for print error message
dearblue Jan 20, 2019
a3cfe75
Fix NULL pointer dereference `mrb->c` by `mark_context()`
dearblue Jan 19, 2019
3f8e2b3
Fix keep wrong symbol capacity when out of memory
dearblue Jan 19, 2019
15e6729
Fix keep wrong symbol index when out of memory
dearblue Jan 19, 2019
19162dd
Fix memory leak for symbol string when out of memory in `kh_put()`
dearblue Jan 19, 2019
b6214ff
Fix memory leak for `khash_t` in `kh_init_size()` when out of memory …
dearblue Jan 19, 2019
e2d6896
Fix memory leak for irep when out of memory by `mrb_proc_new()`
dearblue Jan 19, 2019
2531f26
Fix NULL pointer dereference when do not finished initializing irep
dearblue Jan 20, 2019
6b35ebf
Fix uninitialized pointer dereference when do not finished initializi…
dearblue Jan 20, 2019
8b42257
Fix memory leak for irep when out of memory
dearblue Jan 20, 2019
8e99316
Fix memory leak for temporary filenames when out of memory
dearblue Jan 20, 2019
4c5499b
Fix uninitialized pointer dereference for debug section
dearblue Jan 20, 2019
52e3d5d
Fix memory leak for temporary symbols when out of memory
dearblue Jan 19, 2019
b178914
Fix invalid pointer free inside other heap's block
dearblue Jan 19, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions include/mruby/khash.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0};
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h); \
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
Expand All @@ -95,24 +96,36 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
__hash_equal: hash comparation function
*/
#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb); \
int kh_alloc_simple_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
khint_t sz = h->n_buckets; \
size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \
uint8_t *p = (uint8_t*)mrb_malloc(mrb, sizeof(uint8_t)*sz/4+len*sz); \
uint8_t *p = (uint8_t*)mrb_malloc_simple(mrb, sizeof(uint8_t)*sz/4+len*sz); \
if (!p) { return 1; } \
h->size = h->n_occupied = 0; \
h->keys = (khkey_t *)p; \
h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \
h->ed_flags = p+len*sz; \
kh_fill_flags(h->ed_flags, 0xaa, sz/4); \
return 0; \
} \
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
if (kh_alloc_simple_##name(mrb, h)) { \
mrb_raise_nomemory(mrb); \
} \
} \
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
if (size < KHASH_MIN_SIZE) \
size = KHASH_MIN_SIZE; \
khash_power2(size); \
h->n_buckets = size; \
kh_alloc_##name(mrb, h); \
if (kh_alloc_simple_##name(mrb, h)) { \
mrb_free(mrb, h); \
mrb_raise_nomemory(mrb); \
} \
return h; \
} \
kh_##name##_t *kh_init_##name(mrb_state *mrb) { \
Expand Down Expand Up @@ -171,12 +184,16 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
mrb_free(mrb, old_keys); \
} \
} \
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
khint_t k, del_k, step = 0; \
if (h->n_occupied >= khash_upper_bound(h)) { \
kh_resize_##name(mrb, h, h->n_buckets*2); \
} \
} \
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
{ \
khint_t k, del_k, step = 0; \
kh_put_prepare_##name(mrb, h); \
k = __hash_func(mrb,key) & khash_mask(h); \
del_k = kh_end(h); \
while (!__ac_isempty(h->ed_flags, k)) { \
Expand Down Expand Up @@ -239,6 +256,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h)
#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h)
#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s)
#define kh_put_prepare(name, mrb, h) kh_put_prepare_##name(mrb, h)
#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL)
#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r)
#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k)
Expand Down
13 changes: 8 additions & 5 deletions src/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,14 @@ mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d)

if (!d) { return; }

for (i = 0; i < d->flen; ++i) {
mrb_assert(d->files[i]);
mrb_free(mrb, d->files[i]->lines.ptr);
mrb_free(mrb, d->files[i]);
if (d->files) {
for (i = 0; i < d->flen; ++i) {
if (d->files[i]) {
mrb_free(mrb, d->files[i]->lines.ptr);
mrb_free(mrb, d->files[i]);
}
}
mrb_free(mrb, d->files);
}
mrb_free(mrb, d->files);
mrb_free(mrb, d);
}
63 changes: 58 additions & 5 deletions src/error.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
mrb_callinfo *ci = mrb->c->ci;
mrb_code *pc = ci->pc;

if (!exc || exc == mrb->nomem_err) return;
if (mrb_obj_iv_defined(mrb, exc, mrb_intern_lit(mrb, "file"))) return;
while (ci >= mrb->c->cibase) {
mrb_code *err = ci->err;
Expand Down Expand Up @@ -240,18 +241,24 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc)
}
}

static mrb_noreturn void
exc_throw(mrb_state *mrb, mrb_value exc)
{
if (!mrb->jmp) {
mrb_p(mrb, exc);
abort();
}
MRB_THROW(mrb->jmp);
}

MRB_API mrb_noreturn void
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
{
if (!mrb_obj_is_kind_of(mrb, exc, mrb->eException_class)) {
mrb_raise(mrb, E_TYPE_ERROR, "exception object expected");
}
mrb_exc_set(mrb, exc);
if (!mrb->jmp) {
mrb_p(mrb, exc);
abort();
}
MRB_THROW(mrb->jmp);
exc_throw(mrb, exc);
}

MRB_API mrb_noreturn void
Expand Down Expand Up @@ -483,6 +490,52 @@ mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt,
mrb_exc_raise(mrb, exc);
}

void mrb_core_init_printabort(void);

int
mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state *, void *), void *opaque)
{
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
struct mrb_jmpbuf c_jmp;
int err = 1;

MRB_TRY(&c_jmp) {
mrb->jmp = &c_jmp;
body(mrb, opaque);
err = 0;
} MRB_CATCH(&c_jmp) {
if (mrb->exc) {
mrb_p(mrb, mrb_obj_value(mrb->exc));
mrb->exc = NULL;
}
else {
mrb_core_init_printabort();
}
} MRB_END_EXC(&c_jmp);

mrb->jmp = prev_jmp;

return err;
}

mrb_noreturn void
mrb_core_init_abort(mrb_state *mrb)
{
mrb->exc = NULL;
exc_throw(mrb, mrb_nil_value());
}

mrb_noreturn void
mrb_raise_nomemory(mrb_state *mrb)
{
if (mrb->nomem_err) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
}
else {
mrb_core_init_abort(mrb);
}
}

void
mrb_init_exception(mrb_state *mrb)
{
Expand Down
7 changes: 5 additions & 2 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ gettimeofday_time(void)

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

mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb);

MRB_API void*
mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
{
Expand All @@ -221,12 +223,12 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len)
if (len == 0) return p2;
if (p2 == NULL) {
if (mrb->gc.out_of_memory) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
mrb_raise_nomemory(mrb);
/* mrb_panic(mrb); */
}
else {
mrb->gc.out_of_memory = TRUE;
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
mrb_raise_nomemory(mrb);
}
}
else {
Expand Down Expand Up @@ -1275,6 +1277,7 @@ mrb_full_gc(mrb_state *mrb)
{
mrb_gc *gc = &mrb->gc;

if (!mrb->c) return;
if (gc->disabled || gc->iterating) return;

GC_INVOKE_TIME_REPORT("mrb_full_gc()");
Expand Down
Loading