From 87779a8c85eec0b71703ed3090a3949761396a15 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Wed, 15 Apr 2026 10:10:15 -0400 Subject: Replace sprintf with snprintf * A few strcpy and strcat changes as well --- src/cli/stasis_indexer/args.c | 2 +- src/cli/stasis_indexer/junitxml_report.c | 4 ++-- src/cli/stasis_indexer/readmes.c | 10 +++++----- src/cli/stasis_indexer/stasis_indexer_main.c | 12 ++++++------ src/cli/stasis_indexer/website.c | 10 +++++----- 5 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src/cli/stasis_indexer') diff --git a/src/cli/stasis_indexer/args.c b/src/cli/stasis_indexer/args.c index 2d92ab0..8c9d3fe 100644 --- a/src/cli/stasis_indexer/args.c +++ b/src/cli/stasis_indexer/args.c @@ -30,7 +30,7 @@ void usage(char *name) { for (int i = 0; i < maxopts - 1; i++) { char line[255] = {0}; - sprintf(line, " --%s -%c %-20s", long_options[i].name, long_options[i].val, long_options_help[i]); + snprintf(line, sizeof(line), " --%s -%c %-20s", long_options[i].name, long_options[i].val, long_options_help[i]); puts(line); } diff --git a/src/cli/stasis_indexer/junitxml_report.c b/src/cli/stasis_indexer/junitxml_report.c index 21cf729..d30ee09 100644 --- a/src/cli/stasis_indexer/junitxml_report.c +++ b/src/cli/stasis_indexer/junitxml_report.c @@ -98,7 +98,7 @@ static int write_report_output(struct Delivery *ctx, FILE *destfp, const char *x int indexer_junitxml_report(struct Delivery **ctx, const size_t nelem) { char indexfile[PATH_MAX] = {0}; - sprintf(indexfile, "%s/README.md", (*ctx)->storage.results_dir); + snprintf(indexfile, sizeof(indexfile), "%s/README.md", (*ctx)->storage.results_dir); struct StrList *file_listing = listdir((*ctx)->storage.results_dir); if (!file_listing) { @@ -117,7 +117,7 @@ int indexer_junitxml_report(struct Delivery **ctx, const size_t nelem) { int current_rc = (*ctx)->meta.rc; for (size_t d = 0; d < nelem; d++) { char pattern[PATH_MAX] = {0}; - snprintf(pattern, sizeof(pattern) - 1, "*%s*", ctx[d]->info.release_name); + snprintf(pattern, sizeof(pattern), "*%s*", ctx[d]->info.release_name); // if the result directory contains tests for this release name, print them if (!is_file_in_listing(file_listing, pattern)) { diff --git a/src/cli/stasis_indexer/readmes.c b/src/cli/stasis_indexer/readmes.c index edc6312..91c936f 100644 --- a/src/cli/stasis_indexer/readmes.c +++ b/src/cli/stasis_indexer/readmes.c @@ -12,7 +12,7 @@ int indexer_readmes(struct Delivery **ctx, const size_t nelem) { } char indexfile[PATH_MAX] = {0}; - sprintf(indexfile, "%s/README.md", (*ctx)->storage.delivery_dir); + snprintf(indexfile, sizeof(indexfile), "%s/README.md", (*ctx)->storage.delivery_dir); FILE *indexfp = fopen(indexfile, "w+"); if (!indexfp) { @@ -52,10 +52,10 @@ int indexer_readmes(struct Delivery **ctx, const size_t nelem) { if (!latest_deliveries[i]->meta.name) { continue; } - sprintf(link_name, "latest-py%s-%s-%s.yml", latest_deliveries[i]->meta.python_compact, latest_deliveries[i]->system.platform[DELIVERY_PLATFORM_RELEASE], latest_deliveries[i]->system.arch); - sprintf(readme_name, "README-py%s-%s-%s.md", latest_deliveries[i]->meta.python_compact, latest_deliveries[i]->system.platform[DELIVERY_PLATFORM_RELEASE], latest_deliveries[i]->system.arch); - sprintf(conf_name, "%s.ini", latest_deliveries[i]->info.release_name); - sprintf(conf_name_relative, "../config/%s.ini", latest_deliveries[i]->info.release_name); + snprintf(link_name, sizeof(link_name), "latest-py%s-%s-%s.yml", latest_deliveries[i]->meta.python_compact, latest_deliveries[i]->system.platform[DELIVERY_PLATFORM_RELEASE], latest_deliveries[i]->system.arch); + snprintf(readme_name, sizeof(readme_name), "README-py%s-%s-%s.md", latest_deliveries[i]->meta.python_compact, latest_deliveries[i]->system.platform[DELIVERY_PLATFORM_RELEASE], latest_deliveries[i]->system.arch); + snprintf(conf_name, sizeof(conf_name), "%s.ini", latest_deliveries[i]->info.release_name); + snprintf(conf_name_relative, sizeof(conf_name_relative), "../config/%s.ini", latest_deliveries[i]->info.release_name); if (strstr(link_name, platform) && strstr(link_name, arch)) { fprintf(indexfp, "- Python %s\n", latest_deliveries[i]->meta.python); fprintf(indexfp, " - Info: [README](%s)\n", readme_name); diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c index 840e897..5f7ded4 100644 --- a/src/cli/stasis_indexer/stasis_indexer_main.c +++ b/src/cli/stasis_indexer/stasis_indexer_main.c @@ -80,11 +80,11 @@ int indexer_symlinks(struct Delivery **ctx, const size_t nelem) { if (!data[i]->meta.name) { continue; } - sprintf(link_name_spec, "latest-py%s-%s-%s.yml", data[i]->meta.python_compact, data[i]->system.platform[DELIVERY_PLATFORM_RELEASE], data[i]->system.arch); - sprintf(file_name_spec, "%s.yml", data[i]->info.release_name); + snprintf(link_name_spec, sizeof(link_name_spec), "latest-py%s-%s-%s.yml", data[i]->meta.python_compact, data[i]->system.platform[DELIVERY_PLATFORM_RELEASE], data[i]->system.arch); + snprintf(file_name_spec, sizeof(file_name_spec), "%s.yml", data[i]->info.release_name); - sprintf(link_name_readme, "README-py%s-%s-%s.md", data[i]->meta.python_compact, data[i]->system.platform[DELIVERY_PLATFORM_RELEASE], data[i]->system.arch); - sprintf(file_name_readme, "README-%s.md", data[i]->info.release_name); + snprintf(link_name_readme, sizeof(link_name_readme), "README-py%s-%s-%s.md", data[i]->meta.python_compact, data[i]->system.platform[DELIVERY_PLATFORM_RELEASE], data[i]->system.arch); + snprintf(file_name_readme, sizeof(file_name_readme), "README-%s.md", data[i]->info.release_name); if (!access(link_name_spec, F_OK)) { if (unlink(link_name_spec)) { @@ -151,7 +151,7 @@ void indexer_init_dirs(struct Delivery *ctx, const char *workdir) { char newpath[PATH_MAX] = {0}; if (getenv("PATH")) { - sprintf(newpath, "%s/bin:%s", ctx->storage.tools_dir, getenv("PATH")); + snprintf(newpath, sizeof(newpath), "%s/bin:%s", ctx->storage.tools_dir, getenv("PATH")); setenv("PATH", newpath, 1); } else { SYSERROR("%s", "environment variable PATH is undefined. Unable to continue."); @@ -411,7 +411,7 @@ int main(const int argc, char *argv[]) { msg(STASIS_MSG_L1, "Copying indexed delivery to '%s'\n", destdir); char cmd[PATH_MAX] = {0}; - sprintf(cmd, "rsync -ah%s --delete --exclude 'tmp/' --exclude 'tools/' '%s/' '%s/'", globals.verbose ? "v" : "q", workdir, destdir); + snprintf(cmd, sizeof(cmd), "rsync -ah%s --delete --exclude 'tmp/' --exclude 'tools/' '%s/' '%s/'", globals.verbose ? "v" : "q", workdir, destdir); guard_free(destdir); if (globals.verbose) { diff --git a/src/cli/stasis_indexer/website.c b/src/cli/stasis_indexer/website.c index 966391e..e758d47 100644 --- a/src/cli/stasis_indexer/website.c +++ b/src/cli/stasis_indexer/website.c @@ -8,7 +8,7 @@ int indexer_make_website(struct Delivery **ctx) { return -1; } - sprintf(css_filename, "%s/%s", globals.sysconfdir, "stasis_pandoc.css"); + snprintf(css_filename, PATH_MAX, "%s/%s", globals.sysconfdir, "stasis_pandoc.css"); const int have_css = access(css_filename, F_OK | R_OK) == 0; struct StrList *dirs = strlist_init(); @@ -29,13 +29,13 @@ int indexer_make_website(struct Delivery **ctx) { char *filename = path_basename(strlist_item(inputs, x)); char fullpath_src[PATH_MAX] = {0}; char fullpath_dest[PATH_MAX] = {0}; - sprintf(fullpath_src, "%s/%s", root, filename); + snprintf(fullpath_src, sizeof(fullpath_src), "%s/%s", root, filename); if (access(fullpath_src, F_OK)) { continue; } // Replace *.md extension with *.html. - strcpy(fullpath_dest, fullpath_src); + strncpy(fullpath_dest, fullpath_src, sizeof(fullpath_dest) - 1); gen_file_extension_str(fullpath_dest, ".html"); // Convert markdown to html @@ -52,8 +52,8 @@ int indexer_make_website(struct Delivery **ctx) { if (!strcmp(filename, "README.md")) { char link_from[PATH_MAX] = {0}; char link_dest[PATH_MAX] = {0}; - strcpy(link_from, "README.html"); - sprintf(link_dest, "%s/%s", root, "index.html"); + strncpy(link_from, "README.html", sizeof(link_from) - 1); + snprintf(link_dest, sizeof(link_dest), "%s/%s", root, "index.html"); if (symlink(link_from, link_dest)) { SYSERROR("Warning: symlink(%s, %s) failed: %s", link_from, link_dest, strerror(errno)); } -- cgit From dc6b871b419159097c272fe21cdef6acece40a99 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 16 Apr 2026 11:52:11 -0400 Subject: Convert more strcat and strcpy to strn variants --- src/cli/stasis_indexer/helpers.c | 38 ++++++++++++++-------------- src/cli/stasis_indexer/stasis_indexer_main.c | 18 ++++++------- src/cli/stasis_indexer/website.c | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) (limited to 'src/cli/stasis_indexer') diff --git a/src/cli/stasis_indexer/helpers.c b/src/cli/stasis_indexer/helpers.c index 6dc653d..27608d3 100644 --- a/src/cli/stasis_indexer/helpers.c +++ b/src/cli/stasis_indexer/helpers.c @@ -96,44 +96,44 @@ int pandoc_exec(const char *in_file, const char *out_file, const char *css_file, if (!get_pandoc_version(&pandoc_version)) { // < 2.19 if (pandoc_version < 0x02130000) { - strcat(pandoc_versioned_args, "--self-contained "); + strncat(pandoc_versioned_args, "--self-contained ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1); } else { // >= 2.19 - strcat(pandoc_versioned_args, "--embed-resources "); + strncat(pandoc_versioned_args, "--embed-resources ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1); } // >= 1.15.0.4 if (pandoc_version >= 0x010f0004) { - strcat(pandoc_versioned_args, "--standalone "); + strncat(pandoc_versioned_args, "--standalone ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1); } // >= 1.10.0.1 if (pandoc_version >= 0x010a0001) { - strcat(pandoc_versioned_args, "-f gfm+autolink_bare_uris "); + strncat(pandoc_versioned_args, "-f gfm+autolink_bare_uris ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1); } // > 3.1.9 if (pandoc_version > 0x03010900) { - strcat(pandoc_versioned_args, "-f gfm+alerts "); + strncat(pandoc_versioned_args, "-f gfm+alerts ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1); } } // Converts a markdown file to html char cmd[STASIS_BUFSIZ] = {0}; - strcpy(cmd, "pandoc "); - strcat(cmd, pandoc_versioned_args); + strncpy(cmd, "pandoc ", sizeof(cmd)); + strncat(cmd, pandoc_versioned_args, sizeof(cmd) - strlen(cmd) - 1); if (css_file && strlen(css_file)) { - strcat(cmd, "--css "); - strcat(cmd, css_file); + strncat(cmd, "--css ", sizeof(cmd) - strlen(cmd) - 1); + strncat(cmd, css_file, sizeof(cmd) - strlen(cmd) - 1); } - strcat(cmd, " "); - strcat(cmd, "--metadata title=\""); - strcat(cmd, title); - strcat(cmd, "\" "); - strcat(cmd, "-o "); - strcat(cmd, out_file); - strcat(cmd, " "); - strcat(cmd, in_file); + strncat(cmd, " ", sizeof(cmd) - strlen(cmd) - 1); + strncat(cmd, "--metadata title=\"", sizeof(cmd) - strlen(cmd) - 1); + strncat(cmd, title, sizeof(cmd) - strlen(cmd) - 1); + strncat(cmd, "\" ", sizeof(cmd) - strlen(cmd) - 1); + strncat(cmd, "-o ", sizeof(cmd) - strlen(cmd) - 1); + strncat(cmd, out_file, sizeof(cmd) - strlen(cmd) - 1); + strncat(cmd, " ", sizeof(cmd) - strlen(cmd) - 1); + strncat(cmd, in_file, sizeof(cmd) - strlen(cmd) - 1); if (globals.verbose) { puts(cmd); @@ -377,8 +377,8 @@ int write_manifest(const char *path, char **exclude_path, FILE *fp) { } char filepath[PATH_MAX] = {0}; strncpy(filepath, path, PATH_MAX - 1); - strcat(filepath, "/"); - strcat(filepath, rec->d_name); + strncat(filepath, "/", sizeof(filepath) - strlen(filepath) - 1); + strncat(filepath, rec->d_name, sizeof(filepath) - strlen(filepath) - 1); if (rec->d_type == DT_DIR) { write_manifest(filepath, exclude_path, fp); continue; diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c index 5f7ded4..63fb45c 100644 --- a/src/cli/stasis_indexer/stasis_indexer_main.c +++ b/src/cli/stasis_indexer/stasis_indexer_main.c @@ -13,9 +13,9 @@ int indexer_combine_rootdirs(const char *dest, char **rootdirs, const size_t roo char destdir_with_output[PATH_MAX] = {0}; char *destdir = destdir_bare; - strcpy(destdir_bare, dest); - strcpy(destdir_with_output, dest); - strcat(destdir_with_output, "/output"); + strncpy(destdir_bare, dest, sizeof(destdir_bare) - 1); + strncpy(destdir_with_output, dest, sizeof(destdir_with_output) - 1); + strncat(destdir_with_output, "/output", sizeof(destdir_with_output) - strlen(destdir_with_output) - 1); if (!access(destdir_with_output, F_OK)) { destdir = destdir_with_output; @@ -26,9 +26,9 @@ int indexer_combine_rootdirs(const char *dest, char **rootdirs, const size_t roo char srcdir_bare[PATH_MAX] = {0}; char srcdir_with_output[PATH_MAX] = {0}; char *srcdir = srcdir_bare; - strcpy(srcdir_bare, rootdirs[i]); - strcpy(srcdir_with_output, rootdirs[i]); - strcat(srcdir_with_output, "/output"); + strncpy(srcdir_bare, rootdirs[i], sizeof(srcdir_bare) - 1); + strncpy(srcdir_with_output, rootdirs[i], sizeof(srcdir_with_output) - 1); + strncat(srcdir_with_output, "/output", sizeof(srcdir_with_output) - strlen(srcdir_with_output) - 1); if (access(srcdir_bare, F_OK)) { fprintf(stderr, "%s does not exist\n", srcdir_bare); @@ -261,11 +261,11 @@ int main(const int argc, char *argv[]) { char workdir_template[PATH_MAX] = {0}; const char *system_tmp = getenv("TMPDIR"); if (system_tmp) { - strcat(workdir_template, system_tmp); + strncat(workdir_template, system_tmp, sizeof(workdir_template) - strlen(workdir_template) - 1); } else { - strcat(workdir_template, "/tmp"); + strncat(workdir_template, "/tmp", sizeof(workdir_template) - strlen(workdir_template) - 1); } - strcat(workdir_template, "/stasis-combine.XXXXXX"); + strncat(workdir_template, "/stasis-combine.XXXXXX", sizeof(workdir_template) - strlen(workdir_template) - 1); char *workdir = mkdtemp(workdir_template); if (!workdir) { SYSERROR("Unable to create temporary directory: %s", workdir_template); diff --git a/src/cli/stasis_indexer/website.c b/src/cli/stasis_indexer/website.c index e758d47..8a5126d 100644 --- a/src/cli/stasis_indexer/website.c +++ b/src/cli/stasis_indexer/website.c @@ -36,7 +36,7 @@ int indexer_make_website(struct Delivery **ctx) { // Replace *.md extension with *.html. strncpy(fullpath_dest, fullpath_src, sizeof(fullpath_dest) - 1); - gen_file_extension_str(fullpath_dest, ".html"); + gen_file_extension_str(fullpath_dest, sizeof(fullpath_dest), ".html"); // Convert markdown to html if (pandoc_exec(fullpath_src, fullpath_dest, have_css ? css_filename : NULL, "STASIS")) { -- cgit From d17103f326bbf026f55a326629e41e69c21a78ad Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 16 Apr 2026 13:04:33 -0400 Subject: Fix cmd buffer size to copy --- src/cli/stasis_indexer/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cli/stasis_indexer') diff --git a/src/cli/stasis_indexer/helpers.c b/src/cli/stasis_indexer/helpers.c index 27608d3..2ecdc74 100644 --- a/src/cli/stasis_indexer/helpers.c +++ b/src/cli/stasis_indexer/helpers.c @@ -120,7 +120,7 @@ int pandoc_exec(const char *in_file, const char *out_file, const char *css_file, // Converts a markdown file to html char cmd[STASIS_BUFSIZ] = {0}; - strncpy(cmd, "pandoc ", sizeof(cmd)); + strncpy(cmd, "pandoc ", sizeof(cmd) - 1); strncat(cmd, pandoc_versioned_args, sizeof(cmd) - strlen(cmd) - 1); if (css_file && strlen(css_file)) { strncat(cmd, "--css ", sizeof(cmd) - strlen(cmd) - 1); -- cgit From 90cbf865cb6e88d5db6484040dc4dc885f88caed Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 17 Apr 2026 10:57:43 -0400 Subject: Convert vsprintf * Check error conditions in related v-functions --- src/cli/stasis_indexer/helpers.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/cli/stasis_indexer') diff --git a/src/cli/stasis_indexer/helpers.c b/src/cli/stasis_indexer/helpers.c index 2ecdc74..0debfe4 100644 --- a/src/cli/stasis_indexer/helpers.c +++ b/src/cli/stasis_indexer/helpers.c @@ -243,7 +243,15 @@ int get_files(struct StrList **out, const char *path, const char *pattern, ...) va_list args; va_start(args, pattern); char userpattern[PATH_MAX] = {0}; - vsprintf(userpattern, pattern, args); + const int len = vsnprintf(userpattern, sizeof(userpattern), pattern, args); + if (len < 0) { + SYSERROR("%s", "vsnprintf failed\n"); + va_end(args); + return -1; + } + if ((size_t) len > sizeof(userpattern)) { + fprintf(stderr, "WARNING: %s: userpattern truncated!\n", __FUNCTION__); + } va_end(args); if (!strlen(userpattern)) { userpattern[0] = '*'; -- cgit From 577912ff0e1996b9846db00247648abd828a8f43 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Tue, 21 Apr 2026 10:48:03 -0400 Subject: Avoid segfault on empty meta directory --- src/cli/stasis_indexer/stasis_indexer_main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/cli/stasis_indexer') diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c index 63fb45c..d475c15 100644 --- a/src/cli/stasis_indexer/stasis_indexer_main.c +++ b/src/cli/stasis_indexer/stasis_indexer_main.c @@ -320,6 +320,11 @@ int main(const int argc, char *argv[]) { msg(STASIS_MSG_L1, "Loading metadata\n"); struct StrList *metafiles = NULL; get_files(&metafiles, ctx.storage.meta_dir, "*.stasis"); + if (!metafiles || !strlist_count(metafiles)) { + SYSERROR("%s: No metadata!", ctx.storage.meta_dir); + delivery_free(&ctx); + exit(1); + } strlist_sort(metafiles, STASIS_SORT_LEN_ASCENDING); struct Delivery **local = calloc(strlist_count(metafiles) + 1, sizeof(*local)); -- cgit