aboutsummaryrefslogtreecommitdiff
path: root/src/pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pack.c')
-rw-r--r--src/pack.c140
1 files changed, 84 insertions, 56 deletions
diff --git a/src/pack.c b/src/pack.c
index 5594bb1..12dc19d 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -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;
}

Return to:

Send suggestions and report system problems to the System administrator.