Common Var(warn_analyzer_deref_before_check) Init(1) Warning
Warn about code paths in which a pointer is checked for NULL after it has already been dereferenced.
+Wanalyzer-div-by-zero
+Common Var(warn_analyzer_div_by_zero) Init(1) Warning
+Warn about code paths which attempt integer division by zero.
+
Wanalyzer-double-fclose
Common Var(warn_analyzer_double_fclose) Init(1) Warning
Warn about code paths in which a stdio FILE can be closed more than once.
Wanalyzer-deref-before-check
UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-deref-before-check)
+Wanalyzer-div-by-zero
+UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-div-by-zero)
+
Wanalyzer-double-fclose
UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-double-fclose)
const region *m_base_reg_b;
};
+class div_by_zero_diagnostic
+: public pending_diagnostic_subclass<div_by_zero_diagnostic>
+{
+public:
+ div_by_zero_diagnostic (const gassign *assign)
+ : m_assign (assign)
+ {}
+
+ const char *get_kind () const final override
+ {
+ return "div_by_zero_diagnostic";
+ }
+
+ bool operator== (const div_by_zero_diagnostic &other) const
+ {
+ return m_assign == other.m_assign;
+ }
+
+ int get_controlling_option () const final override
+ {
+ return OPT_Wanalyzer_div_by_zero;
+ }
+
+ bool emit (diagnostic_emission_context &ctxt) final override
+ {
+ return ctxt.warn ("division by zero");
+ }
+
+ bool
+ describe_final_event (pretty_printer &pp,
+ const evdesc::final_event &) final override
+ {
+ pp_printf (&pp, "division by zero");
+ return true;
+ }
+
+private:
+ const gassign *m_assign;
+};
+
/* Check the pointer subtraction SVAL_A - SVAL_B at ASSIGN and add
a warning to CTXT if they're not within the same base region. */
}
}
- if (ctxt
- && (op == TRUNC_DIV_EXPR
- || op == CEIL_DIV_EXPR
- || op == FLOOR_DIV_EXPR
- || op == ROUND_DIV_EXPR
- || op == TRUNC_MOD_EXPR
- || op == CEIL_MOD_EXPR
- || op == FLOOR_MOD_EXPR
- || op == ROUND_MOD_EXPR
- || op == RDIV_EXPR
- || op == EXACT_DIV_EXPR))
+ if (op == TRUNC_DIV_EXPR
+ || op == CEIL_DIV_EXPR
+ || op == FLOOR_DIV_EXPR
+ || op == ROUND_DIV_EXPR
+ || op == TRUNC_MOD_EXPR
+ || op == CEIL_MOD_EXPR
+ || op == FLOOR_MOD_EXPR
+ || op == ROUND_MOD_EXPR
+ || op == RDIV_EXPR
+ || op == EXACT_DIV_EXPR)
{
value_range rhs_vr;
if (rhs2_sval->maybe_get_value_range (rhs_vr))
if (rhs_vr.zero_p ())
{
- /* Ideally we should issue a warning here;
- see PR analyzer/124217. */
+ if (ctxt)
+ {
+ ctxt->warn
+ (std::make_unique<div_by_zero_diagnostic> (assign));
+ ctxt->terminate_path ();
+ }
return nullptr;
}
}
{
if (!type)
return false;
- if (!irange::supports_p (type))
- return false;
- return true;
+ if (irange::supports_p (type))
+ return true;
+ if (frange::supports_p (type))
+ return true;
+ return false;
}
/* Base implementation of svalue::maybe_get_value_range_1 vfunc.
@gccoptlist{
-Wanalyzer-allocation-size
-Wanalyzer-deref-before-check
+-Wanalyzer-div-by-zero
-Wanalyzer-double-fclose
-Wanalyzer-double-free
-Wanalyzer-exposure-through-output-file
See @uref{https://cwe.mitre.org/data/definitions/131.html, CWE-131: Incorrect Calculation of Buffer Size}.
+@opindex Wanalyzer-div-by-zero
+@opindex Wno-analyzer-div-by-zero
+@item -Wno-analyzer-div-by-zero
+This warning requires @option{-fanalyzer}, which enables it;
+to disable it, use @option{-Wno-analyzer-div-by-zero}.
+
+This diagnostic warns for paths through the code which attempt
+integer division by zero. It is analogous to @option{-Wdiv-by-zero}, but
+implemented in a different way.
+
+See @uref{https://cwe.mitre.org/data/definitions/369.html, CWE-369: Divide By Zero}.
+
@opindex Wanalyzer-deref-before-check
@opindex Wno-analyzer-deref-before-check
@item -Wno-analyzer-deref-before-check
void
test_div (int a)
{
- __analyzer_eval (a / return_zero () == 0); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (a / return_zero () == 0); /* { dg-warning "division by zero \\\[-Wanalyzer-div-by-zero\\\]" } */
}
void
test_mod (int a)
{
- __analyzer_eval (a % return_zero () == 0); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (a % return_zero () == 0); /* { dg-warning "division by zero \\\[-Wanalyzer-div-by-zero\\\]" } */
}
int
foo()
{
- s %= 0; /* { dg-warning "division by zero" } */
+ s %= 0; /* { dg-warning "division by zero \\\[-Wdiv-by-zero\\\]" } */
+ /* { dg-warning "division by zero \\\[-Wanalyzer-div-by-zero\\\]" "" { target *-*-* } .-1 } */
return s > 0;
}
__analyzer_eval (i / j == 1); /* { dg-warning "TRUE" } */
__analyzer_eval (i % j == 2); /* { dg-warning "TRUE" } */
- /* Division by zero. */
- // TODO: should we warn for this?
- __analyzer_eval (i / zero); /* { dg-warning "UNKNOWN" } */
- __analyzer_eval (i % zero); /* { dg-warning "UNKNOWN" } */
-
__analyzer_eval ((i & 1) == (5 & 1)); /* { dg-warning "TRUE" } */
__analyzer_eval ((i & j) == (5 & 3)); /* { dg-warning "TRUE" } */
__analyzer_eval ((i | 1) == (5 | 1)); /* { dg-warning "TRUE" } */
__analyzer_eval (+i == +5); /* { dg-warning "TRUE" } */
}
+void test_21_division_by_zero (void)
+{
+ int i, zero;
+ int *pi = &i;
+ int *pzero = &zero;
+ *pi = 5;
+ *pzero = 0;
+
+ __analyzer_eval (i / zero); /* { dg-warning "Wanalyzer-div-by-zero" } */
+}
+
+void test_21_modulus_by_zero (void)
+{
+ int i, zero;
+ int *pi = &i;
+ int *pzero = &zero;
+ *pi = 5;
+ *pzero = 0;
+
+ __analyzer_eval (i % zero); /* { dg-warning "Wanalyzer-div-by-zero" } */
+}
+
void test_22 (int i, int j)
{
__analyzer_eval (i + j == i + j); /* { dg-warning "TRUE" } */
--- /dev/null
+float
+test_1 ()
+{
+ return 42.f / 0.f; /* { dg-warning "division by zero \\\[-Wanalyzer-div-by-zero\\\]" } */
+}
+
+static float __attribute__((noinline))
+get_zero ()
+{
+ return 0.f;
+}
+
+float
+test_2 ()
+{
+ return 42.f / get_zero (); /* { dg-warning "division by zero \\\[-Wanalyzer-div-by-zero\\\]" } */
+}
+
+float
+test_3 (float x)
+{
+ return x / get_zero (); /* { dg-warning "division by zero \\\[-Wanalyzer-div-by-zero\\\]" } */
+}
void
foo()
{
- do c %= (5ull << 40) & m;
+ do c %= (5ull << 40) & m; /* { dg-warning "division by zero \\\[-Wanalyzer-div-by-zero\\\]" } */
while (c);
}
int
foo()
{
- s %= (0, 0);
+ s %= (0, 0); /* { dg-warning "division by zero \\\[-Wanalyzer-div-by-zero\\\]" } */
return s > 0;
}