aboutsummaryrefslogtreecommitdiff
path: root/src/lib/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/core')
-rw-r--r--src/lib/core/artifactory.c6
-rw-r--r--src/lib/core/conda.c40
-rw-r--r--src/lib/core/include/log.h2
-rw-r--r--src/lib/core/include/template.h7
-rw-r--r--src/lib/core/include/template_func_proto.h10
-rw-r--r--src/lib/core/include/utils.h20
-rw-r--r--src/lib/core/ini.c88
-rw-r--r--src/lib/core/junitxml.c93
-rw-r--r--src/lib/core/log.c33
-rw-r--r--src/lib/core/multiprocessing.c78
-rw-r--r--src/lib/core/str.c11
-rw-r--r--src/lib/core/strlist.c115
-rw-r--r--src/lib/core/system.c1
-rw-r--r--src/lib/core/template.c2
-rw-r--r--src/lib/core/template_func_proto.c10
-rw-r--r--src/lib/core/utils.c141
-rw-r--r--src/lib/core/wheel.c70
17 files changed, 507 insertions, 220 deletions
diff --git a/src/lib/core/artifactory.c b/src/lib/core/artifactory.c
index 669bfff..d4b48fb 100644
--- a/src/lib/core/artifactory.c
+++ b/src/lib/core/artifactory.c
@@ -38,7 +38,7 @@ int artifactory_download_cli(char *dest,
strncpy(os_ident, "linux", sizeof(os_ident) - 1);
os_ident[sizeof(os_ident) - 1] = '\0';
} else {
- SYSERROR("%s: unknown operating system: %s", __FUNCTION__, os_ident);
+ SYSERROR("unknown operating system: %s", os_ident);
return -1;
}
@@ -59,7 +59,7 @@ int artifactory_download_cli(char *dest,
} else if (!strcmp(arch_ident, "arm64") || !strcmp(arch_ident, "aarch64")) {
strncpy(arch_ident, "arm64", sizeof(arch_ident) - 1);
} else {
- SYSERROR("%s: unknown architecture: %s", __FUNCTION__, arch_ident);
+ SYSERROR("unknown architecture: %s", arch_ident);
return -1;
}
arch_ident[sizeof(arch_ident) - 1] = '\0';
@@ -79,7 +79,7 @@ int artifactory_download_cli(char *dest,
path[sizeof(path) - 1] = '\0';
if (mkdirs(path, 0755)) {
- SYSERROR("%s: %s: %s", __FUNCTION__, path, strerror(errno));
+ SYSERROR("%s: %s", path, strerror(errno));
return -1;
}
diff --git a/src/lib/core/conda.c b/src/lib/core/conda.c
index f9e2bd2..6083023 100644
--- a/src/lib/core/conda.c
+++ b/src/lib/core/conda.c
@@ -207,42 +207,30 @@ int pkg_index_provides(int mode, const char *index, const char *spec, const char
return PKG_INDEX_PROVIDES_E_INTERNAL_MODE_UNKNOWN;
}
-#if defined(DEBUG)
- const int debug_log = 1;
-#else
- const int 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);
- }
+ SYSDEBUG("Executing: %s", cmd);
status = shell(&proc, cmd);
- if (debug_log) {
- SYSDEBUG("Log file: %s", logfile);
- }
- if (status < 0 || debug_log) {
+ SYSDEBUG("Log file: %s", logfile);
+ if (status != 0) {
FILE *fp = fdopen(logfd, "r");
if (!fp) {
remove(logfile);
return -1;
- } else {
- char line[STASIS_BUFSIZ] = {0};
- fflush(stdout);
- fflush(stderr);
- while (fgets(line, sizeof(line) - 1, fp) != NULL) {
- if (debug_log) {
- SYSDEBUG("%s", strip(line));
- } else {
- fprintf(stderr, "%s", line);
- }
- }
- fflush(stderr);
- fclose(fp);
}
+
+ fflush(stdout);
+ fflush(stderr);
+
+ char line[STASIS_BUFSIZ] = {0};
+ while (fgets(line, sizeof(line) - 1, fp) != NULL) {
+ SYSDEBUG("%s", strip(line));
+ }
+
+ fflush(stderr);
+ fclose(fp);
}
remove(logfile);
diff --git a/src/lib/core/include/log.h b/src/lib/core/include/log.h
index 18617c4..cad954f 100644
--- a/src/lib/core/include/log.h
+++ b/src/lib/core/include/log.h
@@ -16,7 +16,7 @@ struct ExecPoint {
const char *function; // function of origin
};
-#define EXECPOINT (struct ExecPoint) {.line = __LINE__, .file = __FILE__, .function = __FUNCTION__}
+#define EXECPOINT (struct ExecPoint) {.line = __LINE__, .file = __FILE__, .function = __func__}
void log_print_error(struct ExecPoint ep, const char *fmt, ...);
void log_print_warning(struct ExecPoint ep, const char *fmt, ...);
diff --git a/src/lib/core/include/template.h b/src/lib/core/include/template.h
index e3d83fb..436fcc6 100644
--- a/src/lib/core/include/template.h
+++ b/src/lib/core/include/template.h
@@ -40,7 +40,9 @@ char *tpl_render(char *str);
*/
int tpl_render_to_file(char *str, const char *filename);
-typedef int tplfunc(void *frame, void *data_out);
+struct tplfunc_frame;
+
+typedef int tplfunc(struct tplfunc_frame *frame, void *data_out);
struct tplfunc_frame {
char *key; ///< Name of the function
@@ -68,8 +70,9 @@ struct tplfunc_frame {
* @param key function name to expose to "func:" interface
* @param tplfunc_ptr pointer to function of type tplfunc
* @param argc number of function arguments to accept
+ * @param data_in pointer to function input data
*/
-void tpl_register_func(char *key, void *tplfunc_ptr, int argc, void *data_in);
+void tpl_register_func(char *key, tplfunc *tplfunc_ptr, int argc, void *data_in);
/**
* Get the function frame associated with a template function
diff --git a/src/lib/core/include/template_func_proto.h b/src/lib/core/include/template_func_proto.h
index 286ccfb..0f2ad80 100644
--- a/src/lib/core/include/template_func_proto.h
+++ b/src/lib/core/include/template_func_proto.h
@@ -4,10 +4,10 @@
#include "template.h"
-int get_github_release_notes_tplfunc_entrypoint(void *frame, void *data_out);
-int get_github_release_notes_auto_tplfunc_entrypoint(void *frame, void *data_out);
-int get_junitxml_file_entrypoint(void *frame, void *data_out);
-int get_basetemp_dir_entrypoint(void *frame, void *data_out);
-int tox_run_entrypoint(void *frame, void *data_out);
+int get_github_release_notes_tplfunc_entrypoint(struct tplfunc_frame *frame, void *data_out);
+int get_github_release_notes_auto_tplfunc_entrypoint(struct tplfunc_frame *frame, void *data_out);
+int get_junitxml_file_entrypoint(struct tplfunc_frame *frame, void *data_out);
+int get_basetemp_dir_entrypoint(struct tplfunc_frame *frame, void *data_out);
+int tox_run_entrypoint(struct tplfunc_frame *frame, void *data_out);
#endif //TEMPLATE_FUNC_PROTO_H \ No newline at end of file
diff --git a/src/lib/core/include/utils.h b/src/lib/core/include/utils.h
index 1a5e97f..98b8ae8 100644
--- a/src/lib/core/include/utils.h
+++ b/src/lib/core/include/utils.h
@@ -210,17 +210,17 @@ int path_store(char **destptr, size_t maxlen, const char *base, const char *path
#define STASIS_COLOR_RESET ""
#else
//! Set output color to red
-#define STASIS_COLOR_RED "\e[1;91m"
+#define STASIS_COLOR_RED "\x1b[1;91m"
//! Set output color to green
-#define STASIS_COLOR_GREEN "\e[1;92m"
+#define STASIS_COLOR_GREEN "\x1b[1;92m"
//! Set output color to yellow
-#define STASIS_COLOR_YELLOW "\e[1;93m"
+#define STASIS_COLOR_YELLOW "\x1b[1;93m"
//! Set output color to blue
-#define STASIS_COLOR_BLUE "\e[1;94m"
+#define STASIS_COLOR_BLUE "\x1b[1;94m"
//! Set output color to white
-#define STASIS_COLOR_WHITE "\e[1;97m"
+#define STASIS_COLOR_WHITE "\x1b[1;97m"
//! Reset output color to terminal default
-#define STASIS_COLOR_RESET "\e[0;37m\e[0m"
+#define STASIS_COLOR_RESET "\x1b[0;37m\x1b[0m"
#endif
#define STASIS_MSG_SUCCESS 0
@@ -484,4 +484,12 @@ int str_to_timeout(char *s);
const char *get_random_generator_file();
int get_random_bytes(char *result, size_t maxlen);
+/**
+ * Get length of `s` as if any formatters are not present
+ * @param s format string
+ * @return length
+ */
+int non_format_len(const char *s);
+
+char *center_text(const char *s, size_t maxwidth);
#endif //STASIS_UTILS_H
diff --git a/src/lib/core/ini.c b/src/lib/core/ini.c
index 81c75ac..3c0377f 100644
--- a/src/lib/core/ini.c
+++ b/src/lib/core/ini.c
@@ -14,8 +14,9 @@ struct INIFILE *ini_init() {
return ini;
}
-void ini_section_init(struct INIFILE **ini) {
- (*ini)->section = calloc((*ini)->section_count + 1, sizeof(**(*ini)->section));
+struct INISection **ini_section_init(struct INIFILE **ini) {
+ struct INISection **section = calloc((*ini)->section_count + 1, sizeof(**(*ini)->section));
+ return section;
}
struct INISection *ini_section_search(struct INIFILE **ini, unsigned mode, const char *value) {
@@ -219,80 +220,82 @@ int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, int
#define getval_returns(t) return result.t
#define getval_setup(t, f) \
- union INIVal result; \
+ union INIVal result = {0}; \
+ do {\
int state_local = 0; \
state_local = ini_getval(ini, section_name, key, t, f, &result); \
if (state != NULL) { \
*state = state_local; \
- }
+ } \
+} while (0)
int ini_getval_int(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_INT, flags)
+ getval_setup(INIVAL_TYPE_INT, flags);
getval_returns(as_int);
}
unsigned int ini_getval_uint(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_UINT, flags)
+ getval_setup(INIVAL_TYPE_UINT, flags);
getval_returns(as_uint);
}
long ini_getval_long(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_LONG, flags)
+ getval_setup(INIVAL_TYPE_LONG, flags);
getval_returns(as_long);
}
unsigned long ini_getval_ulong(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_ULONG, flags)
+ getval_setup(INIVAL_TYPE_ULONG, flags);
getval_returns(as_ulong);
}
long long ini_getval_llong(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_LLONG, flags)
+ getval_setup(INIVAL_TYPE_LLONG, flags);
getval_returns(as_llong);
}
unsigned long long ini_getval_ullong(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_ULLONG, flags)
+ getval_setup(INIVAL_TYPE_ULLONG, flags);
getval_returns(as_ullong);
}
float ini_getval_float(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_FLOAT, flags)
+ getval_setup(INIVAL_TYPE_FLOAT, flags);
getval_returns(as_float);
}
double ini_getval_double(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_DOUBLE, flags)
+ getval_setup(INIVAL_TYPE_DOUBLE, flags);
getval_returns(as_double);
}
bool ini_getval_bool(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_BOOL, flags)
+ getval_setup(INIVAL_TYPE_BOOL, flags);
getval_returns(as_bool);
}
short ini_getval_short(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_SHORT, flags)
+ getval_setup(INIVAL_TYPE_SHORT, flags);
getval_returns(as_short);
}
unsigned short ini_getval_ushort(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_USHORT, flags)
+ getval_setup(INIVAL_TYPE_USHORT, flags);
getval_returns(as_ushort);
}
char ini_getval_char(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_CHAR, flags)
+ getval_setup(INIVAL_TYPE_CHAR, flags);
getval_returns(as_char);
}
unsigned char ini_getval_uchar(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_UCHAR, flags)
+ getval_setup(INIVAL_TYPE_UCHAR, flags);
getval_returns(as_uchar);
}
char *ini_getval_char_p(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_STR, flags)
+ getval_setup(INIVAL_TYPE_STR, flags);
getval_returns(as_char_p);
}
@@ -301,7 +304,7 @@ char *ini_getval_str(struct INIFILE *ini, char *section_name, char *key, int fla
}
char *ini_getval_char_array_p(struct INIFILE *ini, char *section_name, char *key, int flags, int *state) {
- getval_setup(INIVAL_TYPE_STR_ARRAY, flags)
+ getval_setup(INIVAL_TYPE_STR_ARRAY, flags);
getval_returns(as_char_p);
}
@@ -310,7 +313,7 @@ char *ini_getval_str_array(struct INIFILE *ini, char *section_name, char *key, i
}
struct StrList *ini_getval_strlist(struct INIFILE *ini, char *section_name, char *key, char *tok, int flags, int *state) {
- getval_setup(INIVAL_TYPE_STR_ARRAY, flags)
+ getval_setup(INIVAL_TYPE_STR_ARRAY, flags);
struct StrList *list = strlist_init();
strlist_append_tokenize(list, result.as_char_p, tok);
guard_free(result.as_char_p);
@@ -401,20 +404,22 @@ int ini_setval(struct INIFILE **ini, unsigned type, char *section_name, char *ke
}
int ini_section_create(struct INIFILE **ini, char *key) {
- struct INISection **tmp = realloc((*ini)->section, ((*ini)->section_count + 1) * sizeof(**(*ini)->section));
- if (tmp == NULL) {
+ struct INISection **tmp = realloc((*ini)->section, ((*ini)->section_count + 1) * sizeof (*(*ini)->section));
+ if (!tmp) {
+ ini_free(ini);
return 1;
- } else {
- (*ini)->section = tmp;
}
+ (*ini)->section = tmp;
- (*ini)->section[(*ini)->section_count] = calloc(1, sizeof(*(*ini)->section[0]));
- if (!(*ini)->section[(*ini)->section_count]) {
+ struct INISection **section = &(*ini)->section[(*ini)->section_count];
+ //[(*ini)->section_count];
+ *section = calloc(1, sizeof(*(*ini)->section[0]));
+ if (!*section) {
return -1;
}
- (*ini)->section[(*ini)->section_count]->key = strdup(key);
- if (!(*ini)->section[(*ini)->section_count]->key) {
+ (*section)->key = strdup(key);
+ if (!(*section)->key) {
return -1;
}
@@ -512,6 +517,9 @@ char *unquote(char *s) {
}
void ini_free(struct INIFILE **ini) {
+ if (!(*ini)) {
+ return;
+ }
for (size_t section = 0; section < (*ini)->section_count; section++) {
for (size_t data = 0; data < (*ini)->section[section]->data_count; data++) {
if ((*ini)->section[section]->data[data]) {
@@ -538,10 +546,19 @@ struct INIFILE *ini_open(const char *filename) {
return NULL;
}
- ini_section_init(&ini);
+ ini->section = ini_section_init(&ini);
+ if (!ini->section) {
+ ini_free(&ini);
+ return NULL;
+ }
// Create an implicit section. [default] does not need to be present in the INI config
- ini_section_create(&ini, "default");
+ if (ini_section_create(&ini, "default")) {
+ SYSERROR("%s", "unable to create default section");
+ ini_free(&ini);
+ ini = NULL;
+ return NULL;
+ }
strncpy(current_section, "default", sizeof(current_section) - 1);
current_section[sizeof(current_section) - 1] = '\0';
@@ -614,7 +631,12 @@ struct INIFILE *ini_open(const char *filename) {
// Create new named section
strip(section_name);
- ini_section_create(&ini, section_name);
+ if (ini_section_create(&ini, section_name)) {
+ SYSERROR("unable to create section: %s", section_name);
+ guard_free(section_name);
+ ini_free(&ini);
+ return NULL;
+ }
// Record the name of the section. This is used until another section is found.
memset(current_section, 0, sizeof(current_section));
@@ -631,7 +653,7 @@ struct INIFILE *ini_open(const char *filename) {
continue;
}
- char *operator = strchr(line, '=');
+ const char *operator = strchr(line, '=');
// a value continuation line
if (multiline_data && (startswith(line, " ") || startswith(line, "\t"))) {
@@ -639,7 +661,7 @@ struct INIFILE *ini_open(const char *filename) {
}
if (operator) {
- size_t key_len = operator - line;
+ const size_t key_len = operator - line;
memset(key, 0, key_size);
strncpy(key, line, key_len);
diff --git a/src/lib/core/junitxml.c b/src/lib/core/junitxml.c
index a59cb9d..e590cb5 100644
--- a/src/lib/core/junitxml.c
+++ b/src/lib/core/junitxml.c
@@ -209,42 +209,78 @@ static int read_xml_data(xmlTextReaderPtr reader, struct JUNIT_Testsuite **tests
for (size_t x = 0; x < strlist_count(attrs); x += 2) {
char *attr_name = strlist_item(attrs, x);
char *attr_value = strlist_item(attrs, x + 1);
- if (!strcmp(attr_name, "name")) {
- (*testsuite)->name = strdup(attr_value);
- } else if (!strcmp(attr_name, "errors")) {
- (*testsuite)->errors = (int) strtol(attr_value, NULL, 10);
- } else if (!strcmp(attr_name, "failures")) {
- (*testsuite)->failures = (int) strtol(attr_value, NULL, 0);
- } else if (!strcmp(attr_name, "skipped")) {
- (*testsuite)->skipped = (int) strtol(attr_value, NULL, 0);
- } else if (!strcmp(attr_name, "tests")) {
- (*testsuite)->tests = (int) strtol(attr_value, NULL, 0);
- } else if (!strcmp(attr_name, "time")) {
- (*testsuite)->time = strtof(attr_value, NULL);
- } else if (!strcmp(attr_name, "timestamp")) {
- (*testsuite)->timestamp = strdup(attr_value);
- } else if (!strcmp(attr_name, "hostname")) {
- (*testsuite)->hostname = strdup(attr_value);
+ if (attr_name && attr_value) {
+ if (!strcmp(attr_name, "name")) {
+ (*testsuite)->name = strdup(attr_value);
+ if (!(*testsuite)->name) {
+ SYSERROR("%s", "failed to allocate memory for testcase name");
+ return -1;
+ }
+ } else if (!strcmp(attr_name, "errors")) {
+ (*testsuite)->errors = (int) strtol(attr_value, NULL, 10);
+ } else if (!strcmp(attr_name, "failures")) {
+ (*testsuite)->failures = (int) strtol(attr_value, NULL, 0);
+ } else if (!strcmp(attr_name, "skipped")) {
+ (*testsuite)->skipped = (int) strtol(attr_value, NULL, 0);
+ } else if (!strcmp(attr_name, "tests")) {
+ (*testsuite)->tests = (int) strtol(attr_value, NULL, 0);
+ } else if (!strcmp(attr_name, "time")) {
+ (*testsuite)->time = strtof(attr_value, NULL);
+ } else if (!strcmp(attr_name, "timestamp")) {
+ (*testsuite)->timestamp = strdup(attr_value);
+ if (!(*testsuite)->timestamp) {
+ SYSERROR("%s", "failed to allocate memory for testcase timestamp");
+ return -1;
+ }
+ } else if (!strcmp(attr_name, "hostname")) {
+ (*testsuite)->hostname = strdup(attr_value);
+ if (!(*testsuite)->hostname) {
+ SYSERROR("%s", "failed to allocate memory for testcase hostname");
+ return -1;
+ }
+ }
}
}
} else if (!strcmp(node_name, "testcase")) {
struct JUNIT_Testcase *testcase = testcase_from_attributes(attrs);
+ if (!testcase) {
+ SYSERROR("%s", "failed to allocate memory for testcase");
+ return -1;
+ }
testsuite_append_testcase(testsuite, testcase);
} else if (!strcmp(node_name, "failure")) {
size_t cur_tc = (*testsuite)->_tc_inuse > 0 ? (*testsuite)->_tc_inuse - 1 : (*testsuite)->_tc_inuse;
struct JUNIT_Failure *failure = testcase_failure_from_attributes(attrs);
- (*testsuite)->testcase[cur_tc]->tc_result_state_type = JUNIT_RESULT_STATE_FAILURE;
- (*testsuite)->testcase[cur_tc]->result_state.failure = failure;
+ if (!failure) {
+ SYSERROR("%s", "failed to allocate memory for testcase failure");
+ return -1;
+ }
+ if ((*testsuite)->testcase && (*testsuite)->testcase[cur_tc]) {
+ (*testsuite)->testcase[cur_tc]->tc_result_state_type = JUNIT_RESULT_STATE_FAILURE;
+ (*testsuite)->testcase[cur_tc]->result_state.failure = failure;
+ }
} else if (!strcmp(node_name, "error")) {
size_t cur_tc = (*testsuite)->_tc_inuse > 0 ? (*testsuite)->_tc_inuse - 1 : (*testsuite)->_tc_inuse;
struct JUNIT_Error *error = testcase_error_from_attributes(attrs);
- (*testsuite)->testcase[cur_tc]->tc_result_state_type = JUNIT_RESULT_STATE_ERROR;
- (*testsuite)->testcase[cur_tc]->result_state.error = error;
+ if (!error) {
+ SYSERROR("%s", "failed to allocate memory for testcase error");
+ return -1;
+ }
+ if ((*testsuite)->testcase && (*testsuite)->testcase[cur_tc]) {
+ (*testsuite)->testcase[cur_tc]->tc_result_state_type = JUNIT_RESULT_STATE_ERROR;
+ (*testsuite)->testcase[cur_tc]->result_state.error = error;
+ }
} else if (!strcmp(node_name, "skipped")) {
size_t cur_tc = (*testsuite)->_tc_inuse > 0 ? (*testsuite)->_tc_inuse - 1 : (*testsuite)->_tc_inuse;
struct JUNIT_Skipped *skipped = testcase_skipped_from_attributes(attrs);
- (*testsuite)->testcase[cur_tc]->tc_result_state_type = JUNIT_RESULT_STATE_SKIPPED;
- (*testsuite)->testcase[cur_tc]->result_state.skipped = skipped;
+ if (!skipped) {
+ SYSERROR("%s", "failed to allocate memory for testcase skipped");
+ return -1;
+ }
+ if ((*testsuite)->testcase && (*testsuite)->testcase[cur_tc]) {
+ (*testsuite)->testcase[cur_tc]->tc_result_state_type = JUNIT_RESULT_STATE_SKIPPED;
+ (*testsuite)->testcase[cur_tc]->result_state.skipped = skipped;
+ }
}
}
(*testsuite)->passed = (*testsuite)->tests - (*testsuite)->failures - (*testsuite)->errors - (*testsuite)->skipped;
@@ -255,12 +291,17 @@ static int read_xml_data(xmlTextReaderPtr reader, struct JUNIT_Testsuite **tests
static int read_xml_file(const char *filename, struct JUNIT_Testsuite **testsuite) {
xmlTextReaderPtr reader = xmlReaderForFile(filename, NULL, 0);
if (!reader) {
+ xmlFreeTextReader(reader);
return -1;
}
int result = xmlTextReaderRead(reader);
while (result == 1) {
- read_xml_data(reader, testsuite);
+ if (read_xml_data(reader, testsuite) < 0) {
+ xmlFreeTextReader(reader);
+ return -1;
+ }
+
result = xmlTextReaderRead(reader);
}
@@ -279,6 +320,10 @@ struct JUNIT_Testsuite *junitxml_testsuite_read(const char *filename) {
if (!result) {
return NULL;
}
- read_xml_file(filename, &result);
+
+ if (read_xml_file(filename, &result)) {
+ junitxml_testsuite_free(&result);
+ }
+
return result;
} \ No newline at end of file
diff --git a/src/lib/core/log.c b/src/lib/core/log.c
index aea3231..b1cab4c 100644
--- a/src/lib/core/log.c
+++ b/src/lib/core/log.c
@@ -42,19 +42,38 @@ void log_print_debug(const struct ExecPoint ep, const char *fmt, ...) {
int log_msgv(FILE *stream, const struct ExecPoint ep, const char *preface_color, const char *preface, const char *fmt, va_list ap) {
char header[STASIS_BUFSIZ] = {0};
+ const int no_info = LOG_LEVEL < LOG_LEVEL_INFO;
+ const int some_info = LOG_LEVEL < LOG_LEVEL_DEBUG;
int len = snprintf(header, sizeof(header),
STASIS_COLOR_RESET
"%s%s: "
- STASIS_COLOR_RESET
- STASIS_COLOR_WHITE
- "%s:%d: %s(): "
STASIS_COLOR_RESET,
preface_color ? preface_color : STASIS_COLOR_RED,
- preface ? preface : "UNKNOWN",
- path_basename((char *) ep.file),
- ep.line,
- ep.function);
+ preface ? preface : "UNKNOWN");
+
+ if (no_info) {
+ len += snprintf(header + strlen(header), sizeof(header) - len,
+ STASIS_COLOR_WHITE
+ ""
+ STASIS_COLOR_RESET);
+ } else if (some_info) {
+ len += snprintf(header + strlen(header), sizeof(header) - len,
+ STASIS_COLOR_WHITE
+ "%s(): "
+ STASIS_COLOR_RESET,
+ ep.function);
+ } else {
+ // everything
+ len += snprintf(header + strlen(header), sizeof(header) - len,
+ STASIS_COLOR_WHITE
+ "%s:%d: %s(): "
+ STASIS_COLOR_RESET,
+ path_basename((char *) ep.file),
+ ep.line,
+ ep.function);
+ }
+
if (len >= (int) sizeof(header)) {
SYSERROR("header format truncated (%d >= %d)", len, (int) sizeof(header));
return len;
diff --git a/src/lib/core/multiprocessing.c b/src/lib/core/multiprocessing.c
index f431dd3..b17bdc1 100644
--- a/src/lib/core/multiprocessing.c
+++ b/src/lib/core/multiprocessing.c
@@ -62,6 +62,7 @@ int child(struct MultiProcessingPool *pool, struct MultiProcessingTask *task) {
(void) pool;
FILE *fp_log = NULL;
+ semaphore_wait(&pool->semaphore);
// The task starts inside the requested working directory
if (chdir(task->working_dir)) {
perror(task->working_dir);
@@ -77,22 +78,32 @@ int child(struct MultiProcessingPool *pool, struct MultiProcessingTask *task) {
snprintf(task->log_file + strlen(task->log_file), sizeof(task->log_file) - strlen(task->log_file),
"task-%zu-%d.log", mp_global_task_count, task->parent_pid);
SYSDEBUG("using log file: %s", task->log_file);
+ semaphore_post(&pool->semaphore);
}
fp_log = freopen(task->log_file, "w+", stdout);
if (!fp_log) {
- fprintf(stderr, "unable to open '%s' for writing: %s\n", task->log_file, strerror(errno));
SYSERROR("unable to open '%s' for writing: %s", task->log_file, strerror(errno));
+ semaphore_post(&pool->semaphore);
return -1;
}
- int fd = -1;
- if ((fd = dup2(STDOUT_FILENO, STDERR_FILENO)) < 0) {
+ const int redirect = dup2(STDOUT_FILENO, STDERR_FILENO);
+ if (redirect < 0) {
SYSERROR("%s", "Unable to redirect stderr to stdout");
SYSERROR("Unable to redirect stderr to stdout");
fclose(fp_log);
+ semaphore_post(&pool->semaphore);
return -1;
}
+ // Close child file descriptors
+ for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); fd++) {
+ if (fd == redirect) {
+ continue;
+ }
+ close(fd);
+ }
+
// Generate timestamp for log header
const time_t t = time(NULL);
char *timebuf = ctime(&t);
@@ -114,7 +125,10 @@ int child(struct MultiProcessingPool *pool, struct MultiProcessingTask *task) {
fflush(stdout);
fflush(stderr);
char *args[] = {"bash", "--norc", task->parent_script, (char *) NULL};
- return execvp("/bin/bash", args);
+ semaphore_post(&pool->semaphore);
+ execvp("bash", args);
+ SYSERROR("execvp failed (%s)", strerror(errno));
+ _exit(127);
}
int parent(struct MultiProcessingPool *pool, struct MultiProcessingTask *task, pid_t pid, int *child_status) {
@@ -182,7 +196,9 @@ struct MultiProcessingTask *mp_pool_task(struct MultiProcessingPool *pool, const
// Set log file path
memset(slot->log_file, 0, sizeof(*slot->log_file));
if (globals.enable_task_logging) {
- snprintf(slot->log_file, sizeof(slot->log_file) - strlen(slot->log_file), "%s/", pool->log_root);
+ snprintf(slot->log_file, sizeof(slot->log_file), "%s", pool->log_root);
+ // FORTIFY_SOURCE won't leave snprintf alone. The chance for truncation is slim anyway.
+ strncat(slot->log_file, "/", sizeof(slot->log_file) - strlen(slot->log_file));
} else {
snprintf(slot->log_file, sizeof(slot->log_file), "/dev/stdout");
}
@@ -230,8 +246,12 @@ struct MultiProcessingTask *mp_pool_task(struct MultiProcessingPool *pool, const
// Record the command(s)
SYSDEBUG("%s", "mmap() slot command");
- slot->cmd_len = (strlen(cmd) * sizeof(*cmd)) + 1;
- slot->cmd = mmap(NULL, slot->cmd_len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ slot->cmd_len = strlen(cmd) + 1;
+ slot->cmd = calloc(slot->cmd_len, sizeof(*slot->cmd));
+ if (!slot->cmd) {
+ SYSERROR("Failed to allocate memory for slot command");
+ return NULL;
+ }
memset(slot->cmd, 0, slot->cmd_len);
snprintf(slot->cmd, slot->cmd_len, "%s", cmd);
@@ -335,7 +355,7 @@ int mp_pool_kill(struct MultiProcessingPool *pool, int signum) {
}
int mp_pool_join(struct MultiProcessingPool *pool, size_t jobs, size_t flags) {
- int status = 0;
+ int child_status = 0;
int failures = 0;
size_t tasks_complete = 0;
size_t lower_i = 0;
@@ -376,7 +396,7 @@ int mp_pool_join(struct MultiProcessingPool *pool, size_t jobs, size_t flags) {
}
// Is the process finished?
- pid_t pid = waitpid(slot->pid, &status, WNOHANG | WUNTRACED | WCONTINUED);
+ const pid_t pid = waitpid(slot->pid, &child_status, WNOHANG | WUNTRACED | WCONTINUED);
char progress[1024] = {0};
const double percent = ((double) (tasks_complete + 1) / (double) pool->num_used) * 100;
@@ -389,7 +409,7 @@ int mp_pool_join(struct MultiProcessingPool *pool, size_t jobs, size_t flags) {
seconds_to_human_readable(slot->timeout, duration, sizeof(duration));
printf("%s Task timed out after %s (pid: %d)\n", progress, duration, slot->pid);
if (kill(slot->pid, SIGKILL) == 0) {
- status = SIGKILL;
+ child_status = SIGKILL;
} else {
SYSERROR("Timeout reached, however pid %d could not be killed.", slot->pid);
return -1;
@@ -397,13 +417,13 @@ int mp_pool_join(struct MultiProcessingPool *pool, size_t jobs, size_t flags) {
}
}
- const int task_ended = WIFEXITED(status);
- const int task_ended_by_signal = WIFSIGNALED(status);
- const int task_stopped = WIFSTOPPED(status);
- const int task_continued = WIFCONTINUED(status);
- const int status_exit = WEXITSTATUS(status);
- const int status_signal = WTERMSIG(status);
- const int status_stopped = WSTOPSIG(status);
+ const int task_ended = WIFEXITED(child_status);
+ const int task_ended_by_signal = WIFSIGNALED(child_status);
+ const int task_stopped = WIFSTOPPED(child_status);
+ const int task_continued = WIFCONTINUED(child_status);
+ const int status_exit = WEXITSTATUS(child_status);
+ const int status_signal = WTERMSIG(child_status);
+ const int status_stopped = WSTOPSIG(child_status);
// Update status
slot->status = status_exit;
@@ -427,7 +447,7 @@ int mp_pool_join(struct MultiProcessingPool *pool, size_t jobs, size_t flags) {
printf("%s Task ended (status: %d)\n", progress, status_exit);
tasks_complete++;
} else {
- SYSWARN("%s Task state is unknown (0x%04X)", progress, status);
+ SYSWARN("%s Task state is unknown (0x%04X)", progress, child_status);
}
if (globals.enable_task_logging) {
@@ -437,7 +457,7 @@ int mp_pool_join(struct MultiProcessingPool *pool, size_t jobs, size_t flags) {
}
}
- if (status >> 8 != 0 || (status & 0xff) != 0) {
+ if (child_status >> 8 != 0 || (child_status & 0xff) != 0) {
semaphore_wait(&pool->semaphore);
update_task_elapsed(slot);
semaphore_post(&pool->semaphore);
@@ -526,6 +546,10 @@ struct MultiProcessingPool *mp_pool_init(const char *ident, const char *log_root
// The pool is shared with children
pool = mmap(NULL, sizeof(*pool), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ if (pool == MAP_FAILED) {
+ SYSERROR("unable to memory map pool");
+ return NULL;
+ }
// Set pool identity string
memset(pool->ident, 0, sizeof(pool->ident));
@@ -576,21 +600,21 @@ void mp_pool_free(struct MultiProcessingPool **pool) {
semaphore_destroy(&(*pool)->semaphore);
}
- // Unmap all pool tasks
+ // Free all task commands
if ((*pool)->task) {
- if ((*pool)->task->cmd) {
- if (munmap((*pool)->task->cmd, (*pool)->task->cmd_len) < 0) {
- perror("munmap");
- }
+ for (size_t i = 0; i < (*pool)->num_alloc + 1; i++) {
+ struct MultiProcessingTask *task = &(*pool)->task[i];
+ guard_free(task->cmd);
}
- if (munmap((*pool)->task, sizeof(*(*pool)->task) * (*pool)->num_alloc) < 0) {
- perror("munmap");
+ // Unmap the task array
+ if (munmap((*pool)->task, sizeof(*(*pool)->task) * (*pool)->num_alloc + 1) < 0) {
+ SYSWARN("munmap pool task failed: %s", strerror(errno));
}
}
// Unmap the pool
if ((*pool)) {
if (munmap((*pool), sizeof(*(*pool))) < 0) {
- SYSWARN("munmap failed: %s", strerror(errno));
+ SYSWARN("munmap pool failed: %s", strerror(errno));
}
(*pool) = NULL;
}
diff --git a/src/lib/core/str.c b/src/lib/core/str.c
index 501c232..c31ce5e 100644
--- a/src/lib/core/str.c
+++ b/src/lib/core/str.c
@@ -11,7 +11,7 @@ char *strdup_maybe_entry(const char * restrict s, const struct ExecPoint ep, con
if (s != NULL) {
char *x = strdup(s);
if (!x) {
- SYSERROR("unable to duplicate string");
+ // We want to trace the origin of the allocation so SYSERROR can't be used here.
log_print_error(ep, "out of memory");
exit(exit_code);
}
@@ -93,7 +93,6 @@ char** split(char *_sptr, const char* delim, size_t max)
// Duplicate the input string and save a copy of the pointer to be freed later
char *orig = _sptr;
char *sptr = strdup(orig);
-
if (!sptr) {
return NULL;
}
@@ -134,6 +133,8 @@ char** split(char *_sptr, const char* delim, size_t max)
}
result[i] = calloc(STASIS_BUFSIZ, sizeof(char));
if (!result[i]) {
+ guard_free(sptr);
+ guard_array_n_free(result, i);
return NULL;
}
strncpy(result[i], token, STASIS_BUFSIZ - 1);
@@ -145,6 +146,8 @@ char** split(char *_sptr, const char* delim, size_t max)
// append the remaining string contents to array
result[i] = calloc(STASIS_BUFSIZ, sizeof(char));
if (!result[i]) {
+ guard_free(sptr);
+ guard_array_n_free(result, i);
return NULL;
}
strncpy(result[i], &orig[pos], STASIS_BUFSIZ - 1);
@@ -172,7 +175,7 @@ char *join(char **arr, const char *separator) {
result = (char *)calloc(total_bytes, sizeof(char));
for (int i = 0; i < records; i++) {
- strncat(result, arr[i], total_bytes - strlen(result) - 1);
+ strncat(result, arr[i], total_bytes - (result ? strlen(result) - 1 : 0));
if (i < (records - 1)) {
strncat(result, separator, total_bytes - strlen(result) - 1);
}
@@ -227,7 +230,7 @@ char *join_ex(char *separator, ...) {
result = calloc(size + 1, sizeof(char));
for (size_t i = 0; i < argc; i++) {
// Append argument to string
- strncat(result, argv[i], size - strlen(result)); // no -1 because +1 above
+ strncat(result, argv[i], size - (result ? strlen(result) - 1 : 0)); // no -1 because +1 above
// Do not append a trailing separator when we reach the last argument
if (i < (argc - 1)) {
diff --git a/src/lib/core/strlist.c b/src/lib/core/strlist.c
index 526a1c9..5cd3f4a 100644
--- a/src/lib/core/strlist.c
+++ b/src/lib/core/strlist.c
@@ -171,6 +171,10 @@ int strlist_contains(struct StrList *pStrList, const char *value, size_t *index_
for (size_t i = 0; i < strlist_count(pStrList); i++) {
const char *item = strlist_item(pStrList, i);
+ if (!item) {
+ *index_of = 0;
+ break;
+ }
if (!strcmp(item, value)) {
*index_of = i;
return 1;
@@ -359,9 +363,10 @@ int strlist_cmp(struct StrList *a, struct StrList *b) {
return 1;
}
-
for (size_t i = 0; i < strlist_count(a); i++) {
- if (strcmp(strlist_item(a, i), strlist_item(b, i)) != 0) {
+ const char *item_a = strlist_item(a, i);
+ const char *item_b = strlist_item(b, i);
+ if ((!item_a || !item_b) || strcmp(item_a, item_b) != 0) {
return 1;
}
}
@@ -439,9 +444,8 @@ void strlist_set(struct StrList **pStrList, size_t index, char *value) {
if (!tmp) {
SYSERROR("strlist_set replacement realloc failed: %s", strerror(errno));
return;
- } else if (tmp != (*pStrList)->data[index]) {
- (*pStrList)->data[index] = tmp;
}
+ (*pStrList)->data[index] = tmp;
const size_t len = strlen(value) + 1;
memset((*pStrList)->data[index], '\0', len);
@@ -506,7 +510,13 @@ char strlist_item_as_char(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- char result = (char) strtol(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return CHAR_MAX;
+ }
+
+ char result = (char) strtol(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -525,7 +535,13 @@ unsigned char strlist_item_as_uchar(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- unsigned char result = (unsigned char) strtoul(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return UCHAR_MAX;
+ }
+
+ unsigned char result = (unsigned char) strtoul(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -544,7 +560,12 @@ short strlist_item_as_short(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- short result = (short) strtol(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return SHRT_MAX;
+ }
+ short result = (short) strtol(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -563,7 +584,13 @@ unsigned short strlist_item_as_ushort(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- unsigned short result = (unsigned short) strtoul(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return USHRT_MAX;
+ }
+
+ unsigned short result = (unsigned short) strtoul(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -582,7 +609,13 @@ int strlist_item_as_int(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- int result = (int) strtol(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return INT_MAX;
+ }
+
+ int result = (int) strtol(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -601,7 +634,13 @@ unsigned int strlist_item_as_uint(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- unsigned int result = (unsigned int) strtoul(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return UINT_MAX;
+ }
+
+ unsigned int result = (unsigned int) strtoul(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -620,7 +659,13 @@ long strlist_item_as_long(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- long result = (long) strtol(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return LONG_MAX;
+ }
+
+ long result = (long) strtol(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -639,7 +684,13 @@ unsigned long strlist_item_as_ulong(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- unsigned long result = (unsigned long) strtoul(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return ULONG_MAX;
+ }
+
+ unsigned long result = (unsigned long) strtoul(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -658,7 +709,13 @@ long long strlist_item_as_long_long(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- long long result = (long long) strtoll(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return LONG_LONG_MAX;
+ }
+
+ long long result = (long long) strtoll(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -677,7 +734,13 @@ unsigned long long strlist_item_as_ulong_long(struct StrList *pStrList, size_t i
char *error_p;
strlist_clear_error();
- unsigned long long result = (unsigned long long) strtol(strlist_item(pStrList, index), &error_p, 10);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return ULONG_LONG_MAX;
+ }
+
+ unsigned long long result = (unsigned long long) strtol(item, &error_p, 10);
if (!result && error_p && *error_p != 0) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -696,7 +759,13 @@ float strlist_item_as_float(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- const float result = strtof(strlist_item(pStrList, index), &error_p);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return HUGE_VALF;
+ }
+
+ const float result = strtof(item, &error_p);
if ((result == FLT_MIN || result == HUGE_VALF) && errno == ERANGE) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -715,7 +784,13 @@ double strlist_item_as_double(struct StrList *pStrList, size_t index) {
char *error_p;
strlist_clear_error();
- const double result = strtod(strlist_item(pStrList, index), &error_p);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return HUGE_VAL;
+ }
+
+ const double result = strtod(item, &error_p);
if ((result == DBL_MIN || result == HUGE_VAL) && errno == ERANGE) {
strlist_set_error(STRLIST_E_INVALID_VALUE);
return 0;
@@ -734,7 +809,13 @@ long double strlist_item_as_long_double(struct StrList *pStrList, size_t index)
char *error_p;
strlist_clear_error();
- const long double result = strtold(strlist_item(pStrList, index), &error_p);
+ char *item = strlist_item(pStrList, index);
+ if (!item) {
+ strlist_set_error(STRLIST_E_INVALID_VALUE);
+ return LDBL_MAX;
+ }
+
+ const long double result = strtold(item, &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 f0fd38f..d0956f4 100644
--- a/src/lib/core/system.c
+++ b/src/lib/core/system.c
@@ -177,6 +177,7 @@ char *shell_output(const char *command, int *status) {
current_size += initial_size;
char *tmp = realloc(result, sizeof(*result) * current_size);
if (!tmp) {
+ guard_free(result);
return NULL;
}
result = tmp;
diff --git a/src/lib/core/template.c b/src/lib/core/template.c
index 00e0058..8396b1e 100644
--- a/src/lib/core/template.c
+++ b/src/lib/core/template.c
@@ -26,7 +26,7 @@ extern void tpl_reset() {
tpl_pool_func_used = 0;
}
-void tpl_register_func(char *key, void *tplfunc_ptr, int argc, void *data_in) {
+void tpl_register_func(char *key, tplfunc *tplfunc_ptr, int argc, void *data_in) {
struct tplfunc_frame *frame = calloc(1, sizeof(*frame));
if (!frame) {
SYSERROR("unable to allocate memory for function frame");
diff --git a/src/lib/core/template_func_proto.c b/src/lib/core/template_func_proto.c
index f28a1eb..54a8860 100644
--- a/src/lib/core/template_func_proto.c
+++ b/src/lib/core/template_func_proto.c
@@ -2,7 +2,7 @@
#include "delivery.h"
#include "github.h"
-int get_github_release_notes_tplfunc_entrypoint(void *frame, void *data_out) {
+int get_github_release_notes_tplfunc_entrypoint(struct tplfunc_frame *frame, void *data_out) {
char **output = (char **) data_out;
struct tplfunc_frame *f = (struct tplfunc_frame *) frame;
char *api_token = getenv("STASIS_GH_TOKEN");
@@ -17,7 +17,7 @@ int get_github_release_notes_tplfunc_entrypoint(void *frame, void *data_out) {
return result;
}
-int get_github_release_notes_auto_tplfunc_entrypoint(void *frame, void *data_out) {
+int get_github_release_notes_auto_tplfunc_entrypoint(struct tplfunc_frame *frame, void *data_out) {
int result = 0;
char **output = (char **) data_out;
struct tplfunc_frame *f = (struct tplfunc_frame *) frame;
@@ -68,7 +68,7 @@ int get_github_release_notes_auto_tplfunc_entrypoint(void *frame, void *data_out
return result;
}
-int get_junitxml_file_entrypoint(void *frame, void *data_out) {
+int get_junitxml_file_entrypoint(struct tplfunc_frame *frame, void *data_out) {
int result = 0;
char **output = (char **) data_out;
struct tplfunc_frame *f = (struct tplfunc_frame *) frame;
@@ -95,7 +95,7 @@ int get_junitxml_file_entrypoint(void *frame, void *data_out) {
return result;
}
-int get_basetemp_dir_entrypoint(void *frame, void *data_out) {
+int get_basetemp_dir_entrypoint(struct tplfunc_frame *frame, void *data_out) {
int result = 0;
char **output = (char **) data_out;
struct tplfunc_frame *f = (struct tplfunc_frame *) frame;
@@ -121,7 +121,7 @@ int get_basetemp_dir_entrypoint(void *frame, void *data_out) {
return result;
}
-int tox_run_entrypoint(void *frame, void *data_out) {
+int tox_run_entrypoint(struct tplfunc_frame *frame, void *data_out) {
char **output = (char **) data_out;
struct tplfunc_frame *f = (struct tplfunc_frame *) frame;
const struct Delivery *ctx = (const struct Delivery *) f->data_in;
diff --git a/src/lib/core/utils.c b/src/lib/core/utils.c
index 54c3dce..d869143 100644
--- a/src/lib/core/utils.c
+++ b/src/lib/core/utils.c
@@ -415,7 +415,11 @@ char *git_rev_parse(const char *path, char *args) {
if (!pp) {
return NULL;
}
- fgets(version, sizeof(version) - 1, pp);
+ if (fgets(version, sizeof(version) - 1, pp) == NULL) {
+ pclose(pp);
+ popd();
+ return NULL;
+ }
strip(version);
pclose(pp);
popd();
@@ -423,26 +427,28 @@ char *git_rev_parse(const char *path, char *args) {
}
void msg(unsigned type, char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+
FILE *stream = NULL;
char header[255];
char status[20];
if (type & STASIS_MSG_NOP) {
// quiet mode
+ va_end(args);
return;
}
if (!globals.verbose && type & STASIS_MSG_RESTRICT) {
// Verbose mode is not active
+ va_end(args);
return;
}
memset(header, 0, sizeof(header));
memset(status, 0, sizeof(status));
- va_list args;
- va_start(args, fmt);
-
stream = stdout;
fprintf(stream, "%s", STASIS_COLOR_RESET);
if (type & STASIS_MSG_ERROR) {
@@ -498,14 +504,10 @@ void debug_shell() {
char *xmkstemp(FILE **fp, const char *mode) {
int fd = -1;
- char tmpdir[PATH_MAX];
- char t_name[PATH_MAX * 2];
+ char tmpdir[PATH_MAX] = {0};
+ char t_name[PATH_MAX * 2] = {0};
- if (globals.tmpdir) {
- strncpy(tmpdir, globals.tmpdir, sizeof(tmpdir) - 1);
- } else {
- strncpy(tmpdir, "/tmp/stasis", sizeof(tmpdir) - 1);
- }
+ strncpy(tmpdir, globals.tmpdir ? globals.tmpdir : "/tmp/stasis", sizeof(tmpdir) - 1);
tmpdir[sizeof(tmpdir) - 1] = '\0';
if (mkdirs(tmpdir, 0700) < 0) {
@@ -523,23 +525,19 @@ char *xmkstemp(FILE **fp, const char *mode) {
}
*fp = fdopen(fd, mode);
if (!*fp) {
- // unable to open, die
- if (fd > 0)
- close(fd);
- *fp = NULL;
+ close(fd);
return NULL;
}
char *path = strdup(t_name);
if (!path) {
// strdup failed, die
- if (*fp) {
- // close the file handle
- fclose(*fp);
- *fp = NULL;
- }
- // fall through. path is NULL.
+ // close the file handle
+ fclose(*fp);
+ *fp = NULL;
+ return NULL;
}
+
return path;
}
@@ -607,10 +605,7 @@ int path_store(char **destptr, size_t maxlen, const char *base, const char *path
int xml_pretty_print_in_place(const char *filename, const char *pretty_print_prog, const char *pretty_print_args) {
int status = 0;
- char *tempfile = NULL;
char *result = NULL;
- FILE *fp = NULL;
- FILE *tmpfp = NULL;
char cmd[PATH_MAX];
if (!find_program(pretty_print_prog)) {
// Pretty printing is optional. 99% chance the XML data will
@@ -621,11 +616,18 @@ int xml_pretty_print_in_place(const char *filename, const char *pretty_print_pro
snprintf(cmd, sizeof(cmd), "%s %s %s", pretty_print_prog, pretty_print_args, filename);
result = shell_output(cmd, &status);
if (status || !result) {
- goto pretty_print_failed;
+ return status;
}
- tempfile = xmkstemp(&tmpfp, "w+");
- if (!tmpfp || !tempfile) {
+ int clean_up_fp = 0;
+ FILE *tmpfp = NULL;
+ char *tempfile = xmkstemp(&tmpfp, "w+");
+ if (!tempfile || !tmpfp) {
+ guard_free(tempfile);
+ if (tmpfp) {
+ fclose(tmpfp);
+ }
+ status = -1;
goto pretty_print_failed;
}
@@ -633,10 +635,12 @@ int xml_pretty_print_in_place(const char *filename, const char *pretty_print_pro
fflush(tmpfp);
fclose(tmpfp);
- fp = fopen(filename, "w+");
+ FILE *fp = fopen(filename, "w+");
if (!fp) {
+ status = -1;
goto pretty_print_failed;
}
+ clean_up_fp = 1;
if (copy2(tempfile, filename, CT_PERM)) {
SYSWARN("unable to copy: '%s' -> '%s'", tempfile, filename);
@@ -653,15 +657,16 @@ int xml_pretty_print_in_place(const char *filename, const char *pretty_print_pro
return 0;
pretty_print_failed:
- if (fp) {
- fclose(fp);
- }
- if (tmpfp) {
- fclose(tmpfp);
- }
- guard_free(tempfile);
- guard_free(result);
- return -1;
+ if (tempfile && remove(tempfile)) {
+ SYSWARN("unable to remove temporary file: %s", tempfile);
+ }
+ guard_free(tempfile);
+ guard_free(result);
+ if (clean_up_fp) {
+ fclose(fp);
+ }
+
+ return status;
}
/**
@@ -673,12 +678,15 @@ int xml_pretty_print_in_place(const char *filename, const char *pretty_print_pro
*/
int fix_tox_conf(const char *filename, char **result, size_t maxlen) {
struct INIFILE *toxini;
- FILE *fptemp;
+ FILE *fptemp = NULL;
// Create new temporary tox configuration file
char *tempfile = xmkstemp(&fptemp, "w+");
if (!tempfile) {
SYSERROR("unable to create temporary file");
+ if (fptemp) {
+ fclose(fptemp);
+ }
return -1;
}
@@ -687,6 +695,9 @@ int fix_tox_conf(const char *filename, char **result, size_t maxlen) {
*result = calloc(maxlen, sizeof(**result));
if (!*result) {
guard_free(tempfile);
+ if (fptemp) {
+ fclose(fptemp);
+ }
return -1;
}
}
@@ -724,6 +735,7 @@ int fix_tox_conf(const char *filename, char **result, size_t maxlen) {
strlen(value) + strlen(with_posargs) + 1);
guard_free(*result);
guard_free(tempfile);
+ fclose(fptemp);
return -1;
}
value = tmp;
@@ -1217,3 +1229,56 @@ int get_random_bytes(char *result, size_t maxlen) {
result[bytes ? bytes - 1 : 0] = '\0';
return 0;
}
+
+int non_format_len(const char *s) {
+ int len = 0;
+ int until_space = 0;
+ for (size_t i = 0; i < strlen(s); i++) {
+ if (until_space && isspace(s[i])) {
+ until_space = 0;
+ }
+ if (until_space && !isspace(s[i])) {
+ continue;
+ }
+ if (s[i] == '%') {
+ until_space = 1;
+ continue;
+ }
+ len++;
+ }
+ return len;
+}
+
+char *center_text(const char *s, const size_t maxwidth) {
+ if (maxwidth < 2) {
+ SYSERROR("%s", "maximum width must be greater than 0");
+ return NULL;
+ }
+
+ if (maxwidth % 2 != 0) {
+ SYSERROR("maximum width (%zu) must be even", maxwidth);
+ return NULL;
+ }
+
+ const size_t s_len = strlen(s);
+ if (s_len + 1 > maxwidth) {
+ SYSERROR("length of input string (%zu) exceeds maximum width (%zu)", s_len, maxwidth);
+ return NULL;
+ }
+
+ char *result = calloc(maxwidth + 1, sizeof(*result));
+ if (!result) {
+ SYSERROR("%s", "unable to allocate bytes for centered text string");
+ return NULL;
+ }
+ const size_t middle = (maxwidth / 2) - s_len / 2;
+ size_t i = 0;
+ for (; i < middle; i++) {
+ result[i] = ' ';
+ }
+ strncpy(&result[i], s, maxwidth - middle - 1);
+ result[maxwidth] = '\0';
+
+ return result;
+}
+
diff --git a/src/lib/core/wheel.c b/src/lib/core/wheel.c
index ea2089a..e94060a 100644
--- a/src/lib/core/wheel.c
+++ b/src/lib/core/wheel.c
@@ -172,7 +172,7 @@ static ssize_t wheel_parse_metadata(struct WheelMetadata * const pkg, const char
return -1;
}
- pkg->provides_extra = calloc(WHEEL_MAXELEM + 1, sizeof(pkg->provides_extra[0]));
+ pkg->provides_extra = calloc(WHEEL_MAXELEM + 1, sizeof(*pkg->provides_extra));
if (!pkg->provides_extra) {
// memory error
return -1;
@@ -539,6 +539,10 @@ static ssize_t wheel_parse_metadata(struct WheelMetadata * const pkg, const char
return -1;
}
current_extra = pkg->provides_extra[provides_extra_i];
+ if (!current_extra) {
+ SYSERROR("%s", "provides_extra array cannot have a NULL record");
+ return -1;
+ }
current_extra->target = strdup(value);
if (!current_extra->target) {
// memory error
@@ -688,8 +692,8 @@ static int wheel_metadata_get(const struct Wheel *pkg, const char *wheel_filenam
if (wheel_get_file_contents(wheel_filename, "*.dist-info/METADATA", &data)) {
return -1;
}
- const ssize_t result = wheel_parse_metadata(pkg->metadata, data);
char *data_orig = data;
+ const ssize_t result = wheel_parse_metadata(pkg->metadata, data);
guard_free(data_orig);
return (int) result;
}
@@ -953,6 +957,9 @@ void wheel_entry_point_free(struct WheelEntryPoint **entry) {
}
void wheel_metadata_free(struct WheelMetadata *meta) {
+ if (!meta) {
+ return;
+ }
guard_free(meta->license);
guard_free(meta->license_expression);
guard_free(meta->version);
@@ -975,18 +982,22 @@ void wheel_metadata_free(struct WheelMetadata *meta) {
guard_strlist_free(&meta->requires_dist);
guard_strlist_free(&meta->keywords);
guard_strlist_free(&meta->license_file);
-
- for (size_t i = 0; meta->provides_extra[i] != NULL; i++) {
- guard_free(meta->provides_extra[i]->target);
- guard_strlist_free(&meta->provides_extra[i]->requires_dist);
- guard_free(meta->provides_extra[i]);
+ if (meta->provides_extra) {
+ for (size_t i = 0; meta->provides_extra[i] != NULL; i++) {
+ guard_free(meta->provides_extra[i]->target);
+ guard_strlist_free(&meta->provides_extra[i]->requires_dist);
+ guard_free(meta->provides_extra[i]);
+ }
+ guard_free(meta->provides_extra);
}
- guard_free(meta->provides_extra);
guard_free(meta);
}
void wheel_package_free(struct Wheel **pkg) {
+ if (!*pkg) {
+ return;
+ }
guard_free((*pkg)->wheel_version);
guard_free((*pkg)->generator);
guard_free((*pkg)->root_is_pure_lib);
@@ -997,7 +1008,7 @@ void wheel_package_free(struct Wheel **pkg) {
for (size_t i = 0; (*pkg)->record && (*pkg)->record[i] != NULL; i++) {
wheel_record_free(&(*pkg)->record[i]);
}
- guard_free((*pkg)->record);
+ guard_array_n_free((*pkg)->record, (*pkg)->num_record);
for (size_t i = 0; (*pkg)->entry_point && (*pkg)->entry_point[i] != NULL; i++) {
wheel_entry_point_free(&(*pkg)->entry_point[i]);
@@ -1122,13 +1133,14 @@ int wheel_get_entry_point(struct Wheel *pkg, const char *filename) {
usable_lines--;
}
}
+ pkg->num_entry_point = usable_lines;
- pkg->entry_point = calloc(usable_lines + 1, sizeof(*pkg->entry_point));
+ pkg->entry_point = calloc(pkg->num_entry_point + 1, sizeof(*pkg->entry_point));
if (!pkg->entry_point) {
goto GEP_FAIL;
}
- for (size_t i = 0; i < usable_lines; i++) {
+ for (size_t i = 0; i < pkg->num_entry_point; i++) {
pkg->entry_point[i] = calloc(1, sizeof(*pkg->entry_point[0]));
if (!pkg->entry_point[i]) {
goto GEP_FAIL;
@@ -1186,6 +1198,9 @@ int wheel_get_entry_point(struct Wheel *pkg, const char *filename) {
return 0;
GEP_FAIL:
+ if (pkg->entry_point) {
+ guard_array_n_free(pkg->entry_point, pkg->num_entry_point);
+ }
guard_strlist_free(&lines);
guard_free(data);
return -1;
@@ -1332,41 +1347,54 @@ int wheel_show_info(const struct Wheel *wheel) {
}
int wheel_package(struct Wheel **pkg, const char *filename) {
+ int status = 0;
if (!filename) {
- return WHEEL_PACKAGE_E_FILENAME;
+ status = WHEEL_PACKAGE_E_FILENAME;
+ goto fail;
}
if (!*pkg) {
*pkg = calloc(1, sizeof(**pkg));
if (!*pkg) {
- return WHEEL_PACKAGE_E_ALLOC;
+ status = WHEEL_PACKAGE_E_ALLOC;
+ goto fail;
}
(*pkg)->metadata = calloc(1, sizeof(*(*pkg)->metadata));
if (!(*pkg)->metadata) {
- guard_free(*pkg);
- return WHEEL_PACKAGE_E_ALLOC;
+ status = WHEEL_PACKAGE_E_ALLOC;
+ goto fail;
}
}
if (wheel_get(pkg, filename) < 0) {
- return WHEEL_PACKAGE_E_GET;
+ status = WHEEL_PACKAGE_E_GET;
+ goto fail;
}
if (wheel_metadata_get(*pkg, filename) < 0) {
- return WHEEL_PACKAGE_E_GET_METADATA;
+ status = WHEEL_PACKAGE_E_GET_METADATA;
+ goto fail;
}
if (wheel_get_top_level(*pkg, filename) < 0) {
- return WHEEL_PACKAGE_E_GET_TOP_LEVEL;
+ status = WHEEL_PACKAGE_E_GET_TOP_LEVEL;
+ goto fail;
}
if (wheel_get_records(*pkg, filename) < 0) {
- return WHEEL_PACKAGE_E_GET_RECORDS;
+ status = WHEEL_PACKAGE_E_GET_RECORDS;
+ goto fail;
}
if (wheel_get_entry_point(*pkg, filename) < 0) {
- return WHEEL_PACKAGE_E_GET_ENTRY_POINT;
+ status = WHEEL_PACKAGE_E_GET_ENTRY_POINT;
+ goto fail;
}
// Optional marker
wheel_get_zip_safe(*pkg, filename);
- return WHEEL_PACKAGE_E_SUCCESS;
+ status = WHEEL_PACKAGE_E_SUCCESS;
+ return status;
+
+ fail:
+ wheel_package_free(pkg);
+ return status;
}