ccan: update to get improved grab_file API, and adapt code.
What changed, and why it matters
This commit updates an internal helper library (CCAN's grab_file) so it can read files either as plain binary data or as text with a trailing null character. Most existing callers are switched to the text variant to keep old behavior, while a few callers that handle binary data (like HSM secrets, plugin checksums, and Tor authentication cookies) now use the new binary variant. This is a cleanup/refactoring change that removes the awkward workaround of trimming off an unwanted null byte. There is no direct evidence in the commit that it fixes an active security vulnerability, but correct handling of binary secrets is security-relevant.
Review the migrated binary consumers to confirm they no longer rely on the old trailing-NUL behavior, and verify that no remaining callers accidentally use the text variant for binary data. Consider running the relevant test suites (especially HSM, plugin checksum, and Tor authentication paths). No urgent security patch is indicated by the commit itself.
Security signals we found
Binary secret handling improved: HSM secret, emergency.recover, and Tor cookie no longer include a spurious trailing NUL byte
Deprecated wrapper retained with WARN_DEPRECATED to avoid breaking existing callers
No explicit security bug or CVE mentioned in commit message or diff
Refactoring of widely-used file-reading primitive across ~39 files
Evidence from the diff
The patch refactors ccan/tal/grab_file into internal helpers with an add_nul_term flag, exposing grab_file_str/grab_fd_str (null-terminated) and grab_file_raw/grab_fd_raw (raw bytes). Legacy grab_file/grab_fd are kept as deprecated aliases. Callers are migrated: text/config/JSON/test-vector consumers use _str; binary consumers (common/hsm_secret.c, devtools/checkchannels.c, lightningd/plugin.c, plugins/chanbackup.c, plugins/exposesecret.c, tests/fuzz/libfuzz.c, connectd/tor_autoservice.c) use _raw. A configurator test for attribute((deprecated)) is also adjusted. The change eliminates manual tal_resize(…, -1) hacks and prevents accidental inclusion of a trailing NUL in cryptographic material or checksums.
Changed components
ccan/tal/grab_filecommon/hsm_secret.ccommon/configdir.cconnectd/tor_autoservice.cdevtools/checkchannels.cdevtools/decodemsg.cdevtools/onion.clightningd/configs.clightningd/lightningd.clightningd/plugin.cplugins/bcli.cplugins/chanbackup.cplugins/exposesecret.ctests/fuzz/libfuzz.ctools/check-bolt.ctools/headerversions.cInspect captured patch +180 / −114
diff --git a/ccan/README b/ccan/README
index 0710c5f1..022df6bf 100644
--- a/ccan/README
+++ b/ccan/README
@@ -1,3 +1,3 @@
CCAN imported from http://ccodearchive.net.
-CCAN version: init-2602-gfd3fd70c
+CCAN version: init-2605-gc47bf0d9
diff --git a/ccan/ccan/cdump/_info b/ccan/ccan/cdump/_info
index c79d013b..5c2acee7 100644
--- a/ccan/ccan/cdump/_info
+++ b/ccan/ccan/cdump/_info
@@ -33,7 +33,7 @@
* size_t j;
*
* // Read code from stdin.
- * code = grab_file(NULL, NULL);
+ * code = grab_file_str(NULL, NULL);
*
* defs = cdump_extract(NULL, code, &problems);
* if (!defs)
diff --git a/ccan/ccan/cdump/tools/cdump-enumstr.c b/ccan/ccan/cdump/tools/cdump-enumstr.c
index f0b70ecd..147f2a23 100644
--- a/ccan/ccan/cdump/tools/cdump-enumstr.c
+++ b/ccan/ccan/cdump/tools/cdump-enumstr.c
@@ -27,7 +27,7 @@ int main(int argc, char *argv[])
if (argc < 2)
errx(1, "Usage: cdump-enumstr <filename> [<enums>...]");
- code = grab_file(NULL, streq(argv[1], "-") ? NULL : argv[1]);
+ code = grab_file_str(NULL, streq(argv[1], "-") ? NULL : argv[1]);
if (!code)
err(1, "Reading %s", argv[1]);
diff --git a/ccan/ccan/crc32c/benchmark/bench.c b/ccan/ccan/crc32c/benchmark/bench.c
index 54b2d97a..e584ae71 100644
--- a/ccan/ccan/crc32c/benchmark/bench.c
+++ b/ccan/ccan/crc32c/benchmark/bench.c
@@ -31,7 +31,7 @@ int main(int argc, char *argv[])
if (argc < 2 || (runs = atol(argv[1])) == 0)
errx(1, "Usage: bench <num-runs> [<file>]");
- p = grab_file(NULL, argv[2]);
+ p = grab_file_str(NULL, argv[2]);
if (!p)
err(1, "Reading %s", argv[2] ? argv[2] : "<stdin>");
len = tal_count(p) - 1;
diff --git a/ccan/ccan/htable/tools/hsearchspeed.c b/ccan/ccan/htable/tools/hsearchspeed.c
index 88280114..bed6f859 100644
--- a/ccan/ccan/htable/tools/hsearchspeed.c
+++ b/ccan/ccan/htable/tools/hsearchspeed.c
@@ -29,7 +29,7 @@ int main(int argc, char *argv[])
char **w;
ENTRY *words, *misswords;
- w = tal_strsplit(NULL, grab_file(NULL,
+ w = tal_strsplit(NULL, grab_file_str(NULL,
argv[1] ? argv[1] : "/usr/share/dict/words"), "\n", STR_NO_EMPTY);
num = tal_count(w) - 1;
printf("%zu words\n", num);
diff --git a/ccan/ccan/htable/tools/stringspeed.c b/ccan/ccan/htable/tools/stringspeed.c
index 5f30359a..24eb1587 100644
--- a/ccan/ccan/htable/tools/stringspeed.c
+++ b/ccan/ccan/htable/tools/stringspeed.c
@@ -48,7 +48,7 @@ int main(int argc, char *argv[])
struct htable_str ht;
char **words, **misswords;
- words = tal_strsplit(NULL, grab_file(NULL,
+ words = tal_strsplit(NULL, grab_file_str(NULL,
argv[1] ? argv[1] : "/usr/share/dict/words"), "\n",
STR_NO_EMPTY);
htable_str_init(&ht);
diff --git a/ccan/ccan/rune/test/run.c b/ccan/ccan/rune/test/run.c
index d90b701c..85cb6903 100644
--- a/ccan/ccan/rune/test/run.c
+++ b/ccan/ccan/rune/test/run.c
@@ -39,7 +39,7 @@ int main(void)
mr = rune_new(NULL, secret_zero, sizeof(secret_zero), NULL);
/* Python runes library generates test vectors */
- vecs = grab_file(mr, "test/test_vectors.csv");
+ vecs = grab_file_str(mr, "test/test_vectors.csv");
assert(vecs);
lines = tal_strsplit(mr, take(vecs), "\n", STR_NO_EMPTY);
diff --git a/ccan/ccan/strset/_info b/ccan/ccan/strset/_info
index 982a9c0f..bcd261b9 100644
--- a/ccan/ccan/strset/_info
+++ b/ccan/ccan/strset/_info
@@ -32,7 +32,7 @@
* char *file, *word;
*
* strset_init(&words);
- * file = grab_fd(NULL, 0);
+ * file = grab_fd_str(NULL, 0);
* if (!file)
* err(1, "Reading stdin");
*
diff --git a/ccan/ccan/strset/tools/cbspeed.c b/ccan/ccan/strset/tools/cbspeed.c
index 5d551b6e..88ce981a 100644
--- a/ccan/ccan/strset/tools/cbspeed.c
+++ b/ccan/ccan/strset/tools/cbspeed.c
@@ -395,7 +395,7 @@ int main(int argc, char *argv[])
critbit0_tree ct;
char **words, **misswords;
- words = tal_strsplit(NULL, grab_file(NULL,
+ words = tal_strsplit(NULL, grab_file_str(NULL,
argv[1] ? argv[1] : "/usr/share/dict/words"), "\n", STR_NO_EMPTY);
ct.root = NULL;
num = tal_count(words) - 1;
diff --git a/ccan/ccan/strset/tools/speed.c b/ccan/ccan/strset/tools/speed.c
index 325b3a88..70a43c25 100644
--- a/ccan/ccan/strset/tools/speed.c
+++ b/ccan/ccan/strset/tools/speed.c
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
struct strset set;
char **words, **misswords;
- words = tal_strsplit(NULL, grab_file(NULL,
+ words = tal_strsplit(NULL, grab_file_str(NULL,
argv[1] ? argv[1] : "/usr/share/dict/words"),
"\n", STR_NO_EMPTY);
strset_init(&set);
diff --git a/ccan/ccan/tal/grab_file/_info b/ccan/ccan/tal/grab_file/_info
index 056f1099..9b130a5f 100644
--- a/ccan/ccan/tal/grab_file/_info
+++ b/ccan/ccan/tal/grab_file/_info
@@ -20,7 +20,7 @@
*
* if (argc > 2)
* err(1, "Takes 0 or 1 arguments");
- * file = grab_file(NULL, argv[1]);
+ * file = grab_file_str(NULL, argv[1]);
* if (!file)
* err(1, "Could not read file %s", argv[1]);
* if (strlen(file)+1 != tal_count(file))
@@ -45,6 +45,7 @@ int main(int argc, char *argv[])
return 1;
if (strcmp(argv[1], "depends") == 0) {
+ printf("ccan/compiler\n");
printf("ccan/tal\n");
printf("ccan/noerr\n");
return 0;
diff --git a/ccan/ccan/tal/grab_file/grab_file.c b/ccan/ccan/tal/grab_file/grab_file.c
index 6528780a..fcadc833 100644
--- a/ccan/ccan/tal/grab_file/grab_file.c
+++ b/ccan/ccan/tal/grab_file/grab_file.c
@@ -8,7 +8,7 @@
#include <errno.h>
#include <fcntl.h>
-void *grab_fd(const void *ctx, int fd)
+static void *grab_fd_internal(const void *ctx, int fd, bool add_nul_term)
{
int ret;
size_t max, size;
@@ -22,7 +22,7 @@ void *grab_fd(const void *ctx, int fd)
else
max = 16384;
- buffer = tal_arr(ctx, char, max+1);
+ buffer = tal_arr(ctx, char, max+add_nul_term);
while ((ret = read(fd, buffer + size, max - size)) != 0) {
if (ret < 0) {
if (errno == EINTR)
@@ -35,19 +35,20 @@ void *grab_fd(const void *ctx, int fd)
if (extra > 1024 * 1024)
extra = 1024 * 1024;
- if (!tal_resize(&buffer, max+extra+1))
+ if (!tal_resize(&buffer, max+extra+add_nul_term))
return NULL;
max += extra;
}
}
- buffer[size] = '\0';
- tal_resize(&buffer, size+1);
+ if (add_nul_term)
+ buffer[size] = '\0';
+ tal_resize(&buffer, size+add_nul_term);
return buffer;
}
-void *grab_file(const void *ctx, const char *filename)
+static void *grab_file_internal(const void *ctx, const char *filename, bool add_nul_term)
{
int fd;
char *buffer;
@@ -60,7 +61,27 @@ void *grab_file(const void *ctx, const char *filename)
if (fd < 0)
return NULL;
- buffer = grab_fd(ctx, fd);
+ buffer = grab_fd_internal(ctx, fd, add_nul_term);
close_noerr(fd);
return buffer;
}
+
+void *grab_fd_raw(const void *ctx, int fd)
+{
+ return grab_fd_internal(ctx, fd, false);
+}
+
+void *grab_fd_str(const void *ctx, int fd)
+{
+ return grab_fd_internal(ctx, fd, true);
+}
+
+void *grab_file_str(const void *ctx, const char *filename)
+{
+ return grab_file_internal(ctx, filename, true);
+}
+
+void *grab_file_raw(const void *ctx, const char *filename)
+{
+ return grab_file_internal(ctx, filename, false);
+}
diff --git a/ccan/ccan/tal/grab_file/grab_file.h b/ccan/ccan/tal/grab_file/grab_file.h
index 2eb1a008..f2f7e673 100644
--- a/ccan/ccan/tal/grab_file/grab_file.h
+++ b/ccan/ccan/tal/grab_file/grab_file.h
@@ -2,9 +2,31 @@
#ifndef CCAN_TAL_GRAB_FILE_H
#define CCAN_TAL_GRAB_FILE_H
#include <stdio.h> // For size_t
+#include <ccan/compiler/compiler.h>
/**
- * grab_fd - read all of a file descriptor into memory
+ * grab_fd_raw - read all of a file descriptor into memory WITHOUT adding a nul.
+ * @ctx: the context to tallocate from (often NULL)
+ * @fd: the file descriptor to read from
+ * @size: the (optional) size of the file
+ *
+ * This function reads from the given file descriptor until no more
+ * input is available. The content is talloced off @ctx, and the
+ * tal_count() is the size in bytes.
+ *
+ * Note that this does *not* currently exit on EINTR, but continues
+ * reading. *
+ * Example:
+ * // Return the first line.
+ * static char *read_stdin_all(void)
+ * {
+ * return grab_fd_raw(NULL, 0);
+ * }
+ */
+void *grab_fd_raw(const void *ctx, int fd);
+
+/**
+ * grab_fd_str - read all of a file descriptor into memory with a NUL terminator.
* @ctx: the context to tallocate from (often NULL)
* @fd: the file descriptor to read from
*
@@ -25,7 +47,7 @@
* {
* char **lines, *all;
*
- * all = grab_fd(NULL, 0);
+ * all = grab_fd_str(NULL, 0);
* if (!all)
* return NULL;
* lines = tal_strsplit(NULL, all, "\n", STR_EMPTY_OK);
@@ -33,10 +55,18 @@
* return lines;
* }
*/
-void *grab_fd(const void *ctx, int fd);
+void *grab_fd_str(const void *ctx, int fd);
+
+/* Deprecated synonym for grab_fd_str */
+static inline void *grab_fd(const void *ctx, int fd)
+ WARN_DEPRECATED;
+static inline void *grab_fd(const void *ctx, int fd)
+{
+ return grab_fd_str(ctx, fd);
+}
/**
- * grab_file - read all of a file (or stdin) into memory
+ * grab_file_str - read all of a file (or stdin) into memory with a NUL terminator
* @ctx: the context to tallocate from (often NULL)
* @filename: the file to read (NULL for stdin)
*
@@ -51,7 +81,7 @@ void *grab_fd(const void *ctx, int fd);
* {
* char **lines, *all;
*
- * all = grab_file(NULL, filename);
+ * all = grab_file_str(NULL, filename);
* if (!all)
* return NULL;
* lines = tal_strsplit(NULL, all, "\n", STR_EMPTY_OK);
@@ -59,5 +89,32 @@ void *grab_fd(const void *ctx, int fd);
* return lines;
* }
*/
-void *grab_file(const void *ctx, const char *filename);
+void *grab_file_str(const void *ctx, const char *filename);
+
+/**
+ * grab_file_raw - read all of a file (or stdin) into memory WITHOUT a NUL terminator
+ * @ctx: the context to tallocate from (often NULL)
+ * @filename: the file to read (NULL for stdin)
+ * @size: the (optional) size of the file
+ *
+ * This function reads from the given file until no more input is
+ * available. The content is talloced off @ctx, and the tal_count()
+ * is the size in bytes.
+ *
+ * Example:
+ * static char *read_file_all(const char *filename)
+ * {
+ * return grab_file_raw(NULL, filename);
+ * }
+ */
+void *grab_file_raw(const void *ctx, const char *filename);
+
+/* Deprecated synonym for grab_file_str */
+static inline void *grab_file(const void *ctx, const char *filename)
+ WARN_DEPRECATED;
+static inline void *grab_file(const void *ctx, const char *filename)
+{
+ return grab_file_str(ctx, filename);
+}
+
#endif /* CCAN_TAL_GRAB_FILE_H */
diff --git a/ccan/ccan/tal/grab_file/test/run-grab.c b/ccan/ccan/tal/grab_file/test/run-grab.c
index ddb5ca30..02e78aca 100644
--- a/ccan/ccan/tal/grab_file/test/run-grab.c
+++ b/ccan/ccan/tal/grab_file/test/run-grab.c
@@ -1,4 +1,4 @@
-/* This is test for grab_file() function
+/* This is test for grab_file_str() and grab_file_raw() functions
*/
#include <ccan/tal/grab_file/grab_file.h>
#include <stdlib.h>
@@ -13,25 +13,31 @@ int
main(void)
{
unsigned int i;
- char **split, *str;
+ char **split, *str, *raw;
int length;
struct stat st;
- str = grab_file(NULL, "test/run-grab.c");
+ plan_tests(5);
+ str = grab_file_str(NULL, "test/run-grab.c");
split = tal_strsplit(str, str, "\n", STR_EMPTY_OK);
length = strlen(split[0]);
- ok1(!strcmp(split[0], "/* This is test for grab_file() function"));
+ ok1(!strcmp(split[0], "This is test for grab_file_str() and grab_file_raw() functions"));
for (i = 1; split[i]; i++)
length += strlen(split[i]);
- ok1(!strcmp(split[i-1], "/* End of grab_file() test */"));
+ ok1(!strcmp(split[i-1], "/* End of grab_file.c test */"));
if (stat("test/run-grab.c", &st) != 0)
/* FIXME: ditto */
if (stat("ccan/tal/grab_file/test/run-grab.c", &st) != 0)
err(1, "Could not stat self");
ok1(st.st_size == length + i);
+
+ /* Raw does not nul term */
+ raw = grab_file_raw(str, "test/run-grab.c");
+ ok1(tal_count(raw) + 1 == tal_count(str));
+ ok1(memcmp(raw, str, tal_bytelen(raw)) == 0);
tal_free(str);
return 0;
}
-/* End of grab_file() test */
+/* End of grab_file.c test */
diff --git a/ccan/ccan/tal/str/_info b/ccan/ccan/tal/str/_info
index 9b9c70b6..83e089e7 100644
--- a/ccan/ccan/tal/str/_info
+++ b/ccan/ccan/tal/str/_info
@@ -25,7 +25,7 @@
* if (argc > 2)
* errx(1, "Takes 0 or 1 arguments");
* // Grab lines in file.
- * textfile = grab_file(NULL, argv[1]);
+ * textfile = grab_file_str(NULL, argv[1]);
* if (!textfile)
* err(1, "Failed reading %s", argv[1]);
* lines = tal_strsplit(textfile, textfile, "\n", STR_EMPTY_OK);
diff --git a/ccan/tools/configurator/configurator.c b/ccan/tools/configurator/configurator.c
index 4efeaba3..085034fd 100644
--- a/ccan/tools/configurator/configurator.c
+++ b/ccan/tools/configurator/configurator.c
@@ -137,8 +137,8 @@ static const struct test base_tests[] = {
"DEFINES_FUNC", NULL, NULL,
"static int __attribute__((const)) func(int x) { return x; }" },
{ "HAVE_ATTRIBUTE_DEPRECATED", "__attribute__((deprecated)) support",
- "DEFINES_FUNC", NULL, NULL,
- "static int __attribute__((deprecated)) func(int x) { return x; }" },
+ "OUTSIDE_MAIN", NULL, NULL,
+ "int __attribute__((deprecated)) depr(int x);" },
{ "HAVE_ATTRIBUTE_NONNULL", "__attribute__((nonnull)) support",
"DEFINES_FUNC", NULL, NULL,
"static char *__attribute__((nonnull)) func(char *p) { return p; }" },
diff --git a/common/configdir.c b/common/configdir.c
index 8bbf29b4..453e3424 100644
--- a/common/configdir.c
+++ b/common/configdir.c
@@ -62,7 +62,7 @@ static struct configvar **gather_file_configvars(const tal_t *ctx,
char *contents, **lines;
struct configvar **cvs = tal_arr(ctx, struct configvar *, 0);
- contents = grab_file(tmpctx, filename);
+ contents = grab_file_str(tmpctx, filename);
/* The default config doesn't have to exist, but if the config was
* specified on the command line it has to exist. */
diff --git a/common/hsm_secret.c b/common/hsm_secret.c
index bcb8cf4a..93c03752 100644
--- a/common/hsm_secret.c
+++ b/common/hsm_secret.c
@@ -499,17 +499,9 @@ const char *format_type_name(enum hsm_secret_type type)
u8 *grab_file_contents(const tal_t *ctx, const char *filename, size_t *len)
{
- u8 *contents = grab_file(ctx, filename);
- if (!contents) {
- if (len)
- *len = 0;
- return NULL;
- }
-
- /* grab_file adds a NUL terminator, so we resize to remove it */
- size_t contents_len = tal_bytelen(contents) - 1;
+ u8 *contents = grab_file_raw(ctx, filename);
if (len)
- *len = contents_len;
+ *len = tal_bytelen(contents);
return contents;
}
diff --git a/common/test/run-bigsize.c b/common/test/run-bigsize.c
index 9b181261..8ff40e54 100644
--- a/common/test/run-bigsize.c
+++ b/common/test/run-bigsize.c
@@ -333,8 +333,8 @@ int main(int argc, char *argv[])
common_setup(argv[0]);
- lines = tal_strsplit(tmpctx, grab_file(tmpctx, tal_fmt(tmpctx, "%s.c",
- argv[0])),
+ lines = tal_strsplit(tmpctx, grab_file_str(tmpctx, tal_fmt(tmpctx, "%s.c",
+ argv[0])),
"\n", STR_NO_EMPTY);
for (size_t i = 0; lines[i]; i++) {
diff --git a/common/test/run-bolt12-offer-decode.c b/common/test/run-bolt12-offer-decode.c
index 5296e8fd..6febbb36 100644
--- a/common/test/run-bolt12-offer-decode.c
+++ b/common/test/run-bolt12-offer-decode.c
@@ -131,13 +131,13 @@ int main(int argc, char *argv[])
common_setup(argv[0]);
if (argv[1])
- json = grab_file(tmpctx, argv[1]);
+ json = grab_file_str(tmpctx, argv[1]);
else {
char *dir = getenv("BOLTDIR");
- json = grab_file(tmpctx,
- path_join(tmpctx,
- dir ? dir : ".tmp.lightningrfc",
- "bolt12/offers-test.json"));
+ json = grab_file_str(tmpctx,
+ path_join(tmpctx,
+ dir ? dir : ".tmp.lightningrfc",
+ "bolt12/offers-test.json"));
if (!json) {
printf("test file not found, skipping\n");
goto out;
diff --git a/common/test/run-bolt12_decode.c b/common/test/run-bolt12_decode.c
index 6f0fa2a5..9e5333b3 100644
--- a/common/test/run-bolt12_decode.c
+++ b/common/test/run-bolt12_decode.c
@@ -168,13 +168,13 @@ int main(int argc, char *argv[])
common_setup(argv[0]);
if (argv[1])
- json = grab_file(tmpctx, argv[1]);
+ json = grab_file_str(tmpctx, argv[1]);
else {
char *dir = getenv("BOLTDIR");
- json = grab_file(tmpctx,
- path_join(tmpctx,
- dir ? dir : ".tmp.lightningrfc",
- "bolt12/format-string-test.json"));
+ json = grab_file_str(tmpctx,
+ path_join(tmpctx,
+ dir ? dir : ".tmp.lightningrfc",
+ "bolt12/format-string-test.json"));
if (!json) {
printf("test file not found, skipping\n");
goto out;
diff --git a/common/test/run-bolt12_merkle-json.c b/common/test/run-bolt12_merkle-json.c
index dba66a29..3c7d5a04 100644
--- a/common/test/run-bolt12_merkle-json.c
+++ b/common/test/run-bolt12_merkle-json.c
@@ -110,13 +110,13 @@ int main(int argc, char *argv[])
common_setup(argv[0]);
if (argv[1])
- json = grab_file(tmpctx, argv[1]);
+ json = grab_file_str(tmpctx, argv[1]);
else {
char *dir = getenv("BOLTDIR");
- json = grab_file(tmpctx,
- path_join(tmpctx,
- dir ? dir : ".tmp.lightningrfc",
- "bolt12/merkle-test.json"));
+ json = grab_file_str(tmpctx,
+ path_join(tmpctx,
+ dir ? dir : ".tmp.lightningrfc",
+ "bolt12/merkle-test.json"));
if (!json) {
printf("test file not found, skipping\n");
goto out;
diff --git a/common/test/run-bolt12_period.c b/common/test/run-bolt12_period.c
index 514e47fe..e4daf72f 100644
--- a/common/test/run-bolt12_period.c
+++ b/common/test/run-bolt12_period.c
@@ -174,13 +174,13 @@ int main(int argc, char *argv[])
common_setup(argv[0]);
if (argv[1])
- json = grab_file(tmpctx, argv[1]);
+ json = grab_file_str(tmpctx, argv[1]);
else {
char *dir = getenv("BOLTDIR");
- json = grab_file(tmpctx,
- path_join(tmpctx,
- dir ? dir : ".tmp.lightningrfc",
- "bolt12/offer-period-test.json"));
+ json = grab_file_str(tmpctx,
+ path_join(tmpctx,
+ dir ? dir : ".tmp.lightningrfc",
+ "bolt12/offer-period-test.json"));
if (!json) {
printf("test file not found, skipping\n");
common_shutdown();
diff --git a/common/test/run-onion-test-vector.c b/common/test/run-onion-test-vector.c
index 06453710..842c96c5 100644
--- a/common/test/run-onion-test-vector.c
+++ b/common/test/run-onion-test-vector.c
@@ -144,13 +144,13 @@ int main(int argc, char *argv[])
common_setup(argv[0]);
if (argv[1])
- json = grab_file(tmpctx, argv[1]);
+ json = grab_file_str(tmpctx, argv[1]);
else {
char *dir = getenv("BOLTDIR");
- json = grab_file(tmpctx,
- path_join(tmpctx,
- dir ? dir : ".tmp.lightningrfc",
- "bolt04/onion-test.json"));
+ json = grab_file_str(tmpctx,
+ path_join(tmpctx,
+ dir ? dir : ".tmp.lightningrfc",
+ "bolt04/onion-test.json"));
if (!json) {
printf("test file not found, skipping\n");
goto out;
diff --git a/common/test/run-route_blinding_onion_test.c b/common/test/run-route_blinding_onion_test.c
index 0dfc0d23..d3b26db4 100644
--- a/common/test/run-route_blinding_onion_test.c
+++ b/common/test/run-route_blinding_onion_test.c
@@ -86,13 +86,13 @@ int main(int argc, char *argv[])
common_setup(argv[0]);
if (argv[1])
- json = grab_file(tmpctx, argv[1]);
+ json = grab_file_str(tmpctx, argv[1]);
else {
char *dir = getenv("BOLTDIR");
- json = grab_file(tmpctx,
- path_join(tmpctx,
- dir ? dir : ".tmp.lightningrfc",
- "bolt04/blinded-payment-onion-test.json"));
+ json = grab_file_str(tmpctx,
+ path_join(tmpctx,
+ dir ? dir : ".tmp.lightningrfc",
+ "bolt04/blinded-payment-onion-test.json"));
if (!json) {
printf("test file not found, skipping\n");
goto out;
diff --git a/common/test/run-route_blinding_test.c b/common/test/run-route_blinding_test.c
index 3358319d..049e2a58 100644
--- a/common/test/run-route_blinding_test.c
+++ b/common/test/run-route_blinding_test.c
@@ -164,13 +164,13 @@ int main(int argc, char *argv[])
common_setup(argv[0]);
if (argv[1])
- json = grab_file(tmpctx, argv[1]);
+ json = grab_file_str(tmpctx, argv[1]);
else {
char *dir = getenv("BOLTDIR");
- json = grab_file(tmpctx,
- path_join(tmpctx,
- dir ? dir : ".tmp.lightningrfc",
- "bolt04/route-blinding-test.json"));
+ json = grab_file_str(tmpctx,
+ path_join(tmpctx,
+ dir ? dir : ".tmp.lightningrfc",
+ "bolt04/route-blinding-test.json"));
if (!json) {
printf("test file not found, skipping\n");
goto out;
diff --git a/connectd/tor_autoservice.c b/connectd/tor_autoservice.c
index 4b08f923..fef93a80 100644
--- a/connectd/tor_autoservice.c
+++ b/connectd/tor_autoservice.c
@@ -231,18 +231,15 @@ static void negotiate_auth(struct rbuf *rbuf, const char *tor_password)
/* If we can't access this, try other methods */
cookiefile = tal_strdup(tmpctx, p);
- contents = grab_file(tmpctx, p);
+ contents = grab_file_raw(tmpctx, p);
if (!contents) {
cookiefileerrno = errno;
continue;
}
- assert(tal_count(contents) != 0);
discard_remaining_response(rbuf);
tor_send_cmd(rbuf,
tal_fmt(tmpctx, "AUTHENTICATE %s",
- tal_hexstr(tmpctx,
- contents,
- tal_count(contents)-1)));
+ tal_hex(tmpctx, contents)));
discard_remaining_response(rbuf);
return;
}
diff --git a/devtools/checkchannels.c b/devtools/checkchannels.c
index 144646f3..1ca9babc 100644
--- a/devtools/checkchannels.c
+++ b/devtools/checkchannels.c
@@ -144,7 +144,7 @@ int main(int argc, char *argv[])
errx(1, "failed to open database %s: %s", dbfile,
sqlite3_errstr(dberr));
- hsm_secret = grab_file(hsmfile, hsmfile);
+ hsm_secret = grab_file_raw(hsmfile, hsmfile);
if (!hsm_secret)
err(1, "failed to read %s", hsmfile);
diff --git a/devtools/decodemsg.c b/devtools/decodemsg.c
index 390a4093..9a31f3a6 100644
--- a/devtools/decodemsg.c
+++ b/devtools/decodemsg.c
@@ -83,7 +83,7 @@ int main(int argc, char *argv[])
ok &= printwire(m);
}
} else {
- u8 *f = grab_fd(NULL, STDIN_FILENO);
+ u8 *f = grab_fd_str(NULL, STDIN_FILENO);
size_t off = 0;
while (off != tal_count(f)) {
diff --git a/devtools/onion.c b/devtools/onion.c
index 461494af..9627b2da 100644
--- a/devtools/onion.c
+++ b/devtools/onion.c
@@ -141,7 +141,7 @@ static void do_decode(int argc, char **argv, const u8 *assocdata)
opt_usage_exit_fail("Expect an filename and privkey with 'decode' method");
/* "-" means stdin, which is NULL for grab_file */
- char *hextemp = grab_file(ctx, streq(argv[2], "-") ? NULL : argv[2]);
+ char *hextemp = grab_file_str(ctx, streq(argv[2], "-") ? NULL : argv[2]);
size_t hexlen = strlen(hextemp);
// trim trailing whitespace
@@ -193,7 +193,7 @@ static char *opt_set_node_id(const char *arg, struct node_id *node_id)
static void runtest(const char *filename)
{
const tal_t *ctx = tal(NULL, u8);
- char *buffer = grab_file(ctx, filename);
+ char *buffer = grab_file_str(ctx, filename);
const jsmntok_t *toks, *session_key_tok, *associated_data_tok, *gentok,
*hopstok, *hop, *payloadtok, *pubkeytok, *typetok, *oniontok, *decodetok;
const u8 *associated_data, *session_key_raw, *payload, *serialized, *onion;
diff --git a/lightningd/configs.c b/lightningd/configs.c
index 553dafff..8482a78f 100644
--- a/lightningd/configs.c
+++ b/lightningd/configs.c
@@ -357,7 +357,7 @@ static size_t append_to_file(struct lightningd *ld,
}
/* Note: always nul terminates */
- buffer = grab_fd(tmpctx, fd);
+ buffer = grab_fd_str(tmpctx, fd);
if (!buffer)
fatal("Error reading %s: %s", fname, strerror(errno));
@@ -387,7 +387,7 @@ static const char *grab_and_check(const tal_t *ctx,
{
char *contents;
- contents = grab_file(tmpctx, fname);
+ contents = grab_file_str(tmpctx, fname);
if (!contents)
return tal_fmt(ctx, "Could not load configfile %s: %s",
fname, strerror(errno));
diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c
index fda955df..e5e3dedd 100644
--- a/lightningd/lightningd.c
+++ b/lightningd/lightningd.c
@@ -479,8 +479,8 @@ void test_subdaemons(const struct lightningd *ld)
err(EXITCODE_SUBDAEMON_FAIL, "Could not run %s", dpath);
/*~ CCAN's grab_file module contains a routine to read into a
- * tallocated buffer until EOF */
- verstring = grab_fd(tmpctx, outfd);
+ * tallocated buffer until EOF (with nul appended!) */
+ verstring = grab_fd_str(tmpctx, outfd);
/*~ Like many CCAN modules, it set errno on failure, which
* err (ccan/err, but usually just the BSD <err.h>) prints */
if (!verstring)
diff --git a/lightningd/plugin.c b/lightningd/plugin.c
index 98637642..9ce2fc44 100644
--- a/lightningd/plugin.c
+++ b/lightningd/plugin.c
@@ -322,7 +322,7 @@ static u32 file_checksum(struct lightningd *ld, const char *path)
if (ld->dev_no_plugin_checksum)
return 0;
- content = grab_file(tmpctx, path);
+ content = grab_file_raw(tmpctx, path);
crc = crc32c(0, content, tal_count(content));
/* We could leave this around, but we checksum many files in a loop,
* causing 450MB of allocations at startup! */
diff --git a/plugins/bcli.c b/plugins/bcli.c
index 656df9ff..5203022f 100644
--- a/plugins/bcli.c
+++ b/plugins/bcli.c
@@ -1066,7 +1066,7 @@ static void wait_and_check_bitcoind(struct plugin *p)
plugin_err(p, "%s exec failed: %s", cmd[0], strerror(errno));
}
- output = grab_fd(cmd, from);
+ output = grab_fd_str(cmd, from);
waitpid(child, &status, 0);
diff --git a/plugins/chanbackup.c b/plugins/chanbackup.c
index 4b4addf5..09afcb75 100644
--- a/plugins/chanbackup.c
+++ b/plugins/chanbackup.c
@@ -242,13 +242,9 @@ static void maybe_create_new_scb(struct plugin *p,
static u8 *get_file_data(const tal_t *ctx, struct plugin *p)
{
- u8 *scb = grab_file(ctx, FILENAME);
- if (!scb) {
+ u8 *scb = grab_file_raw(ctx, FILENAME);
+ if (!scb)
plugin_err(p, "Cannot read emergency.recover: %s", strerror(errno));
- } else {
- /* grab_file adds nul term */
- tal_resize(&scb, tal_bytelen(scb) - 1);
- }
return scb;
}
diff --git a/plugins/exposesecret.c b/plugins/exposesecret.c
index 1303254f..c46c4ee0 100644
--- a/plugins/exposesecret.c
+++ b/plugins/exposesecret.c
@@ -68,14 +68,10 @@ static struct command_result *json_exposesecret(struct command *cmd,
if (!compare_passphrases(exposesecret->exposure_passphrase, passphrase))
return command_fail(cmd, LIGHTNINGD, "passphrase does not match exposesecrets-passphrase");
- contents = grab_file(tmpctx, "hsm_secret");
+ contents = grab_file_raw(tmpctx, "hsm_secret");
if (!contents)
return command_fail(cmd, LIGHTNINGD, "Could not open hsm_secret: %s", strerror(errno));
- /* grab_file adds a \0 byte at the end for convenience */
- if (tal_bytelen(contents) > 0)
- tal_resize(&contents, tal_bytelen(contents) - 1);
-
/* Check if the HSM secret needs a passphrase */
if (hsm_secret_needs_passphrase(contents, tal_bytelen(contents))) {
return command_fail(cmd, LIGHTNINGD, "Secret with passphrase is not supported");
diff --git a/tests/fuzz/libfuzz.c b/tests/fuzz/libfuzz.c
index 78ee0064..aada6f8c 100644
--- a/tests/fuzz/libfuzz.c
+++ b/tests/fuzz/libfuzz.c
@@ -146,9 +146,9 @@ int main(int argc, char *argv[])
u8 *contents;
if (streq(di->d_name, ".") || streq(di->d_name, ".."))
continue;
- contents = grab_file(tmpctx, di->d_name);
+ contents = grab_file_raw(tmpctx, di->d_name);
assert(contents);
- run(contents, tal_bytelen(contents)-1);
+ run(contents, tal_bytelen(contents));
}
closedir(d);
common_shutdown();
diff --git a/tools/check-bolt.c b/tools/check-bolt.c
index 01e47cc1..95addc59 100644
--- a/tools/check-bolt.c
+++ b/tools/check-bolt.c
@@ -74,9 +74,9 @@ static bool get_files(const char *dir, const char *subdir,
bf.prefix = tal_strndup(*files, e->d_name, preflen);
bf.contents
- = canonicalize(grab_file(*files,
- path_join(path, path,
- e->d_name)));
+ = canonicalize(grab_file_str(*files,
+ path_join(path, path,
+ e->d_name)));
tal_arr_expand(files, bf);
}
closedir(d);
@@ -308,7 +308,7 @@ int main(int argc, char *argv[])
bolts = get_bolt_files(argv[1]);
for (i = 2; i < argc; i++) {
- char *f = grab_file(NULL, argv[i]), *p, *bolt;
+ char *f = grab_file_str(NULL, argv[i]), *p, *bolt;
size_t len;
if (!f)
err(1, "Loading %s", argv[i]);
diff --git a/tools/headerversions.c b/tools/headerversions.c
index 15100bde..8cee70ad 100644
--- a/tools/headerversions.c
+++ b/tools/headerversions.c
@@ -49,7 +49,7 @@ int main(int argc, char *argv[])
if (argc != 2)
errx(1, "Usage: %s <versionheader>", argv[0]);
- file = grab_file(NULL, argv[1]);
+ file = grab_file_str(NULL, argv[1]);
if (!file && errno != ENOENT)
err(1, "Reading %s", argv[1]);
Why this scored 28/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.