]> git.ozlabs.org Git - ccan/commitdiff
global: avoid using sprintf.
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 13 Oct 2025 03:38:56 +0000 (14:08 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 13 Oct 2025 03:38:56 +0000 (14:08 +1030)
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 <rusty@rustcorp.com.au>
19 files changed:
ccan/closefrom/closefrom.c
ccan/json/json.c
ccan/json_out/_info
ccan/likely/likely.c
ccan/opt/helpers.c
ccan/opt/opt.c
ccan/opt/test/run-helpers.c
ccan/rfc822/test/run-hdr-and-body.c
ccan/rfc822/test/run-hdr-of-name.c
ccan/rune/rune.c
ccan/str/test/run-STR_MAX_CHARS.c
ccan/str/test/run.c
ccan/strmap/test/run-order.c
ccan/strmap/test/run-prefix.c
ccan/strset/test/run-order.c
ccan/strset/test/run-prefix.c
ccan/take/take.c
ccan/tal/tal.c
tools/tools.c

index 177b05eeee37d246eaa694ca7295249c2e1ba146..e796ed29c79f5175278781ac5df8bf8b77b084d0 100644 (file)
@@ -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);
index 2f0452aebe568277f554072eff7685bdd6b33fc9..b9a87afb5d783c24bf646094abafd77f070422ca 100644 (file)
@@ -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);
index fbb4fa56783c3428f2b461826e66c71d06c2fc31..304652e9a2f1db0254d0f5e46e7694e86a75af87 100644 (file)
@@ -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]);
index 6b6e4aea0319f7e71e5c21695b2df767551fee77..aabb51ed24712178aee653776db294d36428c9ad 100644 (file)
@@ -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);
index df7ee6bb1f20cf791fe82525393e7c809b6f7afb..5db87bba3b04b9f7e1cd1dbc671ec1899b7e42f9 100644 (file)
@@ -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;
 }
 
index 9149374cb001e6152eb46e03de6cc092ef6e4297..3cafedeb2e55e19f066f3478a0c4ebbcf335938a 100644 (file)
@@ -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;
 }
 
index 9aa41fe8db62c5f384b517a811b9b49b3ca3577d..3161183850f1d0b783b5c58c854ede00144fd087 100644 (file)
@@ -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)
index b7f4e7f179f3d7b13278650e92de457e296cda28..89798d4301f8b5cbbd1a98371f2de8030f1688ad 100644 (file)
@@ -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);
index 9c2e2a373c85fe6a91648397704903b3b71207a0..3b07028c2b7148ec589c8cf9d7d788c6467df306 100644 (file)
@@ -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);
index efbd8c49e797e0d20399e41d4a7f17550c8c13b0..7937f8cb5329c3534d68ba2aa7ca17643926b16f 100644 (file)
@@ -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);
        }
index fa45bad8a6414bd7df108823e3b2adeecbb864dd..80663c8ef839b77253c92d680c3865e28f79d4c8 100644 (file)
@@ -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();
index 9917fe7111c5bac1ff34ba52b61854e4f7862a66..a188ff389e5d8097e9649abf391bc2e5182ca7ae 100644 (file)
@@ -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]);
                }
        }
 
index b541666d81209820f62d37418476ee51a1f22a88..8ad7aefbeffa5645b051b03f55b283b53ededd37 100644 (file)
@@ -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);
        }
 
index 6232d71b26135106016d22a01f84feee45c988ca..1bfb741221a26c9825daf90abb3bfad0ffbcb22b 100644 (file)
@@ -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);
        }
 
index 910a9f7a2b55feb1ffbebbc42cee5bb5cc9a60fc..c748432d5319c6b082fc7d58d5fd1d22b44d7750 100644 (file)
@@ -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);
        }
 
index e88f2dd0c141ae185b576b93750a50dd335a6f43..62b73b56dbd7d66a2da3abd7eba777ea2f1ec552 100644 (file)
@@ -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);
        }
 
index 4833bf93576473a964e0cb6eab120af7f49c1fd5..437855a27c75e59094432883c28d9d850eecaefd 100644 (file)
@@ -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;
 }
 
index e799059fc0fbcbe8d0fe9ccf5cfc8c65f079fde5..39eb21537f4f3177e3bd128629fbf785812eb317 100644 (file)
@@ -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;
index 4874fc62645fdff6aa372ecc6637227e6377865e..6a96c943ab2c66ada77688606cce316df6ec1df1 100644 (file)
@@ -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)