@@ -9,6 +9,7 @@
#include "qemu/osdep.h"
#include "qemu/accel.h"
+#include "qapi/error.h"
AccelState *current_accel(void)
{
@@ -18,7 +19,8 @@ AccelState *current_accel(void)
AccelClass *ac = accel_find("tcg");
g_assert(ac != NULL);
- accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac)));
+ accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac),
+ &error_abort));
}
return accel;
}
@@ -155,7 +155,7 @@ DeviceState *qdev_try_new(const char *name)
if (!oc) {
return NULL;
}
- return DEVICE(object_new_with_class(oc));
+ return DEVICE(object_new_with_class(oc, &error_abort));
}
static QTAILQ_HEAD(, DeviceListener) device_listeners
@@ -606,14 +606,19 @@ struct InterfaceClass
/**
* object_new_with_class:
* @klass: The class to instantiate.
+ * @errp: pointer to be filled with error details on failure
*
* This function will initialize a new object using heap allocated memory.
* The returned object has a reference count of 1, and will be freed when
* the last reference is dropped.
*
- * Returns: The newly allocated and instantiated object.
+ * If an instance of @klass is not permitted to be instantiated, an
+ * error will be raised. This can happen if @klass is abstract.
+ *
+ * Returns: The newly allocated and instantiated object, or NULL
+ * on error.
*/
-Object *object_new_with_class(ObjectClass *klass);
+Object *object_new_with_class(ObjectClass *klass, Error **errp);
/**
* object_new:
@@ -948,7 +948,8 @@ GPtrArray *qemu_get_nic_models(const char *device_type)
* create this property during instance_init, so we have to create
* a temporary instance here to be able to check it.
*/
- Object *obj = object_new_with_class(OBJECT_CLASS(dc));
+ Object *obj = object_new_with_class(OBJECT_CLASS(dc),
+ &error_abort);
if (object_property_find(obj, "netdev")) {
g_ptr_array_add(nic_models, (gpointer)name);
}
@@ -794,9 +794,9 @@ static Object *object_new_with_type(Type type, Error **errp)
return obj;
}
-Object *object_new_with_class(ObjectClass *klass)
+Object *object_new_with_class(ObjectClass *klass, Error **errp)
{
- return object_new_with_type(klass->type, &error_abort);
+ return object_new_with_type(klass->type, errp);
}
Object *object_new(const char *typename)
@@ -102,13 +102,12 @@ Object *user_creatable_add_type(const char *type, const char *id,
return NULL;
}
- if (object_class_is_abstract(klass)) {
- error_setg(errp, "object type '%s' is abstract", type);
+ assert(qdict);
+ obj = object_new_with_class(klass, errp);
+ if (!obj) {
return NULL;
}
- assert(qdict);
- obj = object_new_with_class(klass);
object_set_properties_from_qdict(obj, qdict, v, &local_err);
if (local_err) {
goto out;
@@ -134,14 +134,15 @@ ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
return NULL;
}
- if (!object_class_dynamic_cast(klass, TYPE_DEVICE)
- || object_class_is_abstract(klass)) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
- "a non-abstract device type");
+ if (!object_class_dynamic_cast(klass, TYPE_DEVICE)) {
+ error_setg(errp, "Object '%s' is not a device type", typename);
return NULL;
}
- obj = object_new_with_class(klass);
+ obj = object_new_with_class(klass, errp);
+ if (!obj) {
+ return NULL;
+ }
object_property_iter_init(&iter, obj);
while ((prop = object_property_iter_next(&iter))) {
@@ -2117,7 +2117,8 @@ static void qemu_create_machine(QDict *qdict)
MachineClass *machine_class = select_machine(qdict, &error_fatal);
object_set_machine_compat_props(machine_class->compat_props);
- current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));
+ current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class),
+ &error_fatal));
object_property_add_child(object_get_root(), "machine",
OBJECT(current_machine));
object_property_add_child(container_get(OBJECT(current_machine),
@@ -2327,7 +2328,8 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp)
}
goto bad;
}
- accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac)));
+ accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac),
+ &error_fatal));
object_apply_compat_props(OBJECT(accel));
qemu_opt_foreach(opts, accelerator_set_property,
accel,
@@ -43,12 +43,18 @@ void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
{
APICCommonState *apic;
APICCommonClass *apic_class = apic_get_class(errp);
+ Object *apicobj;
if (!apic_class) {
return;
}
- cpu->apic_state = DEVICE(object_new_with_class(OBJECT_CLASS(apic_class)));
+ apicobj = object_new_with_class(OBJECT_CLASS(apic_class),
+ errp);
+ if (!apicobj) {
+ return;
+ }
+ cpu->apic_state = DEVICE(apicobj);
object_property_add_child(OBJECT(cpu), "lapic",
OBJECT(cpu->apic_state));
object_unref(OBJECT(cpu->apic_state));
@@ -156,15 +156,20 @@ static X86CPU *x86_cpu_from_model(const char *model, QObject *props,
{
X86CPU *xc = NULL;
X86CPUClass *xcc;
+ Object *xcobj;
Error *err = NULL;
xcc = X86_CPU_CLASS(cpu_class_by_name(TYPE_X86_CPU, model));
if (xcc == NULL) {
- error_setg(&err, "CPU model '%s' not found", model);
- goto out;
+ error_setg(errp, "CPU model '%s' not found", model);
+ return NULL;
}
- xc = X86_CPU(object_new_with_class(OBJECT_CLASS(xcc)));
+ xcobj = object_new_with_class(OBJECT_CLASS(xcc), errp);
+ if (!xcobj) {
+ return NULL;
+ }
+ xc = X86_CPU(xcobj);
if (props) {
object_apply_props(OBJECT(xc), props, props_arg_name, &err);
if (err) {
@@ -5973,7 +5973,7 @@ static GSList *get_sorted_cpu_model_list(void)
static char *x86_cpu_class_get_model_id(X86CPUClass *xc)
{
- Object *obj = object_new_with_class(OBJECT_CLASS(xc));
+ Object *obj = object_new_with_class(OBJECT_CLASS(xc), &error_abort);
char *r = object_property_get_str(obj, "model-id", &error_abort);
object_unref(obj);
return r;
@@ -6071,7 +6071,7 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc,
return;
}
- xc = X86_CPU(object_new_with_class(OBJECT_CLASS(xcc)));
+ xc = X86_CPU(object_new_with_class(OBJECT_CLASS(xcc), &error_abort));
x86_cpu_expand_features(xc, &err);
if (err) {
@@ -69,7 +69,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
if (cpu_list_data->model) {
Object *obj;
S390CPU *sc;
- obj = object_new_with_class(klass);
+ obj = object_new_with_class(klass, &error_abort);
sc = S390_CPU(obj);
if (sc->model) {
info->has_unavailable_features = true;
@@ -116,7 +116,10 @@ static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info,
error_setg(errp, "The CPU definition '%s' requires KVM", info->name);
return;
}
- obj = object_new_with_class(oc);
+ obj = object_new_with_class(oc, errp);
+ if (!obj) {
+ return;
+ }
cpu = S390_CPU(obj);
if (!cpu->model) {
Since object_new_with_class() accepts a non-const parameter for the class, callers should be prepared for failures from unexpected input. Add an Error parameter for this and make callers check. If the caller does not already have an Error parameter, it is satisfactory to use &error_abort if the class parameter choice is not driven by untrusted user input. This conversion allows removal of any object_class_is_abstract() checks immediately before object_new_with_class(). Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- accel/accel-user.c | 4 +++- hw/core/qdev.c | 2 +- include/qom/object.h | 9 +++++++-- net/net.c | 3 ++- qom/object.c | 4 ++-- qom/object_interfaces.c | 7 +++---- qom/qom-qmp-cmds.c | 11 ++++++----- system/vl.c | 6 ++++-- target/i386/cpu-apic.c | 8 +++++++- target/i386/cpu-sysemu.c | 11 ++++++++--- target/i386/cpu.c | 4 ++-- target/s390x/cpu_models_sysemu.c | 7 +++++-- 12 files changed, 50 insertions(+), 26 deletions(-)