From ab672133a9bde75d20afd59d8db1405c7300a557 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 14 Feb 2023 14:03:42 -0500 Subject: [PATCH] Give strlcat() full buffer lengths rather than smaller buffer lengths strlcat() is supposed to be given the length of the destination buffer, including the existing contents. Unfortunately, I had been overzealous when I wrote a51288aabbbc176a8a73a8b3cd56f79607db32cf, since I gave it the length of the destination buffer, minus the existing contents. This likely caused a regression on large strings. On the topic of being overzealous, the use of strlcat() in dmu_send_estimate_fast() was unnecessary because recv_clone_name is a fixed length string. We continue using strlcat() mostly as defensive programming, in case the string length is ever changed, even though it is unnecessary. Reviewed-by: Ryan Moeller Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14476 --- lib/libshare/nfs.c | 2 +- lib/libzfs/libzfs_sendrecv.c | 4 ++-- module/zfs/dmu_send.c | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/libshare/nfs.c b/lib/libshare/nfs.c index 118ad7ef2..3962c8745 100644 --- a/lib/libshare/nfs.c +++ b/lib/libshare/nfs.c @@ -97,7 +97,7 @@ nfs_init_tmpfile(const char *prefix, const char *mdir, struct tmpfile *tmpf) } strlcpy(tmpf->name, prefix, sizeof (tmpf->name)); - strlcat(tmpf->name, ".XXXXXXXX", sizeof (tmpf->name) - strlen(prefix)); + strlcat(tmpf->name, ".XXXXXXXX", sizeof (tmpf->name)); int fd = mkostemp(tmpf->name, O_CLOEXEC); if (fd == -1) { diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 1d2ad1944..66a22e333 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -4590,7 +4590,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, B_FALSE, destsnap) == 0) { *strchr(destsnap, '@') = '\0'; (void) strlcat(destsnap, suffix, - sizeof (destsnap) - strlen(destsnap)); + sizeof (destsnap)); } } } else { @@ -4626,7 +4626,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, B_FALSE, destsnap) == 0) { *strchr(destsnap, '@') = '\0'; (void) strlcat(destsnap, snap, - sizeof (destsnap) - strlen(destsnap)); + sizeof (destsnap)); } } } diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c index 33beb04b1..f86a0a5b1 100644 --- a/module/zfs/dmu_send.c +++ b/module/zfs/dmu_send.c @@ -3029,8 +3029,7 @@ dmu_send_estimate_fast(dsl_dataset_t *origds, dsl_dataset_t *fromds, dsl_dataset_name(origds, dsname); (void) strcat(dsname, "/"); - (void) strlcat(dsname, recv_clone_name, - sizeof (dsname) - strlen(dsname)); + (void) strlcat(dsname, recv_clone_name, sizeof (dsname)); err = dsl_dataset_hold(origds->ds_dir->dd_pool, dsname, FTAG, &ds);