Commit ba2dbf30 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

cifs: clean up unaligned accesses in cifs_unicode.c

Make sure we use get/put_unaligned routines when accessing wide
character strings.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Acked-by: default avatarPavel Shilovsky <piastryyy@gmail.com>
Reviewed-by: default avatarShirish Pargaonkar <shirishpargaonkar@gmail.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 26ec2548
...@@ -44,10 +44,14 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, ...@@ -44,10 +44,14 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes,
int charlen, outlen = 0; int charlen, outlen = 0;
int maxwords = maxbytes / 2; int maxwords = maxbytes / 2;
char tmp[NLS_MAX_CHARSET_SIZE]; char tmp[NLS_MAX_CHARSET_SIZE];
__u16 ftmp;
for (i = 0; i < maxwords && from[i]; i++) { for (i = 0; i < maxwords; i++) {
charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, ftmp = get_unaligned_le16(&from[i]);
NLS_MAX_CHARSET_SIZE); if (ftmp == 0)
break;
charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE);
if (charlen > 0) if (charlen > 0)
outlen += charlen; outlen += charlen;
else else
...@@ -58,9 +62,9 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, ...@@ -58,9 +62,9 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes,
} }
/* /*
* cifs_mapchar - convert a little-endian char to proper char in codepage * cifs_mapchar - convert a host-endian char to proper char in codepage
* @target - where converted character should be copied * @target - where converted character should be copied
* @src_char - 2 byte little-endian source character * @src_char - 2 byte host-endian source character
* @cp - codepage to which character should be converted * @cp - codepage to which character should be converted
* @mapchar - should character be mapped according to mapchars mount option? * @mapchar - should character be mapped according to mapchars mount option?
* *
...@@ -69,7 +73,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, ...@@ -69,7 +73,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes,
* enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
*/ */
static int static int
cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
bool mapchar) bool mapchar)
{ {
int len = 1; int len = 1;
...@@ -82,7 +86,7 @@ cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, ...@@ -82,7 +86,7 @@ cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp,
* build_path_from_dentry are modified, as they use slash as * build_path_from_dentry are modified, as they use slash as
* separator. * separator.
*/ */
switch (le16_to_cpu(src_char)) { switch (src_char) {
case UNI_COLON: case UNI_COLON:
*target = ':'; *target = ':';
break; break;
...@@ -109,8 +113,7 @@ cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, ...@@ -109,8 +113,7 @@ cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp,
return len; return len;
cp_convert: cp_convert:
len = cp->uni2char(le16_to_cpu(src_char), target, len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE);
NLS_MAX_CHARSET_SIZE);
if (len <= 0) { if (len <= 0) {
*target = '?'; *target = '?';
len = 1; len = 1;
...@@ -149,6 +152,7 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, ...@@ -149,6 +152,7 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
int nullsize = nls_nullsize(codepage); int nullsize = nls_nullsize(codepage);
int fromwords = fromlen / 2; int fromwords = fromlen / 2;
char tmp[NLS_MAX_CHARSET_SIZE]; char tmp[NLS_MAX_CHARSET_SIZE];
__u16 ftmp;
/* /*
* because the chars can be of varying widths, we need to take care * because the chars can be of varying widths, we need to take care
...@@ -158,19 +162,23 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, ...@@ -158,19 +162,23 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
*/ */
safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
for (i = 0; i < fromwords && from[i]; i++) { for (i = 0; i < fromwords; i++) {
ftmp = get_unaligned_le16(&from[i]);
if (ftmp == 0)
break;
/* /*
* check to see if converting this character might make the * check to see if converting this character might make the
* conversion bleed into the null terminator * conversion bleed into the null terminator
*/ */
if (outlen >= safelen) { if (outlen >= safelen) {
charlen = cifs_mapchar(tmp, from[i], codepage, mapchar); charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar);
if ((outlen + charlen) > (tolen - nullsize)) if ((outlen + charlen) > (tolen - nullsize))
break; break;
} }
/* put converted char into 'to' buffer */ /* put converted char into 'to' buffer */
charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar); charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar);
outlen += charlen; outlen += charlen;
} }
...@@ -193,24 +201,21 @@ cifs_strtoUCS(__le16 *to, const char *from, int len, ...@@ -193,24 +201,21 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
{ {
int charlen; int charlen;
int i; int i;
wchar_t *wchar_to = (wchar_t *)to; /* needed to quiet sparse */ wchar_t wchar_to; /* needed to quiet sparse */
for (i = 0; len && *from; i++, from += charlen, len -= charlen) { for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
charlen = codepage->char2uni(from, len, &wchar_to);
/* works for 2.4.0 kernel or later */
charlen = codepage->char2uni(from, len, &wchar_to[i]);
if (charlen < 1) { if (charlen < 1) {
cERROR(1, "strtoUCS: char2uni of %d returned %d", cERROR(1, "strtoUCS: char2uni of 0x%x returned %d",
(int)*from, charlen); *from, charlen);
/* A question mark */ /* A question mark */
to[i] = cpu_to_le16(0x003f); wchar_to = 0x003f;
charlen = 1; charlen = 1;
} else }
to[i] = cpu_to_le16(wchar_to[i]); put_unaligned_le16(wchar_to, &to[i]);
} }
to[i] = 0; put_unaligned_le16(0, &to[i]);
return i; return i;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment