From ab9155c7baabc9da30f44e87fc358907b4c5186b Mon Sep 17 00:00:00 2001 From: pranayr710 Date: Wed, 9 Sep 2026 19:24:05 +0530 Subject: [PATCH] [FIX] webvtt: don't leak basefilename or skip the header flag on CSS failure write_webvtt_header() is called once per cue and guards re-entry with context->wrote_webvtt_header, which it sets on its last line. The --webvtt-create-css path returned early when the .css file could not be created, bypassing that assignment, so the whole header block was written again before every subsequent cue. The existing trailing comment ("Do it even if couldn't write the header, because it won't be possible anyway") already stated the intent. Replace the early return with an else branch so the flag is always reached, and move free(css_file_name) after it so both paths release it. basefilename came from get_basename(), which allocates, but was never freed on any path. Every other caller in the tree frees it. On its own that is one small leak per output file; together with the early return it became a leak per cue. Refs #2338 --- src/lib_ccx/ccx_encoders_webvtt.c | 32 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/lib_ccx/ccx_encoders_webvtt.c b/src/lib_ccx/ccx_encoders_webvtt.c index bcb86ad16..583f095d5 100644 --- a/src/lib_ccx/ccx_encoders_webvtt.c +++ b/src/lib_ccx/ccx_encoders_webvtt.c @@ -249,31 +249,37 @@ void write_webvtt_header(struct encoder_ctx *context) char *css_file_name = (char *)malloc(css_file_name_size); if (!css_file_name) { + free(basefilename); fatal(EXIT_NOT_ENOUGH_MEMORY, "In write_webvtt_header: Out of memory allocating css_file_name."); } snprintf(css_file_name, css_file_name_size, "%s.css", basefilename); + free(basefilename); FILE *f = fopen(css_file_name, "wb"); if (f == NULL) { + // Carry on without the stylesheet. Returning here would leave + // wrote_webvtt_header unset, so the header block would be written + // again before every later cue. mprint("Warning: Error creating the file %s\n", css_file_name); - free(css_file_name); - return; } - fprintf(f, "%s", webvtt_inline_css); - fclose(f); - - size_t outline_css_file_size = strlen(css_file_name) + strlen(webvtt_outline_css) + 1; - char *outline_css_file = (char *)malloc(outline_css_file_size); - if (!outline_css_file) + else { - free(css_file_name); - fatal(EXIT_NOT_ENOUGH_MEMORY, "In write_webvtt_header: Out of memory allocating outline_css_file."); + fprintf(f, "%s", webvtt_inline_css); + fclose(f); + + size_t outline_css_file_size = strlen(css_file_name) + strlen(webvtt_outline_css) + 1; + char *outline_css_file = (char *)malloc(outline_css_file_size); + if (!outline_css_file) + { + free(css_file_name); + fatal(EXIT_NOT_ENOUGH_MEMORY, "In write_webvtt_header: Out of memory allocating outline_css_file."); + } + snprintf(outline_css_file, outline_css_file_size, webvtt_outline_css, css_file_name); + write_wrapped(context->out->fh, outline_css_file, strlen(outline_css_file)); + free(outline_css_file); } - snprintf(outline_css_file, outline_css_file_size, webvtt_outline_css, css_file_name); - write_wrapped(context->out->fh, outline_css_file, strlen(outline_css_file)); free(css_file_name); - free(outline_css_file); } else if (ccx_options.use_webvtt_styling) {