diff mbox series

media: v4l2-ctrls-core.c: fix incorrect init if from_idx > 0

Message ID 6c02f890-84e7-a39c-9365-7c5fdc1fef5a@xs4all.nl (mailing list archive)
State New, archived
Headers show
Series media: v4l2-ctrls-core.c: fix incorrect init if from_idx > 0 | expand

Commit Message

Hans Verkuil Aug. 26, 2022, 2:03 p.m. UTC
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>
---
diff mbox series

Patch

diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index 5d1a89884b28..01f00093f259 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -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;
 	}
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index b2acb64d55aa..b76a0714d425 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -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,