From 98ef6a8510d555148528e4fffb6cfa587dbd4c46 Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Sat, 7 Aug 2021 15:10:44 +0100 Subject: always va_end even when an error occurs --- common.h | 3 +++ pack.c | 10 ++++++---- unpack.c | 13 ++++++++----- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/common.h b/common.h index f22f588..abef5af 100644 --- a/common.h +++ b/common.h @@ -12,6 +12,9 @@ #define BITMASK(n) (UINTMAX_MAX >> (sizeof (uintmax_t) * CHAR_BIT - n)) +#define SET_AND_GOTO(what, to, where) \ + do { (what) = (to); goto where; } while (0); + #ifndef PRIuSIZE #ifdef _WIN32 #ifdef _WIN64 diff --git a/pack.c b/pack.c index 002d1ee..4a8228a 100644 --- a/pack.c +++ b/pack.c @@ -22,6 +22,7 @@ enum pack_status pack(void *buf_, size_t size, const char *fmt, ...) { enum pack_endian endianness = PACK_ENDIAN_BIG; unsigned char *buf = buf_; + enum pack_status ret = PACK_OK; size_t offset = 0; va_list ap; @@ -45,15 +46,15 @@ enum pack_status pack(void *buf_, size_t size, const char *fmt, ...) ITYPE_MACROS #undef T case PACK_TYPE_PADDING: v.unsigned_ = 0; sign = false; break; - default: return PACK_FMTINVAL; + default: SET_AND_GOTO(ret, PACK_FMTINVAL, stop); } tr_debug("i: %d, fmt[i]: %c, sign: %ssigned", i, fmt[i], sign ? "" : "un"); s = getsize(fmt[i]); tr_debug("s: %" PRIuSIZE, s); - if (s == (size_t)-1) return PACK_FMTINVAL; + if (s == (size_t)-1) SET_AND_GOTO(ret, PACK_FMTINVAL, stop); - if (size - offset < s) return PACK_TOOSMALL; + if (size - offset < s) SET_AND_GOTO(ret, PACK_TOOSMALL, stop); if (sign) { intmax_t n = v.signed_; @@ -71,7 +72,8 @@ enum pack_status pack(void *buf_, size_t size, const char *fmt, ...) offset += s; } +stop: va_end(ap); - return PACK_OK; + return ret; } diff --git a/unpack.c b/unpack.c index 472cc8c..3143931 100644 --- a/unpack.c +++ b/unpack.c @@ -40,6 +40,7 @@ enum pack_status unpack(const void *buf_, size_t size, const char *fmt, ...) { enum pack_endian endianness = PACK_ENDIAN_BIG; const unsigned char *buf = buf_; + enum pack_status ret = PACK_OK; size_t offset = 0; va_list ap; @@ -73,7 +74,7 @@ enum pack_status unpack(const void *buf_, size_t size, const char *fmt, ...) errno = 0; c = strtoull(&fmt[i], &end, 10); if ((c == ULLONG_MAX && errno == ERANGE) || c > SIZE_MAX) - return PACK_FMTINVAL; + SET_AND_GOTO(ret, PACK_FMTINVAL, stop); count = c; i += end - &fmt[i]; } else if (fmt[i] == '*') { @@ -95,15 +96,16 @@ enum pack_status unpack(const void *buf_, size_t size, const char *fmt, ...) case PACK_TYPE_FLOAT: arg.f = va_arg(ap, float *); break; case PACK_TYPE_DOUBLE: arg.d = va_arg(ap, double *); break; case PACK_TYPE_PADDING: break; - default: return PACK_FMTINVAL; + default: SET_AND_GOTO(ret, PACK_FMTINVAL, stop); } t = fmt[i]; s = getsize(t); tr_debug("s: %" PRIuSIZE, s); - if (s == (size_t)-1) return PACK_FMTINVAL; + if (s == (size_t)-1) SET_AND_GOTO(ret, PACK_FMTINVAL, stop); - if (size - offset < s * count) return PACK_TOOSMALL; + if (size - offset < s * count) + SET_AND_GOTO(ret, PACK_TOOSMALL, stop); if (t == PACK_TYPE_PADDING) goto skip; @@ -149,7 +151,8 @@ skip: offset += s * count; } +stop: va_end(ap); - return PACK_OK; + return ret; } -- cgit v1.2.3-54-g00ecf