aboutsummaryrefslogtreecommitdiffstats
path: root/common/argparse.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-10-29 16:07:51 +0000
committerWerner Koch <[email protected]>2014-10-29 16:07:51 +0000
commit0d73a242cb53522669cf712b5ece7d1ed05d003a (patch)
treeae9494b2b7b11cd349afc7a5400cbdcffdd32be7 /common/argparse.c
parentFix stdint.h problem for Apple. (diff)
downloadgnupg-0d73a242cb53522669cf712b5ece7d1ed05d003a.tar.gz
gnupg-0d73a242cb53522669cf712b5ece7d1ed05d003a.zip
common: Check option arguments for a valid range.
* common/argparse.h (ARGPARSE_INVALID_ARG): New. * common/argparse.c: Include limits h and errno.h. (initialize): Add error strings for new error constant. (set_opt_arg): Add range checking. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'common/argparse.c')
-rw-r--r--common/argparse.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/common/argparse.c b/common/argparse.c
index c713bf609..844c1707e 100644
--- a/common/argparse.c
+++ b/common/argparse.c
@@ -39,6 +39,8 @@
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
#include "libjnlib-config.h"
#include "mischelp.h"
@@ -262,6 +264,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
s = _("keyword too long");
else if ( arg->r_opt == ARGPARSE_MISSING_ARG )
s = _("missing argument");
+ else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
+ s = _("invalid argument");
else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
s = _("invalid command");
else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS )
@@ -278,6 +282,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
if ( arg->r_opt == ARGPARSE_MISSING_ARG )
jnlib_log_error (_("missing argument for option \"%.50s\"\n"), s);
+ else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
+ jnlib_log_error (_("invalid argument for option \"%.50s\"\n"), s);
else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
jnlib_log_error (_("option \"%.50s\" does not expect an "
"argument\n"), s );
@@ -588,7 +594,7 @@ optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
p[strlen(p)-1] = 0;
}
if (!set_opt_arg (arg, opts[idx].flags, p))
- jnlib_free(buffer);
+ jnlib_free(buffer);
}
}
break;
@@ -1032,23 +1038,54 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
}
-
+/* Returns: -1 on error, 0 for an integer type and 1 for a non integer
+ type argument. */
static int
-set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s)
+set_opt_arg (ARGPARSE_ARGS *arg, unsigned flags, char *s)
{
int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10;
+ long l;
switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) )
{
- case ARGPARSE_TYPE_INT:
- arg->r.ret_int = (int)strtol(s,NULL,base);
- return 0;
case ARGPARSE_TYPE_LONG:
- arg->r.ret_long= strtol(s,NULL,base);
+ case ARGPARSE_TYPE_INT:
+ errno = 0;
+ l = strtol (s, NULL, base);
+ if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE)
+ {
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ if (arg->r_type == ARGPARSE_TYPE_LONG)
+ arg->r.ret_long = l;
+ else if ( (l < 0 && l < INT_MIN) || l > INT_MAX )
+ {
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ else
+ arg->r.ret_int = (int)l;
return 0;
+
case ARGPARSE_TYPE_ULONG:
- arg->r.ret_ulong= strtoul(s,NULL,base);
+ while (isascii (*s) && isspace(*s))
+ s++;
+ if (*s == '-')
+ {
+ arg->r.ret_ulong = 0;
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ errno = 0;
+ arg->r.ret_ulong = strtoul (s, NULL, base);
+ if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE)
+ {
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
return 0;
+
case ARGPARSE_TYPE_STRING:
default:
arg->r.ret_str = s;