aboutsummaryrefslogtreecommitdiff
path: root/src/cli
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@users.noreply.github.com>2026-04-21 12:15:11 -0400
committerGitHub <noreply@github.com>2026-04-21 12:15:11 -0400
commite05702d1818088439fd017786a036103062db358 (patch)
tree379773aaaae0193d1a53583646b48e23edd817a5 /src/cli
parent2258cd05bcded0125136c17d51568831ac421bf7 (diff)
parent577912ff0e1996b9846db00247648abd828a8f43 (diff)
downloadstasis-e05702d1818088439fd017786a036103062db358.tar.gz
Merge pull request #134 from jhunkeler/sprintf-to-snprintf
String safety
Diffstat (limited to 'src/cli')
-rw-r--r--src/cli/stasis/args.c20
-rw-r--r--src/cli/stasis/stasis_main.c20
-rw-r--r--src/cli/stasis_indexer/args.c2
-rw-r--r--src/cli/stasis_indexer/helpers.c48
-rw-r--r--src/cli/stasis_indexer/junitxml_report.c4
-rw-r--r--src/cli/stasis_indexer/readmes.c10
-rw-r--r--src/cli/stasis_indexer/stasis_indexer_main.c35
-rw-r--r--src/cli/stasis_indexer/website.c12
8 files changed, 83 insertions, 68 deletions
diff --git a/src/cli/stasis/args.c b/src/cli/stasis/args.c
index dbc9c2f..98b4479 100644
--- a/src/cli/stasis/args.c
+++ b/src/cli/stasis/args.c
@@ -85,28 +85,30 @@ void usage(char *progname) {
int width = get_option_max_width(long_options);
for (int x = 0; long_options[x].name != 0; x++) {
char tmp[STASIS_NAME_MAX] = {0};
- char output[sizeof(tmp)] = {0};
+ char output[STASIS_NAME_MAX] = {0};
char opt_long[50] = {0}; // --? [ARG]?
char opt_short[50] = {0}; // -? [ARG]?
- strcat(opt_long, "--");
- strcat(opt_long, long_options[x].name);
+ strncat(opt_long, "--", sizeof(opt_long) - strlen(opt_long) - 1);
+ strncat(opt_long, long_options[x].name, sizeof(opt_long) - strlen(opt_long) - 1);
if (long_options[x].has_arg) {
- strcat(opt_long, " ARG");
+ strncat(opt_long, " ARG", sizeof(opt_long) - strlen(opt_long) - 1);
}
if (long_options[x].val <= 'z') {
- strcat(opt_short, "-");
+ strncat(opt_short, "-", sizeof(opt_short) - strlen(opt_short) - 1);
opt_short[1] = (char) long_options[x].val;
if (long_options[x].has_arg) {
- strcat(opt_short, " ARG");
+ strncat(opt_short, " ARG", sizeof(opt_short) - strlen(opt_short) - 1);
}
} else {
- strcat(opt_short, " ");
+ strncat(opt_short, " ", sizeof(opt_short) - strlen(opt_short) - 1);
}
- sprintf(tmp, " %%-%ds\t%%s\t\t%%s", width + 4);
- sprintf(output, tmp, opt_long, opt_short, long_options_help[x]);
+ const char *opt_fmt = " %%-%ds\t%%s\t\t%%s";
+ size_t opt_fmt_len = snprintf(NULL, 0, opt_fmt, width);
+ snprintf(tmp, sizeof(tmp) - opt_fmt_len, opt_fmt, width + 4);
+ snprintf(output, sizeof(output), tmp, opt_long, opt_short, long_options_help[x]);
puts(output);
}
}
diff --git a/src/cli/stasis/stasis_main.c b/src/cli/stasis/stasis_main.c
index 44efc4a..328d825 100644
--- a/src/cli/stasis/stasis_main.c
+++ b/src/cli/stasis/stasis_main.c
@@ -45,7 +45,7 @@ static void configure_stasis_ini(struct Delivery *ctx, char **config_input) {
if (!*config_input) {
SYSDEBUG("%s", "No configuration passed by argument. Using basic config.");
char cfgfile[PATH_MAX * 2];
- sprintf(cfgfile, "%s/%s", globals.sysconfdir, "stasis.ini");
+ snprintf(cfgfile, sizeof(cfgfile), "%s/%s", globals.sysconfdir, "stasis.ini");
SYSDEBUG("cfgfile: %s", cfgfile);
if (!access(cfgfile, F_OK | R_OK)) {
*config_input = strdup(cfgfile);
@@ -161,9 +161,9 @@ static void check_conda_prefix_length(const struct Delivery *ctx) {
}
}
-static void setup_conda(struct Delivery *ctx, char *installer_url) {
+static void setup_conda(struct Delivery *ctx, char *installer_url, const size_t maxlen) {
msg(STASIS_MSG_L1, "Conda setup\n");
- delivery_get_conda_installer_url(ctx, installer_url);
+ delivery_get_conda_installer_url(ctx, installer_url, maxlen);
msg(STASIS_MSG_L2, "Downloading: %s\n", installer_url);
if (delivery_get_conda_installer(ctx, installer_url)) {
msg(STASIS_MSG_ERROR, "download failed: %s\n", installer_url);
@@ -429,7 +429,7 @@ static void build_docker(struct Delivery *ctx, const int disabled) {
msg(STASIS_MSG_L1 | STASIS_MSG_WARN, "Docker image building is disabled by CLI argument\n");
} else {
char dockerfile[PATH_MAX] = {0};
- sprintf(dockerfile, "%s/%s", ctx->storage.build_docker_dir, "Dockerfile");
+ snprintf(dockerfile, sizeof(dockerfile), "%s/%s", ctx->storage.build_docker_dir, "Dockerfile");
if (globals.enable_docker) {
if (!access(dockerfile, F_OK)) {
msg(STASIS_MSG_L1, "Building Docker image\n");
@@ -461,7 +461,7 @@ static void generate_release(struct Delivery *ctx, char *env_name, char *env_nam
delivery_export(ctx, (char *[]) {env_name, env_name_testing, NULL});
char specfile[PATH_MAX];
- sprintf(specfile, "%s/%s.yml", ctx->storage.delivery_dir, env_name);
+ snprintf(specfile, sizeof(specfile), "%s/%s.yml", ctx->storage.delivery_dir, env_name);
delivery_rewrite_stage1(ctx, specfile);
build_docker(ctx, disable_docker);
@@ -532,7 +532,7 @@ int main(int argc, char *argv[]) {
globals.continue_on_error = true;
break;
case 'p':
- strcpy(python_override_version, optarg);
+ strncpy(python_override_version, optarg, sizeof(python_override_version) - 1);
break;
case 'l':
globals.cpu_limit = strtol(optarg, NULL, 10);
@@ -652,9 +652,9 @@ int main(int argc, char *argv[]) {
configure_jfrog_cli(&ctx);
runtime_apply(ctx.runtime.environ);
- strcpy(env_name, ctx.info.release_name);
- strcpy(env_name_testing, env_name);
- strcat(env_name_testing, "-test");
+ strncpy(env_name, ctx.info.release_name, sizeof(env_name) - 1);
+ strncpy(env_name_testing, env_name, sizeof(env_name_testing) - 1);
+ strncat(env_name_testing, "-test", sizeof(env_name_testing) - strlen(env_name_testing) - 1);
char *envs[] = {
"release", env_name,
"testing", env_name_testing,
@@ -666,7 +666,7 @@ int main(int argc, char *argv[]) {
check_conda_install_prefix(&ctx);
check_conda_prefix_length(&ctx);
- setup_conda(&ctx, installer_url);
+ setup_conda(&ctx, installer_url, sizeof(installer_url));
configure_conda_base(&ctx, envs);
configure_conda_purge(&ctx, envs);
setup_activate_test_env(&ctx, env_name_testing);
diff --git a/src/cli/stasis_indexer/args.c b/src/cli/stasis_indexer/args.c
index 2d92ab0..8c9d3fe 100644
--- a/src/cli/stasis_indexer/args.c
+++ b/src/cli/stasis_indexer/args.c
@@ -30,7 +30,7 @@ void usage(char *name) {
for (int i = 0; i < maxopts - 1; i++) {
char line[255] = {0};
- sprintf(line, " --%s -%c %-20s", long_options[i].name, long_options[i].val, long_options_help[i]);
+ snprintf(line, sizeof(line), " --%s -%c %-20s", long_options[i].name, long_options[i].val, long_options_help[i]);
puts(line);
}
diff --git a/src/cli/stasis_indexer/helpers.c b/src/cli/stasis_indexer/helpers.c
index 6dc653d..0debfe4 100644
--- a/src/cli/stasis_indexer/helpers.c
+++ b/src/cli/stasis_indexer/helpers.c
@@ -96,44 +96,44 @@ int pandoc_exec(const char *in_file, const char *out_file, const char *css_file,
if (!get_pandoc_version(&pandoc_version)) {
// < 2.19
if (pandoc_version < 0x02130000) {
- strcat(pandoc_versioned_args, "--self-contained ");
+ strncat(pandoc_versioned_args, "--self-contained ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1);
} else {
// >= 2.19
- strcat(pandoc_versioned_args, "--embed-resources ");
+ strncat(pandoc_versioned_args, "--embed-resources ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1);
}
// >= 1.15.0.4
if (pandoc_version >= 0x010f0004) {
- strcat(pandoc_versioned_args, "--standalone ");
+ strncat(pandoc_versioned_args, "--standalone ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1);
}
// >= 1.10.0.1
if (pandoc_version >= 0x010a0001) {
- strcat(pandoc_versioned_args, "-f gfm+autolink_bare_uris ");
+ strncat(pandoc_versioned_args, "-f gfm+autolink_bare_uris ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1);
}
// > 3.1.9
if (pandoc_version > 0x03010900) {
- strcat(pandoc_versioned_args, "-f gfm+alerts ");
+ strncat(pandoc_versioned_args, "-f gfm+alerts ", sizeof(pandoc_versioned_args) - strlen(pandoc_versioned_args) - 1);
}
}
// Converts a markdown file to html
char cmd[STASIS_BUFSIZ] = {0};
- strcpy(cmd, "pandoc ");
- strcat(cmd, pandoc_versioned_args);
+ strncpy(cmd, "pandoc ", sizeof(cmd) - 1);
+ strncat(cmd, pandoc_versioned_args, sizeof(cmd) - strlen(cmd) - 1);
if (css_file && strlen(css_file)) {
- strcat(cmd, "--css ");
- strcat(cmd, css_file);
+ strncat(cmd, "--css ", sizeof(cmd) - strlen(cmd) - 1);
+ strncat(cmd, css_file, sizeof(cmd) - strlen(cmd) - 1);
}
- strcat(cmd, " ");
- strcat(cmd, "--metadata title=\"");
- strcat(cmd, title);
- strcat(cmd, "\" ");
- strcat(cmd, "-o ");
- strcat(cmd, out_file);
- strcat(cmd, " ");
- strcat(cmd, in_file);
+ strncat(cmd, " ", sizeof(cmd) - strlen(cmd) - 1);
+ strncat(cmd, "--metadata title=\"", sizeof(cmd) - strlen(cmd) - 1);
+ strncat(cmd, title, sizeof(cmd) - strlen(cmd) - 1);
+ strncat(cmd, "\" ", sizeof(cmd) - strlen(cmd) - 1);
+ strncat(cmd, "-o ", sizeof(cmd) - strlen(cmd) - 1);
+ strncat(cmd, out_file, sizeof(cmd) - strlen(cmd) - 1);
+ strncat(cmd, " ", sizeof(cmd) - strlen(cmd) - 1);
+ strncat(cmd, in_file, sizeof(cmd) - strlen(cmd) - 1);
if (globals.verbose) {
puts(cmd);
@@ -243,7 +243,15 @@ int get_files(struct StrList **out, const char *path, const char *pattern, ...)
va_list args;
va_start(args, pattern);
char userpattern[PATH_MAX] = {0};
- vsprintf(userpattern, pattern, args);
+ const int len = vsnprintf(userpattern, sizeof(userpattern), pattern, args);
+ if (len < 0) {
+ SYSERROR("%s", "vsnprintf failed\n");
+ va_end(args);
+ return -1;
+ }
+ if ((size_t) len > sizeof(userpattern)) {
+ fprintf(stderr, "WARNING: %s: userpattern truncated!\n", __FUNCTION__);
+ }
va_end(args);
if (!strlen(userpattern)) {
userpattern[0] = '*';
@@ -377,8 +385,8 @@ int write_manifest(const char *path, char **exclude_path, FILE *fp) {
}
char filepath[PATH_MAX] = {0};
strncpy(filepath, path, PATH_MAX - 1);
- strcat(filepath, "/");
- strcat(filepath, rec->d_name);
+ strncat(filepath, "/", sizeof(filepath) - strlen(filepath) - 1);
+ strncat(filepath, rec->d_name, sizeof(filepath) - strlen(filepath) - 1);
if (rec->d_type == DT_DIR) {
write_manifest(filepath, exclude_path, fp);
continue;
diff --git a/src/cli/stasis_indexer/junitxml_report.c b/src/cli/stasis_indexer/junitxml_report.c
index 21cf729..d30ee09 100644
--- a/src/cli/stasis_indexer/junitxml_report.c
+++ b/src/cli/stasis_indexer/junitxml_report.c
@@ -98,7 +98,7 @@ static int write_report_output(struct Delivery *ctx, FILE *destfp, const char *x
int indexer_junitxml_report(struct Delivery **ctx, const size_t nelem) {
char indexfile[PATH_MAX] = {0};
- sprintf(indexfile, "%s/README.md", (*ctx)->storage.results_dir);
+ snprintf(indexfile, sizeof(indexfile), "%s/README.md", (*ctx)->storage.results_dir);
struct StrList *file_listing = listdir((*ctx)->storage.results_dir);
if (!file_listing) {
@@ -117,7 +117,7 @@ int indexer_junitxml_report(struct Delivery **ctx, const size_t nelem) {
int current_rc = (*ctx)->meta.rc;
for (size_t d = 0; d < nelem; d++) {
char pattern[PATH_MAX] = {0};
- snprintf(pattern, sizeof(pattern) - 1, "*%s*", ctx[d]->info.release_name);
+ snprintf(pattern, sizeof(pattern), "*%s*", ctx[d]->info.release_name);
// if the result directory contains tests for this release name, print them
if (!is_file_in_listing(file_listing, pattern)) {
diff --git a/src/cli/stasis_indexer/readmes.c b/src/cli/stasis_indexer/readmes.c
index edc6312..91c936f 100644
--- a/src/cli/stasis_indexer/readmes.c
+++ b/src/cli/stasis_indexer/readmes.c
@@ -12,7 +12,7 @@ int indexer_readmes(struct Delivery **ctx, const size_t nelem) {
}
char indexfile[PATH_MAX] = {0};
- sprintf(indexfile, "%s/README.md", (*ctx)->storage.delivery_dir);
+ snprintf(indexfile, sizeof(indexfile), "%s/README.md", (*ctx)->storage.delivery_dir);
FILE *indexfp = fopen(indexfile, "w+");
if (!indexfp) {
@@ -52,10 +52,10 @@ int indexer_readmes(struct Delivery **ctx, const size_t nelem) {
if (!latest_deliveries[i]->meta.name) {
continue;
}
- sprintf(link_name, "latest-py%s-%s-%s.yml", latest_deliveries[i]->meta.python_compact, latest_deliveries[i]->system.platform[DELIVERY_PLATFORM_RELEASE], latest_deliveries[i]->system.arch);
- sprintf(readme_name, "README-py%s-%s-%s.md", latest_deliveries[i]->meta.python_compact, latest_deliveries[i]->system.platform[DELIVERY_PLATFORM_RELEASE], latest_deliveries[i]->system.arch);
- sprintf(conf_name, "%s.ini", latest_deliveries[i]->info.release_name);
- sprintf(conf_name_relative, "../config/%s.ini", latest_deliveries[i]->info.release_name);
+ snprintf(link_name, sizeof(link_name), "latest-py%s-%s-%s.yml", latest_deliveries[i]->meta.python_compact, latest_deliveries[i]->system.platform[DELIVERY_PLATFORM_RELEASE], latest_deliveries[i]->system.arch);
+ snprintf(readme_name, sizeof(readme_name), "README-py%s-%s-%s.md", latest_deliveries[i]->meta.python_compact, latest_deliveries[i]->system.platform[DELIVERY_PLATFORM_RELEASE], latest_deliveries[i]->system.arch);
+ snprintf(conf_name, sizeof(conf_name), "%s.ini", latest_deliveries[i]->info.release_name);
+ snprintf(conf_name_relative, sizeof(conf_name_relative), "../config/%s.ini", latest_deliveries[i]->info.release_name);
if (strstr(link_name, platform) && strstr(link_name, arch)) {
fprintf(indexfp, "- Python %s\n", latest_deliveries[i]->meta.python);
fprintf(indexfp, " - Info: [README](%s)\n", readme_name);
diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c
index 840e897..d475c15 100644
--- a/src/cli/stasis_indexer/stasis_indexer_main.c
+++ b/src/cli/stasis_indexer/stasis_indexer_main.c
@@ -13,9 +13,9 @@ int indexer_combine_rootdirs(const char *dest, char **rootdirs, const size_t roo
char destdir_with_output[PATH_MAX] = {0};
char *destdir = destdir_bare;
- strcpy(destdir_bare, dest);
- strcpy(destdir_with_output, dest);
- strcat(destdir_with_output, "/output");
+ strncpy(destdir_bare, dest, sizeof(destdir_bare) - 1);
+ strncpy(destdir_with_output, dest, sizeof(destdir_with_output) - 1);
+ strncat(destdir_with_output, "/output", sizeof(destdir_with_output) - strlen(destdir_with_output) - 1);
if (!access(destdir_with_output, F_OK)) {
destdir = destdir_with_output;
@@ -26,9 +26,9 @@ int indexer_combine_rootdirs(const char *dest, char **rootdirs, const size_t roo
char srcdir_bare[PATH_MAX] = {0};
char srcdir_with_output[PATH_MAX] = {0};
char *srcdir = srcdir_bare;
- strcpy(srcdir_bare, rootdirs[i]);
- strcpy(srcdir_with_output, rootdirs[i]);
- strcat(srcdir_with_output, "/output");
+ strncpy(srcdir_bare, rootdirs[i], sizeof(srcdir_bare) - 1);
+ strncpy(srcdir_with_output, rootdirs[i], sizeof(srcdir_with_output) - 1);
+ strncat(srcdir_with_output, "/output", sizeof(srcdir_with_output) - strlen(srcdir_with_output) - 1);
if (access(srcdir_bare, F_OK)) {
fprintf(stderr, "%s does not exist\n", srcdir_bare);
@@ -80,11 +80,11 @@ int indexer_symlinks(struct Delivery **ctx, const size_t nelem) {
if (!data[i]->meta.name) {
continue;
}
- sprintf(link_name_spec, "latest-py%s-%s-%s.yml", data[i]->meta.python_compact, data[i]->system.platform[DELIVERY_PLATFORM_RELEASE], data[i]->system.arch);
- sprintf(file_name_spec, "%s.yml", data[i]->info.release_name);
+ snprintf(link_name_spec, sizeof(link_name_spec), "latest-py%s-%s-%s.yml", data[i]->meta.python_compact, data[i]->system.platform[DELIVERY_PLATFORM_RELEASE], data[i]->system.arch);
+ snprintf(file_name_spec, sizeof(file_name_spec), "%s.yml", data[i]->info.release_name);
- sprintf(link_name_readme, "README-py%s-%s-%s.md", data[i]->meta.python_compact, data[i]->system.platform[DELIVERY_PLATFORM_RELEASE], data[i]->system.arch);
- sprintf(file_name_readme, "README-%s.md", data[i]->info.release_name);
+ snprintf(link_name_readme, sizeof(link_name_readme), "README-py%s-%s-%s.md", data[i]->meta.python_compact, data[i]->system.platform[DELIVERY_PLATFORM_RELEASE], data[i]->system.arch);
+ snprintf(file_name_readme, sizeof(file_name_readme), "README-%s.md", data[i]->info.release_name);
if (!access(link_name_spec, F_OK)) {
if (unlink(link_name_spec)) {
@@ -151,7 +151,7 @@ void indexer_init_dirs(struct Delivery *ctx, const char *workdir) {
char newpath[PATH_MAX] = {0};
if (getenv("PATH")) {
- sprintf(newpath, "%s/bin:%s", ctx->storage.tools_dir, getenv("PATH"));
+ snprintf(newpath, sizeof(newpath), "%s/bin:%s", ctx->storage.tools_dir, getenv("PATH"));
setenv("PATH", newpath, 1);
} else {
SYSERROR("%s", "environment variable PATH is undefined. Unable to continue.");
@@ -261,11 +261,11 @@ int main(const int argc, char *argv[]) {
char workdir_template[PATH_MAX] = {0};
const char *system_tmp = getenv("TMPDIR");
if (system_tmp) {
- strcat(workdir_template, system_tmp);
+ strncat(workdir_template, system_tmp, sizeof(workdir_template) - strlen(workdir_template) - 1);
} else {
- strcat(workdir_template, "/tmp");
+ strncat(workdir_template, "/tmp", sizeof(workdir_template) - strlen(workdir_template) - 1);
}
- strcat(workdir_template, "/stasis-combine.XXXXXX");
+ strncat(workdir_template, "/stasis-combine.XXXXXX", sizeof(workdir_template) - strlen(workdir_template) - 1);
char *workdir = mkdtemp(workdir_template);
if (!workdir) {
SYSERROR("Unable to create temporary directory: %s", workdir_template);
@@ -320,6 +320,11 @@ int main(const int argc, char *argv[]) {
msg(STASIS_MSG_L1, "Loading metadata\n");
struct StrList *metafiles = NULL;
get_files(&metafiles, ctx.storage.meta_dir, "*.stasis");
+ if (!metafiles || !strlist_count(metafiles)) {
+ SYSERROR("%s: No metadata!", ctx.storage.meta_dir);
+ delivery_free(&ctx);
+ exit(1);
+ }
strlist_sort(metafiles, STASIS_SORT_LEN_ASCENDING);
struct Delivery **local = calloc(strlist_count(metafiles) + 1, sizeof(*local));
@@ -411,7 +416,7 @@ int main(const int argc, char *argv[]) {
msg(STASIS_MSG_L1, "Copying indexed delivery to '%s'\n", destdir);
char cmd[PATH_MAX] = {0};
- sprintf(cmd, "rsync -ah%s --delete --exclude 'tmp/' --exclude 'tools/' '%s/' '%s/'", globals.verbose ? "v" : "q", workdir, destdir);
+ snprintf(cmd, sizeof(cmd), "rsync -ah%s --delete --exclude 'tmp/' --exclude 'tools/' '%s/' '%s/'", globals.verbose ? "v" : "q", workdir, destdir);
guard_free(destdir);
if (globals.verbose) {
diff --git a/src/cli/stasis_indexer/website.c b/src/cli/stasis_indexer/website.c
index 966391e..8a5126d 100644
--- a/src/cli/stasis_indexer/website.c
+++ b/src/cli/stasis_indexer/website.c
@@ -8,7 +8,7 @@ int indexer_make_website(struct Delivery **ctx) {
return -1;
}
- sprintf(css_filename, "%s/%s", globals.sysconfdir, "stasis_pandoc.css");
+ snprintf(css_filename, PATH_MAX, "%s/%s", globals.sysconfdir, "stasis_pandoc.css");
const int have_css = access(css_filename, F_OK | R_OK) == 0;
struct StrList *dirs = strlist_init();
@@ -29,14 +29,14 @@ int indexer_make_website(struct Delivery **ctx) {
char *filename = path_basename(strlist_item(inputs, x));
char fullpath_src[PATH_MAX] = {0};
char fullpath_dest[PATH_MAX] = {0};
- sprintf(fullpath_src, "%s/%s", root, filename);
+ snprintf(fullpath_src, sizeof(fullpath_src), "%s/%s", root, filename);
if (access(fullpath_src, F_OK)) {
continue;
}
// Replace *.md extension with *.html.
- strcpy(fullpath_dest, fullpath_src);
- gen_file_extension_str(fullpath_dest, ".html");
+ strncpy(fullpath_dest, fullpath_src, sizeof(fullpath_dest) - 1);
+ gen_file_extension_str(fullpath_dest, sizeof(fullpath_dest), ".html");
// Convert markdown to html
if (pandoc_exec(fullpath_src, fullpath_dest, have_css ? css_filename : NULL, "STASIS")) {
@@ -52,8 +52,8 @@ int indexer_make_website(struct Delivery **ctx) {
if (!strcmp(filename, "README.md")) {
char link_from[PATH_MAX] = {0};
char link_dest[PATH_MAX] = {0};
- strcpy(link_from, "README.html");
- sprintf(link_dest, "%s/%s", root, "index.html");
+ strncpy(link_from, "README.html", sizeof(link_from) - 1);
+ snprintf(link_dest, sizeof(link_dest), "%s/%s", root, "index.html");
if (symlink(link_from, link_dest)) {
SYSERROR("Warning: symlink(%s, %s) failed: %s", link_from, link_dest, strerror(errno));
}