From: Jakub Jelinek <jakub@redhat.com>
To: Marek Polacek <polacek@redhat.com>
Cc: GCC Patches <gcc-patches@gcc.gnu.org>, Jeff Law <law@redhat.com>
Subject: Re: [PATCH] Implement -fsanitize=object-size
Date: Mon, 14 Jul 2014 11:54:00 -0000 [thread overview]
Message-ID: <20140714115413.GK31640@tucnak.redhat.com> (raw)
In-Reply-To: <20140713175543.GB13277@redhat.com>
On Sun, Jul 13, 2014 at 07:55:44PM +0200, Marek Polacek wrote:
> 2014-07-13 Marek Polacek <polacek@redhat.com>
>
> * ubsan.h (struct ubsan_mismatch_data):
Missing description.
> +/* Expand UBSAN_OBJECT_SIZE internal call. */
> +
> +void
> +ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
> +{
> + gimple stmt = gsi_stmt (*gsi);
> + location_t loc = gimple_location (stmt);
> + gcc_assert (gimple_call_num_args (stmt) == 4);
> +
> + tree base = gimple_call_arg (stmt, 0);
> + tree ptr = gimple_call_arg (stmt, 1);
> + tree size = gimple_call_arg (stmt, 2);
> + tree ckind = gimple_call_arg (stmt, 3);
> + gimple_stmt_iterator gsi_orig = *gsi;
> + gimple g;
> +
> + gcc_assert (TREE_CODE (size) == INTEGER_CST);
> + /* See if we can discard the check. */
> + if (tree_to_uhwi (size) == (unsigned HOST_WIDE_INT) -1)
This would be integer_all_onesp (size).
> +static void
> +instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
> +{
> + gimple stmt = gsi_stmt (*gsi);
> + location_t loc = gimple_location (stmt);
> + tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
> +
> + if (TREE_CODE (t) != MEM_REF)
> + return;
I think this is undesirable. IMHO you want to call here
get_inner_reference, and if the given size is equal to maxsize, consider
instrumenting it, otherwise you don't instrument e.g. COMPONENT_REFs and
many other things. Look at what e.g. asan.c or even ubsan.c does; the
question is what exactly to do with bitfields, but supposedly we should
require that the DECL_BIT_FIELD_REPRESENTATIVE is accessible in that case.
Also, I wonder if using base, ptr, objsz, ckind arguments are best for the
builtin, I'd think you want instead base, ptr+size-base, objsz, ckind.
Reasons:
a) the size addition when expanding UBSAN_OBJECT_SIZE will not work
reliably, the middle end considers all pointer conversions useless,
so you can very well end up with a different TREE_TYPE of the pointer
type
b) sanopt runs very late, there aren't many GIMPLE optimization passes,
so to optimize the condition checks you pretty much rely on RTL passes
c) for e.g. gimple_fold_call it will be much easier if it can remove
redundant UBSAN_OBJECT_SIZE calls if it can just compare two constants
> + tree ptr = TREE_OPERAND (t, 0);
> + tree sizet, base = ptr;
> + gimple g;
> + gimple def_stmt;
> +
> + while (TREE_CODE (base) == SSA_NAME)
> + {
> + def_stmt = SSA_NAME_DEF_STMT (base);
> + if (is_gimple_assign (def_stmt))
> + base = gimple_assign_rhs1 (def_stmt);
This looks too dangerous. All you should look through are:
a) gimple_assign_ssa_name_copy_p
b) gimple_assign_cast_p if the rhs1 also has POINTER_TYPE_P
c) gimple_assign_rhs_code == POINTER_PLUS_EXPR
I'm also including a testcase, which shows why instrumenting
also COMPONENT_REFs etc. is important (see my reference to
get_inner_reference above) and also that IMHO we should instrument
not just when the base is a pointer, but also when it is a decl,
but in that case we should avoid instrumenting when -fsanitize=bounds
is on and we know it will handle it (in particular, if there was e.g.
char d[8]; int e; in the struct definition instead).
Note, the testcase ICEs with -O2 -fsanitize=bounds, can you please look
at that first and fix it separately?
struct S { int a; int b; };
struct T { int c; char d[]; };
static inline __attribute__((always_inline)) int
foo (struct S *p)
{
return p->b;
}
int
bar (void)
{
struct S *p = __builtin_calloc (sizeof (int) + sizeof (int) / 2, 1);
return foo (p);
}
struct T t = { 1, "abcdefg" };
int
baz (int i)
{
return t.d[i];
}
Other comments, in a form of a patch:
1) the gimple_fold_call bit shows that we should for the quite common
case where __bos is folded into -1 remove the UBSAN_OBJECT_SIZE call
immediately, not worth keeping it around through many other passes
2) if you add -O2 to the dg-options, that just means the tests are done
8 times or how many with -O2 all the time. Better skip it unless
-O2
3) when the second argument is something that can be directly compared
against the third argument, you can in gimple_fold_call fold not just
the "don't know" cases, but also when the third argument is >= the
second and both are INTEGER_CSTs - then we know at compile time
we are ok.
--- gcc/gimple-fold.c.jj 2014-07-07 10:39:45.000000000 +0200
+++ gcc/gimple-fold.c 2014-07-14 12:41:15.419687543 +0200
@@ -1209,6 +1209,15 @@ gimple_fold_call (gimple_stmt_iterator *
gimple_call_arg (stmt, 1),
gimple_call_arg (stmt, 2));
break;
+ case IFN_UBSAN_OBJECT_SIZE:
+ if (integer_all_onesp (gimple_call_arg (stmt, 2)))
+ {
+ gsi_replace (gsi, gimple_build_nop (), true);
+ unlink_stmt_vdef (stmt);
+ release_defs (stmt);
+ return true;
+ }
+ break;
case IFN_UBSAN_CHECK_ADD:
subcode = PLUS_EXPR;
break;
--- gcc/testsuite/c-c++-common/ubsan/object-size-3.c.jj 2014-07-14 10:42:24.000000000 +0200
+++ gcc/testsuite/c-c++-common/ubsan/object-size-3.c 2014-07-14 12:08:00.379413090 +0200
@@ -1,5 +1,6 @@
/* { dg-do run } */
-/* { dg-options "-fsanitize=object-size -O2 -fno-sanitize-recover" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=object-size -fno-sanitize-recover" } */
/* Test valid uses. */
--- gcc/testsuite/c-c++-common/ubsan/object-size-2.c.jj 2014-07-14 10:42:24.000000000 +0200
+++ gcc/testsuite/c-c++-common/ubsan/object-size-2.c 2014-07-14 12:07:54.760440751 +0200
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fsanitize=undefined -O2" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=undefined" } */
void
foo (unsigned long ul)
--- gcc/testsuite/c-c++-common/ubsan/object-size-6.c.jj 2014-07-14 10:42:24.000000000 +0200
+++ gcc/testsuite/c-c++-common/ubsan/object-size-6.c 2014-07-14 12:08:21.063305726 +0200
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-fsanitize=object-size -O2" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=object-size" } */
char
foo (void *v)
--- gcc/testsuite/c-c++-common/ubsan/object-size-4.c.jj 2014-07-14 10:42:24.000000000 +0200
+++ gcc/testsuite/c-c++-common/ubsan/object-size-4.c 2014-07-14 12:08:05.867384036 +0200
@@ -1,5 +1,6 @@
/* { dg-do run } */
-/* { dg-options "-fsanitize=object-size -O2 -fno-sanitize-recover" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=object-size -fno-sanitize-recover" } */
/* Test that we don't instrument flexible array members. */
--- gcc/testsuite/c-c++-common/ubsan/object-size-1.c.jj 2014-07-14 10:42:24.000000000 +0200
+++ gcc/testsuite/c-c++-common/ubsan/object-size-1.c 2014-07-14 12:07:49.463467643 +0200
@@ -1,5 +1,6 @@
/* { dg-do run } */
-/* { dg-options "-fsanitize=undefined -O2" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=undefined" } */
/* Sanity-test -fsanitize=object-size. We use -fsanitize=undefined option
to check that this feature doesn't clash with -fsanitize=bounds et al. */
--- gcc/testsuite/c-c++-common/ubsan/object-size-7.c.jj 2014-07-14 10:42:24.000000000 +0200
+++ gcc/testsuite/c-c++-common/ubsan/object-size-7.c 2014-07-14 12:08:26.685276937 +0200
@@ -1,5 +1,6 @@
/* { dg-do run } */
-/* { dg-options "-fsanitize=object-size -O2" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=object-size" } */
#define N 20
--- gcc/testsuite/c-c++-common/ubsan/object-size-5.c.jj 2014-07-14 10:42:24.000000000 +0200
+++ gcc/testsuite/c-c++-common/ubsan/object-size-5.c 2014-07-14 12:08:10.901364754 +0200
@@ -1,5 +1,6 @@
/* { dg-do run } */
-/* { dg-options "-fsanitize=object-size -O2" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
+/* { dg-options "-fsanitize=object-size" } */
/* Test structures with -fsanitize=object-size. */
Jakub
next prev parent reply other threads:[~2014-07-14 11:54 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-13 17:55 Marek Polacek
2014-07-13 21:10 ` Gerald Pfeifer
2014-07-14 11:54 ` Jakub Jelinek [this message]
2014-09-11 17:48 ` Marek Polacek
2014-10-02 12:04 ` Jakub Jelinek
2014-10-10 10:26 ` Marek Polacek
2014-10-10 10:27 ` Jakub Jelinek
2014-10-10 16:37 ` Marek Polacek
2014-10-14 16:01 ` Jakub Jelinek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140714115413.GK31640@tucnak.redhat.com \
--to=jakub@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=law@redhat.com \
--cc=polacek@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).