From patchwork Mon Feb 13 20:11:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 727566 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 3vMcBg1SWsz9s7M for ; Tue, 14 Feb 2017 07:11:22 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="FiTCraTd"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=UDpS/VLYspVVLuoPe6wR/ZUvLxrxcUdmUxjGzXhHJhv+xEouMLgYW mUUVsNqZBSE6BHLiOCXFChdO1JoYslxT7BxhyzUOQ87KHQc9BPzFeEaPrerPYSW0 sEIQfMmyUBJjKR7RABMUwVj32gnsnKgSJCxvycy5/XTdEFL1DaL7nA= 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:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=lu0GTVZU7o7ji8qX1DMyRuDGVZM=; b=FiTCraTdWqf2AJ3looCC Fn4AOZZqn2R1BZNiuXA4IY2sY0iha2+5MhuhkcftdMlwcMf1N38UtdKWAeYnXVaT MF72G6ILOfKKpLL4xKKQSraijFLHztQGzAh/HLufFk5+0LgubkcRmBEFeU+qBTfw VTDgA5gWej72487GwUD6Gdk= Received: (qmail 81113 invoked by alias); 13 Feb 2017 20:11:06 -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 81099 invoked by uid 89); 13 Feb 2017 20:11:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=non-zero, UD:format, UD:min.to_shwi, minto_uhwi X-HELO: mail-qk0-f173.google.com Received: from mail-qk0-f173.google.com (HELO mail-qk0-f173.google.com) (209.85.220.173) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 13 Feb 2017 20:11:04 +0000 Received: by mail-qk0-f173.google.com with SMTP id s186so105041584qkb.1 for ; Mon, 13 Feb 2017 12:11:04 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:subject:to:message-id:date:user-agent :mime-version; bh=FDASp8nMdXbjQm8JLqU+jr+vXV8/2MLKBwOPk269jlM=; b=jL11jZx4xcUShNZfNkrDXKTq2vO2nst6x29TNfP7K2nOMkI/0Jhu2wBbPeul6NVS3J TIRdt4Xvz2q1KOnsxbk76hxakXGQPZ6Cj/gTXC5WJJ6kq8u9KV132BC301TBmOHhnz49 IF5VDNv1CjxQy8VejH141miDMPAo5v4Gj2aRx7nW5zO9C2JBSLdG2nGTIyg6hYUkkWpR EfGYHaaUTapKxp5RLIOSOiMKPJMczJQ67odbtxzbXdqyUKOZXMKBZFFvzf1hh2UuxFsf YxacSKxN6MVPtt+c6f0K4YFA34S4cEBU6eUB3PyE6FX53/nTR3G74TZiYDJewbcaPSgz K+vA== X-Gm-Message-State: AMke39ngEpFGWWJKXD0mHwoSk/xX6gZ44iRT/xDRWldHLDGT7wbDe54MnNoFP2lWusQtYg== X-Received: by 10.55.16.215 with SMTP id 84mr2758289qkq.181.1487016662794; Mon, 13 Feb 2017 12:11:02 -0800 (PST) Received: from [192.168.0.3] (97-118-113-37.hlrn.qwest.net. [97.118.113.37]) by smtp.gmail.com with ESMTPSA id i51sm6445053qtc.67.2017.02.13.12.11.02 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 13 Feb 2017 12:11:02 -0800 (PST) From: Martin Sebor Subject: [PATCH] avoid eliminating snprintf(d, n, ...) whose zero size comes from a range (PR 79496) To: Gcc Patch List Message-ID: <62da7958-6152-d23a-bd05-f96bcb19b482@gmail.com> Date: Mon, 13 Feb 2017 13:11:00 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 X-IsSubscribed: yes When the size of the destination in a call to snprintf is in a range, at level 1 -Wformat-truncation uses the upper bound as the size while the stricter level 2 uses the lower bound. However, when the lower bound is zero treating it the same as a constant zero and optimizing the call into a constant isn't correct because the actual argument need not be zero and the output of the function is important. The attached patch avoids this unsafe transformation. Is this okay for trunk? Martin PR middle-end/79496 - call to snprintf with zero size eliminated with -Wformat-truncation=2 gcc/ChangeLog: PR middle-end/79496 * gimple-ssa-sprintf.c (pass_sprintf_length::handle_gimple_call): Avoid clearing info.nowrite flag when snprintf size argument is a range. gcc/testsuite/ChangeLog: PR middle-end/79496 * gcc.dg/tree-ssa/builtin-snprintf-2.c: New test. diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index bf76162..1079a41 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -3452,6 +3452,10 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) info.format = gimple_call_arg (info.callstmt, idx_format); + /* True when the destination size is constant as opposed to the lower + or upper bound of a range. */ + bool dstsize_cst_p = true; + if (idx_dstsize == HOST_WIDE_INT_M1U) { /* For non-bounded functions like sprintf, determine the size @@ -3492,8 +3496,8 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) else if (TREE_CODE (size) == SSA_NAME) { /* Try to determine the range of values of the argument - and use the greater of the two at -Wformat-level 1 and - the smaller of them at level 2. */ + and use the greater of the two at level 1 and the smaller + of them at level 2. */ wide_int min, max; enum value_range_type range_type = get_range_info (size, &min, &max); @@ -3504,6 +3508,11 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) ? wi::fits_uhwi_p (max) ? max.to_uhwi () : max.to_shwi () : wi::fits_uhwi_p (min) ? min.to_uhwi () : min.to_shwi ()); } + + /* The destination size is not constant. If the function is + bounded (e.g., snprintf) a lower bound of zero doesn't + necessarily imply it can be eliminated. */ + dstsize_cst_p = false; } } @@ -3520,7 +3529,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) without actually producing any. Pretend the size is unlimited in this case. */ info.objsize = HOST_WIDE_INT_MAX; - info.nowrite = true; + info.nowrite = dstsize_cst_p; } else { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-2.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-2.c new file mode 100644 index 0000000..a192aee --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-2.c @@ -0,0 +1,24 @@ +/* PR middle-end/79496 - call to snprintf with non-zero size eliminated + with -Wformat-truncation=2 + { dg-do compile } + { dg-options "-O2 -Wall -Wformat-truncation=2 -fprintf-return-value -fdump-tree-optimized" } */ + +char d[2]; + +int test_cst (unsigned n) +{ + if (1 < n) + n = 0; + + return __builtin_snprintf (d, n, "%d", 1); +} + +int test_var (char *d, unsigned n) +{ + if (2 < n) + n = 0; + + return __builtin_snprintf (d, n, "%i", 1); +} + +/* { dg-final { scan-tree-dump-times "snprintf" 2 "optimized"} } */