diff options
author | Takashi Iwai <tiwai@suse.de> | 2016-07-25 17:01:14 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-07-25 17:01:14 +0200 |
commit | cf81d6b583444cb6f5e656f050e43413b236354e (patch) | |
tree | 646567ef019e0bbc5cc9db0e26c464a9fc239481 /sound/core/control.c | |
parent | 76df52969711ae3725a98f26fbbc6a349803dcbf (diff) | |
parent | 275353bb684ecfeb42f7a353fead81d43a01c519 (diff) | |
download | linux-cf81d6b583444cb6f5e656f050e43413b236354e.tar.bz2 |
Merge branch 'for-next' into for-linus
Merged 4.8 changes.
Diffstat (limited to 'sound/core/control.c')
-rw-r--r-- | sound/core/control.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index b4fe9b002512..fb096cb20a80 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -807,6 +807,36 @@ static int snd_ctl_elem_list(struct snd_card *card, return 0; } +static bool validate_element_member_dimension(struct snd_ctl_elem_info *info) +{ + unsigned int members; + unsigned int i; + + if (info->dimen.d[0] == 0) + return true; + + members = 1; + for (i = 0; i < ARRAY_SIZE(info->dimen.d); ++i) { + if (info->dimen.d[i] == 0) + break; + members *= info->dimen.d[i]; + + /* + * info->count should be validated in advance, to guarantee + * calculation soundness. + */ + if (members > info->count) + return false; + } + + for (++i; i < ARRAY_SIZE(info->dimen.d); ++i) { + if (info->dimen.d[i] > 0) + return false; + } + + return members == info->count; +} + static int snd_ctl_elem_info(struct snd_ctl_file *ctl, struct snd_ctl_elem_info *info) { @@ -1274,6 +1304,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, if (info->count < 1 || info->count > max_value_counts[info->type]) return -EINVAL; + if (!validate_element_member_dimension(info)) + return -EINVAL; private_size = value_sizes[info->type] * info->count; /* |