From patchwork Sun Jul 29 10:56:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Edlinger X-Patchwork-Id: 950570 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-482603-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=hotmail.de Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="kTxtJO27"; dkim-atps=neutral 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 41dflz0CvCz9s0R for ; Sun, 29 Jul 2018 20:57:00 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:content-type:mime-version; q=dns; s= default; b=s385jrxlUS3Gm214qQFgdNFTOiexJAXi2+9u2V3A52RpJYqfaF1Yc D/RzoQN0NAy35MSo6XzweGLqjQhYVUkrtzKfDNna5plZy2r25iyMixQ6XENJ9gKe +dXcqTdTWuornFEA4+KcIIZEE73MJYv/wZmIvCS7Z8I1ddyMKPnG3E= 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 :to:subject:date:message-id:content-type:mime-version; s= default; bh=pnKyMqk5eCuKq07djacn1h/cRsU=; b=kTxtJO27ely8pGepmAq3 2r+nlMfw1eYbdZhoA6v8I8+HgtcrVGU0L82jFC6u54vh3Klafn9uI3s0Cf+F4wbD r96CeJCFYk59HjqvMiAEETzaVmUxBWWRlzplJTqHMkELO71OzdnX/BB4Ld4Afr2A RbvOXcQhIRUhLVA1L3n5tUg= Received: (qmail 118431 invoked by alias); 29 Jul 2018 10:56:52 -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 118422 invoked by uid 89); 29 Jul 2018 10:56:51 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-10.8 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=contribute, integer_cst, H*r:sk:VE1EUR0, Hx-spam-relays-external:sk:VE1EUR0 X-HELO: EUR01-HE1-obe.outbound.protection.outlook.com Received: from mail-oln040092065013.outbound.protection.outlook.com (HELO EUR01-HE1-obe.outbound.protection.outlook.com) (40.92.65.13) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 29 Jul 2018 10:56:48 +0000 Received: from VE1EUR01FT055.eop-EUR01.prod.protection.outlook.com (10.152.2.58) by VE1EUR01HT103.eop-EUR01.prod.protection.outlook.com (10.152.3.111) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.20.995.12; Sun, 29 Jul 2018 10:56:45 +0000 Received: from DB6PR0701MB2664.eurprd07.prod.outlook.com (10.152.2.54) by VE1EUR01FT055.mail.protection.outlook.com (10.152.3.104) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.20.995.12 via Frontend Transport; Sun, 29 Jul 2018 10:56:44 +0000 Received: from DB6PR0701MB2664.eurprd07.prod.outlook.com ([fe80::7534:c74e:4feb:cbda]) by DB6PR0701MB2664.eurprd07.prod.outlook.com ([fe80::7534:c74e:4feb:cbda%8]) with mapi id 15.20.1017.010; Sun, 29 Jul 2018 10:56:44 +0000 From: Bernd Edlinger To: "gcc-patches@gcc.gnu.org" , Richard Biener , Jeff Law , Jakub Jelinek , Martin Sebor Subject: [PATCH] Fix wrong code with truncated string literals (PR 86711/86714) Date: Sun, 29 Jul 2018 10:56:44 +0000 Message-ID: received-spf: None (protection.outlook.com: hotmail.de does not designate permitted sender hosts) authentication-results: spf=none (sender IP is ) smtp.mailfrom=bernd.edlinger@hotmail.de; MIME-Version: 1.0 Hi! This fixes two wrong code bugs where string_constant returns over length string constants. Initializers like that are rejected in C++, but valid in C. I have xfailed strlenopt-49.c, which tests this feature. Personally I don't think that it is worth the effort to optimize something that is per se invalid in C++. The hunk in builtins.c is unrelated, but I would like to use tree_to_shwi here, to be in line with the tree_fits_shwi_p check above, and the rest of that function which uses signed HWI throughout. Bootstrapped and reg-tested on x86_64-pc-linux-gnu. Is it OK for trunk? Thanks Bernd. gcc: 2018-07-29 Bernd Edlinger PR middle-end/86711 PR middle-end/86714 * builtins.c (c_strlen): Use tree_to_shwi because maxelts is signed. * expr.c (string_constant): Don't return truncated string literals. * fold-const.c (c_getstr): Fix function comment. Remove unused third argument. Fix range checks. * fold-const.c (c_getstr): Adjust protoype. testsuite: 2018-07-29 Bernd Edlinger PR middle-end/86711 PR middle-end/86714 * gcc.c-torture/execute/pr86711.c: New test. * gcc.c-torture/execute/pr86714.c: New test. * gcc.dg/strlenopt-49.c: Add xfail. Index: gcc/builtins.c =================================================================== --- gcc/builtins.c (revision 263045) +++ gcc/builtins.c (working copy) @@ -617,7 +617,7 @@ c_strlen (tree src, int only_value) if (tree size = TYPE_SIZE_UNIT (type)) if (tree_fits_shwi_p (size)) { - maxelts = tree_to_uhwi (size); + maxelts = tree_to_shwi (size); maxelts = maxelts / eltsize - 1; } Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 263045) +++ gcc/expr.c (working copy) @@ -11410,24 +11410,14 @@ string_constant (tree arg, tree *ptr_offset) if (!init || TREE_CODE (init) != STRING_CST) return NULL_TREE; - tree array_size = DECL_SIZE_UNIT (array); - if (!array_size || TREE_CODE (array_size) != INTEGER_CST) - return NULL_TREE; - /* Avoid returning a string that doesn't fit in the array - it is stored in, like - const char a[4] = "abcde"; - but do handle those that fit even if they have excess - initializers, such as in - const char a[4] = "abc\000\000"; - The excess elements contribute to TREE_STRING_LENGTH() - but not to strlen(). */ - unsigned HOST_WIDE_INT charsize - = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (init)))); - unsigned HOST_WIDE_INT length = TREE_STRING_LENGTH (init); - length = string_length (TREE_STRING_POINTER (init), charsize, - length / charsize); - if (compare_tree_int (array_size, length + 1) < 0) + it is stored in, like: + const char a[4] = "abcd"; + because callers expect to be able to access the string + up to the limit imposed by TREE_STRING_LENGTH which + always includes the terminating NUL char. */ + if (compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (init)), + TREE_STRING_LENGTH (init)) < 0) return NULL_TREE; *ptr_offset = offset; Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 263045) +++ gcc/fold-const.c (working copy) @@ -14577,16 +14577,12 @@ fold_build_pointer_plus_hwi_loc (location_t loc, t /* Return a pointer P to a NUL-terminated string representing the sequence of constant characters referred to by SRC (or a subsequence of such characters within it if SRC is a reference to a string plus some - constant offset). If STRLEN is non-null, store stgrlen(P) in *STRLEN. - If STRSIZE is non-null, store in *STRSIZE the size of the array - the string is stored in; in that case, even though P points to a NUL - terminated string, SRC need not refer to one. This can happen when - SRC refers to a constant character array initialized to all non-NUL - values, as in the C declaration: char a[4] = "1234"; */ + constant offset). If STRLEN is non-null, store the number of bytes + in the string constant including the terminating NUL char. *STRLEN is + typically strlen(P) + 1 in the absence of embedded NUL characters. */ const char * -c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */, - unsigned HOST_WIDE_INT *strsize /* = NULL */) +c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */) { tree offset_node; @@ -14613,40 +14609,24 @@ const char * unsigned HOST_WIDE_INT string_size = string_length; tree type = TREE_TYPE (src); if (tree size = TYPE_SIZE_UNIT (type)) - if (tree_fits_shwi_p (size)) + if (tree_fits_uhwi_p (size)) string_size = tree_to_uhwi (size); + if (offset >= string_size) + return NULL; + if (strlen) { /* Compute and store the length of the substring at OFFSET. All offsets past the initial length refer to null strings. */ - if (offset <= string_length) + if (offset < string_length) *strlen = string_length - offset; else - *strlen = 0; + *strlen = 1; } const char *string = TREE_STRING_POINTER (src); - - if (string_length == 0 - || offset >= string_size) - return NULL; - - if (strsize) - { - /* Support even constant character arrays that aren't proper - NUL-terminated strings. */ - *strsize = string_size; - } - else if (string[string_length - 1] != '\0') - { - /* Support only properly NUL-terminated strings but handle - consecutive strings within the same array, such as the six - substrings in "1\0002\0003". */ - return NULL; - } - - return offset <= string_length ? string + offset : ""; + return offset < string_length ? string + offset : ""; } /* Given a tree T, compute which bits in T may be nonzero. */ Index: gcc/fold-const.h =================================================================== --- gcc/fold-const.h (revision 263045) +++ gcc/fold-const.h (working copy) @@ -187,8 +187,7 @@ extern bool expr_not_equal_to (tree t, const wide_ extern tree const_unop (enum tree_code, tree, tree); extern tree const_binop (enum tree_code, tree, tree, tree); extern bool negate_mathfn_p (combined_fn); -extern const char *c_getstr (tree, unsigned HOST_WIDE_INT * = NULL, - unsigned HOST_WIDE_INT * = NULL); +extern const char *c_getstr (tree, unsigned HOST_WIDE_INT * = NULL); extern wide_int tree_nonzero_bits (const_tree); /* Return OFF converted to a pointer offset type suitable as offset for Index: gcc/testsuite/gcc.c-torture/execute/pr86711.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/pr86711.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr86711.c (working copy) @@ -0,0 +1,11 @@ +/* PR middle-end/86711 */ + +static const char a[2][4] = { "1234", "5678" }; + +int main () +{ + void *p = __builtin_memchr (a, 0, 5); + + if (p) + __builtin_abort (); +} Index: gcc/testsuite/gcc.c-torture/execute/pr86714.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/pr86714.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr86714.c (working copy) @@ -0,0 +1,12 @@ +/* PR middle-end/86714 */ + +const char a[2][3] = { "1234", "xyz" }; +char b[6]; + +int main () +{ + __builtin_memcpy (b, a, 4); + __builtin_memset (b + 4, 'a', 2); + if (__builtin_memcmp (b, "123xaa", 6)) + __builtin_abort (); +} Index: gcc/testsuite/gcc.dg/strlenopt-49.c =================================================================== --- gcc/testsuite/gcc.dg/strlenopt-49.c (revision 263045) +++ gcc/testsuite/gcc.dg/strlenopt-49.c (working copy) @@ -45,9 +45,9 @@ int cmp88 (void) return cmp88; } -/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } } - { dg-final { scan-tree-dump-times "len0 = 0;" 1 "gimple" } } - { dg-final { scan-tree-dump-times "len = 18;" 1 "gimple" } } - { dg-final { scan-tree-dump-times "lenx = 8;" 1 "gimple" } } - { dg-final { scan-tree-dump-times "leny = 0;" 1 "gimple" } } - { dg-final { scan-tree-dump-times "cmp88 = 0;" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" { xfail *-*-* } } } + { dg-final { scan-tree-dump-times "len0 = 0;" 1 "gimple" { xfail *-*-* } } } + { dg-final { scan-tree-dump-times "len = 18;" 1 "gimple" { xfail *-*-* } } } + { dg-final { scan-tree-dump-times "lenx = 8;" 1 "gimple" { xfail *-*-* } } } + { dg-final { scan-tree-dump-times "leny = 0;" 1 "gimple" { xfail *-*-* } } } + { dg-final { scan-tree-dump-times "cmp88 = 0;" 1 "gimple" { xfail *-*-* } } } */