]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
Don't cast pointers, cast values.
authorWalter Doekes <wjdoekes@osso.nl>
Wed, 16 Dec 2015 14:08:11 +0000 (15:08 +0100)
committerWalter Doekes <wjdoekes@osso.nl>
Wed, 16 Dec 2015 14:24:06 +0000 (15:24 +0100)
The compiler rightly warned about an issue in ed3848130, but the fix was
wrong.

There is no guarantee that an int is exactly 32 bits and no guarantee
that a long long is exactly 64 bits. The former one is guaranteed to be
at least 16 bits (but we can safely assume 32 for non-ancient machines).

Imagine an u32 array:

    0... 1... 2... 3... 4... 5...

Now cast the pointer to the zeroth element to a 64-bits-int-pointer;
64bit sized int are quite common.

    0.......  1.......  2.......

Writing to 0, 1 and 2 would put values in 0, 2 and 4 (on little endian).
And if there is enough data, it would overwrite the stack.

This change moves the casting to the point where the individual values
are copied. That's safe.

nvme.c

diff --git a/nvme.c b/nvme.c
index c64d42c536a1ac095051da39ef90322a504b5c02..35eede24df43f5ec17ae6fd0ab4c81c514eb867f 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -52,6 +52,7 @@
 #include "src/argconfig.h"
 #include "src/suffix.h"
 
+#define array_len(x) ((size_t)(sizeof(x) / sizeof(0[x])))
 #define min(x, y) (x) > (y) ? (y) : (x)
 #define max(x, y) (x) > (y) ? (x) : (y)
 
@@ -2165,9 +2166,9 @@ static int dsm(int argc, char **argv)
 
        int i, err;
        uint16_t nr, nc, nb, ns;
-       __u32 ctx_attrs[256];
-       __u32 nlbs[256];
-       __u64 slbas[256];
+       int ctx_attrs[256] = {0,};
+       int nlbs[256] = {0,};
+       unsigned long long slbas[256] = {0,};
        void *buffer;
        struct nvme_dsm_range *dsm;
 
@@ -2214,17 +2215,13 @@ static int dsm(int argc, char **argv)
                {0}
        };
 
-       memset(ctx_attrs, 0, sizeof(ctx_attrs));
-       memset(slbas, 0, sizeof(slbas));
-       memset(nlbs, 0, sizeof(nlbs));
-
        argconfig_parse(argc, argv, desc, command_line_options,
                        &defaults, &cfg, sizeof(cfg));
        get_dev(1, argc, argv);
 
-       nc = argconfig_parse_comma_sep_array(cfg.ctx_attrs, (int *)ctx_attrs, 256);
-       nb = argconfig_parse_comma_sep_array(cfg.blocks, (int *)nlbs, 256);
-       ns = argconfig_parse_comma_sep_array_long(cfg.slbas, (unsigned long long *)slbas, 256);
+       nc = argconfig_parse_comma_sep_array(cfg.ctx_attrs, ctx_attrs, array_len(ctx_attrs));
+       nb = argconfig_parse_comma_sep_array(cfg.blocks, nlbs, array_len(nlbs));
+       ns = argconfig_parse_comma_sep_array_long(cfg.slbas, slbas, array_len(slbas));
        nr = max(nc, max(nb, ns));
        if (!nr || nr > 256) {
                fprintf(stderr, "No range definition provided\n");
@@ -2256,9 +2253,9 @@ static int dsm(int argc, char **argv)
 
        dsm = buffer;
        for (i = 0; i < nr; i++) {
-               dsm[i].cattr = htole32(ctx_attrs[i]);
-               dsm[i].nlb = htole32(nlbs[i]);
-               dsm[i].slba = htole64(slbas[i]);
+               dsm[i].cattr = htole32((uint32_t)ctx_attrs[i]);
+               dsm[i].nlb = htole32((uint32_t)nlbs[i]);
+               dsm[i].slba = htole64((uint64_t)slbas[i]);
        }
 
        memset(&cmd, 0, sizeof(cmd));