diff --git a/src/c2.c b/src/c2.c index d0c1aeb8..70d5b84c 100644 --- a/src/c2.c +++ b/src/c2.c @@ -886,11 +886,10 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) case 'v': *(ptptnstr++) = '\v'; break; case 'o': case 'x': { - char *tstr = strndup(pattern + offset + 1, 2); + scoped_charp tstr = strndup(pattern + offset + 1, 2); char *pstr = NULL; long val = strtol( tstr, &pstr, ('o' == pattern[offset] ? 8 : 16)); - free(tstr); if (pstr != &tstr[2] || val <= 0) c2_error("Invalid octal/hex escape " "sequence."); diff --git a/src/compiler.h b/src/compiler.h index f146bd21..76326707 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -85,6 +85,12 @@ # define fallthrough() #endif +#if __has_attribute(cleanup) +# define cleanup(func) __attribute__((cleanup(func))) +#else +# error "Compiler is missing cleanup attribute" +#endif + #if __STDC_VERSION__ >= 201112L # define attr_noret _Noreturn #else diff --git a/src/utils.h b/src/utils.h index 23a5abb1..b9a81b46 100644 --- a/src/utils.h +++ b/src/utils.h @@ -273,6 +273,15 @@ allocchk_(const char *func_name, const char *file, unsigned int line, void *ptr) void name##_ref(type *a); \ void name##_unref(type **a); +static inline void free_charpp(char **str) { + if (str) { + free(*str); + *str = NULL; + } +} + +/// An allocated char* that is automatically freed when it goes out of scope. +#define scoped_charp char *cleanup(free_charpp) /// /// Calculates next closest power of two of 32bit integer n