From: Martin Sebor <msebor@gmail.com>
To: Jeff Law <law@redhat.com>, Gcc Patch List <gcc-patches@gcc.gnu.org>
Subject: [PATCH 1/4] enhance overflow and truncation detection in strncpy and strncat (PR 81117)
Date: Sun, 06 Aug 2017 20:07:00 -0000 [thread overview]
Message-ID: <33a2ba18-274d-8229-06b4-c4983f0d3e2f@gmail.com> (raw)
In-Reply-To: <a0069a6d-d4a8-67df-e2f3-902dc7704ab2@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 292 bytes --]
The attached patch adds support for a new GCC format specifier,
G, that behaves like %K but accepts a gcall* argument. This
makes it possible to provide inlining context for "artificial"
inline functions like strncpy (with _FORTIFY_SOURCE) in
diagnostics issued from the middle end.
Martin
[-- Attachment #2: gcc-81117-1.diff --]
[-- Type: text/x-patch, Size: 14293 bytes --]
PR c/81117 - Improve buffer overflow checking in strncpy
gcc/ChangeLog:
PR c/81117
* tree-diagnostic.c (default_tree_printer): Handle %G.
* tree-pretty-print.h (percent_G_format): Declare new function.
* tree-pretty-print.c (percent_K_format): Define a static overload.
(percent_G_format): New function.
gcc/c/ChangeLog:
PR c/81117
* c-objc-common.c (c_objc_common_init): Handle 'G'.
gcc/c-family/ChangeLog:
* c-format.h (T89_G): New macro.
* c-format.c (local_gcall_ptr_node): New variable.
(init_dynamic_diag_info): Initialize it.
gcc/cp/ChangeLog:
PR c/81117
* error.c (cp_printer): Handle 'G'.
gcc/testsuite/ChangeLog:
PR c/81117
* gcc.dg/format/gcc_diag-10.c: Exercise %G.
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 52b7e7f..ad58b69 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -275,6 +275,10 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
t = va_arg (*text->args_ptr, tree);
break;
+ case 'G':
+ percent_G_format (text);
+ return true;
+
case 'K':
percent_K_format (text);
return true;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 4d8177c..7c4c805 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "dumpfile.h"
#include "internal-fn.h"
#include "gomp-constants.h"
+#include "gimple.h"
/* Local functions, macros and variables. */
static const char *op_symbol (const_tree);
@@ -3970,15 +3971,15 @@ newline_and_indent (pretty_printer *pp, int spc)
INDENT (spc);
}
-/* Handle a %K format for TEXT. Separate from default_tree_printer so
- it can also be used in front ends.
- %K: a statement, from which EXPR_LOCATION and TREE_BLOCK will be recorded.
-*/
+/* Handle the %K and %G format for TEXT. Separate from default_tree_printer
+ so it can also be used in front ends.
+ argument is a statement from which EXPR_LOCATION and TREE_BLOCK will be
+ recorded. */
-void
-percent_K_format (text_info *text)
+static void
+percent_K_format (text_info *text, tree t)
{
- tree t = va_arg (*text->args_ptr, tree), block;
+ tree block;
text->set_location (0, EXPR_LOCATION (t), true);
gcc_assert (pp_ti_abstract_origin (text) != NULL);
block = TREE_BLOCK (t);
@@ -4022,6 +4023,34 @@ percent_K_format (text_info *text)
}
}
+/* Handle the %K format for TEXT. */
+
+void
+percent_K_format (text_info *text)
+{
+ tree t = va_arg (*text->args_ptr, tree);
+ percent_K_format (text, t);
+}
+
+/* Handle the %G format for TEXT. Same as %K but with a Gimple call
+ statement as an argument. */
+
+void
+percent_G_format (text_info *text)
+{
+ gcall *stmt = va_arg (*text->args_ptr, gcall*);
+
+ /* Build a call expression from the Gimple call statement and
+ pass it to the K formatter that knows how to format it. */
+ tree exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
+ CALL_EXPR_FN (exp) = gimple_call_fn (stmt);
+ TREE_TYPE (exp) = gimple_call_return_type (stmt);
+ CALL_EXPR_STATIC_CHAIN (exp) = gimple_call_chain (stmt);
+ SET_EXPR_LOCATION (exp, gimple_location (stmt));
+
+ percent_K_format (text, exp);
+}
+
/* Print the identifier ID to PRETTY-PRINTER. */
void
diff --git a/gcc/tree-pretty-print.h b/gcc/tree-pretty-print.h
index 07270b7..213841e 100644
--- a/gcc/tree-pretty-print.h
+++ b/gcc/tree-pretty-print.h
@@ -45,6 +45,7 @@ extern int op_code_prio (enum tree_code);
extern int op_prio (const_tree);
extern const char *op_symbol_code (enum tree_code);
extern void print_call_name (pretty_printer *, tree, dump_flags_t);
+extern void percent_G_format (text_info *);
extern void percent_K_format (text_info *);
extern void pp_tree_identifier (pretty_printer *, tree);
extern void dump_function_header (FILE *, tree, dump_flags_t);
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
index 05212b2..9dd5718 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -66,6 +66,8 @@ c_objc_common_init (void)
%D: a general decl,
%E: an identifier or expression,
%F: a function declaration,
+ %G: a Gimple call statement,
+ %K: a CALL_EXPR,
%T: a type.
%V: a list of type qualifiers from a tree.
%v: an explicit list of type qualifiers
@@ -87,6 +89,12 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
if (precision != 0 || wide)
return false;
+ if (*spec == 'G')
+ {
+ percent_G_format (text);
+ return true;
+ }
+
if (*spec == 'K')
{
percent_K_format (text);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 2497c7f..483d3b5 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -4048,6 +4048,10 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
case 'V': result = cv_to_string (next_tree, verbose); break;
case 'X': result = eh_spec_to_string (next_tree, verbose); break;
+ case 'G':
+ percent_G_format (text);
+ return true;
+
case 'K':
percent_K_format (text);
return true;
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 0a5cc03..0ff9446 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -55,6 +55,7 @@ struct function_format_info
/* Initialized in init_dynamic_diag_info. */
static GTY(()) tree local_tree_type_node;
+static GTY(()) tree local_gcall_ptr_node;
static GTY(()) tree locus;
static bool decode_format_attr (tree, function_format_info *, int);
@@ -689,7 +690,9 @@ static const format_char_info gcc_diag_char_table[] =
/* Custom conversion specifiers. */
- /* These will require a "tree" at runtime. */
+ /* G requires a "gcall*" argument at runtime. */
+ { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
+ /* K requires a "tree" argument at runtime. */
{ "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
{ "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL },
@@ -718,6 +721,9 @@ static const format_char_info gcc_tdiag_char_table[] =
{ "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
{ "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
+ /* G requires a "gcall*" argument at runtime. */
+ { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
+
{ "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
{ "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL },
@@ -747,6 +753,9 @@ static const format_char_info gcc_cdiag_char_table[] =
{ "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
{ "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
+ /* G requires a "gcall*" argument at runtime. */
+ { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
+
{ "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
{ "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL },
@@ -777,6 +786,9 @@ static const format_char_info gcc_cxxdiag_char_table[] =
{ "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
{ "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
+ /* G requires a "gcall*" argument at runtime. */
+ { "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
+
/* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */
{ "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
@@ -3834,6 +3846,29 @@ init_dynamic_diag_info (void)
local_tree_type_node = void_type_node;
}
+ /* Similar to the above but for gcall*. */
+ if (!local_gcall_ptr_node
+ || local_gcall_ptr_node == void_type_node)
+ {
+ if ((local_gcall_ptr_node = maybe_get_identifier ("gcall")))
+ {
+ local_gcall_ptr_node
+ = identifier_global_value (local_gcall_ptr_node);
+ if (local_gcall_ptr_node)
+ {
+ if (TREE_CODE (local_gcall_ptr_node) != TYPE_DECL)
+ {
+ error ("%<gcall%> is not defined as a type");
+ local_gcall_ptr_node = 0;
+ }
+ else
+ local_gcall_ptr_node = TREE_TYPE (local_gcall_ptr_node);
+ }
+ }
+ else
+ local_gcall_ptr_node = void_type_node;
+ }
+
static tree hwi;
if (!hwi)
diff --git a/gcc/c-family/c-format.h b/gcc/c-family/c-format.h
index 37fa382..05e9bb7 100644
--- a/gcc/c-family/c-format.h
+++ b/gcc/c-family/c-format.h
@@ -298,6 +298,7 @@ struct format_kind_info
#define T_UC &unsigned_char_type_node
#define T99_UC { STD_C99, NULL, T_UC }
#define T_V &void_type_node
+#define T89_G { STD_C89, NULL, &local_gcall_ptr_node }
#define T89_T { STD_C89, NULL, &local_tree_type_node }
#define T89_V { STD_C89, NULL, T_V }
#define T_W &wchar_type_node
diff --git a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
index b3be277..9bda73b 100644
--- a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
+++ b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
@@ -15,6 +15,9 @@ typedef struct location_s
union tree_node;
typedef union tree_node *tree;
+/* Define gcall as a dummy type. The typedef must be provided for
+ the C test to find the symbol. */
+typedef struct gcall gcall;
#define FORMAT(kind) __attribute__ ((format (__gcc_## kind ##__, 1, 2)))
@@ -23,12 +26,13 @@ void cdiag (const char*, ...) FORMAT (cdiag);
void tdiag (const char*, ...) FORMAT (tdiag);
void cxxdiag (const char*, ...) FORMAT (cxxdiag);
-void test_diag (tree t)
+void test_diag (tree t, gcall *gc)
{
diag ("%<"); /* { dg-warning "unterminated quoting directive" } */
diag ("%>"); /* { dg-warning "unmatched quoting directive " } */
diag ("%<foo%<bar%>%>"); /* { dg-warning "nested quoting directive" } */
+ diag ("%G", gc);
diag ("%K", t);
diag ("%R"); /* { dg-warning "unmatched color reset directive" } */
@@ -38,6 +42,7 @@ void test_diag (tree t)
diag ("%r%r%R", "", "");
diag ("%r%R%r%R", "", "");
+ diag ("%<%G%>", gc); /* { dg-warning ".G. conversion used within a quoted sequence" } */
diag ("%<%K%>", t); /* { dg-warning ".K. conversion used within a quoted sequence" } */
diag ("%<%R%>"); /* { dg-warning "unmatched color reset directive" } */
@@ -45,7 +50,7 @@ void test_diag (tree t)
diag ("%<%r%R%>", "");
}
-void test_cdiag (tree t)
+void test_cdiag (tree t, gcall *gc)
{
cdiag ("%<"); /* { dg-warning "unterminated quoting directive" } */
cdiag ("%>"); /* { dg-warning "unmatched quoting directive " } */
@@ -54,6 +59,7 @@ void test_cdiag (tree t)
cdiag ("%D", t); /* { dg-warning ".D. conversion used unquoted" } */
cdiag ("%E", t);
cdiag ("%F", t); /* { dg-warning ".F. conversion used unquoted" } */
+ cdiag ("%G", gc);
cdiag ("%K", t);
cdiag ("%R"); /* { dg-warning "unmatched color reset directive" } */
@@ -69,6 +75,7 @@ void test_cdiag (tree t)
cdiag ("%<%D%>", t);
cdiag ("%<%E%>", t);
cdiag ("%<%F%>", t);
+ cdiag ("%<%G%>", gc); /* { dg-warning ".G. conversion used within a quoted sequence" } */
cdiag ("%<%K%>", t); /* { dg-warning ".K. conversion used within a quoted sequence" } */
cdiag ("%<%R%>"); /* { dg-warning "unmatched color reset directive" } */
@@ -83,7 +90,7 @@ void test_cdiag (tree t)
cdiag ("%<%qT%>", t); /* { dg-warning ".q. flag used within a quoted sequence" } */
}
-void test_tdiag (tree t)
+void test_tdiag (tree t, gcall *gc)
{
tdiag ("%<"); /* { dg-warning "unterminated quoting directive" } */
tdiag ("%>"); /* { dg-warning "unmatched quoting directive " } */
@@ -91,6 +98,7 @@ void test_tdiag (tree t)
tdiag ("%D", t); /* { dg-warning ".D. conversion used unquoted" } */
tdiag ("%E", t);
+ tdiag ("%G", gc);
tdiag ("%K", t);
tdiag ("%R"); /* { dg-warning "unmatched color reset directive" } */
@@ -105,6 +113,7 @@ void test_tdiag (tree t)
tdiag ("%<%D%>", t);
tdiag ("%<%E%>", t);
+ tdiag ("%<%G%>", gc); /* { dg-warning ".G. conversion used within a quoted sequence" } */
tdiag ("%<%K%>", t); /* { dg-warning ".K. conversion used within a quoted sequence" } */
tdiag ("%<%R%>"); /* { dg-warning "unmatched color reset directive" } */
@@ -118,12 +127,14 @@ void test_tdiag (tree t)
tdiag ("%<%qT%>", t); /* { dg-warning ".q. flag used within a quoted sequence" } */
}
-void test_cxxdiag (tree t)
+void test_cxxdiag (tree t, gcall *gc)
{
cxxdiag ("%A", t); /* { dg-warning ".A. conversion used unquoted" } */
cxxdiag ("%D", t); /* { dg-warning ".D. conversion used unquoted" } */
cxxdiag ("%E", t);
cxxdiag ("%F", t); /* { dg-warning ".F. conversion used unquoted" } */
+ cxxdiag ("%G", gc);
+ cxxdiag ("%K", t);
cxxdiag ("%R"); /* { dg-warning "unmatched color reset directive" } */
cxxdiag ("%r", ""); /* { dg-warning "unterminated color directive" } */
next prev parent reply other threads:[~2017-08-06 20:07 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-07-08 20:45 [PATCH] " Martin Sebor
2017-07-18 2:51 ` [PING] " Martin Sebor
2017-07-25 3:10 ` [PING #2] " Martin Sebor
2017-07-31 17:29 ` Jeff Law
2017-07-31 19:42 ` Martin Sebor
2017-08-02 16:59 ` Jeff Law
2017-08-06 20:07 ` Martin Sebor [this message]
2017-08-10 5:02 ` [PATCH 1/4] " Jeff Law
2017-08-14 19:21 ` Martin Sebor
2017-08-06 20:07 ` [PATCH] " Martin Sebor
2017-08-09 19:21 ` Jeff Law
2017-08-06 20:07 ` [PATCH 3/4] " Martin Sebor
2017-08-10 7:17 ` Jeff Law
2017-08-10 7:39 ` Richard Biener
2017-08-10 20:21 ` Martin Sebor
2017-08-15 3:06 ` Martin Sebor
2017-08-23 21:11 ` [PING] " Martin Sebor
2017-08-29 5:07 ` [PING 2] " Martin Sebor
2017-09-19 15:44 ` [PING 3] " Martin Sebor
2017-09-26 2:27 ` [PING 4] " Martin Sebor
2017-10-02 22:15 ` Jeff Law
2017-10-21 0:26 ` Martin Sebor
2017-11-04 3:49 ` Jeff Law
2017-11-10 0:17 ` Martin Sebor
2017-11-10 0:31 ` Jeff Law
2017-11-14 9:24 ` [testsuite, committed] Require alloca for c-c++-common/Wstringop-truncation.c Tom de Vries
2017-11-15 15:30 ` [testsuite, committed] Compile strncpy-fix-1.c with -Wno-stringop-truncation Tom de Vries
2017-11-15 15:58 ` Martin Sebor
2017-08-06 20:07 ` [PATCH 2/4] enhance overflow and truncation detection in strncpy and strncat (PR 81117) Martin Sebor
2017-08-10 6:39 ` Jeff Law
2017-08-14 18:04 ` Martin Sebor
2017-08-14 18:29 ` Joseph Myers
2017-08-14 19:26 ` Martin Sebor
2017-08-14 20:41 ` Joseph Myers
2017-08-14 20:44 ` Martin Sebor
2017-08-15 3:03 ` Joseph Myers
2017-11-10 23:03 ` Marc Glisse
2017-11-11 21:10 ` Martin Sebor
2017-08-06 20:07 ` [PATCH 4/4] " Martin Sebor
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=33a2ba18-274d-8229-06b4-c4983f0d3e2f@gmail.com \
--to=msebor@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=law@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).