diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c --- a/sys/kern/kern_environment.c +++ b/sys/kern/kern_environment.c @@ -747,6 +747,33 @@ return (cp != NULL); } +static int +quad_multiplier(char suffix, int64_t *mult) +{ + int64_t multiplier = 1; + + switch (suffix) { + case 't': case 'T': + multiplier *= 1024; + /* FALLTHROUGH */ + case 'g': case 'G': + multiplier *= 1024; + /* FALLTHROUGH */ + case 'm': case 'M': + multiplier *= 1024; + /* FALLTHROUGH */ + case 'k': case 'K': + multiplier *= 1024; + case '\0': + break; + default: + return (-1); + } + *mult = multiplier; + + return (0); +} + /* * Return an array of integers at the given type size and signedness. */ @@ -754,8 +781,8 @@ getenv_array(const char *name, void *pdata, int size, int *psize, int type_size, bool allow_signed) { - uint8_t shift; int64_t value; + int64_t mult; int64_t old; const char *buf; char *end; @@ -786,37 +813,9 @@ goto error; /* check for valid suffix */ - switch (*end) { - case 't': - case 'T': - shift = 40; - end++; - break; - case 'g': - case 'G': - shift = 30; - end++; - break; - case 'm': - case 'M': - shift = 20; - end++; - break; - case 'k': - case 'K': - shift = 10; - end++; - break; - case ' ': - case '\t': - case ',': - case 0: - shift = 0; - break; - default: - /* garbage after numeric value */ + rc = quad_multiplier(*end, &mult); + if (rc != 0) goto error; - } /* skip till next value, if any */ while (*end == '\t' || *end == ',' || *end == ' ') @@ -827,10 +826,10 @@ /* apply shift */ old = value; - value <<= shift; + value *= mult; /* overflow check */ - if ((value >> shift) != old) + if ((value / mult) != old) goto error; /* check for buffer overflow */ @@ -910,7 +909,7 @@ quad_t tmp; int rval; - rval = getenv_quad(name, &tmp); + rval = getenv_uquad(name, &tmp); if (rval) *data = (unsigned int) tmp; return (rval); @@ -940,7 +939,7 @@ quad_t tmp; uint64_t rval; - rval = getenv_quad(name, &tmp); + rval = getenv_uquad(name, &tmp); if (rval) *data = (uint64_t) tmp; return (rval); @@ -970,12 +969,45 @@ quad_t tmp; int rval; - rval = getenv_quad(name, &tmp); + rval = getenv_uquad(name, &tmp); if (rval) *data = (unsigned long) tmp; return (rval); } +/* + * Return a u_quad_t value from an environment variable. + */ +int +getenv_uquad(const char *name, u_quad_t *data) +{ + const char *value; + char suffix, *vtp; + u_quad_t iv; + int64_t mult; + int err; + + value = kenv_acquire(name); + if (value == NULL) { + goto error; + } + iv = strtouq(value, &vtp, 0); + if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) { + goto error; + } + suffix = vtp[0]; + kenv_release(value); + err = quad_multiplier(suffix, &mult); + if (err != 0) + return (0); + iv *= mult; + *data = iv; + return (1); +error: + kenv_release(value); + return (0); +} + /* * Return a quad_t value from an environment variable. */ @@ -985,6 +1017,8 @@ const char *value; char suffix, *vtp; quad_t iv; + int64_t mult; + int err; value = kenv_acquire(name); if (value == NULL) { @@ -996,23 +1030,10 @@ } suffix = vtp[0]; kenv_release(value); - switch (suffix) { - case 't': case 'T': - iv *= 1024; - /* FALLTHROUGH */ - case 'g': case 'G': - iv *= 1024; - /* FALLTHROUGH */ - case 'm': case 'M': - iv *= 1024; - /* FALLTHROUGH */ - case 'k': case 'K': - iv *= 1024; - case '\0': - break; - default: + err = quad_multiplier(suffix, &mult); + if (err != 0) return (0); - } + iv *= mult; *data = iv; return (1); error: diff --git a/sys/sys/systm.h b/sys/sys/systm.h --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -417,6 +417,7 @@ int getenv_int64(const char *name, int64_t *data); int getenv_uint64(const char *name, uint64_t *data); int getenv_quad(const char *name, quad_t *data); +int getenv_uquad(const char *name, u_quad_t *data); int getenv_bool(const char *name, bool *data); bool getenv_is_true(const char *name); bool getenv_is_false(const char *name);