From patchwork Fri Sep 26 19:04:03 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Capitulino X-Patchwork-Id: 393923 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 403A41401EB for ; Sat, 27 Sep 2014 05:06:22 +1000 (EST) Received: from localhost ([::1]:51117 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XXaqR-0003nA-Oo for incoming@patchwork.ozlabs.org; Fri, 26 Sep 2014 15:06:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56051) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XXaos-0001o0-Lv for qemu-devel@nongnu.org; Fri, 26 Sep 2014 15:04:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XXaon-0004Gk-Gn for qemu-devel@nongnu.org; Fri, 26 Sep 2014 15:04:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:32674) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XXaon-0004F4-7T for qemu-devel@nongnu.org; Fri, 26 Sep 2014 15:04:37 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s8QJ4PFJ006686 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 26 Sep 2014 15:04:25 -0400 Received: from localhost (ovpn-116-58.ams2.redhat.com [10.36.116.58]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s8QJ4Oma022172; Fri, 26 Sep 2014 15:04:24 -0400 From: Luiz Capitulino To: peter.maydell@linaro.org Date: Fri, 26 Sep 2014 15:04:03 -0400 Message-Id: <1411758247-12161-6-git-send-email-lcapitulino@redhat.com> In-Reply-To: <1411758247-12161-1-git-send-email-lcapitulino@redhat.com> References: <1411758247-12161-1-git-send-email-lcapitulino@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: qemu-devel@nongnu.org, anthony@codemonkey.ws Subject: [Qemu-devel] [PULL 5/9] tests: add QMP input visitor test for unions with no discriminator X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Michael Roth This is more of an exercise of the dealloc visitor, where it may erroneously use an uninitialized discriminator field as indication that union fields corresponding to that discriminator field/type are present, which can lead to attempts to free random chunks of heap memory. Cc: qemu-stable@nongnu.org Reviewed-by: Eric Blake Reviewed-by: Paolo Bonzini Signed-off-by: Michael Roth Signed-off-by: Luiz Capitulino --- tests/qapi-schema/qapi-schema-test.json | 10 ++++++++++ tests/qapi-schema/qapi-schema-test.out | 3 +++ tests/test-qmp-input-strict.c | 17 +++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index ab4d3d9..d43b5fd 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -33,6 +33,9 @@ { 'type': 'UserDefB', 'data': { 'integer': 'int' } } +{ 'type': 'UserDefC', + 'data': { 'string1': 'str', 'string2': 'str' } } + { 'union': 'UserDefUnion', 'base': 'UserDefZero', 'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } } @@ -47,6 +50,13 @@ # FIXME generated struct UserDefFlatUnion has members for direct base # UserDefOne, but lacks members for indirect base UserDefZero +# this variant of UserDefFlatUnion defaults to a union that uses fields with +# allocated types to test corner cases in the cleanup/dealloc visitor +{ 'union': 'UserDefFlatUnion2', + 'base': 'UserDefUnionBase', + 'discriminator': 'enum1', + 'data': { 'value1' : 'UserDefC', 'value2' : 'UserDefB', 'value3' : 'UserDefA' } } + { 'union': 'UserDefAnonUnion', 'discriminator': {}, 'data': { 'uda': 'UserDefA', 's': 'str', 'i': 'int' } } diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 95e9899..08d7304 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -6,9 +6,11 @@ OrderedDict([('type', 'UserDefNested'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef1', 'UserDefOne'), ('string2', 'str')])), ('*dict3', OrderedDict([('userdef2', 'UserDefOne'), ('string3', 'str')]))]))]))]), OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]), OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]), + OrderedDict([('type', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]), OrderedDict([('union', 'UserDefUnion'), ('base', 'UserDefZero'), ('data', OrderedDict([('a', 'UserDefA'), ('b', 'UserDefB')]))]), OrderedDict([('type', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]), OrderedDict([('union', 'UserDefFlatUnion'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefA'), ('value2', 'UserDefB'), ('value3', 'UserDefB')]))]), + OrderedDict([('union', 'UserDefFlatUnion2'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefC'), ('value2', 'UserDefB'), ('value3', 'UserDefA')]))]), OrderedDict([('union', 'UserDefAnonUnion'), ('discriminator', OrderedDict()), ('data', OrderedDict([('uda', 'UserDefA'), ('s', 'str'), ('i', 'int')]))]), OrderedDict([('union', 'UserDefNativeListUnion'), ('data', OrderedDict([('integer', ['int']), ('s8', ['int8']), ('s16', ['int16']), ('s32', ['int32']), ('s64', ['int64']), ('u8', ['uint8']), ('u16', ['uint16']), ('u32', ['uint32']), ('u64', ['uint64']), ('number', ['number']), ('boolean', ['bool']), ('string', ['str'])]))]), OrderedDict([('command', 'user_def_cmd'), ('data', OrderedDict())]), @@ -32,6 +34,7 @@ OrderedDict([('type', 'UserDefNested'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef1', 'UserDefOne'), ('string2', 'str')])), ('*dict3', OrderedDict([('userdef2', 'UserDefOne'), ('string3', 'str')]))]))]))]), OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]), OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]), + OrderedDict([('type', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]), OrderedDict([('type', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]), OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]), OrderedDict([('type', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))])] diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c index 0f77003..d5360c6 100644 --- a/tests/test-qmp-input-strict.c +++ b/tests/test-qmp-input-strict.c @@ -260,6 +260,21 @@ static void test_validate_fail_union_flat(TestInputVisitorData *data, qapi_free_UserDefFlatUnion(tmp); } +static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData *data, + const void *unused) +{ + UserDefFlatUnion2 *tmp = NULL; + Error *err = NULL; + Visitor *v; + + /* test situation where discriminator field ('enum1' here) is missing */ + v = validate_test_init(data, "{ 'string': 'c', 'string1': 'd', 'string2': 'e' }"); + + visit_type_UserDefFlatUnion2(v, &tmp, NULL, &err); + g_assert(err); + qapi_free_UserDefFlatUnion2(tmp); +} + static void test_validate_fail_union_anon(TestInputVisitorData *data, const void *unused) { @@ -310,6 +325,8 @@ int main(int argc, char **argv) &testdata, test_validate_fail_union); validate_test_add("/visitor/input-strict/fail/union-flat", &testdata, test_validate_fail_union_flat); + validate_test_add("/visitor/input-strict/fail/union-flat-no-discriminator", + &testdata, test_validate_fail_union_flat_no_discrim); validate_test_add("/visitor/input-strict/fail/union-anon", &testdata, test_validate_fail_union_anon);