avformat/vorbiscomment: use null buf to calculate vorbis comment length

Also check possible failures when calculating length, and change return type to
int as bigger return values are no longer possible.
This commit is contained in:
Marton Balint
2025-12-23 02:52:59 +01:00
parent c80d3b35ae
commit b2e077ad69
5 changed files with 27 additions and 25 deletions

View File

@@ -64,11 +64,13 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
int last_block, int bitexact)
{
const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
int64_t len;
int len;
ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
len = ff_vorbiscomment_length(*m, vendor, NULL, 0);
if (len < 0)
return len;
if (len >= ((1<<24) - 4))
return AVERROR(EINVAL);

View File

@@ -1061,12 +1061,14 @@ static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb,
"Lavf" : LIBAVFORMAT_IDENT;
AVDictionary *dict = NULL;
uint8_t buf[32];
int64_t len;
int len;
snprintf(buf, sizeof(buf), "0x%"PRIx64, par->ch_layout.u.mask);
av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0);
len = ff_vorbiscomment_length(dict, vendor, NULL, 0);
if (len < 0)
return len;
av_assert1(len < (1 << 24) - 4);
avio_w8(pb, 0x84);

View File

@@ -295,7 +295,10 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
size = offset + ff_vorbiscomment_length(*m, vendor, chapters, nb_chapters) + framing_bit;
size = ff_vorbiscomment_length(*m, vendor, chapters, nb_chapters);
if (size < 0)
return NULL;
size += offset + framing_bit;
if (size > INT_MAX)
return NULL;
p = av_mallocz(size);

View File

@@ -20,6 +20,7 @@
*/
#include "avio.h"
#include "avio_internal.h"
#include "avformat.h"
#include "metadata.h"
#include "vorbiscomment.h"
@@ -38,27 +39,21 @@ const AVMetadataConv ff_vorbiscomment_metadata_conv[] = {
{ 0 }
};
int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string,
AVChapter **chapters, unsigned int nb_chapters)
int ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string,
AVChapter **chapters, unsigned int nb_chapters)
{
int64_t len = 8;
len += strlen(vendor_string);
if (chapters && nb_chapters) {
for (int i = 0; i < nb_chapters; i++) {
const AVDictionaryEntry *tag = NULL;
len += 4 + 12 + 1 + 10;
while ((tag = av_dict_iterate(chapters[i]->metadata, tag))) {
int64_t len1 = !strcmp(tag->key, "title") ? 4 : strlen(tag->key);
len += 4 + 10 + len1 + 1 + strlen(tag->value);
}
}
}
if (m) {
const AVDictionaryEntry *tag = NULL;
while ((tag = av_dict_iterate(m, tag))) {
len += 4 +strlen(tag->key) + 1 + strlen(tag->value);
}
}
AVIOContext *avio_buf;
int ret, len;
ret = ffio_open_null_buf(&avio_buf);
if (ret < 0)
return ret;
ret = ff_vorbiscomment_write(avio_buf, m, vendor_string, chapters, nb_chapters);
len = ffio_close_null_buf(avio_buf);
if (ret < 0)
return ret;
return len;
}

View File

@@ -34,8 +34,8 @@
* For no string, set to an empty string.
* @return The length in bytes.
*/
int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string,
AVChapter **chapters, unsigned int nb_chapters);
int ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string,
AVChapter **chapters, unsigned int nb_chapters);
/**
* Write a VorbisComment into an AVIOContext. The output size can be obtained