mirror of
https://git.FreeBSD.org/ports.git
synced 2025-01-25 09:34:11 +00:00
339e20ffc2
auditing purposes. Submitted by: kris Obtained from: NetBSD
374 lines
11 KiB
Plaintext
374 lines
11 KiB
Plaintext
--- gcc/c-common.c.orig Tue Sep 7 01:11:16 1999
|
||
+++ gcc/c-common.c Sun Nov 26 15:35:38 2000
|
||
@@ -64,7 +64,7 @@
|
||
int, int, int));
|
||
static void init_attributes PROTO((void));
|
||
static void record_function_format PROTO((tree, tree, enum format_type,
|
||
- int, int));
|
||
+ int, int, int));
|
||
static void record_international_format PROTO((tree, tree, int));
|
||
static tree c_find_base_decl PROTO((tree));
|
||
static int default_valid_lang_attribute PROTO ((tree, tree, tree, tree));
|
||
@@ -715,6 +715,7 @@
|
||
= TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
|
||
int format_num;
|
||
int first_arg_num;
|
||
+ int null_format_ok;
|
||
enum format_type format_type;
|
||
tree argument;
|
||
int arg_num;
|
||
@@ -728,7 +729,7 @@
|
||
|
||
if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
|
||
{
|
||
- error ("unrecognized format specifier");
|
||
+ error_with_decl (decl, "unrecognized format specifier");
|
||
continue;
|
||
}
|
||
else
|
||
@@ -736,12 +737,26 @@
|
||
const char *p = IDENTIFIER_POINTER (format_type_id);
|
||
|
||
if (!strcmp (p, "printf") || !strcmp (p, "__printf__"))
|
||
+ {
|
||
+ format_type = printf_format_type;
|
||
+ null_format_ok = 0;
|
||
+ }
|
||
+ else if (!strcmp (p, "printf0") || !strcmp (p, "__printf0__"))
|
||
+ {
|
||
format_type = printf_format_type;
|
||
+ null_format_ok = 1;
|
||
+ }
|
||
else if (!strcmp (p, "scanf") || !strcmp (p, "__scanf__"))
|
||
+ {
|
||
format_type = scanf_format_type;
|
||
+ null_format_ok = 0;
|
||
+ }
|
||
else if (!strcmp (p, "strftime")
|
||
|| !strcmp (p, "__strftime__"))
|
||
+ {
|
||
format_type = strftime_format_type;
|
||
+ null_format_ok = 0;
|
||
+ }
|
||
else
|
||
{
|
||
warning ("`%s' is an unrecognized format function type", p);
|
||
@@ -812,7 +827,8 @@
|
||
|
||
record_function_format (DECL_NAME (decl),
|
||
DECL_ASSEMBLER_NAME (decl),
|
||
- format_type, format_num, first_arg_num);
|
||
+ format_type, null_format_ok, format_num,
|
||
+ first_arg_num);
|
||
break;
|
||
}
|
||
|
||
@@ -1090,6 +1106,11 @@
|
||
} format_char_info;
|
||
|
||
static format_char_info print_char_table[] = {
|
||
+/* FreeBSD kernel extensions. */
|
||
+ { "D", 1, T_C, T_C, NULL, NULL, NULL, NULL, NULL, "-wp" },
|
||
+ { "b", 1, T_C, T_C, NULL, NULL, NULL, NULL, NULL, "-wp" },
|
||
+ { "rz", 0, NULL, T_I, T_I, T_L, NULL, NULL, NULL, "-wp0 +#" },
|
||
+#define unextended_print_char_table (print_char_table + 3)
|
||
{ "di", 0, T_I, T_I, T_I, T_L, T_LL, T_LL, T_ST, "-wp0 +" },
|
||
{ "oxX", 0, T_UI, T_UI, T_UI, T_UL, T_ULL, T_ULL, T_ST, "-wp0#" },
|
||
{ "u", 0, T_UI, T_UI, T_UI, T_UL, T_ULL, T_ULL, T_ST, "-wp0" },
|
||
@@ -1150,6 +1171,7 @@
|
||
tree name; /* identifier such as "printf" */
|
||
tree assembler_name; /* optional mangled identifier (for C++) */
|
||
enum format_type format_type; /* type of format (printf, scanf, etc.) */
|
||
+ int null_format_ok; /* TRUE if the format string may be NULL */
|
||
int format_num; /* number of format argument */
|
||
int first_arg_num; /* number of first arg (zero for varargs) */
|
||
} function_format_info;
|
||
@@ -1182,25 +1204,25 @@
|
||
init_function_format_info ()
|
||
{
|
||
record_function_format (get_identifier ("printf"), NULL_TREE,
|
||
- printf_format_type, 1, 2);
|
||
+ printf_format_type, 0, 1, 2);
|
||
record_function_format (get_identifier ("fprintf"), NULL_TREE,
|
||
- printf_format_type, 2, 3);
|
||
+ printf_format_type, 0, 2, 3);
|
||
record_function_format (get_identifier ("sprintf"), NULL_TREE,
|
||
- printf_format_type, 2, 3);
|
||
+ printf_format_type, 0, 2, 3);
|
||
record_function_format (get_identifier ("scanf"), NULL_TREE,
|
||
- scanf_format_type, 1, 2);
|
||
+ scanf_format_type, 0, 1, 2);
|
||
record_function_format (get_identifier ("fscanf"), NULL_TREE,
|
||
- scanf_format_type, 2, 3);
|
||
+ scanf_format_type, 0, 2, 3);
|
||
record_function_format (get_identifier ("sscanf"), NULL_TREE,
|
||
- scanf_format_type, 2, 3);
|
||
+ scanf_format_type, 0, 2, 3);
|
||
record_function_format (get_identifier ("vprintf"), NULL_TREE,
|
||
- printf_format_type, 1, 0);
|
||
+ printf_format_type, 0, 1, 0);
|
||
record_function_format (get_identifier ("vfprintf"), NULL_TREE,
|
||
- printf_format_type, 2, 0);
|
||
+ printf_format_type, 0, 2, 0);
|
||
record_function_format (get_identifier ("vsprintf"), NULL_TREE,
|
||
- printf_format_type, 2, 0);
|
||
+ printf_format_type, 0, 2, 0);
|
||
record_function_format (get_identifier ("strftime"), NULL_TREE,
|
||
- strftime_format_type, 3, 0);
|
||
+ strftime_format_type, 0, 3, 0);
|
||
|
||
record_international_format (get_identifier ("gettext"), NULL_TREE, 1);
|
||
record_international_format (get_identifier ("dgettext"), NULL_TREE, 2);
|
||
@@ -1217,11 +1239,12 @@
|
||
(e.g. for varargs such as vfprintf). */
|
||
|
||
static void
|
||
-record_function_format (name, assembler_name, format_type,
|
||
+record_function_format (name, assembler_name, format_type, null_format_ok,
|
||
format_num, first_arg_num)
|
||
tree name;
|
||
tree assembler_name;
|
||
enum format_type format_type;
|
||
+ int null_format_ok;
|
||
int format_num;
|
||
int first_arg_num;
|
||
{
|
||
@@ -1245,6 +1268,7 @@
|
||
}
|
||
|
||
info->format_type = format_type;
|
||
+ info->null_format_ok = null_format_ok;
|
||
info->format_num = format_num;
|
||
info->first_arg_num = first_arg_num;
|
||
}
|
||
@@ -1292,6 +1316,21 @@
|
||
warning ("too few arguments for format");
|
||
}
|
||
|
||
+static function_format_info *
|
||
+find_function_format (name, assembler_name)
|
||
+ tree name;
|
||
+ tree assembler_name;
|
||
+{
|
||
+ function_format_info *info;
|
||
+
|
||
+ for (info = function_format_list; info; info = info->next)
|
||
+ if (info->assembler_name
|
||
+ ? (info->assembler_name == assembler_name)
|
||
+ : (info->name == name))
|
||
+ return info;
|
||
+ return 0;
|
||
+}
|
||
+
|
||
/* Check the argument list of a call to printf, scanf, etc.
|
||
NAME is the function identifier.
|
||
ASSEMBLER_NAME is the function's assembler identifier.
|
||
@@ -1307,17 +1346,10 @@
|
||
function_format_info *info;
|
||
|
||
/* See if this function is a format function. */
|
||
- for (info = function_format_list; info; info = info->next)
|
||
- {
|
||
- if (info->assembler_name
|
||
- ? (info->assembler_name == assembler_name)
|
||
- : (info->name == name))
|
||
- {
|
||
- /* Yup; check it. */
|
||
- check_format_info (info, params);
|
||
- break;
|
||
- }
|
||
- }
|
||
+ info = find_function_format (name, assembler_name);
|
||
+
|
||
+ if (info)
|
||
+ check_format_info (info, params);
|
||
}
|
||
|
||
/* Check the argument list of a call to printf, scanf, etc.
|
||
@@ -1361,6 +1393,7 @@
|
||
return;
|
||
|
||
/* We can only check the format if it's a string constant. */
|
||
+ again:
|
||
while (TREE_CODE (format_tree) == NOP_EXPR)
|
||
format_tree = TREE_OPERAND (format_tree, 0); /* strip coercion */
|
||
|
||
@@ -1396,16 +1429,73 @@
|
||
}
|
||
}
|
||
|
||
+ if (TREE_CODE (format_tree) == COND_EXPR)
|
||
+ {
|
||
+ format_tree = TREE_OPERAND(format_tree, 1);
|
||
+ goto again;
|
||
+ }
|
||
+
|
||
if (integer_zerop (format_tree))
|
||
{
|
||
- warning ("null format string");
|
||
+ if (!info->null_format_ok)
|
||
+ warning ("null format string");
|
||
+ return;
|
||
+ }
|
||
+ if (TREE_CODE (format_tree) != ADDR_EXPR)
|
||
+ {
|
||
+ if ((info->first_arg_num == 0) &&
|
||
+ (TREE_CODE(format_tree) == PARM_DECL))
|
||
+ {
|
||
+ function_format_info *i2;
|
||
+ tree p;
|
||
+ int n;
|
||
+
|
||
+ /* Now, we need to determine if the current function is printf-like,
|
||
+ and, if so, if the parameter we have here is as a parameter of
|
||
+ the current function and is in the argument slot declared to
|
||
+ contain the format argument. */
|
||
+
|
||
+ p = current_function_decl;
|
||
+
|
||
+ i2 = find_function_format (p->decl.name, p->decl.assembler_name);
|
||
+
|
||
+ if (i2 == NULL)
|
||
+ {
|
||
+ if (warn_format > 1)
|
||
+ warning("non-constant format parameter");
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ for (n = 1, p = current_function_decl->decl.arguments;
|
||
+ (n < i2->format_num) && (p != NULL);
|
||
+ n++, p = TREE_CHAIN(p))
|
||
+ ;
|
||
+ if ((p == NULL) || (n != i2->format_num))
|
||
+ warning("can't find format arg for current format function");
|
||
+ else if (p != format_tree)
|
||
+ warning("format argument passed here is not declared as format argument");
|
||
+ }
|
||
+ }
|
||
+ else if ((info->format_type != strftime_format_type) &&
|
||
+ (warn_format > 1))
|
||
+ warning("non-constant format parameter");
|
||
return;
|
||
}
|
||
- if (TREE_CODE (format_tree) != ADDR_EXPR)
|
||
- return;
|
||
format_tree = TREE_OPERAND (format_tree, 0);
|
||
- if (TREE_CODE (format_tree) != STRING_CST)
|
||
- return;
|
||
+ if (warn_format > 1 &&
|
||
+ (TREE_CODE (format_tree) == VAR_DECL) &&
|
||
+ TREE_READONLY(format_tree) &&
|
||
+ (DECL_INITIAL(format_tree) != NULL) &&
|
||
+ TREE_CODE(DECL_INITIAL(format_tree)) == STRING_CST)
|
||
+ format_tree = DECL_INITIAL(format_tree);
|
||
+
|
||
+ if (TREE_CODE (format_tree) != STRING_CST)
|
||
+ {
|
||
+ if ((info->format_type != strftime_format_type) &&
|
||
+ (warn_format > 1))
|
||
+ warning("non-constant format parameter");
|
||
+ return;
|
||
+ }
|
||
format_chars = TREE_STRING_POINTER (format_tree);
|
||
format_length = TREE_STRING_LENGTH (format_tree);
|
||
if (format_length <= 1)
|
||
@@ -1433,7 +1523,10 @@
|
||
if (format_chars - TREE_STRING_POINTER (format_tree) != format_length)
|
||
warning ("embedded `\\0' in format");
|
||
if (info->first_arg_num != 0 && params != 0 && ! has_operand_number)
|
||
- warning ("too many arguments for format");
|
||
+ {
|
||
+ if (warn_format_extra_args)
|
||
+ warning ("too many arguments for format");
|
||
+ }
|
||
return;
|
||
}
|
||
if (*format_chars++ != '%')
|
||
@@ -1569,12 +1662,13 @@
|
||
It will work on most machines, because size_t and int
|
||
have the same mode. But might as well warn anyway,
|
||
since it will fail on other machines. */
|
||
+ /* XXX should we allow unsigned ints here? */
|
||
if ((TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
|
||
!= integer_type_node)
|
||
&&
|
||
(TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
|
||
!= unsigned_type_node))
|
||
- warning ("field width is not type int (arg %d)", arg_num);
|
||
+ warning ("precision is not type int (arg %d)", arg_num);
|
||
}
|
||
}
|
||
else
|
||
@@ -1619,6 +1713,53 @@
|
||
}
|
||
}
|
||
}
|
||
+ if (*format_chars == 'b')
|
||
+ {
|
||
+ /* There should be an int arg to control the string arg. */
|
||
+ if (params == 0)
|
||
+ {
|
||
+ warning (tfaff);
|
||
+ return;
|
||
+ }
|
||
+ if (info->first_arg_num != 0)
|
||
+ {
|
||
+ cur_param = TREE_VALUE (params);
|
||
+ params = TREE_CHAIN (params);
|
||
+ ++arg_num;
|
||
+ if ((TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
|
||
+ != integer_type_node)
|
||
+ &&
|
||
+ (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
|
||
+ != unsigned_type_node))
|
||
+ {
|
||
+ warning ("bitmap is not type int (arg %d)", arg_num);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ if (*format_chars == 'D')
|
||
+ {
|
||
+ /* There should be an unsigned char * arg before the string arg. */
|
||
+ if (params == 0)
|
||
+ {
|
||
+ warning (tfaff);
|
||
+ return;
|
||
+ }
|
||
+ if (info->first_arg_num != 0)
|
||
+ {
|
||
+ cur_param = TREE_VALUE (params);
|
||
+ params = TREE_CHAIN (params);
|
||
+ ++arg_num;
|
||
+ cur_type = TREE_TYPE (cur_param);
|
||
+ if (TREE_CODE (cur_type) != POINTER_TYPE
|
||
+ || TYPE_MAIN_VARIANT (TREE_TYPE (cur_type))
|
||
+ != unsigned_char_type_node)
|
||
+ {
|
||
+ warning ("ethernet address is not type unsigned char *"
|
||
+ " (arg %d)",
|
||
+ arg_num);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
|
||
aflag = 0;
|
||
|
||
@@ -1688,7 +1829,8 @@
|
||
switch (info->format_type)
|
||
{
|
||
case printf_format_type:
|
||
- fci = print_char_table;
|
||
+ fci = flag_format_extensions ? print_char_table
|
||
+ : unextended_print_char_table;
|
||
break;
|
||
case scanf_format_type:
|
||
fci = scan_char_table;
|
||
@@ -1787,7 +1929,6 @@
|
||
warning ("use of `%c' length character with `%c' type character",
|
||
length_char, format_char);
|
||
|
||
- /* Finally. . .check type of argument against desired type! */
|
||
if (info->first_arg_num == 0)
|
||
continue;
|
||
if (fci->pointer_count == 0 && wanted_type == void_type_node)
|