domain_capabilities: Assert enums fit into unsigned int bitmask

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@redhat.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
Michal Privoznik 2020-11-18 11:58:01 +01:00
parent 1fdbd4047e
commit 912421e7b6

View File

@ -36,6 +36,9 @@ struct _virDomainCapsEnum {
unsigned int values; /* Bitmask of values supported in the corresponding enum */ 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 struct _virDomainCapsStringValues virDomainCapsStringValues;
typedef virDomainCapsStringValues *virDomainCapsStringValuesPtr; typedef virDomainCapsStringValues *virDomainCapsStringValuesPtr;
struct _virDomainCapsStringValues { struct _virDomainCapsStringValues {
@ -43,6 +46,8 @@ struct _virDomainCapsStringValues {
size_t nvalues; /* number of strings */ 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 struct _virDomainCapsLoader virDomainCapsLoader;
typedef virDomainCapsLoader *virDomainCapsLoaderPtr; typedef virDomainCapsLoader *virDomainCapsLoaderPtr;
struct _virDomainCapsLoader { struct _virDomainCapsLoader {
@ -53,6 +58,7 @@ struct _virDomainCapsLoader {
virDomainCapsEnum secure; /* Info about secure:virTristateBool */ virDomainCapsEnum secure; /* Info about secure:virTristateBool */
}; };
STATIC_ASSERT_ENUM(VIR_DOMAIN_OS_DEF_FIRMWARE_LAST);
typedef struct _virDomainCapsOS virDomainCapsOS; typedef struct _virDomainCapsOS virDomainCapsOS;
typedef virDomainCapsOS *virDomainCapsOSPtr; typedef virDomainCapsOS *virDomainCapsOSPtr;
struct _virDomainCapsOS { struct _virDomainCapsOS {
@ -61,6 +67,9 @@ struct _virDomainCapsOS {
virDomainCapsLoader loader; /* Info about virDomainLoaderDef */ 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 struct _virDomainCapsDeviceDisk virDomainCapsDeviceDisk;
typedef virDomainCapsDeviceDisk *virDomainCapsDeviceDiskPtr; typedef virDomainCapsDeviceDisk *virDomainCapsDeviceDiskPtr;
struct _virDomainCapsDeviceDisk { struct _virDomainCapsDeviceDisk {
@ -71,6 +80,7 @@ struct _virDomainCapsDeviceDisk {
/* add new fields here */ /* add new fields here */
}; };
STATIC_ASSERT_ENUM(VIR_DOMAIN_GRAPHICS_TYPE_LAST);
typedef struct _virDomainCapsDeviceGraphics virDomainCapsDeviceGraphics; typedef struct _virDomainCapsDeviceGraphics virDomainCapsDeviceGraphics;
typedef virDomainCapsDeviceGraphics *virDomainCapsDeviceGraphicsPtr; typedef virDomainCapsDeviceGraphics *virDomainCapsDeviceGraphicsPtr;
struct _virDomainCapsDeviceGraphics { struct _virDomainCapsDeviceGraphics {
@ -78,6 +88,7 @@ struct _virDomainCapsDeviceGraphics {
virDomainCapsEnum type; /* virDomainGraphicsType */ virDomainCapsEnum type; /* virDomainGraphicsType */
}; };
STATIC_ASSERT_ENUM(VIR_DOMAIN_VIDEO_TYPE_LAST);
typedef struct _virDomainCapsDeviceVideo virDomainCapsDeviceVideo; typedef struct _virDomainCapsDeviceVideo virDomainCapsDeviceVideo;
typedef virDomainCapsDeviceVideo *virDomainCapsDeviceVideoPtr; typedef virDomainCapsDeviceVideo *virDomainCapsDeviceVideoPtr;
struct _virDomainCapsDeviceVideo { struct _virDomainCapsDeviceVideo {
@ -85,6 +96,11 @@ struct _virDomainCapsDeviceVideo {
virDomainCapsEnum modelType; /* virDomainVideoType */ 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 struct _virDomainCapsDeviceHostdev virDomainCapsDeviceHostdev;
typedef virDomainCapsDeviceHostdev *virDomainCapsDeviceHostdevPtr; typedef virDomainCapsDeviceHostdev *virDomainCapsDeviceHostdevPtr;
struct _virDomainCapsDeviceHostdev { struct _virDomainCapsDeviceHostdev {
@ -97,6 +113,8 @@ struct _virDomainCapsDeviceHostdev {
/* add new fields here */ /* 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 struct _virDomainCapsDeviceRNG virDomainCapsDeviceRNG;
typedef virDomainCapsDeviceRNG *virDomainCapsDeviceRNGPtr; typedef virDomainCapsDeviceRNG *virDomainCapsDeviceRNGPtr;
struct _virDomainCapsDeviceRNG { struct _virDomainCapsDeviceRNG {
@ -105,6 +123,7 @@ struct _virDomainCapsDeviceRNG {
virDomainCapsEnum backendModel; /* virDomainRNGBackend */ virDomainCapsEnum backendModel; /* virDomainRNGBackend */
}; };
STATIC_ASSERT_ENUM(VIR_GIC_VERSION_LAST);
typedef struct _virDomainCapsFeatureGIC virDomainCapsFeatureGIC; typedef struct _virDomainCapsFeatureGIC virDomainCapsFeatureGIC;
typedef virDomainCapsFeatureGIC *virDomainCapsFeatureGICPtr; typedef virDomainCapsFeatureGIC *virDomainCapsFeatureGICPtr;
struct _virDomainCapsFeatureGIC { struct _virDomainCapsFeatureGIC {