media: v4l2-tpg: fix some memleaks in tpg_alloc

[ Upstream commit 8cf9c50510 ]

In tpg_alloc, resources should be deallocated in each and every
error-handling paths, since they are allocated in for statements.
Otherwise there would be memleaks because tpg_free is called only when
tpg_alloc return 0.

Fixes: 63881df94d ("[media] vivid: add the Test Pattern Generator")
Signed-off-by: Zhipeng Lu <alexious@zju.edu.cn>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Zhipeng Lu 2024-02-01 20:47:53 +08:00 committed by Sasha Levin
parent 3828fc3ab8
commit 6bf5c2fade
1 changed files with 42 additions and 10 deletions

View File

@ -113,6 +113,7 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
{
unsigned pat;
unsigned plane;
int ret = 0;
tpg->max_line_width = max_w;
for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) {
@ -121,14 +122,18 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
tpg->lines[pat][plane] =
vzalloc(array3_size(max_w, 2, pixelsz));
if (!tpg->lines[pat][plane])
return -ENOMEM;
if (!tpg->lines[pat][plane]) {
ret = -ENOMEM;
goto free_lines;
}
if (plane == 0)
continue;
tpg->downsampled_lines[pat][plane] =
vzalloc(array3_size(max_w, 2, pixelsz));
if (!tpg->downsampled_lines[pat][plane])
return -ENOMEM;
if (!tpg->downsampled_lines[pat][plane]) {
ret = -ENOMEM;
goto free_lines;
}
}
}
for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
@ -136,18 +141,45 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
tpg->contrast_line[plane] =
vzalloc(array_size(pixelsz, max_w));
if (!tpg->contrast_line[plane])
return -ENOMEM;
if (!tpg->contrast_line[plane]) {
ret = -ENOMEM;
goto free_contrast_line;
}
tpg->black_line[plane] =
vzalloc(array_size(pixelsz, max_w));
if (!tpg->black_line[plane])
return -ENOMEM;
if (!tpg->black_line[plane]) {
ret = -ENOMEM;
goto free_contrast_line;
}
tpg->random_line[plane] =
vzalloc(array3_size(max_w, 2, pixelsz));
if (!tpg->random_line[plane])
return -ENOMEM;
if (!tpg->random_line[plane]) {
ret = -ENOMEM;
goto free_contrast_line;
}
}
return 0;
free_contrast_line:
for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
vfree(tpg->contrast_line[plane]);
vfree(tpg->black_line[plane]);
vfree(tpg->random_line[plane]);
tpg->contrast_line[plane] = NULL;
tpg->black_line[plane] = NULL;
tpg->random_line[plane] = NULL;
}
free_lines:
for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++)
for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
vfree(tpg->lines[pat][plane]);
tpg->lines[pat][plane] = NULL;
if (plane == 0)
continue;
vfree(tpg->downsampled_lines[pat][plane]);
tpg->downsampled_lines[pat][plane] = NULL;
}
return ret;
}
EXPORT_SYMBOL_GPL(tpg_alloc);