aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common.h3
-rw-r--r--pack.c10
-rw-r--r--unpack.c13
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;
}