From 9340c2e55ca81bec8e5393def4d2a6d414e5ea23 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sun, 24 May 2020 19:50:32 +0200 Subject: [PATCH] Fix memory leak for _parse_str in case of error. --- m-array.h | 11 ++++++----- m-bptree.h | 36 ++++++++++++++++++------------------ m-deque.h | 11 ++++++----- m-dict.h | 15 ++++++++------- m-list.h | 11 ++++++----- m-rbtree.h | 11 ++++++----- 6 files changed, 50 insertions(+), 45 deletions(-) diff --git a/m-array.h b/m-array.h index 912505f8..7bbd788a 100644 --- a/m-array.h +++ b/m-array.h @@ -880,7 +880,7 @@ { \ ARRAYI_CONTRACT(array); \ assert (str != NULL); \ - M_C(name,_clean)(array); \ + M_C(name,_clean)(array); \ bool success = false; \ int c = *str++; \ if (M_UNLIKELY (c != '[')) goto exit; \ @@ -893,12 +893,13 @@ do { \ bool b = M_CALL_PARSE_STR(oplist, item, str, &str); \ do { c = *str++; } while (isspace(c)); \ - if (b == false || c == 0) { goto exit; } \ - M_C(name, _push_back)(array, item); \ - } while (c == M_GET_SEPARATOR oplist); \ - M_CALL_CLEAR(oplist, item); \ + if (b == false || c == 0) { goto exit_clear; } \ + M_C(name, _push_back)(array, item); \ + } while (c == M_GET_SEPARATOR oplist); \ ARRAYI_CONTRACT(array); \ success = (c == ']'); \ + exit_clear: \ + M_CALL_CLEAR(oplist, item); \ exit: \ if (endp) *endp = str; \ return success; \ diff --git a/m-bptree.h b/m-bptree.h index 46c00bb1..da2f7365 100644 --- a/m-bptree.h +++ b/m-bptree.h @@ -1186,7 +1186,7 @@ { \ BPTREEI_CONTRACT(N, isMulti, key_oplist, t1); \ assert (str != NULL); \ - M_C(name,_clean)(t1); \ + M_C(name,_clean)(t1); \ bool success = false; \ int c = *str++; \ if (M_UNLIKELY (c != '[')) goto exit; \ @@ -1194,28 +1194,28 @@ if (M_UNLIKELY (c == ']')) { success = true; goto exit;} \ if (M_UNLIKELY (c == 0)) goto exit; \ str--; \ - key_t key; \ - M_CALL_INIT(key_oplist, key); \ - M_IF(isMap)(value_t value; \ - M_CALL_INIT(value_oplist, value); \ - ,) \ + key_t key; \ + M_CALL_INIT(key_oplist, key); \ + M_IF(isMap)(value_t value; \ + M_CALL_INIT(value_oplist, value); \ + , /* No isMap */) \ do { \ bool b = M_CALL_PARSE_STR(key_oplist, key, str, &str); \ do { c = *str++; } while (isspace(c)); \ - if (b == false) goto exit; \ - M_IF(isMap)(if (c != ':') goto exit; \ + if (b == false) goto exit_clear; \ + M_IF(isMap)(if (c != ':') goto exit_clear; \ b = M_CALL_PARSE_STR(value_oplist, value, str, &str); \ - do { c = *str++; } while (isspace(c)); \ - if (b == false || c == 0) goto exit; \ - M_C(name, _set_at)(t1, key, value) \ - , \ - M_C(name, _push)(t1, key) \ - ); \ - } while (c == M_GET_SEPARATOR key_oplist); \ - M_CALL_CLEAR(key_oplist, key); \ - M_IF(isMap)(M_CALL_CLEAR(value_oplist, value); \ - ,) \ + do { c = *str++; } while (isspace(c)); \ + if (b == false || c == 0) goto exit_clear; \ + M_C(name, _set_at)(t1, key, value); \ + , \ + M_C(name, _push)(t1, key); \ + ) \ + } while (c == M_GET_SEPARATOR key_oplist); \ success = (c == ']'); \ + exit_clear: \ + M_CALL_CLEAR(key_oplist, key); \ + M_IF(isMap)(M_CALL_CLEAR(value_oplist, value); , /* No isMap */ ) \ exit: \ if (endp) *endp = str; \ return success; \ diff --git a/m-deque.h b/m-deque.h index 13fae28d..7f5dcae1 100644 --- a/m-deque.h +++ b/m-deque.h @@ -847,7 +847,7 @@ { \ DEQUEI_CONTRACT(deque); \ assert (str != NULL); \ - M_C(name,_clean)(deque); \ + M_C(name,_clean)(deque); \ bool success = false; \ int c = *str++; \ if (M_UNLIKELY (c != '[')) goto exit; \ @@ -860,12 +860,13 @@ do { \ bool b = M_CALL_PARSE_STR(oplist, item, str, &str); \ do { c = *str++; } while (isspace(c)); \ - if (b == false || c == 0) { goto exit; } \ - M_C(name, _push_back)(deque, item); \ - } while (c == M_GET_SEPARATOR oplist); \ - M_CALL_CLEAR(oplist, item); \ + if (b == false || c == 0) { goto exit_clear; } \ + M_C(name, _push_back)(deque, item); \ + } while (c == M_GET_SEPARATOR oplist); \ DEQUEI_CONTRACT(deque); \ success = (c == ']'); \ + exit_clear: \ + M_CALL_CLEAR(oplist, item); \ exit: \ if (endp) *endp = str; \ return success; \ diff --git a/m-dict.h b/m-dict.h index 97a95d74..976f8bef 100644 --- a/m-dict.h +++ b/m-dict.h @@ -743,7 +743,7 @@ M_C(name, _parse_str)(dict_t dict, const char str[], const char **endp) \ { \ assert (str != NULL); \ - M_C(name, _clean)(dict); \ + M_C(name, _clean)(dict); \ bool success = false; \ int c = *str++; \ if (M_UNLIKELY (c != '{')) goto exit; \ @@ -759,20 +759,21 @@ while (isspace((int) *str)) str++; \ bool b = M_CALL_PARSE_STR(key_oplist, key, str, &str); \ M_IF(isSet)( \ - if (b == false) { break; } \ + if (b == false) { goto exit_clear; } \ M_C(name, _push)(dict, key); \ , \ do { c = *str++; } while (isspace(c)); \ - if (b == false || c != ':') { goto exit; } \ + if (b == false || c != ':') { goto exit_clear; } \ b = M_CALL_PARSE_STR(value_oplist, value, str, &str); \ - if (b == false) { goto exit; } \ + if (b == false) { goto exit_clear; } \ M_C(name, _set_at)(dict, key, value); \ - ) \ + ) \ do { c = *str++; } while (isspace(c)); \ - } while (c == ','); \ + } while (c == ','); \ + success = (c == '}'); \ + exit_clear: \ M_CALL_CLEAR(key_oplist, key); \ M_CALL_CLEAR(value_oplist, value); \ - success = (c == '}'); \ exit: \ if (endp) *endp = str; \ return success; \ diff --git a/m-list.h b/m-list.h index 4cd7d4cc..4d611e87 100644 --- a/m-list.h +++ b/m-list.h @@ -697,12 +697,13 @@ do { \ bool b = M_CALL_PARSE_STR(oplist, item, str, &str); \ do { c = *str++; } while (isspace(c)); \ - if (b == false || c == 0) { goto exit; } \ - M_C(name, _push_back)(list, item); \ - } while (c == M_GET_SEPARATOR oplist); \ - M_CALL_CLEAR(oplist, item); \ - M_C(name, _reverse)(list); \ + if (b == false || c == 0) { goto exit_clear; } \ + M_C(name, _push_back)(list, item); \ + } while (c == M_GET_SEPARATOR oplist); \ + M_C(name, _reverse)(list); \ success = (c == ']'); \ + exit_clear: \ + M_CALL_CLEAR(oplist, item); \ exit: \ if (endp) *endp = str; \ return success; \ diff --git a/m-rbtree.h b/m-rbtree.h index 4e21cede..0d872c94 100644 --- a/m-rbtree.h +++ b/m-rbtree.h @@ -989,7 +989,7 @@ typedef enum { { \ RBTREEI_CONTRACT(rbtree); \ assert (str != NULL); \ - M_C(name,_clean)(rbtree); \ + M_C(name,_clean)(rbtree); \ bool success = false; \ int c = *str++; \ if (M_UNLIKELY (c != '[')) goto exit; \ @@ -1002,11 +1002,12 @@ typedef enum { do { \ bool b = M_CALL_PARSE_STR(oplist, item, str, &str); \ do { c = *str++; } while (isspace(c)); \ - if (b == false || c == 0) goto exit; \ - M_C(name, _push)(rbtree, item); \ - } while (c == M_GET_SEPARATOR oplist); \ - M_CALL_CLEAR(oplist, item); \ + if (b == false || c == 0) goto exit_clear; \ + M_C(name, _push)(rbtree, item); \ + } while (c == M_GET_SEPARATOR oplist); \ success = (c == ']'); \ + exit_clear: \ + M_CALL_CLEAR(oplist, item); \ exit: \ if (endp) *endp = str; \ return success; \