0ffeb6ec02
don't undefine C99 math macros, if !_GLIBCPP_USE_C99, so that we can use these functions in C++. espie@ agrees
201 lines
9.5 KiB
Plaintext
201 lines
9.5 KiB
Plaintext
$OpenBSD: patch-gcc_c-format_c,v 1.2 2008/07/25 20:50:26 martynas Exp $
|
|
--- gcc/c-format.c.orig Sun Dec 1 19:51:44 2002
|
|
+++ gcc/c-format.c Fri Jul 25 12:34:57 2008
|
|
@@ -54,7 +54,7 @@ set_Wformat (setting)
|
|
|
|
/* This must be in the same order as format_types, with format_type_error
|
|
last. */
|
|
-enum format_type { printf_format_type, scanf_format_type,
|
|
+enum format_type { printf_format_type, kprintf_format_type, syslog_format_type, scanf_format_type,
|
|
strftime_format_type, strfmon_format_type,
|
|
format_type_error };
|
|
|
|
@@ -540,6 +540,10 @@ typedef struct format_wanted_type
|
|
/* Whether the argument, dereferenced once, is written into and so the
|
|
argument must not be a pointer to a const-qualified type. */
|
|
int writing_in_flag;
|
|
+ /* If the argument is to be written into and is an array, should the
|
|
+ width specifier be equal to the size of the array, or one less
|
|
+ (to accommodate a NULL being placed at the end) */
|
|
+ int size_equals_width;
|
|
/* Whether the argument, dereferenced once, is read from and so
|
|
must not be a NULL pointer. */
|
|
int reading_from_flag;
|
|
@@ -552,6 +556,8 @@ typedef struct format_wanted_type
|
|
const char *name;
|
|
/* The actual parameter to check against the wanted type. */
|
|
tree param;
|
|
+ /* Field width of type */
|
|
+ int field_width;
|
|
/* The argument number of that parameter. */
|
|
int arg_num;
|
|
/* The next type to check for this format conversion, or NULL if none. */
|
|
@@ -572,7 +578,15 @@ static const format_length_info printf_length_specs[]
|
|
{ NULL, 0, 0, NULL, 0, 0 }
|
|
};
|
|
|
|
+static const format_length_info kprintf_length_specs[] =
|
|
+{
|
|
+ { "h", FMT_LEN_h, STD_C89, NULL, 0, 0 },
|
|
+ { "l", FMT_LEN_l, STD_C89, NULL, 0, 0 },
|
|
+ { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 },
|
|
+ { NULL, 0, 0, NULL, 0, 0 }
|
|
+};
|
|
|
|
+
|
|
/* This differs from printf_length_specs only in that "Z" is not accepted. */
|
|
static const format_length_info scanf_length_specs[] =
|
|
{
|
|
@@ -765,6 +779,46 @@ static const format_char_info print_char_table[] =
|
|
{ NULL, 0, 0, NOLENGTHS, NULL, NULL }
|
|
};
|
|
|
|
+static const format_char_info kprint_char_table[] =
|
|
+{
|
|
+ /* C89 conversion specifiers. */
|
|
+ { "di", 0, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM }, "-wp0 +'I", "i" },
|
|
+ { "oxX", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0#", "i" },
|
|
+ { "u", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0'I", "i" },
|
|
+ { "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", "cR" },
|
|
+ { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c" },
|
|
+/* Kernel bitmap formatting */
|
|
+ { "b", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
|
|
+/* Kernel recursive format */
|
|
+ { ":", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" },
|
|
+/* Kernel debugger auto-radix printing */
|
|
+ { "nrz", 0, STD_C89, { T89_I, T89_I, T89_I, T89_L, T9L_LL, TEX_LL, BADLEN, BADLEN, BADLEN }, "-wp0# +", "" },
|
|
+ { NULL, 0, 0, NOLENGTHS, NULL, NULL }
|
|
+};
|
|
+
|
|
+static const format_char_info syslog_char_table[] =
|
|
+{
|
|
+ /* C89 conversion specifiers. */
|
|
+ { "di", 0, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM }, "-wp0 +'I", "i" },
|
|
+ { "oxX", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0#", "i" },
|
|
+ { "u", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_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 +#'", "" },
|
|
+ { "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", "" },
|
|
+ { "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" },
|
|
+ { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM }, "", "W" },
|
|
+ /* C99 conversion specifiers. */
|
|
+ { "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 +#", "" },
|
|
+ /* X/Open conversion specifiers. */
|
|
+ { "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", "R" },
|
|
+ { "m", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "" },
|
|
+ { NULL, 0, 0, NOLENGTHS, NULL, NULL }
|
|
+};
|
|
+
|
|
static const format_char_info scan_char_table[] =
|
|
{
|
|
/* C89 conversion specifiers. */
|
|
@@ -828,6 +882,18 @@ static const format_kind_info format_types[] =
|
|
'w', 0, 'p', 0, 'L',
|
|
&integer_type_node, &integer_type_node
|
|
},
|
|
+ { "kprintf", kprintf_length_specs, kprint_char_table, " +#0-'I", NULL,
|
|
+ printf_flag_specs, printf_flag_pairs,
|
|
+ FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
|
|
+ 'w', 0, 'p', 0, 'L',
|
|
+ &integer_type_node, &integer_type_node
|
|
+ },
|
|
+ { "syslog", printf_length_specs, syslog_char_table, " +#0-'I", NULL,
|
|
+ printf_flag_specs, printf_flag_pairs,
|
|
+ FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
|
|
+ 'w', 0, 'p', 0, 'L',
|
|
+ &integer_type_node, &integer_type_node
|
|
+ },
|
|
{ "scanf", scanf_length_specs, scan_char_table, "*'I", NULL,
|
|
scanf_flag_specs, scanf_flag_pairs,
|
|
FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
|
|
@@ -1574,6 +1640,7 @@ check_format_info_main (status, res, info, format_char
|
|
const format_length_info *fli = NULL;
|
|
const format_char_info *fci = NULL;
|
|
char flag_chars[256];
|
|
+ int field_width = 0;
|
|
int aflag = 0;
|
|
if (*format_chars == 0)
|
|
{
|
|
@@ -1715,20 +1782,29 @@ check_format_info_main (status, res, info, format_char
|
|
/* Possibly read a numeric width. If the width is zero,
|
|
we complain if appropriate. */
|
|
int non_zero_width_char = FALSE;
|
|
- int found_width = FALSE;
|
|
+ unsigned int found_width = 0;
|
|
+ char format_num_str[32];
|
|
+
|
|
+ format_num_str[0] = '\0';
|
|
while (ISDIGIT (*format_chars))
|
|
{
|
|
- found_width = TRUE;
|
|
+ if (found_width < (sizeof(format_num_str)-2))
|
|
+ {
|
|
+ format_num_str[found_width++] = *format_chars;
|
|
+ format_num_str[found_width] = '\0';
|
|
+ }
|
|
if (*format_chars != '0')
|
|
non_zero_width_char = TRUE;
|
|
++format_chars;
|
|
}
|
|
- if (found_width && !non_zero_width_char &&
|
|
+
|
|
+ if (found_width > 0 && !non_zero_width_char &&
|
|
(fki->flags & (int) FMT_FLAG_ZERO_WIDTH_BAD))
|
|
status_warning (status, "zero width in %s format",
|
|
fki->name);
|
|
- if (found_width)
|
|
+ if (found_width > 0)
|
|
{
|
|
+ field_width = atoi(format_num_str);
|
|
i = strlen (flag_chars);
|
|
flag_chars[i++] = fki->width_char;
|
|
flag_chars[i] = 0;
|
|
@@ -2126,10 +2202,15 @@ check_format_info_main (status, res, info, format_char
|
|
main_wanted_type.wanted_type_name = wanted_type_name;
|
|
main_wanted_type.pointer_count = fci->pointer_count + aflag;
|
|
main_wanted_type.char_lenient_flag = 0;
|
|
+ main_wanted_type.field_width = field_width;
|
|
if (strchr (fci->flags2, 'c') != 0)
|
|
main_wanted_type.char_lenient_flag = 1;
|
|
main_wanted_type.writing_in_flag = 0;
|
|
main_wanted_type.reading_from_flag = 0;
|
|
+ if (strchr (fci->format_chars, 'c') != 0)
|
|
+ main_wanted_type.size_equals_width = 1;
|
|
+ else
|
|
+ main_wanted_type.size_equals_width = 0;
|
|
if (aflag)
|
|
main_wanted_type.writing_in_flag = 1;
|
|
else
|
|
@@ -2224,6 +2305,27 @@ check_format_types (status, types)
|
|
cur_param = TREE_OPERAND (cur_param, 0);
|
|
else
|
|
cur_param = 0;
|
|
+
|
|
+ /* Test static string bounds for sscan if -Wbounded is on as well */
|
|
+ if (warn_bounded
|
|
+ && types->writing_in_flag
|
|
+ && i == 0
|
|
+ && cur_param != 0
|
|
+ && COMPLETE_TYPE_P (TREE_TYPE (cur_param))
|
|
+ && TREE_CODE (TREE_TYPE (cur_param)) == ARRAY_TYPE
|
|
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (cur_param))) == INTEGER_TYPE)
|
|
+ {
|
|
+ tree array_domain = TYPE_DOMAIN (TREE_TYPE (cur_param));
|
|
+ tree array_size_expr = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (cur_param)));
|
|
+ int f = types->size_equals_width ? 0 : 1;
|
|
+ if (array_size_expr != 0 && types->field_width > 0)
|
|
+ {
|
|
+ int array_size = TREE_INT_CST_LOW (array_size_expr) + 1;
|
|
+ if (array_size < (types->field_width + f))
|
|
+ warning ("Array size (%d) smaller than format string size (%d)",
|
|
+ array_size, types->field_width + f);
|
|
+ }
|
|
+ }
|
|
|
|
/* See if this is an attempt to write into a const type with
|
|
scanf or with printf "%n". Note: the writing in happens
|