aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@users.noreply.github.com>2026-04-28 11:45:10 -0400
committerGitHub <noreply@github.com>2026-04-28 11:45:10 -0400
commit10f13b36560c5112554c54d8958081b7aa518050 (patch)
treebd27866c4352de38ebc5b13f8208768d576ae904
parent017bc273aedf3f20512beeb78a2f513913e56305 (diff)
parentd761cc976a8d645e61d23f6e43dcfec1a7fdb061 (diff)
downloadstasis-10f13b36560c5112554c54d8958081b7aa518050.tar.gz
Merge pull request #137 from jhunkeler/bughunt-1001
Bug Hunt 0x1001
-rw-r--r--cmake/GitVersion.cmake2
-rw-r--r--src/cli/stasis/stasis_main.c12
-rw-r--r--src/cli/stasis/system_requirements.c4
-rw-r--r--src/cli/stasis_indexer/args.c4
-rw-r--r--src/cli/stasis_indexer/helpers.c8
-rw-r--r--src/cli/stasis_indexer/junitxml_report.c11
-rw-r--r--src/cli/stasis_indexer/readmes.c1
-rw-r--r--src/cli/stasis_indexer/stasis_indexer_main.c27
-rw-r--r--src/cli/stasis_indexer/website.c3
-rw-r--r--src/lib/core/artifactory.c11
-rw-r--r--src/lib/core/conda.c68
-rw-r--r--src/lib/core/copy.c1
-rw-r--r--src/lib/core/docker.c9
-rw-r--r--src/lib/core/envctl.c2
-rw-r--r--src/lib/core/environment.c1
-rw-r--r--src/lib/core/include/conda.h4
-rw-r--r--src/lib/core/include/core_message.h4
-rw-r--r--src/lib/core/ini.c64
-rw-r--r--src/lib/core/multiprocessing.c1
-rw-r--r--src/lib/core/recipe.c1
-rw-r--r--src/lib/core/relocation.c6
-rw-r--r--src/lib/core/str.c18
-rw-r--r--src/lib/core/strlist.c24
-rw-r--r--src/lib/core/system.c4
-rw-r--r--src/lib/core/template.c4
-rw-r--r--src/lib/core/template_func_proto.c3
-rw-r--r--src/lib/core/utils.c27
-rw-r--r--src/lib/core/wheel.c18
-rw-r--r--src/lib/core/wheelinfo.c4
-rw-r--r--src/lib/delivery/delivery.c20
-rw-r--r--src/lib/delivery/delivery_build.c11
-rw-r--r--src/lib/delivery/delivery_docker.c2
-rw-r--r--src/lib/delivery/delivery_export.c18
-rw-r--r--src/lib/delivery/delivery_init.c62
-rw-r--r--src/lib/delivery/delivery_install.c12
-rw-r--r--src/lib/delivery/delivery_postprocess.c1
-rw-r--r--src/lib/delivery/delivery_test.c6
-rw-r--r--tests/CMakeLists.txt9
-rw-r--r--tests/test_conda.c14
-rw-r--r--tests/test_relocation.c4
-rw-r--r--tests/test_str.c3
-rw-r--r--tests/test_utils.c3
-rw-r--r--tests/test_wheel.c4
43 files changed, 416 insertions, 99 deletions
diff --git a/cmake/GitVersion.cmake b/cmake/GitVersion.cmake
index c9c6159..005667d 100644
--- a/cmake/GitVersion.cmake
+++ b/cmake/GitVersion.cmake
@@ -15,7 +15,7 @@ function(get_version_from_git)
endif()
execute_process(
- COMMAND ${GIT_EXECUTABLE} describe --first-parent --long --dirty --tags --always
+ COMMAND ${GIT_EXECUTABLE} describe --long --dirty --tags --always
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
diff --git a/src/cli/stasis/stasis_main.c b/src/cli/stasis/stasis_main.c
index 01a126e..78aae0c 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 - 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);
@@ -687,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");
@@ -696,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);
/*
@@ -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/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/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;
}
diff --git a/src/cli/stasis_indexer/helpers.c b/src/cli/stasis_indexer/helpers.c
index 23e4f5a..425d209 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);
@@ -152,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;
// ^^^^^^^^^^^^^^^^^^
@@ -397,8 +402,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..c6cf4b0 100644
--- a/src/cli/stasis_indexer/junitxml_report.c
+++ b/src/cli/stasis_indexer/junitxml_report.c
@@ -36,10 +36,16 @@ 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");
+ guard_free(bname);
+ 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 +58,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/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;
}
diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c
index d475c15..ed938b7 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;
@@ -27,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);
@@ -202,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) {
@@ -213,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;
}
@@ -251,6 +269,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) {
@@ -263,8 +282,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) {
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));
diff --git a/src/lib/core/artifactory.c b/src/lib/core/artifactory.c
index 2490346..54f4ba0 100644
--- a/src/lib/core/artifactory.c
+++ b/src/lib/core/artifactory.c
@@ -26,14 +26,17 @@ int artifactory_download_cli(char *dest,
// convert platform string to lower-case
SYSDEBUG("%s", "Set os_ident");
strncpy(os_ident, os, sizeof(os_ident) - 1);
+ os_ident[sizeof(os_ident) - 1] = '\0';
tolower_s(os_ident);
SYSDEBUG("os_ident=%s", os_ident);
// translate OS identifier
if (!strcmp(os_ident, "darwin") || startswith(os_ident, "macos")) {
strncpy(os_ident, "mac", sizeof(os_ident) - 1);
+ os_ident[sizeof(os_ident) - 1] = '\0';
} else if (!strcmp(os_ident, "linux")) {
strncpy(os_ident, "linux", sizeof(os_ident) - 1);
+ os_ident[sizeof(os_ident) - 1] = '\0';
} else {
fprintf(stderr, "%s: unknown operating system: %s\n", __FUNCTION__, os_ident);
return -1;
@@ -42,7 +45,9 @@ int artifactory_download_cli(char *dest,
// translate ARCH identifier
SYSDEBUG("%s", "Set arch_ident");
strncpy(arch_ident, arch, sizeof(arch_ident) - 1);
+ arch_ident[sizeof(arch_ident) - 1] = '\0';
SYSDEBUG("arch_ident=%s", arch_ident);
+
if (startswith(arch_ident, "i") && endswith(arch_ident, "86")) {
strncpy(arch_ident, "386", sizeof(arch_ident) - 1);
} else if (!strcmp(arch_ident, "amd64") || !strcmp(arch_ident, "x86_64") || !strcmp(arch_ident, "x64")) {
@@ -57,6 +62,8 @@ int artifactory_download_cli(char *dest,
fprintf(stderr, "%s: unknown architecture: %s\n", __FUNCTION__, arch_ident);
return -1;
}
+ arch_ident[sizeof(arch_ident) - 1] = '\0';
+
SYSDEBUG("%s", "Construct URL");
snprintf(url, sizeof(url), "%s/%s/%s/%s/%s-%s-%s/%s",
@@ -69,6 +76,7 @@ int artifactory_download_cli(char *dest,
arch_ident, // jfrog-cli-linux-x86_64
remote_filename); // jf
strncpy(path, dest, sizeof(path) - 1);
+ path[sizeof(path) - 1] = '\0';
if (mkdirs(path, 0755)) {
fprintf(stderr, "%s: %s: %s", __FUNCTION__, path, strerror(errno));
@@ -265,7 +273,10 @@ int jfrog_cli(struct JFRT_Auth *auth, const char *subsystem, const char *task, c
if (!globals.verbose) {
strncpy(proc.f_stdout, "/dev/null", sizeof(proc.f_stdout) - 1);
+ proc.f_stdout[sizeof(proc.f_stdout) - 1] = '\0';
+
strncpy(proc.f_stderr, "/dev/null", sizeof(proc.f_stderr) - 1);
+ proc.f_stderr[sizeof(proc.f_stderr) - 1] = '\0';
}
return shell(&proc, cmd);
}
diff --git a/src/lib/core/conda.c b/src/lib/core/conda.c
index 854d56d..4557c5c 100644
--- a/src/lib/core/conda.c
+++ b/src/lib/core/conda.c
@@ -11,17 +11,30 @@ int micromamba(const struct MicromambaInfo *info, char *command, ...) {
tolower_s(sys.sysname);
if (!strcmp(sys.sysname, "darwin")) {
strncpy(sys.sysname, "osx", sizeof(sys.sysname) - 1);
+ sys.sysname[sizeof(sys.sysname) - 1] = '\0';
}
if (!strcmp(sys.machine, "x86_64")) {
strncpy(sys.machine, "64", sizeof(sys.machine) - 1);
+ sys.machine[sizeof(sys.machine) - 1] = '\0';
+ }
+
+ if (!info->download_dir || isempty(info->download_dir)) {
+ SYSERROR("%s", "micromamba inf->download_dir is NULL, or empty");
+ return -1;
+ }
+
+ if (mkdirs(info->download_dir, 0755) < 0) {
+ SYSERROR("Unable to create info->download_dir: %s", info->download_dir);
+ return -1;
}
char url[PATH_MAX] = {0};
snprintf(url, sizeof(url), "https://micro.mamba.pm/api/micromamba/%s-%s/latest", sys.sysname, sys.machine);
- char installer_path[PATH_MAX];
- snprintf(installer_path, sizeof(installer_path), "%s/latest", getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
+ const char installer_name[] = "mm_latest";
+ char installer_path[PATH_MAX] = {0};
+ snprintf(installer_path, sizeof(installer_path), "%s/%s", info->download_dir, installer_name);
if (access(installer_path, F_OK)) {
char *errmsg = NULL;
@@ -39,7 +52,9 @@ int micromamba(const struct MicromambaInfo *info, char *command, ...) {
if (access(mmbin, F_OK)) {
char untarcmd[PATH_MAX * 2];
mkdirs(info->micromamba_prefix, 0755);
- snprintf(untarcmd, sizeof(untarcmd), "tar -xvf %s -C %s --strip-components=1 bin/micromamba 1>/dev/null", installer_path, info->micromamba_prefix);
+ snprintf(untarcmd, sizeof(untarcmd),
+ "tar -xvf %s -C %s --strip-components=1 bin/micromamba 1>/dev/null",
+ installer_path, info->micromamba_prefix);
int untarcmd_status = system(untarcmd);
if (untarcmd_status) {
return -1;
@@ -135,7 +150,7 @@ const char *pkg_index_provides_strerror(int code) {
return PKG_ERROR_STR[code];
}
-int pkg_index_provides(int mode, const char *index, const char *spec) {
+int pkg_index_provides(int mode, const char *index, const char *spec, const char *logdir) {
char cmd[PATH_MAX] = {0};
char spec_local[255] = {0};
@@ -146,11 +161,19 @@ int pkg_index_provides(int mode, const char *index, const char *spec) {
// Normalize the local spec string
strncpy(spec_local, spec, sizeof(spec_local) - 1);
+ spec_local[sizeof(spec_local) - 1] = '\0';
tolower_s(spec_local);
lstrip(spec_local);
strip(spec_local);
- char logfile[] = "/tmp/STASIS-package_exists.XXXXXX";
+ if (mkdirs(logdir, 0700) < 0) {
+ SYSERROR("Unable to create log directory: %s", logdir ? logdir : "NULL");
+ return -1;
+ }
+ const char logfile_template[] = "STASIS-package_exists.XXXXXX";
+ char logfile[PATH_MAX] = {0};
+ snprintf(logfile, sizeof(logfile), "%s/%s", logdir, logfile_template);
+
int logfd = mkstemp(logfile);
if (logfd < 0) {
perror(logfile);
@@ -167,12 +190,15 @@ int pkg_index_provides(int mode, const char *index, const char *spec) {
// Do an installation in dry-run mode to see if the package exists in the given index.
// The --force argument ignores local installation and cache, and actually polls the remote index(es)
strncpy(cmd, "python -m pip install --force --dry-run --no-cache --no-deps ", sizeof(cmd) - 1);
+ cmd[sizeof(cmd) - 1] = '\0';
if (index) {
snprintf(cmd + strlen(cmd), sizeof(cmd) - strlen(cmd), "--index-url='%s' ", index);
}
snprintf(cmd + strlen(cmd), sizeof(cmd) - strlen(cmd), "'%s' ", spec_local);
} else if (mode == PKG_USE_CONDA) {
strncpy(cmd, "mamba search ", sizeof(cmd) - 1);
+ cmd[sizeof(cmd) - 1] = '\0';
+
if (index) {
snprintf(cmd + strlen(cmd), sizeof(cmd) - strlen(cmd), "--channel '%s' ", index);
}
@@ -181,11 +207,24 @@ int pkg_index_provides(int mode, const char *index, const char *spec) {
return PKG_INDEX_PROVIDES_E_INTERNAL_MODE_UNKNOWN;
}
+#if defined(DEBUG)
+ const int debug_log = 1;
+#else
+ const debug_log = 0;
+#endif
+
// Print errors only when shell() itself throws one
// If some day we want to see the errors thrown by pip too, use this
// condition instead: (status != 0)
+ if (debug_log) {
+ SYSDEBUG("Executing: %s", cmd);
+ }
status = shell(&proc, cmd);
- if (status < 0) {
+
+ if (debug_log) {
+ SYSDEBUG("Log file: %s", logfile);
+ }
+ if (status < 0 || debug_log) {
FILE *fp = fdopen(logfd, "r");
if (!fp) {
remove(logfile);
@@ -195,7 +234,11 @@ int pkg_index_provides(int mode, const char *index, const char *spec) {
fflush(stdout);
fflush(stderr);
while (fgets(line, sizeof(line) - 1, fp) != NULL) {
- fprintf(stderr, "%s", line);
+ if (debug_log) {
+ SYSDEBUG("%s", strip(line));
+ } else {
+ fprintf(stderr, "%s", line);
+ }
}
fflush(stderr);
fclose(fp);
@@ -247,6 +290,8 @@ int conda_exec(const char *args) {
break;
}
}
+ conda_as[sizeof(conda_as) - 1] = '\0';
+
const char *command_fmt = "%s %s";
const int len = snprintf(NULL, 0, command_fmt, conda_as, args);
@@ -352,7 +397,8 @@ int conda_activate(const char *root, const char *env_name) {
close(fd);
// Configure our process for output to a log file
- strncpy(proc.f_stdout, logfile, PATH_MAX - 1);
+ strncpy(proc.f_stdout, logfile, sizeof(proc.f_stdout) - 1);
+ proc.f_stdout[sizeof(proc.f_stdout) - 1] = '\0';
// Verify conda's init scripts are available
if (access(path_conda, F_OK) < 0) {
@@ -497,6 +543,7 @@ int conda_setup_headless() {
if (globals.conda_packages && strlist_count(globals.conda_packages)) {
memset(cmd, 0, sizeof(cmd));
strncpy(cmd, "install ", sizeof(cmd) - 1);
+ cmd[sizeof(cmd) - 1] = '\0';
total = strlist_count(globals.conda_packages);
for (size_t i = 0; i < total; i++) {
@@ -520,6 +567,7 @@ int conda_setup_headless() {
if (globals.pip_packages && strlist_count(globals.pip_packages)) {
memset(cmd, 0, sizeof(cmd));
strncpy(cmd, "install ", sizeof(cmd) - 1);
+ cmd[sizeof(cmd) - 1] = '\0';
total = strlist_count(globals.pip_packages);
for (size_t i = 0; i < total; i++) {
@@ -561,11 +609,11 @@ int conda_env_create_from_uri(char *name, char *uri, char *python_version) {
// Convert a bare system path to a file:// path
if (!strstr(uri, "://")) {
- uri_fs = calloc(strlen(uri) + strlen("file://") + 1, sizeof(*uri_fs));
+ uri_fs = calloc(PATH_MAX, sizeof(*uri_fs));
if (!uri_fs) {
return -1;
}
- snprintf(uri_fs, strlen(uri) + strlen("file://") + 1, "%s%s", "file://", uri);
+ snprintf(uri_fs, PATH_MAX, "%s%s", "file://", uri);
}
char tempfile[PATH_MAX] = {0};
diff --git a/src/lib/core/copy.c b/src/lib/core/copy.c
index 5b4e468..6697f59 100644
--- a/src/lib/core/copy.c
+++ b/src/lib/core/copy.c
@@ -15,6 +15,7 @@ int copy2(const char *src, const char *dest, unsigned int op) {
char dname[1024] = {0};
strncpy(dname, dest, sizeof(dname) - 1);
+ dname[sizeof(dname) - 1] = '\0';
char *dname_endptr = strrchr(dname, '/');
if (dname_endptr != NULL) {
diff --git a/src/lib/core/docker.c b/src/lib/core/docker.c
index b289e5a..484f476 100644
--- a/src/lib/core/docker.c
+++ b/src/lib/core/docker.c
@@ -19,9 +19,11 @@ int docker_exec(const char *args, const unsigned flags) {
if (final_flags & STASIS_DOCKER_QUIET_STDOUT) {
strncpy(proc.f_stdout, "/dev/null", sizeof(proc.f_stdout) - 1);
+ proc.f_stdout[sizeof(proc.f_stdout) - 1] = '\0';
}
if (final_flags & STASIS_DOCKER_QUIET_STDERR) {
strncpy(proc.f_stderr, "/dev/null", sizeof(proc.f_stderr) - 1);
+ proc.f_stderr[sizeof(proc.f_stderr) - 1] = '\0';
}
if (!final_flags) {
@@ -74,6 +76,8 @@ int docker_build(const char *dirpath, const char *args, int engine) {
if (engine & STASIS_DOCKER_BUILD_X) {
strncpy(build, "buildx build", sizeof(build) - 1);
}
+ build[sizeof(build) - 1] = '\0';
+
snprintf(cmd, sizeof(cmd), "%s %s %s", build, args, dirpath);
return docker_exec(cmd, 0);
}
@@ -94,6 +98,7 @@ int docker_save(const char *image, const char *destdir, const char *compression_
} else {
strncpy(ext, compression_program, sizeof(ext) - 1);
}
+ ext[sizeof(ext) - 1] = '\0';
snprintf(cmd, sizeof(cmd), "save \"%s\" | %s > \"%s/%s.tar.%s\"", image, compression_program, destdir, image, ext);
} else {
snprintf(cmd, sizeof(cmd), "save \"%s\" -o \"%s/%s.tar\"", image, destdir, image);
@@ -122,7 +127,11 @@ static char *docker_ident() {
memset(&proc, 0, sizeof(proc));
strncpy(proc.f_stdout, tempfile, sizeof(proc.f_stdout) - 1);
+ proc.f_stdout[sizeof(proc.f_stdout) - 1] = '\0';
+
strncpy(proc.f_stderr, "/dev/null", sizeof(proc.f_stderr) - 1);
+ proc.f_stderr[sizeof(proc.f_stderr) - 1] = '\0';
+
shell(&proc, "docker --version");
if (!freopen(tempfile, "r", fp)) {
diff --git a/src/lib/core/envctl.c b/src/lib/core/envctl.c
index d8d1b3d..5987616 100644
--- a/src/lib/core/envctl.c
+++ b/src/lib/core/envctl.c
@@ -53,7 +53,7 @@ size_t envctl_get_index(const struct EnvCtl *envctl, const char *name) {
for (size_t i = 0; i < envctl->num_used; i++) {
if (!strcmp(envctl->item[i]->name, name)) {
// pack state flag, outer (struct) index and inner (name) index
- return 1L << 63L | i;
+ return 1UL << 63UL | i;
}
}
return 0;
diff --git a/src/lib/core/environment.c b/src/lib/core/environment.c
index 3c94d33..1bd9d28 100644
--- a/src/lib/core/environment.c
+++ b/src/lib/core/environment.c
@@ -90,6 +90,7 @@ void runtime_export(RuntimeEnv *env, char **keys) {
break;
}
}
+ export_command[sizeof(export_command) - 1] = '\0';
for (size_t i = 0; i < strlist_count(env); i++) {
char output[STASIS_BUFSIZ] = {0};
diff --git a/src/lib/core/include/conda.h b/src/lib/core/include/conda.h
index f3d481c..cc9426d 100644
--- a/src/lib/core/include/conda.h
+++ b/src/lib/core/include/conda.h
@@ -29,6 +29,7 @@
struct MicromambaInfo {
char *micromamba_prefix; //!< Path to write micromamba binary
char *conda_prefix; //!< Path to install conda base tree
+ char *download_dir; //!< Path to store micromamba installer
};
/**
@@ -219,12 +220,13 @@ int conda_index(const char *path);
* @param mode USE_CONDA
* @param index a file system path or url pointing to a simple index or conda channel
* @param spec a pip package specification (e.g. `name==1.2.3`)
+ * @param logdir the directory to store the output log
* @param spec a conda package specification (e.g. `name=1.2.3`)
* @return PKG_NOT_FOUND, if not found
* @return PKG_FOUND, if found
* @return PKG_E_INDEX_PROVIDES_{ERROR}, on error (see conda.h)
*/
-int pkg_index_provides(int mode, const char *index, const char *spec);
+int pkg_index_provides(int mode, const char *index, const char *spec, const char *logdir);
const char *pkg_index_provides_strerror(int code);
char *conda_get_active_environment();
diff --git a/src/lib/core/include/core_message.h b/src/lib/core/include/core_message.h
index 1ffa846..aab7203 100644
--- a/src/lib/core/include/core_message.h
+++ b/src/lib/core/include/core_message.h
@@ -3,13 +3,13 @@
#define STASIS_CORE_MESSAGE_H
#define SYSERROR(MSG, ...) do { \
- fprintf(stderr, "%s:%d:%s():%s - ", path_basename(__FILE__), __LINE__, __FUNCTION__, (errno > 0) ? strerror(errno) : "info"); \
+ fprintf(stderr, STASIS_COLOR_RED "ERROR: " STASIS_COLOR_RESET STASIS_COLOR_WHITE "%s:%d:%s()" STASIS_COLOR_RESET ":%s - ", path_basename(__FILE__), __LINE__, __FUNCTION__, (errno > 0) ? strerror(errno) : "info"); \
fprintf(stderr, MSG LINE_SEP, __VA_ARGS__); \
} while (0)
#ifdef DEBUG
#define SYSDEBUG(MSG, ...) do { \
- fprintf(stderr, "DEBUG: %s:%d:%s(): ", path_basename(__FILE__), __LINE__, __FUNCTION__); \
+ fprintf(stderr, STASIS_COLOR_BLUE "DEBUG: " STASIS_COLOR_RESET STASIS_COLOR_WHITE "%s:%d:%s()" STASIS_COLOR_RESET ": ", path_basename(__FILE__), __LINE__, __FUNCTION__); \
fprintf(stderr, MSG LINE_SEP, __VA_ARGS__); \
} while (0)
#else
diff --git a/src/lib/core/ini.c b/src/lib/core/ini.c
index 6995eb2..c37030c 100644
--- a/src/lib/core/ini.c
+++ b/src/lib/core/ini.c
@@ -181,7 +181,9 @@ int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, int
break;
case INIVAL_TYPE_STR_ARRAY:
strncpy(tbufp, data_copy, sizeof(tbuf) - 1);
+ tbuf[sizeof(tbuf) - 1] = '\0';
guard_free(data_copy);
+
data_copy = calloc(STASIS_BUFSIZ, sizeof(*data_copy));
if (!data_copy) {
return -1;
@@ -345,6 +347,10 @@ int ini_data_append(struct INIFILE **ini, char *section_name, char *key, char *v
section->data_count++;
} else {
struct INIData *data = ini_data_get(*ini, section_name, key);
+ if (!data) {
+ SYSERROR("%s:%s: key does not exist", section_name, key);
+ return -1;
+ }
size_t value_len_old = strlen(data->value);
size_t value_len = strlen(value);
size_t value_len_new = value_len_old + value_len;
@@ -353,9 +359,9 @@ int ini_data_append(struct INIFILE **ini, char *section_name, char *key, char *v
if (!value_tmp) {
SYSERROR("Unable to increase data->value size to %zu bytes", value_len_new + 2);
return -1;
- } else {
- data->value = value_tmp;
}
+ data->value = value_tmp;
+
strncat(data->value, value, value_len_new - strlen(data->value));
}
return 0;
@@ -420,6 +426,7 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) {
for (size_t x = 0; x < ini->section_count; x++) {
struct INISection *section = ini->section[x];
char *section_name = section->key;
+
fprintf(*stream, "[%s]" LINE_SEP, section_name);
for (size_t y = 0; y < ini->section[x]->data_count; y++) {
@@ -428,6 +435,7 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) {
char *key = data->key;
char *value = data->value;
unsigned *hint = &data->type_hint;
+
memset(outvalue, 0, sizeof(outvalue));
if (key && value) {
@@ -440,6 +448,9 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) {
xvalue = ini_getval_str(ini, section_name, key, (int) mode, &err);
value = xvalue;
}
+
+ const size_t buf_size = sizeof(outvalue);
+ size_t buf_len = 0;
char **parts = split(value, LINE_SEP, 0);
for (size_t p = 0; parts && parts[p] != NULL; p++) {
char *render = NULL;
@@ -454,15 +465,16 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) {
return -1;
}
+ buf_len = strlen(outvalue);
if (*hint == INIVAL_TYPE_STR_ARRAY) {
- int leading_space = isspace(*render);
+ const int leading_space = isspace(*render);
if (leading_space) {
- snprintf(outvalue + strlen(outvalue), sizeof(outvalue) - strlen(outvalue), "%s" LINE_SEP, render);
+ snprintf(outvalue + buf_len, buf_size - buf_len, "%s" LINE_SEP, render);
} else {
- snprintf(outvalue + strlen(outvalue), sizeof(outvalue) - strlen(outvalue), " %s" LINE_SEP, render);
+ snprintf(outvalue + buf_len, buf_size - buf_len, " %s" LINE_SEP, render);
}
} else {
- snprintf(outvalue + strlen(outvalue), sizeof(outvalue) - strlen(outvalue), "%s", render);
+ snprintf(outvalue + buf_len, buf_size - buf_len, "%s", render);
}
if (mode == INI_WRITE_PRESERVE) {
guard_free(render);
@@ -470,7 +482,12 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) {
}
guard_array_free(parts);
strip(outvalue);
- strncat(outvalue, LINE_SEP, sizeof(outvalue) - strlen(outvalue) - 1);
+
+ // update length of outvalue
+ buf_len = strlen(outvalue);
+
+ snprintf(outvalue + buf_len, buf_size - buf_len, "%s", LINE_SEP);
+
fprintf(*stream, "%s = %s%s", ini->section[x]->data[y]->key, *hint == INIVAL_TYPE_STR_ARRAY ? LINE_SEP : "", outvalue);
guard_free(value);
} else {
@@ -493,12 +510,9 @@ char *unquote(char *s) {
void ini_free(struct INIFILE **ini) {
for (size_t section = 0; section < (*ini)->section_count; section++) {
- SYSDEBUG("freeing section: %s", (*ini)->section[section]->key);
for (size_t data = 0; data < (*ini)->section[section]->data_count; data++) {
if ((*ini)->section[section]->data[data]) {
- SYSDEBUG("freeing data key: %s", (*ini)->section[section]->data[data]->key);
guard_free((*ini)->section[section]->data[data]->key);
- SYSDEBUG("freeing data value: %s", (*ini)->section[section]->data[data]->value);
guard_free((*ini)->section[section]->data[data]->value);
guard_free((*ini)->section[section]->data[data]);
}
@@ -526,6 +540,7 @@ struct INIFILE *ini_open(const char *filename) {
// Create an implicit section. [default] does not need to be present in the INI config
ini_section_create(&ini, "default");
strncpy(current_section, "default", sizeof(current_section) - 1);
+ current_section[sizeof(current_section) - 1] = '\0';
// Open the configuration file for reading
FILE *fp = fopen(filename, "r");
@@ -538,15 +553,15 @@ struct INIFILE *ini_open(const char *filename) {
unsigned hint = 0;
int multiline_data = 0;
int no_data = 0;
- char inikey[2][255];
+ char inikey[2][255] = {0};
char *key = inikey[0];
char *key_last = inikey[1];
char value[STASIS_BUFSIZ] = {0};
- memset(inikey, 0, sizeof(inikey));
-
// Read file
for (size_t i = 0; fgets(line, sizeof(line), fp) != NULL; i++) {
+ const size_t key_last_size = sizeof(inikey[1]);
+ const size_t key_size = sizeof(inikey[0]);
if (no_data && multiline_data) {
if (!isempty(line)) {
no_data = 0;
@@ -555,7 +570,7 @@ struct INIFILE *ini_open(const char *filename) {
}
memset(value, 0, sizeof(value));
} else {
- memset(key, 0, sizeof(inikey[0]));
+ memset(key, 0, key_size);
}
// Find pointer to first comment character
char *comment = strpbrk(line, ";#");
@@ -579,7 +594,7 @@ struct INIFILE *ini_open(const char *filename) {
// Test for section header: [string]
if (startswith(line, "[")) {
// The previous key is irrelevant now
- memset(key_last, 0, sizeof(inikey[1]));
+ memset(key_last, 0, key_last_size);
char *section_name = substring_between(line, "[]");
if (!section_name) {
@@ -600,6 +615,8 @@ struct INIFILE *ini_open(const char *filename) {
// Record the name of the section. This is used until another section is found.
memset(current_section, 0, sizeof(current_section));
strncpy(current_section, section_name, sizeof(current_section) - 1);
+ current_section[sizeof(current_section) - 1] = '\0';
+
guard_free(section_name);
memset(line, 0, sizeof(line));
continue;
@@ -619,18 +636,25 @@ struct INIFILE *ini_open(const char *filename) {
if (operator) {
size_t key_len = operator - line;
- memset(key, 0, sizeof(inikey[0]));
+ memset(key, 0, key_size);
+
strncpy(key, line, key_len);
+ key[key_size - 1] = '\0';
lstrip(key);
strip(key);
- memset(key_last, 0, sizeof(inikey[1]));
- strncpy(key_last, key, sizeof(inikey[1]) - 1);
+
+ memset(key_last, 0, key_last_size);
+ strncpy(key_last, key, key_last_size - 1);
+ key_last[key_last_size - 1] = '\0';
+
reading_value = 1;
if (strlen(operator) > 1) {
strncpy(value, &operator[1], sizeof(value) - 1);
} else {
strncpy(value, "", sizeof(value) - 1);
}
+ value[sizeof(value) - 1] = '\0';
+
if (isempty(value)) {
//printf("%s is probably long raw data\n", key);
hint = INIVAL_TYPE_STR_ARRAY;
@@ -643,8 +667,10 @@ struct INIFILE *ini_open(const char *filename) {
}
strip(value);
} else {
- strncpy(key, key_last, sizeof(inikey[0]) - 1);
+ strncpy(key, key_last, key_size - 1);
+ key[key_size - 1] = '\0';
strncpy(value, line, sizeof(value) - 1);
+ value[sizeof(value) - 1] = '\0';
}
memset(line, 0, sizeof(line));
diff --git a/src/lib/core/multiprocessing.c b/src/lib/core/multiprocessing.c
index 7b16af3..8fd8b93 100644
--- a/src/lib/core/multiprocessing.c
+++ b/src/lib/core/multiprocessing.c
@@ -261,7 +261,6 @@ void mp_pool_show_summary(struct MultiProcessingPool *pool) {
char duration[255] = {0};
seconds_to_human_readable(task->time_data.duration, duration, sizeof(duration));
printf("%-4s %10d %10s %-10s\n", status_str, task->parent_pid, duration, task->ident) ;
- //printf("%-4s %10d %7lds %-10s\n", status_str, task->parent_pid, task->elapsed, task->ident) ;
}
puts("");
}
diff --git a/src/lib/core/recipe.c b/src/lib/core/recipe.c
index cc96139..e5769bb 100644
--- a/src/lib/core/recipe.c
+++ b/src/lib/core/recipe.c
@@ -17,6 +17,7 @@ int recipe_clone(char *recipe_dir, char *url, char *gitref, char **result) {
}
}
strncpy(*result, destdir, PATH_MAX - 1);
+ (*result)[PATH_MAX - 1] = '\0';
if (!access(destdir, F_OK)) {
if (!strcmp(destdir, "/")) {
diff --git a/src/lib/core/relocation.c b/src/lib/core/relocation.c
index ea8b9c6..16376b3 100644
--- a/src/lib/core/relocation.c
+++ b/src/lib/core/relocation.c
@@ -8,8 +8,9 @@
* Replace all occurrences of `target` with `replacement` in `original`
*
* ~~~{.c}
- * char *str = calloc(100, sizeof(char));
- * strcpy(str, "This are a test.");
+ * size_t str_maxlen = 100;
+ * char *str = calloc(str_maxlen, sizeof(char));
+ * strncpy(str, "This are a test.", str_maxlen - 1);
* if (replace_text(str, "are", "is")) {
* fprintf(stderr, "string replacement failed\n");
* exit(1);
@@ -85,6 +86,7 @@ int replace_text(char *original, const char *target, const char *replacement, un
}
// replace original with contents of buffer
strncpy(original, buffer, buffer_len + 1);
+ original[buffer_len] = '\0';
return 0;
}
diff --git a/src/lib/core/str.c b/src/lib/core/str.c
index 368ab49..a08bd2b 100644
--- a/src/lib/core/str.c
+++ b/src/lib/core/str.c
@@ -63,6 +63,7 @@ void strchrdel(char *sptr, const char *chars) {
for (size_t i = 0; i < strlen(chars); i++) {
char ch[2] = {0};
strncpy(ch, &chars[i], 1);
+ ch[sizeof(ch) - 1] = '\0';
replace_text(sptr, ch, "", 0);
}
}
@@ -105,7 +106,7 @@ char** split(char *_sptr, const char* delim, size_t max)
// Separate the string into individual parts and store them in the result array
char *token = NULL;
char *sptr_tmp = sptr;
- size_t pos = 0;
+ ptrdiff_t pos = 0;
size_t i;
for (i = 0; (token = strsep(&sptr_tmp, delim)) != NULL; i++) {
// When max is zero, record all tokens
@@ -120,6 +121,7 @@ char** split(char *_sptr, const char* delim, size_t max)
return NULL;
}
strncpy(result[i], token, STASIS_BUFSIZ - 1);
+ result[i][STASIS_BUFSIZ - 1] = '\0';
}
// pos is non-zero when maximum split is reached
@@ -130,6 +132,7 @@ char** split(char *_sptr, const char* delim, size_t max)
return NULL;
}
strncpy(result[i], &orig[pos], STASIS_BUFSIZ - 1);
+ result[i][STASIS_BUFSIZ - 1] = '\0';
}
guard_free(sptr);
@@ -562,7 +565,10 @@ char *normalize_space(char *s) {
}
// Rewrite the input string
- strncpy(result, tmp_orig, strlen(result) + 1);
+ const size_t result_len = strlen(result) + 1;
+ strncpy(result, tmp_orig, result_len);
+ result[result_len] = '\0';
+
guard_free(tmp_orig);
return result;
}
@@ -581,8 +587,16 @@ char **strdup_array(char **array) {
// Create new array
result = calloc(elems + 1, sizeof(*result));
+ if (!result) {
+ SYSERROR("%s", "could not allocate memory for result array");
+ return NULL;
+ }
for (size_t i = 0; i < elems; i++) {
result[i] = strdup(array[i]);
+ if (!result[i]) {
+ guard_array_free(result);
+ break;
+ }
}
return result;
diff --git a/src/lib/core/strlist.c b/src/lib/core/strlist.c
index ff9c098..42d5b85 100644
--- a/src/lib/core/strlist.c
+++ b/src/lib/core/strlist.c
@@ -4,6 +4,10 @@
*/
#include "download.h"
#include "strlist.h"
+
+#include <float.h>
+#include <math.h>
+
#include "utils.h"
/**
@@ -85,6 +89,8 @@ int strlist_append_file(struct StrList *pStrList, char *_path, ReaderFn *readerF
int fd;
char tempfile[PATH_MAX] = {0};
strncpy(tempfile, "/tmp/.remote_file.XXXXXX", sizeof(tempfile) - 1);
+ tempfile[sizeof(tempfile) - 1] = '\0';
+
if ((fd = mkstemp(tempfile)) < 0) {
retval = -1;
goto fatal;
@@ -420,8 +426,10 @@ void strlist_set(struct StrList **pStrList, size_t index, char *value) {
(*pStrList)->data[index] = tmp;
}
- memset((*pStrList)->data[index], '\0', strlen(value) + 1);
- strncpy((*pStrList)->data[index], value, strlen(value));
+ const size_t len = strlen(value) + 1;
+ memset((*pStrList)->data[index], '\0', len);
+ strncpy((*pStrList)->data[index], value, len);
+ (*pStrList)->data[index][len] = '\0';
}
}
@@ -671,8 +679,8 @@ float strlist_item_as_float(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- float result = (float) strtof(strlist_item(pStrList, index), &error_p);
- if (!result && error_p && *error_p != 0) {
+ const float result = strtof(strlist_item(pStrList, index), &error_p);
+ if ((result == FLT_MIN || result == HUGE_VALF) && errno == ERANGE) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
}
@@ -690,8 +698,8 @@ double strlist_item_as_double(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- double result = (double) strtod(strlist_item(pStrList, index), &error_p);
- if (!result && error_p && *error_p != 0) {
+ const double result = strtod(strlist_item(pStrList, index), &error_p);
+ if ((result == DBL_MIN || result == HUGE_VAL) && errno == ERANGE) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
}
@@ -709,8 +717,8 @@ long double strlist_item_as_long_double(struct StrList *pStrList, size_t index)
char *error_p;
strlist_clear_error();
- long double result = (long double) strtold(strlist_item(pStrList, index), &error_p);
- if (!result && error_p && *error_p != 0) {
+ const long double result = strtold(strlist_item(pStrList, index), &error_p);
+ if ((result == DBL_MIN || result == HUGE_VALL) && errno == ERANGE) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
}
diff --git a/src/lib/core/system.c b/src/lib/core/system.c
index 5b47a62..06ca7bf 100644
--- a/src/lib/core/system.c
+++ b/src/lib/core/system.c
@@ -80,7 +80,6 @@ int shell(struct Process *proc, char *args) {
fclose(fp_err);
_exit(1);
}
- fclose(fp_err);
} else {
// redirect stderr to stdout
if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) {
@@ -179,9 +178,8 @@ char *shell_output(const char *command, int *status) {
char *tmp = realloc(result, sizeof(*result) * current_size);
if (!tmp) {
return NULL;
- } else if (tmp != result) {
- result = tmp;
}
+ result = tmp;
}
strncat(result, line, current_size - strlen(result) - 1);
memset(line, 0, sizeof(line));
diff --git a/src/lib/core/template.c b/src/lib/core/template.c
index 3a1b759..3b6f58d 100644
--- a/src/lib/core/template.c
+++ b/src/lib/core/template.c
@@ -98,7 +98,7 @@ void tpl_register(char *key, char **ptr) {
item->ptr = ptr;
if (!replacing) {
- SYSDEBUG("Registered tpl_item at index %u:\n\tkey=%s\n\tptr=%s", tpl_pool_used, item->key, *item->ptr);
+ SYSDEBUG("Registered tpl_item at index %u:\n\tkey=%s\n\tptr=%s", tpl_pool_used, item->key, *item->ptr ? *item->ptr : "NULL");
tpl_pool[tpl_pool_used] = item;
tpl_pool_used++;
}
@@ -236,6 +236,8 @@ char *tpl_render(char *str) {
} else if (do_func) { // {{ func:NAME(a, ...) }}
char func_name_temp[STASIS_NAME_MAX] = {0};
strncpy(func_name_temp, type_stop + 1, sizeof(func_name_temp) - 1);
+ func_name_temp[sizeof(func_name_temp) - 1] = '\0';
+
char *param_begin = strchr(func_name_temp, '(');
if (!param_begin) {
fprintf(stderr, "At position %zu in %s\nfunction name must be followed by a '('\n", off, key);
diff --git a/src/lib/core/template_func_proto.c b/src/lib/core/template_func_proto.c
index fc58e33..f28a1eb 100644
--- a/src/lib/core/template_func_proto.c
+++ b/src/lib/core/template_func_proto.c
@@ -81,6 +81,8 @@ int get_junitxml_file_entrypoint(void *frame, void *data_out) {
}
char nametmp[PATH_MAX] = {0};
strncpy(nametmp, cwd, sizeof(nametmp) - 1);
+ nametmp[sizeof(nametmp) - 1] = '\0';
+
char *name = path_basename(nametmp);
*output = calloc(PATH_MAX, sizeof(**output));
@@ -106,6 +108,7 @@ int get_basetemp_dir_entrypoint(void *frame, void *data_out) {
}
char nametmp[PATH_MAX] = {0};
strncpy(nametmp, cwd, sizeof(nametmp) - 1);
+ nametmp[sizeof(nametmp) - 1] = '\0';
char *name = path_basename(nametmp);
*output = calloc(PATH_MAX, sizeof(**output));
diff --git a/src/lib/core/utils.c b/src/lib/core/utils.c
index 2b7f0ec..90dac1d 100644
--- a/src/lib/core/utils.c
+++ b/src/lib/core/utils.c
@@ -35,9 +35,11 @@ int popd() {
int rmtree(char *_path) {
int status = 0;
char path[PATH_MAX] = {0};
- strncpy(path, _path, sizeof(path) - 1);
struct dirent *d_entity;
+ strncpy(path, _path, sizeof(path) - 1);
+ path[sizeof(path) - 1] = '\0';
+
DIR *dir = opendir(path);
if (!dir) {
return 1;
@@ -106,6 +108,7 @@ char *expandpath(const char *_path) {
char *tmphome;
if ((tmphome = getenv(homes[i])) != NULL) {
strncpy(home, tmphome, PATH_MAX - 1);
+ home[PATH_MAX - 1] = '\0';
break;
}
}
@@ -285,6 +288,7 @@ char *find_program(const char *name) {
continue;
}
strncpy(result, abspath, sizeof(result) - 1);
+ result[sizeof(result) - 1] = '\0';
break;
}
path = path_orig;
@@ -451,6 +455,7 @@ void msg(unsigned type, char *fmt, ...) {
fprintf(stream, "%s", STASIS_COLOR_GREEN);
strncpy(status, " ", sizeof(status) - 1);
}
+ status[sizeof(status) - 1] = '\0';
if (type & STASIS_MSG_L1) {
snprintf(header, sizeof(header), "==>%s" STASIS_COLOR_RESET STASIS_COLOR_WHITE, status);
@@ -496,8 +501,15 @@ char *xmkstemp(FILE **fp, const char *mode) {
if (globals.tmpdir) {
strncpy(tmpdir, globals.tmpdir, sizeof(tmpdir) - 1);
} else {
- strncpy(tmpdir, "/tmp", sizeof(tmpdir) - 1);
+ strncpy(tmpdir, "/tmp/stasis", sizeof(tmpdir) - 1);
}
+ tmpdir[sizeof(tmpdir) - 1] = '\0';
+
+ if (mkdirs(tmpdir, 0700) < 0) {
+ SYSERROR("unable to create sub-directories in %s", tmpdir);
+ return NULL;
+ }
+
memset(t_name, 0, sizeof(t_name));
snprintf(t_name, sizeof(t_name), "%s/%s", tmpdir, "STASIS.XXXXXX");
@@ -658,6 +670,7 @@ int fix_tox_conf(const char *filename, char **result, size_t maxlen) {
// Create new temporary tox configuration file
char *tempfile = xmkstemp(&fptemp, "w+");
if (!tempfile) {
+ SYSERROR("%s", "unable to create temporary file");
return -1;
}
@@ -722,6 +735,7 @@ int fix_tox_conf(const char *filename, char **result, size_t maxlen) {
// Store path to modified config
strncpy(*result, tempfile, maxlen - 1);
+ (*result)[maxlen - 1] = '\0';
guard_free(tempfile);
ini_free(&toxini);
@@ -766,11 +780,12 @@ char *collapse_whitespace(char **s) {
int redact_sensitive(const char **to_redact, size_t to_redact_size, char *src, char *dest, size_t maxlen) {
const char *redacted = "***REDACTED***";
- char *tmp = calloc(strlen(redacted) + strlen(src) + 1, sizeof(*tmp));
+ char *tmp = calloc(maxlen + 1, sizeof(*tmp));
if (!tmp) {
return -1;
}
- strncpy(tmp, src, strlen(redacted) + strlen(src));
+ strncpy(tmp, src, maxlen);
+ tmp[maxlen] = '\0';
for (size_t i = 0; i < to_redact_size; i++) {
if (to_redact[i] && strstr(tmp, to_redact[i])) {
@@ -780,7 +795,8 @@ int redact_sensitive(const char **to_redact, size_t to_redact_size, char *src, c
}
memset(dest, 0, maxlen);
- strncpy(dest, tmp, maxlen - 1);
+ strncpy(dest, tmp, maxlen);
+ dest[maxlen] = '\0';
guard_free(tmp);
return 0;
@@ -834,6 +850,7 @@ int mkdirs(const char *_path, mode_t mode) {
char *token;
char pathbuf[PATH_MAX] = {0};
strncpy(pathbuf, _path, sizeof(pathbuf) - 1);
+ pathbuf[sizeof(pathbuf) - 1] = '\0';
char *path = pathbuf;
errno = 0;
diff --git a/src/lib/core/wheel.c b/src/lib/core/wheel.c
index 0bc4209..9f3b3c8 100644
--- a/src/lib/core/wheel.c
+++ b/src/lib/core/wheel.c
@@ -69,9 +69,15 @@ static ssize_t wheel_parse_wheel(struct Wheel * pkg, const char * data) {
char **pair = split(line, ":", 1);
if (pair) {
char *key = strdup(strip(pair[0]));
- char *value = strdup(lstrip(pair[1]));
+ if (!key) {
+ SYSERROR("%s", "could not allocate memory for pair wheel key");
+ return -1;
+ }
- if (!key || !value) {
+ char *value = strdup(lstrip(pair[1]));
+ if (!value) {
+ SYSERROR("%s", "could not allocate memory for wheel value");
+ guard_free(key);
return -1;
}
@@ -90,6 +96,8 @@ static ssize_t wheel_parse_wheel(struct Wheel * pkg, const char * data) {
pkg->wheel_version = strdup(value);
if (!pkg->wheel_version) {
// memory error
+ guard_free(key);
+ guard_free(value);
wheel_package_free(&pkg);
return -1;
}
@@ -99,6 +107,8 @@ static ssize_t wheel_parse_wheel(struct Wheel * pkg, const char * data) {
pkg->generator = strdup(value);
if (!pkg->generator) {
// memory error
+ guard_free(key);
+ guard_free(value);
wheel_package_free(&pkg);
return -1;
}
@@ -108,6 +118,8 @@ static ssize_t wheel_parse_wheel(struct Wheel * pkg, const char * data) {
pkg->root_is_pure_lib = strdup(value);
if (!pkg->root_is_pure_lib) {
// memory error
+ guard_free(key);
+ guard_free(value);
wheel_package_free(&pkg);
return -1;
}
@@ -117,6 +129,8 @@ static ssize_t wheel_parse_wheel(struct Wheel * pkg, const char * data) {
if (!pkg->tag) {
pkg->tag = strlist_init();
if (!pkg->tag) {
+ guard_free(key);
+ guard_free(value);
wheel_package_free(&pkg);
return -1;
}
diff --git a/src/lib/core/wheelinfo.c b/src/lib/core/wheelinfo.c
index ce8ea74..9d8a6af 100644
--- a/src/lib/core/wheelinfo.c
+++ b/src/lib/core/wheelinfo.c
@@ -7,6 +7,7 @@ struct WheelInfo *wheelinfo_get(const char *basepath, const char *name, char *to
char package_name[NAME_MAX];
strncpy(package_name, name, sizeof(package_name) - 1);
+ package_name[sizeof(package_name) - 1] = '\0';
tolower_s(package_name);
snprintf(package_path, sizeof(package_path), "%s/%s", basepath, package_name);
@@ -19,8 +20,11 @@ struct WheelInfo *wheelinfo_get(const char *basepath, const char *name, char *to
if (!strcmp(rec->d_name, ".") || !strcmp(rec->d_name, "..")) {
continue;
}
+
char filename[NAME_MAX];
strncpy(filename, rec->d_name, sizeof(filename) - 1);
+ filename[sizeof(filename) - 1] = '\0';
+
char *ext = strstr(filename, ".whl");
if (ext) {
*ext = '\0';
diff --git a/src/lib/delivery/delivery.c b/src/lib/delivery/delivery.c
index 5403743..45b3b35 100644
--- a/src/lib/delivery/delivery.c
+++ b/src/lib/delivery/delivery.c
@@ -312,13 +312,13 @@ int delivery_format_str(struct Delivery *ctx, char **dest, size_t maxlen, const
strncat(*dest, ctx->meta.mission, maxlen - 1);
break;
case 'r': // revision
- snprintf(*dest + strlen(*dest), maxlen, "%d", ctx->meta.rc);
+ snprintf(*dest + strlen(*dest), maxlen - strlen(*dest), "%d", ctx->meta.rc);
break;
case 'R': // "final"-aware revision
if (ctx->meta.final)
strncat(*dest, "final", maxlen);
else
- snprintf(*dest + strlen(*dest), maxlen, "%d", ctx->meta.rc);
+ snprintf(*dest + strlen(*dest), maxlen - strlen(*dest), "%d", ctx->meta.rc);
break;
case 'v': // version
strncat(*dest, ctx->meta.version, maxlen - 1);
@@ -336,14 +336,14 @@ int delivery_format_str(struct Delivery *ctx, char **dest, size_t maxlen, const
strncat(*dest, ctx->system.platform[DELIVERY_PLATFORM_RELEASE], maxlen - 1);
break;
case 't': // unix epoch
- snprintf(*dest + strlen(*dest), maxlen, "%ld", ctx->info.time_now);
+ snprintf(*dest + strlen(*dest), maxlen - strlen(*dest), "%ld", ctx->info.time_now);
break;
default: // unknown formatter, write as-is
- snprintf(*dest + strlen(*dest), maxlen, "%c%c", fmt[i - 1], fmt[i]);
+ snprintf(*dest + strlen(*dest), maxlen - strlen(*dest), "%c%c", fmt[i - 1], fmt[i]);
break;
}
} else { // write non-format text
- snprintf(*dest + strlen(*dest), maxlen, "%c", fmt[i]);
+ snprintf(*dest + strlen(*dest), maxlen - strlen(*dest), "%c", fmt[i]);
}
}
return 0;
@@ -367,6 +367,8 @@ void delivery_defer_packages(struct Delivery *ctx, int type) {
SYSERROR("BUG: type %d does not map to a supported package manager!\n", type);
exit(1);
}
+ mode[sizeof(mode) - 1] = '\0';
+
msg(STASIS_MSG_L2, "Filtering %s packages by test definition...\n", mode);
struct StrList *filtered = NULL;
@@ -391,8 +393,10 @@ void delivery_defer_packages(struct Delivery *ctx, int type) {
spec_end++;
}
strncpy(package_name, name, spec_begin - name);
+ package_name[spec_begin - name] = '\0';
} else {
strncpy(package_name, name, sizeof(package_name) - 1);
+ package_name[sizeof(package_name) - 1] = '\0';
}
remove_extras(package_name);
@@ -404,6 +408,8 @@ void delivery_defer_packages(struct Delivery *ctx, int type) {
char nametmp[STASIS_NAME_MAX] = {0};
strncpy(nametmp, package_name, sizeof(nametmp) - 1);
+ nametmp[sizeof(nametmp) - 1] = '\0';
+
// Is the [test:NAME] in the package name?
if (!strcmp(nametmp, test->name)) {
// Override test->version when a version is provided by the (pip|conda)_package list item
@@ -447,9 +453,9 @@ void delivery_defer_packages(struct Delivery *ctx, int type) {
int upstream_exists = 0;
if (DEFER_PIP == type) {
- upstream_exists = pkg_index_provides(PKG_USE_PIP, PYPI_INDEX_DEFAULT, name);
+ upstream_exists = pkg_index_provides(PKG_USE_PIP, PYPI_INDEX_DEFAULT, name, ctx->storage.tmpdir);
} else if (DEFER_CONDA == type) {
- upstream_exists = pkg_index_provides(PKG_USE_CONDA, NULL, name);
+ upstream_exists = pkg_index_provides(PKG_USE_CONDA, NULL, name, ctx->storage.tmpdir);
}
if (PKG_INDEX_PROVIDES_FAILED(upstream_exists)) {
diff --git a/src/lib/delivery/delivery_build.c b/src/lib/delivery/delivery_build.c
index 3ff5df7..49d2f5b 100644
--- a/src/lib/delivery/delivery_build.c
+++ b/src/lib/delivery/delivery_build.c
@@ -34,10 +34,11 @@ int delivery_build_recipes(struct Delivery *ctx) {
tag[len] = '\0';
} else {
strncpy(tag, ctx->tests->test[i]->repository_info_tag, sizeof(tag) - 1);
- tag[strlen(ctx->tests->test[i]->repository_info_tag)] = '\0';
+ tag[sizeof(tag) - 1] = '\0';
}
} else {
strncpy(tag, ctx->tests->test[i]->version, sizeof(tag) - 1);
+ tag[sizeof(tag) - 1] = '\0';
}
//sprintf(recipe_version, "{%% set version = GIT_DESCRIBE_TAG ~ \".dev\" ~ GIT_DESCRIBE_NUMBER ~ \"+\" ~ GIT_DESCRIBE_HASH %%}");
@@ -51,6 +52,7 @@ int delivery_build_recipes(struct Delivery *ctx) {
snprintf(recipe_version, sizeof(recipe_version), "{%% set version = \"%s\" %%}", tag);
snprintf(recipe_git_url, sizeof(recipe_git_url), " url: %s/archive/refs/tags/{{ version }}.tar.gz", ctx->tests->test[i]->repository);
strncpy(recipe_git_rev, "", sizeof(recipe_git_rev) - 1);
+ recipe_git_rev[sizeof(recipe_git_rev) - 1] = '\0';
snprintf(recipe_buildno, sizeof(recipe_buildno), " number: 0");
unsigned flags = REPLACE_TRUNCATE_AFTER_MATCH;
@@ -79,14 +81,17 @@ int delivery_build_recipes(struct Delivery *ctx) {
memset(platform, 0, sizeof(platform));
strncpy(platform, "osx", sizeof(platform) - 1);
}
+ platform[sizeof(platform) - 1] = '\0';
tolower_s(platform);
+
if (strstr(ctx->system.arch, "arm64")) {
strncpy(arch, "arm64", sizeof(arch) - 1);
} else if (strstr(ctx->system.arch, "64")) {
strncpy(arch, "64", sizeof(arch) - 1);
} else {
- strncat(arch, "32", sizeof(arch) - 1); // blind guess
+ strncat(arch, "32", sizeof(arch) - strlen(arch) - 1); // blind guess
}
+ arch[sizeof(arch) - 1] = '\0';
tolower_s(arch);
snprintf(command, sizeof(command), "mambabuild --python=%s -m ../.ci_support/%s_%s_.yaml .",
@@ -385,6 +390,7 @@ struct StrList *delivery_build_wheels(struct Delivery *ctx) {
char name[100] = {0};
char *fullspec = strlist_item(ctx->conda.pip_packages_defer, p);
strncpy(name, fullspec, sizeof(name) - 1);
+ name[sizeof(name) - 1] = '\0';
remove_extras(name);
char *spec = find_version_spec(name);
if (spec) {
@@ -435,6 +441,7 @@ struct StrList *delivery_build_wheels(struct Delivery *ctx) {
}
strncpy(dname, ctx->tests->test[i]->name, sizeof(dname) - 1);
+ dname[sizeof(dname) - 1] = '\0';
tolower_s(dname);
snprintf(outdir, sizeof(outdir), "%s/%s", ctx->storage.wheel_artifact_dir, dname);
if (mkdirs(outdir, 0755)) {
diff --git a/src/lib/delivery/delivery_docker.c b/src/lib/delivery/delivery_docker.c
index 1178a8c..3177c96 100644
--- a/src/lib/delivery/delivery_docker.c
+++ b/src/lib/delivery/delivery_docker.c
@@ -45,6 +45,7 @@ int delivery_docker(struct Delivery *ctx) {
for (size_t i = 0; i < total_tags; i++) {
char *tag_orig = strlist_item(ctx->deploy.docker.tags, i);
strncpy(tag, tag_orig, sizeof(tag) - 1);
+ tag[sizeof(tag) - 1] = '\0';
docker_sanitize_tag(tag);
snprintf(args + strlen(args), sizeof(args) - strlen(args), " -t \"%s\" ", tag);
}
@@ -103,6 +104,7 @@ int delivery_docker(struct Delivery *ctx) {
// All tags point back to the same image so test the first one we see
// regardless of how many are defined
strncpy(tag, strlist_item(ctx->deploy.docker.tags, 0), sizeof(tag) - 1);
+ tag[sizeof(tag) - 1] = '\0';
docker_sanitize_tag(tag);
msg(STASIS_MSG_L2, "Executing image test script for %s\n", tag);
diff --git a/src/lib/delivery/delivery_export.c b/src/lib/delivery/delivery_export.c
index c12a365..e67fdfb 100644
--- a/src/lib/delivery/delivery_export.c
+++ b/src/lib/delivery/delivery_export.c
@@ -2,26 +2,44 @@
static void delivery_export_configuration(const struct Delivery *ctx) {
msg(STASIS_MSG_L2, "Exporting delivery configuration\n");
+
+ SYSDEBUG("Entering configuration directory: %s", ctx->storage.delivery_dir);
if (!pushd(ctx->storage.cfgdump_dir)) {
char filename[PATH_MAX] = {0};
+ SYSDEBUG("%s", "Populating filename");
snprintf(filename, sizeof(filename), "%s.ini", ctx->info.release_name);
+ SYSDEBUG("filename: %s", filename);
+
+ SYSDEBUG("%s: opening", filename);
FILE *spec = fopen(filename, "w+");
if (!spec) {
msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "failed %s\n", filename);
exit(1);
}
+ SYSDEBUG("%s: writing", filename);
ini_write(ctx->_stasis_ini_fp.delivery, &spec, INI_WRITE_RAW);
+ SYSDEBUG("%s: writing done", filename);
fclose(spec);
+ SYSDEBUG("%s: closing", filename);
+ SYSDEBUG("%s", "Zeroing filename");
memset(filename, 0, sizeof(filename));
+ SYSDEBUG("%s", "Populating rendered filename");
snprintf(filename, sizeof(filename), "%s-rendered.ini", ctx->info.release_name);
+ SYSDEBUG("filename: %s", filename);
+
+ SYSDEBUG("%s: opening", filename);
spec = fopen(filename, "w+");
if (!spec) {
msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "failed %s\n", filename);
exit(1);
}
+ SYSDEBUG("%s: writing", filename);
ini_write(ctx->_stasis_ini_fp.delivery, &spec, INI_WRITE_PRESERVE);
+ SYSDEBUG("%s: writing done", filename);
+ SYSDEBUG("%s: closing", filename);
fclose(spec);
+ SYSDEBUG("Returning from %s", ctx->storage.cfgdump_dir);
popd();
} else {
SYSERROR("Failed to enter directory: %s", ctx->storage.delivery_dir);
diff --git a/src/lib/delivery/delivery_init.c b/src/lib/delivery/delivery_init.c
index ff877f0..ec05a0f 100644
--- a/src/lib/delivery/delivery_init.c
+++ b/src/lib/delivery/delivery_init.c
@@ -11,23 +11,43 @@ int has_mount_flags(const char *mount_point, const unsigned long flags) {
int delivery_init_tmpdir(struct Delivery *ctx) {
char *tmpdir = NULL;
- char *x = NULL;
- int unusable = 0;
+ int unusable = 1;
errno = 0;
- x = getenv("TMPDIR");
+ //int need_setenv = 0;
+ const char *x = getenv("TMPDIR");
if (x) {
guard_free(ctx->storage.tmpdir);
tmpdir = strdup(x);
+ if (!tmpdir) {
+ // memory error
+ SYSERROR("%s", "unable to allocate tmpdir");
+ goto l_delivery_init_tmpdir_fatal;
+ }
} else {
- tmpdir = ctx->storage.tmpdir;
+ tmpdir = strdup("/tmp/stasis");
+ if (!tmpdir) {
+ SYSERROR("%s", "unable to allocate tmpdir");
+ goto l_delivery_init_tmpdir_fatal;
+ }
+ //need_setenv = 1;
}
- if (!tmpdir) {
- // memory error
- return -1;
+ if (!ctx->storage.tmpdir) {
+ ctx->storage.tmpdir = strdup(tmpdir);
+ if (!ctx->storage.tmpdir) {
+ SYSERROR("%s", "unable to allocate ctx->storage.tmpdir");
+ goto l_delivery_init_tmpdir_fatal;
+ }
+ } else {
+ // we already have a temp directory to use
+ guard_free(tmpdir);
+ tmpdir = strdup(ctx->storage.tmpdir);
+ if (!tmpdir) {
+ SYSERROR("%s", "unable to allocate tmpdir");
+ goto l_delivery_init_tmpdir_fatal;
+ }
}
-
// If the directory doesn't exist, create it
if (access(tmpdir, F_OK) < 0) {
if (mkdirs(tmpdir, 0755) < 0) {
@@ -59,17 +79,29 @@ int delivery_init_tmpdir(struct Delivery *ctx) {
goto l_delivery_init_tmpdir_fatal;
}
- if (!globals.tmpdir) {
+ if (!globals.tmpdir || strcmp(globals.tmpdir, ctx->storage.tmpdir) != 0) {
globals.tmpdir = strdup(tmpdir);
+ if (!globals.tmpdir) {
+ SYSERROR("%s", "unable to allocate globals.tmpdir");
+ goto l_delivery_init_tmpdir_fatal;
+ }
}
if (!ctx->storage.tmpdir) {
ctx->storage.tmpdir = strdup(globals.tmpdir);
+ if (!ctx->storage.tmpdir) {
+ SYSERROR("%s", "unable to allocate globals.tmpdir");
+ goto l_delivery_init_tmpdir_fatal;
+ }
}
- return unusable;
+ unusable = 0;
+ // TODO: Figure out why this breaks EVERYTHING
+ //if (need_setenv) {
+ // setenv("TMPDIR", ctx->storage.tmpdir, 1);
+ //}
l_delivery_init_tmpdir_fatal:
- unusable = 1;
+ guard_free(tmpdir);
return unusable;
}
@@ -178,22 +210,30 @@ int delivery_init_platform(struct Delivery *ctx) {
} else {
strncpy(archsuffix, ctx->system.arch, sizeof(archsuffix) - 1);
}
+ archsuffix[sizeof(archsuffix) - 1] = '\0';
SYSDEBUG("%s", "Setting platform");
strncpy(ctx->system.platform[DELIVERY_PLATFORM], uts.sysname, DELIVERY_PLATFORM_MAXLEN - 1);
if (!strcmp(ctx->system.platform[DELIVERY_PLATFORM], "Darwin")) {
snprintf(ctx->system.platform[DELIVERY_PLATFORM_CONDA_SUBDIR], DELIVERY_PLATFORM_MAXLEN, "osx-%s", archsuffix);
strncpy(ctx->system.platform[DELIVERY_PLATFORM_CONDA_INSTALLER], "MacOSX", DELIVERY_PLATFORM_MAXLEN - 1);
+ ctx->system.platform[DELIVERY_PLATFORM_CONDA_INSTALLER][DELIVERY_PLATFORM_MAXLEN - 1] = '\0';
strncpy(ctx->system.platform[DELIVERY_PLATFORM_RELEASE], "macos", DELIVERY_PLATFORM_MAXLEN - 1);
+ ctx->system.platform[DELIVERY_PLATFORM_RELEASE][DELIVERY_PLATFORM_MAXLEN - 1] = '\0';
} else if (!strcmp(ctx->system.platform[DELIVERY_PLATFORM], "Linux")) {
snprintf(ctx->system.platform[DELIVERY_PLATFORM_CONDA_SUBDIR], DELIVERY_PLATFORM_MAXLEN, "linux-%s", archsuffix);
strncpy(ctx->system.platform[DELIVERY_PLATFORM_CONDA_INSTALLER], "Linux", DELIVERY_PLATFORM_MAXLEN - 1);
+ ctx->system.platform[DELIVERY_PLATFORM_CONDA_INSTALLER][DELIVERY_PLATFORM_MAXLEN - 1] = '\0';
strncpy(ctx->system.platform[DELIVERY_PLATFORM_RELEASE], "linux", DELIVERY_PLATFORM_MAXLEN - 1);
+ ctx->system.platform[DELIVERY_PLATFORM_RELEASE][DELIVERY_PLATFORM_MAXLEN - 1] = '\0';
} else {
// Not explicitly supported systems
strncpy(ctx->system.platform[DELIVERY_PLATFORM_CONDA_SUBDIR], ctx->system.platform[DELIVERY_PLATFORM], DELIVERY_PLATFORM_MAXLEN - 1);
+ ctx->system.platform[DELIVERY_PLATFORM_CONDA_SUBDIR][DELIVERY_PLATFORM_MAXLEN - 1] = '\0';
strncpy(ctx->system.platform[DELIVERY_PLATFORM_CONDA_INSTALLER], ctx->system.platform[DELIVERY_PLATFORM], DELIVERY_PLATFORM_MAXLEN - 1);
+ ctx->system.platform[DELIVERY_PLATFORM_CONDA_INSTALLER][DELIVERY_PLATFORM_MAXLEN - 1] = '\0';
strncpy(ctx->system.platform[DELIVERY_PLATFORM_RELEASE], ctx->system.platform[DELIVERY_PLATFORM], DELIVERY_PLATFORM_MAXLEN - 1);
+ ctx->system.platform[DELIVERY_PLATFORM_RELEASE][DELIVERY_PLATFORM_MAXLEN - 1] = '\0';
tolower_s(ctx->system.platform[DELIVERY_PLATFORM_RELEASE]);
}
diff --git a/src/lib/delivery/delivery_install.c b/src/lib/delivery/delivery_install.c
index 22b3752..3d54eaa 100644
--- a/src/lib/delivery/delivery_install.c
+++ b/src/lib/delivery/delivery_install.c
@@ -32,8 +32,10 @@ static char *have_spec_in_config(const struct Delivery *ctx, const char *name) {
char package[255] = {0};
if (op) {
strncpy(package, config_spec, op - config_spec);
+ package[op - config_spec] = '\0';
} else {
strncpy(package, config_spec, sizeof(package) - 1);
+ package[sizeof(package) - 1] = '\0';
}
remove_extras(package);
if (strncmp(package, name, strlen(name)) == 0) {
@@ -81,8 +83,10 @@ int delivery_overlay_packages_from_env(struct Delivery *ctx, const char *env_nam
char *op = find_version_spec(spec);
if (op) {
strncpy(spec_name, spec, op - spec);
+ spec_name[op - spec] = '\0';
} else {
strncpy(spec_name, spec, sizeof(spec_name) - 1);
+ spec_name[sizeof(spec_name) - 1] = '\0';
}
struct Test *test_block = requirement_from_test(ctx, spec_name);
@@ -102,8 +106,10 @@ int delivery_overlay_packages_from_env(struct Delivery *ctx, const char *env_nam
// we only care about packages with specs here. if something else arrives, ignore it
if (op) {
strncpy(frozen_name, frozen_spec, op - frozen_spec);
+ frozen_name[op - frozen_spec] = '\0';
} else {
strncpy(frozen_name, frozen_spec, sizeof(frozen_name) - 1);
+ frozen_name[sizeof(frozen_name) - 1] = '\0';
}
struct Test *test = requirement_from_test(ctx, frozen_name);
if (test && strcmp(test->name, frozen_name) == 0) {
@@ -151,15 +157,19 @@ int delivery_purge_packages(struct Delivery *ctx, const char *env_name, int use_
fn = conda_exec;
list = ctx->conda.conda_packages_purge;
strncpy(package_manager, "conda", sizeof(package_manager) - 1);
+ package_manager[sizeof(package_manager) - 1] = '\0';
// conda is already configured for "always_yes"
strncpy(subcommand, "remove", sizeof(subcommand) - 1);
+ subcommand[sizeof(subcommand) - 1] = '\0';
break;
case PKG_USE_PIP:
fn = pip_exec;
list = ctx->conda.pip_packages_purge;
strncpy(package_manager, "pip", sizeof(package_manager) - 1);
+ package_manager[sizeof(package_manager) - 1] = '\0';
// avoid user prompt to remove packages
strncpy(subcommand, "uninstall -y", sizeof(subcommand) - 1);
+ subcommand[sizeof(subcommand) - 1] = '\0';
break;
default:
SYSERROR("Unknown package manager: %d", use_pkg_manager);
@@ -300,8 +310,10 @@ int delivery_install_packages(struct Delivery *ctx, char *conda_install_dir, cha
char req[255] = {0};
if (!strcmp(name, info->name)) {
strncpy(req, info->name, sizeof(req) - 1);
+ req[sizeof(req) - 1] = '\0';
} else {
strncpy(req, name, sizeof(req) - 1);
+ req[sizeof(req) - 1] = '\0';
char *spec = find_version_spec(req);
if (spec) {
*spec = 0;
diff --git a/src/lib/delivery/delivery_postprocess.c b/src/lib/delivery/delivery_postprocess.c
index 95bcc0a..3ff1d56 100644
--- a/src/lib/delivery/delivery_postprocess.c
+++ b/src/lib/delivery/delivery_postprocess.c
@@ -243,6 +243,7 @@ int delivery_index_wheel_artifacts(struct Delivery *ctx) {
FILE *bottom_fp = fopen(bottom_index, "w+");
if (!bottom_fp) {
closedir(dp);
+ fclose(top_fp);
return -3;
}
diff --git a/src/lib/delivery/delivery_test.c b/src/lib/delivery/delivery_test.c
index a088cd7..5d5a3e8 100644
--- a/src/lib/delivery/delivery_test.c
+++ b/src/lib/delivery/delivery_test.c
@@ -201,6 +201,7 @@ void delivery_tests_run(struct Delivery *ctx) {
memset(&proc, 0, sizeof(proc));
strncpy(cmd, test->script, strlen(test->script) + STASIS_BUFSIZ - 1);
+ cmd[strlen(test->script) + STASIS_BUFSIZ - 1] = '\0';
char *cmd_rendered = tpl_render(cmd);
if (cmd_rendered) {
if (strcmp(cmd_rendered, cmd) != 0) {
@@ -230,6 +231,7 @@ void delivery_tests_run(struct Delivery *ctx) {
selected = SERIAL;
memset(pool_name, 0, sizeof(pool_name));
strncpy(pool_name, "serial", sizeof(pool_name) - 1);
+ pool_name[sizeof(pool_name) - 1] = '\0';
}
if (asprintf(&runner_cmd, runner_cmd_fmt, cmd) < 0) {
@@ -281,11 +283,13 @@ void delivery_tests_run(struct Delivery *ctx) {
}
strncpy(cmd, test->script_setup, cmd_len - 1);
+ cmd[cmd_len - 1] = '\0';
+
char *cmd_rendered = tpl_render(cmd);
if (cmd_rendered) {
if (strcmp(cmd_rendered, cmd) != 0) {
strncpy(cmd, cmd_rendered, cmd_len - 1);
- cmd[strlen(cmd_rendered) ? strlen(cmd_rendered) - 1 : 0] = 0;
+ cmd[strlen(cmd_rendered) ? strlen(cmd_rendered) - 1 : 0] = '\0';
}
guard_free(cmd_rendered);
} else {
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index dd68231..26c4250 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -17,7 +17,10 @@ if (BASH_PROGRAM AND TESTS_RT)
file(REAL_PATH ${rt_file} rt_name)
string(REGEX REPLACE ${ext_pattern} "" rt_name ${rt_file})
add_test (${rt_name} ${BASH_PROGRAM} ${rt_file})
- endforeach()
+ set_property(TEST ${rt_name}
+ PROPERTY ENVIRONMENT "GIT_CEILING_DIRECTORIES=${CMAKE_BINARY_DIR}"
+ )
+endforeach()
endif()
foreach(source_file ${source_files})
@@ -49,5 +52,7 @@ foreach(source_file ${source_files})
PROPERTIES
SKIP_RETURN_CODE 127)
set_property(TEST ${test_executable}
- PROPERTY ENVIRONMENT "STASIS_SYSCONFDIR=${CMAKE_SOURCE_DIR}")
+ PROPERTY ENVIRONMENT "STASIS_SYSCONFDIR=${CMAKE_SOURCE_DIR}"
+ PROPERTY ENVIRONMENT "GIT_CEILING_DIRECTORIES=${CMAKE_BINARY_DIR}"
+ )
endforeach()
diff --git a/tests/test_conda.c b/tests/test_conda.c
index 9f0e718..e32c9f2 100644
--- a/tests/test_conda.c
+++ b/tests/test_conda.c
@@ -18,10 +18,10 @@ void test_micromamba() {
int result;
};
struct testcase tc[] = {
- {.mminfo = {.micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "info", .result = 0},
- {.mminfo = {.micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "env list", .result = 0},
- {.mminfo = {.micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "run python3 -V", .result = 0},
- {.mminfo = {.micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "no_such_option", .result = 109},
+ {.mminfo = {.download_dir = cwd_workspace, .micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "info", .result = 0},
+ {.mminfo = {.download_dir = cwd_workspace, .micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "env list", .result = 0},
+ {.mminfo = {.download_dir = cwd_workspace, .micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "run python3 -V", .result = 0},
+ {.mminfo = {.download_dir = cwd_workspace, .micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "no_such_option", .result = 109},
};
for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) {
@@ -31,7 +31,7 @@ void test_micromamba() {
result = result >> 8;
}
STASIS_ASSERT(result == item->result, "unexpected exit value");
- SYSERROR("micromamba command: '%s' (returned: %d)", item->cmd, result);
+ SYSDEBUG("micromamba command: '%s' (returned: %d)", item->cmd, result);
}
}
@@ -143,7 +143,7 @@ void test_pip_index_provides() {
};
for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) {
struct testcase *test = &tc[i];
- int result = pkg_index_provides(PKG_USE_PIP, test->pindex, test->name);
+ int result = pkg_index_provides(PKG_USE_PIP, test->pindex, test->name, ".");
STASIS_ASSERT(result == test->expected, "Unexpected result");
if (PKG_INDEX_PROVIDES_FAILED(result)) {
fprintf(stderr, "error: %s\n", pkg_index_provides_strerror(result));
@@ -175,7 +175,7 @@ void test_conda_provides() {
for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) {
struct testcase *test = &tc[i];
- int result = pkg_index_provides(PKG_USE_CONDA, NULL, test->name);
+ int result = pkg_index_provides(PKG_USE_CONDA, NULL, test->name, ".");
printf("%s returned %d, expecting %d\n", test->name, result, test->expected);
STASIS_ASSERT(result == test->expected, "Unexpected result");
}
diff --git a/tests/test_relocation.c b/tests/test_relocation.c
index 69142dc..4a02e01 100644
--- a/tests/test_relocation.c
+++ b/tests/test_relocation.c
@@ -15,6 +15,7 @@ void test_replace_text() {
const char *expected = targets[i + 1];
char input[BUFSIZ] = {0};
strncpy(input, test_string, sizeof(input) - 1);
+ input[sizeof(input) - 1] = '\0';
printf("input: %s\n", input);
printf("target: %s\n", target);
@@ -39,6 +40,7 @@ void test_file_replace_text() {
STASIS_ASSERT(file_replace_text(filename, target, "^^^", 0) == 0, "string replacement failed");
} else {
STASIS_ASSERT(false, "failed to open file for writing");
+ fclose(fp);
return;
}
@@ -47,8 +49,10 @@ void test_file_replace_text() {
if (fp) {
fread(input, sizeof(*input), sizeof(input), fp);
STASIS_ASSERT(strcmp(input, expected) == 0, "unexpected replacement");
+ fclose(fp);
} else {
STASIS_ASSERT(false, "failed to open file for reading");
+ fclose(fp);
return;
}
}
diff --git a/tests/test_str.c b/tests/test_str.c
index aac5d71..09d8809 100644
--- a/tests/test_str.c
+++ b/tests/test_str.c
@@ -38,6 +38,7 @@ void test_tolower_s() {
for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) {
char input[100] = {0};
strncpy(input, tc[i].data, sizeof(input) - 1);
+ input[sizeof(input) - 1] = '\0';
tolower_s(input);
STASIS_ASSERT(strcmp(input, tc[i].expected) == 0, "unexpected result");
}
@@ -318,6 +319,7 @@ void test_lstrip() {
for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) {
char *buf = calloc(255, sizeof(*buf));
strncpy(buf, tc[i].data, 254);
+ buf[254] = '\0';
char *result = lstrip(buf);
STASIS_ASSERT(strcmp(result ? result : "", tc[i].expected) == 0, "incorrect strip-from-left");
guard_free(buf);
@@ -342,6 +344,7 @@ void test_strip() {
for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) {
char *buf = calloc(255, sizeof(*buf));
strncpy(buf, tc[i].data, 254);
+ buf[254] = '\0';
char *result = strip(buf);
STASIS_ASSERT(strcmp(result ? result : "", tc[i].expected) == 0, "incorrect strip-from-right");
guard_free(buf);
diff --git a/tests/test_utils.c b/tests/test_utils.c
index a5faf5c..fd398e2 100644
--- a/tests/test_utils.c
+++ b/tests/test_utils.c
@@ -71,6 +71,8 @@ void test_fix_tox_conf() {
}
char **lines = file_readlines(result, 0, 0, NULL);
+ STASIS_ASSERT_FATAL(lines != NULL, "lines array should not be NULL");
+ STASIS_ASSERT_FATAL(result != NULL, "result should not be NULL");
STASIS_ASSERT(strstr_array(lines, expected) != NULL, "{posargs} not found in result");
guard_array_free(lines);
@@ -312,6 +314,7 @@ void test_path_dirname() {
const char *expected = data[i + 1];
char tmp[PATH_MAX] = {0};
strncpy(tmp, input, sizeof(tmp) - 1);
+ tmp[sizeof(tmp) - 1] = '\0';
char *result = path_dirname(tmp);
STASIS_ASSERT(strcmp(expected, result) == 0, NULL);
diff --git a/tests/test_wheel.c b/tests/test_wheel.c
index 531e4b7..a1623e8 100644
--- a/tests/test_wheel.c
+++ b/tests/test_wheel.c
@@ -41,13 +41,13 @@ static void test_wheel_package() {
const struct WheelValue dist_version = wheel_get_value_by_name(wheel, WHEEL_FROM_DIST, "Wheel-Version");
STASIS_ASSERT(dist_version.type == WHEELVAL_STR, "Wheel dist version value must be a string");
STASIS_ASSERT_FATAL(dist_version.data != NULL, "Wheel dist version value must not be NULL");
- STASIS_ASSERT(dist_version.count, "Wheel value must be populated");
+ STASIS_ASSERT(dist_version.count != 0, "Wheel value must be populated");
// Get data from METADATA
const struct WheelValue meta_name = wheel_get_value_by_name(wheel, WHEEL_FROM_METADATA, "Metadata-Version");
STASIS_ASSERT(meta_name.type == WHEELVAL_STR, "Wheel metadata version value must be a string");
STASIS_ASSERT_FATAL(meta_name.data != NULL, "Wheel metadata version value must not be NULL");
- STASIS_ASSERT(meta_name.count, "Wheel metadata version value must be populated");
+ STASIS_ASSERT(meta_name.count != 0, "Wheel metadata version value must be populated");
wheel_package_free(&wheel);
STASIS_ASSERT(wheel == NULL, "wheel struct should be NULL after free");