summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-03-04 14:37:22 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-03-04 14:37:22 +0000
commit37102f6bdba6ca819dc96fc13ebc44087115ec08 (patch)
tree5dc16f3194eda52fdade36c1d0064316a16da399 /compile.c
parent8f2b1b67eafe193013fcac973363e50d666a5a5e (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.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/compile.c b/compile.c
index 5d838b7ac7..6fd0c2a2fd 100644
--- a/compile.c
+++ b/compile.c
@@ -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;