From 14226be499d27935d54981f0a6e1b15fd65746cd Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Mon, 24 Aug 2020 06:34:17 +0200 Subject: [PATCH] avfilter/af_headphone: Don't overrun array The headphone filter stores the channel position of the ith HRIR stream in the ith element of an array of 64 elements; but because there is no check for duplicate channels, it is easy to write beyond the end of the array by simply repeating channels. This commit adds a check for duplicate channels to rule this out. Reviewed-by: Paul B Mahol Signed-off-by: Andreas Rheinhardt --- libavfilter/af_headphone.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index 54b5dfec4c..99bdefbcff 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -88,15 +88,13 @@ typedef struct HeadphoneContext { } *in; } HeadphoneContext; -static int parse_channel_name(HeadphoneContext *s, int x, char **arg, int *rchannel, char *buf) +static int parse_channel_name(char **arg, int *rchannel, char *buf) { int len, i, channel_id = 0; int64_t layout, layout0; if (sscanf(*arg, "%7[A-Z]%n", buf, &len)) { layout0 = layout = av_get_channel_layout(buf); - if (layout == AV_CH_LOW_FREQUENCY) - s->lfe_channel = x; for (i = 32; i > 0; i >>= 1) { if (layout >= 1LL << i) { channel_id += i; @@ -116,6 +114,7 @@ static void parse_map(AVFilterContext *ctx) { HeadphoneContext *s = ctx->priv; char *arg, *tokenizer, *p, *args = av_strdup(s->map); + uint64_t used_channels = 0; int i; if (!args) @@ -134,10 +133,17 @@ static void parse_map(AVFilterContext *ctx) char buf[8]; p = NULL; - if (parse_channel_name(s, s->nb_irs, &arg, &out_ch_id, buf)) { + if (parse_channel_name(&arg, &out_ch_id, buf)) { av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", arg); continue; } + if (used_channels & (1ULL << out_ch_id)) { + av_log(ctx, AV_LOG_WARNING, "Ignoring duplicate channel '%s'.\n", buf); + continue; + } + used_channels |= 1ULL << out_ch_id; + if (out_ch_id == av_log2(AV_CH_LOW_FREQUENCY)) + s->lfe_channel = s->nb_irs; s->mapping[s->nb_irs] = out_ch_id; s->nb_irs++; }