Skip to content

Commit

Permalink
Use get_unaligned_be*() to avoid UB
Browse files Browse the repository at this point in the history
In most cases using strict aliasing is undefined behaviour.
Obviously cdb is supposed to be an array of bytes and accessing
any CDB field using strict aliasing leads to misaligned read which
may cause even a crash.

Signed-off-by: Dmitry Ashkadov <[email protected]>
  • Loading branch information
dmitryash authored and lxbsz committed Oct 13, 2022
1 parent 364ae61 commit 4df9a54
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 8 deletions.
14 changes: 7 additions & 7 deletions api.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ uint64_t tcmu_cdb_get_lba(uint8_t *cdb)

switch (tcmu_cdb_get_length(cdb)) {
case 6:
val = be16toh(*((uint16_t *)&cdb[2]));
val = get_unaligned_be16(&cdb[2]);
return ((cdb[1] & 0x1f) << 16) | val;
case 10:
return be32toh(*((u_int32_t *)&cdb[2]));
return get_unaligned_be32(&cdb[2]);
case 12:
return be32toh(*((u_int32_t *)&cdb[2]));
return get_unaligned_be32(&cdb[2]);
case 16:
return be64toh(*((u_int64_t *)&cdb[2]));
return get_unaligned_be64(&cdb[2]);
default:
assert(0);
return 0; /* not reached */
Expand All @@ -87,11 +87,11 @@ uint32_t tcmu_cdb_get_xfer_length(uint8_t *cdb)
case 6:
return cdb[4];
case 10:
return be16toh(*((uint16_t *)&cdb[7]));
return get_unaligned_be16(&cdb[7]);
case 12:
return be32toh(*((u_int32_t *)&cdb[6]));
return get_unaligned_be32(&cdb[6]);
case 16:
return be32toh(*((u_int32_t *)&cdb[10]));
return get_unaligned_be32(&cdb[10]);
default:
assert(0);
return 0; /* not reached */
Expand Down
20 changes: 19 additions & 1 deletion be_byteshift.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
#ifndef _TCMU_BE_BYTESHIFT_H
#define _TCMU_BE_BYTESHIFT_H

#include <endian.h>
#include <stdint.h>
#include <string.h>


static inline void __put_unaligned_be32(uint32_t val, uint8_t *p)
{
*p++ = val >> 24;
Expand Down Expand Up @@ -48,9 +53,22 @@ static inline uint32_t __get_unaligned_be32(const uint8_t *p)
return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}

static inline uint16_t get_unaligned_be32(const void *p)
static inline uint32_t get_unaligned_be32(const void *p)
{
return __get_unaligned_be32(p);
}

static inline uint64_t get_unaligned_be64(const void *p)
{
uint64_t val;
memcpy(&val, p, sizeof(val));
return be64toh(val);
}

static inline void put_unaligned_be64(uint64_t val, void *p)
{
val = htobe64(val);
memcpy(p, &val, sizeof(val));
}

#endif

0 comments on commit 4df9a54

Please sign in to comment.