qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 08/14] nbd/client: Refactor nbd_receive_list()


From: Vladimir Sementsov-Ogievskiy
Subject: Re: [Qemu-devel] [PATCH 08/14] nbd/client: Refactor nbd_receive_list()
Date: Thu, 6 Dec 2018 17:03:34 +0000

06.12.2018 19:31, Eric Blake wrote:
> On 12/6/18 8:18 AM, Vladimir Sementsov-Ogievskiy wrote:
>> 01.12.2018 1:03, Eric Blake wrote:
>>> Add some parameters to make this function reusable in upcoming
>>> export listing, where we will want to capture the name and
>>> description rather than compare against a user-supplied name.
>>> No change in semantics to the existing caller.
>>>
>>> Signed-off-by: Eric Blake <address@hidden>
>>> ---
>>>    nbd/client.c | 66 +++++++++++++++++++++++++++++++++++++---------------
>>>    1 file changed, 47 insertions(+), 19 deletions(-)
> 
>>> @@ -290,30 +298,49 @@ static int nbd_receive_list(QIOChannel *ioc, const 
>>> char *want, bool *match,
>>>            nbd_send_opt_abort(ioc);
>>>            return -1;
>>>        }
>>> -    if (namelen != strlen(want)) {
>>> -        if (nbd_drop(ioc, len, errp) < 0) {
>>> -            error_prepend(errp,
>>> -                          "failed to skip export name with wrong length: 
>>> ");
>>> -            nbd_send_opt_abort(ioc);
>>> -            return -1;
>>> +    if (want) {
>>> +        if (namelen != strlen(want)) {
>>> +            if (nbd_drop(ioc, len, errp) < 0) {
>>> +                error_prepend(errp,
>>> +                              "failed to skip export name with wrong 
>>> length: ");
>>> +                nbd_send_opt_abort(ioc);
>>> +                return -1;
>>> +            }
>>> +            return 1;
>>>            }
>>> -        return 1;
>>> +        assert(namelen < sizeof(array));
>>> +    } else {
>>> +        assert(nameout);
>>
>> this assert looks a bit redundant, if nameout is 0, next line will abort not 
>> less clearly
>>
>>> +        *nameout = name = g_new(char, namelen + 1);
>>
>> We should check namelen <= NBD_MAX_NAME_SIZE before it, I think.
> 
> Why? We already validated

Ah, than OK, the worst case is ~ NBD_MAX_BUFFER_SIZE (32M), not 4G. Missed that 
:(

  that the overall option is not too large, and even if the resulting name from 
the server is larger than NBD_MAX_NAME_SIZE, it's still nice to report that 
name to the client for 'qemu-nbd --list'.  And these days, we only call 
nbd_receive_list if a server lacked NBD_OPT_GO, which is getting rarer and 
rarer, so micro-optimizing a rare case to avoid a large malloc isn't going to 
make a noticeable difference.
> 
>>
>>>        }
>>>
>>> -    assert(namelen < sizeof(name));
>>>        if (nbd_read(ioc, name, namelen, errp) < 0) {
>>>            error_prepend(errp, "failed to read export name: ");
>>>            nbd_send_opt_abort(ioc);
>>> +        if (!want) {
>>> +            free(name);
>>
>> g_free
>>
>>> +        }
>>>            return -1;
>>>        }
>>>        name[namelen] = '\0';
>>>        len -= namelen;
>>> -    if (nbd_drop(ioc, len, errp) < 0) {
>>> +    if (!want) {
>>> +        assert(description);
>>
>> NBD_MAX_NAME_SIZE
> 
> The description is not bound by NBD_MAX_NAME_SIZE.  The NBD protocol DOES 
> document a maximum string size (4k), but we are (so far) not actually 
> honoring that limit (our choice for NBD_MAX_NAME_SIZE is 256, which is 
> smaller than the NBD protocol limit).
> 

Ohm, yes, you are right :(. Too much reviewing, I should stop and make some 
patches :)

>>
>>> +        *description = g_new(char, len + 1);
>>> +        if (nbd_read(ioc, *description, len, errp) < 0) {
>>> +            error_prepend(errp, "failed to read export description: ");
>>> +            nbd_send_opt_abort(ioc);
>>> +            free(name);
>>> +            free(*description);
>>
>> g_free
>>
>>> +            return -1;
>>> +        }
>>> +        (*description)[len] = '\0';
>>> +    } else if (nbd_drop(ioc, len, errp) < 0) {
>>>            error_prepend(errp, "failed to read export description: ");
>>>            nbd_send_opt_abort(ioc);
>>>            return -1;
>>>        }
>>> -    if (!strcmp(name, want)) {
>>> +    if (want && !strcmp(name, want)) {
>>>            *match = true;
>>>        }
>>>        return 1;
>>
>> one more thing: on fail path, you finally fill output name and description
>> with freed pointers. I'd prefer to keep them unchanged in this case, however,
>> it's a matter of taste.
> 
> Okay, I'll try and be more careful in v2 about not altering the callers 
> pointers on failure.
> 


-- 
Best regards,
Vladimir

reply via email to

[Prev in Thread] Current Thread [Next in Thread]