From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from crocodile.elm.relay.mailchannels.net (crocodile.elm.relay.mailchannels.net [23.83.212.45]) by sourceware.org (Postfix) with ESMTPS id 8D115385829A for ; Fri, 4 Nov 2022 13:47:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8D115385829A Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gotplt.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gotplt.org X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 44C418815E6; Fri, 4 Nov 2022 13:47:32 +0000 (UTC) Received: from pdx1-sub0-mail-a306.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id BBF038814F5; Fri, 4 Nov 2022 13:47:31 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1667569651; a=rsa-sha256; cv=none; b=qe27DGEQyef1QxDFOMWXExF4WTcGRY6qp2/G2Vf0RqnNXUf4pMAlYmmdUUkMSQrhbEwoHY pYVaRFOY83dtkgRE0UaCooHdcdGC/Jc9b5JZ4OmCVfkc84N5bY15eOgeYYNXCqf5F70s98 28qu3KsjDtaoO0XHQK8spajnqUQ7AFQ64cKVwCXA+gJ2G9NrCCqrEDHibI1F8lN5j2814k MnZZbk4zB/biZjEQIR1bqSol1b09wMfC9MUgB3XbQXMONyqC0QEpiSujFeN52FfXdMWHHP JUCztjMNPeCk5ALS10TisUJjjq+ka3ohnvHbRuXur+y4yRmw9Gp7h5p7HyNamw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1667569651; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=KP/EOnR8U0I9WsxvLMoMD++Gn3IatHQXjkUoYU3PkEg=; b=rnur5qAjTTBqhOlnXJIZ5AP0wxwaibHNW9DYKF86dVegxnX0eGVRkYn9gSd5wxgqDwC+PM wB3woWxchjrqTGjPLE0f7mw1y79cXOOtc8lIZSru0qztunIICJiN9JA9e7x6yst+22mC5L dqYA5wJOv5hIo/dQ8DSyF6wANJURQmFY3jrlNAh7blw4BwJrWk+Q5sw65rNxjnDSzUVwt3 uOow5KGEHnn+tIVNYleIXsbCcfyUfaipZpZroQVwgQTMzwtHKEx9OWorvw2+6YLMKYRVgn A4FkUntisGYTtNd3L4LOb4yxt8RA9UynqNxgLePmLXMftV7NQ892So6yu6ov6Q== ARC-Authentication-Results: i=1; rspamd-5cb65d95c4-d2jjj; auth=pass smtp.auth=dreamhost smtp.mailfrom=siddhesh@gotplt.org X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-Lonely-Hysterical: 3b3d4bff597ed571_1667569652058_3644954030 X-MC-Loop-Signature: 1667569652057:1232646592 X-MC-Ingress-Time: 1667569652057 Received: from pdx1-sub0-mail-a306.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.105.95.137 (trex/6.7.1); Fri, 04 Nov 2022 13:47:32 +0000 Received: from [192.168.0.182] (bras-vprn-toroon4834w-lp130-15-184-147-71-211.dsl.bell.ca [184.147.71.211]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: siddhesh@gotplt.org) by pdx1-sub0-mail-a306.dreamhost.com (Postfix) with ESMTPSA id 4N3hl70wg9zGH; Fri, 4 Nov 2022 06:47:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gotplt.org; s=dreamhost; t=1667569651; bh=KP/EOnR8U0I9WsxvLMoMD++Gn3IatHQXjkUoYU3PkEg=; h=Date:Subject:To:Cc:From:Content-Type:Content-Transfer-Encoding; b=Lc8CYDQNQpxvZJtraAqzjOks3AO0svAcPo3bCUD5HlchJM3uBEiVy3aHeXG8+eqTJ VP86oyPvlgRj7EbByV/Q87ntxG/YTwPth3B/fNHELIx43vA/wGcIYRH0AdW4c4kZ3H dsavgdgaPJNqQGIjNIAawhrnB/+IkCUkrrDK2SyyiU4FU0/HD7Zq5+5n91r/rJ68Oo N68igmZmngn9u+yCS8YPiOpLUV5+wJYcgjpV1p8ICWtfa41G9igrb5kRj6ehhokpsw Eflgjy0Zj91mD1vlDBhF1TVFjRg3syC73Spz/aovo0Y3KDEGdfuoIdBWURIASo3lnz RIKV4zR4jS8ig== Message-ID: <0519cbc0-31f4-5ae2-0e44-cef59a563a49@gotplt.org> Date: Fri, 4 Nov 2022 09:47:29 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.4.0 Subject: Re: [PATCH v2] tree-object-size: Support strndup and strdup Content-Language: en-US To: Prathamesh Kulkarni Cc: gcc-patches@gcc.gnu.org, jakub@redhat.com References: <20220815192311.763473-1-siddhesh@gotplt.org> <20221104124800.910588-1-siddhesh@gotplt.org> From: Siddhesh Poyarekar In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-3037.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 2022-11-04 09:43, Prathamesh Kulkarni wrote: > On Fri, 4 Nov 2022 at 18:18, Siddhesh Poyarekar wrote: >> >> Use string length of input to strdup to determine the usable size of the >> resulting object. Avoid doing the same for strndup since there's a >> chance that the input may be too large, resulting in an unnecessary >> overhead or worse, the input may not be NULL terminated, resulting in a >> crash where there would otherwise have been none. >> >> gcc/ChangeLog: >> >> * tree-object-size.cc (todo): New variable. >> (object_sizes_execute): Use it. >> (strdup_object_size): New function. >> (call_object_size): Use it. >> >> gcc/testsuite/ChangeLog: >> >> * gcc.dg/builtin-dynamic-object-size-0.c (test_strdup, >> test_strndup, test_strdup_min, test_strndup_min): New tests. >> (main): Call them. >> * gcc.dg/builtin-dynamic-object-size-1.c: Silence overread >> warnings. >> * gcc.dg/builtin-dynamic-object-size-2.c: Likewise. >> * gcc.dg/builtin-dynamic-object-size-3.c: Likewise. >> * gcc.dg/builtin-dynamic-object-size-4.c: Likewise. >> * gcc.dg/builtin-object-size-1.c: Silence overread warnings. >> Declare free, strdup and strndup. >> (test11): New test. >> (main): Call it. >> * gcc.dg/builtin-object-size-2.c: Silence overread warnings. >> Declare free, strdup and strndup. >> (test9): New test. >> (main): Call it. >> * gcc.dg/builtin-object-size-3.c: Silence overread warnings. >> Declare free, strdup and strndup. >> (test11): New test. >> (main): Call it. >> * gcc.dg/builtin-object-size-4.c: Silence overread warnings. >> Declare free, strdup and strndup. >> (test9): New test. >> (main): Call it. >> --- >> Tested: >> >> - x86_64 bootstrap and testsuite run >> - i686 build and testsuite run >> - ubsan bootstrap >> >> .../gcc.dg/builtin-dynamic-object-size-0.c | 43 +++++++++ >> .../gcc.dg/builtin-dynamic-object-size-1.c | 2 +- >> .../gcc.dg/builtin-dynamic-object-size-2.c | 2 +- >> .../gcc.dg/builtin-dynamic-object-size-3.c | 2 +- >> .../gcc.dg/builtin-dynamic-object-size-4.c | 2 +- >> gcc/testsuite/gcc.dg/builtin-object-size-1.c | 94 +++++++++++++++++- >> gcc/testsuite/gcc.dg/builtin-object-size-2.c | 94 +++++++++++++++++- >> gcc/testsuite/gcc.dg/builtin-object-size-3.c | 95 ++++++++++++++++++- >> gcc/testsuite/gcc.dg/builtin-object-size-4.c | 94 +++++++++++++++++- >> gcc/tree-object-size.cc | 84 +++++++++++++++- >> 10 files changed, 502 insertions(+), 10 deletions(-) >> >> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c >> index 01a280b2d7b..4f1606a486b 100644 >> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c >> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c >> @@ -479,6 +479,40 @@ test_loop (int *obj, size_t sz, size_t start, size_t end, int incr) >> return __builtin_dynamic_object_size (ptr, 0); >> } >> >> +/* strdup/strndup. */ >> + >> +size_t >> +__attribute__ ((noinline)) >> +test_strdup (const char *in) >> +{ >> + char *res = __builtin_strdup (in); >> + return __builtin_dynamic_object_size (res, 0); >> +} >> + >> +size_t >> +__attribute__ ((noinline)) >> +test_strndup (const char *in, size_t bound) >> +{ >> + char *res = __builtin_strndup (in, bound); >> + return __builtin_dynamic_object_size (res, 0); >> +} >> + >> +size_t >> +__attribute__ ((noinline)) >> +test_strdup_min (const char *in) >> +{ >> + char *res = __builtin_strdup (in); >> + return __builtin_dynamic_object_size (res, 2); >> +} >> + >> +size_t >> +__attribute__ ((noinline)) >> +test_strndup_min (const char *in, size_t bound) >> +{ >> + char *res = __builtin_strndup (in, bound); >> + return __builtin_dynamic_object_size (res, 2); >> +} >> + >> /* Other tests. */ >> >> struct TV4 >> @@ -651,6 +685,15 @@ main (int argc, char **argv) >> int *t = test_pr105736 (&val3); >> if (__builtin_dynamic_object_size (t, 0) != -1) >> FAIL (); >> + const char *str = "hello world"; >> + if (test_strdup (str) != __builtin_strlen (str) + 1) >> + FAIL (); >> + if (test_strndup (str, 4) != 5) >> + FAIL (); >> + if (test_strdup_min (str) != __builtin_strlen (str) + 1) >> + FAIL (); >> + if (test_strndup_min (str, 4) != 1) >> + FAIL (); >> >> if (nfails > 0) >> __builtin_abort (); >> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c >> index 7cc8b1c9488..8f17c8edcaf 100644 >> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c >> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c >> @@ -1,5 +1,5 @@ >> /* { dg-do run } */ >> -/* { dg-options "-O2" } */ >> +/* { dg-options "-O2 -Wno-stringop-overread" } */ >> /* { dg-require-effective-target alloca } */ >> >> #define __builtin_object_size __builtin_dynamic_object_size >> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c >> index 267dbf48ca7..3677782ff1c 100644 >> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c >> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c >> @@ -1,5 +1,5 @@ >> /* { dg-do run } */ >> -/* { dg-options "-O2" } */ >> +/* { dg-options "-O2 -Wno-stringop-overread" } */ >> /* { dg-require-effective-target alloca } */ >> >> #define __builtin_object_size __builtin_dynamic_object_size >> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c >> index fb9dc56da7e..5b6987b7773 100644 >> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c >> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c >> @@ -1,5 +1,5 @@ >> /* { dg-do run } */ >> -/* { dg-options "-O2" } */ >> +/* { dg-options "-O2 -Wno-stringop-overread" } */ >> /* { dg-require-effective-target alloca } */ >> >> #define __builtin_object_size __builtin_dynamic_object_size >> diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c >> index 870548b4206..9d796224e96 100644 >> --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c >> +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c >> @@ -1,5 +1,5 @@ >> /* { dg-do run } */ >> -/* { dg-options "-O2" } */ >> +/* { dg-options "-O2 -Wno-stringop-overread" } */ >> /* { dg-require-effective-target alloca } */ >> >> #define __builtin_object_size __builtin_dynamic_object_size >> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-1.c b/gcc/testsuite/gcc.dg/builtin-object-size-1.c >> index b772e2da9b9..c6e5b4c29f8 100644 >> --- a/gcc/testsuite/gcc.dg/builtin-object-size-1.c >> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-1.c >> @@ -1,5 +1,5 @@ >> /* { dg-do run } */ >> -/* { dg-options "-O2" } */ >> +/* { dg-options "-O2 -Wno-stringop-overread" } */ >> /* { dg-require-effective-target alloca } */ >> >> typedef __SIZE_TYPE__ size_t; >> @@ -7,10 +7,13 @@ extern void abort (void); >> extern void exit (int); >> extern void *malloc (size_t); >> extern void *calloc (size_t, size_t); >> +extern void free (void *); >> extern void *alloca (size_t); >> extern void *memcpy (void *, const void *, size_t); >> extern void *memset (void *, int, size_t); >> extern char *strcpy (char *, const char *); >> +extern char *strdup (const char *); >> +extern char *strndup (const char *, size_t); >> >> struct A >> { >> @@ -629,6 +632,94 @@ test10 (void) >> } >> } >> >> +/* Tests for strdup/strndup. */ >> +size_t >> +__attribute__ ((noinline)) >> +test11 (void) >> +{ >> + int i = 0; >> + const char *ptr = "abcdefghijklmnopqrstuvwxyz"; >> + char *res = strndup (ptr, 21); >> + if (__builtin_object_size (res, 0) != 22) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr, 32); >> + if (__builtin_object_size (res, 0) != 27) >> + abort (); >> + >> + free (res); >> + >> + res = strdup (ptr); >> + if (__builtin_object_size (res, 0) != 27) >> + abort (); >> + >> + free (res); >> + >> + char *ptr2 = malloc (64); >> + strcpy (ptr2, ptr); >> + >> + res = strndup (ptr2, 21); >> + if (__builtin_object_size (res, 0) != 22) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr2, 32); >> + if (__builtin_object_size (res, 0) != 33) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr2, 128); >> + if (__builtin_object_size (res, 0) != 64) >> + abort (); >> + >> + free (res); >> + >> + res = strdup (ptr2); >> +#ifdef __builtin_object_size >> + if (__builtin_object_size (res, 0) != 27) >> +#else >> + if (__builtin_object_size (res, 0) != (size_t) -1) >> +#endif >> + abort (); >> + free (res); >> + free (ptr2); >> + >> + ptr = "abcd\0efghijklmnopqrstuvwxyz"; >> + res = strdup (ptr); >> + if (__builtin_object_size (res, 0) != 5) >> + abort (); >> + free (res); >> + >> + res = strndup (ptr, 24); >> + if (__builtin_object_size (res, 0) != 5) >> + abort (); >> + free (res); >> + >> + res = strndup (ptr, 2); >> + if (__builtin_object_size (res, 0) != 3) >> + abort (); >> + free (res); >> + >> + res = strdup (&ptr[4]); >> + if (__builtin_object_size (res, 0) != 1) >> + abort (); >> + free (res); >> + >> + res = strndup (&ptr[4], 4); >> + if (__builtin_object_size (res, 0) != 1) >> + abort (); >> + free (res); >> + >> + res = strndup (&ptr[4], 1); >> + if (__builtin_object_size (res, 0) != 1) >> + abort (); >> + free (res); >> +} >> + >> int >> main (void) >> { >> @@ -644,5 +735,6 @@ main (void) >> test8 (); >> test9 (1); >> test10 (); >> + test11 (); >> exit (0); >> } >> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-2.c b/gcc/testsuite/gcc.dg/builtin-object-size-2.c >> index 2729538da17..639a83cfd39 100644 >> --- a/gcc/testsuite/gcc.dg/builtin-object-size-2.c >> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-2.c >> @@ -1,5 +1,5 @@ >> /* { dg-do run } */ >> -/* { dg-options "-O2" } */ >> +/* { dg-options "-O2 -Wno-stringop-overread" } */ >> /* { dg-require-effective-target alloca } */ >> >> typedef __SIZE_TYPE__ size_t; >> @@ -7,10 +7,13 @@ extern void abort (void); >> extern void exit (int); >> extern void *malloc (size_t); >> extern void *calloc (size_t, size_t); >> +extern void free (void *); >> extern void *alloca (size_t); >> extern void *memcpy (void *, const void *, size_t); >> extern void *memset (void *, int, size_t); >> extern char *strcpy (char *, const char *); >> +extern char *strdup (const char *); >> +extern char *strndup (const char *, size_t); >> >> struct A >> { >> @@ -544,6 +547,94 @@ test8 (unsigned cond) >> #endif >> } >> >> +/* Tests for strdup/strndup. */ >> +size_t >> +__attribute__ ((noinline)) >> +test9 (void) >> +{ >> + const char *ptr = "abcdefghijklmnopqrstuvwxyz"; >> + char *res = strndup (ptr, 21); >> + if (__builtin_object_size (res, 1) != 22) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr, 32); >> + if (__builtin_object_size (res, 1) != 27) >> + abort (); >> + >> + free (res); >> + >> + res = strdup (ptr); >> + if (__builtin_object_size (res, 1) != 27) >> + abort (); >> + >> + free (res); >> + >> + char *ptr2 = malloc (64); >> + strcpy (ptr2, ptr); >> + >> + res = strndup (ptr2, 21); >> + if (__builtin_object_size (res, 1) != 22) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr2, 32); >> + if (__builtin_object_size (res, 1) != 33) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr2, 128); >> + if (__builtin_object_size (res, 1) != 64) >> + abort (); >> + >> + free (res); >> + >> + res = strdup (ptr2); >> +#ifdef __builtin_object_size >> + if (__builtin_object_size (res, 1) != 27) >> +#else >> + if (__builtin_object_size (res, 1) != (size_t) -1) >> +#endif >> + abort (); >> + >> + free (res); >> + free (ptr2); >> + >> + ptr = "abcd\0efghijklmnopqrstuvwxyz"; >> + res = strdup (ptr); >> + if (__builtin_object_size (res, 1) != 5) >> + abort (); >> + free (res); >> + >> + res = strndup (ptr, 24); >> + if (__builtin_object_size (res, 1) != 5) >> + abort (); >> + free (res); >> + >> + res = strndup (ptr, 2); >> + if (__builtin_object_size (res, 1) != 3) >> + abort (); >> + free (res); >> + >> + res = strdup (&ptr[4]); >> + if (__builtin_object_size (res, 1) != 1) >> + abort (); >> + free (res); >> + >> + res = strndup (&ptr[4], 4); >> + if (__builtin_object_size (res, 1) != 1) >> + abort (); >> + free (res); >> + >> + res = strndup (&ptr[4], 1); >> + if (__builtin_object_size (res, 1) != 1) >> + abort (); >> + free (res); >> +} >> + >> int >> main (void) >> { >> @@ -557,5 +648,6 @@ main (void) >> test6 (); >> test7 (); >> test8 (1); >> + test9 (); >> exit (0); >> } >> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-3.c b/gcc/testsuite/gcc.dg/builtin-object-size-3.c >> index 44a99189776..ff4f1747334 100644 >> --- a/gcc/testsuite/gcc.dg/builtin-object-size-3.c >> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-3.c >> @@ -1,5 +1,5 @@ >> /* { dg-do run } */ >> -/* { dg-options "-O2" } */ >> +/* { dg-options "-O2 -Wno-stringop-overread" } */ >> /* { dg-require-effective-target alloca } */ >> >> typedef __SIZE_TYPE__ size_t; >> @@ -7,10 +7,13 @@ extern void abort (void); >> extern void exit (int); >> extern void *malloc (size_t); >> extern void *calloc (size_t, size_t); >> +extern void free (void *); >> extern void *alloca (size_t); >> extern void *memcpy (void *, const void *, size_t); >> extern void *memset (void *, int, size_t); >> extern char *strcpy (char *, const char *); >> +extern char *strdup (const char *); >> +extern char *strndup (const char *, size_t); >> >> struct A >> { >> @@ -636,6 +639,95 @@ test10 (void) >> } >> } >> >> +/* Tests for strdup/strndup. */ >> +size_t >> +__attribute__ ((noinline)) >> +test11 (void) >> +{ >> + const char *ptr = "abcdefghijklmnopqrstuvwxyz"; >> + char *res = strndup (ptr, 21); >> + if (__builtin_object_size (res, 2) != 22) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr, 32); >> + if (__builtin_object_size (res, 2) != 27) >> + abort (); >> + >> + free (res); >> + >> + res = strdup (ptr); >> + if (__builtin_object_size (res, 2) != 27) >> + abort (); >> + >> + free (res); >> + >> + char *ptr2 = malloc (64); >> + strcpy (ptr2, ptr); >> + >> + res = strndup (ptr2, 21); >> + if (__builtin_object_size (res, 2) != 1) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr2, 32); >> + if (__builtin_object_size (res, 2) != 1) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr2, 128); >> + if (__builtin_object_size (res, 2) != 1) >> + abort (); >> + >> + free (res); >> + >> + res = strdup (ptr2); >> + >> +#ifdef __builtin_object_size >> + if (__builtin_object_size (res, 2) != 27) >> +#else >> + if (__builtin_object_size (res, 2) != 1) >> +#endif >> + abort (); >> + >> + free (res); >> + free (ptr2); >> + >> + ptr = "abcd\0efghijklmnopqrstuvwxyz"; >> + res = strdup (ptr); >> + if (__builtin_object_size (res, 2) != 5) >> + abort (); >> + free (res); >> + >> + res = strndup (ptr, 24); >> + if (__builtin_object_size (res, 2) != 5) >> + abort (); >> + free (res); >> + >> + res = strndup (ptr, 2); >> + if (__builtin_object_size (res, 2) != 3) >> + abort (); >> + free (res); >> + >> + res = strdup (&ptr[4]); >> + if (__builtin_object_size (res, 2) != 1) >> + abort (); >> + free (res); >> + >> + res = strndup (&ptr[4], 4); >> + if (__builtin_object_size (res, 2) != 1) >> + abort (); >> + free (res); >> + >> + res = strndup (&ptr[4], 1); >> + if (__builtin_object_size (res, 2) != 1) >> + abort (); >> + free (res); >> +} >> + >> int >> main (void) >> { >> @@ -651,5 +743,6 @@ main (void) >> test8 (); >> test9 (1); >> test10 (); >> + test11 (); >> exit (0); >> } >> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-4.c >> index b9fddfed036..4c007c364b7 100644 >> --- a/gcc/testsuite/gcc.dg/builtin-object-size-4.c >> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-4.c >> @@ -1,5 +1,5 @@ >> /* { dg-do run } */ >> -/* { dg-options "-O2" } */ >> +/* { dg-options "-O2 -Wno-stringop-overread" } */ >> /* { dg-require-effective-target alloca } */ >> >> typedef __SIZE_TYPE__ size_t; >> @@ -7,10 +7,13 @@ extern void abort (void); >> extern void exit (int); >> extern void *malloc (size_t); >> extern void *calloc (size_t, size_t); >> +extern void free (void *); >> extern void *alloca (size_t); >> extern void *memcpy (void *, const void *, size_t); >> extern void *memset (void *, int, size_t); >> extern char *strcpy (char *, const char *); >> +extern char *strdup (const char *); >> +extern char *strndup (const char *, size_t); >> >> struct A >> { >> @@ -517,6 +520,94 @@ test8 (unsigned cond) >> #endif >> } >> >> +/* Tests for strdup/strndup. */ >> +size_t >> +__attribute__ ((noinline)) >> +test9 (void) >> +{ >> + const char *ptr = "abcdefghijklmnopqrstuvwxyz"; >> + char *res = strndup (ptr, 21); >> + if (__builtin_object_size (res, 3) != 22) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr, 32); >> + if (__builtin_object_size (res, 3) != 27) >> + abort (); >> + >> + free (res); >> + >> + res = strdup (ptr); >> + if (__builtin_object_size (res, 3) != 27) >> + abort (); >> + >> + free (res); >> + >> + char *ptr2 = malloc (64); >> + strcpy (ptr2, ptr); >> + >> + res = strndup (ptr2, 21); >> + if (__builtin_object_size (res, 3) != 1) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr2, 32); >> + if (__builtin_object_size (res, 3) != 1) >> + abort (); >> + >> + free (res); >> + >> + res = strndup (ptr2, 128); >> + if (__builtin_object_size (res, 3) != 1) >> + abort (); >> + >> + free (res); >> + >> + res = strdup (ptr2); >> +#ifdef __builtin_object_size >> + if (__builtin_object_size (res, 3) != 27) >> +#else >> + if (__builtin_object_size (res, 3) != 1) >> +#endif >> + abort (); >> + >> + free (res); >> + free (ptr2); >> + >> + ptr = "abcd\0efghijklmnopqrstuvwxyz"; >> + res = strdup (ptr); >> + if (__builtin_object_size (res, 3) != 5) >> + abort (); >> + free (res); >> + >> + res = strndup (ptr, 24); >> + if (__builtin_object_size (res, 3) != 5) >> + abort (); >> + free (res); >> + >> + res = strndup (ptr, 2); >> + if (__builtin_object_size (res, 3) != 3) >> + abort (); >> + free (res); >> + >> + res = strdup (&ptr[4]); >> + if (__builtin_object_size (res, 3) != 1) >> + abort (); >> + free (res); >> + >> + res = strndup (&ptr[4], 4); >> + if (__builtin_object_size (res, 3) != 1) >> + abort (); >> + free (res); >> + >> + res = strndup (&ptr[4], 1); >> + if (__builtin_object_size (res, 3) != 1) >> + abort (); >> + free (res); >> +} >> + >> int >> main (void) >> { >> @@ -530,5 +621,6 @@ main (void) >> test6 (); >> test7 (); >> test8 (1); >> + test9 (); >> exit (0); >> } >> diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc >> index 1f04cb80fd0..08e5731617d 100644 >> --- a/gcc/tree-object-size.cc >> +++ b/gcc/tree-object-size.cc >> @@ -89,6 +89,10 @@ static bitmap computed[OST_END]; >> /* Maximum value of offset we consider to be addition. */ >> static unsigned HOST_WIDE_INT offset_limit; >> >> +/* Tell the generic SSA updater what kind of update is needed after the pass >> + executes. */ >> +static unsigned todo; >> + >> /* Return true if VAL represents an initial size for OBJECT_SIZE_TYPE. */ >> >> static inline bool >> @@ -787,6 +791,73 @@ alloc_object_size (const gcall *call, int object_size_type) >> return bytes ? bytes : size_unknown (object_size_type); >> } >> >> +/* Compute __builtin_object_size for CALL, which is a call to either >> + BUILT_IN_STRDUP or BUILT_IN_STRNDUP; IS_STRNDUP indicates which it is. >> + OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. >> + If unknown, return size_unknown (object_size_type). */ >> + >> +static tree >> +strdup_object_size (const gcall *call, int object_size_type, bool is_strndup) >> +{ >> + tree src = gimple_call_arg (call, 0); >> + tree sz = size_unknown (object_size_type); >> + tree n = NULL_TREE; >> + >> + if (is_strndup) >> + n = fold_build2 (PLUS_EXPR, sizetype, size_one_node, >> + gimple_call_arg (call, 1)); >> + >> + >> + /* For strdup, simply emit strlen (SRC) + 1 and let the optimizer fold it the >> + way it likes. */ >> + if (!is_strndup) > Sorry to nitpick, should this just be under else ? Since this > condition will be false if the above if (is_strndup) > is true. Fixed locally. I'll resend once I have more comments on the rest of the patch. Thanks, Sid