fix a memleaking issue in cs_disasm_ex() where memory was not freed when input code is illegit
diff --git a/cs.c b/cs.c
index ad1586f..49e9504 100644
--- a/cs.c
+++ b/cs.c
@@ -424,7 +424,7 @@
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
MCInst mci;
uint16_t insn_size;
- size_t c = 0;
+ size_t c = 0, i;
unsigned int f = 0;
cs_insn *insn_cache;
void *total = NULL;
@@ -482,6 +482,12 @@
total_size += (sizeof(cs_insn) * INSN_CACHE_SIZE);
tmp = cs_mem_realloc(total, total_size);
if (tmp == NULL) { // insufficient memory
+ if (handle->detail) {
+ insn_cache = (cs_insn *)total;
+ for (i = 0; i < c; i++, insn_cache++)
+ cs_mem_free(insn_cache->detail);
+ }
+
cs_mem_free(total);
handle->errnum = CS_ERR_MEM;
return 0;
@@ -503,6 +509,11 @@
size -= insn_size;
offset += insn_size;
} else {
+ if (handle->detail) {
+ // free memory of @detail pointer
+ cs_mem_free(insn_cache->detail);
+ }
+
// encounter a broken instruction
// if there is no request to skip data, or remaining data is too small,
// then bail out
@@ -539,16 +550,24 @@
total_size += (sizeof(cs_insn) * INSN_CACHE_SIZE);
tmp = cs_mem_realloc(total, total_size);
if (tmp == NULL) { // insufficient memory
+ if (handle->detail) {
+ insn_cache = (cs_insn *)total;
+ for (i = 0; i < c; i++, insn_cache++)
+ cs_mem_free(insn_cache->detail);
+ }
+
cs_mem_free(total);
handle->errnum = CS_ERR_MEM;
return 0;
}
total = tmp;
+ insn_cache = (cs_insn *)((char *)total + total_size - (sizeof(cs_insn) * INSN_CACHE_SIZE));
// reset f back to 0
f = 0;
- }
+ } else
+ insn_cache++;
buffer += skipdata_bytes;
size -= skipdata_bytes;
@@ -561,12 +580,23 @@
// resize total to contain newly disasm insns
void *tmp = cs_mem_realloc(total, total_size - (INSN_CACHE_SIZE - f) * sizeof(*insn_cache));
if (tmp == NULL) { // insufficient memory
+ // free all detail pointers
+ if (handle->detail) {
+ insn_cache = (cs_insn *)total;
+ for (i = 0; i < c; i++, insn_cache++)
+ cs_mem_free(insn_cache->detail);
+ }
+
cs_mem_free(total);
+
handle->errnum = CS_ERR_MEM;
return 0;
}
total = tmp;
+ } else if (!c) {
+ cs_mem_free(total);
+ total = NULL;
}
*insn = total;