From 347677c3330ece8496b9cd242fd7e4292c2260ae Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 24 Apr 2026 15:55:21 -0400 Subject: NUL terminate after copy --- src/cli/stasis/stasis_main.c | 10 ++++++++++ src/cli/stasis_indexer/helpers.c | 7 +++++++ src/cli/stasis_indexer/junitxml_report.c | 10 +++++++--- src/cli/stasis_indexer/stasis_indexer_main.c | 6 ++++++ src/cli/stasis_indexer/website.c | 3 +++ 5 files changed, 33 insertions(+), 3 deletions(-) (limited to 'src/cli') diff --git a/src/cli/stasis/stasis_main.c b/src/cli/stasis/stasis_main.c index 01a126e..252e67e 100644 --- a/src/cli/stasis/stasis_main.c +++ b/src/cli/stasis/stasis_main.c @@ -20,6 +20,7 @@ static void setup_sysconfdir() { } else { strncpy(stasis_sysconfdir_tmp, STASIS_SYSCONFDIR, sizeof(stasis_sysconfdir_tmp) - 1); } + stasis_sysconfdir_tmp[sizeof(stasis_sysconfdir_tmp) - 1] = '\0'; globals.sysconfdir = realpath(stasis_sysconfdir_tmp, NULL); if (!globals.sysconfdir) { @@ -521,6 +522,8 @@ static char *center_text(const char *s, const size_t maxwidth) { } result[i++] = 'v'; strncpy(&result[i], s, maxwidth - middle - 1); + result[maxwidth - middle - 1] = '\0'; + return result; } @@ -571,6 +574,7 @@ int main(int argc, char *argv[]) { break; case 'p': strncpy(python_override_version, optarg, sizeof(python_override_version) - 1); + python_override_version[sizeof(python_override_version) - 1] = '\0'; break; case 'l': globals.cpu_limit = strtol(optarg, NULL, 10); @@ -707,8 +711,14 @@ int main(int argc, char *argv[]) { runtime_apply(ctx.runtime.environ); strncpy(env_name, ctx.info.release_name, sizeof(env_name) - 1); + env_name[sizeof(env_name) - 1] = '\0'; + strncpy(env_name_testing, env_name, sizeof(env_name_testing) - 1); + env_name_testing[sizeof(env_name_testing) - 1] = '\0'; + strncat(env_name_testing, "-test", sizeof(env_name_testing) - strlen(env_name_testing) - 1); + env_name_testing[sizeof(env_name_testing) - 1] = '\0'; + char *envs[] = { "release", env_name, "testing", env_name_testing, diff --git a/src/cli/stasis_indexer/helpers.c b/src/cli/stasis_indexer/helpers.c index 23e4f5a..86a20e4 100644 --- a/src/cli/stasis_indexer/helpers.c +++ b/src/cli/stasis_indexer/helpers.c @@ -121,7 +121,11 @@ 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) - 1); + cmd[sizeof(cmd) - 1] = '\0'; + strncat(cmd, pandoc_versioned_args, sizeof(cmd) - strlen(cmd) - 1); + cmd[sizeof(cmd) - 1] = '\0'; + if (css_file && strlen(css_file)) { strncat(cmd, "--css ", sizeof(cmd) - strlen(cmd) - 1); strncat(cmd, css_file, sizeof(cmd) - strlen(cmd) - 1); @@ -397,8 +401,11 @@ int write_manifest(const char *path, char **exclude_path, FILE *fp) { } char filepath[PATH_MAX] = {0}; strncpy(filepath, path, PATH_MAX - 1); + filepath[PATH_MAX - 1] = '\0'; + 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/junitxml_report.c b/src/cli/stasis_indexer/junitxml_report.c index d30ee09..4eae7f7 100644 --- a/src/cli/stasis_indexer/junitxml_report.c +++ b/src/cli/stasis_indexer/junitxml_report.c @@ -36,10 +36,15 @@ static int write_report_output(struct Delivery *ctx, FILE *destfp, const char *x char result_outfile[PATH_MAX] = {0}; char *short_name_pattern = NULL; - asprintf(&short_name_pattern, "-%s", ctx->info.release_name); + if (asprintf(&short_name_pattern, "-%s", ctx->info.release_name) < 0 || !short_name_pattern) { + SYSERROR("%s", "unable to allocate bytes for short name pattern"); + return -1; + } char short_name[PATH_MAX] = {0}; strncpy(short_name, bname, sizeof(short_name) - 1); + short_name[sizeof(short_name) - 1] = '\0'; + replace_text(short_name, short_name_pattern, "", 0); replace_text(short_name, "results-", "", 0); guard_free(short_name_pattern); @@ -52,8 +57,7 @@ static int write_report_output(struct Delivery *ctx, FILE *destfp, const char *x testsuite->passed, testsuite->failures, testsuite->skipped, testsuite->errors); - snprintf(result_outfile, sizeof(result_outfile) - strlen(bname) - 3, "%s.md", - bname); + snprintf(result_outfile, sizeof(result_outfile) - strlen(bname), "%s.md", bname); guard_free(bname); FILE *resultfp = fopen(result_outfile, "w+"); diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c index d475c15..fa28c58 100644 --- a/src/cli/stasis_indexer/stasis_indexer_main.c +++ b/src/cli/stasis_indexer/stasis_indexer_main.c @@ -14,8 +14,13 @@ int indexer_combine_rootdirs(const char *dest, char **rootdirs, const size_t roo char *destdir = destdir_bare; strncpy(destdir_bare, dest, sizeof(destdir_bare) - 1); + destdir[sizeof(destdir_bare) - 1] = '\0'; + strncpy(destdir_with_output, dest, sizeof(destdir_with_output) - 1); + destdir_with_output[sizeof(destdir_with_output) - 1] = '\0'; + strncat(destdir_with_output, "/output", sizeof(destdir_with_output) - strlen(destdir_with_output) - 1); + destdir_with_output[sizeof(destdir_with_output) - 1] = '\0'; if (!access(destdir_with_output, F_OK)) { destdir = destdir_with_output; @@ -251,6 +256,7 @@ int main(const int argc, char *argv[]) { } else { strncpy(stasis_sysconfdir_tmp, STASIS_SYSCONFDIR, sizeof(stasis_sysconfdir_tmp) - 1); } + stasis_sysconfdir_tmp[sizeof(stasis_sysconfdir_tmp) - 1] = '\0'; globals.sysconfdir = realpath(stasis_sysconfdir_tmp, NULL); if (!globals.sysconfdir) { diff --git a/src/cli/stasis_indexer/website.c b/src/cli/stasis_indexer/website.c index 8a5126d..aa6e2a5 100644 --- a/src/cli/stasis_indexer/website.c +++ b/src/cli/stasis_indexer/website.c @@ -36,6 +36,8 @@ int indexer_make_website(struct Delivery **ctx) { // Replace *.md extension with *.html. strncpy(fullpath_dest, fullpath_src, sizeof(fullpath_dest) - 1); + fullpath_dest[sizeof(fullpath_dest) - 1] = '\0'; + gen_file_extension_str(fullpath_dest, sizeof(fullpath_dest), ".html"); // Convert markdown to html @@ -53,6 +55,7 @@ int indexer_make_website(struct Delivery **ctx) { char link_from[PATH_MAX] = {0}; char link_dest[PATH_MAX] = {0}; strncpy(link_from, "README.html", sizeof(link_from) - 1); + link_dest[sizeof(link_dest) - 1] = '\0'; 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 32e8aa87ba1f592f31f5a94b2d35bf2159071ae0 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 24 Apr 2026 16:15:40 -0400 Subject: NUL after copy --- src/cli/stasis_indexer/stasis_indexer_main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/cli') diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c index fa28c58..5a92014 100644 --- a/src/cli/stasis_indexer/stasis_indexer_main.c +++ b/src/cli/stasis_indexer/stasis_indexer_main.c @@ -32,8 +32,13 @@ int indexer_combine_rootdirs(const char *dest, char **rootdirs, const size_t roo char srcdir_with_output[PATH_MAX] = {0}; char *srcdir = srcdir_bare; strncpy(srcdir_bare, rootdirs[i], sizeof(srcdir_bare) - 1); + srcdir_bare[sizeof(srcdir_bare) - 1] = '\0'; + strncpy(srcdir_with_output, rootdirs[i], sizeof(srcdir_with_output) - 1); + srcdir_with_output[sizeof(srcdir_with_output) - 1] = '\0'; + strncat(srcdir_with_output, "/output", sizeof(srcdir_with_output) - strlen(srcdir_with_output) - 1); + srcdir_with_output[sizeof(srcdir_with_output) - 1] = '\0'; if (access(srcdir_bare, F_OK)) { fprintf(stderr, "%s does not exist\n", srcdir_bare); -- cgit From 51b01cdd30aafb0846263c60334850e0f82118e6 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Fri, 24 Apr 2026 19:56:51 -0400 Subject: Fix NUL placement in center text --- src/cli/stasis/stasis_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cli') diff --git a/src/cli/stasis/stasis_main.c b/src/cli/stasis/stasis_main.c index 252e67e..c04e88b 100644 --- a/src/cli/stasis/stasis_main.c +++ b/src/cli/stasis/stasis_main.c @@ -522,7 +522,7 @@ static char *center_text(const char *s, const size_t maxwidth) { } result[i++] = 'v'; strncpy(&result[i], s, maxwidth - middle - 1); - result[maxwidth - middle - 1] = '\0'; + result[maxwidth - 1] = '\0'; return result; } -- cgit From 0d4b95442be1dcb72855a2384744d0e13cc4ee7d Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sat, 25 Apr 2026 14:18:37 -0400 Subject: usage: fail on allocation error --- src/cli/stasis_indexer/args.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/cli') diff --git a/src/cli/stasis_indexer/args.c b/src/cli/stasis_indexer/args.c index 8c9d3fe..e77c0b7 100644 --- a/src/cli/stasis_indexer/args.c +++ b/src/cli/stasis_indexer/args.c @@ -22,6 +22,10 @@ const char *long_options_help[] = { void usage(char *name) { const int maxopts = sizeof(long_options) / sizeof(long_options[0]); char *opts = calloc(maxopts + 1, sizeof(char)); + if (!opts) { + SYSERROR("%s", "Unable to allocate memory for options array"); + exit(1); + } for (int i = 0; i < maxopts; i++) { opts[i] = (char) long_options[i].val; } -- cgit From 8f209a9ab8dfca02ce5c53f50d87919b7202e3f1 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sat, 25 Apr 2026 16:35:28 -0400 Subject: Set starting TMPDIR to /tmp/stasis * Easier to remove leftover files, if any * Now uses setenv() to have better control over external programs * Removes the hack to initialize TMPDIR early --- src/cli/stasis/system_requirements.c | 4 ---- src/cli/stasis_indexer/stasis_indexer_main.c | 8 +++++++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src/cli') diff --git a/src/cli/stasis/system_requirements.c b/src/cli/stasis/system_requirements.c index 0f0aae8..ebfbffc 100644 --- a/src/cli/stasis/system_requirements.c +++ b/src/cli/stasis/system_requirements.c @@ -38,10 +38,6 @@ void check_system_requirements(struct Delivery *ctx) { msg(STASIS_MSG_RESTRICT, "found\n"); } - if (!globals.tmpdir && !ctx->storage.tmpdir) { - delivery_init_tmpdir(ctx); - } - msg(STASIS_MSG_L2, "Docker\n"); if (docker_capable(&ctx->deploy.docker.capabilities)) { struct DockerCapabilities *dcap = &ctx->deploy.docker.capabilities; diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c index 5a92014..d71c341 100644 --- a/src/cli/stasis_indexer/stasis_indexer_main.c +++ b/src/cli/stasis_indexer/stasis_indexer_main.c @@ -274,8 +274,14 @@ int main(const int argc, char *argv[]) { if (system_tmp) { strncat(workdir_template, system_tmp, sizeof(workdir_template) - strlen(workdir_template) - 1); } else { - strncat(workdir_template, "/tmp", sizeof(workdir_template) - strlen(workdir_template) - 1); + strncat(workdir_template, "/tmp/stasis", sizeof(workdir_template) - strlen(workdir_template) - 1); } + + if (mkdirs(workdir_template, 0700)) { + SYSERROR("Unable to create directory '%s': %s", workdir_template, strerror(errno)); + exit(1); + } + strncat(workdir_template, "/stasis-combine.XXXXXX", sizeof(workdir_template) - strlen(workdir_template) - 1); char *workdir = mkdtemp(workdir_template); if (!workdir) { -- cgit From 2057ef8a1b88e97a16f1f7afc7b4b3c350a104bd Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sat, 25 Apr 2026 16:36:54 -0400 Subject: Move system requirement check down so configure_delivery_context can set TMPDIR before getting executed --- src/cli/stasis/stasis_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cli') diff --git a/src/cli/stasis/stasis_main.c b/src/cli/stasis/stasis_main.c index c04e88b..78aae0c 100644 --- a/src/cli/stasis/stasis_main.c +++ b/src/cli/stasis/stasis_main.c @@ -691,7 +691,6 @@ int main(int argc, char *argv[]) { setup_python_version_override(&ctx, python_override_version); configure_stasis_ini(&ctx, &config_input); check_system_path(); - check_requirements(&ctx); msg(STASIS_MSG_L1, "Setup\n"); @@ -700,6 +699,7 @@ int main(int argc, char *argv[]) { configure_delivery_ini(&ctx, &delivery_input); configure_delivery_context(&ctx); + check_requirements(&ctx); configure_jfrog_cli(&ctx); /* -- cgit From 421903a1379353f07a10deb335ed3c0361233064 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sun, 26 Apr 2026 01:49:02 -0400 Subject: Fix file handle leaks --- src/cli/stasis_indexer/readmes.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/cli') diff --git a/src/cli/stasis_indexer/readmes.c b/src/cli/stasis_indexer/readmes.c index 749b1ee..7357fca 100644 --- a/src/cli/stasis_indexer/readmes.c +++ b/src/cli/stasis_indexer/readmes.c @@ -67,6 +67,7 @@ int indexer_readmes(struct Delivery **ctx, const size_t nelem) { latest_deliveries[i]->info.build_number, strstr((*ctx)->rules.release_fmt, "%p") ? latest_deliveries[i]->meta.python_compact : "" ) < 0) { SYSERROR("%s", "Unable to allocate bytes for pattern"); + fclose(indexfp); return -1; } -- cgit From 917df9195011c852a6efffd4f1dc40ff007534c9 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sun, 26 Apr 2026 01:49:22 -0400 Subject: Fix leaks --- src/cli/stasis_indexer/junitxml_report.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/cli') diff --git a/src/cli/stasis_indexer/junitxml_report.c b/src/cli/stasis_indexer/junitxml_report.c index 4eae7f7..c6cf4b0 100644 --- a/src/cli/stasis_indexer/junitxml_report.c +++ b/src/cli/stasis_indexer/junitxml_report.c @@ -38,6 +38,7 @@ static int write_report_output(struct Delivery *ctx, FILE *destfp, const char *x char *short_name_pattern = NULL; if (asprintf(&short_name_pattern, "-%s", ctx->info.release_name) < 0 || !short_name_pattern) { SYSERROR("%s", "unable to allocate bytes for short name pattern"); + guard_free(bname); return -1; } -- cgit From f4bccc6b21c8eec58bb08bc22115a93a2352868d Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sun, 26 Apr 2026 01:49:48 -0400 Subject: Add allocation checks --- src/cli/stasis_indexer/stasis_indexer_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/cli') diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c index d71c341..ed938b7 100644 --- a/src/cli/stasis_indexer/stasis_indexer_main.c +++ b/src/cli/stasis_indexer/stasis_indexer_main.c @@ -212,6 +212,10 @@ int main(const int argc, char *argv[]) { if (optind < argc) { rootdirs_total = argc - current_index; rootdirs = calloc(rootdirs_total + 1, sizeof(*rootdirs)); + if (!rootdirs) { + SYSERROR("%s", "unable to allocate memory for rootdirs array"); + exit(1); + } int i = 0; while (optind < argc) { @@ -223,6 +227,10 @@ int main(const int argc, char *argv[]) { } // use first positional argument rootdirs[i] = realpath(argv[optind], NULL); + if (!rootdirs[i]) { + SYSERROR("%s", "Unable to allocate memory for root directory"); + exit(1); + } optind++; break; } -- cgit From 11bc498b5bca18662a582a163d3e9aaed1a17b79 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 27 Apr 2026 09:20:06 -0400 Subject: Add download_dir member to MicroMambaInfo struct. * TMPDIR and hardcoded path is too unpredictable. --- src/cli/stasis_indexer/helpers.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/cli') diff --git a/src/cli/stasis_indexer/helpers.c b/src/cli/stasis_indexer/helpers.c index 86a20e4..425d209 100644 --- a/src/cli/stasis_indexer/helpers.c +++ b/src/cli/stasis_indexer/helpers.c @@ -156,6 +156,7 @@ int micromamba_configure(const struct Delivery *ctx, struct MicromambaInfo *m) { } m->conda_prefix = globals.conda_install_prefix; m->micromamba_prefix = micromamba_prefix; + m->download_dir = ctx->storage.tmpdir; const size_t pathvar_len = strlen(getenv("PATH")) + strlen(m->micromamba_prefix) + strlen(m->conda_prefix) + 3 + 4 + 1; // ^^^^^^^^^^^^^^^^^^ -- cgit