analyzer: early rejection of disabled warnings [PR104955]
Avoid generating execution paths for warnings that are ultimately rejected due to -Wno-analyzer-* flags. This improves the test case from taking at least several minutes (before I killed it) to taking under a second. This doesn't fix the slowdown seen in PR analyzer/104955 with large numbers of warnings when the warnings are still enabled. gcc/analyzer/ChangeLog: PR analyzer/104955 * diagnostic-manager.cc (get_emission_location): New. (diagnostic_manager::diagnostic_manager): Initialize m_num_disabled_diagnostics. (diagnostic_manager::add_diagnostic): Reject diagnostics that will eventually be rejected due to being disabled. (diagnostic_manager::emit_saved_diagnostics): Log the number of disabled diagnostics. (diagnostic_manager::emit_saved_diagnostic): Split out logic for determining emission location to get_emission_location. * diagnostic-manager.h (diagnostic_manager::m_num_disabled_diagnostics): New field. * engine.cc (stale_jmp_buf::get_controlling_option): New. (stale_jmp_buf::emit): Use it. * pending-diagnostic.h (pending_diagnostic::get_controlling_option): New vfunc. * region-model.cc (poisoned_value_diagnostic::get_controlling_option): New. (poisoned_value_diagnostic::emit): Use it. (shift_count_negative_diagnostic::get_controlling_option): New. (shift_count_negative_diagnostic::emit): Use it. (shift_count_overflow_diagnostic::get_controlling_option): New. (shift_count_overflow_diagnostic::emit): Use it. (dump_path_diagnostic::get_controlling_option): New. (dump_path_diagnostic::emit): Use it. (write_to_const_diagnostic::get_controlling_option): New. (write_to_const_diagnostic::emit): Use it. (write_to_string_literal_diagnostic::get_controlling_option): New. (write_to_string_literal_diagnostic::emit): Use it. * sm-file.cc (double_fclose::get_controlling_option): New. (double_fclose::emit): Use it. (file_leak::get_controlling_option): New. (file_leak::emit): Use it. * sm-malloc.cc (mismatching_deallocation::get_controlling_option): New. (mismatching_deallocation::emit): Use it. (double_free::get_controlling_option): New. (double_free::emit): Use it. (possible_null_deref::get_controlling_option): New. (possible_null_deref::emit): Use it. (possible_null_arg::get_controlling_option): New. (possible_null_arg::emit): Use it. (null_deref::get_controlling_option): New. (null_deref::emit): Use it. (null_arg::get_controlling_option): New. (null_arg::emit): Use it. (use_after_free::get_controlling_option): New. (use_after_free::emit): Use it. (malloc_leak::get_controlling_option): New. (malloc_leak::emit): Use it. (free_of_non_heap::get_controlling_option): New. (free_of_non_heap::emit): Use it. * sm-pattern-test.cc (pattern_match::get_controlling_option): New. (pattern_match::emit): Use it. * sm-sensitive.cc (exposure_through_output_file::get_controlling_option): New. (exposure_through_output_file::emit): Use it. * sm-signal.cc (signal_unsafe_call::get_controlling_option): New. (signal_unsafe_call::emit): Use it. * sm-taint.cc (tainted_array_index::get_controlling_option): New. (tainted_array_index::emit): Use it. (tainted_offset::get_controlling_option): New. (tainted_offset::emit): Use it. (tainted_size::get_controlling_option): New. (tainted_size::emit): Use it. (tainted_divisor::get_controlling_option): New. (tainted_divisor::emit): Use it. (tainted_allocation_size::get_controlling_option): New. (tainted_allocation_size::emit): Use it. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/many-disabled-diagnostics.c: New test. * gcc.dg/plugin/analyzer_gil_plugin.c (gil_diagnostic::get_controlling_option): New. (double_save_thread::emit): Use it. (fncall_without_gil::emit): Likewise. (pyobject_usage_without_gil::emit): Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
parent
5a4e208022
commit
7fd6e36ea9
13 changed files with 300 additions and 73 deletions
|
@ -849,13 +849,28 @@ private:
|
||||||
const feasibility_problem *m_feasibility_problem;
|
const feasibility_problem *m_feasibility_problem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Determine the emission location for PD at STMT in FUN. */
|
||||||
|
|
||||||
|
static location_t
|
||||||
|
get_emission_location (const gimple *stmt, function *fun,
|
||||||
|
const pending_diagnostic &pd)
|
||||||
|
{
|
||||||
|
location_t loc = get_stmt_location (stmt, fun);
|
||||||
|
|
||||||
|
/* Allow the pending_diagnostic to fix up the location. */
|
||||||
|
loc = pd.fixup_location (loc);
|
||||||
|
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
/* class diagnostic_manager. */
|
/* class diagnostic_manager. */
|
||||||
|
|
||||||
/* diagnostic_manager's ctor. */
|
/* diagnostic_manager's ctor. */
|
||||||
|
|
||||||
diagnostic_manager::diagnostic_manager (logger *logger, engine *eng,
|
diagnostic_manager::diagnostic_manager (logger *logger, engine *eng,
|
||||||
int verbosity)
|
int verbosity)
|
||||||
: log_user (logger), m_eng (eng), m_verbosity (verbosity)
|
: log_user (logger), m_eng (eng), m_verbosity (verbosity),
|
||||||
|
m_num_disabled_diagnostics (0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,6 +892,25 @@ diagnostic_manager::add_diagnostic (const state_machine *sm,
|
||||||
through the exploded_graph to the diagnostic. */
|
through the exploded_graph to the diagnostic. */
|
||||||
gcc_assert (enode);
|
gcc_assert (enode);
|
||||||
|
|
||||||
|
/* If this warning is ultimately going to be rejected by a -Wno-analyzer-*
|
||||||
|
flag, reject it now.
|
||||||
|
We can only do this for diagnostics where we already know the stmt,
|
||||||
|
and thus can determine the emission location. */
|
||||||
|
if (stmt)
|
||||||
|
{
|
||||||
|
location_t loc = get_emission_location (stmt, snode->m_fun, *d);
|
||||||
|
int option = d->get_controlling_option ();
|
||||||
|
if (!warning_enabled_at (loc, option))
|
||||||
|
{
|
||||||
|
if (get_logger ())
|
||||||
|
get_logger ()->log ("rejecting disabled warning %qs",
|
||||||
|
d->get_kind ());
|
||||||
|
delete d;
|
||||||
|
m_num_disabled_diagnostics++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
saved_diagnostic *sd
|
saved_diagnostic *sd
|
||||||
= new saved_diagnostic (sm, enode, snode, stmt, finder, var, sval,
|
= new saved_diagnostic (sm, enode, snode, stmt, finder, var, sval,
|
||||||
state, d, m_saved_diagnostics.length ());
|
state, d, m_saved_diagnostics.length ());
|
||||||
|
@ -1186,6 +1220,7 @@ diagnostic_manager::emit_saved_diagnostics (const exploded_graph &eg)
|
||||||
LOG_SCOPE (get_logger ());
|
LOG_SCOPE (get_logger ());
|
||||||
auto_timevar tv (TV_ANALYZER_DIAGNOSTICS);
|
auto_timevar tv (TV_ANALYZER_DIAGNOSTICS);
|
||||||
log ("# saved diagnostics: %i", m_saved_diagnostics.length ());
|
log ("# saved diagnostics: %i", m_saved_diagnostics.length ());
|
||||||
|
log ("# disabled diagnostics: %i", m_num_disabled_diagnostics);
|
||||||
if (get_logger ())
|
if (get_logger ())
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -1265,11 +1300,10 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
|
||||||
|
|
||||||
emission_path.prepare_for_emission (sd.m_d);
|
emission_path.prepare_for_emission (sd.m_d);
|
||||||
|
|
||||||
location_t loc = get_stmt_location (sd.m_stmt, sd.m_snode->m_fun);
|
location_t loc
|
||||||
|
= get_emission_location (sd.m_stmt, sd.m_snode->m_fun, *sd.m_d);
|
||||||
|
|
||||||
/* Allow the pending_diagnostic to fix up the primary location
|
/* Allow the pending_diagnostic to fix up the locations of events. */
|
||||||
and any locations for events. */
|
|
||||||
loc = sd.m_d->fixup_location (loc);
|
|
||||||
emission_path.fixup_locations (sd.m_d);
|
emission_path.fixup_locations (sd.m_d);
|
||||||
|
|
||||||
gcc_rich_location rich_loc (loc);
|
gcc_rich_location rich_loc (loc);
|
||||||
|
|
|
@ -179,6 +179,7 @@ private:
|
||||||
engine *m_eng;
|
engine *m_eng;
|
||||||
auto_delete_vec<saved_diagnostic> m_saved_diagnostics;
|
auto_delete_vec<saved_diagnostic> m_saved_diagnostics;
|
||||||
const int m_verbosity;
|
const int m_verbosity;
|
||||||
|
int m_num_disabled_diagnostics;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ana
|
} // namespace ana
|
||||||
|
|
|
@ -1526,10 +1526,15 @@ public:
|
||||||
m_setjmp_point (setjmp_point), m_stack_pop_event (NULL)
|
m_setjmp_point (setjmp_point), m_stack_pop_event (NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_stale_setjmp_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *richloc) FINAL OVERRIDE
|
bool emit (rich_location *richloc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
return warning_at
|
return warning_at
|
||||||
(richloc, OPT_Wanalyzer_stale_setjmp_buffer,
|
(richloc, get_controlling_option (),
|
||||||
"%qs called after enclosing function of %qs has returned",
|
"%qs called after enclosing function of %qs has returned",
|
||||||
get_user_facing_name (m_longjmp_call),
|
get_user_facing_name (m_longjmp_call),
|
||||||
get_user_facing_name (m_setjmp_call));
|
get_user_facing_name (m_setjmp_call));
|
||||||
|
|
|
@ -162,6 +162,12 @@ class pending_diagnostic
|
||||||
public:
|
public:
|
||||||
virtual ~pending_diagnostic () {}
|
virtual ~pending_diagnostic () {}
|
||||||
|
|
||||||
|
/* Vfunc to get the command-line option used when emitting the diagnostic,
|
||||||
|
or zero if there is none.
|
||||||
|
Used by diagnostic_manager for early rejection of diagnostics (to avoid
|
||||||
|
having to generate feasible execution paths for them). */
|
||||||
|
virtual int get_controlling_option () const = 0;
|
||||||
|
|
||||||
/* Vfunc for emitting the diagnostic. The rich_location will have been
|
/* Vfunc for emitting the diagnostic. The rich_location will have been
|
||||||
populated with a diagnostic_path.
|
populated with a diagnostic_path.
|
||||||
Return true if a diagnostic is actually emitted. */
|
Return true if a diagnostic is actually emitted. */
|
||||||
|
|
|
@ -479,6 +479,21 @@ public:
|
||||||
&& m_src_region == other.m_src_region);
|
&& m_src_region == other.m_src_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
switch (m_pkind)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
gcc_unreachable ();
|
||||||
|
case POISON_KIND_UNINIT:
|
||||||
|
return OPT_Wanalyzer_use_of_uninitialized_value;
|
||||||
|
case POISON_KIND_FREED:
|
||||||
|
return OPT_Wanalyzer_use_after_free;
|
||||||
|
case POISON_KIND_POPPED_STACK:
|
||||||
|
return OPT_Wanalyzer_use_of_pointer_in_stale_stack_frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
switch (m_pkind)
|
switch (m_pkind)
|
||||||
|
@ -489,8 +504,7 @@ public:
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
m.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */
|
m.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_use_of_uninitialized_value,
|
|
||||||
"use of uninitialized value %qE",
|
"use of uninitialized value %qE",
|
||||||
m_expr);
|
m_expr);
|
||||||
}
|
}
|
||||||
|
@ -499,8 +513,7 @@ public:
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
m.add_cwe (416); /* "CWE-416: Use After Free". */
|
m.add_cwe (416); /* "CWE-416: Use After Free". */
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_use_after_free,
|
|
||||||
"use after %<free%> of %qE",
|
"use after %<free%> of %qE",
|
||||||
m_expr);
|
m_expr);
|
||||||
}
|
}
|
||||||
|
@ -509,8 +522,7 @@ public:
|
||||||
{
|
{
|
||||||
/* TODO: which CWE? */
|
/* TODO: which CWE? */
|
||||||
return warning_at
|
return warning_at
|
||||||
(rich_loc,
|
(rich_loc, get_controlling_option (),
|
||||||
OPT_Wanalyzer_use_of_pointer_in_stale_stack_frame,
|
|
||||||
"dereferencing pointer %qE to within stale stack frame",
|
"dereferencing pointer %qE to within stale stack frame",
|
||||||
m_expr);
|
m_expr);
|
||||||
}
|
}
|
||||||
|
@ -571,9 +583,14 @@ public:
|
||||||
&& same_tree_p (m_count_cst, other.m_count_cst));
|
&& same_tree_p (m_count_cst, other.m_count_cst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_shift_count_negative;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
return warning_at (rich_loc, OPT_Wanalyzer_shift_count_negative,
|
return warning_at (rich_loc, get_controlling_option (),
|
||||||
"shift by negative count (%qE)", m_count_cst);
|
"shift by negative count (%qE)", m_count_cst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,9 +630,14 @@ public:
|
||||||
&& same_tree_p (m_count_cst, other.m_count_cst));
|
&& same_tree_p (m_count_cst, other.m_count_cst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_shift_count_overflow;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
return warning_at (rich_loc, OPT_Wanalyzer_shift_count_overflow,
|
return warning_at (rich_loc, get_controlling_option (),
|
||||||
"shift by count (%qE) >= precision of type (%qi)",
|
"shift by count (%qE) >= precision of type (%qi)",
|
||||||
m_count_cst, m_operand_precision);
|
m_count_cst, m_operand_precision);
|
||||||
}
|
}
|
||||||
|
@ -1095,6 +1117,11 @@ class dump_path_diagnostic
|
||||||
: public pending_diagnostic_subclass<dump_path_diagnostic>
|
: public pending_diagnostic_subclass<dump_path_diagnostic>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *richloc) FINAL OVERRIDE
|
bool emit (rich_location *richloc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
inform (richloc, "path");
|
inform (richloc, "path");
|
||||||
|
@ -2534,6 +2561,11 @@ public:
|
||||||
&& m_decl == other.m_decl);
|
&& m_decl == other.m_decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_write_to_const;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
auto_diagnostic_group d;
|
auto_diagnostic_group d;
|
||||||
|
@ -2541,15 +2573,15 @@ public:
|
||||||
switch (m_reg->get_kind ())
|
switch (m_reg->get_kind ())
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
warned = warning_at (rich_loc, OPT_Wanalyzer_write_to_const,
|
warned = warning_at (rich_loc, get_controlling_option (),
|
||||||
"write to %<const%> object %qE", m_decl);
|
"write to %<const%> object %qE", m_decl);
|
||||||
break;
|
break;
|
||||||
case RK_FUNCTION:
|
case RK_FUNCTION:
|
||||||
warned = warning_at (rich_loc, OPT_Wanalyzer_write_to_const,
|
warned = warning_at (rich_loc, get_controlling_option (),
|
||||||
"write to function %qE", m_decl);
|
"write to function %qE", m_decl);
|
||||||
break;
|
break;
|
||||||
case RK_LABEL:
|
case RK_LABEL:
|
||||||
warned = warning_at (rich_loc, OPT_Wanalyzer_write_to_const,
|
warned = warning_at (rich_loc, get_controlling_option (),
|
||||||
"write to label %qE", m_decl);
|
"write to label %qE", m_decl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2597,9 +2629,14 @@ public:
|
||||||
return m_reg == other.m_reg;
|
return m_reg == other.m_reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_write_to_string_literal;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
return warning_at (rich_loc, OPT_Wanalyzer_write_to_string_literal,
|
return warning_at (rich_loc, get_controlling_option (),
|
||||||
"write to string literal");
|
"write to string literal");
|
||||||
/* Ideally we would show the location of the STRING_CST as well,
|
/* Ideally we would show the location of the STRING_CST as well,
|
||||||
but it is not available at this point. */
|
but it is not available at this point. */
|
||||||
|
|
|
@ -157,9 +157,14 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "double_fclose"; }
|
const char *get_kind () const FINAL OVERRIDE { return "double_fclose"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_double_fclose;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
return warning_at (rich_loc, OPT_Wanalyzer_double_fclose,
|
return warning_at (rich_loc, get_controlling_option (),
|
||||||
"double %<fclose%> of FILE %qE",
|
"double %<fclose%> of FILE %qE",
|
||||||
m_arg);
|
m_arg);
|
||||||
}
|
}
|
||||||
|
@ -197,6 +202,11 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "file_leak"; }
|
const char *get_kind () const FINAL OVERRIDE { return "file_leak"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_file_leak;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
|
@ -204,11 +214,11 @@ public:
|
||||||
Effective Lifetime". */
|
Effective Lifetime". */
|
||||||
m.add_cwe (775);
|
m.add_cwe (775);
|
||||||
if (m_arg)
|
if (m_arg)
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_file_leak,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"leak of FILE %qE",
|
"leak of FILE %qE",
|
||||||
m_arg);
|
m_arg);
|
||||||
else
|
else
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_file_leak,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"leak of FILE");
|
"leak of FILE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -760,6 +760,11 @@ public:
|
||||||
return "mismatching_deallocation";
|
return "mismatching_deallocation";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_mismatching_deallocation;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
auto_diagnostic_group d;
|
auto_diagnostic_group d;
|
||||||
|
@ -767,13 +772,13 @@ public:
|
||||||
m.add_cwe (762); /* CWE-762: Mismatched Memory Management Routines. */
|
m.add_cwe (762); /* CWE-762: Mismatched Memory Management Routines. */
|
||||||
if (const deallocator *expected_dealloc
|
if (const deallocator *expected_dealloc
|
||||||
= m_expected_deallocators->maybe_get_single ())
|
= m_expected_deallocators->maybe_get_single ())
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_mismatching_deallocation,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"%qE should have been deallocated with %qs"
|
"%qE should have been deallocated with %qs"
|
||||||
" but was deallocated with %qs",
|
" but was deallocated with %qs",
|
||||||
m_arg, expected_dealloc->m_name,
|
m_arg, expected_dealloc->m_name,
|
||||||
m_actual_dealloc->m_name);
|
m_actual_dealloc->m_name);
|
||||||
else
|
else
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_mismatching_deallocation,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"%qs called on %qE returned from a mismatched"
|
"%qs called on %qE returned from a mismatched"
|
||||||
" allocation function",
|
" allocation function",
|
||||||
m_actual_dealloc->m_name, m_arg);
|
m_actual_dealloc->m_name, m_arg);
|
||||||
|
@ -834,12 +839,17 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "double_free"; }
|
const char *get_kind () const FINAL OVERRIDE { return "double_free"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_double_free;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
auto_diagnostic_group d;
|
auto_diagnostic_group d;
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
m.add_cwe (415); /* CWE-415: Double Free. */
|
m.add_cwe (415); /* CWE-415: Double Free. */
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_double_free,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"double-%qs of %qE", m_funcname, m_arg);
|
"double-%qs of %qE", m_funcname, m_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,13 +935,17 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "possible_null_deref"; }
|
const char *get_kind () const FINAL OVERRIDE { return "possible_null_deref"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_possible_null_dereference;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
/* CWE-690: Unchecked Return Value to NULL Pointer Dereference. */
|
/* CWE-690: Unchecked Return Value to NULL Pointer Dereference. */
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
m.add_cwe (690);
|
m.add_cwe (690);
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_possible_null_dereference,
|
|
||||||
"dereference of possibly-NULL %qE", m_arg);
|
"dereference of possibly-NULL %qE", m_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1010,6 +1024,10 @@ public:
|
||||||
&& m_arg_idx == sub_other.m_arg_idx);
|
&& m_arg_idx == sub_other.m_arg_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_possible_null_argument;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
|
@ -1018,7 +1036,7 @@ public:
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
m.add_cwe (690);
|
m.add_cwe (690);
|
||||||
bool warned
|
bool warned
|
||||||
= warning_meta (rich_loc, m, OPT_Wanalyzer_possible_null_argument,
|
= warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of possibly-NULL %qE where non-null expected",
|
"use of possibly-NULL %qE where non-null expected",
|
||||||
m_arg);
|
m_arg);
|
||||||
if (warned)
|
if (warned)
|
||||||
|
@ -1058,13 +1076,17 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "null_deref"; }
|
const char *get_kind () const FINAL OVERRIDE { return "null_deref"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_null_dereference;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
/* CWE-476: NULL Pointer Dereference. */
|
/* CWE-476: NULL Pointer Dereference. */
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
m.add_cwe (476);
|
m.add_cwe (476);
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_null_dereference,
|
|
||||||
"dereference of NULL %qE", m_arg);
|
"dereference of NULL %qE", m_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1106,6 +1128,11 @@ public:
|
||||||
&& m_arg_idx == sub_other.m_arg_idx);
|
&& m_arg_idx == sub_other.m_arg_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_null_argument;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
/* CWE-476: NULL Pointer Dereference. */
|
/* CWE-476: NULL Pointer Dereference. */
|
||||||
|
@ -1115,10 +1142,10 @@ public:
|
||||||
|
|
||||||
bool warned;
|
bool warned;
|
||||||
if (zerop (m_arg))
|
if (zerop (m_arg))
|
||||||
warned = warning_meta (rich_loc, m, OPT_Wanalyzer_null_argument,
|
warned = warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of NULL where non-null expected");
|
"use of NULL where non-null expected");
|
||||||
else
|
else
|
||||||
warned = warning_meta (rich_loc, m, OPT_Wanalyzer_null_argument,
|
warned = warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of NULL %qE where non-null expected",
|
"use of NULL %qE where non-null expected",
|
||||||
m_arg);
|
m_arg);
|
||||||
if (warned)
|
if (warned)
|
||||||
|
@ -1159,12 +1186,17 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "use_after_free"; }
|
const char *get_kind () const FINAL OVERRIDE { return "use_after_free"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_use_after_free;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
/* CWE-416: Use After Free. */
|
/* CWE-416: Use After Free. */
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
m.add_cwe (416);
|
m.add_cwe (416);
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_use_after_free,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use after %<%s%> of %qE",
|
"use after %<%s%> of %qE",
|
||||||
m_deallocator->m_name, m_arg);
|
m_deallocator->m_name, m_arg);
|
||||||
}
|
}
|
||||||
|
@ -1248,15 +1280,20 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "malloc_leak"; }
|
const char *get_kind () const FINAL OVERRIDE { return "malloc_leak"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_malloc_leak;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
m.add_cwe (401);
|
m.add_cwe (401);
|
||||||
if (m_arg)
|
if (m_arg)
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_malloc_leak,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"leak of %qE", m_arg);
|
"leak of %qE", m_arg);
|
||||||
else
|
else
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_malloc_leak,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"leak of %qs", "<unknown>");
|
"leak of %qs", "<unknown>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1316,6 +1353,11 @@ public:
|
||||||
&& m_freed_reg == other.m_freed_reg);
|
&& m_freed_reg == other.m_freed_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_free_of_non_heap;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
auto_diagnostic_group d;
|
auto_diagnostic_group d;
|
||||||
|
@ -1330,13 +1372,13 @@ public:
|
||||||
case MEMSPACE_CODE:
|
case MEMSPACE_CODE:
|
||||||
case MEMSPACE_GLOBALS:
|
case MEMSPACE_GLOBALS:
|
||||||
case MEMSPACE_READONLY_DATA:
|
case MEMSPACE_READONLY_DATA:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_free_of_non_heap,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"%<%s%> of %qE which points to memory"
|
"%<%s%> of %qE which points to memory"
|
||||||
" not on the heap",
|
" not on the heap",
|
||||||
m_funcname, m_arg);
|
m_funcname, m_arg);
|
||||||
break;
|
break;
|
||||||
case MEMSPACE_STACK:
|
case MEMSPACE_STACK:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_free_of_non_heap,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"%<%s%> of %qE which points to memory"
|
"%<%s%> of %qE which points to memory"
|
||||||
" on the stack",
|
" on the stack",
|
||||||
m_funcname, m_arg);
|
m_funcname, m_arg);
|
||||||
|
|
|
@ -89,9 +89,15 @@ public:
|
||||||
&& same_tree_p (m_rhs, other.m_rhs));
|
&& same_tree_p (m_rhs, other.m_rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
return warning_at (rich_loc, 0, "pattern match on %<%E %s %E%>",
|
return warning_at (rich_loc, get_controlling_option (),
|
||||||
|
"pattern match on %<%E %s %E%>",
|
||||||
m_lhs, op_symbol_code (m_op), m_rhs);
|
m_lhs, op_symbol_code (m_op), m_rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,13 +91,17 @@ public:
|
||||||
return same_tree_p (m_arg, other.m_arg);
|
return same_tree_p (m_arg, other.m_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_exposure_through_output_file;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
/* CWE-532: Information Exposure Through Log Files */
|
/* CWE-532: Information Exposure Through Log Files */
|
||||||
m.add_cwe (532);
|
m.add_cwe (532);
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_exposure_through_output_file,
|
|
||||||
"sensitive value %qE written to output file",
|
"sensitive value %qE written to output file",
|
||||||
m_arg);
|
m_arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,14 +113,18 @@ public:
|
||||||
return m_unsafe_call == other.m_unsafe_call;
|
return m_unsafe_call == other.m_unsafe_call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_unsafe_call_within_signal_handler;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
auto_diagnostic_group d;
|
auto_diagnostic_group d;
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
/* CWE-479: Signal Handler Use of a Non-reentrant Function. */
|
/* CWE-479: Signal Handler Use of a Non-reentrant Function. */
|
||||||
m.add_cwe (479);
|
m.add_cwe (479);
|
||||||
if (warning_meta (rich_loc, m,
|
if (warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_unsafe_call_within_signal_handler,
|
|
||||||
"call to %qD from within signal handler",
|
"call to %qD from within signal handler",
|
||||||
m_unsafe_fndecl))
|
m_unsafe_fndecl))
|
||||||
{
|
{
|
||||||
|
|
|
@ -180,6 +180,11 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "tainted_array_index"; }
|
const char *get_kind () const FINAL OVERRIDE { return "tainted_array_index"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_tainted_array_index;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
|
@ -190,19 +195,19 @@ public:
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
case BOUNDS_NONE:
|
case BOUNDS_NONE:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_array_index,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE"
|
"use of attacker-controlled value %qE"
|
||||||
" in array lookup without bounds checking",
|
" in array lookup without bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
break;
|
break;
|
||||||
case BOUNDS_UPPER:
|
case BOUNDS_UPPER:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_array_index,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE"
|
"use of attacker-controlled value %qE"
|
||||||
" in array lookup without checking for negative",
|
" in array lookup without checking for negative",
|
||||||
m_arg);
|
m_arg);
|
||||||
break;
|
break;
|
||||||
case BOUNDS_LOWER:
|
case BOUNDS_LOWER:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_array_index,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE"
|
"use of attacker-controlled value %qE"
|
||||||
" in array lookup without upper-bounds checking",
|
" in array lookup without upper-bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
|
@ -248,6 +253,11 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "tainted_offset"; }
|
const char *get_kind () const FINAL OVERRIDE { return "tainted_offset"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_tainted_offset;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
|
@ -259,19 +269,19 @@ public:
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
case BOUNDS_NONE:
|
case BOUNDS_NONE:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_offset,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE as offset"
|
"use of attacker-controlled value %qE as offset"
|
||||||
" without bounds checking",
|
" without bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
break;
|
break;
|
||||||
case BOUNDS_UPPER:
|
case BOUNDS_UPPER:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_offset,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE as offset"
|
"use of attacker-controlled value %qE as offset"
|
||||||
" without lower-bounds checking",
|
" without lower-bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
break;
|
break;
|
||||||
case BOUNDS_LOWER:
|
case BOUNDS_LOWER:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_offset,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE as offset"
|
"use of attacker-controlled value %qE as offset"
|
||||||
" without upper-bounds checking",
|
" without upper-bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
|
@ -283,17 +293,17 @@ public:
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
case BOUNDS_NONE:
|
case BOUNDS_NONE:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_offset,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value as offset"
|
"use of attacker-controlled value as offset"
|
||||||
" without bounds checking");
|
" without bounds checking");
|
||||||
break;
|
break;
|
||||||
case BOUNDS_UPPER:
|
case BOUNDS_UPPER:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_offset,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value as offset"
|
"use of attacker-controlled value as offset"
|
||||||
" without lower-bounds checking");
|
" without lower-bounds checking");
|
||||||
break;
|
break;
|
||||||
case BOUNDS_LOWER:
|
case BOUNDS_LOWER:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_offset,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value as offset"
|
"use of attacker-controlled value as offset"
|
||||||
" without upper-bounds checking");
|
" without upper-bounds checking");
|
||||||
break;
|
break;
|
||||||
|
@ -353,6 +363,11 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const OVERRIDE { return "tainted_size"; }
|
const char *get_kind () const OVERRIDE { return "tainted_size"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_tainted_size;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) OVERRIDE
|
bool emit (rich_location *rich_loc) OVERRIDE
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
|
@ -362,19 +377,19 @@ public:
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
case BOUNDS_NONE:
|
case BOUNDS_NONE:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_size,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE as size"
|
"use of attacker-controlled value %qE as size"
|
||||||
" without bounds checking",
|
" without bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
break;
|
break;
|
||||||
case BOUNDS_UPPER:
|
case BOUNDS_UPPER:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_size,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE as size"
|
"use of attacker-controlled value %qE as size"
|
||||||
" without lower-bounds checking",
|
" without lower-bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
break;
|
break;
|
||||||
case BOUNDS_LOWER:
|
case BOUNDS_LOWER:
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_size,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE as size"
|
"use of attacker-controlled value %qE as size"
|
||||||
" without upper-bounds checking",
|
" without upper-bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
|
@ -455,18 +470,23 @@ public:
|
||||||
|
|
||||||
const char *get_kind () const FINAL OVERRIDE { return "tainted_divisor"; }
|
const char *get_kind () const FINAL OVERRIDE { return "tainted_divisor"; }
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_tainted_divisor;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
/* CWE-369: "Divide By Zero". */
|
/* CWE-369: "Divide By Zero". */
|
||||||
m.add_cwe (369);
|
m.add_cwe (369);
|
||||||
if (m_arg)
|
if (m_arg)
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_divisor,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value %qE as divisor"
|
"use of attacker-controlled value %qE as divisor"
|
||||||
" without checking for zero",
|
" without checking for zero",
|
||||||
m_arg);
|
m_arg);
|
||||||
else
|
else
|
||||||
return warning_meta (rich_loc, m, OPT_Wanalyzer_tainted_divisor,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
"use of attacker-controlled value as divisor"
|
"use of attacker-controlled value as divisor"
|
||||||
" without checking for zero");
|
" without checking for zero");
|
||||||
}
|
}
|
||||||
|
@ -503,6 +523,11 @@ public:
|
||||||
return "tainted_allocation_size";
|
return "tainted_allocation_size";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return OPT_Wanalyzer_tainted_allocation_size;
|
||||||
|
}
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
diagnostic_metadata m;
|
diagnostic_metadata m;
|
||||||
|
@ -515,22 +540,19 @@ public:
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
case BOUNDS_NONE:
|
case BOUNDS_NONE:
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_tainted_allocation_size,
|
|
||||||
"use of attacker-controlled value %qE as"
|
"use of attacker-controlled value %qE as"
|
||||||
" allocation size without bounds checking",
|
" allocation size without bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
break;
|
break;
|
||||||
case BOUNDS_UPPER:
|
case BOUNDS_UPPER:
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_tainted_allocation_size,
|
|
||||||
"use of attacker-controlled value %qE as"
|
"use of attacker-controlled value %qE as"
|
||||||
" allocation size without lower-bounds checking",
|
" allocation size without lower-bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
break;
|
break;
|
||||||
case BOUNDS_LOWER:
|
case BOUNDS_LOWER:
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_tainted_allocation_size,
|
|
||||||
"use of attacker-controlled value %qE as"
|
"use of attacker-controlled value %qE as"
|
||||||
" allocation size without upper-bounds checking",
|
" allocation size without upper-bounds checking",
|
||||||
m_arg);
|
m_arg);
|
||||||
|
@ -542,22 +564,19 @@ public:
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
case BOUNDS_NONE:
|
case BOUNDS_NONE:
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_tainted_allocation_size,
|
|
||||||
"use of attacker-controlled value as"
|
"use of attacker-controlled value as"
|
||||||
" allocation size without bounds"
|
" allocation size without bounds"
|
||||||
" checking");
|
" checking");
|
||||||
break;
|
break;
|
||||||
case BOUNDS_UPPER:
|
case BOUNDS_UPPER:
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_tainted_allocation_size,
|
|
||||||
"use of attacker-controlled value as"
|
"use of attacker-controlled value as"
|
||||||
" allocation size without lower-bounds"
|
" allocation size without lower-bounds"
|
||||||
" checking");
|
" checking");
|
||||||
break;
|
break;
|
||||||
case BOUNDS_LOWER:
|
case BOUNDS_LOWER:
|
||||||
return warning_meta (rich_loc, m,
|
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||||
OPT_Wanalyzer_tainted_allocation_size,
|
|
||||||
"use of attacker-controlled value as"
|
"use of attacker-controlled value as"
|
||||||
" allocation size without upper-bounds"
|
" allocation size without upper-bounds"
|
||||||
" checking");
|
" checking");
|
||||||
|
|
55
gcc/testsuite/gcc.dg/analyzer/many-disabled-diagnostics.c
Normal file
55
gcc/testsuite/gcc.dg/analyzer/many-disabled-diagnostics.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/* { dg-additional-options "-Wno-analyzer-double-free" } */
|
||||||
|
|
||||||
|
#define DOUBLE_FREE() \
|
||||||
|
do { \
|
||||||
|
void *p = __builtin_malloc (1024); \
|
||||||
|
__builtin_free (p); \
|
||||||
|
__builtin_free (p); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DOUBLE_FREE_x_10() \
|
||||||
|
do { \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
DOUBLE_FREE(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DOUBLE_FREE_x_100() \
|
||||||
|
do { \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
DOUBLE_FREE_x_10(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DOUBLE_FREE_x_1000() \
|
||||||
|
do { \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
DOUBLE_FREE_x_100(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
void test_1 (void)
|
||||||
|
{
|
||||||
|
DOUBLE_FREE_x_1000 ();
|
||||||
|
}
|
|
@ -81,6 +81,12 @@ public:
|
||||||
class gil_diagnostic : public pending_diagnostic
|
class gil_diagnostic : public pending_diagnostic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/* There isn't a warning ID for us to use. */
|
||||||
|
int get_controlling_option () const FINAL OVERRIDE
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
location_t fixup_location (location_t loc) const FINAL OVERRIDE
|
location_t fixup_location (location_t loc) const FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
/* Ideally we'd check for specific macros here, and only
|
/* Ideally we'd check for specific macros here, and only
|
||||||
|
@ -133,7 +139,7 @@ class double_save_thread : public gil_diagnostic
|
||||||
|
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
return warning_at (rich_loc, 0,
|
return warning_at (rich_loc, get_controlling_option (),
|
||||||
"nested usage of %qs", "Py_BEGIN_ALLOW_THREADS");
|
"nested usage of %qs", "Py_BEGIN_ALLOW_THREADS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,14 +179,13 @@ class fncall_without_gil : public gil_diagnostic
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
auto_diagnostic_group d;
|
auto_diagnostic_group d;
|
||||||
/* There isn't a warning ID for use to use. */
|
|
||||||
if (m_callee_fndecl)
|
if (m_callee_fndecl)
|
||||||
return warning_at (rich_loc, 0,
|
return warning_at (rich_loc, get_controlling_option (),
|
||||||
"use of PyObject as argument %i of %qE"
|
"use of PyObject as argument %i of %qE"
|
||||||
" without the GIL",
|
" without the GIL",
|
||||||
m_arg_idx + 1, m_callee_fndecl);
|
m_arg_idx + 1, m_callee_fndecl);
|
||||||
else
|
else
|
||||||
return warning_at (rich_loc, 0,
|
return warning_at (rich_loc, get_controlling_option (),
|
||||||
"use of PyObject as argument %i of call"
|
"use of PyObject as argument %i of call"
|
||||||
" without the GIL",
|
" without the GIL",
|
||||||
m_arg_idx + 1, m_callee_fndecl);
|
m_arg_idx + 1, m_callee_fndecl);
|
||||||
|
@ -225,8 +230,7 @@ class pyobject_usage_without_gil : public gil_diagnostic
|
||||||
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
bool emit (rich_location *rich_loc) FINAL OVERRIDE
|
||||||
{
|
{
|
||||||
auto_diagnostic_group d;
|
auto_diagnostic_group d;
|
||||||
/* There isn't a warning ID for use to use. */
|
return warning_at (rich_loc, get_controlling_option (),
|
||||||
return warning_at (rich_loc, 0,
|
|
||||||
"use of PyObject %qE without the GIL", m_expr);
|
"use of PyObject %qE without the GIL", m_expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue