Commit c9b39a49 by Jakub Jelinek Committed by Jakub Jelinek

re PR sanitizer/80998 (Implement -fsanitize=pointer-overflow)

	PR sanitizer/80998
	* sanopt.c (pass_sanopt::execute): Handle IFN_UBSAN_PTR.
	* tree-ssa-alias.c (call_may_clobber_ref_p_1): Likewise.
	* flag-types.h (enum sanitize_code): Add SANITIZER_POINTER_OVERFLOW.
	Or it into SANITIZER_UNDEFINED.
	* ubsan.c: Include gimple-fold.h and varasm.h.
	(ubsan_expand_ptr_ifn): New function.
	(instrument_pointer_overflow): New function.
	(maybe_instrument_pointer_overflow): New function.
	(instrument_object_size): Formatting fix.
	(pass_ubsan::execute): Call instrument_pointer_overflow
	and maybe_instrument_pointer_overflow.
	* internal-fn.c (expand_UBSAN_PTR): New function.
	* ubsan.h (ubsan_expand_ptr_ifn): Declare.
	* sanitizer.def (__ubsan_handle_pointer_overflow,
	__ubsan_handle_pointer_overflow_abort): New builtins.
	* tree-ssa-tail-merge.c (merge_stmts_p): Handle IFN_UBSAN_PTR.
	* internal-fn.def (UBSAN_PTR): New internal function.
	* opts.c (sanitizer_opts): Add pointer-overflow.
	* lto-streamer-in.c (input_function): Handle IFN_UBSAN_PTR.
	* fold-const.c (build_range_check): Compute pointer range check in
	integral type if pointer arithmetics would be needed.  Formatting
	fixes.
gcc/testsuite/
	* c-c++-common/ubsan/ptr-overflow-1.c: New test.
	* c-c++-common/ubsan/ptr-overflow-2.c: New test.
libsanitizer/
	* ubsan/ubsan_handlers.cc: Cherry-pick upstream r304461.
	* ubsan/ubsan_checks.inc: Likewise.
	* ubsan/ubsan_handlers.h: Likewise.

From-SVN: r250656
parent 70affe6a
2017-07-28 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/80998
* sanopt.c (pass_sanopt::execute): Handle IFN_UBSAN_PTR.
* tree-ssa-alias.c (call_may_clobber_ref_p_1): Likewise.
* flag-types.h (enum sanitize_code): Add SANITIZER_POINTER_OVERFLOW.
Or it into SANITIZER_UNDEFINED.
* ubsan.c: Include gimple-fold.h and varasm.h.
(ubsan_expand_ptr_ifn): New function.
(instrument_pointer_overflow): New function.
(maybe_instrument_pointer_overflow): New function.
(instrument_object_size): Formatting fix.
(pass_ubsan::execute): Call instrument_pointer_overflow
and maybe_instrument_pointer_overflow.
* internal-fn.c (expand_UBSAN_PTR): New function.
* ubsan.h (ubsan_expand_ptr_ifn): Declare.
* sanitizer.def (__ubsan_handle_pointer_overflow,
__ubsan_handle_pointer_overflow_abort): New builtins.
* tree-ssa-tail-merge.c (merge_stmts_p): Handle IFN_UBSAN_PTR.
* internal-fn.def (UBSAN_PTR): New internal function.
* opts.c (sanitizer_opts): Add pointer-overflow.
* lto-streamer-in.c (input_function): Handle IFN_UBSAN_PTR.
* fold-const.c (build_range_check): Compute pointer range check in
integral type if pointer arithmetics would be needed. Formatting
fixes.
2017-07-28 Martin Liska <mliska@suse.cz>
PR sanitizer/81460
......
......@@ -238,6 +238,7 @@ enum sanitize_code {
SANITIZE_OBJECT_SIZE = 1UL << 21,
SANITIZE_VPTR = 1UL << 22,
SANITIZE_BOUNDS_STRICT = 1UL << 23,
SANITIZE_POINTER_OVERFLOW = 1UL << 24,
SANITIZE_SHIFT = SANITIZE_SHIFT_BASE | SANITIZE_SHIFT_EXPONENT,
SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
| SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
......@@ -245,7 +246,8 @@ enum sanitize_code {
| SANITIZE_BOUNDS | SANITIZE_ALIGNMENT
| SANITIZE_NONNULL_ATTRIBUTE
| SANITIZE_RETURNS_NONNULL_ATTRIBUTE
| SANITIZE_OBJECT_SIZE | SANITIZE_VPTR,
| SANITIZE_OBJECT_SIZE | SANITIZE_VPTR
| SANITIZE_POINTER_OVERFLOW,
SANITIZE_UNDEFINED_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
| SANITIZE_BOUNDS_STRICT
};
......
......@@ -4859,21 +4859,21 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
if (low == 0)
return fold_build2_loc (loc, LE_EXPR, type, exp,
fold_convert_loc (loc, etype, high));
fold_convert_loc (loc, etype, high));
if (high == 0)
return fold_build2_loc (loc, GE_EXPR, type, exp,
fold_convert_loc (loc, etype, low));
fold_convert_loc (loc, etype, low));
if (operand_equal_p (low, high, 0))
return fold_build2_loc (loc, EQ_EXPR, type, exp,
fold_convert_loc (loc, etype, low));
fold_convert_loc (loc, etype, low));
if (TREE_CODE (exp) == BIT_AND_EXPR
&& maskable_range_p (low, high, etype, &mask, &value))
return fold_build2_loc (loc, EQ_EXPR, type,
fold_build2_loc (loc, BIT_AND_EXPR, etype,
exp, mask),
exp, mask),
value);
if (integer_zerop (low))
......@@ -4905,7 +4905,7 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
exp = fold_convert_loc (loc, etype, exp);
}
return fold_build2_loc (loc, GT_EXPR, type, exp,
build_int_cst (etype, 0));
build_int_cst (etype, 0));
}
}
......@@ -4915,25 +4915,15 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
if (etype == NULL_TREE)
return NULL_TREE;
if (POINTER_TYPE_P (etype))
etype = unsigned_type_for (etype);
high = fold_convert_loc (loc, etype, high);
low = fold_convert_loc (loc, etype, low);
exp = fold_convert_loc (loc, etype, exp);
value = const_binop (MINUS_EXPR, high, low);
if (POINTER_TYPE_P (etype))
{
if (value != 0 && !TREE_OVERFLOW (value))
{
low = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (low), low);
return build_range_check (loc, type,
fold_build_pointer_plus_loc (loc, exp, low),
1, build_int_cst (etype, 0), value);
}
return 0;
}
if (value != 0 && !TREE_OVERFLOW (value))
return build_range_check (loc, type,
fold_build2_loc (loc, MINUS_EXPR, etype, exp, low),
......
......@@ -402,6 +402,14 @@ expand_UBSAN_VPTR (internal_fn, gcall *)
/* This should get expanded in the sanopt pass. */
static void
expand_UBSAN_PTR (internal_fn, gcall *)
{
gcc_unreachable ();
}
/* This should get expanded in the sanopt pass. */
static void
expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
{
gcc_unreachable ();
......
......@@ -166,6 +166,7 @@ DEF_INTERNAL_FN (UBSAN_VPTR, ECF_LEAF | ECF_NOTHROW, ".RR..")
DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (UBSAN_PTR, ECF_LEAF | ECF_NOTHROW, ".R.")
DEF_INTERNAL_FN (UBSAN_OBJECT_SIZE, ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN, NULL)
DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
......
......@@ -1143,6 +1143,10 @@ input_function (tree fn_decl, struct data_in *data_in,
if ((flag_sanitize & SANITIZE_OBJECT_SIZE) == 0)
remove = true;
break;
case IFN_UBSAN_PTR:
if ((flag_sanitize & SANITIZE_POINTER_OVERFLOW) == 0)
remove = true;
break;
case IFN_ASAN_MARK:
if ((flag_sanitize & SANITIZE_ADDRESS) == 0)
remove = true;
......
......@@ -1521,6 +1521,7 @@ const struct sanitizer_opts_s sanitizer_opts[] =
true),
SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE, true),
SANITIZER_OPT (vptr, SANITIZE_VPTR, true),
SANITIZER_OPT (pointer-overflow, SANITIZE_POINTER_OVERFLOW, true),
SANITIZER_OPT (all, ~0U, true),
#undef SANITIZER_OPT
{ NULL, 0U, 0UL, false }
......
......@@ -448,6 +448,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE,
"__ubsan_handle_load_invalid_value",
BT_FN_VOID_PTR_PTR,
ATTR_COLD_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW,
"__ubsan_handle_pointer_overflow",
BT_FN_VOID_PTR_PTR_PTR,
ATTR_COLD_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT,
"__ubsan_handle_divrem_overflow_abort",
BT_FN_VOID_PTR_PTR_PTR,
......@@ -484,6 +488,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT,
"__ubsan_handle_load_invalid_value_abort",
BT_FN_VOID_PTR_PTR,
ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT,
"__ubsan_handle_pointer_overflow_abort",
BT_FN_VOID_PTR_PTR_PTR,
ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW,
"__ubsan_handle_float_cast_overflow",
BT_FN_VOID_PTR_PTR,
......
......@@ -1063,6 +1063,9 @@ pass_sanopt::execute (function *fun)
case IFN_UBSAN_OBJECT_SIZE:
no_next = ubsan_expand_objsize_ifn (&gsi);
break;
case IFN_UBSAN_PTR:
no_next = ubsan_expand_ptr_ifn (&gsi);
break;
case IFN_UBSAN_VPTR:
no_next = ubsan_expand_vptr_ifn (&gsi);
break;
......
......@@ -5,6 +5,10 @@
2017-07-28 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/80998
* c-c++-common/ubsan/ptr-overflow-1.c: New test.
* c-c++-common/ubsan/ptr-overflow-2.c: New test.
PR tree-optimization/81578
* gcc.dg/pr81578.c: New test.
......
/* PR sanitizer/80998 */
/* { dg-do run } */
/* { dg-options "-fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -Wall" } */
struct S { int a; int b; int c[64]; };
__attribute__((noinline, noclone)) char *f1 (char *p) { return p + 1; }
__attribute__((noinline, noclone)) char *f2 (char *p) { return p - 1; }
__attribute__((noinline, noclone)) char *f3 (char *p, int i) { return p + i; }
__attribute__((noinline, noclone)) char *f4 (char *p, int i) { return p - i; }
__attribute__((noinline, noclone)) char *f5 (char *p, unsigned long int i) { return p + i; }
__attribute__((noinline, noclone)) char *f6 (char *p, unsigned long int i) { return p - i; }
__attribute__((noinline, noclone)) int *f7 (struct S *p) { return &p->a; }
__attribute__((noinline, noclone)) int *f8 (struct S *p) { return &p->b; }
__attribute__((noinline, noclone)) int *f9 (struct S *p) { return &p->c[64]; }
__attribute__((noinline, noclone)) int *f10 (struct S *p, int i) { return &p->c[i]; }
char *volatile p;
struct S *volatile q;
char a[64];
struct S s;
int *volatile r;
int
main ()
{
struct S t;
p = &a[32];
p = f1 (p);
p = f1 (p);
p = f2 (p);
p = f3 (p, 1);
p = f3 (p, -1);
p = f3 (p, 3);
p = f3 (p, -6);
p = f4 (p, 1);
p = f4 (p, -1);
p = f4 (p, 3);
p = f4 (p, -6);
p = f5 (p, 1);
p = f5 (p, 3);
p = f6 (p, 1);
p = f6 (p, 3);
if (sizeof (unsigned long) >= sizeof (char *))
{
p = f5 (p, -1);
p = f5 (p, -6);
p = f6 (p, -1);
p = f6 (p, -6);
}
q = &s;
r = f7 (q);
r = f8 (q);
r = f9 (q);
r = f10 (q, 0);
r = f10 (q, 10);
r = f10 (q, 64);
q = &t;
r = f7 (q);
r = f8 (q);
r = f9 (q);
r = f10 (q, 0);
r = f10 (q, 10);
r = f10 (q, 64);
return 0;
}
/* PR sanitizer/80998 */
/* { dg-do run } */
/* { dg-options "-fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -fno-ipa-icf -Wall" } */
__attribute__((noinline, noclone)) char * f1 (char *p) { return p + 1; }
__attribute__((noinline, noclone)) char * f2 (char *p) { return p - 1; }
__attribute__((noinline, noclone)) char * f3 (char *p, int i) { return p + i; }
__attribute__((noinline, noclone)) char * f4 (char *p, int i) { return p + i; }
__attribute__((noinline, noclone)) char * f5 (char *p, int i) { return p - i; }
__attribute__((noinline, noclone)) char * f6 (char *p, int i) { return p - i; }
__attribute__((noinline, noclone)) char * f7 (char *p, unsigned long int i) { return p + i; }
__attribute__((noinline, noclone)) char * f8 (char *p, unsigned long int i) { return p + i; }
__attribute__((noinline, noclone)) char * f9 (char *p, unsigned long int i) { return p - i; }
__attribute__((noinline, noclone)) char * f10 (char *p, unsigned long int i) { return p - i; }
struct S { int a; int b; int c[64]; };
__attribute__((noinline, noclone)) int *f11 (struct S *p) { return &p->a; }
__attribute__((noinline, noclone)) int *f12 (struct S *p) { return &p->b; }
__attribute__((noinline, noclone)) int *f13 (struct S *p) { return &p->c[64]; }
__attribute__((noinline, noclone)) int *f14 (struct S *p, int i) { return &p->c[i]; }
__attribute__((noinline, noclone)) int *f15 (struct S *p, int i) { return &p->c[i]; }
__attribute__((noinline, noclone)) int *f16 (struct S *p) { return &p->a; }
__attribute__((noinline, noclone)) int *f17 (struct S *p) { return &p->b; }
__attribute__((noinline, noclone)) int *f18 (struct S *p) { return &p->c[64]; }
__attribute__((noinline, noclone)) int *f19 (struct S *p, int i) { return &p->c[i]; }
__attribute__((noinline, noclone)) int *f20 (struct S *p, int i) { return &p->c[i]; }
__attribute__((noinline, noclone)) int *f21 (struct S *p) { return &p->a; }
__attribute__((noinline, noclone)) int *f22 (struct S *p) { return &p->b; }
__attribute__((noinline, noclone)) int *f23 (struct S *p) { return &p->c[64]; }
__attribute__((noinline, noclone)) int *f24 (struct S *p, int i) { return &p->c[i]; }
__attribute__((noinline, noclone)) int *f25 (struct S *p, int i) { return &p->c[i]; }
char *volatile p;
__UINTPTR_TYPE__ volatile u;
struct S *volatile q;
int *volatile r;
int
main ()
{
u = ~(__UINTPTR_TYPE__) 0;
p = (char *) u;
p = f1 (p);
u = 0;
p = (char *) u;
p = f2 (p);
u = -(__UINTPTR_TYPE__) 7;
p = (char *) u;
p = f3 (p, 7);
u = 3;
p = (char *) u;
p = f4 (p, -4);
u = 23;
p = (char *) u;
p = f5 (p, 27);
u = -(__UINTPTR_TYPE__) 15;
p = (char *) u;
p = f6 (p, -15);
u = -(__UINTPTR_TYPE__) 29;
p = (char *) u;
p = f7 (p, 31);
u = 23;
p = (char *) u;
p = f9 (p, 24);
if (sizeof (unsigned long) < sizeof (char *))
return 0;
u = 7;
p = (char *) u;
p = f8 (p, -8);
u = -(__UINTPTR_TYPE__) 25;
p = (char *) u;
p = f10 (p, -25);
u = ~(__UINTPTR_TYPE__) 0;
q = (struct S *) u;
r = f11 (q);
r = f12 (q);
r = f13 (q);
r = f14 (q, 0);
r = f15 (q, 63);
u = ~(__UINTPTR_TYPE__) 0 - (17 * sizeof (int));
q = (struct S *) u;
r = f16 (q);
r = f17 (q);
r = f18 (q);
r = f19 (q, 0);
r = f20 (q, 63);
u = 3 * sizeof (int);
q = (struct S *) u;
r = f21 (q);
r = f22 (q);
r = f23 (q);
r = f24 (q, -2);
r = f25 (q, -6);
return 0;
}
/* { dg-output ":5:6\[79]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*:6:6\[79]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+ overflowed to (0\[xX])?\[fF]\+(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*:7:7\[46]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+9 overflowed to (0\[xX])?0\+(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*:8:7\[46]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+3 overflowed to (0\[xX])?\[fF]\+(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*:9:7\[46]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+17 overflowed to (0\[xX])?\[fF]\+\[cC](\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*:10:7\[46]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+1 overflowed to (0\[xX])?0\+(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*:11:\[89]\[80]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+\[eE]3 overflowed to (0\[xX])?0\+2(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*:13:\[89]\[80]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+17 overflowed to (0\[xX])?\[fF]\+(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*:12:\[89]\[80]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+7 overflowed to (0\[xX])?\[fF]\+(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*:14:\[89]\[91]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+\[eE]7 overflowed to (0\[xX])?0\+" } */
/* { dg-output "(\n|\r\n|\r)" { target int32 } } */
/* { dg-output "\[^\n\r]*:17:\[67]\[82]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+3(\n|\r\n|\r)" { target int32 } } */
/* { dg-output "\[^\n\r]*:18:\[67]\[86]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+107(\n|\r\n|\r)" { target int32 } } */
/* { dg-output "\[^\n\r]*:19:\[78]\[52]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+7(\n|\r\n|\r)" { target int32 } } */
/* { dg-output "\[^\n\r]*:20:\[78]\[52]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+ overflowed to (0\[xX])?0\+103(\n|\r\n|\r)" { target int32 } } */
/* { dg-output "\[^\n\r]*:23:\[67]\[86]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+\[bB]\[bB] overflowed to (0\[xX])?0\+\[cC]3(\n|\r\n|\r)" { target int32 } } */
/* { dg-output "\[^\n\r]*:25:\[78]\[52]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?\[fF]\+\[bB]\[bB] overflowed to (0\[xX])?0\+\[bB]\[fF](\n|\r\n|\r)" { target int32 } } */
/* { dg-output "\[^\n\r]*:30:\[78]\[52]\[^\n\r]*runtime error: pointer index expression with base (0\[xX])?0\+\[cC] overflowed to (0\[xX])?\[fF]\+\[cC]" { target int32 } } */
......@@ -1991,6 +1991,7 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
case IFN_UBSAN_BOUNDS:
case IFN_UBSAN_VPTR:
case IFN_UBSAN_OBJECT_SIZE:
case IFN_UBSAN_PTR:
case IFN_ASAN_CHECK:
return false;
default:
......
......@@ -1241,6 +1241,7 @@ merge_stmts_p (gimple *stmt1, gimple *stmt2)
case IFN_UBSAN_CHECK_SUB:
case IFN_UBSAN_CHECK_MUL:
case IFN_UBSAN_OBJECT_SIZE:
case IFN_UBSAN_PTR:
case IFN_ASAN_CHECK:
/* For these internal functions, gimple_location is an implicit
parameter, which will be used explicitly after expansion.
......
......@@ -52,6 +52,7 @@ enum ubsan_encode_value_phase {
extern bool ubsan_expand_bounds_ifn (gimple_stmt_iterator *);
extern bool ubsan_expand_null_ifn (gimple_stmt_iterator *);
extern bool ubsan_expand_objsize_ifn (gimple_stmt_iterator *);
extern bool ubsan_expand_ptr_ifn (gimple_stmt_iterator *);
extern bool ubsan_expand_vptr_ifn (gimple_stmt_iterator *);
extern bool ubsan_instrument_unreachable (gimple_stmt_iterator *);
extern tree ubsan_create_data (const char *, int, const location_t *, ...);
......
2017-07-28 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/80998
* ubsan/ubsan_handlers.cc: Cherry-pick upstream r304461.
* ubsan/ubsan_checks.inc: Likewise.
* ubsan/ubsan_handlers.h: Likewise.
2017-07-14 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/81066
......
......@@ -17,6 +17,7 @@
UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined")
UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null")
UBSAN_CHECK(PointerOverflow, "pointer-overflow", "pointer-overflow")
UBSAN_CHECK(MisalignedPointerUse, "misaligned-pointer-use", "alignment")
UBSAN_CHECK(InsufficientObjectSize, "insufficient-object-size", "object-size")
UBSAN_CHECK(SignedIntegerOverflow, "signed-integer-overflow",
......
......@@ -521,6 +521,37 @@ void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
Die();
}
static void handlePointerOverflowImpl(PointerOverflowData *Data,
ValueHandle Base,
ValueHandle Result,
ReportOptions Opts) {
SourceLocation Loc = Data->Loc.acquire();
ErrorType ET = ErrorType::PointerOverflow;
if (ignoreReport(Loc, Opts, ET))
return;
ScopedReport R(Opts, Loc, ET);
Diag(Loc, DL_Error, "pointer index expression with base %0 overflowed to %1")
<< (void *)Base << (void*)Result;
}
void __ubsan::__ubsan_handle_pointer_overflow(PointerOverflowData *Data,
ValueHandle Base,
ValueHandle Result) {
GET_REPORT_OPTIONS(false);
handlePointerOverflowImpl(Data, Base, Result, Opts);
}
void __ubsan::__ubsan_handle_pointer_overflow_abort(PointerOverflowData *Data,
ValueHandle Base,
ValueHandle Result) {
GET_REPORT_OPTIONS(true);
handlePointerOverflowImpl(Data, Base, Result, Opts);
Die();
}
static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function,
ReportOptions Opts) {
if (Data->CheckKind != CFITCK_ICall)
......
......@@ -146,6 +146,13 @@ struct NonNullArgData {
/// \brief Handle passing null pointer to function with nonnull attribute.
RECOVERABLE(nonnull_arg, NonNullArgData *Data)
struct PointerOverflowData {
SourceLocation Loc;
};
RECOVERABLE(pointer_overflow, PointerOverflowData *Data, ValueHandle Base,
ValueHandle Result)
/// \brief Known CFI check kinds.
/// Keep in sync with the enum of the same name in CodeGenFunction.h
enum CFITypeCheckKind : unsigned char {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment