qdev_new() has a failure scenario where it will assert() if given an abstract type. Callers which are creating qdevs based on user input, or unknown/untrusted type names, must manually check the result of qdev_class_is_abstract() before calling qdev_new() to propagate an Error, instead of asserting.
Introduce a qdev_new_dynamic() method which is a counterpart to qdev_new() that directly returns an Error, instead of asserting. This new method is to be used where the typename is specified dynamically by code separate from the immediate caller. Signed-off-by: Daniel P. Berrangé <berra...@redhat.com> --- hw/core/qdev.c | 5 +++++ include/hw/qdev-core.h | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 7fcbbe431b..eceba33222 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -149,6 +149,11 @@ DeviceState *qdev_new(const char *name) return DEVICE(object_new_dynamic(name, &error_abort)); } +DeviceState *qdev_new_dynamic(const char *name, Error **errp) +{ + return DEVICE(object_new_dynamic(name, errp)); +} + static QTAILQ_HEAD(, DeviceListener) device_listeners = QTAILQ_HEAD_INITIALIZER(device_listeners); diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 020417d027..566c5ef277 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -435,14 +435,41 @@ compat_props_add(GPtrArray *arr, * qdev_new: Create a device on the heap * @name: device type to create (we assert() that this type exists) * + * This method should be used where @name is statically specified + * from a const string at build time, where the caller does not expect + * failure to be possible. + * * This only allocates the memory and initializes the device state * structure, ready for the caller to set properties if they wish. * The device still needs to be realized. * + * If an instance of @name is not permitted to be instantiated, an + * assert will be raised. This can happen if @name is abstract. + * * Return: a derived DeviceState object with a reference count of 1. */ DeviceState *qdev_new(const char *name); +/** + * qdev_new_dynamic: Create a device on the heap + * @name: device type to create (we assert() that this type exists) + * @errp: pointer to be filled with error details on failure + * + * This method must be used where @name is dynamically chosen + * at runtime, which has the possibility of unexpected choices leading + * to failures. + * + * This only allocates the memory and initializes the device state + * structure, ready for the caller to set properties if they wish. + * The device still needs to be realized. + * + * If an instance of @name is not permitted to be instantiated, an + * error will be reported. This can happen if @name is abstract. + * + * Return: a derived DeviceState object with a reference count of 1. + */ +DeviceState *qdev_new_dynamic(const char *name, Error **errp); + /** * qdev_is_realized() - check if device is realized * @dev: The device to check. -- 2.46.0