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
This commit is contained in:
Ian Lepore 2015-12-21 17:17:00 +00:00
parent 86acfcf878
commit 69ba629255
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=292552

View file

@ -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)