diff options
Diffstat (limited to 'src/pack.c')
-rw-r--r-- | src/pack.c | 140 |
1 files changed, 84 insertions, 56 deletions
@@ -20,6 +20,8 @@ #include <stdio.h> #include <string.h> #include <ctype.h> +#include <inttypes.h> +#include <limits.h> #include "pack.h" /* Data format specification is a simplified form of Perl pack() template. @@ -99,6 +101,80 @@ printsnum(FILE *fp, intmax_t num) printunum(fp, num); } +static int +getunum(char *s, uintmax_t maxval, uintmax_t *retval) +{ + uintmax_t x = 0; + + for (; *s && isspace(*s); s++); + for (; *s; s++) { + if (!isdigit(*s)) + return -1; + x = x*10 + *s - '0'; + } + if (x > maxval) + return -1; + *retval = x; + return 0; +} + +static int +getsnum(char *s, intmax_t minval, intmax_t maxval, intmax_t *retval) +{ + uintmax_t x = 0; + int neg = 0; + + for (; *s && isspace(*s); s++); + if (*s == '-') { + neg = 1; + ++s; + } + for (; *s; s++) { + if (!isdigit(*s)) + return -1; + x = x*10 + *s - '0'; + } + + if (neg) { + if (x > -minval) + return -1; + *retval = -x; + } else if (x > maxval) + return -1; + else + *retval = x; + return 0; +} + +#define GETSARG(env, type, minv, maxv) do { \ + if ((env)->buf_base) { \ + char *arg = packenv_get(env); \ + if (arg) { \ + intmax_t x; \ + if (getsnum(arg, minv, maxv, &x) == 0) { \ + type v = (type) x; \ + memcpy(env->buf_base + env->buf_pos, \ + &v, sizeof(v)); \ + } \ + } \ + } \ + } while(0) + +#define GETUARG(env, type, maxv) do { \ + if ((env)->buf_base) { \ + char *arg = packenv_get(env); \ + if (arg) { \ + uintmax_t x; \ + if (getunum(arg, maxv, &x) == 0) { \ + type v = (type) x; \ + memcpy(env->buf_base + env->buf_pos, \ + &v, sizeof(v)); \ + } \ + } \ + } \ + } while(0) + + static void Z_packer(struct packenv *env, struct packspec *spec, int rep) { @@ -143,13 +219,7 @@ c_unpacker(struct packenv *env, struct packspec *spec, int rep) static void s_packer(struct packenv *env, struct packspec *spec, int rep) { - if (env->buf_base) { - char *arg = packenv_get(env); - if (arg) { - int16_t v = atoi(arg); - memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); - } - } + GETSARG(env, int16_t, INT16_MIN, INT16_MAX); env->buf_pos += spec->size; } @@ -163,13 +233,7 @@ s_unpacker(struct packenv *env, struct packspec *spec, int rep) static void S_packer(struct packenv *env, struct packspec *spec, int rep) { - if (env->buf_base) { - char *arg = packenv_get(env); - if (arg) { - uint16_t v = atoi(arg); - memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); - } - } + GETUARG(env, uint16_t, UINT16_MAX); env->buf_pos += spec->size; } @@ -183,13 +247,7 @@ S_unpacker(struct packenv *env, struct packspec *spec, int rep) static void l_packer(struct packenv *env, struct packspec *spec, int rep) { - if (env->buf_base) { - char *arg = packenv_get(env); - if (arg) { - int32_t v = atoi(arg); - memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); - } - } + GETSARG(env, int32_t, INT32_MIN, INT32_MAX); env->buf_pos += spec->size; } @@ -203,13 +261,7 @@ l_unpacker(struct packenv *env, struct packspec *spec, int rep) static void L_packer(struct packenv *env, struct packspec *spec, int rep) { - if (env->buf_base) { - char *arg = packenv_get(env); - if (arg) { - uint32_t v = atoi(arg); - memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); - } - } + GETUARG(env, uint32_t, UINT32_MAX); env->buf_pos += spec->size; } @@ -223,13 +275,7 @@ L_unpacker(struct packenv *env, struct packspec *spec, int rep) static void q_packer(struct packenv *env, struct packspec *spec, int rep) { - if (env->buf_base) { - char *arg = packenv_get(env); - if (arg) { - int64_t v = atoi(arg); - memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); - } - } + GETSARG(env, int64_t, INT64_MIN, INT64_MAX); env->buf_pos += spec->size; } @@ -243,13 +289,7 @@ q_unpacker(struct packenv *env, struct packspec *spec, int rep) static void Q_packer(struct packenv *env, struct packspec *spec, int rep) { - if (env->buf_base) { - char *arg = packenv_get(env); - if (arg) { - uint64_t v = atoi(arg); - memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); - } - } + GETUARG(env, uint64_t, UINT64_MAX); env->buf_pos += spec->size; } @@ -263,13 +303,7 @@ Q_unpacker(struct packenv *env, struct packspec *spec, int rep) static void i_packer(struct packenv *env, struct packspec *spec, int rep) { - if (env->buf_base) { - char *arg = packenv_get(env); - if (arg) { - int v = atoi(arg); - memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); - } - } + GETSARG(env, int, INT_MIN, INT_MAX); env->buf_pos += spec->size; } @@ -283,13 +317,7 @@ i_unpacker(struct packenv *env, struct packspec *spec, int rep) static void I_packer(struct packenv *env, struct packspec *spec, int rep) { - if (env->buf_base) { - char *arg = packenv_get(env); - if (arg) { - unsigned int v = atoi(arg); - memcpy(env->buf_base + env->buf_pos, &v, sizeof(v)); - } - } + GETUARG(env, unsigned, UINT_MAX); env->buf_pos += spec->size; } |