fix: memory leaks and invalid CSS in WebVTT encoder (#2164)

* fix: memory leaks and invalid CSS in WebVTT encoder

- Remove 6 unnecessary strdup() calls on string literals in
  write_cc_buffer_as_webvtt() — literals are passed directly to
  write_wrapped() which takes void*, no heap allocation needed.
  This runs in a per-character inner loop and leaked on every
  styled subtitle in a broadcast.
- Fix invalid CSS: rgba(0, 256, 0, 0.5) -> rgba(0, 255, 0, 0.5)
  CSS color channels are 0-255; 256 is out of range.
- Fix missing free(unescaped) on write-error path in
  write_stringz_as_webvtt() — matched the existing pattern on
  the adjacent error path which correctly freed both el and unescaped.

Fixes #2154

* fix: move WebVTT changelog entry to unreleased 0.96.7 section
This commit is contained in:
Varad Raj Agrawal
2026-03-07 14:07:12 +05:30
committed by GitHub
parent b2c1babf90
commit 90128d8c28
2 changed files with 9 additions and 7 deletions

View File

@@ -1,5 +1,6 @@
0.96.7 (unreleased)
-------------------
- Fix: Remove strdup() memory leaks in WebVTT styling encoder, fix invalid CSS rgba(0,256,0) green value, fix missing free(unescaped) on write-error path (#2154)
- Fix: Prevent crash in Rust timing module when logging out-of-range PTS/FTS timestamps from malformed streams.
0.96.6 (2026-02-19)

View File

@@ -94,7 +94,7 @@ static const char *webvtt_inline_css = "\r\nSTYLE\n\n"
" background-color: rgba(255, 255, 255, 0.5);\n"
"}\n"
"::cue(c.bg_green.bg_semi-transparent) {\n"
" background-color: rgba(0, 256, 0, 0.5);\n"
" background-color: rgba(0, 255, 0, 0.5);\n"
"}\n"
"::cue(c.bg_blue.bg_semi-transparent) {\n"
" background-color: rgba(0, 0, 255, 0.5);\n"
@@ -189,6 +189,7 @@ int write_stringz_as_webvtt(char *string, struct encoder_ctx *context, LLONG ms_
if (written != context->encoded_crlf_length)
{
free(el);
free(unescaped);
return -1;
}
begin += strlen((const char *)begin) + 1;
@@ -502,16 +503,16 @@ int write_cc_buffer_as_webvtt(struct eia608_screen *data, struct encoder_ctx *co
if (open_font != FONT_REGULAR)
{
if (open_font & FONT_ITALICS)
write_wrapped(context->out->fh, strdup("<i>"), 3);
write_wrapped(context->out->fh, "<i>", 3);
if (open_font & FONT_UNDERLINED)
write_wrapped(context->out->fh, strdup("<u>"), 3);
write_wrapped(context->out->fh, "<u>", 3);
}
// opening events for colors
int open_color = color_events[j] & 0xFF; // Last 16 bytes
if (open_color != COL_WHITE)
{
write_wrapped(context->out->fh, strdup("<c."), 3);
write_wrapped(context->out->fh, "<c.", 3);
write_wrapped(context->out->fh, color_text[open_color][0], strlen(color_text[open_color][0]));
write_wrapped(context->out->fh, ">", 1);
}
@@ -532,7 +533,7 @@ int write_cc_buffer_as_webvtt(struct eia608_screen *data, struct encoder_ctx *co
int close_color = color_events[j] >> 16; // First 16 bytes
if (close_color != COL_WHITE)
{
write_wrapped(context->out->fh, strdup("</c>"), 4);
write_wrapped(context->out->fh, "</c>", 4);
}
// closing events for fonts
@@ -540,9 +541,9 @@ int write_cc_buffer_as_webvtt(struct eia608_screen *data, struct encoder_ctx *co
if (close_font != FONT_REGULAR)
{
if (close_font & FONT_UNDERLINED)
write_wrapped(context->out->fh, strdup("</u>"), 4);
write_wrapped(context->out->fh, "</u>", 4);
if (close_font & FONT_ITALICS)
write_wrapped(context->out->fh, strdup("</i>"), 4);
write_wrapped(context->out->fh, "</i>", 4);
}
}
}