[CRIU] [PATCH 01/23] criu/filesystems.c: refactor binfmt_misc_restore_bme
Kir Kolyshkin
kir at openvz.org
Wed Oct 12 08:45:05 PDT 2016
On 10/12/2016 02:14 AM, Kirill Tkhai wrote:
>
> 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
Thanks for noting it, as I was paying attention, too. Looked around in
the code and found that both forms are used. If the one you want is
preferable, I am to resend the fixed version.
>
>> /* :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