[linux-cifs-client] Re: [PATCH] cifs: add helper to simplify unicode to NLS conversion and use it (try #2)

Suresh Jayaraman sjayaraman at suse.de
Mon Apr 13 12:59:11 GMT 2009


Jeff Layton wrote:
> On Mon, 13 Apr 2009 15:13:16 +0530
> Suresh Jayaraman <sjayaraman at suse.de> wrote:

>> Add helper to simplify unicode(UCS/UTF-16) to NLS conversion. The helper
>> function calculates the memory needed exactly instead of using size
>> assumptions and consolidates some common code in there.
>>
>> Signed-off-by: Suresh Jayaraman <sjayaraman at suse.de>
>> ---
>>
>>  fs/cifs/cifs_unicode.h |   28 ++++++++++++++++++++
>>  fs/cifs/cifsproto.h    |    2 +
>>  fs/cifs/cifssmb.c      |   31 ++++++++++++++++++++++
>>  fs/cifs/connect.c      |   67 +++++++++++++++++++----------------------------
>>  fs/cifs/sess.c         |   46 +++++++++++++++-----------------
>>  5 files changed, 110 insertions(+), 64 deletions(-)
>>
>> diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
>> index 14eb9a2..06a267b 100644
>> --- a/fs/cifs/cifs_unicode.h
>> +++ b/fs/cifs/cifs_unicode.h
>> @@ -159,6 +159,34 @@ UniStrnlen(const wchar_t *ucs1, int maxlen)
>>  }
>>  
>>  /*
>> + * UniStrnlenBytes: Return the length of a NLS string in bytes. Also, populates
>> + * 'nchars' with the length of string in 16 bit Unicode chars.
>> + */
>> +static inline size_t
>> +UniStrnlenBytes(const wchar_t *str, int maxlen, int *nchars,
>> +		const struct nls_table *codepage)
>> +{
>> +	int nc;
>> +	size_t i = 0, nbytes = 0;
>> +	wchar_t uni = *str;
>> +	char buf[NLS_MAX_CHARSET_SIZE]; /* enough for one char at a time */
>> +
>> +	while (*str++ && maxlen) {
>> +		nc = codepage->uni2char(uni, buf, NLS_MAX_CHARSET_SIZE);
>> +		if (nc > 0)
>> +			nbytes += nc;
>> +		else
>> +			nbytes += 1; /* for '?' */
>> +		i++;
>> +		if (i >= maxlen)
>> +			break;
>> +	}
>> +	*nchars = i;
> 
> Peter has a good point that we can get nchars by dividing the input
> string size by 2. It might mean a few less operations but I doubt it
> will be measurable.

Did you mean output nbytes by 2?

As Peter pointed out, unneeded stack var uni can be removed. Other than
that, do you see any other changes/improvements?

>> diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
>> index 5c68b42..1c50063 100644
>> --- a/fs/cifs/sess.c
>> +++ b/fs/cifs/sess.c
>> @@ -301,33 +301,32 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
>>  	words_left = bleft / 2;
>>  
>>  	/* save off server operating system */
>> -	len = UniStrnlen((wchar_t *) data, words_left);
>>  
>> -/* We look for obvious messed up bcc or strings in response so we do not go off
>> -   the end since (at least) WIN2K and Windows XP have a major bug in not null
>> -   terminating last Unicode string in response  */
>> +	/* Win2K and Windows XP seem to have a major bug in not null terminating
>> +	 * last unicode string in response */
>> +	kfree(ses->serverOS);
>> +	rc = cifs_ucs_to_nls(&(ses->serverOS), data, words_left, &len, nls_cp);
>> +	if (rc)
>> +		return rc;
>> +
>>  	if (len >= words_left)
>>  		return rc;
>>  
> 
> So will this code make it so that we work around this bug in win2k and
> XP? Or will it return an error when it gets one of these improperly
> terminated packets?

I think so, perhaps Steve is the right person to ask, Steve?

> It seems like if that's a danger then before doing the string
> coversion, maybe we should detect when the response isn't properly NULL
> terminated and fix up the packet so that it is. Then we could just run
> it through the helper routines above without having to these extra
> checks. Or maybe I'm misunderstanding the problem?

My comment was based on the earlier comment and I have not seen
experienced this issue. I also need to understand this better.

Thanks,

-- 
Suresh Jayaraman


More information about the linux-cifs-client mailing list