summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2021-10-01 11:57:34 +0200
committerAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2021-10-02 17:14:20 +0200
commit60e12318bb9372b3053703f2a3b849270b9d2fe5 (patch)
tree9e6f2b9cf240a11c6ba5075344af06e2598570bd
parent03a0dbaff34222970960f0df9f92b818005ee03f (diff)
avformat/sccdec: Don't use uninitialized data, fix crash, simplify logic
Up until now, the scc demuxer not only read the line that it intends to process, but also the next line, in order to be able to calculate the duration of the current line. This approach leads to unnecessary complexity and also to bugs: For the last line, the timing of the next subtitle is not only logically indeterminate, but also uninitialized and the same applies to the duration of the last packet derived from it.* Worse yet, in case of e.g. an empty file, it is not only the duration that is uninitialized, but the whole timing as well as the line buffer itself.** The latter is used in av_strtok(), which could lead to crashes. Furthermore, the current code always outputs at least one packet, even for empty files. This commit fixes all of this: It stops using two lines at a time; instead only the current line is dealt with and in case there is a packet after that, the duration of the last packet is fixed up after having already parsed it; consequently the duration of the last packet is left in its default state (meaning "unknown/up until the next subtitle"). If no further line could be read, processing is stopped; in particular, no packet is output for an empty file. *: Due to stack reuse it seems to be zero quite often; for the same reason Valgrind does not report any errors for a normal input file. **: While ff_subtitles_read_line() claims to always zero-terminate the buffer like snprintf(), it doesn't do so if it didn't read anything. And even if it did, it would not necessarily help here: The current code jumps over 12 bytes that it deems to have read even when it hasn't. Reviewed-by: Paul B Mahol <onemda@gmail.com> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
-rw-r--r--libavformat/sccdec.c54
1 files changed, 15 insertions, 39 deletions
diff --git a/libavformat/sccdec.c b/libavformat/sccdec.c
index e95fd881a3..61b6acf637 100644
--- a/libavformat/sccdec.c
+++ b/libavformat/sccdec.c
@@ -63,8 +63,7 @@ static int scc_read_header(AVFormatContext *s)
{
SCCContext *scc = s->priv_data;
AVStream *st = avformat_new_stream(s, NULL);
- char line2[4096], line[4096];
- int64_t pos, ts, next_ts = AV_NOPTS_VALUE;
+ AVPacket *sub = NULL;
ptrdiff_t len;
uint8_t out[4096];
FFTextReader tr;
@@ -77,47 +76,26 @@ static int scc_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
st->codecpar->codec_id = AV_CODEC_ID_EIA_608;
- while (!ff_text_eof(&tr) || next_ts == AV_NOPTS_VALUE || line2[0]) {
+ while (1) {
char *saveptr = NULL, *lline;
int hh, mm, ss, fs, i;
- AVPacket *sub;
+ char line[4096];
+ int64_t pos, ts;
- if (next_ts == AV_NOPTS_VALUE) {
- while (!ff_text_eof(&tr)) {
- len = ff_subtitles_read_line(&tr, line, sizeof(line));
- if (len <= 13)
- continue;
+ len = ff_subtitles_read_line(&tr, line, sizeof(line));
+ if (len <= 13) {
+ if (ff_text_eof(&tr))
+ break;
+ continue;
+ }
if (!strncmp(line, "Scenarist_SCC V1.0", 18))
continue;
- if (av_sscanf(line, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) == 4)
- break;
- }
-
- ts = (hh * 3600LL + mm * 60LL + ss) * 1000LL + fs * 33LL;
-
- while (!ff_text_eof(&tr)) {
- len = ff_subtitles_read_line(&tr, line2, sizeof(line2));
- if (len <= 13)
- continue;
-
- if (av_sscanf(line2, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) == 4)
- break;
- }
- } else {
- memmove(line, line2, sizeof(line));
- line2[0] = 0;
-
- while (!ff_text_eof(&tr)) {
- len = ff_subtitles_read_line(&tr, line2, sizeof(line2));
- if (len <= 13)
- continue;
-
- if (av_sscanf(line2, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) == 4)
- break;
- }
- }
+ if (av_sscanf(line, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) != 4)
+ continue;
- next_ts = (hh * 3600LL + mm * 60LL + ss) * 1000LL + fs * 33LL;
+ ts = (hh * 3600LL + mm * 60LL + ss) * 1000LL + fs * 33LL;
+ if (sub)
+ sub->duration = ts - sub->pts;
pos = ff_text_pos(&tr);
lline = (char *)&line;
@@ -168,8 +146,6 @@ static int scc_read_header(AVFormatContext *s)
sub->pos = pos;
sub->pts = ts;
- sub->duration = next_ts - ts;
- ts = next_ts;
}
ff_subtitles_queue_finalize(s, &scc->q);