media: v4l2-ctrls-core.c: check min/max for menu, controls
authorHans Verkuil <hverkuil-cisco@xs4all.nl>
Mon, 5 Feb 2024 11:10:31 +0000 (12:10 +0100)
committerHans Verkuil <hverkuil-cisco@xs4all.nl>
Fri, 16 Feb 2024 10:46:32 +0000 (11:46 +0100)
Menu controls that use the menu_skip_mask require that the min-max range is
inside 0-63.

Negative values obviously make no sense for menu controls, and the maximum
value is currently limited by the number of bits of the menu_skip_mask
value. However, if menu_skip_mask == 0, then larger menus are fine.

If we ever need to add support for larger menus that support the skip
mask, then more work is needed.

In the places where the menu_skip_mask is checked, use BIT_ULL to get the
bit to check and check if the bit number is < BITS_PER_LONG_LONG to avoid
shifting out of range. With the new check in check_range this should
never happen, but it is better to be safe and avoid static analyzer
warnings.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
drivers/media/v4l2-core/v4l2-ctrls-api.c
drivers/media/v4l2-core/v4l2-ctrls-core.c

index 002ea6588edf163d116ccfff8be7cf18cfe733da..d9a422017bd9d05bb0f8c74a4bc0cb7210316bf3 100644 (file)
@@ -1179,7 +1179,7 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)
                return -EINVAL;
 
        /* Use mask to see if this menu item should be skipped */
-       if (ctrl->menu_skip_mask & (1ULL << i))
+       if (i < BITS_PER_LONG_LONG && (ctrl->menu_skip_mask & BIT_ULL(i)))
                return -EINVAL;
        /* Empty menu items should also be skipped */
        if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
index 0accb96001db07a7d4a5835c7cebf3536f0f1eba..c4d995f32191c9dfce3ff0dbc430f89a02a61d31 100644 (file)
@@ -1504,11 +1504,12 @@ int check_range(enum v4l2_ctrl_type type,
                return 0;
        case V4L2_CTRL_TYPE_MENU:
        case V4L2_CTRL_TYPE_INTEGER_MENU:
-               if (min > max || def < min || def > max)
+               if (min > max || def < min || def > max ||
+                   min < 0 || (step && max >= BITS_PER_LONG_LONG))
                        return -ERANGE;
                /* Note: step == menu_skip_mask for menu controls.
                   So here we check if the default value is masked out. */
-               if (step && ((1 << def) & step))
+               if (def < BITS_PER_LONG_LONG && (step & BIT_ULL(def)))
                        return -EINVAL;
                return 0;
        case V4L2_CTRL_TYPE_STRING: