From patchwork Wed Jun 25 13:36:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 364009 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3357F140081 for ; Wed, 25 Jun 2014 23:37:22 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; q=dns; s=default; b=MYgMrugZOiaxjxlME Q10KaSdIqsXcPEQkPV9ElSIegJh6tCbdfzIOnOxMvh0MY8s+pYRXsgJJYRSgGXb0 t0QPeMF1p0zuEzeCyeQTAlXGqBqr8AKIUT0+S8LsvJj7Q59RnuoOpkFUZ8faaAHs X2JYaj9ysjdpJ4B/UW1SkXvdIk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=default; bh=z82tzM+LKC5C+yS4jAPRAgA xDqk=; b=HATrlqcvUEfdVYtfUwN6djf4K+ZYDM8FeXJ36T/femBnIpSH1GLQNRS PmDJevsrEHuNeaCAaRFJGg6gGmpNZusq6BjHq1Sx9oN/PhR5a5b/+Mq+D4dZAcmM K6fWIi47v899ds9Pz+pvExAgp9xEVYSXHH1yHaQkEfm0XzXvpUu0= Received: (qmail 25106 invoked by alias); 25 Jun 2014 13:37:16 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 25087 invoked by uid 89); 25 Jun 2014 13:37:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.4 required=5.0 tests=AWL, BAYES_50, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD, UNSUBSCRIBE_BODY autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 25 Jun 2014 13:36:49 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s5PDagte020386 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 25 Jun 2014 09:36:42 -0400 Received: from redhat.com (ovpn-116-31.ams2.redhat.com [10.36.116.31]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s5PDadhQ017026 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO); Wed, 25 Jun 2014 09:36:41 -0400 Date: Wed, 25 Jun 2014 15:36:38 +0200 From: Marek Polacek To: Jakub Jelinek Cc: GCC Patches , Ramana Radhakrishnan Subject: Re: [PATCH] Fix ubsan/bounds-2.c Message-ID: <20140625133638.GC489@redhat.com> References: <20140625124039.GB489@redhat.com> <20140625124956.GE31640@tucnak.redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20140625124956.GE31640@tucnak.redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) On Wed, Jun 25, 2014 at 02:49:56PM +0200, Jakub Jelinek wrote: > On Wed, Jun 25, 2014 at 02:40:40PM +0200, Marek Polacek wrote: > > On IRC Ramana reported that on ARM ubsan/bounds-2.c test fails with -O0, > > since we write to out-of-bounds location and probably rewrite the > > frame pointer stored in the stack. This patch removes such stores > > and adds some asm magic so the compiler doesn't optimize loads away as > > uninitialized memory read. > > > > Ramana, does this patch help on ARM? > > Tested x86_64-unknown-linux-gnu, ok for trunk? > > What about bounds-5.c ? Also, do you have any tests for negative indexes? Ok, adjusted bounds-5.c as well. New test for negative indexes added. make -C gcc check-g{cc,++} RUNTESTFLAGS='--target_board=unix\{-m32,-m64\} ubsan.exp' passes on x86_64-linux. 2014-06-25 Marek Polacek * c-c++-common/ubsan/bounds-2.c: Adjust dg-output. (fn1): Remove store to out-of-bounds location. Add memory barrier. (fn2): Likewise. (fn5): Likewise. (fn6): Likewise. (fn7): Likewise. (fn8): Likewise. (fn9): Likewise. (fn11): Likewise. * c-c++-common/ubsan/bounds-5.c (fn1): Remove store to out-of-bounds location. Add memory barrier. (fn2): Likewise. (fn3): Likewise. (fn4): Likewise. (fn5): Likewise. * c-c++-common/ubsan/bounds-7.c: New test. Marek diff --git gcc/testsuite/c-c++-common/ubsan/bounds-2.c gcc/testsuite/c-c++-common/ubsan/bounds-2.c index 95f77c2..3a24d40 100644 --- gcc/testsuite/c-c++-common/ubsan/bounds-2.c +++ gcc/testsuite/c-c++-common/ubsan/bounds-2.c @@ -22,7 +22,7 @@ static void __attribute__ ((noinline, noclone)) fn1 (void) { volatile int a[5]; - a[5] = 1; + asm ("" : : "r" (&a[5]) : "memory"); a[2] = a[5]; } @@ -30,9 +30,11 @@ static void __attribute__ ((noinline, noclone)) fn2 (void) { volatile int a[5]; + volatile int j; int i = 5; int *p = &i; - a[*p] = 1; + asm ("" : : "r" (&a[*p]) : "memory"); + j = a[*p]; } static void __attribute__ ((noinline, noclone)) @@ -54,7 +56,7 @@ fn5 (void) { int i = 5; volatile int a[i]; - a[i] = 1; + asm ("" : : "r" (&a[i]) : "memory"); a[2] = a[i]; } @@ -63,29 +65,32 @@ fn6 (void) { int i = 5; volatile int a[i]; + volatile int j; fn_p (a[i]); - a[foo_5 ()] = 1; + asm ("" : : "r" (&a[foo_5 ()]) : "memory"); + j = a[foo_5 ()]; } static void __attribute__ ((noinline, noclone)) fn7 (void) { - int n = 5, i; + int n = 5; + volatile int i; volatile int c[n][n][n]; - c[5][2][2] = 2; - c[2][5][2] = 2; - c[2][2][5] = 2; + asm ("" : : "r" (&c[5][2][2]) : "memory"); i = c[5][2][2]; + asm ("" : : "r" (&c[2][5][2]) : "memory"); i = c[2][5][2]; + asm ("" : : "r" (&c[2][2][5]) : "memory"); i = c[2][2][5]; } static void __attribute__ ((noinline, noclone)) fn8 (void) { - int i = 5; + volatile int i; volatile struct S s; - s.a[10] = 1; + asm ("" : : "r" (&s.a[10]) : "memory"); i = s.a[10]; } @@ -93,7 +98,7 @@ static void __attribute__ ((noinline, noclone)) fn9 (void) { long int *volatile d[10][5]; - d[10][0] = 0; + asm ("" : : "r" (&d[10][0]) : "memory"); d[8][3] = d[10][0]; } @@ -115,7 +120,7 @@ static void __attribute__ ((noinline, noclone)) fn11 (void) { char ***volatile f[5]; - f[5] = 0; + asm ("" : : "r" (&f[5]) : "memory"); f[2] = f[5]; } @@ -148,21 +153,16 @@ main (void) /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 10 out of bounds for type 'long int \\\*\\\[10\\\]\\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 10 out of bounds for type 'long int \\\*\\\[10\\\]\\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'char \\\*\\\*\\\*\\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 5 out of bounds for type 'char \\\*\\\*\\\*\\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*index 5 out of bounds for type 'int \\\[5\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ diff --git gcc/testsuite/c-c++-common/ubsan/bounds-5.c gcc/testsuite/c-c++-common/ubsan/bounds-5.c index 7b7d76d..68f0648 100644 --- gcc/testsuite/c-c++-common/ubsan/bounds-5.c +++ gcc/testsuite/c-c++-common/ubsan/bounds-5.c @@ -9,11 +9,16 @@ void fn1 (void) { volatile struct S { char a[1]; char b; } s; - s.a[0] = 1; // OK - s.a[1] = 2; // error + volatile int i; + asm ("" : : "r" (&s.a[0]) : "memory"); + i = s.a[0]; // OK + asm ("" : : "r" (&s.a[1]) : "memory"); + i = s.a[1]; // error volatile struct S *p = &s; - p->a[0] = 1; // OK - p->a[1] = 1; // error + asm ("" : : "r" (&p->a[0]) : "memory"); + i = p->a[0]; // OK + asm ("" : : "r" (&p->a[1]) : "memory"); + i = p->a[1]; // error } __attribute__ ((noinline, noclone)) @@ -22,11 +27,16 @@ fn2 (void) { struct S { int c; char d[4]; }; volatile struct T { int e; struct S f; int g; } t; - t.f.d[3] = 1; // OK - t.f.d[4] = 1; // error + volatile int i; + asm ("" : : "r" (&t.f.d[3]) : "memory"); + i = t.f.d[3]; // OK + asm ("" : : "r" (&t.f.d[4]) : "memory"); + i = t.f.d[4]; // error volatile struct T *p = &t; - p->f.d[3] = 1; // OK - p->f.d[4] = 1; // error + asm ("" : : "r" (&p->f.d[3]) : "memory"); + i = p->f.d[3]; // OK + asm ("" : : "r" (&p->f.d[4]) : "memory"); + i = p->f.d[4]; // error } __attribute__ ((noinline, noclone)) @@ -34,11 +44,16 @@ void fn3 (void) { volatile struct S { char b; char a[1]; } s; - s.a[0] = 1; // OK - s.a[1] = 1; // error + volatile int i; + asm ("" : : "r" (&s.a[0]) : "memory"); + i = s.a[0]; // OK + asm ("" : : "r" (&s.a[1]) : "memory"); + i = s.a[1]; // error volatile struct S *p = &s; - p->a[0] = 1; // OK - p->a[1] = 1; // error in strict mode + asm ("" : : "r" (&p->a[0]) : "memory"); + i = p->a[0]; // OK + asm ("" : : "r" (&p->a[1]) : "memory"); + i = p->a[1]; // error in strict mode } __attribute__ ((noinline, noclone)) @@ -47,11 +62,16 @@ fn4 (void) { volatile struct S { char b; char a[1]; } s; volatile struct T { struct S s; int i; } t; - t.s.a[0] = 1; // OK - t.s.a[1] = 1; // error + volatile int i; + asm ("" : : "r" (&t.s.a[0]) : "memory"); + i = t.s.a[0]; // OK + asm ("" : : "r" (&t.s.a[1]) : "memory"); + i = t.s.a[1]; // error volatile struct T *pt = &t; - pt->s.a[0] = 1; // OK - pt->s.a[1] = 1; // error + asm ("" : : "r" (&pt->s.a[0]) : "memory"); + i = pt->s.a[0]; // OK + asm ("" : : "r" (&pt->s.a[1]) : "memory"); + i = pt->s.a[1]; // error } __attribute__ ((noinline, noclone)) @@ -60,11 +80,16 @@ fn5 (void) { volatile struct S { char b; char a[1]; } s; volatile struct U { int a; struct S s; } u; - u.s.a[0] = 1; // OK - u.s.a[1] = 1; // error + volatile int i; + asm ("" : : "r" (&u.s.a[0]) : "memory"); + i = u.s.a[0]; // OK + asm ("" : : "r" (&u.s.a[1]) : "memory"); + i = u.s.a[1]; // error volatile struct U *pu = &u; - pu->s.a[0] = 1; // OK - pu->s.a[1] = 1; // error in strict mode + asm ("" : : "r" (&pu->s.a[0]) : "memory"); + i = pu->s.a[0]; // OK + asm ("" : : "r" (&pu->s.a[1]) : "memory"); + i = pu->s.a[1]; // error in strict mode } int diff --git gcc/testsuite/c-c++-common/ubsan/bounds-7.c gcc/testsuite/c-c++-common/ubsan/bounds-7.c index e69de29..266b53b 100644 --- gcc/testsuite/c-c++-common/ubsan/bounds-7.c +++ gcc/testsuite/c-c++-common/ubsan/bounds-7.c @@ -0,0 +1,56 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=bounds" } */ + +/* Test negative bounds. */ + +struct S { int a[10]; }; + +__attribute__ ((noinline, noclone)) +void +fn1 (void) +{ + volatile int i; + int m = -1; + volatile int a[7]; + asm ("" : : "r" (&a[-1]) : "memory"); + i = a[-1]; + asm ("" : : "r" (&a[m]) : "memory"); + i = a[m]; +} + +__attribute__ ((noinline, noclone)) +void +fn2 (void) +{ + volatile int i; + int m = 7; + volatile int a[m]; + asm ("" : : "r" (&a[-1]) : "memory"); + i = a[-1]; +} + +__attribute__ ((noinline, noclone)) +void +fn3 (void) +{ + volatile int i; + volatile struct S s; + asm ("" : : "r" (&s.a[-1]) : "memory"); + i = s.a[-1]; +} + +int +main (void) +{ + fn1 (); + fn2 (); + fn3 (); + return 0; +} + +/* { dg-output "index -1 out of bounds for type 'int \\\[7\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[7\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*index -1 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */