@@ -178,13 +178,17 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
}
void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
- u32 elems, union v4l2_ctrl_ptr ptr)
+ u32 tot_elems, union v4l2_ctrl_ptr ptr)
{
unsigned int i;
+ u32 elems = tot_elems - from_idx;
+
+ if (from_idx >= tot_elems)
+ return;
switch (ctrl->type) {
case V4L2_CTRL_TYPE_STRING:
- for (i = from_idx; i < elems; i++) {
+ for (i = from_idx; i < tot_elems; i++) {
unsigned int offset = i * ctrl->elem_size;
memset(ptr.p_char + offset, ' ', ctrl->minimum);
@@ -193,7 +197,7 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
break;
case V4L2_CTRL_TYPE_INTEGER64:
if (ctrl->default_value) {
- for (i = from_idx; i < elems; i++)
+ for (i = from_idx; i < tot_elems; i++)
ptr.p_s64[i] = ctrl->default_value;
} else {
memset(ptr.p_s64 + from_idx, 0, elems * sizeof(s64));
@@ -205,7 +209,7 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
case V4L2_CTRL_TYPE_BITMASK:
case V4L2_CTRL_TYPE_BOOLEAN:
if (ctrl->default_value) {
- for (i = from_idx; i < elems; i++)
+ for (i = from_idx; i < tot_elems; i++)
ptr.p_s32[i] = ctrl->default_value;
} else {
memset(ptr.p_s32 + from_idx, 0, elems * sizeof(s32));
@@ -220,7 +224,7 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
break;
case V4L2_CTRL_TYPE_U16:
if (ctrl->default_value) {
- for (i = from_idx; i < elems; i++)
+ for (i = from_idx; i < tot_elems; i++)
ptr.p_u16[i] = ctrl->default_value;
} else {
memset(ptr.p_u16 + from_idx, 0, elems * sizeof(u16));
@@ -228,14 +232,14 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
break;
case V4L2_CTRL_TYPE_U32:
if (ctrl->default_value) {
- for (i = from_idx; i < elems; i++)
+ for (i = from_idx; i < tot_elems; i++)
ptr.p_u32[i] = ctrl->default_value;
} else {
memset(ptr.p_u32 + from_idx, 0, elems * sizeof(u32));
}
break;
default:
- for (i = from_idx; i < elems; i++)
+ for (i = from_idx; i < tot_elems; i++)
std_init_compound(ctrl, i, ptr);
break;
}
@@ -131,7 +131,7 @@ struct v4l2_ctrl_type_ops {
bool (*equal)(const struct v4l2_ctrl *ctrl, u32 elems,
union v4l2_ctrl_ptr ptr1,
union v4l2_ctrl_ptr ptr2);
- void (*init)(const struct v4l2_ctrl *ctrl, u32 from_idx, u32 elems,
+ void (*init)(const struct v4l2_ctrl *ctrl, u32 from_idx, u32 tot_elems,
union v4l2_ctrl_ptr ptr);
void (*log)(const struct v4l2_ctrl *ctrl);
int (*validate)(const struct v4l2_ctrl *ctrl, u32 elems,
The v4l2_ctrl_type_op_init mixed up the meaning of the 'elems' argument: in a for-loop it was the total number of elements, but in memset it was the number of elements to be cleared. This is the same as long as from_idx == 0, but when it is non-0, then it will cause a memory overrun in the memset case. Rename the 'elems' argument to 'tot_elems' and use that in the for loops. Add a new 'elems' variable that is the number of elements to clear. Since that's what memset expects, no changes are needed there. Also add a check to see if there is anything to initialize at all, and just return if there is nothing to be done. Fixes: b19b54e9ccd8 (media: v4l2-ctrls: optimize type_ops for arrays) Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> ---