[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Refactoring of a possibly unsafe pattern for variable initialization via function calls


  • To: Julien Grall <julien@xxxxxxx>
  • From: Luca Fancellu <Luca.Fancellu@xxxxxxx>
  • Date: Mon, 19 Jun 2023 08:54:35 +0000
  • Accept-language: en-GB, en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=ydNtWTWcQnbLJb4qM4a7EMG9UytbrrupTAKWTSfKRsQ=; b=F2Dz/0U00jqHVrbp8Y7lY68u9w6y7CRRueACxGViJsWeseG7Vyak+TjgzviZA5nCiCF+7Nvnm10L9lb0watweeulpIiKJdBfahUeSbHfjrGik67TWH+xK1YH5sk6KkKwcNMj/xgsEDzJyMQprZME3V7Vv0F/BtF7TgxW3iAhDX8cNlP2TXrRyFTkyZfGzEFb0HpRF0SDueOfaafwU2tGR3IczNHSoj7mP8FtlSW0umEWNU50PngwQdgveUCUvaKKEm7Lf+5S8U6/jRFh3epSMZ+ifDXprGwL4SAQqOWD7gqW3VTbPiie8zfCZFUo9adBZ7lBB4XEG16l26mqMXNqgA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Wunpun0RXO8b57+mN+F71Sz5aB3Bs5izUbReCucJUBjQJKOhYA3js2m9zDWl7oxTdZp4zzWjoDAgJ+vc6GMvbzIGkq6xdlkbjNAFPfJo96dYGhMEwSxk8gYkYTYcQ8TeaSMWbhAxc4YQJC+gisog94bx2v8KTwvz2WMt5hgSlkEM3mxvBO8ljAwyQdl4xhwucKncaIOxAdyqLY9OSmUhYU6UeVTyS9i7X/xqWPO4A4S8ENvUySJv3KD4Xy5clSykaZbmW5O1O2Ej3rImrPjrvThhlHAFSH08/pxaTqfkqDJN9KKOz+/zUQTwc4VjZT9kmJ5xwigniqTL8y93IB3tnQ==
  • Authentication-results-original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com;
  • Cc: Jan Beulich <jbeulich@xxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Nicola Vetrini <nicola.vetrini@xxxxxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, George Dunlap <george.dunlap@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, Xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • Delivery-date: Mon, 19 Jun 2023 08:54:55 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Nodisclaimer: true
  • Original-authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com;
  • Thread-index: AQHZn6gWgGF2ZXPPc02I099nu6PTEa+NBmIAgAAYV4CAAMv8AIAD4yaAgAABdQCAAAIygIAABVUAgAABJIA=
  • Thread-topic: Refactoring of a possibly unsafe pattern for variable initialization via function calls


> On 19 Jun 2023, at 09:50, Julien Grall <julien@xxxxxxx> wrote:
> 
> 
> 
> On 19/06/2023 09:31, Luca Fancellu wrote:
>>> On 19 Jun 2023, at 09:23, Julien Grall <julien@xxxxxxx> wrote:
>>> 
>>> 
>>> 
>>> On 19/06/2023 09:18, Jan Beulich wrote:
>>>> On 16.06.2023 22:56, Stefano Stabellini wrote:
>>>>> On Fri, 16 Jun 2023, Nicola Vetrini wrote:
>>>>>> On 16/06/23 09:19, Jan Beulich wrote:
>>>>>>> On 15.06.2023 18:39, nicola wrote:
>>>>>>>> while investigating possible patches regarding Mandatory Rule 9.1, I
>>>>>>>> found the following pattern, that is likely to results in a lot 
>>>>>>>> possible
>>>>>>>> positives from many (all) static analysis tools for this rule.
>>>>>>>> 
>>>>>>>> This is the current status (taken from `xen/common/device_tree.c:135')
>>>>>>>> 
>>>>>>>> 
>>>>>>>> const struct dt_property *dt_find_property(const struct dt_device_node
>>>>>>>> *np,
>>>>>>>>                                              const char *name, u32 
>>>>>>>> *lenp)
>>>>>>>> {
>>>>>>>>       const struct dt_property *pp;
>>>>>>>> 
>>>>>>>>       if ( !np )
>>>>>>>>           return NULL;
>>>>>>>> 
>>>>>>>>       for ( pp = np->properties; pp; pp = pp->next )
>>>>>>>>       {
>>>>>>>>           if ( dt_prop_cmp(pp->name, name) == 0 )
>>>>>>>>           {
>>>>>>>>               if ( lenp )
>>>>>>>>                   *lenp = pp->length;
>>>>>>>>               break;
>>>>>>>>           }
>>>>>>>>       }
>>>>>>>> 
>>>>>>>>       return pp;
>>>>>>>> }
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> It's very hard to detect that the pointee is always written whenever a
>>>>>>>> non-NULL pointer for `lenp' is supplied, and it can safely be read in
>>>>>>>> the callee, so a sound analysis will err on the cautious side.
>>>>>>> 
>>>>>>> I'm having trouble seeing why this is hard to recognize: The loop can
>>>>>>> only be exited two ways: pp == NULL or with *lenp written.
>>>>>>> 
>>>>>>> For rule 9.1 I'd rather expect the scanning tool (and often the 
>>>>>>> compiler)
>>>>>>> to get into trouble with the NULL return value case, and *lenp not being
>>>>>>> written yet apparently consumed in the caller. Then, however, ...
>>>>>> 
>>>>>> 
>>>>>> You're right, I made a mistake, thank you for finding it.
>>>>>> I meant to write on `*lenp' in all execution paths.
>>>>>> Please, take a look at this revised version:
>>>>>> 
>>>>>> 
>>>>>> const struct dt_property *dt_find_property(const struct dt_device_node 
>>>>>> *np,
>>>>>>                                            const char *name, u32 *lenp)
>>>>>> {
>>>>>>     u32 len = 0;
>>>>>>     const struct dt_property *pp = NULL;
>>>>>> 
>>>>>>     if ( np )
>>>>>>     {
>>>>>>         for ( pp = np->properties; pp; pp = pp->next )
>>>>>>         {
>>>>>>             if ( dt_prop_cmp(pp->name, name) == 0 )
>>>>>>             {
>>>>>>                 len = pp->length;
>>>>>>                 break;
>>>>>>             }
>>>>>>         }
>>>>>>     }
>>>>>> 
>>>>>>     if ( lenp )
>>>>>>         *lenp = len;
>>>>>>     return pp;
>>>>>> }
>>>>> 
>>>>> Nesting more will make the code less readable and also cause other code
>>>>> quality metrics to deteriorate (cyclomatic complexity).
>>>>> 
>>>>> Would the below work?
>>>>> 
>>>>> 
>>>>> const struct dt_property *dt_find_property(const struct dt_device_node 
>>>>> *np,
>>>>>                                            const char *name, u32 *lenp)
>>>>> {
>>>>>     u32 len = 0;
>>>>>     const struct dt_property *pp = NULL;
>>>>> 
>>>>>     if ( !np )
>>>>>         return NULL
>>>> That's what we started from, but leaving *lenp not written to. How
>>>> about ...
>>>>>     for ( pp = np->properties; pp; pp = pp->next )
>>>>     for ( pp = np ? np->properties : NULL; pp; pp = pp->next ) > > ?
>>> 
>>> I would be OK with that. Maybe with an extra set of parentheses around ' np 
>>> ? ... : NULL' just to make visually easier to parse.
>> Agree, and for MISRA, we should use a boolean expression as condition, even 
>> if I know that we would like to deviate from that,
> The code will even be more difficult to read. So if we plan to deviate, then 
> I don't want us to use MISRA-compliant boolean expression here.
> 
>> which I dislike.
> 
> What do you dislike?

The fact that we don’t use boolean expressions as conditions (in general, not 
only this example), anyway it was only my personal opinion

> 
> Cheers,
> 
> -- 
> Julien Grall


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.