The vmstate_save_state_v() function does not support NULL in VMStateDescription::fields and will crash if one is provided.
This change prevents this situation from happening by explicitly crashing earlier. Suggested-by: Fabiano Rosas <[email protected]> Reviewed-by: Peter Xu <[email protected]> Signed-off-by: Roman Kiryanov <[email protected]> --- v3: - Also added assert to virtio.c to validate VirtioDeviceClass instances which bypass vmstate_register_with_alias_id. - Updated the commit message to "Reviewed-by". v2: - Moved the assert from vmstate_save_state_v to the registration path (vmstate_register_with_alias_id) and the qtest validation path (vmstate_check) to catch missing fields earlier. --- hw/virtio/virtio.c | 6 ++++++ migration/savevm.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 0ba734d0bc..e4543de335 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -4054,6 +4054,12 @@ static void virtio_device_realize(DeviceState *dev, Error **errp) /* Devices should either use vmsd or the load/save methods */ assert(!vdc->vmsd || !vdc->load); + /* + * If a device has vmsd, it either MUST have valid fields + * or marked unmigratable. + */ + assert(!vdc->vmsd || (vdc->vmsd->unmigratable || vdc->vmsd->fields)); + if (vdc->realize != NULL) { vdc->realize(dev, &err); if (err != NULL) { diff --git a/migration/savevm.c b/migration/savevm.c index 197c89e0e6..20c2b99231 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -861,6 +861,8 @@ static void vmstate_check(const VMStateDescription *vmsd) const VMStateField *field = vmsd->fields; const VMStateDescription * const *subsection = vmsd->subsections; + assert(field || vmsd->unmigratable); + if (field) { while (field->name) { if (field->flags & (VMS_STRUCT | VMS_VSTRUCT)) { @@ -900,6 +902,9 @@ int vmstate_register_with_alias_id(VMStateIf *obj, uint32_t instance_id, /* If this triggers, alias support can be dropped for the vmsd. */ assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id); + /* If vmsd is migratable it MUST have valid fields. */ + assert(vmsd->fields || vmsd->unmigratable); + se = g_new0(SaveStateEntry, 1); se->version_id = vmsd->version_id; se->section_id = savevm_state.global_section_id++; -- 2.53.0.851.ga537e3e6e9-goog
