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. */
/* diagnostic_manager's ctor. */
diagnostic_manager::diagnostic_manager (logger *logger, engine *eng,
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)
{
}
through the exploded_graph to the diagnostic. */
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
= new saved_diagnostic (sm, enode, snode, stmt, finder, var, sval,
state, d, m_saved_diagnostics.length ());
LOG_SCOPE (get_logger ());
auto_timevar tv (TV_ANALYZER_DIAGNOSTICS);
log ("# saved diagnostics: %i", m_saved_diagnostics.length ());
+ log ("# disabled diagnostics: %i", m_num_disabled_diagnostics);
if (get_logger ())
{
unsigned i;
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
- and any locations for events. */
- loc = sd.m_d->fixup_location (loc);
+ /* Allow the pending_diagnostic to fix up the locations of events. */
emission_path.fixup_locations (sd.m_d);
gcc_rich_location rich_loc (loc);
engine *m_eng;
auto_delete_vec<saved_diagnostic> m_saved_diagnostics;
const int m_verbosity;
+ int m_num_disabled_diagnostics;
};
} // namespace ana
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
{
return warning_at
- (richloc, OPT_Wanalyzer_stale_setjmp_buffer,
+ (richloc, get_controlling_option (),
"%qs called after enclosing function of %qs has returned",
get_user_facing_name (m_longjmp_call),
get_user_facing_name (m_setjmp_call));
public:
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
populated with a diagnostic_path.
Return true if a diagnostic is actually emitted. */
&& 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
{
switch (m_pkind)
{
diagnostic_metadata m;
m.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable". */
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_use_of_uninitialized_value,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"use of uninitialized value %qE",
m_expr);
}
{
diagnostic_metadata m;
m.add_cwe (416); /* "CWE-416: Use After Free". */
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_use_after_free,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"use after %<free%> of %qE",
m_expr);
}
{
/* TODO: which CWE? */
return warning_at
- (rich_loc,
- OPT_Wanalyzer_use_of_pointer_in_stale_stack_frame,
+ (rich_loc, get_controlling_option (),
"dereferencing pointer %qE to within stale stack frame",
m_expr);
}
&& 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
{
- 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);
}
&& 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
{
- 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)",
m_count_cst, m_operand_precision);
}
: public pending_diagnostic_subclass<dump_path_diagnostic>
{
public:
+ int get_controlling_option () const FINAL OVERRIDE
+ {
+ return 0;
+ }
+
bool emit (rich_location *richloc) FINAL OVERRIDE
{
inform (richloc, "path");
&& 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
{
auto_diagnostic_group d;
switch (m_reg->get_kind ())
{
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);
break;
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);
break;
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);
break;
}
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
{
- return warning_at (rich_loc, OPT_Wanalyzer_write_to_string_literal,
+ return warning_at (rich_loc, get_controlling_option (),
"write to string literal");
/* Ideally we would show the location of the STRING_CST as well,
but it is not available at this point. */
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
{
- return warning_at (rich_loc, OPT_Wanalyzer_double_fclose,
+ return warning_at (rich_loc, get_controlling_option (),
"double %<fclose%> of FILE %qE",
m_arg);
}
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
{
diagnostic_metadata m;
Effective Lifetime". */
m.add_cwe (775);
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",
m_arg);
else
- return warning_meta (rich_loc, m, OPT_Wanalyzer_file_leak,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"leak of FILE");
}
return "mismatching_deallocation";
}
+ int get_controlling_option () const FINAL OVERRIDE
+ {
+ return OPT_Wanalyzer_mismatching_deallocation;
+ }
+
bool emit (rich_location *rich_loc) FINAL OVERRIDE
{
auto_diagnostic_group d;
m.add_cwe (762); /* CWE-762: Mismatched Memory Management Routines. */
if (const deallocator *expected_dealloc
= 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"
" but was deallocated with %qs",
m_arg, expected_dealloc->m_name,
m_actual_dealloc->m_name);
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"
" allocation function",
m_actual_dealloc->m_name, m_arg);
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
{
auto_diagnostic_group d;
diagnostic_metadata m;
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);
}
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
{
/* CWE-690: Unchecked Return Value to NULL Pointer Dereference. */
diagnostic_metadata m;
m.add_cwe (690);
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_possible_null_dereference,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"dereference of possibly-NULL %qE", m_arg);
}
&& 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
{
diagnostic_metadata m;
m.add_cwe (690);
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",
m_arg);
if (warned)
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
{
/* CWE-476: NULL Pointer Dereference. */
diagnostic_metadata m;
m.add_cwe (476);
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_null_dereference,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"dereference of NULL %qE", m_arg);
}
&& 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
{
/* CWE-476: NULL Pointer Dereference. */
bool warned;
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");
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",
m_arg);
if (warned)
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
{
/* CWE-416: Use After Free. */
diagnostic_metadata m;
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",
m_deallocator->m_name, m_arg);
}
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
{
diagnostic_metadata m;
m.add_cwe (401);
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);
else
- return warning_meta (rich_loc, m, OPT_Wanalyzer_malloc_leak,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"leak of %qs", "<unknown>");
}
&& 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
{
auto_diagnostic_group d;
case MEMSPACE_CODE:
case MEMSPACE_GLOBALS:
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"
" not on the heap",
m_funcname, m_arg);
break;
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"
" on the stack",
m_funcname, m_arg);
&& 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
{
- 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);
}
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
{
diagnostic_metadata m;
/* CWE-532: Information Exposure Through Log Files */
m.add_cwe (532);
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_exposure_through_output_file,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"sensitive value %qE written to output file",
m_arg);
}
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
{
auto_diagnostic_group d;
diagnostic_metadata m;
/* CWE-479: Signal Handler Use of a Non-reentrant Function. */
m.add_cwe (479);
- if (warning_meta (rich_loc, m,
- OPT_Wanalyzer_unsafe_call_within_signal_handler,
+ if (warning_meta (rich_loc, m, get_controlling_option (),
"call to %qD from within signal handler",
m_unsafe_fndecl))
{
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
{
diagnostic_metadata m;
default:
gcc_unreachable ();
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"
" in array lookup without bounds checking",
m_arg);
break;
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"
" in array lookup without checking for negative",
m_arg);
break;
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"
" in array lookup without upper-bounds checking",
m_arg);
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
{
diagnostic_metadata m;
default:
gcc_unreachable ();
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"
" without bounds checking",
m_arg);
break;
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"
" without lower-bounds checking",
m_arg);
break;
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"
" without upper-bounds checking",
m_arg);
default:
gcc_unreachable ();
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"
" without bounds checking");
break;
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"
" without lower-bounds checking");
break;
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"
" without upper-bounds checking");
break;
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
{
diagnostic_metadata m;
default:
gcc_unreachable ();
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"
" without bounds checking",
m_arg);
break;
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"
" without lower-bounds checking",
m_arg);
break;
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"
" without upper-bounds checking",
m_arg);
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
{
diagnostic_metadata m;
/* CWE-369: "Divide By Zero". */
m.add_cwe (369);
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"
" without checking for zero",
m_arg);
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"
" without checking for zero");
}
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
{
diagnostic_metadata m;
default:
gcc_unreachable ();
case BOUNDS_NONE:
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_tainted_allocation_size,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"use of attacker-controlled value %qE as"
" allocation size without bounds checking",
m_arg);
break;
case BOUNDS_UPPER:
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_tainted_allocation_size,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"use of attacker-controlled value %qE as"
" allocation size without lower-bounds checking",
m_arg);
break;
case BOUNDS_LOWER:
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_tainted_allocation_size,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"use of attacker-controlled value %qE as"
" allocation size without upper-bounds checking",
m_arg);
default:
gcc_unreachable ();
case BOUNDS_NONE:
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_tainted_allocation_size,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"use of attacker-controlled value as"
" allocation size without bounds"
" checking");
break;
case BOUNDS_UPPER:
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_tainted_allocation_size,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"use of attacker-controlled value as"
" allocation size without lower-bounds"
" checking");
break;
case BOUNDS_LOWER:
- return warning_meta (rich_loc, m,
- OPT_Wanalyzer_tainted_allocation_size,
+ return warning_meta (rich_loc, m, get_controlling_option (),
"use of attacker-controlled value as"
" allocation size without upper-bounds"
" checking");
--- /dev/null
+/* { 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 ();
+}
class gil_diagnostic : public pending_diagnostic
{
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
{
/* Ideally we'd check for specific macros here, and only
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");
}
bool emit (rich_location *rich_loc) FINAL OVERRIDE
{
auto_diagnostic_group d;
- /* There isn't a warning ID for use to use. */
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"
" without the GIL",
m_arg_idx + 1, m_callee_fndecl);
else
- return warning_at (rich_loc, 0,
+ return warning_at (rich_loc, get_controlling_option (),
"use of PyObject as argument %i of call"
" without the GIL",
m_arg_idx + 1, m_callee_fndecl);
bool emit (rich_location *rich_loc) FINAL OVERRIDE
{
auto_diagnostic_group d;
- /* There isn't a warning ID for use to use. */
- return warning_at (rich_loc, 0,
+ return warning_at (rich_loc, get_controlling_option (),
"use of PyObject %qE without the GIL", m_expr);
}