From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 74744 invoked by alias); 1 Sep 2017 17:47:25 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 74733 invoked by uid 89); 1 Sep 2017 17:47:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= 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 ESMTP; Fri, 01 Sep 2017 17:47:20 +0000 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B279E806C6 for ; Fri, 1 Sep 2017 17:47:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com B279E806C6 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=polacek@redhat.com Received: from redhat.com (ovpn-204-29.brq.redhat.com [10.40.204.29]) by smtp.corp.redhat.com (Postfix) with ESMTPS id DFD8995699; Fri, 1 Sep 2017 17:47:17 +0000 (UTC) Date: Fri, 01 Sep 2017 17:47:00 -0000 From: Marek Polacek To: GCC Patches , Jakub Jelinek Subject: [PATCH] Disable type demotion for sanitizer (PR sanitizer/82072) Message-ID: <20170901174714.GB20631@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.8.3 (2017-05-23) X-SW-Source: 2017-09/txt/msg00079.txt.bz2 Here, do_narrow and convert_to_integer_1 is demoting signed types to unsigned, e.g. for i = i - lmin where i is int and lmin is long int, so what we should produce is i = (int) ((long int) i - lmin) but instead it produces i = (int) ((unsigned int) i - (unsigned int) lmin); which hides the overflow. Similarly for NEGATE_EXPR. This patch prevents such demoting when the sanitizer is on. There still might be a similar issue with division or shifting, but I couldn't trigger that. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2017-09-01 Marek Polacek PR sanitizer/82072 * convert.c (do_narrow): When sanitizing signed integer overflows, bail out for signed types. (convert_to_integer_1) : Likewise. * c-c++-common/ubsan/pr82072.c: New test. diff --git gcc/convert.c gcc/convert.c index 22152cae79b..139d790fd98 100644 --- gcc/convert.c +++ gcc/convert.c @@ -434,6 +434,13 @@ do_narrow (location_t loc, typex = lang_hooks.types.type_for_size (TYPE_PRECISION (typex), TYPE_UNSIGNED (typex)); + /* The type demotion below might cause doing unsigned arithmetic + instead of signed, and thus hide overflow bugs. */ + if ((ex_form == PLUS_EXPR || ex_form == MINUS_EXPR) + && !TYPE_UNSIGNED (typex) + && sanitize_flags_p (SANITIZE_SI_OVERFLOW)) + return NULL_TREE; + /* But now perhaps TYPEX is as wide as INPREC. In that case, do nothing special here. (Otherwise would recurse infinitely in convert. */ @@ -895,7 +902,12 @@ convert_to_integer_1 (tree type, tree expr, bool dofold) TYPE_UNSIGNED (typex)); if (!TYPE_UNSIGNED (typex)) - typex = unsigned_type_for (typex); + { + /* Using unsigned arithmetic may hide overflow bugs. */ + if (sanitize_flags_p (SANITIZE_SI_OVERFLOW)) + break; + typex = unsigned_type_for (typex); + } return convert (type, fold_build1 (ex_form, typex, convert (typex, diff --git gcc/testsuite/c-c++-common/ubsan/pr82072.c gcc/testsuite/c-c++-common/ubsan/pr82072.c index e69de29bb2d..d5683406b14 100644 --- gcc/testsuite/c-c++-common/ubsan/pr82072.c +++ gcc/testsuite/c-c++-common/ubsan/pr82072.c @@ -0,0 +1,19 @@ +/* PR sanitizer/82072 */ +/* { dg-do run } */ +/* { dg-options "-fsanitize=signed-integer-overflow" } */ + +int +main () +{ + long long l = -__LONG_LONG_MAX__ - 1; + int i = 0; + asm volatile ("" : "+r" (i)); + i -= l; + asm volatile ("" : "+r" (i)); + i = -l; + asm volatile ("" : "+r" (i)); + return 0; +} + +/* { dg-output "signed integer overflow: 0 - -9223372036854775808 cannot be represented in type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*negation of -9223372036854775808 cannot be represented in type 'long long int'\[^\n\r]*; cast to an unsigned type to negate this value to itself" } */ Marek