Use strtonum() instead of atoi(), strtol() or strtoul() where possible.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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
2
configure
vendored
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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));
|
||||
|
@@ -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;
|
||||
|
@@ -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=")) {
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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++) {
|
||||
|
@@ -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;
|
||||
|
53
src/sudo.c
53
src/sudo.c
@@ -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;
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user