[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [Qemu-devel] [PATCH v14 18/19] qapi: Simplify semantics o
From: |
Markus Armbruster |
Subject: |
Re: [Qemu-ppc] [Qemu-devel] [PATCH v14 18/19] qapi: Simplify semantics of visit_next_list() |
Date: |
Fri, 22 Apr 2016 13:35:48 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) |
Markus Armbruster <address@hidden> writes:
> Markus Armbruster <address@hidden> writes:
>
> [...]
>>> diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
>>> index 797973a..77dd1a7 100644
>>> --- a/qapi/string-input-visitor.c
>>> +++ b/qapi/string-input-visitor.c
>>> @@ -25,8 +25,6 @@ struct StringInputVisitor
>>> {
>>> Visitor visitor;
>>>
>>> - bool head;
>>> -
>>> GList *ranges;
>>> GList *cur_range;
>>> int64_t cur;
>>> @@ -125,11 +123,21 @@ error:
>>> }
>>>
>>> static void
>>> -start_list(Visitor *v, const char *name, Error **errp)
>>> +start_list(Visitor *v, const char *name, GenericList **list, size_t size,
>>> + Error **errp)
>>> {
>>> StringInputVisitor *siv = to_siv(v);
>>> + Error *err = NULL;
>>>
>>> - parse_str(siv, errp);
>>> + /* We don't support visits without a GenericList, yet */
>>
>> without a list
>>
>> Do we plan to support them? If not, scratch "yet".
>>
>>> + assert(list);
>>> +
>>> + parse_str(siv, &err);
>>> + if (err) {
>>> + *list = NULL;
>>> + error_propagate(errp, err);
>>> + return;
>>> + }
>
> parse_str() never sets an error, and therefore your new error check is
> dead. Just as well, because it would be wrong.
>
> parse_str() parses a complete string into a non-empty list of uint64_t
> ranges. On success, it sets siv->ranges to this list. On error, it
> sets it to null. It could also set an error then, but it doesn't.
>
> If it did, then what would start_list() do with it? Reporting it would
> be wrong, because the list members need not be integers.
>
> If they aren't, the speculative parse_str()'s failure will be ignored.
>
> If they are, parse_type_int64() will call parse_str() again, then use
> siv->ranges.
>
> If the first parse_str() succeeds, the second will do nothing, and we'll
> use the first one's siv->ranges. Works.
>
> If the first parse_str() fails, the second will fail as well, because
> its input is the same. We'll use the second one's failure. Works.
No, it doesn't: failure gets interpreted as empty list. I'll post my
test case separately.
> When used outside list context, parse_type_int64() will call parse_str()
> for the first time, and use its result. Works.
>
> Note that opts-visitor does it differently: opts_start_list() doesn't
> parse numbers, opts_type_int64() and opts_type_uint64() do.
>
> Further note the latent bug in parse_type_int64(): we first call
> parse_str(siv, errp), and goto error if it fails, where we promptly
> error_setg(errp, ...). If parse_str() set an error, the error_setg()
> would fail error_setv()'s assertion.
>
> Please drop parse_str()'s unused errp parameter, and add a comment to
> start_list() explaining the speculative call to parse_str() there.
Insufficient, doesn't fix the bug. After parse_str(), we need to be
able to distinguish empty list from error. Moving the error_set() into
parse_str() could work. Returning succes/failure and dropping the errp
parameter could also work.
> Alternatively, change the string visitor to work like the opts visitor.
>
>>>
>>> siv->cur_range = g_list_first(siv->ranges);
>>> if (siv->cur_range) {
> [...]