This commit also makes sure the extradata and subtitle_header are NUL terminated, without taking into account the trailing '\0' in account in the size. At the same time, it should fix 'warning: dereferencing type-punned pointer will break strict-aliasing rules' warning for compilers who don't consider uint8_t** and char** compatibles.tags/n1.1
| @@ -29,10 +29,11 @@ | |||||
| static av_cold int ass_decode_init(AVCodecContext *avctx) | static av_cold int ass_decode_init(AVCodecContext *avctx) | ||||
| { | { | ||||
| avctx->subtitle_header = av_malloc(avctx->extradata_size); | |||||
| avctx->subtitle_header = av_malloc(avctx->extradata_size + 1); | |||||
| if (!avctx->subtitle_header) | if (!avctx->subtitle_header) | ||||
| return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | ||||
| memcpy(avctx->subtitle_header, avctx->extradata, avctx->extradata_size); | memcpy(avctx->subtitle_header, avctx->extradata, avctx->extradata_size); | ||||
| avctx->subtitle_header[avctx->extradata_size] = 0; | |||||
| avctx->subtitle_header_size = avctx->extradata_size; | avctx->subtitle_header_size = avctx->extradata_size; | ||||
| avctx->priv_data = ff_ass_split(avctx->extradata); | avctx->priv_data = ff_ass_split(avctx->extradata); | ||||
| if(!avctx->priv_data) | if(!avctx->priv_data) | ||||
| @@ -28,11 +28,12 @@ | |||||
| static av_cold int ass_encode_init(AVCodecContext *avctx) | static av_cold int ass_encode_init(AVCodecContext *avctx) | ||||
| { | { | ||||
| avctx->extradata = av_malloc(avctx->subtitle_header_size); | |||||
| avctx->extradata = av_malloc(avctx->subtitle_header_size + 1); | |||||
| if (!avctx->extradata) | if (!avctx->extradata) | ||||
| return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | ||||
| memcpy(avctx->extradata, avctx->subtitle_header, avctx->subtitle_header_size); | memcpy(avctx->extradata, avctx->subtitle_header, avctx->subtitle_header_size); | ||||
| avctx->extradata_size = avctx->subtitle_header_size; | avctx->extradata_size = avctx->subtitle_header_size; | ||||
| avctx->extradata[avctx->extradata_size] = 0; | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -20,6 +20,7 @@ | |||||
| */ | */ | ||||
| #include "avcodec.h" | #include "avcodec.h" | ||||
| #include "bytestream.h" | #include "bytestream.h" | ||||
| #include "internal.h" | |||||
| #include "libavutil/avassert.h" | #include "libavutil/avassert.h" | ||||
| #include "libavutil/bprint.h" | #include "libavutil/bprint.h" | ||||
| #include "libavutil/imgutils.h" | #include "libavutil/imgutils.h" | ||||
| @@ -408,9 +409,9 @@ static int dvdsub_init(AVCodecContext *avctx) | |||||
| av_bprintf(&extradata, " %06"PRIx32"%c", | av_bprintf(&extradata, " %06"PRIx32"%c", | ||||
| dvdc->global_palette[i] & 0xFFFFFF, i < 15 ? ',' : '\n'); | dvdc->global_palette[i] & 0xFFFFFF, i < 15 ? ',' : '\n'); | ||||
| if ((ret = av_bprint_finalize(&extradata, (char **)&avctx->extradata)) < 0) | |||||
| ret = ff_bprint_to_extradata(avctx, &extradata); | |||||
| if (ret < 0) | |||||
| return ret; | return ret; | ||||
| avctx->extradata_size = extradata.len; | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -201,4 +201,9 @@ int ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDict | |||||
| */ | */ | ||||
| int ff_codec_close_recursive(AVCodecContext *avctx); | int ff_codec_close_recursive(AVCodecContext *avctx); | ||||
| /** | |||||
| * Finalize buf into extradata and set its size appropriately. | |||||
| */ | |||||
| int ff_bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf); | |||||
| #endif /* AVCODEC_INTERNAL_H */ | #endif /* AVCODEC_INTERNAL_H */ | ||||
| @@ -27,6 +27,7 @@ | |||||
| #include "libavutil/avassert.h" | #include "libavutil/avassert.h" | ||||
| #include "libavutil/avstring.h" | #include "libavutil/avstring.h" | ||||
| #include "libavutil/bprint.h" | |||||
| #include "libavutil/channel_layout.h" | #include "libavutil/channel_layout.h" | ||||
| #include "libavutil/crc.h" | #include "libavutil/crc.h" | ||||
| #include "libavutil/mathematics.h" | #include "libavutil/mathematics.h" | ||||
| @@ -2684,3 +2685,21 @@ int avcodec_is_open(AVCodecContext *s) | |||||
| { | { | ||||
| return !!s->internal; | return !!s->internal; | ||||
| } | } | ||||
| int ff_bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf) | |||||
| { | |||||
| int ret; | |||||
| char *str; | |||||
| ret = av_bprint_finalize(buf, &str); | |||||
| if (ret < 0) | |||||
| return ret; | |||||
| avctx->extradata = str; | |||||
| /* Note: the string is NUL terminated (so extradata can be read as a | |||||
| * string), but the ending character is not accounted in the size (in | |||||
| * binary formats you are likely not supposed to mux that character). When | |||||
| * extradata is copied, it is also padded with FF_INPUT_BUFFER_PADDING_SIZE | |||||
| * zeros. */ | |||||
| avctx->extradata_size = buf->len; | |||||
| return 0; | |||||
| } | |||||
| @@ -22,6 +22,7 @@ | |||||
| #include "avformat.h" | #include "avformat.h" | ||||
| #include "internal.h" | #include "internal.h" | ||||
| #include "subtitles.h" | #include "subtitles.h" | ||||
| #include "libavcodec/internal.h" | |||||
| #include "libavutil/bprint.h" | #include "libavutil/bprint.h" | ||||
| typedef struct ASSContext{ | typedef struct ASSContext{ | ||||
| @@ -132,12 +133,9 @@ static int ass_read_header(AVFormatContext *s) | |||||
| av_bprint_finalize(&line, NULL); | av_bprint_finalize(&line, NULL); | ||||
| av_bprint_finalize(&header, (char **)&st->codec->extradata); | |||||
| if (!st->codec->extradata) { | |||||
| res = AVERROR(ENOMEM); | |||||
| res = ff_bprint_to_extradata(st->codec, &header); | |||||
| if (res < 0) | |||||
| goto end; | goto end; | ||||
| } | |||||
| st->codec->extradata_size = header.len + 1; | |||||
| ff_subtitles_queue_finalize(&ass->q); | ff_subtitles_queue_finalize(&ass->q); | ||||
| @@ -28,6 +28,7 @@ | |||||
| #include "avformat.h" | #include "avformat.h" | ||||
| #include "internal.h" | #include "internal.h" | ||||
| #include "subtitles.h" | #include "subtitles.h" | ||||
| #include "libavcodec/internal.h" | |||||
| #include "libavcodec/jacosub.h" | #include "libavcodec/jacosub.h" | ||||
| #include "libavutil/avstring.h" | #include "libavutil/avstring.h" | ||||
| #include "libavutil/bprint.h" | #include "libavutil/bprint.h" | ||||
| @@ -159,7 +160,7 @@ static int jacosub_read_header(AVFormatContext *s) | |||||
| JACOsubContext *jacosub = s->priv_data; | JACOsubContext *jacosub = s->priv_data; | ||||
| int shift_set = 0; // only the first shift matters | int shift_set = 0; // only the first shift matters | ||||
| int merge_line = 0; | int merge_line = 0; | ||||
| int i; | |||||
| int i, ret; | |||||
| AVStream *st = avformat_new_stream(s, NULL); | AVStream *st = avformat_new_stream(s, NULL); | ||||
| if (!st) | if (!st) | ||||
| @@ -228,8 +229,9 @@ static int jacosub_read_header(AVFormatContext *s) | |||||
| } | } | ||||
| /* general/essential directives in the extradata */ | /* general/essential directives in the extradata */ | ||||
| av_bprint_finalize(&header, (char **)&st->codec->extradata); | |||||
| st->codec->extradata_size = header.len + 1; | |||||
| ret = ff_bprint_to_extradata(st->codec, &header); | |||||
| if (ret < 0) | |||||
| return ret; | |||||
| /* SHIFT and TIMERES affect the whole script so packet timing can only be | /* SHIFT and TIMERES affect the whole script so packet timing can only be | ||||
| * done in a second pass */ | * done in a second pass */ | ||||
| @@ -27,6 +27,7 @@ | |||||
| #include "avformat.h" | #include "avformat.h" | ||||
| #include "internal.h" | #include "internal.h" | ||||
| #include "subtitles.h" | #include "subtitles.h" | ||||
| #include "libavcodec/internal.h" | |||||
| #include "libavutil/avstring.h" | #include "libavutil/avstring.h" | ||||
| #include "libavutil/bprint.h" | #include "libavutil/bprint.h" | ||||
| #include "libavutil/intreadwrite.h" | #include "libavutil/intreadwrite.h" | ||||
| @@ -91,13 +92,9 @@ static int sami_read_header(AVFormatContext *s) | |||||
| av_bprint_clear(&buf); | av_bprint_clear(&buf); | ||||
| } | } | ||||
| st->codec->extradata_size = hdr_buf.len + 1; | |||||
| av_bprint_finalize(&hdr_buf, (char **)&st->codec->extradata); | |||||
| if (!st->codec->extradata) { | |||||
| st->codec->extradata_size = 0; | |||||
| res = AVERROR(ENOMEM); | |||||
| res = ff_bprint_to_extradata(st->codec, &hdr_buf); | |||||
| if (res < 0) | |||||
| goto end; | goto end; | ||||
| } | |||||
| ff_subtitles_queue_finalize(&sami->q); | ff_subtitles_queue_finalize(&sami->q); | ||||
| @@ -27,6 +27,7 @@ | |||||
| #include "avformat.h" | #include "avformat.h" | ||||
| #include "internal.h" | #include "internal.h" | ||||
| #include "subtitles.h" | #include "subtitles.h" | ||||
| #include "libavcodec/internal.h" | |||||
| #include "libavutil/avstring.h" | #include "libavutil/avstring.h" | ||||
| #include "libavutil/bprint.h" | #include "libavutil/bprint.h" | ||||
| #include "libavutil/intreadwrite.h" | #include "libavutil/intreadwrite.h" | ||||
| @@ -99,12 +100,9 @@ static int subviewer_read_header(AVFormatContext *s) | |||||
| av_bprintf(&header, "%s", line); | av_bprintf(&header, "%s", line); | ||||
| if (!strncmp(line, "[END INFORMATION]", 17) || !strncmp(line, "[SUBTITLE]", 10)) { | if (!strncmp(line, "[END INFORMATION]", 17) || !strncmp(line, "[SUBTITLE]", 10)) { | ||||
| /* end of header */ | /* end of header */ | ||||
| av_bprint_finalize(&header, (char **)&st->codec->extradata); | |||||
| if (!st->codec->extradata) { | |||||
| res = AVERROR(ENOMEM); | |||||
| res = ff_bprint_to_extradata(st->codec, &header); | |||||
| if (res < 0) | |||||
| goto end; | goto end; | ||||
| } | |||||
| st->codec->extradata_size = header.len + 1; | |||||
| } else if (strncmp(line, "[INFORMATION]", 13)) { | } else if (strncmp(line, "[INFORMATION]", 13)) { | ||||
| /* assume file metadata at this point */ | /* assume file metadata at this point */ | ||||
| int i, j = 0; | int i, j = 0; | ||||