From b978871f202c9812c53b6fe2c08f221eb6d6c6b3 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 19 Feb 2018 22:23:26 -0500 Subject: [PATCH] qapi: Don't cast Enum* to int* C compilers are allowed to represent enums as a smaller type than int, if all enum values fit in the smaller type. There are even compiler flags that force the use of this smaller representation, although using them changes the ABI of a binary. Therefore, our generated code for visit_type_ENUM() (for all qapi enums) was wrong for casting Enum* to int* when calling visit_type_enum(). It appears that no one has been using compiler ABI switches for qemu, because if they had, we are potentially dereferencing beyond bounds or even risking a SIGBUS on platforms where unaligned pointer dereferencing is fatal. But it is still better to avoid the practice entirely, and just use the correct types. This matches the fix for alternate qapi types, done earlier in commit 0426d53 "qapi: Simplify visiting of alternate types", with generated code changing as: | void visit_type_QType(Visitor *v, QType *obj, const char *name, Error **errp) | { |- visit_type_enum(v, (int *)obj, QType_lookup, "QType", name, errp); |+ int value = *obj; |+ visit_type_enum(v, &value, QType_lookup, "QType", name, errp); |+ *obj = value; | } Backports commit 395a233f7c089f23e3c0d43ce34c709dc5acd7de from qemu --- msvc/unicorn/qapi-visit.c | 12 +++++++++--- qemu/scripts/qapi-visit.py | 5 +++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/msvc/unicorn/qapi-visit.c b/msvc/unicorn/qapi-visit.c index f5ed07da..cceef9a7 100644 --- a/msvc/unicorn/qapi-visit.c +++ b/msvc/unicorn/qapi-visit.c @@ -52,12 +52,16 @@ out: void visit_type_QType(Visitor *v, QType *obj, const char *name, Error **errp) { - visit_type_enum(v, (int *)obj, QType_lookup, "QType", name, errp); + int value = *obj; + visit_type_enum(v, &value, QType_lookup, "QType", name, errp); + *obj = value; } void visit_type_QapiErrorClass(Visitor *v, QapiErrorClass *obj, const char *name, Error **errp) { - visit_type_enum(v, (int *)obj, QapiErrorClass_lookup, "QapiErrorClass", name, errp); + int value = *obj; + visit_type_enum(v, &value, QapiErrorClass_lookup, "QapiErrorClass", name, errp); + *obj = value; } static void visit_type_X86CPUFeatureWordInfo_fields(Visitor *v, X86CPUFeatureWordInfo **obj, Error **errp) @@ -134,7 +138,9 @@ out: void visit_type_X86CPURegister32(Visitor *v, X86CPURegister32 *obj, const char *name, Error **errp) { - visit_type_enum(v, (int *)obj, X86CPURegister32_lookup, "X86CPURegister32", name, errp); + int value = *obj; + visit_type_enum(v, &value, X86CPURegister32_lookup, "X86CPURegister32", name, errp); + *obj = value; } void visit_type_anyList(Visitor *v, anyList **obj, const char *name, Error **errp) diff --git a/qemu/scripts/qapi-visit.py b/qemu/scripts/qapi-visit.py index 65a8cc92..3a1e79fd 100644 --- a/qemu/scripts/qapi-visit.py +++ b/qemu/scripts/qapi-visit.py @@ -175,12 +175,13 @@ out: def gen_visit_enum(name): - # FIXME cast from enum *obj to int * invalidly assumes enum is int return mcgen(''' void visit_type_%(c_name)s(Visitor *v, %(c_name)s *obj, const char *name, Error **errp) { - visit_type_enum(v, (int *)obj, %(c_name)s_lookup, "%(name)s", name, errp); + int value = *obj; + visit_type_enum(v, &value, %(c_name)s_lookup, "%(name)s", name, errp); + *obj = value; } ''', c_name=c_name(name), name=name)