]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Use signed types to prevent subtraction overflow
authorRyan Moeller <ryan@freqlabs.com>
Sun, 22 Sep 2019 22:27:53 +0000 (18:27 -0400)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Sun, 22 Sep 2019 22:27:53 +0000 (15:27 -0700)
The difference between the sizes could be positive or negative. Leaving
the types as unsigned means the result overflows when the difference is
negative and removing the labs() means we'll have introduced a bug. The
subtraction results in the correct value when the unsigned integer is
interpreted as a signed integer by labs().

Clang doesn't see that we're doing a subtraction and abusing the types.
It sees the result of the subtraction, an unsigned value, being passed
to an absolute value function and emits a warning which we treat as an
error.

Reviewed by: Youzhong Yang <youzhong@gmail.com>
Reviewed-by: Igor Kozhukhov <igor@dilos.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ryan Moeller <ryan@ixsystems.com>
Closes #9355

cmd/zpool/zpool_vdev.c

index ef2a30996e530d91336bf37b54fb16496a3ed935..527fca08b887b80483f0409ad351fe62044449de 100644 (file)
@@ -829,7 +829,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
                        rep.zprl_children = 1;
                        rep.zprl_parity = 0;
                } else {
-                       uint64_t vdev_size;
+                       int64_t vdev_size;
 
                        /*
                         * This is a mirror or RAID-Z vdev.  Go through and make
@@ -859,12 +859,12 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
                         */
                        type = NULL;
                        dontreport = 0;
-                       vdev_size = -1ULL;
+                       vdev_size = -1LL;
                        for (c = 0; c < children; c++) {
                                nvlist_t *cnv = child[c];
                                char *path;
                                struct stat64 statbuf;
-                               uint64_t size = -1ULL;
+                               int64_t size = -1LL;
                                char *childtype;
                                int fd, err;
 
@@ -955,7 +955,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
                                 * (~16MB) then report an error.
                                 */
                                if (!dontreport &&
-                                   (vdev_size != -1ULL &&
+                                   (vdev_size != -1LL &&
                                    (labs(size - vdev_size) >
                                    ZPOOL_FUZZ))) {
                                        if (ret != NULL)