From patchwork Sun Jan 8 21:04:16 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 90322 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp579677qgi; Sun, 8 Jan 2017 13:04:40 -0800 (PST) X-Received: by 10.84.236.76 with SMTP id h12mr6705065pln.173.1483909480716; Sun, 08 Jan 2017 13:04:40 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id s3si86592098plb.40.2017.01.08.13.04.40 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 08 Jan 2017 13:04:40 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-445635-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-445635-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-445635-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com 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:references:message-id:date:mime-version:in-reply-to :content-type; q=dns; s=default; b=kMe1q1Dcl4HTI0OcodEl9Tff5HkuH 6Y8IBDcMmFNROCmRcdrpu5qp4etv53mtr3vAIalbfWJSuaHnsD62ALlUi6szRWR6 g5r7em/41+5eEPGub7aDep2tr73CQc44Iyzs4XvlKk4TBtvfFocV9cat89QIVx28 0uN3OJDQBAFpfY= 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:references:message-id:date:mime-version:in-reply-to :content-type; s=default; bh=DpzvnpZDwUCg3doXcRFoHwbPK2I=; b=RYH BIfWl/bxlOHE9pJMlb5j/OJtd9TAfRhaprHcb+zP1Zm7iWV2z6YNDjBMQ5QJXN6k Pat8bmvCA9HKIKauxVu0pYKkJHXAdec51cC7dSARfZSNATF7Bzpkfg3GV1aw2CNG IYipiCp9dW/3cBEFAZYNQ+gfWuPacB1gk+nuBirE= Received: (qmail 45052 invoked by alias); 8 Jan 2017 21:04:25 -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 45031 invoked by uid 89); 8 Jan 2017 21:04:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.4 required=5.0 tests=BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=wi, sar, Fill, companion X-HELO: mail-io0-f195.google.com Received: from mail-io0-f195.google.com (HELO mail-io0-f195.google.com) (209.85.223.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 08 Jan 2017 21:04:21 +0000 Received: by mail-io0-f195.google.com with SMTP id m98so5145994iod.2 for ; Sun, 08 Jan 2017 13:04:21 -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:references:message-id:date :user-agent:mime-version:in-reply-to; bh=yJKWRr3RSBhKcdpPlFWWSYLPcjmF+4dSN23nifvjAGE=; b=UqlZOcjmSzECEZ6Fkx9vbNqZLU2g12a0IczJqXOGCi50Q5+CbnWqqm3JGeJg99zIwx u39KFj3qbS1dKKWmDwO9AFDVB+Q8hFg1Oy+r+XJgQxMHQtKpk9o3R8TEcmIOYfvcKNyw hughUwVbgM9iaLcG+nx8qXGzf6+fSF8uC7cJHLx8RoMGf0dJOS3zBxctg+RVi8hqa8H4 8+0HeeKEKmsuAJ9jTDSvkoQ3BSSM6I5qHLrbCr/7QHtZfTYb3sppB8FVUL1EelkbrdiH 6f6OlHYA4tUZk8tlxXfVA+FyV/PwgRgGCZJ0q7xj0YcmQiBlGjGwkpcMmigu9lcoRuDe BMPA== X-Gm-Message-State: AIkVDXKk6VjvLc7C/QYA8kf+aJ/Zz8IlOpW3Fxx6bH2g2W7mSmytTEmLJujbfZdvKWB6dg== X-Received: by 10.107.172.134 with SMTP id v128mr79422679ioe.49.1483909459856; Sun, 08 Jan 2017 13:04:19 -0800 (PST) Received: from [192.168.0.26] (71-212-241-10.hlrn.qwest.net. [71.212.241.10]) by smtp.gmail.com with ESMTPSA id o138sm5194177itc.18.2017.01.08.13.04.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 08 Jan 2017 13:04:19 -0800 (PST) From: Martin Sebor Subject: Re: [PATCH] avoid infinite recursion in maybe_warn_alloc_args_overflow (pr 78775) To: Jeff Law , Gcc Patch List References: <54b65645-5158-86fe-71d4-469ce788482b@redhat.com> <98d46520-8ef7-7240-c13a-10945b575e3e@gmail.com> <32a6812b-4f39-2c96-5a56-52af93d6b8e4@redhat.com> Message-ID: Date: Sun, 8 Jan 2017 14:04:16 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 In-Reply-To: <32a6812b-4f39-2c96-5a56-52af93d6b8e4@redhat.com> X-IsSubscribed: yes On 01/06/2017 09:45 AM, Jeff Law wrote: > On 01/05/2017 08:52 PM, Martin Sebor wrote: >>>>> So Richi asked for removal of the VR_ANTI_RANGE handling, which would >>>>> imply removal of operand_signed_p. >>>>> >>>>> What are the implications if we do that? >>>> >>>> I just got back to this yesterday. The implications of the removal >>>> of the anti-range handling are a number of false negatives in the >>>> test suite: >>> I was thinking more at a higher level. ie, are the warnings still >>> useful if we don't have the anti-range handling? I suspect so, but >>> would like to hear your opinion. >> ... >>>> n = ~[-4, MAX]; (I.e., n is either negative or too big.) >>>> p = malloc (n); >>> Understood. The low level question is do we get these kinds of ranges >>> often enough in computations leading to allocation sizes? >> >> My intuition tells me that they are likely common enough not to >> disregard but I don't have a lot of data to back it up with. In >> a Bash build a full 23% of all checked calls are of this kind (24 >> out of 106). In a Binutils build only 4% are (9 out of 228). In >> Glibc, a little under 3%. My guess is that the number will be >> inversely proportional to the quality of the code. > So I think you've made a case that we do want to handle this case. So > what's left is how best to avoid the infinite recursion and mitigate the > pathological cases. > > What you're computing seems to be "this object may have been derived > from a signed type". Right? It's a property we can compute for any > given SSA_NAME and it's not context/path specific beyond the > context/path information encoded by the SSA graph. > > So just thinking out load here, could we walk the IL once to identify > call sites and build a worklist of SSA_NAMEs we care about. Then we > iterate on the worklist much like Aldy's code he's working on for the > unswitching vs uninitialized variable issue? Thanks for the suggestion. It occurred to me while working on the fix for 78973 (the non-bug) that size ranges should be handled the same by -Wstringop-overflow as by -Walloc-size-larger-than, and that both have the same problem: missing or incomplete support for anti-ranges. The attached patch moves get_size_range() from builtins.c to calls.c and adds better support for anti-ranges. That solves the problems also lets it get rid of the objectionable operand_positive_p function. Martin PS The change to the alloc_max_size function is only needed to make it possible to specify any argument to the -Walloc-size-larger-than option, including 0 and -1, so that allocations of any size, including zero can be flagged. PR tree-optimization/78775 - [7 Regression] ICE in maybe_warn_alloc_args_overflow gcc/ChangeLog: PR tree-optimization/78775 * builtins.c (get_size_range): Move... * calls.c: ...to here. (alloc_max_size): Accept zero argument. (operand_signed_p): Remove. (maybe_warn_alloc_args_overflow): Call get_size_range. * calls.h (get_size_range): Declare. gcc/testsuite/ChangeLog: PR tree-optimization/78775 * gcc.dg/attr-alloc_size-4.c: Add test cases. * gcc.dg/pr78775.c: New test. * gcc.dg/pr78973-2.c: New test. * gcc.dg/pr78973.c: New test. diff --git a/gcc/builtins.c b/gcc/builtins.c index 5b76dfd..bf68e31 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3031,42 +3031,6 @@ expand_builtin_memcpy_args (tree dest, tree src, tree len, rtx target, tree exp) return dest_addr; } -/* Fill the 2-element RANGE array with the minimum and maximum values - EXP is known to have and return true, otherwise null and return - false. */ - -static bool -get_size_range (tree exp, tree range[2]) -{ - if (tree_fits_uhwi_p (exp)) - { - range[0] = range[1] = exp; - return true; - } - - if (TREE_CODE (exp) == SSA_NAME) - { - wide_int min, max; - enum value_range_type range_type = get_range_info (exp, &min, &max); - - if (range_type == VR_RANGE) - { - /* Interpret the bound in the variable's type. */ - range[0] = wide_int_to_tree (TREE_TYPE (exp), min); - range[1] = wide_int_to_tree (TREE_TYPE (exp), max); - return true; - } - else if (range_type == VR_ANTI_RANGE) - { - /* FIXME: Handle anti-ranges. */ - } - } - - range[0] = NULL_TREE; - range[1] = NULL_TREE; - return false; -} - /* Try to verify that the sizes and lengths of the arguments to a string manipulation function given by EXP are within valid bounds and that the operation does not lead to buffer overflow. Arguments other than diff --git a/gcc/calls.c b/gcc/calls.c index b7bbec5..c0d60bb 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1197,92 +1197,189 @@ alloc_max_size (void) { alloc_object_size_limit = TYPE_MAX_VALUE (ssizetype); - unsigned HOST_WIDE_INT unit = 1; - - char *end; - errno = 0; - unsigned HOST_WIDE_INT limit - = warn_alloc_size_limit ? strtoull (warn_alloc_size_limit, &end, 10) : 0; - - if (limit && !errno) + if (warn_alloc_size_limit) { - if (end && *end) + char *end = NULL; + errno = 0; + unsigned HOST_WIDE_INT unit = 1; + unsigned HOST_WIDE_INT limit + = strtoull (warn_alloc_size_limit, &end, 10); + + if (!errno) { - /* Numeric option arguments are at most INT_MAX. Make it - possible to specify a larger value by accepting common - suffixes. */ - if (!strcmp (end, "kB")) - unit = 1000; - else if (!strcasecmp (end, "KiB") || strcmp (end, "KB")) - unit = 1024; - else if (!strcmp (end, "MB")) - unit = 1000LU * 1000; - else if (!strcasecmp (end, "MiB")) - unit = 1024LU * 1024; - else if (!strcasecmp (end, "GB")) - unit = 1000LU * 1000 * 1000; - else if (!strcasecmp (end, "GiB")) - unit = 1024LU * 1024 * 1024; - else if (!strcasecmp (end, "TB")) - unit = 1000LU * 1000 * 1000 * 1000; - else if (!strcasecmp (end, "TiB")) - unit = 1024LU * 1024 * 1024 * 1024; - else if (!strcasecmp (end, "PB")) - unit = 1000LU * 1000 * 1000 * 1000 * 1000; - else if (!strcasecmp (end, "PiB")) - unit = 1024LU * 1024 * 1024 * 1024 * 1024; - else if (!strcasecmp (end, "EB")) - unit = 1000LU * 1000 * 1000 * 1000 * 1000 * 1000; - else if (!strcasecmp (end, "EiB")) - unit = 1024LU * 1024 * 1024 * 1024 * 1024 * 1024; - else - unit = 0; - } + if (end && *end) + { + /* Numeric option arguments are at most INT_MAX. Make it + possible to specify a larger value by accepting common + suffixes. */ + if (!strcmp (end, "kB")) + unit = 1000; + else if (!strcasecmp (end, "KiB") || strcmp (end, "KB")) + unit = 1024; + else if (!strcmp (end, "MB")) + unit = 1000LU * 1000; + else if (!strcasecmp (end, "MiB")) + unit = 1024LU * 1024; + else if (!strcasecmp (end, "GB")) + unit = 1000LU * 1000 * 1000; + else if (!strcasecmp (end, "GiB")) + unit = 1024LU * 1024 * 1024; + else if (!strcasecmp (end, "TB")) + unit = 1000LU * 1000 * 1000 * 1000; + else if (!strcasecmp (end, "TiB")) + unit = 1024LU * 1024 * 1024 * 1024; + else if (!strcasecmp (end, "PB")) + unit = 1000LU * 1000 * 1000 * 1000 * 1000; + else if (!strcasecmp (end, "PiB")) + unit = 1024LU * 1024 * 1024 * 1024 * 1024; + else if (!strcasecmp (end, "EB")) + unit = 1000LU * 1000 * 1000 * 1000 * 1000 * 1000; + else if (!strcasecmp (end, "EiB")) + unit = 1024LU * 1024 * 1024 * 1024 * 1024 * 1024; + else + unit = 0; + } - if (unit) - alloc_object_size_limit = build_int_cst (ssizetype, limit * unit); + if (unit) + alloc_object_size_limit + = build_int_cst (ssizetype, limit * unit); + } } } return alloc_object_size_limit; } -/* Return true if the type of OP is signed, looking through any casts - to an unsigned type. */ +/* Return true when EXP's range can be determined and set RANGE[] to it + after adjusting it if necessary to make EXP a valid size argument to + an allocation function declared with attribute alloc_size (whose + argument may be signed), or to a string manipulation function like + memset. SIGNED_P is initially set to -1 and is used internally by + the function and should not be explicitly passed in by callers. */ -static bool -operand_signed_p (tree op) +bool +get_size_range (tree exp, tree range[2], int signed_p /* = -1 */) { - if (TREE_CODE (op) == SSA_NAME) + if (tree_fits_uhwi_p (exp)) + { + /* EXP is a constant. */ + range[0] = range[1] = exp; + return true; + } + + if (TREE_CODE (exp) != SSA_NAME) + { + /* No range information available. */ + range[0] = NULL_TREE; + range[1] = NULL_TREE; + return false; + } + + wide_int min, max; + enum value_range_type range_type = get_range_info (exp, &min, &max); + + tree exptype = TREE_TYPE (exp); + unsigned expprec = TYPE_PRECISION (exptype); + wide_int wzero = wi::zero (expprec); + + /* Set SIGNED_P once (will be used by recursive calls). */ + if (signed_p < 0) + signed_p = !TYPE_UNSIGNED (exptype); + + if (range_type == VR_VARYING) { - gimple *def = SSA_NAME_DEF_STMT (op); - if (is_gimple_assign (def)) + /* No range information available. */ + range[0] = NULL_TREE; + range[1] = NULL_TREE; + return false; + } + + if (range_type == VR_ANTI_RANGE) + { + if (TYPE_UNSIGNED (exptype) || wi::les_p (wzero, min)) { - /* In an assignment involving a cast, ignore the type - of the cast and consider the type of its operand. */ - tree_code code = gimple_assign_rhs_code (def); - if (code == NOP_EXPR) - op = gimple_assign_rhs1 (def); + /* EXP is either unsigned or strictly not in an unsigned + range. Set the result range using zero as the lower + bound if that's still a range or the upper bound if + using zero would result in [0, 0]. */ + if (wi::lts_p (wzero, min - 1)) + { + max = min - 1; + min = wzero; + } + else + { + min = max + 1; + max = wide_int (TYPE_MAX_VALUE (exptype)); + } } - else if (gimple_code (def) == GIMPLE_PHI) + else if (wi::les_p (max, wzero)) { - /* In a phi, a constant argument may be unsigned even - if in the source it's signed and negative. Ignore - those and consider the result of a phi signed if - all its non-constant operands are. */ - unsigned nargs = gimple_phi_num_args (def); - for (unsigned i = 0; i != nargs; ++i) + /* EXP is not in a strictly negative range. That means + it must be in some (not necessarily strictly) positive + range which includes zero. Since in signed to unsigned + conversions negative values end up converted to large + positive values, and otherwise they are not valid sizes, + the resulting range is in both cases [0, TYPE_MAX]. */ + min = wzero; + max = wide_int (TYPE_MAX_VALUE (exptype)); + } + else if (signed_p) + { + /* EXP is not in a negative-positive range and no conversion + is being performed. That means EXP is either negative, + or greater than max. Since negative sizes are invalid + make the range [MAX + 1, TYPE_MAX]. */ + min = max + 1; + max = wide_int (TYPE_MAX_VALUE (exptype)); + } + else + { + /* EXP is not in negative-positive range and it's being + converted to an unsigned. That means the negative + lower bound is inverted and the resulting range is + either [~(MIN - 1), MAX + 1] or [MAX + 1, ~(MIN - 1)], + whichever results in the lower bound being less than + the upper bound. */ + --min; + ++max; + + /* For a signed to unsigned conversion invert + the minimum. */ + min = ~min; + + if (wi::ltu_p (max, min)) { - tree op = gimple_phi_arg_def (def, i); - if (TREE_CODE (op) != INTEGER_CST - && !operand_signed_p (op)) - return false; + wide_int tmp = max; + max = min; + min = tmp; } - - return true; } } - return !TYPE_UNSIGNED (TREE_TYPE (op)); + if (TYPE_UNSIGNED (exptype) || !wi::neg_p (min) || signed_p) + { + /* EXP is either unsigned or in a non-negative range, + or the result is not being converted to unsigned. + Use its range as is. */ + range[0] = wide_int_to_tree (exptype, min); + range[1] = wide_int_to_tree (exptype, max); + } + else if (wi::neg_p (min) && wi::les_p (max, wzero)) + { + /* EXP is in a strictly negative range (or zero) and is + being converted to unsigned. Also use its range as is. */ + range[0] = wide_int_to_tree (exptype, min); + range[1] = wide_int_to_tree (exptype, max); + } + else + { + /* Otherwise, clear the lower bound if it's negative and + the upper bound is positive. */ + range[0] = integer_zero_node; + range[1] = wide_int_to_tree (exptype, max); + } + + return true; } /* Diagnose a call EXP to function FN decorated with attribute alloc_size @@ -1316,8 +1413,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) if (tree_int_cst_lt (args[i], integer_zero_node)) { warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "argument %i value %qE is negative", - idx[i] + 1, args[i]); + "%Kargument %i value %qE is negative", + exp, idx[i] + 1, args[i]); } else if (integer_zerop (args[i])) { @@ -1334,8 +1431,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) && !lookup_attribute ("returns_nonnull", TYPE_ATTRIBUTES (TREE_TYPE (fn))))) warned = warning_at (loc, OPT_Walloc_zero, - "argument %i value is zero", - idx[i] + 1); + "%Kargument %i value is zero", + exp, idx[i] + 1); } else if (tree_int_cst_lt (maxobjsize, args[i])) { @@ -1351,79 +1448,31 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) continue; warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "argument %i value %qE exceeds " + "%Kargument %i value %qE exceeds " "maximum object size %E", - idx[i] + 1, args[i], maxobjsize); + exp, idx[i] + 1, args[i], maxobjsize); } } - else if (TREE_CODE (args[i]) == SSA_NAME) + else if (TREE_CODE (args[i]) == SSA_NAME + && get_size_range (args[i], argrange[i])) { - tree type = TREE_TYPE (args[i]); - - wide_int min, max; - value_range_type range_type = get_range_info (args[i], &min, &max); - if (range_type == VR_RANGE) - { - argrange[i][0] = wide_int_to_tree (type, min); - argrange[i][1] = wide_int_to_tree (type, max); - } - else if (range_type == VR_ANTI_RANGE) - { - /* For an anti-range, if the type of the formal argument - is unsigned and the bounds of the range are of opposite - signs when interpreted as signed, check to see if the - type of the actual argument is signed. If so, the lower - bound must be taken to be zero (rather than a large - positive value corresonding to the actual lower bound - interpreted as unsigned) and there is nothing else that - can be inferred from it. */ - --min; - ++max; - wide_int zero = wi::uhwi (0, TYPE_PRECISION (type)); - if (TYPE_UNSIGNED (type) - && wi::lts_p (zero, min) && wi::lts_p (max, zero) - && operand_signed_p (args[i])) - continue; - - argrange[i][0] = wide_int_to_tree (type, max); - argrange[i][1] = wide_int_to_tree (type, min); - - /* Verify that the anti-range doesn't make all arguments - invalid (treat the anti-range ~[0, 0] as invalid). */ - if (tree_int_cst_lt (maxobjsize, argrange[i][0]) - && tree_int_cst_le (argrange[i][1], integer_zero_node)) - { - warned - = warning_at (loc, OPT_Walloc_size_larger_than_, - (TYPE_UNSIGNED (type) - ? G_("argument %i range [%E, %E] exceeds " - "maximum object size %E") - : G_("argument %i range [%E, %E] is both " - "negative and exceeds maximum object " - "size %E")), - idx[i] + 1, argrange[i][0], - argrange[i][1], maxobjsize); - } - continue; - } - else - continue; - /* Verify that the argument's range is not negative (including upper bound of zero). */ if (tree_int_cst_lt (argrange[i][0], integer_zero_node) && tree_int_cst_le (argrange[i][1], integer_zero_node)) { warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "argument %i range [%E, %E] is negative", - idx[i] + 1, argrange[i][0], argrange[i][1]); + "%Kargument %i range [%E, %E] is negative", + exp, idx[i] + 1, + argrange[i][0], argrange[i][1]); } else if (tree_int_cst_lt (maxobjsize, argrange[i][0])) { warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "argument %i range [%E, %E] exceeds " + "%Kargument %i range [%E, %E] exceeds " "maximum object size %E", - idx[i] + 1, argrange[i][0], argrange[i][1], + exp, idx[i] + 1, + argrange[i][0], argrange[i][1], maxobjsize); } } @@ -1450,15 +1499,15 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) if (vflow) warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "product %<%E * %E%> of arguments %i and %i " + "%Kproduct %<%E * %E%> of arguments %i and %i " "exceeds %", - argrange[0][0], argrange[1][0], + exp, argrange[0][0], argrange[1][0], idx[0] + 1, idx[1] + 1); else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod)) warned = warning_at (loc, OPT_Walloc_size_larger_than_, - "product %<%E * %E%> of arguments %i and %i " + "%Kproduct %<%E * %E%> of arguments %i and %i " "exceeds maximum object size %E", - argrange[0][0], argrange[1][0], + exp, argrange[0][0], argrange[1][0], idx[0] + 1, idx[1] + 1, maxobjsize); diff --git a/gcc/calls.h b/gcc/calls.h index e87fbda..ed4b75b 100644 --- a/gcc/calls.h +++ b/gcc/calls.h @@ -38,5 +38,6 @@ extern bool pass_by_reference (CUMULATIVE_ARGS *, machine_mode, extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode, tree, bool); extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]); +extern bool get_size_range (tree, tree[2], int = -1); #endif // GCC_CALLS_H diff --git a/gcc/testsuite/gcc.dg/attr-alloc_size-4.c b/gcc/testsuite/gcc.dg/attr-alloc_size-4.c index 6b70a85..5ce593e 100644 --- a/gcc/testsuite/gcc.dg/attr-alloc_size-4.c +++ b/gcc/testsuite/gcc.dg/attr-alloc_size-4.c @@ -128,15 +128,22 @@ test_int_range (int n) sink (f_int_1 (SR (min, 1234))); sink (f_int_1 (SR (-2, -1))); /* { dg-warning "argument 1 range \\\[-2, -1\\\] is negative" } */ + sink (f_int_1 (SR (1235, 2345))); /* { dg-warning "argument 1 range \\\[1235, 2345\\\] exceeds maximum object size 1234" } */ sink (f_int_1 (SR (max - 1, max))); /* { dg-warning "argument 1 range \\\[\[0-9\]+, \[0-9\]+\\\] exceeds maximum object size 1234" } */ sink (f_int_1 (SAR (-1, 1))); sink (f_int_1 (SAR (-2, 12))); sink (f_int_1 (SAR (-3, 123))); - sink (f_int_1 (SAR (-4, 1234))); /* { dg-warning "argument 1 range \\\[1235, -5\\\] is both negative and exceeds maximum object size 1234" } */ + sink (f_int_1 (SAR (-4, 1234))); /* { dg-warning "argument 1 range \\\[1235, \[0-9\]+\\\] exceeds maximum object size 1234" } */ sink (f_int_1 (SAR (min + 1, 1233))); - sink (f_int_1 (SAR (min + 2, 1235))); /* { dg-warning "argument 1 range \\\[1236, -\[0-9\]+\\\] is both negative and exceeds maximum object size 1234" } */ + sink (f_int_1 (SAR (min + 2, 1235))); /* { dg-warning "argument 1 range \\\[1236, \[0-9\]+\\\] exceeds maximum object size 1234" } */ + sink (f_int_1 (SAR (0, max))); /* { dg-warning "argument 1 range \\\[-\[0-9\]*, -1\\\] is negative" } */ + /* The range below includes zero which would be diagnosed by + -Walloc-size-zero but since all other values are negative it + is diagnosed by -Walloc-size-larger-than. */ + sink (f_int_1 (SAR (1, max))); /* { dg-warning "argument 1 range \\\[-\[0-9\]*, 0\\\] is negative" } */ + sink (f_int_1 (SAR (2, max))); } void diff --git a/gcc/testsuite/gcc.dg/pr78775.c b/gcc/testsuite/gcc.dg/pr78775.c new file mode 100644 index 0000000..120c252 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr78775.c @@ -0,0 +1,19 @@ +/* PR c/78775 - [7 Regression] ICE in maybe_warn_alloc_args_overflow + { dg-do compile } + { dg-options "-O2" } */ + +int a, b, *c; + +int main (void) +{ + unsigned long d = 0; + while (1) + { + switch (b) + case 'S': + d = a; + c = __builtin_malloc (d); + } + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr78973-2.c b/gcc/testsuite/gcc.dg/pr78973-2.c new file mode 100644 index 0000000..dadec16 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr78973-2.c @@ -0,0 +1,25 @@ +/* PR c/78973 - warning: ‘memcpy’: specified size exceeds maximum object + size [-Wstringop-overflow=] + + This is a companion test for the bug above that verifies that the correct + range of the int variable is detected. + + { dg-do compile } + { dg-require-effective-target int32plus } + { dg-options "-O2 -Walloc-size-larger-than=4" } */ + +void *p; + +void f (int n) +{ + if (n <= 4) + p = __builtin_malloc (n); + /* { dg-warning "argument 1 range \\\[5, 2147483647\\\] exceeds maximum object size 4" "ilp32" { xfail { ! lp64 } } .-1 } */ +} + +void g (unsigned n) +{ + if (n < 5) + n = 5; + f (n); +} diff --git a/gcc/testsuite/gcc.dg/pr78973.c b/gcc/testsuite/gcc.dg/pr78973.c new file mode 100644 index 0000000..a6195f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr78973.c @@ -0,0 +1,20 @@ +/* PR c/78973 - warning: ‘memcpy’: specified size exceeds maximum object size + + Test case for what was initially thought to be a false positive but after + deeper investigation turned out to be a true positive. + + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +void f (void *p, int n) +{ + if (n <= 4) + __builtin_memset (p, 0, n); /* { dg-warning "exceeds maximum object size" } */ +} + +void g (void *d, unsigned n) +{ + if (n < 5) + n = 5; + f (d, n); +}