public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
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

  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).