The way our domain capabilities work currently, is that we have virDomainCapsEnum struct which contains 'unsigned int values' member which serves as a bitmask. More complicated structs are composed from this struct, giving us whole virDomainCaps eventually. Whenever we want to report that a certain value is supported, the '1 << value' bit is set in the corresponding unsigned int member. This works as long as the resulting value after bitshift does not overflow unsigned int. There is a check inside virDomainCapsEnumSet() which ensures exactly this, but no caller really checks whether virDomainCapsEnumSet() succeeded. Also, checking at runtime is a bit too late. Fortunately, we know the largest value we want to store in each member, because each enum of ours ends with _LAST member. Therefore, we can check at build time whether an overflow can occur. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- src/conf/domain_capabilities.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index f177af1744..b22d40abb2 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -36,6 +36,9 @@ struct _virDomainCapsEnum { unsigned int values; /* Bitmask of values supported in the corresponding enum */ }; +#define STATIC_ASSERT_ENUM(last) \ + G_STATIC_ASSERT(last <= sizeof(unsigned int) * CHAR_BIT) + typedef struct _virDomainCapsStringValues virDomainCapsStringValues; typedef virDomainCapsStringValues *virDomainCapsStringValuesPtr; struct _virDomainCapsStringValues { @@ -43,6 +46,8 @@ struct _virDomainCapsStringValues { size_t nvalues; /* number of strings */ }; +STATIC_ASSERT_ENUM(VIR_DOMAIN_LOADER_TYPE_LAST); +STATIC_ASSERT_ENUM(VIR_TRISTATE_BOOL_LAST); typedef struct _virDomainCapsLoader virDomainCapsLoader; typedef virDomainCapsLoader *virDomainCapsLoaderPtr; struct _virDomainCapsLoader { @@ -53,6 +58,7 @@ struct _virDomainCapsLoader { virDomainCapsEnum secure; /* Info about secure:virTristateBool */ }; +STATIC_ASSERT_ENUM(VIR_DOMAIN_OS_DEF_FIRMWARE_LAST); typedef struct _virDomainCapsOS virDomainCapsOS; typedef virDomainCapsOS *virDomainCapsOSPtr; struct _virDomainCapsOS { @@ -61,6 +67,9 @@ struct _virDomainCapsOS { virDomainCapsLoader loader; /* Info about virDomainLoaderDef */ }; +STATIC_ASSERT_ENUM(VIR_DOMAIN_DISK_DEVICE_LAST); +STATIC_ASSERT_ENUM(VIR_DOMAIN_DISK_BUS_LAST); +STATIC_ASSERT_ENUM(VIR_DOMAIN_DISK_MODEL_LAST); typedef struct _virDomainCapsDeviceDisk virDomainCapsDeviceDisk; typedef virDomainCapsDeviceDisk *virDomainCapsDeviceDiskPtr; struct _virDomainCapsDeviceDisk { @@ -71,6 +80,7 @@ struct _virDomainCapsDeviceDisk { /* add new fields here */ }; +STATIC_ASSERT_ENUM(VIR_DOMAIN_GRAPHICS_TYPE_LAST); typedef struct _virDomainCapsDeviceGraphics virDomainCapsDeviceGraphics; typedef virDomainCapsDeviceGraphics *virDomainCapsDeviceGraphicsPtr; struct _virDomainCapsDeviceGraphics { @@ -78,6 +88,7 @@ struct _virDomainCapsDeviceGraphics { virDomainCapsEnum type; /* virDomainGraphicsType */ }; +STATIC_ASSERT_ENUM(VIR_DOMAIN_VIDEO_TYPE_LAST); typedef struct _virDomainCapsDeviceVideo virDomainCapsDeviceVideo; typedef virDomainCapsDeviceVideo *virDomainCapsDeviceVideoPtr; struct _virDomainCapsDeviceVideo { @@ -85,6 +96,11 @@ struct _virDomainCapsDeviceVideo { virDomainCapsEnum modelType; /* virDomainVideoType */ }; +STATIC_ASSERT_ENUM(VIR_DOMAIN_HOSTDEV_MODE_LAST); +STATIC_ASSERT_ENUM(VIR_DOMAIN_STARTUP_POLICY_LAST); +STATIC_ASSERT_ENUM(VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST); +STATIC_ASSERT_ENUM(VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST); +STATIC_ASSERT_ENUM(VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST); typedef struct _virDomainCapsDeviceHostdev virDomainCapsDeviceHostdev; typedef virDomainCapsDeviceHostdev *virDomainCapsDeviceHostdevPtr; struct _virDomainCapsDeviceHostdev { @@ -97,6 +113,8 @@ struct _virDomainCapsDeviceHostdev { /* add new fields here */ }; +STATIC_ASSERT_ENUM(VIR_DOMAIN_RNG_MODEL_LAST); +STATIC_ASSERT_ENUM(VIR_DOMAIN_RNG_BACKEND_LAST); typedef struct _virDomainCapsDeviceRNG virDomainCapsDeviceRNG; typedef virDomainCapsDeviceRNG *virDomainCapsDeviceRNGPtr; struct _virDomainCapsDeviceRNG { @@ -105,6 +123,7 @@ struct _virDomainCapsDeviceRNG { virDomainCapsEnum backendModel; /* virDomainRNGBackend */ }; +STATIC_ASSERT_ENUM(VIR_GIC_VERSION_LAST); typedef struct _virDomainCapsFeatureGIC virDomainCapsFeatureGIC; typedef virDomainCapsFeatureGIC *virDomainCapsFeatureGICPtr; struct _virDomainCapsFeatureGIC { -- 2.26.2