From: Walter Doekes Date: Wed, 16 Dec 2015 14:08:11 +0000 (+0100) Subject: Don't cast pointers, cast values. X-Git-Tag: v0.3~7^2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=97ff45ce711e1f356641d25f898f9b53fbb79634;p=users%2Fsagi%2Fnvme-cli.git Don't cast pointers, cast values. 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. --- diff --git a/nvme.c b/nvme.c index c64d42c5..35eede24 100644 --- 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));