c-common.c (format_wanted_type): Add reading_from_flag.

* c-common.c (format_wanted_type): Add reading_from_flag.
	(print_char_table): Mark %s and %S formats with flag "R".
	(check_format_info_main): Set up reading_from_flag appropriately.
	If aflag, always set writing_in_flag rather than relying on the
	format used being a scanf format and so having it set.
	(check_format_types): Check for formats reading through null
	pointers.

testsuite:
	* gcc.dg/c90-printf-1.c: Add test for printf formats reading
	through a null pointer.

From-SVN: r38104
This commit is contained in:
Joseph Myers 2000-12-07 07:40:45 +00:00 committed by Joseph Myers
parent 8308e0b786
commit 014e7f1d30
4 changed files with 54 additions and 15 deletions

View File

@ -1,3 +1,13 @@
2000-12-07 Joseph S. Myers <jsm28@cam.ac.uk>
* c-common.c (format_wanted_type): Add reading_from_flag.
(print_char_table): Mark %s and %S formats with flag "R".
(check_format_info_main): Set up reading_from_flag appropriately.
If aflag, always set writing_in_flag rather than relying on the
format used being a scanf format and so having it set.
(check_format_types): Check for formats reading through null
pointers.
2000-12-07 Joseph S. Myers <jsm28@cam.ac.uk> 2000-12-07 Joseph S. Myers <jsm28@cam.ac.uk>
* invoke.texi (-Wformat): Document what format features are * invoke.texi (-Wformat): Document what format features are

View File

@ -1416,6 +1416,7 @@ typedef struct
years in some locales, "4" for "2" which becomes "3" with an "E" modifier, years in some locales, "4" for "2" which becomes "3" with an "E" modifier,
"o" if use of strftime "O" is a GNU extension beyond C99, "o" if use of strftime "O" is a GNU extension beyond C99,
"W" if the argument is a pointer which is dereferenced and written into, "W" if the argument is a pointer which is dereferenced and written into,
"R" if the argument is a pointer which is dereferenced and read from,
"i" for printf integer formats where the '0' flag is ignored with "i" for printf integer formats where the '0' flag is ignored with
precision, and "[" for the starting character of a scanf scanset. */ precision, and "[" for the starting character of a scanf scanset. */
const char *flags2; const char *flags2;
@ -1521,6 +1522,9 @@ typedef struct format_wanted_type
/* Whether the argument, dereferenced once, is written into and so the /* Whether the argument, dereferenced once, is written into and so the
argument must not be a pointer to a const-qualified type. */ argument must not be a pointer to a const-qualified type. */
int writing_in_flag; int writing_in_flag;
/* Whether the argument, dereferenced once, is read from and so
must not be a NULL pointer. */
int reading_from_flag;
/* If warnings should be of the form "field precision is not type int", /* If warnings should be of the form "field precision is not type int",
the name to use (in this case "field precision"), otherwise NULL, the name to use (in this case "field precision"), otherwise NULL,
for "%s format, %s arg" type messages. If (in an extension), this for "%s format, %s arg" type messages. If (in an extension), this
@ -1694,23 +1698,23 @@ static const format_flag_pair strftime_flag_pairs[] =
static const format_char_info print_char_table[] = static const format_char_info print_char_table[] =
{ {
/* C89 conversion specifiers. */ /* C89 conversion specifiers. */
{ "di", 0, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T99_LL, TEX_LL, T99_SST, T99_PD, T99_IM }, "-wp0 +'I", "i" }, { "di", 0, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T99_LL, TEX_LL, T99_SST, T99_PD, T99_IM }, "-wp0 +'I", "i" },
{ "oxX", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T99_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0#", "i" }, { "oxX", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T99_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0#", "i" },
{ "u", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T99_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0'I", "i" }, { "u", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T99_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0'I", "i" },
{ "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#'", "" }, { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#'", "" },
{ "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "" }, { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "" },
{ "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "" }, { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "" },
{ "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "c" }, { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR" },
{ "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c" }, { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c" },
{ "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T99_LL, BADLEN, T99_SST, T99_PD, T99_IM }, "", "W" }, { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T99_LL, BADLEN, T99_SST, T99_PD, T99_IM }, "", "W" },
/* C99 conversion specifiers. */ /* C99 conversion specifiers. */
{ "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#'", "" }, { "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#'", "" },
{ "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "" }, { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "" },
/* X/Open conversion specifiers. */ /* X/Open conversion specifiers. */
{ "C", 0, STD_EXT, { TEX_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "" }, { "C", 0, STD_EXT, { TEX_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "" },
{ "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "" }, { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R" },
/* GNU conversion specifiers. */ /* GNU conversion specifiers. */
{ "m", 0, STD_EXT, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "" }, { "m", 0, STD_EXT, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "" },
{ NULL, 0, 0, NOLENGTHS, NULL, NULL } { NULL, 0, 0, NOLENGTHS, NULL, NULL }
}; };
@ -2718,6 +2722,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
width_wanted_type.pointer_count = 0; width_wanted_type.pointer_count = 0;
width_wanted_type.char_lenient_flag = 0; width_wanted_type.char_lenient_flag = 0;
width_wanted_type.writing_in_flag = 0; width_wanted_type.writing_in_flag = 0;
width_wanted_type.reading_from_flag = 0;
width_wanted_type.name = _("field width"); width_wanted_type.name = _("field width");
width_wanted_type.param = cur_param; width_wanted_type.param = cur_param;
width_wanted_type.arg_num = arg_num; width_wanted_type.arg_num = arg_num;
@ -2803,6 +2808,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
precision_wanted_type.pointer_count = 0; precision_wanted_type.pointer_count = 0;
precision_wanted_type.char_lenient_flag = 0; precision_wanted_type.char_lenient_flag = 0;
precision_wanted_type.writing_in_flag = 0; precision_wanted_type.writing_in_flag = 0;
precision_wanted_type.reading_from_flag = 0;
precision_wanted_type.name = _("field precision"); precision_wanted_type.name = _("field precision");
precision_wanted_type.param = cur_param; precision_wanted_type.param = cur_param;
precision_wanted_type.arg_num = arg_num; precision_wanted_type.arg_num = arg_num;
@ -3129,8 +3135,16 @@ check_format_info_main (status, res, info, format_chars, format_length,
if (strchr (fci->flags2, 'c') != 0) if (strchr (fci->flags2, 'c') != 0)
main_wanted_type.char_lenient_flag = 1; main_wanted_type.char_lenient_flag = 1;
main_wanted_type.writing_in_flag = 0; main_wanted_type.writing_in_flag = 0;
if (strchr (fci->flags2, 'W') != 0) main_wanted_type.reading_from_flag = 0;
if (aflag)
main_wanted_type.writing_in_flag = 1; main_wanted_type.writing_in_flag = 1;
else
{
if (strchr (fci->flags2, 'W') != 0)
main_wanted_type.writing_in_flag = 1;
if (strchr (fci->flags2, 'R') != 0)
main_wanted_type.reading_from_flag = 1;
}
main_wanted_type.name = NULL; main_wanted_type.name = NULL;
main_wanted_type.param = cur_param; main_wanted_type.param = cur_param;
main_wanted_type.arg_num = arg_num; main_wanted_type.arg_num = arg_num;
@ -3208,6 +3222,15 @@ check_format_types (status, types)
"writing through null pointer (arg %d)", "writing through null pointer (arg %d)",
arg_num); arg_num);
/* Check for reading through a NULL pointer. */
if (types->reading_from_flag
&& i == 0
&& cur_param != 0
&& integer_zerop (cur_param))
status_warning (status,
"reading through null pointer (arg %d)",
arg_num);
if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR) if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR)
cur_param = TREE_OPERAND (cur_param, 0); cur_param = TREE_OPERAND (cur_param, 0);
else else

View File

@ -1,3 +1,8 @@
2000-12-07 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/c90-printf-1.c: Add test for printf formats reading
through a null pointer.
2000-12-06 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> 2000-12-06 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* g++.old-deja/g++.oliva/partspec1.C: Remove XFAIL. * g++.old-deja/g++.oliva/partspec1.C: Remove XFAIL.

View File

@ -245,4 +245,5 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
printf ("%n", cn); /* { dg-warning "constant" "%n with const" } */ printf ("%n", cn); /* { dg-warning "constant" "%n with const" } */
printf ((const char *)L"foo"); /* { dg-warning "wide" "wide string" } */ printf ((const char *)L"foo"); /* { dg-warning "wide" "wide string" } */
printf ("%n", (int *)0); /* { dg-warning "null" "%n with NULL" } */ printf ("%n", (int *)0); /* { dg-warning "null" "%n with NULL" } */
printf ("%s", (char *)0); /* { dg-warning "null" "%s with NULL" } */
} }