diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-06-05 14:38:56 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-06-05 14:40:07 +0900 |
| commit | f1523d24042ca3416dc5b9be7b3fc220ddaed896 (patch) | |
| tree | cedcb588a159379b76bd81efdbbc59ec40af3c4f /src/load.c | |
| parent | 00f6271e3b0fa51daad6a3a14758a361a2ba604d (diff) | |
| download | mruby-f1523d24042ca3416dc5b9be7b3fc220ddaed896.tar.gz mruby-f1523d24042ca3416dc5b9be7b3fc220ddaed896.zip | |
Squashed commit of the following:
commit 2d7d545c4c4bfce7fdcbcbe9baaeb437915742f0
Merge: 625a1249 b178914b
Author: Yukihiro "Matz" Matsumoto <[email protected]>
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 b178914b111dda79a8f36ec4eb3e9d37b76f982e
Author: dearblue <[email protected]>
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 52e3d5d8585daf86af3ed12db5ab0efefbc9b956
Author: dearblue <[email protected]>
Date: Sat Jan 19 21:55:36 2019 +0900
Fix memory leak for temporary symbols when out of memory
commit 4c5499b88e47cc6012ad7d7379cb6bc74c6a0b60
Author: dearblue <[email protected]>
Date: Sun Jan 20 11:42:07 2019 +0900
Fix uninitialized pointer dereference for debug section
commit 8e993167dec62a9709d6faacd517729ddcedf4f9
Author: dearblue <[email protected]>
Date: Sun Jan 20 11:41:09 2019 +0900
Fix memory leak for temporary filenames when out of memory
commit 8b422577e6eae68a28121b88421d937e8707b487
Author: dearblue <[email protected]>
Date: Sun Jan 20 10:57:51 2019 +0900
Fix memory leak for irep when out of memory
commit 6b35ebf49a0aa3edb6bbda770ed58681e9c2e6af
Author: dearblue <[email protected]>
Date: Sun Jan 20 10:55:50 2019 +0900
Fix uninitialized pointer dereference when do not finished initializing irep
commit 2531f2631e67e0462749618e2344c733a29238f0
Author: dearblue <[email protected]>
Date: Sun Jan 20 10:48:15 2019 +0900
Fix NULL pointer dereference when do not finished initializing irep
commit e2d6896ebad13694800af49c2625e106b8440ddf
Author: dearblue <[email protected]>
Date: Sat Jan 19 12:54:19 2019 +0900
Fix memory leak for irep when out of memory by `mrb_proc_new()`
commit b6214ff8a0a1c73bc9554e39053878ac50bb683f
Author: dearblue <[email protected]>
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 19162dd6c11f0093d0011e7cab83b8f9e84c2c07
Author: dearblue <[email protected]>
Date: Sun Jan 20 02:15:07 2019 +0900
Fix memory leak for symbol string when out of memory in `kh_put()`
commit 15e67297ff54bc14ef359d6d1e745d760a4a255a
Author: dearblue <[email protected]>
Date: Sun Jan 20 02:12:24 2019 +0900
Fix keep wrong symbol index when out of memory
commit 3f8e2b375244f5441e8d62efa13c6e6a9afecb14
Author: dearblue <[email protected]>
Date: Sun Jan 20 02:08:13 2019 +0900
Fix keep wrong symbol capacity when out of memory
commit a3cfe755ab3e758046c3f4e30938ac8d567ed046
Author: dearblue <[email protected]>
Date: Sat Jan 19 10:11:37 2019 +0900
Fix NULL pointer dereference `mrb->c` by `mark_context()`
commit d9c7b6be6eb54630b64eea5c35be241e551676e5
Author: dearblue <[email protected]>
Date: Sun Jan 20 15:25:09 2019 +0900
Fix protect exception for print error message
commit 100642750e4d549f2e8050f8d6cabdf8825d4495
Author: dearblue <[email protected]>
Date: Sun Jan 20 11:59:02 2019 +0900
Protect exception for mruby core initialization
commit 7a0418304ec70764fa215bef3599f5f735222075
Author: dearblue <[email protected]>
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 fef1c152ce4e52b9e4a34dc23aca5b02907ac639
Author: dearblue <[email protected]>
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 da7d7f881bbbad9988a3a2b7bad8f2b72ff06bc6
Author: dearblue <[email protected]>
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()`
Diffstat (limited to 'src/load.c')
| -rw-r--r-- | src/load.c | 66 |
1 files changed, 54 insertions, 12 deletions
diff --git a/src/load.c b/src/load.c index 2a118c922..043c5a51c 100644 --- a/src/load.c +++ b/src/load.c @@ -14,6 +14,7 @@ #include <mruby/string.h> #include <mruby/debug.h> #include <mruby/error.h> +#include <mruby/data.h> #if SIZE_MAX < UINT32_MAX # error size_t must be at least 32 bits wide @@ -55,6 +56,14 @@ str_to_double(mrb_state *mrb, const char *p, size_t len) mrb_value mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck); +static void +tempirep_free(mrb_state *mrb, void *p) +{ + if (p) mrb_irep_decref(mrb, (mrb_irep *)p); +} + +static const mrb_data_type tempirep_type = { "temporary irep", tempirep_free }; + static mrb_irep* read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) { @@ -63,8 +72,11 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag ptrdiff_t diff; uint16_t tt, pool_data_len, snl; int plen; - int ai = mrb_gc_arena_save(mrb); + struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); mrb_irep *irep = mrb_add_irep(mrb); + int ai = mrb_gc_arena_save(mrb); + + irep_obj->data = irep; /* skip record size */ src += sizeof(uint32_t); @@ -184,36 +196,47 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag } } - irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen); + irep->reps = (mrb_irep**)mrb_calloc(mrb, irep->rlen, sizeof(mrb_irep*)); diff = src - bin; mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); *len = (size_t)diff; + irep_obj->data = NULL; + return irep; } static mrb_irep* read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) { + struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); + mrb_int ai = mrb_gc_arena_save(mrb); mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags); int i; + mrb_gc_arena_restore(mrb, ai); if (irep == NULL) { return NULL; } + irep_obj->data = irep; + bin += *len; for (i=0; i<irep->rlen; i++) { size_t rlen; irep->reps[i] = read_irep_record(mrb, bin, &rlen, flags); + mrb_gc_arena_restore(mrb, ai); if (irep->reps[i] == NULL) { return NULL; } bin += rlen; *len += rlen; } + + irep_obj->data = NULL; + return irep; } @@ -237,21 +260,21 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; } - irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info)); + irep->debug_info = (mrb_irep_debug_info*)mrb_calloc(mrb, 1, sizeof(mrb_irep_debug_info)); irep->debug_info->pc_count = (uint32_t)irep->ilen; record_size = (size_t)bin_to_uint32(bin); bin += sizeof(uint32_t); irep->debug_info->flen = bin_to_uint16(bin); - irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_malloc(mrb, sizeof(mrb_irep_debug_info*) * irep->debug_info->flen); + irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*)); bin += sizeof(uint16_t); for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { mrb_irep_debug_info_file *file; uint16_t filename_idx; - file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file)); + file = (mrb_irep_debug_info_file *)mrb_calloc(mrb, 1, sizeof(*file)); irep->debug_info->files[f_idx] = file; file->start_pos = bin_to_uint32(bin); @@ -281,8 +304,8 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * case mrb_debug_line_flat_map: { uint32_t l; - file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc( - mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count)); + file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_calloc( + mrb, (size_t)(file->line_entry_count), sizeof(mrb_irep_debug_info_line)); for (l = 0; l < file->line_entry_count; ++l) { file->lines.flat_map[l].start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); @@ -329,6 +352,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t int result; uint16_t filenames_len; mrb_sym *filenames; + mrb_value filenames_obj; bin = start; header = (struct rite_section_debug_header *)bin; @@ -336,7 +360,8 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t filenames_len = bin_to_uint16(bin); bin += sizeof(uint16_t); - filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len); + filenames_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)filenames_len); + filenames = (mrb_sym*)RSTRING_PTR(filenames_obj); for (i = 0; i < filenames_len; ++i) { uint16_t f_len = bin_to_uint16(bin); bin += sizeof(uint16_t); @@ -360,7 +385,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t } debug_exit: - mrb_free(mrb, filenames); + mrb_str_resize(mrb, filenames_obj, 0); return result; } @@ -418,6 +443,7 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl int result; uint32_t syms_len; mrb_sym *syms; + mrb_value syms_obj; mrb_sym (*intern_func)(mrb_state*, const char*, size_t) = (flags & FLAG_SRC_MALLOC)? mrb_intern : mrb_intern_static; @@ -427,7 +453,8 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl syms_len = bin_to_uint32(bin); bin += sizeof(uint32_t); - syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)syms_len); + syms_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)syms_len); + syms = (mrb_sym*)RSTRING_PTR(syms_obj); for (i = 0; i < syms_len; ++i) { uint16_t const str_len = bin_to_uint16(bin); bin += sizeof(uint16_t); @@ -447,7 +474,7 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl } lv_exit: - mrb_free(mrb, syms); + mrb_str_resize(mrb, syms_obj, 0); return result; } @@ -484,6 +511,7 @@ static mrb_irep* read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags) { int result; + struct RData *irep_obj = NULL; mrb_irep *irep = NULL; const struct rite_section_header *section_header; uint16_t crc; @@ -504,12 +532,15 @@ read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags) return NULL; } + irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); + bin += sizeof(struct rite_binary_header); do { section_header = (const struct rite_section_header *)bin; if (memcmp(section_header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(section_header->section_ident)) == 0) { irep = read_section_irep(mrb, bin, flags); if (!irep) return NULL; + irep_obj->data = irep; } else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) { if (!irep) return NULL; /* corrupted data */ @@ -528,6 +559,8 @@ read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags) bin += bin_to_uint32(section_header->section_size); } while (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0); + irep_obj->data = NULL; + return irep; } @@ -579,7 +612,16 @@ load_irep(mrb_state *mrb, mrb_irep *irep, mrbc_context *c) MRB_API mrb_value mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c) { - return load_irep(mrb, mrb_read_irep(mrb, bin), c); + struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type); + mrb_irep *irep = mrb_read_irep(mrb, bin); + mrb_value ret; + + irep_obj->data = irep; + mrb_irep_incref(mrb, irep); + ret = load_irep(mrb, irep, c); + irep_obj->data = NULL; + mrb_irep_decref(mrb, irep); + return ret; } MRB_API mrb_value |
