diff options
author | ian <ian@FreeBSD.org> | 2015-12-21 17:17:00 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2015-12-21 17:17:00 +0000 |
commit | 1a16baceaae6c0428099af41b18d01eebc56f62b (patch) | |
tree | a2a580e85aa980e5154f8536ccf853fde8b151e8 /contrib/smbfs/lib | |
parent | e93f3f0c71917233d6e21e3fd05e1520d2d84984 (diff) | |
download | FreeBSD-src-1a16baceaae6c0428099af41b18d01eebc56f62b.zip FreeBSD-src-1a16baceaae6c0428099af41b18d01eebc56f62b.tar.gz |
Avoid unaligned memory accesses when encoding netbios names in libsmb.
The current code for encoding a netbios name converts each byte to a 16-bit
value and stores the result by casting a char* to u_short*, resulting in
alignment faults on strict-alignment platforms.
This change reimplements the encoding routine using only byte accesses to
memory. There is no particular reason to work with 16-bit values just
because the encoding process creates two bytes of output for every byte of
input. Working a byte at at time also avoids endian problems for big-endian
platforms.
PR: 180438
PR: 189415
Differential Revision: https://reviews.freebsd.org/D4622
Diffstat (limited to 'contrib/smbfs/lib')
-rw-r--r-- | contrib/smbfs/lib/smb/nb_name.c | 32 |
1 files changed, 13 insertions, 19 deletions
diff --git a/contrib/smbfs/lib/smb/nb_name.c b/contrib/smbfs/lib/smb/nb_name.c index 2346ec7..a953ce0 100644 --- a/contrib/smbfs/lib/smb/nb_name.c +++ b/contrib/smbfs/lib/smb/nb_name.c @@ -143,15 +143,13 @@ nb_encname_len(const char *str) return len; } -#define NBENCODE(c) (htole16((u_short)(((u_char)(c) >> 4) | \ - (((u_char)(c) & 0xf) << 8)) + 0x4141)) - -static void -memsetw(char *dst, int n, u_short word) +static inline void +nb_char_encode(u_char **ptr, u_char c, int n) { + while (n--) { - *(u_short*)dst = word; - dst += 2; + *(*ptr)++ = 0x41 + (c >> 4); + *(*ptr)++ = 0x41 + (c & 0x0f); } } @@ -165,19 +163,15 @@ nb_name_encode(struct nb_name *np, u_char *dst) *cp++ = NB_ENCNAMELEN; name = np->nn_name; if (name[0] == '*' && name[1] == 0) { - *(u_short*)cp = NBENCODE('*'); - memsetw(cp + 2, NB_NAMELEN - 1, NBENCODE(' ')); - cp += NB_ENCNAMELEN; + nb_char_encode(&cp, '*', 1); + nb_char_encode(&cp, ' ', NB_NAMELEN - 1); } else { - for (i = 0; *name && i < NB_NAMELEN - 1; i++, cp += 2, name++) - *(u_short*)cp = NBENCODE(toupper(*name)); - i = NB_NAMELEN - i - 1; - if (i > 0) { - memsetw(cp, i, NBENCODE(' ')); - cp += i * 2; - } - *(u_short*)cp = NBENCODE(np->nn_type); - cp += 2; + for (i = 0; i < NB_NAMELEN - 1; i++) + if (*name != 0) + nb_char_encode(&cp, toupper(*name++), 1); + else + nb_char_encode(&cp, ' ', 1); + nb_char_encode(&cp, np->nn_type, 1); } *cp = 0; if (np->nn_scope == NULL) |