From patchwork Mon Nov 3 20:47:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 406357 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 B9B0F1400A0 for ; Tue, 4 Nov 2014 07:47:19 +1100 (AEDT) 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:subject:message-id:mime-version:content-type; q=dns; s= default; b=qjSndpwESzvoU5LCfnHxYfpFRWJPBo370p8cz9mq5dbE41iOr9O7n T+kdIg2aJqd6AnrG1/FP63dZIUYZFadXNESGQFvKV+pClHoHKvQ4T06vtHCemymJ qNV/WU8vEtHTY4aJ8t2rk4ASADYwT9DwjhKQSBte3YcA+yYG5eQ+5Q= 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:subject:message-id:mime-version:content-type; s= default; bh=JwCMW3ElkDFla1POLwnXkH+L31k=; b=lFRUvdlxHXsZh0zVCW9G cp3V4AfVGNbqHRsCBQ1uUwPIkYPkoczaipklyhX+qMD1m4cz+KaIY9/aPJ1VYcFE Jqk99x3WK8dBM5dx5iDK9aSSFVvx6xObHtN+q9k97VUlMJ/vUOCCuj6BqtQfyeYm PXh0MNBsLf6QafbhRv/sNXE= Received: (qmail 11946 invoked by alias); 3 Nov 2014 20:47:13 -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 11915 invoked by uid 89); 3 Nov 2014 20:47:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham 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; Mon, 03 Nov 2014 20:47:11 +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 sA3Kl9YV003145 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Mon, 3 Nov 2014 15:47:10 -0500 Received: from redhat.com (ovpn-116-30.ams2.redhat.com [10.36.116.30]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id sA3Kl60N027892 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO); Mon, 3 Nov 2014 15:47:08 -0500 Date: Mon, 3 Nov 2014 21:47:05 +0100 From: Marek Polacek To: GCC Patches , Jakub Jelinek Subject: [PATCH] Optimize BIT_AND_EXPRs for UBSAN_OBJECT_SIZE Message-ID: <20141103204705.GQ20462@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) We don't emit UBSAN_BOUNDS checks in case we can at compile-time prove that the array access is fine. Also if we have [i & CST], where CST is <= bound_of_the_array, we know we're fine as well. But we don't have similar BIT_AND_EXPR check for UBSAN_OBJECT_SIZE which is what this patch attempts to add. (This is unrelated to the UBSAN_NULL optimization I posted earlier today.) Bootstrap-ubsan/regtest passed on x86_64-linux, ok for trunk? 2014-11-03 Marek Polacek * ubsan.c (instrument_object_size): Optimize [x & CST] array accesses. testsuite/ * c-c++-common/ubsan/object-size-10.c: New test. Marek diff --git gcc/testsuite/c-c++-common/ubsan/object-size-10.c gcc/testsuite/c-c++-common/ubsan/object-size-10.c index e69de29..ebc8582 100644 --- gcc/testsuite/c-c++-common/ubsan/object-size-10.c +++ gcc/testsuite/c-c++-common/ubsan/object-size-10.c @@ -0,0 +1,79 @@ +/* { dg-do run } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-options "-fsanitize=undefined" } */ + +static char a[128]; +static int b[128]; + +__attribute__ ((noinline, noclone)) int +fn1 (int i) +{ + asm (""); + return a[i & 127]; +} + +__attribute__ ((noinline, noclone)) int +fn2 (int i) +{ + asm (""); + return a[i & 128]; +} + +/* { dg-output "index 128 out of bounds for type 'char \\\[128\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */ + +__attribute__ ((noinline, noclone)) int +fn3 (int i) +{ + asm (""); + return b[i & 127]; +} + +__attribute__ ((noinline, noclone)) int +fn4 (int i) +{ + asm (""); + return b[i & 128]; +} + +/* { dg-output "\[^\n\r]*index 128 out of bounds for type 'int \\\[128\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */ + +__attribute__ ((noinline, noclone)) int +fn5 (int i, int j) +{ + asm (""); + return b[i & j]; +} + +/* { dg-output "\[^\n\r]*index 128 out of bounds for type 'int \\\[128\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */ + +__attribute__ ((noinline, noclone)) int +fn6 (int i) +{ + asm (""); + return b[i & 0]; +} + +int +main (void) +{ + fn1 (128); + fn2 (128); + fn3 (128); + fn4 (128); + fn5 (128, 127); + fn5 (128, 128); + fn6 (128); + return 0; +} diff --git gcc/ubsan.c gcc/ubsan.c index ed2fc54..41cf546 100644 --- gcc/ubsan.c +++ gcc/ubsan.c @@ -1438,6 +1438,7 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs) location_t loc = gimple_location (stmt); tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt); tree type; + tree index = NULL_TREE; HOST_WIDE_INT size_in_bytes; type = TREE_TYPE (t); @@ -1456,6 +1457,8 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs) } break; case ARRAY_REF: + index = TREE_OPERAND (t, 1); + break; case INDIRECT_REF: case MEM_REF: case VAR_DECL: @@ -1537,6 +1540,24 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs) && tree_int_cst_le (t, sizet)) return; + if (index != NULL_TREE + && TREE_CODE (index) == SSA_NAME + && TREE_CODE (sizet) == INTEGER_CST) + { + gimple def = SSA_NAME_DEF_STMT (index); + if (is_gimple_assign (def) + && gimple_assign_rhs_code (def) == BIT_AND_EXPR + && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST) + { + tree cst = gimple_assign_rhs2 (def); + tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet, + TYPE_SIZE_UNIT (type)); + if (tree_int_cst_sgn (cst) >= 0 + && tree_int_cst_lt (cst, sz)) + return; + } + } + /* Nope. Emit the check. */ t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);