PR #25471 opened by Kilian (lusoris)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25471
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25471.patch

This patch addresses GCC 14.4.0 and 16.2.1 -Wformat-truncation diagnostics for 
output paths in tools/ismindex.c.

What the patch does:

- `tools/ismindex: allocate output paths and report manifest errors`: 
dynamically allocates fragment and manifest paths and the optional 
output-prefix slash, handles empty prefixes, propagates manifest open, write 
and close errors to main and frees allocated paths on exit.

Behaviour change: paths use heap allocations and manifest errors produce 
nonzero exits; successful output with previously fitting names is unchanged.

Base: FFmpeg master 46f23be8b1.

Testing:

- GCC 14.4.0 (`--enable-gpl --enable-vulkan`) and GCC 16.2.1 (`--enable-gpl 
--enable-vulkan --enable-vaapi --enable-libdrm --enable-nvenc`), targets all, 
alltools, examples, testprogs and checkasm: master 46f23be8b1 shows 8 
-Wformat-truncation warnings in tools/ismindex.c with each compiler; with this 
patch there are none and no new ones.
- FATE has no test for tools/ismindex.

Split out of #25111 so that each part reaches the reviewers for its area.



>From 2b85a9e481c4f2e9fa0a26e19ff65f46cdf39b18 Mon Sep 17 00:00:00 2001
From: lusoris <[email protected]>
Date: Thu, 15 Oct 2026 22:06:37 +0200
Subject: [PATCH] tools/ismindex: allocate output paths and report manifest
 errors

GCC 14.4.0 and 16.2.1 report -Wformat-truncation for output paths.
Fixed-size buffers can silently shorten fragment and manifest names.
Allocate paths and the optional output-prefix slash dynamically,
guarding empty prefixes. Return manifest open, write and close errors to
main and free allocated paths on exit. Successful output with previously
fitting names is unchanged.

Signed-off-by: lusoris <[email protected]>
---
 tools/ismindex.c | 139 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 102 insertions(+), 37 deletions(-)

diff --git a/tools/ismindex.c b/tools/ismindex.c
index 4fd9a781d03..4bf9172028f 100644
--- a/tools/ismindex.c
+++ b/tools/ismindex.c
@@ -50,6 +50,7 @@
 #include "libavformat/avformat.h"
 #include "libavformat/isom.h"
 #include "libavformat/os_support.h"
+#include "libavutil/avstring.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/mem.h"
@@ -175,12 +176,16 @@ static int write_fragments(struct Tracks *tracks, int 
start_index,
                            AVIOContext *in, const char *basename,
                            int split, int ismf, const char* output_prefix)
 {
-    char dirname[2048], filename[2048], idxname[2048];
+    char *dirname = NULL, *filename = NULL, *idxname = NULL;
     int i, j, ret = 0, fragment_ret;
     FILE* out = NULL;
 
     if (ismf) {
-        snprintf(idxname, sizeof(idxname), "%s%s.ismf", output_prefix, 
basename);
+        idxname = av_asprintf("%s%s.ismf", output_prefix, basename);
+        if (!idxname) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
         out = fopen(idxname, "w");
         if (!out) {
             ret = AVERROR(errno);
@@ -191,7 +196,13 @@ static int write_fragments(struct Tracks *tracks, int 
start_index,
     for (i = start_index; i < tracks->nb_tracks; i++) {
         struct Track *track = tracks->tracks[i];
         const char *type    = track->is_video ? "video" : "audio";
-        snprintf(dirname, sizeof(dirname), "%sQualityLevels(%d)", 
output_prefix, track->bitrate);
+        av_freep(&dirname);
+        dirname = av_asprintf("%sQualityLevels(%d)", output_prefix,
+                              track->bitrate);
+        if (!dirname) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
         if (split) {
             if (mkdir(dirname, 0777) == -1 && errno != EEXIST) {
                 ret = AVERROR(errno);
@@ -200,8 +211,13 @@ static int write_fragments(struct Tracks *tracks, int 
start_index,
             }
         }
         for (j = 0; j < track->chunks; j++) {
-            snprintf(filename, sizeof(filename), "%s/Fragments(%s=%"PRId64")",
-                     dirname, type, track->offsets[j].time);
+            av_freep(&filename);
+            filename = av_asprintf("%s/Fragments(%s=%"PRId64")",
+                                   dirname, type, track->offsets[j].time);
+            if (!filename) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
             avio_seek(in, track->offsets[j].offset, SEEK_SET);
             if (ismf)
                 fprintf(out, "%s %"PRId64, filename, avio_tell(in));
@@ -221,6 +237,9 @@ static int write_fragments(struct Tracks *tracks, int 
start_index,
 fail:
     if (out)
         fclose(out);
+    av_free(filename);
+    av_free(dirname);
+    av_free(idxname);
     return ret;
 }
 
@@ -611,20 +630,26 @@ fail:
     return err;
 }
 
-static void output_server_manifest(struct Tracks *tracks, const char *basename,
-                                   const char *output_prefix,
-                                   const char *path_prefix,
-                                   const char *ismc_prefix)
+static int output_server_manifest(struct Tracks *tracks, const char *basename,
+                                  const char *output_prefix,
+                                  const char *path_prefix,
+                                  const char *ismc_prefix)
 {
-    char filename[1000];
+    char *filename;
     FILE *out;
-    int i;
+    int i, ret = 0;
 
-    snprintf(filename, sizeof(filename), "%s%s.ism", output_prefix, basename);
+    filename = av_asprintf("%s%s.ism", output_prefix, basename);
+    if (!filename) {
+        fprintf(stderr, "Unable to allocate server manifest filename\n");
+        return AVERROR(ENOMEM);
+    }
     out = fopen(filename, "w");
     if (!out) {
+        ret = AVERROR(errno);
         perror(filename);
-        return;
+        av_free(filename);
+        return ret;
     }
     fprintf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
     fprintf(out, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\";>\n");
@@ -646,7 +671,14 @@ static void output_server_manifest(struct Tracks *tracks, 
const char *basename,
     fprintf(out, "\t\t</switch>\n");
     fprintf(out, "\t</body>\n");
     fprintf(out, "</smil>\n");
-    fclose(out);
+    if (ferror(out))
+        ret = AVERROR(EIO);
+    if (fclose(out) && ret >= 0)
+        ret = AVERROR(errno ? errno : EIO);
+    if (ret < 0)
+        fprintf(stderr, "Unable to write %s: %s\n", filename, av_err2str(ret));
+    av_free(filename);
+    return ret;
 }
 
 static void print_track_chunks(FILE *out, struct Tracks *tracks, int main,
@@ -684,21 +716,27 @@ static void print_track_chunks(FILE *out, struct Tracks 
*tracks, int main,
     }
 }
 
-static void output_client_manifest(struct Tracks *tracks, const char *basename,
-                                   const char *output_prefix, int split)
+static int output_client_manifest(struct Tracks *tracks, const char *basename,
+                                  const char *output_prefix, int split)
 {
-    char filename[1000];
+    char *filename;
     FILE *out;
-    int i, j;
+    int i, j, ret = 0;
 
     if (split)
-        snprintf(filename, sizeof(filename), "%sManifest", output_prefix);
+        filename = av_asprintf("%sManifest", output_prefix);
     else
-        snprintf(filename, sizeof(filename), "%s%s.ismc", output_prefix, 
basename);
+        filename = av_asprintf("%s%s.ismc", output_prefix, basename);
+    if (!filename) {
+        fprintf(stderr, "Unable to allocate client manifest filename\n");
+        return AVERROR(ENOMEM);
+    }
     out = fopen(filename, "w");
     if (!out) {
+        ret = AVERROR(errno);
         perror(filename);
-        return;
+        av_free(filename);
+        return ret;
     }
     fprintf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
     fprintf(out, "<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" "
@@ -764,7 +802,14 @@ static void output_client_manifest(struct Tracks *tracks, 
const char *basename,
         fprintf(out, "\t</StreamIndex>\n");
     }
     fprintf(out, "</SmoothStreamingMedia>\n");
-    fclose(out);
+    if (ferror(out))
+        ret = AVERROR(EIO);
+    if (fclose(out) && ret >= 0)
+        ret = AVERROR(errno ? errno : EIO);
+    if (ret < 0)
+        fprintf(stderr, "Unable to write %s: %s\n", filename, av_err2str(ret));
+    av_free(filename);
+    return ret;
 }
 
 static void clean_tracks(struct Tracks *tracks)
@@ -784,8 +829,8 @@ int main(int argc, char **argv)
     const char *basename = NULL;
     const char *path_prefix = "", *ismc_prefix = "";
     const char *output_prefix = "";
-    char output_prefix_buf[2048];
-    int split = 0, ismf = 0, i;
+    char *output_prefix_buf = NULL;
+    int split = 0, ismf = 0, i, ret = 0;
     struct Tracks tracks = { 0, .video_track = -1, .audio_track = -1 };
 
     for (i = 1; i < argc; i++) {
@@ -799,11 +844,19 @@ int main(int argc, char **argv)
             ismc_prefix = argv[i + 1];
             i++;
         } else if (!strcmp(argv[i], "-output")) {
+            size_t output_prefix_len;
+
+            av_freep(&output_prefix_buf);
             output_prefix = argv[i + 1];
             i++;
-            if (output_prefix[strlen(output_prefix) - 1] != '/') {
-                snprintf(output_prefix_buf, sizeof(output_prefix_buf),
-                         "%s/", output_prefix);
+            output_prefix_len = strlen(output_prefix);
+            if (output_prefix_len && output_prefix[output_prefix_len - 1] != 
'/') {
+                output_prefix_buf = av_asprintf("%s/", output_prefix);
+                if (!output_prefix_buf) {
+                    fprintf(stderr, "Unable to allocate output path prefix\n");
+                    ret = 1;
+                    goto end;
+                }
                 output_prefix = output_prefix_buf;
             }
         } else if (!strcmp(argv[i], "-split")) {
@@ -811,24 +864,36 @@ int main(int argc, char **argv)
         } else if (!strcmp(argv[i], "-ismf")) {
             ismf = 1;
         } else if (argv[i][0] == '-') {
-            return usage(argv[0], 1);
+            ret = usage(argv[0], 1);
+            goto end;
         } else {
             if (!basename)
                 ismf = 0;
             if (handle_file(&tracks, argv[i], split, ismf,
-                            basename, output_prefix))
-                return 1;
+                            basename, output_prefix)) {
+                ret = 1;
+                goto end;
+            }
         }
     }
-    if (!tracks.nb_tracks || (!basename && !split))
-        return usage(argv[0], 1);
+    if (!tracks.nb_tracks || (!basename && !split)) {
+        ret = usage(argv[0], 1);
+        goto end;
+    }
 
-    if (!split)
-        output_server_manifest(&tracks, basename, output_prefix,
-                               path_prefix, ismc_prefix);
-    output_client_manifest(&tracks, basename, output_prefix, split);
+    if (!split && output_server_manifest(&tracks, basename, output_prefix,
+                                         path_prefix, ismc_prefix) < 0) {
+        ret = 1;
+        goto end;
+    }
+    if (output_client_manifest(&tracks, basename, output_prefix, split) < 0) {
+        ret = 1;
+        goto end;
+    }
 
+end:
     clean_tracks(&tracks);
+    av_free(output_prefix_buf);
 
-    return 0;
+    return ret;
 }
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to