[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v9 03/27] qapi: Plug leaks in test-qmp-*
From: |
Markus Armbruster |
Subject: |
Re: [Qemu-devel] [PATCH v9 03/27] qapi: Plug leaks in test-qmp-* |
Date: |
Wed, 04 Nov 2015 18:44:56 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) |
Eric Blake <address@hidden> writes:
> On 11/04/2015 01:19 AM, Markus Armbruster wrote:
>> Eric Blake <address@hidden> writes:
>>
>>> Make valgrind happy with the current state of the tests, so that
>>> it is easier to see if future patches introduce new memory problems
>>> without being drowned in noise. Many of the leaks were due to
>>> calling a second init without tearing down the data from an earlier
>>> visit. But since teardown is already idempotent, and we already
>>> register teardown as part of input_visitor_test_add(), it is nicer
>>> to just make init() safe to call multiple times than it is to have
>>> to make all tests call teardown.
>>>
>>> Another common leak was forgetting to clean up an error object,
>>> after testing that an error was raised.
>>>
>>> Another leak was in test_visitor_in_struct_nested(), failing to
>>> clean the base member of UserDefTwo. Cleaning that up left
>>> check_and_free_str() as dead code (since using the qapi_free_*
>>> takes care of recursion, and we don't want double frees).
>>>
>>> Signed-off-by: Eric Blake <address@hidden>
>>>
>>> ---
>>> v9: move earlier in series (was 13/17)
>>> v8: no change
>>> v7: no change
>>> v6: make init repeatable rather than adding teardown everywhere,
>>> fix additional leak with UserDefTwo base, plug additional files
>>> ---
>>> tests/test-qmp-input-strict.c | 10 ++++++++++
>>> tests/test-qmp-input-visitor.c | 41
>>> +++++++----------------------------------
>>> tests/test-qmp-output-visitor.c | 3 ++-
>>> 3 files changed, 19 insertions(+), 35 deletions(-)
>>
>> No leaks to plug in test/-qmp-commands.c and test-qmp-event.c?
>
> Didn't check. I'll do that.
>
>>
>>> diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c
>>> index b44184f..910e2f9 100644
>>> --- a/tests/test-qmp-input-strict.c
>>> +++ b/tests/test-qmp-input-strict.c
>>> @@ -77,6 +77,8 @@ static Visitor
>>> *validate_test_init_raw(TestInputVisitorData *data,
>>> {
>>> Visitor *v;
>>>
>>> + validate_teardown(data, NULL);
>>> +
>>> data->obj = qobject_from_json(json_string);
>>> g_assert(data->obj != NULL);
>>>
>>
>> A test added with validate_test_add() may call validate_test_init_raw()
>> any number of time. Since validate_test_add() passes
>> validate_teardown() as fixture teardown function, the last one will be
>> cleaned up on test finalization. The others will be cleaned up by the
>> next validate_test_init_raw(). Okay. Actually, the whole fixture
>> business starts to make sense only now.
>>
>> But why only validate_test_init_raw() and not validate_test_init()?
>>
>
> Umm, because I didn't look, and just plugged holes? Will fix.
>
>> The two duplicate code, by the way.
>
> And the fix will probably be by having one call the other.
>
>>
>>> @@ -193,6 +195,8 @@ static void
>>> test_validate_fail_struct(TestInputVisitorData *data,
>>>
>>> visit_type_TestStruct(v, &p, NULL, &err);
>>> g_assert(err);
>>> + error_free(err);
>>> + /* FIXME: visitor should not allocate p when returning error */
>>
>> Indeed.
>>
>> Recommend to always mention new FIXMEs in the commit message.
>
> This fixme is part of the answer to your question about 6/27 - we do
> have test coverage on non-arrays.
What we (royal we) don't have is memory going back from 06/27 to 03/27
%-}
>>> +++ b/tests/test-qmp-input-visitor.c
>>> @@ -46,6 +46,8 @@ Visitor
>>> *visitor_input_test_init(TestInputVisitorData *data,
>>> Visitor *v;
>>> va_list ap;
>>>
>>> + visitor_input_teardown(data, NULL);
>>> +
>>> va_start(ap, json_string);
>>> data->obj = qobject_from_jsonv(json_string, &ap);
>>> va_end(ap);
>>
>> Here, you add it to visitor_input_test_init(), but not
>> visitor_input_test_init_raw().
>>
>> These two duplicate code, too.
>
> Looks like I get to fix this too.
>
>
>>> +++ b/tests/test-qmp-output-visitor.c
>>> @@ -391,6 +391,7 @@ static void
>>> test_visitor_out_any(TestOutputVisitorData *data,
>>> qobj = QOBJECT(qdict);
>
> Here, qobj is an alias to qdict...
>
>>> visit_type_any(data->ov, &qobj, NULL, &err);
>>> g_assert(!err);
>>> + qobject_decref(qobj);
>>> obj = qmp_output_get_qobject(data->qov);
>>> g_assert(obj != NULL);
>>> qdict = qobject_to_qdict(obj);
>>> @@ -411,7 +412,6 @@ static void
>>> test_visitor_out_any(TestOutputVisitorData *data,
>> qobj = qdict_get(qdict, "string");
>
> ...but then we are reassigning it to instead be an alias within qdict.
>
>> g_assert(qobj);
>> qstring = qobject_to_qstring(qobj);
>>> g_assert(qstring);
>>> g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
>>> qobject_decref(obj);
>>> - qobject_decref(qobj);
>
> Dereferencing a subset of the qdict leaks the overal qdict.
>
>>
>> Hmm... obj is an alias for qdict, qobj is a member of qdict, freeing
>> obj frees qobj (unless there's another reference to qobj I can't see).
>> The line you delete then is a use-after-free bug that underflows the
>> reference counter. Correct?
>
> Valgrind complained about a leak, not a use-after-free. But there indeed
> may be more than one issue that got solved by correctly dropping the
> reference at the right point in time, prior to reassigning qobj for use
> as pointing to a different portion of the qdict.
>
>>
>> If yes, commit message should mention it briefly, because this isn't
>> just a leak. Actually, I'd make it a separate commit, to keep commit
>> messages simple, particularly the headlines.
>
> I'll have to refresh my memory what else is going on, but I can indeed
> split this out if it is different than a simple memleak fix.
I really, really like bug fixes coming with an impact assessment.
However, since this is just *tests*, I recommend *not* to spend time on
figuring out what exactly was broken, and simply adjust the commit
messages claims a bit.
>> Aside: qobject_decref() neglects to assert(!obj || obj->refcnt > 0).
>
> Sounds like a separate patch.
Definitely.
- Re: [Qemu-devel] [PATCH v9 10/27] qapi: Track simple union tag in object.local_members, (continued)
[Qemu-devel] [PATCH v9 16/27] qapi: Eliminate QAPISchemaObjectType.check() variable members, Eric Blake, 2015/11/04
[Qemu-devel] [PATCH v9 11/27] qapi-types: Consolidate gen_struct() and gen_union(), Eric Blake, 2015/11/04
[Qemu-devel] [PATCH v9 24/27] qapi: Fix alternates that accept 'number' but not 'int', Eric Blake, 2015/11/04
[Qemu-devel] [PATCH v9 08/27] qapi: Provide nicer array names in introspection, Eric Blake, 2015/11/04
[Qemu-devel] [PATCH v9 01/27] qapi: Use generated TestStruct machinery in tests, Eric Blake, 2015/11/04
[Qemu-devel] [PATCH v9 18/27] qapi: Factor out QAPISchemaObjectTypeMember.check_clash(), Eric Blake, 2015/11/04
[Qemu-devel] [PATCH v9 20/27] qapi: Simplify QAPISchemaObjectTypeVariants.check(), Eric Blake, 2015/11/04