The OpenBSD strtonum() uses very short error strings that can't

be translated usefully.  Convert them to longer strings on error.
Also use the longer strings for atomode() and atoid().
This commit is contained in:
Todd C. Miller
2013-12-11 13:43:10 -07:00
parent d83bfb9fe6
commit cbf41b8b96
12 changed files with 94 additions and 27 deletions

View File

@@ -75,20 +75,20 @@ atoid(const char *p, const char *sep, char **endp, const char **errstr)
} }
if (!valid) { if (!valid) {
if (errstr != NULL) if (errstr != NULL)
*errstr = N_("invalid"); *errstr = N_("invalid value");
errno = EINVAL; errno = EINVAL;
goto done; goto done;
} }
if ((errno == ERANGE && lval == LONG_MAX) || lval > INT_MAX) { if ((errno == ERANGE && lval == LONG_MAX) || lval > INT_MAX) {
errno = ERANGE; errno = ERANGE;
if (errstr != NULL) if (errstr != NULL)
*errstr = N_("too large"); *errstr = N_("value too large");
goto done; goto done;
} }
if ((errno == ERANGE && lval == LONG_MIN) || lval < INT_MIN) { if ((errno == ERANGE && lval == LONG_MIN) || lval < INT_MIN) {
errno = ERANGE; errno = ERANGE;
if (errstr != NULL) if (errstr != NULL)
*errstr = N_("too small"); *errstr = N_("value too small");
goto done; goto done;
} }
rval = (id_t)lval; rval = (id_t)lval;
@@ -103,14 +103,14 @@ atoid(const char *p, const char *sep, char **endp, const char **errstr)
} }
if (!valid) { if (!valid) {
if (errstr != NULL) if (errstr != NULL)
*errstr = N_("invalid"); *errstr = N_("invalid value");
errno = EINVAL; errno = EINVAL;
goto done; goto done;
} }
if ((errno == ERANGE && ulval == ULONG_MAX) || ulval > UINT_MAX) { if ((errno == ERANGE && ulval == ULONG_MAX) || ulval > UINT_MAX) {
errno = ERANGE; errno = ERANGE;
if (errstr != NULL) if (errstr != NULL)
*errstr = N_("too large"); *errstr = N_("value too large");
goto done; goto done;
} }
rval = (id_t)ulval; rval = (id_t)ulval;

View File

@@ -51,13 +51,13 @@ atomode(const char *cp, const char **errstr)
lval = strtol(cp, &ep, 8); lval = strtol(cp, &ep, 8);
if (ep == cp || *ep != '\0') { if (ep == cp || *ep != '\0') {
if (errstr != NULL) if (errstr != NULL)
*errstr = N_("invalid"); *errstr = N_("invalid value");
errno = EINVAL; errno = EINVAL;
debug_return_int(0); debug_return_int(0);
} }
if (lval < 0 || lval > 0777) { if (lval < 0 || lval > 0777) {
if (errstr != NULL) if (errstr != NULL)
*errstr = lval < 0 ? N_("too small") : N_("too large"); *errstr = lval < 0 ? N_("value too small") : N_("value too large");
errno = ERANGE; errno = ERANGE;
debug_return_int(0); debug_return_int(0);
} }

View File

@@ -22,15 +22,59 @@
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <stdio.h> #include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H # ifdef HAVE_STDLIB_H
# include <stdlib.h> # include <stdlib.h>
# endif # endif
#endif /* STDC_HEADERS */
#ifdef HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include "missing.h" #include "missing.h"
#define DEFAULT_TEXT_DOMAIN "sudo" #define DEFAULT_TEXT_DOMAIN "sudo"
#include "gettext.h" #include "gettext.h"
#ifdef HAVE_STRTONUM
/*
* The OpenBSD strtonum error string too short to be translated sensibly.
* This wrapper just changes errstr as follows:
* invalid -> invalid value
* too large -> value too large
* too small -> value too small
*/
long long
rpl_strtonum(const char *str, long long minval, long long maxval,
const char **errstrp)
{
long long retval;
const char *errstr;
# undef strtonum
retval = strtonum(str, minval, maxval, &errstr);
if (errstr != NULL) {
if (errno == EINVAL) {
errstr = N_("invalid value");
} else if (errno == ERANGE) {
errstr = strcmp(errstr, "too large") == 0 ?
N_("value too large") : N_("value too small");
}
}
if (errstrp != NULL)
*errstrp = errstr;
return retval;
}
#else
enum strtonum_err { enum strtonum_err {
STN_VALID, STN_VALID,
STN_INVALID, STN_INVALID,
@@ -42,7 +86,7 @@ enum strtonum_err {
* Convert a string to a number in the range [minval, maxval] * Convert a string to a number in the range [minval, maxval]
*/ */
long long long long
strtonum(const char *str, long long minval, long long maxval, rpl_strtonum(const char *str, long long minval, long long maxval,
const char **errstrp) const char **errstrp)
{ {
const unsigned char *ustr = (const unsigned char *)str; const unsigned char *ustr = (const unsigned char *)str;
@@ -136,20 +180,21 @@ done:
result = 0; result = 0;
errno = EINVAL; errno = EINVAL;
if (errstrp != NULL) if (errstrp != NULL)
*errstrp = N_("invalid"); *errstrp = N_("invalid value");
break; break;
case STN_TOOSMALL: case STN_TOOSMALL:
result = 0; result = 0;
errno = ERANGE; errno = ERANGE;
if (errstrp != NULL) if (errstrp != NULL)
*errstrp = N_("too small"); *errstrp = N_("value too small");
break; break;
case STN_TOOBIG: case STN_TOOBIG:
result = 0; result = 0;
errno = ERANGE; errno = ERANGE;
if (errstrp != NULL) if (errstrp != NULL)
*errstrp = N_("too large"); *errstrp = N_("value too large");
break; break;
} }
return result; return result;
} }
#endif /* HAVE_STRTONUM */

18
configure vendored
View File

@@ -18014,6 +18014,24 @@ esac
fi fi
fi fi
# We wrap OpenBSD's strtonum() to get translatable error strings.
for ac_func in strtonum
do :
ac_fn_c_check_func "$LINENO" "strtonum" "ac_cv_func_strtonum"
if test "x$ac_cv_func_strtonum" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRTONUM 1
_ACEOF
fi
done
case " $LIBOBJS " in
*" strtonum.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS strtonum.$ac_objext"
;;
esac
if test X"$ac_cv_type_struct_timespec" != X"no"; then if test X"$ac_cv_type_struct_timespec" != X"no"; then
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default" ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then : if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then :

View File

@@ -2415,6 +2415,9 @@ if test X"$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf" = X"yesyes"
AC_LIBOBJ(snprintf) AC_LIBOBJ(snprintf)
fi fi
fi fi
# We wrap OpenBSD's strtonum() to get translatable error strings.
AC_CHECK_FUNCS(strtonum)
AC_LIBOBJ(strtonum)
if test X"$ac_cv_type_struct_timespec" != X"no"; then if test X"$ac_cv_type_struct_timespec" != X"no"; then
AC_CHECK_MEMBER([struct stat.st_mtim], [AC_DEFINE(HAVE_ST_MTIM)] AC_CHECK_MEMBER([struct stat.st_mtim], [AC_DEFINE(HAVE_ST_MTIM)]
[AC_CHECK_MEMBER([struct stat.st_mtim.st__tim], AC_DEFINE(HAVE_ST__TIM))], [AC_CHECK_MEMBER([struct stat.st_mtim.st__tim], AC_DEFINE(HAVE_ST__TIM))],

View File

@@ -475,7 +475,9 @@ char *strsignal(int);
int sig2str(int, char *); int sig2str(int, char *);
#endif #endif
#ifndef HAVE_STRTONUM #ifndef HAVE_STRTONUM
long long strtonum(const char *, long long, long long, const char **); long long rpl_strtonum(const char *, long long, long long, const char **);
# undef strtonum
# define strtonum rpl_strtonum
#endif #endif
void initprogname(const char *); void initprogname(const char *);

View File

@@ -610,7 +610,7 @@ store_int(char *val, struct sudo_defs_types *def, int op)
i = strtonum(val, INT_MIN, INT_MAX, &errstr); i = strtonum(val, INT_MIN, INT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s is %s", val, errstr); "%s: %s", val, errstr);
debug_return_bool(false); debug_return_bool(false);
} }
def->sd_un.ival = i; def->sd_un.ival = i;
@@ -633,7 +633,7 @@ store_uint(char *val, struct sudo_defs_types *def, int op)
u = strtonum(val, 0, UINT_MAX, &errstr); u = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s is %s", val, errstr); "%s: %s", val, errstr);
debug_return_bool(false); debug_return_bool(false);
} }
/* XXX - should have uival */ /* XXX - should have uival */

View File

@@ -144,7 +144,7 @@ io_set_max_sessid(const char *maxval)
if (errstr != NULL) { if (errstr != NULL) {
if (errno != ERANGE) { if (errno != ERANGE) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"bad maxseq: %s is %s", maxval, errstr); "bad maxseq: %s: %s", maxval, errstr);
debug_return_bool(false); debug_return_bool(false);
} }
/* Out of range, clamp to SESSID_MAX as documented. */ /* Out of range, clamp to SESSID_MAX as documented. */

View File

@@ -1421,8 +1421,8 @@ sudo_ldap_parse_keyword(const char *keyword, const char *value,
case CONF_INT: case CONF_INT:
*(int *)(cur->valp) = strtonum(value, INT_MIN, INT_MAX, &errstr); *(int *)(cur->valp) = strtonum(value, INT_MIN, INT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
warningx(U_("%s: %s: value %s out of range)"), warningx(U_("%s: %s: %s: %s"),
path_ldap_conf, keyword, value); path_ldap_conf, keyword, value, U_(errstr));
} }
break; break;
case CONF_STR: case CONF_STR:

View File

@@ -846,7 +846,7 @@ parse_logfile(char *logfile)
li->tstamp = strtonum(cp, LLONG_MIN, LLONG_MAX, &errstr); li->tstamp = strtonum(cp, LLONG_MIN, LLONG_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: timestamp %s is %s", logfile, cp, errstr); "%s: timestamp %s: %s", logfile, cp, errstr);
goto bad; goto bad;
} }
@@ -885,14 +885,14 @@ parse_logfile(char *logfile)
li->rows = strtonum(cp, 1, INT_MAX, &errstr); li->rows = strtonum(cp, 1, INT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: tty rows %s is %s", logfile, cp, errstr); "%s: tty rows %s: %s", logfile, cp, errstr);
} }
if (ep != NULL) { if (ep != NULL) {
cp = ep + 1; cp = ep + 1;
li->cols = strtonum(cp, 1, INT_MAX, &errstr); li->cols = strtonum(cp, 1, INT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: tty cols %s is %s", logfile, cp, errstr); "%s: tty cols %s: %s", logfile, cp, errstr);
} }
} }
} }

View File

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

View File

@@ -449,7 +449,7 @@ get_process_ttyname(void)
dev_t tdev = strtonum(cp, INT_MIN, INT_MAX, &errstr); dev_t tdev = strtonum(cp, INT_MIN, INT_MAX, &errstr);
if (errstr) { if (errstr) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: tty device number %s", path, errstr); "%s: tty device %s: %s", path, cp, errstr);
} }
if (tdev > 0) if (tdev > 0)
tty = sudo_ttyname_dev(tdev); tty = sudo_ttyname_dev(tdev);