From fe86864a4029eb7e5ff8c1fbdd6230701c5facaa Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Thu, 10 Jul 2025 11:17:20 +0000 Subject: [PATCH] btrfsctl: Fix number parsing Signed-off-by: Michael Tremer --- src/misc-progs/btrfsctrl.c | 47 ++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/misc-progs/btrfsctrl.c b/src/misc-progs/btrfsctrl.c index 3222b981c..7a68bb0b2 100644 --- a/src/misc-progs/btrfsctrl.c +++ b/src/misc-progs/btrfsctrl.c @@ -52,14 +52,26 @@ static int btrfsctrl_validate_name(const char* name) { /* * Validates if a given number of type char only contains digits. */ -static int btrfsctrl_validate_number(const char* number) { - if (!number) +static int btrfsctrl_parse_number(uint64_t* result, const char* number) { + char* remainder = NULL; + + // Check the input + if (!result || !number) return -EINVAL; - // Check if the given id is a valid number - if (strspn(number, NUMBERS) != strlen(number)) { - return 1; - } + // Parse the input + unsigned long n = strtoul(number, &remainder, 0); + + // Failed to parse + if (n == ULONG_MAX) + return -errno; + + // If there is a remainder, we could not successfully parse the number + if (remainder && *remainder) + return -EINVAL; + + // Return the number + *result = n; return 0; } @@ -333,6 +345,7 @@ int main(int argc, char *argv[]) { char* restore = NULL; char* path = NULL; int fd = -EBADF; + uint64_t id; int r; if (!(initsetuid())) @@ -402,16 +415,13 @@ int main(int argc, char *argv[]) { // Delete a snapshot by it's given ID } else if (strcmp(argv[1], "snapshot-delete") == 0) { - // Check if the given id is a valid number. - r = btrfsctrl_validate_number(argv[2]); + // Parse the snapshot ID + r = btrfsctrl_parse_number(&id, argv[2]); if (r < 0) { - fprintf(stderr, "Invalid snaphot ID: Not a numerical input.\n"); + fprintf(stderr, "Invalid snapshot ID: %s\n", strerror(-r)); goto ERROR; } - // Convert the given id string to unsigned long int. - uint64_t id = strtoul(argv[2], NULL, 0); - // Open a file descriptor to the SNAPSHOTDIR. fd = open(SNAPSHOTDIR, O_DIRECTORY); if (fd < 0) { @@ -428,16 +438,13 @@ int main(int argc, char *argv[]) { // Restore a snapshot with a given ID. } else if (strcmp(argv[1], "snapshot-restore") == 0) { - // Check if the given id is a valid number. - r = btrfsctrl_validate_number(argv[2]); - if(r < 0) { - fprintf(stderr, "Invalid snapshot ID. Not a numerical input.\n"); + // Parse the snapshot ID + r = btrfsctrl_parse_number(&id, argv[2]); + if (r < 0) { + fprintf(stderr, "Invalid snapshot ID: %s\n", strerror(-r)); goto ERROR; } - // Convert the given id string to unsigned long int. - uint64_t id = strtoul(argv[2], NULL, 0); - // Get the path of the given snapshot ID. r = btrfs_util_subvolume_get_path(ROOTDIR, id, &path); if (r != BTRFS_UTIL_OK) { @@ -509,7 +516,7 @@ int main(int argc, char *argv[]) { r = btrfs_util_subvolume_set_read_only(newname, true); if (r != BTRFS_UTIL_OK) { fprintf(stderr, "Could not change the rootfs backup to read-only: %s\n", - btrfs_util_strerror(ret)); + btrfs_util_strerror(r)); goto ERROR; } #endif -- 2.47.2