plane: check value for range/enum/bitmask properties

We need to drop the assert from apply_current(): the new value
may be outside the range for instance.

Closes: https://gitlab.freedesktop.org/emersion/libliftoff/-/issues/47
This commit is contained in:
Simon Ser 2023-02-15 19:07:15 +01:00
parent 46f35829e0
commit 0b910624f5
2 changed files with 70 additions and 1 deletions

View file

@ -519,7 +519,6 @@ apply_current(struct liftoff_device *device, drmModeAtomicReq *req)
liftoff_list_for_each(plane, &device->planes, link) {
ret = plane_apply(plane, plane->layer, req);
assert(ret != -EINVAL);
if (ret != 0) {
drmModeAtomicSetCursor(req, cursor);
return ret;

70
plane.c
View file

@ -181,6 +181,55 @@ plane_get_property(struct liftoff_plane *plane, const char *name)
return NULL;
}
static int
check_range_prop(const drmModePropertyRes *prop, uint64_t value)
{
if (value < prop->values[0] || value > prop->values[1]) {
return -EINVAL;
}
return 0;
}
static int
check_enum_prop(const drmModePropertyRes *prop, uint64_t value)
{
int i;
for (i = 0; i < prop->count_enums; i++) {
if (prop->enums[i].value == value) {
return 0;
}
}
return -EINVAL;
}
static int
check_bitmask_prop(const drmModePropertyRes *prop, uint64_t value)
{
int i;
uint64_t mask;
mask = 0;
for (i = 0; i < prop->count_enums; i++) {
mask |= 1 << prop->enums[i].value;
}
if ((value & ~mask) != 0) {
return -EINVAL;
}
return 0;
}
static int
check_signed_range_prop(const drmModePropertyRes *prop, uint64_t value)
{
if ((int64_t) value < (int64_t) prop->values[0] ||
(int64_t) value > (int64_t) prop->values[1]) {
return -EINVAL;
}
return 0;
}
static int
plane_set_prop(struct liftoff_plane *plane, drmModeAtomicReq *req,
const drmModePropertyRes *prop, uint64_t value)
@ -191,6 +240,27 @@ plane_set_prop(struct liftoff_plane *plane, drmModeAtomicReq *req,
return -EINVAL;
}
/* Manually check the property value if we can: this may avoid
* unnecessary test commits */
ret = 0;
switch (drmModeGetPropertyType(prop)) {
case DRM_MODE_PROP_RANGE:
ret = check_range_prop(prop, value);
break;
case DRM_MODE_PROP_ENUM:
ret = check_enum_prop(prop, value);
break;
case DRM_MODE_PROP_BITMASK:
ret = check_bitmask_prop(prop, value);
break;
case DRM_MODE_PROP_SIGNED_RANGE:
ret = check_signed_range_prop(prop, value);
break;
}
if (ret != 0) {
return ret;
}
ret = drmModeAtomicAddProperty(req, plane->id, prop->prop_id, value);
if (ret < 0) {
liftoff_log(LIFTOFF_ERROR, "drmModeAtomicAddProperty: %s",