Use strtonum() instead of atoi(), strtol() or strtoul() where possible.

This commit is contained in:
Todd C. Miller
2013-12-10 16:23:21 -07:00
parent f83eac40eb
commit 8f9ce7249a
22 changed files with 227 additions and 200 deletions

View File

@@ -182,16 +182,14 @@ set_var_group_source(const char *entry, const char *conf_file)
static void
set_var_max_groups(const char *entry, const char *conf_file)
{
long lval;
char *ep;
int max_groups;
lval = strtol(entry, &ep, 10);
if (*entry == '\0' || *ep != '\0' || lval <= 0 || lval > INT_MAX ||
(errno == ERANGE && lval == LONG_MAX)) {
warningx(U_("invalid max groups `%s' in %s, line %d"), entry,
conf_file, conf_lineno);
max_groups = strtonum(entry, 1, INT_MAX, NULL);
if (max_groups > 0) {
sudo_conf_data.max_groups = max_groups;
} else {
sudo_conf_data.max_groups = (int)lval;
warningx(U_("invalid max groups `%s' in %s, line %d"), entry,
conf_file, conf_lineno);
}
}

View File

@@ -77,10 +77,14 @@ get_ttysize(int *rowp, int *colp)
char *p;
/* Fall back on $LINES and $COLUMNS. */
if ((p = getenv("LINES")) == NULL || (*rowp = atoi(p)) <= 0)
if ((p = getenv("LINES")) == NULL ||
(*rowp = strtonum(p, 1, INT_MAX, NULL)) <= 0) {
*rowp = 24;
if ((p = getenv("COLUMNS")) == NULL || (*colp = atoi(p)) <= 0)
}
if ((p = getenv("COLUMNS")) == NULL ||
(*colp = strtonum(p, 1, INT_MAX, NULL)) <= 0) {
*colp = 80;
}
}
debug_return;

View File

@@ -222,7 +222,8 @@ strlcpy.lo: $(srcdir)/strlcpy.c $(incdir)/missing.h $(top_builddir)/config.h
strsignal.lo: $(srcdir)/strsignal.c $(incdir)/gettext.h $(incdir)/missing.h \
$(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/strsignal.c
strtonum.lo: $(srcdir)/strtonum.c $(incdir)/missing.h $(top_builddir)/config.h
strtonum.lo: $(srcdir)/strtonum.c $(incdir)/gettext.h $(incdir)/missing.h \
$(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/strtonum.c
utimes.lo: $(srcdir)/utimes.c $(incdir)/missing.h $(top_builddir)/config.h \
$(top_srcdir)/compat/utime.h

View File

@@ -86,7 +86,7 @@ closefrom_fallback(int lowfd)
for (fd = lowfd; fd < maxfd; fd++) {
#ifdef __APPLE__
/* Avoid potential crash with libdispatch when we close its fds. */
(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
(void) fcntl((int) fd, F_SETFD, FD_CLOEXEC);
#else
(void) close((int) fd);
#endif
@@ -123,17 +123,17 @@ void
closefrom(int lowfd)
{
struct dirent *dent;
const char *errstr;
DIR *dirp;
char *endp;
long fd;
int fd;
/* Use /proc/self/fd directory if it exists. */
if ((dirp = opendir("/proc/self/fd")) != NULL) {
while ((dent = readdir(dirp)) != NULL) {
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
(void) close((int) fd);
fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr);
if (errstr == NULL && fd != dirfd(dirp)) {
(void) close(fd);
}
}
(void) closedir(dirp);
} else

View File

@@ -187,29 +187,6 @@ freeaddrinfo(struct addrinfo *ai)
}
/*
* Convert a numeric service string to a number with error checking, returning
* true if the number was parsed correctly and false otherwise. Stores the
* converted number in the second argument. Equivalent to calling strtol, but
* with the base always fixed at 10, with checking of errno, ensuring that all
* of the string is consumed, and checking that the resulting number is
* positive.
*/
static int
convert_service(const char *string, long *result)
{
char *end;
if (*string == '\0')
return 0;
errno = 0;
*result = strtol(string, &end, 10);
if (errno != 0 || *end != '\0' || *result < 0)
return 0;
return 1;
}
/*
* Allocate a new addrinfo struct, setting some defaults given that this
* implementation is IPv4 only. Also allocates an attached sockaddr_in and
@@ -268,12 +245,14 @@ gai_service(const char *servname, int flags, int *type, unsigned short *port)
{
struct servent *servent;
const char *protocol;
long value;
const char *errstr;
unsigned short value;
if (convert_service(servname, &value)) {
if (value > (1L << 16) - 1)
return EAI_SERVICE;
value = strtonum(servname, 0, USHRT_MAX, &errstr);
if (errstr == NULL) {
*port = value;
} else if (errno == ERANGE) {
return EAI_SERVICE;
} else {
if (flags & AI_NUMERICSERV)
return EAI_NONAME;

View File

@@ -28,6 +28,9 @@
#include "missing.h"
#define DEFAULT_TEXT_DOMAIN "sudo"
#include "gettext.h"
enum strtonum_err {
STN_VALID,
STN_INVALID,
@@ -133,19 +136,19 @@ done:
result = 0;
errno = EINVAL;
if (errstrp != NULL)
*errstrp = "invalid";
*errstrp = N_("invalid");
break;
case STN_TOOSMALL:
result = 0;
errno = ERANGE;
if (errstrp != NULL)
*errstrp = "too small";
*errstrp = N_("too small");
break;
case STN_TOOBIG:
result = 0;
errno = ERANGE;
if (errstrp != NULL)
*errstrp = "too large";
*errstrp = N_("too large");
break;
}
return result;

2
configure vendored
View File

@@ -16297,7 +16297,7 @@ $as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h
fi
if test X"$ac_cv_type_long_long_int" != X"yes"; then
as_fn_error $? "\"C compiler does not appear have required long long support\"" "$LINENO" 5
as_fn_error $? "\"C compiler does not appear to support the long long int type\"" "$LINENO" 5
fi
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects

View File

@@ -2196,7 +2196,7 @@ AC_CHECK_TYPES([struct in6_addr], [], [], [#include <sys/types.h>
#include <netinet/in.h>])
AC_TYPE_LONG_LONG_INT
if test X"$ac_cv_type_long_long_int" != X"yes"; then
AC_MSG_ERROR(["C compiler does not appear have required long long support"])
AC_MSG_ERROR(["C compiler does not appear to support the long long int type"])
fi
AC_CHECK_SIZEOF([long int])
AC_CHECK_TYPE(id_t, unsigned int)

View File

@@ -124,10 +124,38 @@
# define OPEN_MAX 256
#endif
#ifndef USHRT_MAX
# define USHRT_MAX 0xffff
#endif
#ifndef INT_MAX
# define INT_MAX 0x7fffffff
#endif
#ifndef INT_MIN
# define INT_MIN (-0x7fffffff-1)
#endif
#ifndef UINT_MAX
# define UINT_MAX 0xffffffffU
#endif
#ifndef LLONG_MAX
# if defined(QUAD_MAX)
# define LLONG_MAX QUAD_MAX
# else
# define LLONG_MAX 0x7fffffffffffffffLL
# endif
#endif
#ifndef LLONG_MIN
# if defined(QUAD_MIN)
# define LLONG_MIN QUAD_MIN
# else
# define LLONG_MIN (-0x7fffffffffffffffLL-1)
# endif
#endif
#ifndef PATH_MAX
# ifdef _POSIX_PATH_MAX
# define PATH_MAX _POSIX_PATH_MAX

View File

@@ -74,21 +74,12 @@ get_boottime(struct timeval *tv)
if (fp != NULL) {
while ((len = getline(&line, &linesize, fp)) != -1) {
if (strncmp(line, "btime ", 6) == 0) {
#ifdef HAVE_STRTOLL
long long llval = strtoll(line + 6, &ep, 10);
if (line[6] != '\0' && *ep == '\0' && (time_t)llval == llval) {
long long llval = strtonum(line + 6, 1, LLONG_MAX, NULL);
if (llval > 0) {
tv->tv_sec = (time_t)llval;
tv->tv_usec = 0;
debug_return_bool(1);
}
#else
long lval = strtol(line + 6, &ep, 10);
if (line[6] != '\0' && *ep == '\0' && (time_t)lval == lval) {
tv->tv_sec = (time_t)llval;
tv->tv_usec = 0;
debug_return_bool(1);
}
#endif
}
}
fclose(fp);

View File

@@ -600,18 +600,20 @@ check_defaults(int what, bool quiet)
static bool
store_int(char *val, struct sudo_defs_types *def, int op)
{
char *endp;
long l;
const char *errstr;
int i;
debug_decl(store_int, SUDO_DEBUG_DEFAULTS)
if (op == false) {
def->sd_un.ival = 0;
} else {
l = strtol(val, &endp, 10);
if (*endp != '\0')
i = strtonum(val, INT_MIN, INT_MAX, &errstr);
if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s is %s", val, errstr);
debug_return_bool(false);
/* XXX - should check against INT_MAX */
def->sd_un.ival = (int)l;
}
def->sd_un.ival = i;
}
if (def->callback)
debug_return_bool(def->callback(val));
@@ -621,18 +623,21 @@ store_int(char *val, struct sudo_defs_types *def, int op)
static bool
store_uint(char *val, struct sudo_defs_types *def, int op)
{
char *endp;
long l;
const char *errstr;
unsigned int u;
debug_decl(store_uint, SUDO_DEBUG_DEFAULTS)
if (op == false) {
def->sd_un.ival = 0;
} else {
l = strtol(val, &endp, 10);
if (*endp != '\0' || l < 0)
u = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s is %s", val, errstr);
debug_return_bool(false);
/* XXX - should check against INT_MAX */
def->sd_un.ival = (unsigned int)l;
}
/* XXX - should have uival */
def->sd_un.ival = u;
}
if (def->callback)
debug_return_bool(def->callback(val));
@@ -814,7 +819,7 @@ store_mode(char *val, struct sudo_defs_types *def, int op)
def->sd_un.mode = (mode_t)0777;
} else {
l = strtol(val, &endp, 8);
if (*endp != '\0' || l < 0 || l > 0777)
if (endp == val || *endp != '\0' || l < 0 || l > 0777)
debug_return_bool(false);
def->sd_un.mode = (mode_t)l;
}

View File

@@ -136,17 +136,22 @@ io_mkdirs(char *path, mode_t mode, bool is_temp)
int
io_set_max_sessid(const char *maxval)
{
unsigned long ulval;
char *ep;
const char *errstr;
unsigned int value;
debug_decl(io_set_max_sessid, SUDO_DEBUG_UTIL)
errno = 0;
ulval = strtoul(maxval, &ep, 0);
if (*maxval != '\0' && *ep == '\0' &&
(errno != ERANGE || ulval != ULONG_MAX)) {
sessid_max = MIN((unsigned int)ulval, SESSID_MAX);
return true;
value = strtonum(maxval, 0, SESSID_MAX, &errstr);
if (errstr != NULL) {
if (errno != ERANGE) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"bad maxseq: %s is %s", maxval, errstr);
debug_return_bool(false);
}
/* Out of range, clamp to SESSID_MAX as documented. */
value = SESSID_MAX;
}
return false;
sessid_max = value;
debug_return_bool(true);
}
/*
@@ -202,7 +207,7 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
nread = read(fd2, buf, sizeof(buf));
if (nread > 0) {
id = strtoul(buf, &ep, 36);
if (buf == ep || id >= sessid_max)
if (ep == buf || *ep != '\0' || id >= sessid_max)
id = 0;
}
close(fd2);
@@ -217,7 +222,7 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
if (nread == -1)
log_fatal(USE_ERRNO, N_("unable to read %s"), pathbuf);
id = strtoul(buf, &ep, 36);
if (buf == ep || id >= sessid_max)
if (ep == buf || *ep != '\0' || id >= sessid_max)
id = 0;
}
}
@@ -237,7 +242,7 @@ io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
memcpy(sessid, buf, 6);
sessid[6] = '\0';
/* Rewind and overwrite old seq file. */
/* Rewind and overwrite old seq file, including the NUL byte. */
if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7)
log_fatal(USE_ERRNO, N_("unable to write to %s"), pathbuf);
close(fd);
@@ -332,7 +337,9 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
switch (**cur) {
case 'c':
if (strncmp(*cur, "cols=", sizeof("cols=") - 1) == 0) {
details->cols = atoi(*cur + sizeof("cols=") - 1);
int n = strtonum(*cur + sizeof("cols=") - 1, 1, INT_MAX, NULL);
if (n > 0)
details->cols = n;
continue;
}
if (strncmp(*cur, "cwd=", sizeof("cwd=") - 1) == 0) {
@@ -342,7 +349,9 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
break;
case 'l':
if (strncmp(*cur, "lines=", sizeof("lines=") - 1) == 0) {
details->lines = atoi(*cur + sizeof("lines=") - 1);
int n = strtonum(*cur + sizeof("lines=") - 1, 1, INT_MAX, NULL);
if (n > 0)
details->lines = n;
continue;
}
break;

View File

@@ -1398,6 +1398,7 @@ sudo_ldap_parse_keyword(const char *keyword, const char *value,
struct ldap_config_table *table)
{
struct ldap_config_table *cur;
const char *errstr;
debug_decl(sudo_ldap_parse_keyword, SUDO_DEBUG_LDAP)
/* Look up keyword in config tables */
@@ -1418,7 +1419,11 @@ sudo_ldap_parse_keyword(const char *keyword, const char *value,
*(int *)(cur->valp) = atobool(value) == true;
break;
case CONF_INT:
*(int *)(cur->valp) = atoi(value);
*(int *)(cur->valp) = strtonum(value, INT_MIN, INT_MAX, &errstr);
if (errstr != NULL) {
warningx(U_("%s: %s: value %s out of range)"),
path_ldap_conf, keyword, value);
}
break;
case CONF_STR:
efree(*(char **)(cur->valp));

View File

@@ -109,6 +109,7 @@ addr_matches_if_netmask(const char *n, const char *m)
unsigned int j;
#endif
unsigned int family;
const char *errstr;
debug_decl(addr_matches_if, SUDO_DEBUG_MATCH)
#ifdef HAVE_STRUCT_IN6_ADDR
@@ -125,7 +126,12 @@ addr_matches_if_netmask(const char *n, const char *m)
if (strchr(m, '.')) {
mask.ip4.s_addr = inet_addr(m);
} else {
i = atoi(m);
i = strtonum(m, 0, 32, &errstr);
if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"IPv4 netmask %s: %s", m, errstr);
debug_return_bool(false);
}
if (i == 0)
mask.ip4.s_addr = 0;
else if (i == 32)
@@ -139,7 +145,12 @@ addr_matches_if_netmask(const char *n, const char *m)
#ifdef HAVE_STRUCT_IN6_ADDR
else {
if (inet_pton(AF_INET6, m, &mask.ip6) <= 0) {
j = atoi(m);
j = strtonum(m, 0, 128, &errstr);
if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"IPv6 netmask %s: %s", m, errstr);
debug_return_bool(false);
}
for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) {
if (j < i * 8)
mask.ip6.s6_addr[i] = 0;

View File

@@ -91,7 +91,6 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group)
const char *debug_flags = NULL;
const char *remhost = NULL;
int flags = 0;
long lval;
char *ep;
debug_decl(sudoers_policy_deserialize_info, SUDO_DEBUG_PLUGIN)
@@ -119,14 +118,16 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group)
continue;
}
if (MATCHES(*cur, "sudoers_mode=")) {
long lval;
errno = 0;
p = *cur + sizeof("sudoers_mode=") - 1;
lval = strtol(p, &ep, 8);
if (*p == '\0' || *ep != '\0')
fatalx(U_("%s: %s"), *cur, U_("invalid value"));
if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
|| (lval > 0777 || lval < 0))
fatalx(U_("%s: %s"), *cur, U_("value out of range"));
if (ep == p || *ep != '\0')
fatalx(U_("%s: %s"), *cur, U_("invalid"));
if (lval < 0)
fatalx(U_("%s: %s"), *cur, U_("too small"));
if (lval > 0777)
fatalx(U_("%s: %s"), *cur, U_("too large"));
sudoers_mode = (mode_t) lval;
continue;
}
@@ -147,13 +148,9 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group)
if (MATCHES(*cur, "closefrom=")) {
errno = 0;
p = *cur + sizeof("closefrom=") - 1;
lval = strtol(p, &ep, 10);
if (*p == '\0' || *ep != '\0')
fatalx(U_("%s: %s"), *cur, U_("invalid value"));
if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
|| (lval > INT_MAX || lval < 3))
fatalx(U_("%s: %s"), *cur, U_("value out of range"));
user_closefrom = (int) lval;
user_closefrom = strtonum(p, 4, INT_MAX, &errstr);
if (user_closefrom == 0)
fatalx(U_("%s: %s"), *cur, U_(errstr));
continue;
}
if (MATCHES(*cur, "debug_flags=")) {
@@ -265,13 +262,9 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group)
if (MATCHES(*cur, "max_groups=")) {
errno = 0;
p = *cur + sizeof("max_groups=") - 1;
lval = strtol(p, &ep, 10);
if (*p == '\0' || *ep != '\0')
fatalx(U_("%s: %s"), *cur, U_("invalid value"));
if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
|| (lval > INT_MAX || lval <= 0))
fatalx(U_("%s: %s"), *cur, U_("value out of range"));
sudo_user.max_groups = (int) lval;
sudo_user.max_groups = strtonum(p, 1, INT_MAX, &errstr);
if (sudo_user.max_groups == 0)
fatalx(U_("%s: %s"), *cur, U_(errstr));
continue;
}
if (MATCHES(*cur, "remote_host=")) {
@@ -322,25 +315,17 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group)
if (MATCHES(*cur, "lines=")) {
errno = 0;
p = *cur + sizeof("lines=") - 1;
lval = strtol(p, &ep, 10);
if (*p == '\0' || *ep != '\0')
fatalx(U_("%s: %s"), *cur, U_("invalid value"));
if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
|| (lval > INT_MAX || lval <= 0))
fatalx(U_("%s: %s"), *cur, U_("value out of range"));
sudo_user.lines = (int) lval;
sudo_user.lines = strtonum(p, 1, INT_MAX, &errstr);
if (sudo_user.lines == 0)
fatalx(U_("%s: %s"), *cur, U_(errstr));
continue;
}
if (MATCHES(*cur, "cols=")) {
errno = 0;
p = *cur + sizeof("cols=") - 1;
lval = strtol(p, &ep, 10);
if (*p == '\0' || *ep != '\0')
fatalx(U_("%s: %s"), *cur, U_("invalid value"));
if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
|| (lval > INT_MAX || lval <= 0))
fatalx(U_("%s: %s"), *cur, U_("value out of range"));
sudo_user.cols = (int) lval;
sudo_user.cols = strtonum(p, 1, INT_MAX, &errstr);
if (sudo_user.lines == 0)
fatalx(U_("%s: %s"), *cur, U_(errstr));
continue;
}
if (MATCHES(*cur, "sid=")) {

View File

@@ -59,6 +59,7 @@ main(int argc, char *argv[])
size_t len;
FILE *fp;
char *cp, *dash, *line, lines[2][2048];
int lineno = 0;
int which = 0;
initprogname(argc > 0 ? argv[0] : "check_wrap");
@@ -83,13 +84,20 @@ main(int argc, char *argv[])
/* If we read the 2nd line, parse list of line lengths and check. */
if (which) {
lineno++;
for (cp = strtok(lines[1], ","); cp != NULL; cp = strtok(NULL, ",")) {
size_t maxlen;
/* May be either a number or a range. */
len = maxlen = atoi(cp);
dash = strchr(cp, '-');
if (dash)
maxlen = atoi(dash + 1);
if (dash != NULL) {
*dash = '\0';
len = strtonum(cp, 1, INT_MAX, NULL);
maxlen = strtonum(dash + 1, 1, INT_MAX, NULL);
} else {
len = maxlen = strtonum(cp, 1, INT_MAX, NULL);
}
if (len == 0 || maxlen == 0)
fatalx("%s: invalid length on line %d\n", argv[1], lineno);
while (len <= maxlen) {
printf("# word wrap at %d characters\n", (int)len);
writeln_wrap(stdout, lines[0], strlen(lines[0]), len);

View File

@@ -54,6 +54,7 @@ static int
check_addr(char *input)
{
int expected, matched;
const char *errstr;
size_t len;
char *cp;
@@ -65,7 +66,9 @@ check_addr(char *input)
cp = input + len;
while (isspace((unsigned char)*cp))
cp++;
expected = atoi(cp);
expected = strtonum(cp, 0, 1, &errstr);
if (errstr != NULL)
fatalx("expecting 0 or 1, got %s", cp);
input[len] = '\0';
matched = addr_matches(input);

View File

@@ -438,6 +438,7 @@ replay_session(const double max_wait, const char *decimal)
bool need_nlcr = false;
char last_char = '\0';
buf[strcspn(buf, "\n")] = '\0';
if (!parse_timing(buf, decimal, &idx, &seconds, &nbytes))
fatalx(U_("invalid timing file line: %s"), buf);
@@ -802,13 +803,9 @@ parse_logfile(char *logfile)
{
FILE *fp;
char *buf = NULL, *cp, *ep;
const char *errstr;
size_t bufsize = 0, cwdsize = 0, cmdsize = 0;
struct log_info *li = NULL;
#ifdef HAVE_STRTOLL
long long llval;
#else
long lval;
#endif
debug_decl(parse_logfile, SUDO_DEBUG_UTIL)
fp = fopen(logfile, "r");
@@ -837,26 +834,21 @@ parse_logfile(char *logfile)
/*
* Crack the log line (rows and cols not present in old versions).
* timestamp:user:runas_user:runas_group:tty:rows:cols
* XXX - probably better to use strtok and switch on the state.
*/
buf[strcspn(buf, "\n")] = '\0';
cp = buf;
/* timestamp */
errno = 0;
#ifdef HAVE_STRTOLL
llval = strtoll(buf, &ep, 10);
if (buf[0] == '\0' || *ep != ':')
if ((ep = strchr(cp, ':')) == NULL)
goto bad;
if (errno == ERANGE && (llval == LLONG_MAX || llval == LLONG_MIN))
*ep = '\0';
li->tstamp = strtonum(cp, LLONG_MIN, LLONG_MAX, &errstr);
if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: timestamp %s is %s", logfile, cp, errstr);
goto bad;
li->tstamp = (time_t)llval;
#else
lval = strtol(buf, &ep, 10);
if (buf[0] == '\0' || *ep != ':')
goto bad;
if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
goto bad;
li->tstamp = (time_t)lval;
#endif /* HAVE_STRTOLL */
}
/* user */
cp = ep + 1;
@@ -880,14 +872,28 @@ parse_logfile(char *logfile)
/* tty, followed by optional rows + columns */
cp = ep + 1;
if ((ep = strchr(cp, ':')) == NULL) {
/* just the tty */
li->tty = estrdup(cp);
} else {
/* tty followed by rows + columns */
li->tty = estrndup(cp, (size_t)(ep - cp));
cp = ep + 1;
li->rows = atoi(cp);
/* need to NULL out separator to use strtonum() */
if ((ep = strchr(cp, ':')) != NULL) {
*ep = '\0';
}
li->rows = strtonum(cp, 1, INT_MAX, &errstr);
if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: tty rows %s is %s", logfile, cp, errstr);
}
if (ep != NULL) {
cp = ep + 1;
li->cols = atoi(cp);
li->cols = strtonum(cp, 1, INT_MAX, &errstr);
if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: tty cols %s is %s", logfile, cp, errstr);
}
}
}
fclose(fp);
@@ -1158,6 +1164,8 @@ parse_timing(const char *buf, const char *decimal, int *idx, double *seconds,
/* Parse index */
ul = strtoul(buf, &ep, 10);
if (ep == buf || !isspace((unsigned char) *ep))
goto bad;
if (ul >= IOFD_TIMING) {
if (ul != 6)
goto bad;
@@ -1176,11 +1184,10 @@ parse_timing(const char *buf, const char *decimal, int *idx, double *seconds,
*/
errno = 0;
l = strtol(cp, &ep, 10);
if ((errno == ERANGE && (l == LONG_MAX || l == LONG_MIN)) ||
l < 0 || l > INT_MAX ||
(*ep != '.' && strncmp(ep, decimal, strlen(decimal)) != 0)) {
if (ep == cp || (*ep != '.' && strncmp(ep, decimal, strlen(decimal)) != 0))
goto bad;
if (l < 0 || l > INT_MAX || (errno == ERANGE && l == LONG_MAX))
goto bad;
}
*seconds = (double)l;
cp = ep + (*ep == '.' ? 1 : strlen(decimal));
d = 10.0;
@@ -1195,7 +1202,7 @@ parse_timing(const char *buf, const char *decimal, int *idx, double *seconds,
errno = 0;
ul = strtoul(cp, &ep, 10);
if (errno == ERANGE && ul == ULONG_MAX)
if (ep == cp || *ep != '\0' || (errno == ERANGE && ul == ULONG_MAX))
goto bad;
*nbytes = (size_t)ul;

View File

@@ -73,6 +73,8 @@ static sysgroup_getgrgid_t sysgroup_getgrgid;
static sysgroup_gr_delref_t sysgroup_gr_delref;
static bool need_setent;
extern id_t atoid(const char *str, const char *sep, char **endp, const char **errstr);
static int
sysgroup_init(int version, sudo_printf_t sudo_printf, char *const argv[])
{
@@ -128,16 +130,15 @@ sysgroup_cleanup(void)
static int
sysgroup_query(const char *user, const char *group, const struct passwd *pwd)
{
char **member, *ep = '\0';
char **member;
struct group *grp;
grp = sysgroup_getgrnam(group);
if (grp == NULL && group[0] == '#' && group[1] != '\0') {
long lval = strtol(group + 1, &ep, 10);
if (*ep == '\0') {
if ((lval != LONG_MAX && lval != LONG_MIN) || errno != ERANGE)
grp = sysgroup_getgrgid((gid_t)lval);
}
const char *errstr;
gid_t gid = atoid(group + 1, NULL, NULL, &errstr);
if (errstr == NULL)
grp = sysgroup_getgrgid(gid);
}
if (grp != NULL) {
for (member = grp->gr_mem; *member != NULL; member++) {

View File

@@ -178,7 +178,7 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
char *cp, **env_add, **settings;
const char *runas_user = NULL;
const char *runas_group = NULL;
const char *debug_flags;
const char *debug_flags, *errstr;
int nenv = 0;
int env_size = 32;
debug_decl(parse_args, SUDO_DEBUG_ARGS)
@@ -242,8 +242,9 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
SET(flags, MODE_BACKGROUND);
break;
case 'C':
if (atoi(optarg) < 3) {
warningx(U_("the argument to -C must be a number greater than or equal to 3"));
strtonum(optarg, 4, INT_MAX, &errstr);
if (errstr != NULL) {
warningx(U_("the argument to -C was %s"), U_(errstr));
usage(1);
}
sudo_settings[ARG_CLOSEFROM].value = optarg;

View File

@@ -530,8 +530,7 @@ command_info_to_details(char * const info[], struct command_details *details)
{
int i;
id_t id;
long lval;
char *cp, *ep;
char *cp;
const char *errstr;
debug_decl(command_info_to_details, SUDO_DEBUG_PCOMM)
@@ -553,16 +552,10 @@ command_info_to_details(char * const info[], struct command_details *details)
SET_STRING("command=", command)
SET_STRING("cwd=", cwd)
if (strncmp("closefrom=", info[i], sizeof("closefrom=") - 1) == 0) {
errno = 0;
cp = info[i] + sizeof("closefrom=") - 1;
lval = strtol(cp, &ep, 10);
if (*cp == '\0' || *ep != '\0')
fatalx(U_("%s: %s"), info[i], U_("invalid value"));
if ((errno == ERANGE &&
(lval == LONG_MAX || lval == LONG_MIN)) ||
(lval > INT_MAX || lval < 0))
fatalx(U_("%s: %s"), info[i], U_("value out of range"));
details->closefrom = (int)lval;
details->closefrom = strtonum(cp, 0, INT_MAX, &errstr);
if (errstr != NULL)
fatalx(U_("%s: %s"), cp, U_(errstr));
break;
}
break;
@@ -578,16 +571,10 @@ command_info_to_details(char * const info[], struct command_details *details)
break;
case 'n':
if (strncmp("nice=", info[i], sizeof("nice=") - 1) == 0) {
errno = 0;
cp = info[i] + sizeof("nice=") - 1;
lval = strtol(cp, &ep, 10);
if (*cp == '\0' || *ep != '\0')
fatalx(U_("%s: %s"), info[i], U_("invalid value"));
if ((errno == ERANGE &&
(lval == LONG_MAX || lval == LONG_MIN)) ||
(lval > INT_MAX || lval < INT_MIN))
fatalx(U_("%s: %s"), info[i], U_("value out of range"));
details->priority = (int)lval;
details->priority = strtonum(cp, INT_MIN, INT_MAX, &errstr);
if (errstr != NULL)
fatalx(U_("%s: %s"), cp, U_(errstr));
SET(details->flags, CD_SET_PRIORITY);
break;
}
@@ -686,31 +673,27 @@ command_info_to_details(char * const info[], struct command_details *details)
break;
case 't':
if (strncmp("timeout=", info[i], sizeof("timeout=") - 1) == 0) {
errno = 0;
cp = info[i] + sizeof("timeout=") - 1;
lval = strtol(cp, &ep, 10);
if (*cp == '\0' || *ep != '\0')
fatalx(U_("%s: %s"), info[i], U_("invalid value"));
if ((errno == ERANGE &&
(lval == LONG_MAX || lval == LONG_MIN)) ||
(lval > INT_MAX || lval < 0))
fatalx(U_("%s: %s"), info[i], U_("value out of range"));
details->timeout = (int)lval;
details->timeout = strtonum(cp, 0, INT_MAX, &errstr);
if (errstr != NULL)
fatalx(U_("%s: %s"), cp, U_(errstr));
SET(details->flags, CD_SET_TIMEOUT);
break;
}
break;
case 'u':
if (strncmp("umask=", info[i], sizeof("umask=") - 1) == 0) {
long lval;
char *ep;
errno = 0;
cp = info[i] + sizeof("umask=") - 1;
lval = strtol(cp, &ep, 8);
if (*cp == '\0' || *ep != '\0')
fatalx(U_("%s: %s"), info[i], U_("invalid value"));
if ((errno == ERANGE &&
(lval == LONG_MAX || lval == LONG_MIN)) ||
(lval > 0777 || lval < 0))
fatalx(U_("%s: %s"), info[i], U_("value out of range"));
if (ep == cp || *ep != '\0')
fatalx(U_("%s: %s"), info[i], U_("invalid"));
if (lval < 0)
fatalx(U_("%s: %s"), info[i], U_("too small"));
if (lval > 0777)
fatalx(U_("%s: %s"), info[i], U_("too large"));
details->umask = (mode_t)lval;
SET(details->flags, CD_SET_UMASK);
break;

View File

@@ -441,11 +441,16 @@ get_process_ttyname(void)
if (len != -1) {
/* Field 7 is the tty dev (0 if no tty) */
char *cp = line;
const char *errstr;
int field = 1;
while (*cp != '\0') {
if (*cp++ == ' ') {
if (++field == 7) {
dev_t tdev = (dev_t)atoi(cp);
dev_t tdev = strtonum(cp, INT_MIN, INT_MAX, &errstr);
if (errstr) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: tty device number %s", path, errstr);
}
if (tdev > 0)
tty = sudo_ttyname_dev(tdev);
break;