new file mode 100644
@@ -0,0 +1,83 @@
+/* { dg-do compile } */
+/* { dg-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-caret -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers" } */
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+
+extern void body_of_program(void);
+
+void custom_logger(const char *msg)
+{
+ fprintf(stderr, "LOG: %s", msg); /* { dg-warning "call to 'fprintf' from within signal handler" } */
+}
+
+static void int_handler(int signum)
+{
+ custom_logger("got signal");
+}
+
+static void register_handler ()
+{
+ signal(SIGINT, int_handler);
+}
+
+void test (void)
+{
+ register_handler ();
+ body_of_program();
+}
+
+/* { dg-begin-multiline-output "" }
+ NN | fprintf(stderr, "LOG: %s", msg);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 'test': events 1-2
+ |
+ | NN | {
+ | | ^
+ | | |
+ | | (1) entering 'test'
+ | NN | register_handler ();
+ | | ~~~~~~~~~~~~~~~~~~~
+ | | |
+ | | (2) calling 'register_handler'
+ |
+ +--> 'register_handler': events 3-4
+ |
+ | NN | {
+ | | ^
+ | | |
+ | | (3) entering 'register_handler'
+ | NN | signal(SIGINT, int_handler);
+ | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | | |
+ | | (4) registering 'int_handler' as signal handler
+ |
+ event 5
+ |
+ |cc1:
+ | (5): later on, when the signal is delivered to the process
+ |
+ +--> 'int_handler': events 6-7
+ |
+ | NN | {
+ | | ^
+ | | |
+ | | (6) entering 'int_handler'
+ | NN | custom_logger("got signal");
+ | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | | |
+ | | (7) calling 'custom_logger'
+ |
+ +--> 'custom_logger': events 8-9
+ |
+ | NN | {
+ | | ^
+ | | |
+ | | (8) entering 'custom_logger'
+ | NN | fprintf(stderr, "LOG: %s", msg);
+ | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | | |
+ | | (9) calling 'fprintf'
+ |
+ { dg-end-multiline-output "" } */
@@ -341,11 +341,92 @@ example_2 ()
}
}
+/* Example 3: an interprocedural path with a callback. */
+
+static void
+example_3 ()
+{
+ gimple_stmt_iterator gsi;
+ basic_block bb;
+
+ event_location_t entry_to_custom_logger;
+ event_location_t call_to_fprintf;
+
+ event_location_t entry_to_int_handler;
+ event_location_t call_to_custom_logger;
+
+ event_location_t entry_to_register_handler;
+ event_location_t call_to_signal;
+
+ event_location_t entry_to_test;
+ event_location_t call_to_register_handler;
+
+ cgraph_node *node;
+ FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+ {
+ function *fun = node->get_fun ();
+ FOR_EACH_BB_FN (bb, fun)
+ {
+ check_for_named_function (fun, "custom_logger",
+ &entry_to_custom_logger);
+ check_for_named_function (fun, "int_handler",
+ &entry_to_int_handler);
+ check_for_named_function (fun, "register_handler",
+ &entry_to_register_handler);
+ check_for_named_function (fun, "test",
+ &entry_to_test);
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (gcall *call = check_for_named_call (stmt, "fprintf", 3))
+ call_to_fprintf.set (call, fun);
+ if (gcall *call = check_for_named_call (stmt, "custom_logger", 1))
+ call_to_custom_logger.set (call, fun);
+ if (gcall *call = check_for_named_call (stmt, "register_handler",
+ 0))
+ call_to_register_handler.set (call, fun);
+ if (gcall *call = check_for_named_call (stmt, "signal", 2))
+ call_to_signal.set (call, fun);
+ }
+ }
+ }
+
+ if (call_to_fprintf.m_fun)
+ {
+ auto_diagnostic_group d;
+
+ gcc_rich_location richloc (call_to_fprintf.m_loc);
+ test_diagnostic_path path (global_dc->printer);
+ path.add_entry (entry_to_test, 1, "test");
+ path.add_call (call_to_register_handler, 1,
+ entry_to_register_handler, "register_handler");
+ path.add_event (call_to_signal.m_loc, call_to_signal.m_fun->decl,
+ 2, "registering 'int_handler' as signal handler");
+ path.add_event (UNKNOWN_LOCATION, NULL_TREE, 0,
+ "later on, when the signal is delivered to the process");
+ path.add_entry (entry_to_int_handler, 1, "int_handler");
+ path.add_call (call_to_custom_logger, 1,
+ entry_to_custom_logger, "custom_logger");
+ path.add_leaf_call (call_to_fprintf, 2, "fprintf");
+
+ richloc.set_path (&path);
+
+ diagnostic_metadata m;
+ /* CWE-479: Signal Handler Use of a Non-reentrant Function. */
+ m.add_cwe (479);
+
+ warning_at (&richloc, m, 0,
+ "call to %qs from within signal handler",
+ "fprintf");
+ }
+}
+
unsigned int
pass_test_show_path::execute (function *)
{
example_1 ();
example_2 ();
+ example_3 ();
return 0;
}
@@ -98,6 +98,7 @@ set plugin_test_list [list \
diagnostic-test-paths-1.c \
diagnostic-test-paths-2.c \
diagnostic-test-paths-3.c \
+ diagnostic-test-paths-4.c \
diagnostic-path-format-default.c \
diagnostic-path-format-none.c \
diagnostic-path-format-separate-events.c \
@@ -339,12 +339,16 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
cur_indent += strlen (push_prefix);
}
}
- print_fndecl (pp, range->m_fndecl, true);
+ if (range->m_fndecl)
+ {
+ print_fndecl (pp, range->m_fndecl, true);
+ pp_string (pp, ": ");
+ }
if (range->m_start_idx == range->m_end_idx)
- pp_printf (pp, ": event %i",
+ pp_printf (pp, "event %i",
range->m_start_idx + 1);
else
- pp_printf (pp, ": events %i-%i",
+ pp_printf (pp, "events %i-%i",
range->m_start_idx + 1, range->m_end_idx + 1);
if (show_depths)
pp_printf (pp, " (depth %i)", range->m_stack_depth);
@@ -387,36 +391,41 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
if (range->m_stack_depth > next_range->m_stack_depth)
{
- /* Show returning from stack frame(s), by printing
- something like:
- " |\n"
- " <------------ +\n"
- " |\n". */
-
- gcc_assert (vbar_column_for_depth.get
- (next_range->m_stack_depth));
-
- int vbar_for_next_frame
- = *vbar_column_for_depth.get (next_range->m_stack_depth);
-
- int indent_for_next_frame
- = vbar_for_next_frame - per_frame_indent;
- write_indent (pp, vbar_for_next_frame);
- pp_string (pp, start_line_color);
- pp_character (pp, '<');
- for (int i = indent_for_next_frame + per_frame_indent;
- i < cur_indent + per_frame_indent - 1; i++)
- pp_character (pp, '-');
- pp_character (pp, '+');
- pp_string (pp, end_line_color);
- pp_newline (pp);
- cur_indent = indent_for_next_frame;
-
- write_indent (pp, vbar_for_next_frame);
- pp_string (pp, start_line_color);
- pp_printf (pp, "|");
- pp_string (pp, end_line_color);
- pp_newline (pp);
+ if (vbar_column_for_depth.get (next_range->m_stack_depth))
+ {
+ /* Show returning from stack frame(s), by printing
+ something like:
+ " |\n"
+ " <------------ +\n"
+ " |\n". */
+ int vbar_for_next_frame
+ = *vbar_column_for_depth.get (next_range->m_stack_depth);
+
+ int indent_for_next_frame
+ = vbar_for_next_frame - per_frame_indent;
+ write_indent (pp, vbar_for_next_frame);
+ pp_string (pp, start_line_color);
+ pp_character (pp, '<');
+ for (int i = indent_for_next_frame + per_frame_indent;
+ i < cur_indent + per_frame_indent - 1; i++)
+ pp_character (pp, '-');
+ pp_character (pp, '+');
+ pp_string (pp, end_line_color);
+ pp_newline (pp);
+ cur_indent = indent_for_next_frame;
+
+ write_indent (pp, vbar_for_next_frame);
+ pp_string (pp, start_line_color);
+ pp_printf (pp, "|");
+ pp_string (pp, end_line_color);
+ pp_newline (pp);
+ }
+ else
+ {
+ /* Handle disjoint paths (e.g. a callback at some later
+ time). */
+ cur_indent = base_indent;
+ }
}
else if (range->m_stack_depth < next_range->m_stack_depth)
{