aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2026-06-11 13:01:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2026-06-11 13:01:52 -0400
commita49aac31673c65527afe47e83d2c561ce1d01469 (patch)
treed3b55fe5e96e2e8facbbf96b5c64b8e952c7c7f3 /src
parent823c5021e9b141ab830ea0f5a9ec176cb29c17a8 (diff)
downloadstasis-a49aac31673c65527afe47e83d2c561ce1d01469.tar.gz
Disallow extraneous conda and pip version specs
* STASIS wants equals-to, or nothing (latest). * The use of URLs with '@' is what we need to avoid * Tell the user the expected format on error
Diffstat (limited to 'src')
-rw-r--r--src/lib/delivery/delivery_populate.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/lib/delivery/delivery_populate.c b/src/lib/delivery/delivery_populate.c
index cfa3da2..c43598c 100644
--- a/src/lib/delivery/delivery_populate.c
+++ b/src/lib/delivery/delivery_populate.c
@@ -194,6 +194,44 @@ static void normalize_ini_list(struct INIFILE **inip, struct StrList **listp, ch
(*listp) = list;
}
+static int check_package_spec_list(struct StrList *list, const char *ini_section, const char *ini_key) {
+ if (!list) {
+ // empty lists are OK
+ return 0;
+ }
+ for (size_t i = 0; i < strlist_count(list); i++) {
+ const char *item = strlist_item(list, i);
+ if (!item) {
+ continue;
+ }
+ const char *invalid_chars = "@:/<>!~";
+ const char *invalid_spec = strpbrk(item, invalid_chars);
+ if (invalid_spec) {
+ SYSERROR("Invalid version specification detected at %s:%s[%zu], \"%s\"", ini_section, ini_key, i, item);
+ SYSERROR("Package specification may not contain the operator '%c' (or any of \"%s\")", *invalid_spec, invalid_chars);
+ SYSERROR("");
+ SYSERROR("%s:%s supports:", ini_section, ini_key);
+ SYSERROR(" {package}[=={version|tag|branch|ref}]");
+ SYSERROR("");
+ char *reported_name = strdup(item);
+ if (!reported_name) {
+ SYSERROR("unable to allocate memory for reported_name");
+ return -1;
+ }
+ const char *reported_name_end = reported_name;
+ while (!ispunct(*reported_name_end)) {
+ reported_name_end++;
+ }
+ reported_name[reported_name_end - reported_name] = '\0';
+ SYSERROR("Set test:%s.repository to point to a valid Git repository URL to enable [tag|branch|ref]", reported_name);
+
+ guard_free(reported_name);
+ return -1;
+ }
+ }
+ return 0;
+}
+
int populate_delivery_ini(struct Delivery *ctx, int render_mode) {
struct INIFILE *ini = ctx->_stasis_ini_fp.delivery;
struct INIData *rtdata;
@@ -230,12 +268,22 @@ int populate_delivery_ini(struct Delivery *ctx, int render_mode) {
ctx->conda.installer_platform = ini_getval_str(ini, "conda", "installer_platform", render_mode, &err);
ctx->conda.installer_arch = ini_getval_str(ini, "conda", "installer_arch", render_mode, &err);
ctx->conda.installer_baseurl = ini_getval_str(ini, "conda", "installer_baseurl", render_mode, &err);
+
ctx->conda.conda_packages = ini_getval_strlist(ini, "conda", "conda_packages", LINE_SEP, render_mode, &err);
normalize_ini_list(&ini, &ctx->conda.conda_packages, "conda", "conda_packages", render_mode);
+ if (check_package_spec_list(ctx->conda.conda_packages, "conda", "conda_packages")) {
+ return -1;
+ }
+
ctx->conda.conda_packages_purge = ini_getval_strlist(ini, "conda", "conda_packages_purge", LINE_SEP, render_mode, &err);
normalize_ini_list(&ini, &ctx->conda.conda_packages_purge, "conda", "conda_package_purge", render_mode);
+
ctx->conda.pip_packages = ini_getval_strlist(ini, "conda", "pip_packages", LINE_SEP, render_mode, &err);
normalize_ini_list(&ini, &ctx->conda.pip_packages, "conda", "pip_packages", render_mode);
+ if (check_package_spec_list(ctx->conda.pip_packages, "conda", "pip_packages")) {
+ return -1;
+ }
+
ctx->conda.pip_packages_purge = ini_getval_strlist(ini, "conda", "pip_packages_purge", LINE_SEP, render_mode, &err);
normalize_ini_list(&ini, &ctx->conda.pip_packages_purge, "conda", "pip_packages_purge", render_mode);