mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 12:41:09 +08:00
re PR sanitizer/63956 ([UBSAN] ICE segfault in cxx_eval_call_expression ../../gcc/cp/constexpr.c)
PR sanitizer/63956 * ubsan.c (is_ubsan_builtin_p): Check also built-in class. cp/ * constexpr.c: Include ubsan.h. (cxx_eval_call_expression): Bail out for IFN_UBSAN_{NULL,BOUNDS} internal functions and for ubsan builtins. * error.c: Include internal-fn.h. (dump_expr): Add printing of internal functions. testsuite/ * c-c++-common/ubsan/shift-5.c: Add xfails. * g++.dg/ubsan/div-by-zero-1.C: Don't use -w. Add xfail. * g++.dg/ubsan/pr63956.C: New test. From-SVN: r218221
This commit is contained in:
parent
e42c407c8a
commit
0b274c179f
@ -1,3 +1,8 @@
|
||||
2014-12-01 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR sanitizer/63956
|
||||
* ubsan.c (is_ubsan_builtin_p): Check also built-in class.
|
||||
|
||||
2014-12-01 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gimple.h (gimple_build_assign_stat): Remove prototype.
|
||||
|
@ -1,3 +1,12 @@
|
||||
2014-12-01 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR sanitizer/63956
|
||||
* constexpr.c: Include ubsan.h.
|
||||
(cxx_eval_call_expression): Bail out for IFN_UBSAN_{NULL,BOUNDS}
|
||||
internal functions and for ubsan builtins.
|
||||
* error.c: Include internal-fn.h.
|
||||
(dump_expr): Add printing of internal functions.
|
||||
|
||||
2014-12-01 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
* constexpr.c (literal_type_p): Return true for void type in C++14.
|
||||
|
@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "gimplify.h"
|
||||
#include "builtins.h"
|
||||
#include "tree-inline.h"
|
||||
#include "ubsan.h"
|
||||
|
||||
static bool verify_constant (tree, bool, bool *, bool *);
|
||||
#define VERIFY_CONSTANT(X) \
|
||||
@ -1152,6 +1153,19 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||
constexpr_call *entry;
|
||||
bool depth_ok;
|
||||
|
||||
if (fun == NULL_TREE)
|
||||
switch (CALL_EXPR_IFN (t))
|
||||
{
|
||||
case IFN_UBSAN_NULL:
|
||||
case IFN_UBSAN_BOUNDS:
|
||||
return void_node;
|
||||
default:
|
||||
if (!ctx->quiet)
|
||||
error_at (loc, "call to internal function");
|
||||
*non_constant_p = true;
|
||||
return t;
|
||||
}
|
||||
|
||||
if (TREE_CODE (fun) != FUNCTION_DECL)
|
||||
{
|
||||
/* Might be a constexpr function pointer. */
|
||||
@ -1172,6 +1186,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||
}
|
||||
if (DECL_CLONED_FUNCTION_P (fun))
|
||||
fun = DECL_CLONED_FUNCTION (fun);
|
||||
|
||||
if (is_ubsan_builtin_p (fun))
|
||||
return void_node;
|
||||
|
||||
if (is_builtin_fn (fun))
|
||||
return cxx_eval_builtin_function_call (ctx, t,
|
||||
addr, non_constant_p, overflow_p);
|
||||
|
@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "tree-pretty-print.h"
|
||||
#include "c-family/c-objc.h"
|
||||
#include "ubsan.h"
|
||||
#include "internal-fn.h"
|
||||
|
||||
#include <new> // For placement-new.
|
||||
|
||||
@ -2039,6 +2040,14 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
|
||||
tree fn = CALL_EXPR_FN (t);
|
||||
bool skipfirst = false;
|
||||
|
||||
/* Deal with internal functions. */
|
||||
if (fn == NULL_TREE)
|
||||
{
|
||||
pp_string (pp, internal_fn_name (CALL_EXPR_IFN (t)));
|
||||
dump_call_expr_args (pp, t, flags, skipfirst);
|
||||
break;
|
||||
}
|
||||
|
||||
if (TREE_CODE (fn) == ADDR_EXPR)
|
||||
fn = TREE_OPERAND (fn, 0);
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
2014-12-01 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR sanitizer/63956
|
||||
* c-c++-common/ubsan/shift-5.c: Add xfails.
|
||||
* g++.dg/ubsan/div-by-zero-1.C: Don't use -w. Add xfail.
|
||||
* g++.dg/ubsan/pr63956.C: New test.
|
||||
|
||||
2014-12-01 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/constexpr-function2.C: Limit dg-error to C++11.
|
||||
|
@ -2,31 +2,41 @@
|
||||
/* { dg-options "-fsanitize=shift -w" } */
|
||||
/* { dg-shouldfail "ubsan" } */
|
||||
|
||||
int x;
|
||||
int
|
||||
foo (void)
|
||||
foo (int x)
|
||||
{
|
||||
/* None of the following should pass. */
|
||||
switch (x)
|
||||
{
|
||||
case 1 >> -1:
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" {target c } 12 } */
|
||||
/* { dg-error "is not a constant expression" "" { target c++ } 12 } */
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" { target c } 11 } */
|
||||
/* { dg-error "is not a constant expression" "" { xfail { *-*-* } } 11 } */
|
||||
case -1 >> -1:
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" {target c } 15 } */
|
||||
/* { dg-error "is not a constant expression" "" { target c++ } 15 } */
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" { target c } 14 } */
|
||||
/* { dg-error "is not a constant expression" "" { xfail { *-*-* } } 14 } */
|
||||
case 1 << -1:
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" {target c } 18 } */
|
||||
/* { dg-error "is not a constant expression" "" { target c++ } 18 } */
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" { target c } 17 } */
|
||||
/* { dg-error "is not a constant expression" "" { xfail { *-*-* } } 17 } */
|
||||
case -1 << -1:
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" {target c } 21 } */
|
||||
/* { dg-error "is not a constant expression" "" { target c++ } 21 } */
|
||||
case -1 >> 200:
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" {target c } 24 } */
|
||||
/* { dg-error "is not a constant expression" "" { target c++ } 24 } */
|
||||
case 1 << 200:
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" {target c } 27 } */
|
||||
/* { dg-error "is not a constant expression" "" { target c++ } 27 } */
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" { target c } 20 } */
|
||||
/* { dg-error "is not a constant expression" "" { xfail { *-*-* } } 20 } */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bar (int x)
|
||||
{
|
||||
/* None of the following should pass. */
|
||||
switch (x)
|
||||
{
|
||||
case -1 >> 200:
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" { target c } 34 } */
|
||||
/* { dg-error "is not a constant expression" "" { xfail { *-*-* } } 34 } */
|
||||
case 1 << 200:
|
||||
/* { dg-error "case label does not reduce to an integer constant" "" { target c } 37 } */
|
||||
/* { dg-error "is not a constant expression" "" { xfail { *-*-* } } 37 } */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1,10 +1,14 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-fsanitize=integer-divide-by-zero -w" } */
|
||||
/* { dg-options "-fsanitize=integer-divide-by-zero" } */
|
||||
|
||||
/* TODO: We expect an error on the invalid case here, because that
|
||||
must be a constant-expression. This will be fixed when we have
|
||||
proper delayed folding. */
|
||||
|
||||
void
|
||||
foo (int i)
|
||||
{
|
||||
switch (i)
|
||||
case 0 * (1 / 0): /* { dg-error "is not a constant expression" } */
|
||||
;
|
||||
case 0 * (1 / 0): /* { dg-warning "division by zero" } */
|
||||
; /* { dg-error "division by zero" "" { xfail *-*-* } 10 } */
|
||||
}
|
||||
|
172
gcc/testsuite/g++.dg/ubsan/pr63956.C
Normal file
172
gcc/testsuite/g++.dg/ubsan/pr63956.C
Normal file
@ -0,0 +1,172 @@
|
||||
// PR sanitizer/63956
|
||||
// { dg-do compile }
|
||||
// { dg-options "-std=c++14 -fsanitize=undefined,float-divide-by-zero,float-cast-overflow" }
|
||||
|
||||
#define SA(X) static_assert((X),#X)
|
||||
#define INT_MIN (-__INT_MAX__ - 1)
|
||||
|
||||
constexpr int
|
||||
fn1 (int a, int b)
|
||||
{
|
||||
if (b != 2)
|
||||
a <<= b;
|
||||
return a;
|
||||
}
|
||||
|
||||
constexpr int i1 = fn1 (5, 3);
|
||||
constexpr int i2 = fn1 (5, -2);
|
||||
constexpr int i3 = fn1 (5, sizeof (int) * __CHAR_BIT__);
|
||||
constexpr int i4 = fn1 (5, 256);
|
||||
constexpr int i5 = fn1 (5, 2);
|
||||
constexpr int i6 = fn1 (-2, 4);
|
||||
constexpr int i7 = fn1 (0, 2);
|
||||
|
||||
SA (i1 == 40);
|
||||
SA (i5 == 5);
|
||||
SA (i7 == 0);
|
||||
|
||||
constexpr int
|
||||
fn2 (int a, int b)
|
||||
{
|
||||
if (b != 2)
|
||||
a >>= b;
|
||||
return a;
|
||||
}
|
||||
|
||||
constexpr int j1 = fn2 (4, 1);
|
||||
constexpr int j2 = fn2 (4, -1);
|
||||
constexpr int j3 = fn2 (10, sizeof (int) * __CHAR_BIT__);
|
||||
constexpr int j4 = fn2 (1, 256);
|
||||
constexpr int j5 = fn2 (5, 2);
|
||||
constexpr int j6 = fn2 (-2, 4);
|
||||
constexpr int j7 = fn2 (0, 4);
|
||||
|
||||
SA (j1 == 2);
|
||||
SA (j5 == 5);
|
||||
SA (j7 == 0);
|
||||
|
||||
constexpr int
|
||||
fn3 (int a, int b)
|
||||
{
|
||||
if (b != 2)
|
||||
a = a / b;
|
||||
return a;
|
||||
}
|
||||
|
||||
constexpr int k1 = fn3 (8, 4);
|
||||
constexpr int k2 = fn3 (7, 0); // { dg-error "is not a constant expression" }
|
||||
constexpr int k3 = fn3 (INT_MIN, -1); // { dg-error "overflow in constant expression" }
|
||||
|
||||
SA (k1 == 2);
|
||||
|
||||
constexpr float
|
||||
fn4 (float a, float b)
|
||||
{
|
||||
if (b != 2.0)
|
||||
a = a / b;
|
||||
return a;
|
||||
}
|
||||
|
||||
constexpr float l1 = fn4 (5.0, 3.0);
|
||||
constexpr float l2 = fn4 (7.0, 0.0); // { dg-error "is not a constant expression" }
|
||||
|
||||
constexpr int
|
||||
fn5 (const int *a, int b)
|
||||
{
|
||||
if (b != 2)
|
||||
b = a[b];
|
||||
return b;
|
||||
}
|
||||
|
||||
constexpr int m1[4] = { 1, 2, 3, 4 };
|
||||
constexpr int m2 = fn5 (m1, 3);
|
||||
constexpr int m3 = fn5 (m1, 4); // { dg-error "array subscript out of bound" }
|
||||
|
||||
constexpr int
|
||||
fn6 (const int &a, int b)
|
||||
{
|
||||
if (b != 2)
|
||||
b = a;
|
||||
return b;
|
||||
}
|
||||
|
||||
constexpr int
|
||||
fn7 (const int *a, int b)
|
||||
{
|
||||
if (b != 3)
|
||||
return fn6 (*a, b);
|
||||
return 7;
|
||||
}
|
||||
|
||||
constexpr int n1 = 7;
|
||||
constexpr int n2 = fn7 (&n1, 5);
|
||||
constexpr int n3 = fn7 ((const int *) 0, 8); // { dg-error "is not a constant expression" }
|
||||
|
||||
constexpr int
|
||||
fn8 (int i)
|
||||
{
|
||||
constexpr int g[10] = { };
|
||||
return g[i];
|
||||
}
|
||||
|
||||
constexpr int o1 = fn8 (9);
|
||||
constexpr int o2 = fn8 (10); // { dg-error "array subscript out of bound" }
|
||||
|
||||
constexpr int
|
||||
fn9 (int a, int b)
|
||||
{
|
||||
if (b != 0)
|
||||
return a + b;
|
||||
return a;
|
||||
}
|
||||
|
||||
constexpr int p1 = fn9 (42, 7);
|
||||
constexpr int p2 = fn9 (__INT_MAX__, 1); // { dg-error "overflow in constant expression" }
|
||||
constexpr int p3 = fn9 (__INT_MAX__, -1);
|
||||
constexpr int p4 = fn9 (INT_MIN, 1);
|
||||
constexpr int p5 = fn9 (INT_MIN, -1); // { dg-error "overflow in constant expression" }
|
||||
|
||||
SA (p1 == 49);
|
||||
SA (p3 == __INT_MAX__ - 1);
|
||||
SA (p4 == INT_MIN + 1);
|
||||
|
||||
constexpr int
|
||||
fn10 (int a, int b)
|
||||
{
|
||||
if (b != 0)
|
||||
return a * b;
|
||||
return a;
|
||||
}
|
||||
|
||||
constexpr int q1 = fn10 (10, 10);
|
||||
constexpr int q2 = fn10 (__INT_MAX__, 2); // { dg-error "overflow in constant expression" }
|
||||
constexpr int q3 = fn10 (INT_MIN, 2); // { dg-error "overflow in constant expression" }
|
||||
constexpr int q4 = fn10 (-1, -1);
|
||||
|
||||
SA (q1 == 100);
|
||||
SA (q4 == 1);
|
||||
|
||||
constexpr int
|
||||
fn11 (double d)
|
||||
{
|
||||
int i = d;
|
||||
if (i != 0)
|
||||
return i;
|
||||
return i * 2;
|
||||
}
|
||||
|
||||
constexpr int r1 = fn11 (3.4);
|
||||
constexpr int r2 = fn11 (__builtin_inf ()); // { dg-error "overflow in constant expression" }
|
||||
|
||||
constexpr int
|
||||
fn12 (int i)
|
||||
{
|
||||
if (i == 42)
|
||||
__builtin_unreachable (); // { dg-error "is not a constant expression" }
|
||||
return i + 10;
|
||||
}
|
||||
|
||||
constexpr int s1 = fn12 (1);
|
||||
constexpr int s2 = fn12 (42);
|
||||
|
||||
SA (s1 == 11);
|
@ -653,6 +653,7 @@ bool
|
||||
is_ubsan_builtin_p (tree t)
|
||||
{
|
||||
return TREE_CODE (t) == FUNCTION_DECL
|
||||
&& DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
|
||||
&& strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
|
||||
"__builtin___ubsan_", 18) == 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user