* printcmd.c (printf_command): Make format string checking
stricter. Add separate cases for long_arg, ptr_arg, and long_double_arg. * utils.c (xstrvprintf): Improve the error message issued for a bad format string. * Makefile.in (GDB_WARN_CFLAGS_NO_FORMAT, INTERNAL_CFLAGS_BASE): New variables. (gnu-v3-abi.o, monitor.o, procfs.o, linux-thread-db.o): Remove $(NO_WERROR_CFLAGS). (printcmd.o): Likewise. Use $(GDB_WARN_CFLAGS_NO_FORMAT) and enable -Werror.
This commit is contained in:
parent
37a105a123
commit
46e9880c62
@ -1,3 +1,17 @@
|
||||
2006-02-01 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* printcmd.c (printf_command): Make format string checking
|
||||
stricter. Add separate cases for long_arg, ptr_arg, and
|
||||
long_double_arg.
|
||||
* utils.c (xstrvprintf): Improve the error message issued
|
||||
for a bad format string.
|
||||
* Makefile.in (GDB_WARN_CFLAGS_NO_FORMAT, INTERNAL_CFLAGS_BASE):
|
||||
New variables.
|
||||
(gnu-v3-abi.o, monitor.o, procfs.o, linux-thread-db.o): Remove
|
||||
$(NO_WERROR_CFLAGS).
|
||||
(printcmd.o): Likewise. Use $(GDB_WARN_CFLAGS_NO_FORMAT) and
|
||||
enable -Werror.
|
||||
|
||||
2006-02-01 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* Makefile.in (remote.o): Update.
|
||||
|
@ -132,6 +132,8 @@ WERROR_CFLAGS = @WERROR_CFLAGS@
|
||||
GDB_WARN_CFLAGS = $(WARN_CFLAGS)
|
||||
GDB_WERROR_CFLAGS = $(WERROR_CFLAGS)
|
||||
|
||||
GDB_WARN_CFLAGS_NO_FORMAT = `echo " $(GDB_WARN_CFLAGS) " | sed "s/ -Wformat-nonliteral / /g"`
|
||||
|
||||
# Where is the INTL library? Typically in ../intl.
|
||||
INTL_DIR = ../intl
|
||||
INTL = @INTLLIBS@
|
||||
@ -344,12 +346,12 @@ CFLAGS = @CFLAGS@
|
||||
CXXFLAGS = -g -O
|
||||
|
||||
# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
|
||||
INTERNAL_WARN_CFLAGS = \
|
||||
INTERNAL_CFLAGS_BASE = \
|
||||
$(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
|
||||
$(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \
|
||||
$(BFD_CFLAGS) $(INCLUDE_CFLAGS) \
|
||||
$(INTL_CFLAGS) $(ENABLE_CFLAGS) \
|
||||
$(GDB_WARN_CFLAGS)
|
||||
$(INTL_CFLAGS) $(ENABLE_CFLAGS)
|
||||
INTERNAL_WARN_CFLAGS = $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS)
|
||||
INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS)
|
||||
|
||||
# LDFLAGS is specifically reserved for setting from the command line
|
||||
@ -1479,8 +1481,7 @@ main.o: main.c
|
||||
# return types - "enum gnu_v3_dtor_kinds" vs "enum ctor_kinds" -
|
||||
# conflict.
|
||||
gnu-v3-abi.o: $(srcdir)/gnu-v3-abi.c
|
||||
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(NO_WERROR_CFLAGS) \
|
||||
$(srcdir)/gnu-v3-abi.c
|
||||
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(srcdir)/gnu-v3-abi.c
|
||||
|
||||
# FIXME: cagney/2003-08-10: "monitor.c" gets -Wformat-nonliteral
|
||||
# errors. It turns out that that is the least of monitor.c's
|
||||
@ -1489,25 +1490,23 @@ gnu-v3-abi.o: $(srcdir)/gnu-v3-abi.c
|
||||
# definitly will not work. "monitor.c" needs to be rewritten so that
|
||||
# it doesn't use format strings and instead uses callbacks.
|
||||
monitor.o: $(srcdir)/monitor.c
|
||||
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(NO_WERROR_CFLAGS) $(srcdir)/monitor.c
|
||||
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(srcdir)/monitor.c
|
||||
|
||||
# FIXME: cagney/2003-08-10: Do not try to build "printcmd.c" with
|
||||
# -Wformat-nonliteral. It needs to be overhauled so that it doesn't
|
||||
# pass user input strings as the format parameter to host printf
|
||||
# function calls.
|
||||
# Do not try to build "printcmd.c" with -Wformat-nonliteral. It manually
|
||||
# checks format strings.
|
||||
printcmd.o: $(srcdir)/printcmd.c
|
||||
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(NO_WERROR_CFLAGS) $(srcdir)/printcmd.c
|
||||
$(CC) -c $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS_NO_FORMAT) \
|
||||
$(GDB_WERROR_CFLAGS) $(srcdir)/printcmd.c
|
||||
|
||||
# FIXME: Procfs.o gets -Wformat errors because things like pid_t don't
|
||||
# match output format strings.
|
||||
procfs.o: $(srcdir)/procfs.c
|
||||
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(NO_WERROR_CFLAGS) $(srcdir)/procfs.c
|
||||
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(srcdir)/procfs.c
|
||||
|
||||
# FIXME: Thread-db.o gets warnings because the definitions of the register
|
||||
# sets are different from kernel to kernel.
|
||||
linux-thread-db.o: $(srcdir)/linux-thread-db.c
|
||||
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(NO_WERROR_CFLAGS) \
|
||||
$(srcdir)/linux-thread-db.c
|
||||
$(CC) -c $(INTERNAL_WARN_CFLAGS) $(srcdir)/linux-thread-db.c
|
||||
|
||||
v850ice.o: $(srcdir)/v850ice.c
|
||||
$(CC) -c $(INTERNAL_CFLAGS) $(IDE_CFLAGS) $(ITCL_CFLAGS) \
|
||||
|
173
gdb/printcmd.c
173
gdb/printcmd.c
@ -1836,13 +1836,13 @@ printf_command (char *arg, int from_tty)
|
||||
|
||||
enum argclass
|
||||
{
|
||||
no_arg, int_arg, string_arg, double_arg, long_long_arg
|
||||
int_arg, long_arg, long_long_arg, ptr_arg, string_arg,
|
||||
double_arg, long_double_arg
|
||||
};
|
||||
enum argclass *argclass;
|
||||
enum argclass this_argclass;
|
||||
char *last_arg;
|
||||
int nargs_wanted;
|
||||
int lcount;
|
||||
int i;
|
||||
|
||||
argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass);
|
||||
@ -1852,23 +1852,136 @@ printf_command (char *arg, int from_tty)
|
||||
while (*f)
|
||||
if (*f++ == '%')
|
||||
{
|
||||
lcount = 0;
|
||||
while (strchr ("0123456789.hlL-+ #", *f))
|
||||
int seen_hash = 0, seen_zero = 0, lcount = 0, seen_prec = 0;
|
||||
int seen_space = 0, seen_plus = 0;
|
||||
int seen_big_l = 0, seen_h = 0;
|
||||
int bad = 0;
|
||||
|
||||
/* Check the validity of the format specifier, and work
|
||||
out what argument it expects. We only accept C89
|
||||
format strings, with the exception of long long (which
|
||||
we autoconf for). */
|
||||
|
||||
/* Skip over "%%". */
|
||||
if (*f == '%')
|
||||
{
|
||||
if (*f == 'l' || *f == 'L')
|
||||
lcount++;
|
||||
f++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The first part of a format specifier is a set of flag
|
||||
characters. */
|
||||
while (strchr ("0-+ #", *f))
|
||||
{
|
||||
if (*f == '#')
|
||||
seen_hash = 1;
|
||||
else if (*f == '0')
|
||||
seen_zero = 1;
|
||||
else if (*f == ' ')
|
||||
seen_space = 1;
|
||||
else if (*f == '+')
|
||||
seen_plus = 1;
|
||||
f++;
|
||||
}
|
||||
|
||||
/* The next part of a format specifier is a width. */
|
||||
while (strchr ("0123456789", *f))
|
||||
f++;
|
||||
|
||||
/* The next part of a format specifier is a precision. */
|
||||
if (*f == '.')
|
||||
{
|
||||
seen_prec = 1;
|
||||
f++;
|
||||
while (strchr ("0123456789", *f))
|
||||
f++;
|
||||
}
|
||||
|
||||
/* The next part of a format specifier is a length modifier. */
|
||||
if (*f == 'h')
|
||||
{
|
||||
seen_h = 1;
|
||||
f++;
|
||||
}
|
||||
else if (*f == 'l')
|
||||
{
|
||||
f++;
|
||||
lcount++;
|
||||
if (*f == 'l')
|
||||
{
|
||||
f++;
|
||||
lcount++;
|
||||
}
|
||||
}
|
||||
else if (*f == 'L')
|
||||
{
|
||||
seen_big_l = 1;
|
||||
f++;
|
||||
}
|
||||
|
||||
switch (*f)
|
||||
{
|
||||
case 'u':
|
||||
if (seen_hash)
|
||||
bad = 1;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 'o':
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (seen_space || seen_plus)
|
||||
bad = 1;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
if (lcount == 0)
|
||||
this_argclass = int_arg;
|
||||
else if (lcount == 1)
|
||||
this_argclass = long_arg;
|
||||
else
|
||||
this_argclass = long_long_arg;
|
||||
|
||||
if (seen_big_l)
|
||||
bad = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
this_argclass = int_arg;
|
||||
if (lcount || seen_h || seen_big_l)
|
||||
bad = 1;
|
||||
if (seen_prec || seen_zero || seen_space || seen_plus)
|
||||
bad = 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
this_argclass = ptr_arg;
|
||||
if (lcount || seen_h || seen_big_l)
|
||||
bad = 1;
|
||||
if (seen_prec || seen_zero || seen_space || seen_plus)
|
||||
bad = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
this_argclass = string_arg;
|
||||
if (lcount || seen_h || seen_big_l)
|
||||
bad = 1;
|
||||
if (seen_zero || seen_space || seen_plus)
|
||||
bad = 1;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
this_argclass = double_arg;
|
||||
case 'E':
|
||||
case 'G':
|
||||
if (seen_big_l)
|
||||
this_argclass = long_double_arg;
|
||||
else
|
||||
this_argclass = double_arg;
|
||||
|
||||
if (lcount || seen_h)
|
||||
bad = 1;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
@ -1877,26 +1990,23 @@ printf_command (char *arg, int from_tty)
|
||||
case 'n':
|
||||
error (_("Format specifier `n' not supported in printf"));
|
||||
|
||||
case '%':
|
||||
this_argclass = no_arg;
|
||||
break;
|
||||
case '\0':
|
||||
error (_("Incomplete format specifier at end of format string"));
|
||||
|
||||
default:
|
||||
if (lcount > 1)
|
||||
this_argclass = long_long_arg;
|
||||
else
|
||||
this_argclass = int_arg;
|
||||
break;
|
||||
error (_("Unrecognized format specifier '%c' in printf"), *f);
|
||||
}
|
||||
|
||||
if (bad)
|
||||
error (_("Inappropriate modifiers to format specifier '%c' in printf"),
|
||||
*f);
|
||||
|
||||
f++;
|
||||
if (this_argclass != no_arg)
|
||||
{
|
||||
strncpy (current_substring, last_arg, f - last_arg);
|
||||
current_substring += f - last_arg;
|
||||
*current_substring++ = '\0';
|
||||
last_arg = f;
|
||||
argclass[nargs_wanted++] = this_argclass;
|
||||
}
|
||||
strncpy (current_substring, last_arg, f - last_arg);
|
||||
current_substring += f - last_arg;
|
||||
*current_substring++ = '\0';
|
||||
last_arg = f;
|
||||
argclass[nargs_wanted++] = this_argclass;
|
||||
}
|
||||
|
||||
/* Now, parse all arguments and evaluate them.
|
||||
@ -1970,6 +2080,16 @@ printf_command (char *arg, int from_tty)
|
||||
printf_filtered (current_substring, val);
|
||||
break;
|
||||
}
|
||||
case long_double_arg:
|
||||
#ifdef HAVE_LONG_DOUBLE
|
||||
{
|
||||
long double val = value_as_double (val_args[i]);
|
||||
printf_filtered (current_substring, val);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
error (_("long double not supported in printf"));
|
||||
#endif
|
||||
case long_long_arg:
|
||||
#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG)
|
||||
{
|
||||
@ -1982,7 +2102,12 @@ printf_command (char *arg, int from_tty)
|
||||
#endif
|
||||
case int_arg:
|
||||
{
|
||||
/* FIXME: there should be separate int_arg and long_arg. */
|
||||
int val = value_as_long (val_args[i]);
|
||||
printf_filtered (current_substring, val);
|
||||
break;
|
||||
}
|
||||
case long_arg:
|
||||
{
|
||||
long val = value_as_long (val_args[i]);
|
||||
printf_filtered (current_substring, val);
|
||||
break;
|
||||
|
18
gdb/utils.c
18
gdb/utils.c
@ -1,8 +1,8 @@
|
||||
/* General utility routines for GDB, the GNU debugger.
|
||||
|
||||
Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
|
||||
1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free
|
||||
Software Foundation, Inc.
|
||||
1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
@ -1069,14 +1069,12 @@ xstrvprintf (const char *format, va_list ap)
|
||||
{
|
||||
char *ret = NULL;
|
||||
int status = vasprintf (&ret, format, ap);
|
||||
/* NULL is returned when there was a memory allocation problem. */
|
||||
if (ret == NULL)
|
||||
nomem (0);
|
||||
/* A negative status (the printed length) with a non-NULL buffer
|
||||
should never happen, but just to be sure. */
|
||||
if (status < 0)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("vasprintf call failed (errno %d)"), errno);
|
||||
/* NULL is returned when there was a memory allocation problem, or
|
||||
any other error (for instance, a bad format string). A negative
|
||||
status (the printed length) with a non-NULL buffer should never
|
||||
happen, but just to be sure. */
|
||||
if (ret == NULL || status < 0)
|
||||
internal_error (__FILE__, __LINE__, _("vasprintf call failed"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user