summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2003-03-11 20:25:18 +0000
committerJim Meyering <jim@meyering.net>2003-03-11 20:25:18 +0000
commit257b85ca8e1e86627d041ef21bfabe61e399ae04 (patch)
tree7ff6baccb50884239b5bb3f39f0afcf51b0a46bc
parent09ad938a09da2800326a6af7a963cd72990c9b05 (diff)
downloadcoreutils-257b85ca8e1e86627d041ef21bfabe61e399ae04.tar.xz
Don't segfault for a negative field width or precision in format string.
(UNSPECIFIED): Define. (print_direc): Use the special value, UNSPECIFIED, to indicate that field_width or precision has not been specified. (print_formatted): Fail if field_width or precision is the special value, UNSPECIFIED.
-rw-r--r--src/printf.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/src/printf.c b/src/printf.c
index 8c5c1aa65..32b8c3e8e 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -72,6 +72,9 @@ unsigned long int strtoul ();
(c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : (c) - '0')
#define octtobin(c) ((c) - '0')
+/* A value for field_width or precision that indicates it was not specified. */
+#define UNSPECIFIED INT_MIN
+
/* The value to return to the calling program. */
static int exit_status;
@@ -310,7 +313,7 @@ print_esc_string (const char *str)
/* Output a % directive. START is the start of the directive,
LENGTH is its length, and ARGUMENT is its argument.
- If FIELD_WIDTH or PRECISION is non-negative, they are args for
+ If FIELD_WIDTH or PRECISION is UNSPECIFIED, they are args for
'*' values in those fields. */
static void
@@ -327,16 +330,16 @@ print_direc (const char *start, size_t length, int field_width,
{
case 'd':
case 'i':
- if (field_width < 0)
+ if (field_width == UNSPECIFIED)
{
- if (precision < 0)
+ if (precision == UNSPECIFIED)
printf (p, xstrtol (argument));
else
printf (p, precision, xstrtol (argument));
}
else
{
- if (precision < 0)
+ if (precision == UNSPECIFIED)
printf (p, field_width, xstrtol (argument));
else
printf (p, field_width, precision, xstrtol (argument));
@@ -347,16 +350,16 @@ print_direc (const char *start, size_t length, int field_width,
case 'u':
case 'x':
case 'X':
- if (field_width < 0)
+ if (field_width == UNSPECIFIED)
{
- if (precision < 0)
+ if (precision == UNSPECIFIED)
printf (p, xstrtoul (argument));
else
printf (p, precision, xstrtoul (argument));
}
else
{
- if (precision < 0)
+ if (precision == UNSPECIFIED)
printf (p, field_width, xstrtoul (argument));
else
printf (p, field_width, precision, xstrtoul (argument));
@@ -368,16 +371,16 @@ print_direc (const char *start, size_t length, int field_width,
case 'E':
case 'g':
case 'G':
- if (field_width < 0)
+ if (field_width == UNSPECIFIED)
{
- if (precision < 0)
+ if (precision == UNSPECIFIED)
printf (p, xstrtod (argument));
else
printf (p, precision, xstrtod (argument));
}
else
{
- if (precision < 0)
+ if (precision == UNSPECIFIED)
printf (p, field_width, xstrtod (argument));
else
printf (p, field_width, precision, xstrtod (argument));
@@ -389,16 +392,16 @@ print_direc (const char *start, size_t length, int field_width,
break;
case 's':
- if (field_width < 0)
+ if (field_width == UNSPECIFIED)
{
- if (precision < 0)
+ if (precision == UNSPECIFIED)
printf (p, argument);
else
printf (p, precision, argument);
}
else
{
- if (precision < 0)
+ if (precision == UNSPECIFIED)
printf (p, field_width, argument);
else
printf (p, field_width, precision, argument);
@@ -420,8 +423,8 @@ print_formatted (const char *format, int argc, char **argv)
const char *f; /* Pointer into `format'. */
const char *direc_start; /* Start of % directive. */
size_t direc_length; /* Length of % directive. */
- int field_width; /* Arg to first '*', or -1 if none. */
- int precision; /* Arg to second '*', or -1 if none. */
+ int field_width; /* Arg to first '*', or UNSPECIFIED if none. */
+ int precision; /* Arg to second '*', or UNSPECIFIED if none. */
for (f = format; *f; ++f)
{
@@ -430,7 +433,7 @@ print_formatted (const char *format, int argc, char **argv)
case '%':
direc_start = f++;
direc_length = 1;
- field_width = precision = -1;
+ field_width = precision = UNSPECIFIED;
if (*f == '%')
{
putchar ('%');
@@ -458,6 +461,9 @@ print_formatted (const char *format, int argc, char **argv)
if (argc > 0)
{
field_width = xstrtoul (*argv);
+ if (field_width == UNSPECIFIED)
+ error (EXIT_FAILURE, 0, _("invalid field width: %s"),
+ *argv);
++argv;
--argc;
}
@@ -481,6 +487,9 @@ print_formatted (const char *format, int argc, char **argv)
if (argc > 0)
{
precision = xstrtoul (*argv);
+ if (precision == UNSPECIFIED)
+ error (EXIT_FAILURE, 0, _("invalid precision: %s"),
+ *argv);
++argv;
--argc;
}