diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-03-04 14:37:22 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-03-04 14:37:22 +0000 |
commit | 37102f6bdba6ca819dc96fc13ebc44087115ec08 (patch) | |
tree | 5dc16f3194eda52fdade36c1d0064316a16da399 /compile.c | |
parent | 8f2b1b67eafe193013fcac973363e50d666a5a5e (diff) |
compile.c: memory leak
* compile.c (iseq_set_sequence): fix potential memory leaks on an
invalid instruction sequence.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57773 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 25 |
1 files changed, 17 insertions, 8 deletions
@@ -1642,6 +1642,12 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) list = FIRST_ELEMENT(anchor); line_info_index = code_index = sp = 0; +#define BADINSN_ERROR \ + (dump_disasm_list(list), \ + xfree(generated_iseq), \ + xfree(line_info_table), \ + COMPILE_ERROR) + while (list) { switch (list->type) { case ISEQ_ELEMENT_INSN: @@ -1653,6 +1659,11 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) /* update sp */ sp = calc_sp_depth(sp, iobj); + if (sp < 0) { + BADINSN_ERROR(iseq, iobj->line_no, + "argument stack underflow (%d)", sp); + return COMPILE_NG; + } if (sp > stack_max) { stack_max = sp; } @@ -1667,10 +1678,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) /* operand check */ if (iobj->operand_size != len - 1) { /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */ - dump_disasm_list(list); - xfree(generated_iseq); - xfree(line_info_table); - COMPILE_ERROR(iseq, iobj->line_no, + BADINSN_ERROR(iseq, iobj->line_no, "operand size miss! (%d for %d)", iobj->operand_size, len - 1); return COMPILE_NG; @@ -1685,7 +1693,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) /* label(destination position) */ LABEL *lobj = (LABEL *)operands[j]; if (!lobj->set) { - COMPILE_ERROR(iseq, iobj->line_no, + BADINSN_ERROR(iseq, iobj->line_no, "unknown label"); return COMPILE_NG; } @@ -1778,9 +1786,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) generated_iseq[code_index + 1 + j] = operands[j]; break; default: - xfree(generated_iseq); - xfree(line_info_table); - COMPILE_ERROR(iseq, iobj->line_no, + BADINSN_ERROR(iseq, iobj->line_no, "unknown operand type: %c", type); return COMPILE_NG; } @@ -1855,6 +1861,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) iseq->body->iseq_size = code_index; iseq->body->stack_max = stack_max; + /* get rid of memory leak when REALLOC failed */ + iseq->body->line_info_table = line_info_table; + REALLOC_N(line_info_table, struct iseq_line_info_entry, line_info_index); iseq->body->line_info_table = line_info_table; iseq->body->line_info_size = line_info_index; |