[CRIU] [PATCH 01/23] criu/filesystems.c: refactor binfmt_misc_restore_bme

Kirill Tkhai ktkhai at virtuozzo.com
Wed Oct 12 02:14:10 PDT 2016



On 12.10.2016 04:46, Kir Kolyshkin wrote:
> The following error is emitted by clang:
> 
>>   CC       criu/filesystems.o
>> criu/filesystems.c:280:13: error: variable 'ret' is used uninitialized
>>    whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized]
>>         } else if (bme->extension) {
>>                    ^~~~~~~~~~~~~~
>> criu/filesystems.c:287:6: note: uninitialized use occurs here
>>         if (ret > 0) {
>>             ^~~
>> criu/filesystems.c:280:9: note: remove the 'if' if its condition is
>>    always true
>>         } else if (bme->extension) {
>>                ^~~~~~~~~~~~~~~~~~~~
>> criu/filesystems.c:272:9: note: initialize the variable 'ret' to silence
>>    this warning
>>         int ret;
>>                ^
>>                 = 0
>> 1 error generated.
> 
> This code was a result of commit 398e7d3.
> 
> If we look closely, this is a false alarm, as "else if (bme->extension)"
> is always true as it was checked before. But this is not very clear,
> and the issue with clangs still needs to be fixed.
> 
> There are many ways to do so:
> 
> 1. Initialize ret to 0. This is what initial version of this patch did.
> 
> 2. Remove the always-true condition, like this:
> 
> 	-	} else if (bme->extension) {
> 	+	} else {
> 
> In my opinion this would hurt readability.
> 
> 3. Change the code flow, improving readability at the same time.
> 
> I believe that #3 is what this patch does. In addition, it fixes
> handling of a few corner cases:
> 
> - an overflow in snprintf();
> - a case when bme->name is NULL (as it is used for strlen/snprintf,
>   there is a potential for SIGSEGV);
> - a case of ret == 0 (currently there is no code flow that
>   results in ret being 0, so it's just for the future).
> 
> Cc: Kirill Tkhai <ktkhai at virtuozzo.com>
> Signed-off-by: Kir Kolyshkin <kir at openvz.org>
> ---
>  criu/filesystems.c | 30 ++++++++++++++++++++----------
>  1 file changed, 20 insertions(+), 10 deletions(-)
> 
> diff --git a/criu/filesystems.c b/criu/filesystems.c
> index d66a6c6..cabfbf2 100644
> --- a/criu/filesystems.c
> +++ b/criu/filesystems.c
> @@ -271,25 +271,35 @@ static int binfmt_misc_restore_bme(struct mount_info *mi, BinfmtMiscEntry *bme,
>  {
>  	int ret;
>  
> -	/* :name:type:offset:magic/extension:mask:interpreter:flags */
> -	if ((!bme->magic && !bme->extension) || !bme->interpreter) {
> -		pr_perror("binfmt_misc: bad dump");
> -		ret = -1;
> -	} else if (bme->magic) {
> +	if (!bme->name || !bme->interpreter)
> +		goto bad_dump;
> +
> +	/* Either magic or extension should be there */
> +	if (bme->magic) {
>  		ret = make_bfmtm_magic_str(buf, bme);
> -	} else if (bme->extension) {
> +	}
> +	else if (bme->extension) {

Don't we use a specific style for "} else" condition? Currently,
the most place are:

} else

and not 

}
else

>  		/* :name:E::extension::interpreter:flags */
>  		ret = snprintf(buf, BINFMT_MISC_STR, ":%s:E::%s::%s:%s",
>  			       bme->name, bme->extension, bme->interpreter,
>  			       bme->flags ? : "\0");
> +		if (ret >= BINFMT_MISC_STR) // output truncated
> +			ret = -1;
>  	}
> +	else
> +		ret = -1;
>  
> -	if (ret > 0) {
> -		pr_debug("binfmt_misc_pattern=%s\n", buf);
> -		ret = write_binfmt_misc_entry(mi->mountpoint, buf, bme);
> -	}
> +	if (ret < 0)
> +		goto bad_dump;
> +
> +	pr_debug("binfmt_misc_pattern=%s\n", buf);
> +	ret = write_binfmt_misc_entry(mi->mountpoint, buf, bme);
>  
>  	return ret;
> +
> +bad_dump:
> +	pr_perror("binfmt_misc: bad dump");
> +	return -1;
>  }
>  
>  static int binfmt_misc_restore(struct mount_info *mi)
> 


More information about the CRIU mailing list