From: Rusty Russell Date: Mon, 13 Oct 2025 03:38:56 +0000 (+1030) Subject: global: avoid using sprintf. X-Git-Url: https://git.ozlabs.org/?a=commitdiff_plain;h=9d97f36eff481b1b6168a07fee1caa7bf56d9981;p=ccan global: avoid using sprintf. snprintf has different footguns, but MacOS started complaining, a-la: Core Lightning fails to compile on macOS with the latest Command Line Tools (macOS 15 SDK) due to sprintf being marked as deprecated and -Werror treating the deprecation as a compilation error. Environment: Sequoia 15.6.1 (24G90) SDK Version: MacOSX15.sdk ``` ccan/ccan/closefrom/closefrom.c:83:2: error: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Werror,-Wdeprecated-declarations] 83 | sprintf(dnam, "/proc/%ld/fd", (long) getpid()); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/_stdio.h:278:1: note: 'sprintf' has been explicitly marked deprecated here 278 | deprecated_msg("This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead.") | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:218:48: note: expanded from macro 'deprecated_msg' 218 | #define deprecated_msg(_msg) attribute((deprecated(_msg))) | ^ ccan/ccan/closefrom/closefrom.c:162:2: error: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Werror,-Wdeprecated-declarations] 162 | sprintf(dnam, "/proc/%ld/fd", (long) getpid()); | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/_stdio.h:278:1: note: 'sprintf' has been explicitly marked deprecated here 278 | deprecated_msg("This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead.") | ^ /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:218:48: note: expanded from macro 'deprecated_msg' 218 | #define deprecated_msg(_msg) attribute((deprecated(_msg))) | ^ 2 errors generated. make: *** [ccan-closefrom.o] Error 1 ``` Signed-off-by: Rusty Russell --- diff --git a/ccan/closefrom/closefrom.c b/ccan/closefrom/closefrom.c index 177b05ee..e796ed29 100644 --- a/ccan/closefrom/closefrom.c +++ b/ccan/closefrom/closefrom.c @@ -80,7 +80,7 @@ static bool can_open_proc_pid_fd(void) char dnam[PROC_PID_FD_LEN]; DIR *dir; - sprintf(dnam, "/proc/%ld/fd", (long) getpid()); + snprintf(dnam, sizeof(dnam), "/proc/%ld/fd", (long) getpid()); dir = opendir(dnam); if (!dir) return false; @@ -159,7 +159,7 @@ void closefrom(int fromfd) maxfd = sysconf(_SC_OPEN_MAX); - sprintf(dnam, "/proc/%ld/fd", (long) getpid()); + snprintf(dnam, sizeof(dnam), "/proc/%ld/fd", (long) getpid()); dir = try_opendir(dnam, &fromfd, maxfd); if (!dir) dir = try_opendir("/dev/fd", &fromfd, maxfd); diff --git a/ccan/json/json.c b/ccan/json/json.c index 2f0452ae..b9a87afb 100644 --- a/ccan/json/json.c +++ b/ccan/json/json.c @@ -1231,7 +1231,7 @@ static void emit_number(SB *out, double num) * like 0.3 -> 0.299999999999999988898 . */ char buf[64]; - sprintf(buf, "%.16g", num); + snprintf(buf, sizeof(buf), "%.16g", num); if (number_is_valid(buf)) sb_puts(out, buf); diff --git a/ccan/json_out/_info b/ccan/json_out/_info index fbb4fa56..304652e9 100644 --- a/ccan/json_out/_info +++ b/ccan/json_out/_info @@ -40,7 +40,7 @@ * json_out_start(jout, NULL, '{'); * for (int i = 1; i < argc; i++) { * char fieldname[80]; - * sprintf(fieldname, "argv%i", i); + * snprintf(fieldname, sizeof(fieldname), "argv%i", i); * json_out_add(jout, fieldname, * !can_be_json_literal(argv[i]), * "%s", argv[i]); diff --git a/ccan/likely/likely.c b/ccan/likely/likely.c index 6b6e4aea..aabb51ed 100644 --- a/ccan/likely/likely.c +++ b/ccan/likely/likely.c @@ -84,6 +84,7 @@ char *likely_stats(unsigned int min_hits, unsigned int percent) struct thash_iter i; char *ret; struct trace *t; + size_t maxlen; worst = NULL; worst_ratio = 2; @@ -101,15 +102,16 @@ char *likely_stats(unsigned int min_hits, unsigned int percent) if (worst_ratio * 100 > percent) return NULL; - ret = malloc(strlen(worst->condstr) + - strlen(worst->file) + - sizeof(long int) * 8 + - sizeof("%s:%u:%slikely(%s) correct %u%% (%lu/%lu)")); - sprintf(ret, "%s:%u:%slikely(%s) correct %u%% (%lu/%lu)", - worst->file, worst->line, - worst->expect ? "" : "un", worst->condstr, - (unsigned)(worst_ratio * 100), - worst->right, worst->count); + maxlen = strlen(worst->condstr) + + strlen(worst->file) + + sizeof(long int) * 8 + + sizeof("%s:%u:%slikely(%s) correct %u%% (%lu/%lu)"); + ret = malloc(maxlen); + snprintf(ret, maxlen - 1, "%s:%u:%slikely(%s) correct %u%% (%lu/%lu)", + worst->file, worst->line, + worst->expect ? "" : "un", worst->condstr, + (unsigned)(worst_ratio * 100), + worst->right, worst->count); thash_del(&htable, worst); free(worst); diff --git a/ccan/opt/helpers.c b/ccan/opt/helpers.c index df7ee6bb..5db87bba 100644 --- a/ccan/opt/helpers.c +++ b/ccan/opt/helpers.c @@ -16,8 +16,9 @@ static char *arg_bad(const char *fmt, const char *arg) { - char *str = opt_alloc.alloc(strlen(fmt) + strlen(arg)); - sprintf(str, fmt, arg); + char *str = opt_alloc.alloc(strlen(fmt) + strlen(arg) + 1); + snprintf(str, strlen(fmt) + strlen(arg), fmt, arg); + str[strlen(fmt) + strlen(arg)] = '\0'; return str; } diff --git a/ccan/opt/opt.c b/ccan/opt/opt.c index 9149374c..3cafedeb 100644 --- a/ccan/opt/opt.c +++ b/ccan/opt/opt.c @@ -296,8 +296,10 @@ void opt_log_stderr_exit(const char *fmt, ...) char *opt_invalid_argument(const char *arg) { - char *str = opt_alloc.alloc(sizeof("Invalid argument '%s'") + strlen(arg)); - sprintf(str, "Invalid argument '%s'", arg); + size_t maxlen = sizeof("Invalid argument '%s'") + strlen(arg); + char *str = opt_alloc.alloc(maxlen + 1); + snprintf(str, maxlen, "Invalid argument '%s'", arg); + str[maxlen] = '\0'; return str; } diff --git a/ccan/opt/test/run-helpers.c b/ccan/opt/test/run-helpers.c index 9aa41fe8..31611838 100644 --- a/ccan/opt/test/run-helpers.c +++ b/ccan/opt/test/run-helpers.c @@ -163,7 +163,7 @@ int main(int argc, char *argv[]) pass("Can't test error message"); } else { char buf[30]; - sprintf(buf, "%lu", ULONG_MAX); + snprintf(buf, sizeof(buf), "%lu", ULONG_MAX); ok1(!parse_args(&argc, &argv, "-a", buf, NULL)); ok1(strstr(err_output, ": -a: value '") && strstr(err_output, buf) diff --git a/ccan/rfc822/test/run-hdr-and-body.c b/ccan/rfc822/test/run-hdr-and-body.c index b7f4e7f1..89798d43 100644 --- a/ccan/rfc822/test/run-hdr-and-body.c +++ b/ccan/rfc822/test/run-hdr-and-body.c @@ -126,7 +126,7 @@ int main(int argc, char *argv[]) size_t len; char exname[256]; - sprintf(exname, "%s[%s]", e->name, NLT(crlf)); + snprintf(exname, sizeof(exname), "%s[%s]", e->name, NLT(crlf)); buf = assemble_msg(e, &len, crlf); ok((buf), "assembled %s", exname); diff --git a/ccan/rfc822/test/run-hdr-of-name.c b/ccan/rfc822/test/run-hdr-of-name.c index 9c2e2a37..3b07028c 100644 --- a/ccan/rfc822/test/run-hdr-of-name.c +++ b/ccan/rfc822/test/run-hdr-of-name.c @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) size_t len; char exname[256]; - sprintf(exname, "%s[%s]", e->name, NLT(crlf)); + snprintf(exname, sizeof(exname), "%s[%s]", e->name, NLT(crlf)); buf = assemble_msg(e, &len, crlf); ok((buf), "assembled %s", exname); diff --git a/ccan/rune/rune.c b/ccan/rune/rune.c index efbd8c49..7937f8cb 100644 --- a/ccan/rune/rune.c +++ b/ccan/rune/rune.c @@ -308,7 +308,8 @@ static const char *rune_alt_single(const tal_t *ctx, /* Caller can't set both! */ if (fieldval_int) { assert(!fieldval_str); - sprintf(strfield, "%"PRIi64, *fieldval_int); + snprintf(strfield, sizeof(strfield) - 1, "%"PRIi64, *fieldval_int); + strfield[sizeof(strfield) - 1] = '\0'; fieldval_str = strfield; fieldval_strlen = strlen(strfield); } diff --git a/ccan/str/test/run-STR_MAX_CHARS.c b/ccan/str/test/run-STR_MAX_CHARS.c index fa45bad8..80663c8e 100644 --- a/ccan/str/test/run-STR_MAX_CHARS.c +++ b/ccan/str/test/run-STR_MAX_CHARS.c @@ -24,35 +24,35 @@ int main(void) memset(&types, 0xFF, sizeof(types)); /* Hex versions */ - sprintf(str, "0x%llx", (unsigned long long)types.u1byte); + snprintf(str, sizeof(str), "0x%llx", (unsigned long long)types.u1byte); ok1(strlen(str) < STR_MAX_CHARS(types.u1byte)); - sprintf(str, "0x%llx", (unsigned long long)types.u2byte); + snprintf(str, sizeof(str), "0x%llx", (unsigned long long)types.u2byte); ok1(strlen(str) < STR_MAX_CHARS(types.u2byte)); - sprintf(str, "0x%llx", (unsigned long long)types.u4byte); + snprintf(str, sizeof(str), "0x%llx", (unsigned long long)types.u4byte); ok1(strlen(str) < STR_MAX_CHARS(types.u4byte)); - sprintf(str, "0x%llx", (unsigned long long)types.u8byte); + snprintf(str, sizeof(str), "0x%llx", (unsigned long long)types.u8byte); ok1(strlen(str) < STR_MAX_CHARS(types.u8byte)); /* Decimal versions */ - sprintf(str, "%u", types.u1byte); + snprintf(str, sizeof(str), "%u", types.u1byte); ok1(strlen(str) < STR_MAX_CHARS(types.u1byte)); - sprintf(str, "%d", types.s1byte); + snprintf(str, sizeof(str), "%d", types.s1byte); ok1(strlen(str) < STR_MAX_CHARS(types.s1byte)); - sprintf(str, "%u", types.u2byte); + snprintf(str, sizeof(str), "%u", types.u2byte); ok1(strlen(str) < STR_MAX_CHARS(types.u2byte)); - sprintf(str, "%d", types.s2byte); + snprintf(str, sizeof(str), "%d", types.s2byte); ok1(strlen(str) < STR_MAX_CHARS(types.s2byte)); - sprintf(str, "%u", types.u4byte); + snprintf(str, sizeof(str), "%u", types.u4byte); ok1(strlen(str) < STR_MAX_CHARS(types.u4byte)); - sprintf(str, "%d", types.s4byte); + snprintf(str, sizeof(str), "%d", types.s4byte); ok1(strlen(str) < STR_MAX_CHARS(types.s4byte)); - sprintf(str, "%llu", (unsigned long long)types.u8byte); + snprintf(str, sizeof(str), "%llu", (unsigned long long)types.u8byte); ok1(strlen(str) < STR_MAX_CHARS(types.u8byte)); - sprintf(str, "%lld", (long long)types.s8byte); + snprintf(str, sizeof(str), "%lld", (long long)types.s8byte); ok1(strlen(str) < STR_MAX_CHARS(types.s8byte)); /* Pointer version. */ - sprintf(str, "%p", types.ptr); + snprintf(str, sizeof(str), "%p", types.ptr); ok1(strlen(str) < STR_MAX_CHARS(types.ptr)); return exit_status(); diff --git a/ccan/str/test/run.c b/ccan/str/test/run.c index 9917fe71..a188ff38 100644 --- a/ccan/str/test/run.c +++ b/ccan/str/test/run.c @@ -31,8 +31,10 @@ int main(void) for (j = 0; j < NUM_SUBSTRINGS; j++) { strings[n] = malloc(strlen(substrings[i]) + strlen(substrings[j]) + 1); - sprintf(strings[n++], "%s%s", - substrings[i], substrings[j]); + snprintf(strings[n++], + strlen(substrings[i]) + strlen(substrings[j]), + "%s%s", + substrings[i], substrings[j]); } } diff --git a/ccan/strmap/test/run-order.c b/ccan/strmap/test/run-order.c index b541666d..8ad7aefb 100644 --- a/ccan/strmap/test/run-order.c +++ b/ccan/strmap/test/run-order.c @@ -43,7 +43,7 @@ int main(void) for (i = 0; i < NUM; i++) { char template[10]; - sprintf(template, "%08u", i); + snprintf(template, sizeof(template), "%08u", i); str[i] = strdup(template); } diff --git a/ccan/strmap/test/run-prefix.c b/ccan/strmap/test/run-prefix.c index 6232d71b..1bfb7412 100644 --- a/ccan/strmap/test/run-prefix.c +++ b/ccan/strmap/test/run-prefix.c @@ -35,7 +35,7 @@ int main(void) for (i = 0; i < NUM; i++) { char template[10]; - sprintf(template, "%08u", i); + snprintf(template, sizeof(template), "%08u", i); str[i] = strdup(template); } diff --git a/ccan/strset/test/run-order.c b/ccan/strset/test/run-order.c index 910a9f7a..c748432d 100644 --- a/ccan/strset/test/run-order.c +++ b/ccan/strset/test/run-order.c @@ -38,7 +38,7 @@ int main(void) for (i = 0; i < NUM; i++) { char template[10]; - sprintf(template, "%08u", i); + snprintf(template, sizeof(template), "%08u", i); str[i] = strdup(template); } diff --git a/ccan/strset/test/run-prefix.c b/ccan/strset/test/run-prefix.c index e88f2dd0..62b73b56 100644 --- a/ccan/strset/test/run-prefix.c +++ b/ccan/strset/test/run-prefix.c @@ -33,7 +33,7 @@ int main(void) for (i = 0; i < NUM; i++) { char template[10]; - sprintf(template, "%08u", i); + snprintf(template, sizeof(template), "%08u", i); str[i] = strdup(template); } diff --git a/ccan/take/take.c b/ccan/take/take.c index 4833bf93..437855a2 100644 --- a/ccan/take/take.c +++ b/ccan/take/take.c @@ -107,7 +107,7 @@ const char *taken_any(void) return labelarr[i]; } - sprintf(pointer_buf, "%p", takenarr[0]); + snprintf(pointer_buf, sizeof(pointer_buf), "%p", takenarr[0]); return pointer_buf; } diff --git a/ccan/tal/tal.c b/ccan/tal/tal.c index e799059f..39eb2153 100644 --- a/ccan/tal/tal.c +++ b/ccan/tal/tal.c @@ -953,7 +953,8 @@ static bool check_err(struct tal_hdr *t, const char *errorstr, if (errorstr) { /* Try not to malloc: it may be corrupted. */ char msg[strlen(errorstr) + 20 + strlen(errmsg) + 1]; - sprintf(msg, "%s:%p %s", errorstr, from_tal_hdr(t), errmsg); + snprintf(msg, sizeof(msg), "%s:%p %s", errorstr, from_tal_hdr(t), errmsg); + msg[sizeof(msg) - 1] = '\0'; call_error(msg); } return false; diff --git a/tools/tools.c b/tools/tools.c index 4874fc62..6a96c943 100644 --- a/tools/tools.c +++ b/tools/tools.c @@ -140,7 +140,7 @@ bool run_command(const void *ctx, unsigned int *time_ms, char **output, static void unlink_all(const char *dir) { char cmd[strlen(dir) + sizeof("rm -rf ")]; - sprintf(cmd, "rm -rf %s", dir); + snprintf(cmd, sizeof(cmd), "rm -rf %s", dir); if (tools_verbose) printf("Running: %s\n", cmd); if (system(cmd) != 0)