All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marcin Slusarz <marcin.slusarz@gmail.com>
To: Jan Kara <jack@suse.cz>
Cc: LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 02/10] udf: fix udf_build_ustr
Date: Mon, 4 Feb 2008 22:27:39 +0100	[thread overview]
Message-ID: <20080204212733.GA12562@joi> (raw)
In-Reply-To: <20080204193107.GN3426@duck.suse.cz>

On Mon, Feb 04, 2008 at 08:31:07PM +0100, Jan Kara wrote:
> On Thu 31-01-08 20:57:47, Marcin Slusarz wrote:
> > On Thu, Jan 31, 2008 at 11:45:32AM +0100, Jan Kara wrote:
> > > On Wed 30-01-08 22:03:52, marcin.slusarz@gmail.com wrote:
> > > > udf_build_ustr was completely broken when
> > > > size >= UDF_NAME_LEN - 1 or size < 2
> > > > 
> > > > nobody noticed because all callers set size
> > > > to acceptable values (constants)
> > > > 
> > > > Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>
> > > > Cc: Jan Kara <jack@suse.cz>
> > > > ---
> > > >  fs/udf/unicode.c |   12 ++++++------
> > > >  1 files changed, 6 insertions(+), 6 deletions(-)
> > > > 
> > > > diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
> > > > index f969617..f4e54e5 100644
> > > > --- a/fs/udf/unicode.c
> > > > +++ b/fs/udf/unicode.c
> > > > @@ -47,16 +47,16 @@ static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
> > > >   */
> > > >  int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
> > > >  {
> > > > -	int usesize;
> > > > +	u8 usesize;
> > >   What is the purpose for this? Why not just leave int there? Arithmetics
> > > is usually best done in ints if that's possible...
> > I made it to stress that length of string fits in one byte.
> > (struct ustr->u_len is uint8_t)
>   I see. I don't think this is really worthwhile, please keep int there.
> 
> > > > -	if ((!dest) || (!ptr) || (!size))
> > > > +	if (!dest || !ptr || size < 2)
> > > >  		return -1;
> > > >  
> > > > -	memset(dest, 0, sizeof(struct ustr));
> > > > -	usesize = (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size;
> > > > +	usesize = min_t(size_t, size - 2, sizeof(dest->u_name));
> > > >  	dest->u_cmpID = ptr[0];
> > > > -	dest->u_len = ptr[size - 1];
> > > > -	memcpy(dest->u_name, ptr + 1, usesize - 1);
> > > > +	dest->u_len = usesize;
> > > > +	memcpy(dest->u_name, ptr + 1, usesize);
> > > > +	memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize);
> > >   Hmm, after parsing what the standard says (ugh), I don't think the code is
> > > wrong (at least I think you made it incorrect). The caller of
> > > udf_char_to_ustr() specifies length of the field (not length of the
> > > string). Now, in the last character of the field is stored the number of
> > > characters in the string and in the first character of the field is stored
> > > encoding of the string. So the original code seems correct.
> > You are right. I broke length calculation.
> > 
> > But observe that:
> > - when size == 1:
> > 	dest->u_len = ptr[1 - 1], but at ptr[0] there's cmpID,
> > 	so we create string with wrong length
>   Yes, but that never happens. This function should always be used for
> fixed-length strings whose maximum length is defined in the standard so if
> someone calls it with size == 1, it is a bug. So you can just do
> BUG_ON(size < 2).
> 
> > - when size > 1 and size < UDF_NAME_LEN:
> > 	we set u_len correctly, but memcpy copies one needless byte
> > - when size == UDF_NAME_LEN - 1:
> > 	memcpy overwrites u_len - with correct value, but...
>   Yes, you're right.
> 
> > - when size >= UDF_NAME_LEN:
> > 	we copy UDF_NAME_LEN - 1 bytes, but dest->u_name is array
> > 	of UDF_NAME_LEN - 2 bytes, so we are overwriting u_len with
> > 	character from input string
>   Again, this should not happen because UDF_NAME_LEN is large enough but
> you are right it's better to clean this.
> 
> > So if I didn't mess up someting, correct change would look like this:
> > ---
> > udf: fix udf_build_ustr
> > 
> > udf_build_ustr was broken when
> > size >= UDF_NAME_LEN or size < 2
> > 
> > nobody noticed because all callers set size
> > to acceptable values (constants whitin range)
> > 
> > Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>
> > Cc: Jan Kara <jack@suse.cz>
> > ---
> >  fs/udf/unicode.c |   13 +++++++------
> >  1 files changed, 7 insertions(+), 6 deletions(-)
> > 
> > diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
> > index 335fc56..83ae9fc 100644
> > --- a/fs/udf/unicode.c
> > +++ b/fs/udf/unicode.c
> > @@ -47,16 +47,17 @@ static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
> >   */
> >  int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
> >  {
> > -	int usesize;
> > +	u8 usesize;
>   Just use int here..
Ok
 
> >  
> > -	if ((!dest) || (!ptr) || (!size))
> > +	if (!dest || !ptr || size < 2)
> >  		return -1;
> >  
> > -	memset(dest, 0, sizeof(struct ustr));
> > -	usesize = (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size;
> > +	usesize = min_t(size_t, ptr[size - 1], sizeof(dest->u_name));
> > +	usesize = min_t(size_t, usesize, size - 2);
>   And here use just min() in both cases so that it's easier to read.
I used min_t because gcc and sparse warned about different types.
 
> >  	dest->u_cmpID = ptr[0];
> > -	dest->u_len = ptr[size - 1];
> > -	memcpy(dest->u_name, ptr + 1, usesize - 1);
> > +	dest->u_len = usesize;
> > +	memcpy(dest->u_name, ptr + 1, usesize);
> > +	memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize);
> >  
> >  	return 0;
> >  }
>   Otherwise it looks fine. Thanks for the cleanups.

Updated patch:
---
udf: fix udf_build_ustr

udf_build_ustr was broken:

- size == 1:
    dest->u_len = ptr[1 - 1], but at ptr[0] there's cmpID,
    so we created string with wrong length
    it should not happen, so we BUG() it
- size > 1 and size < UDF_NAME_LEN:
    we set u_len correctly, but memcpy copied one needless byte
- size == UDF_NAME_LEN - 1:
    memcpy overwrited u_len - with correct value, but...
- size >= UDF_NAME_LEN:
    we copied UDF_NAME_LEN - 1 bytes, but dest->u_name is array
    of UDF_NAME_LEN - 2 bytes, so we were overwriting u_len with
    character from input string

nobody noticed because all callers set size
to acceptable values (constants whitin range)

Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>
Cc: Jan Kara <jack@suse.cz>
---
 fs/udf/unicode.c |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
index 335fc56..442d38a 100644
--- a/fs/udf/unicode.c
+++ b/fs/udf/unicode.c
@@ -49,14 +49,16 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
 {
 	int usesize;
 
-	if ((!dest) || (!ptr) || (!size))
+	if (!dest || !ptr || !size)
 		return -1;
+	BUG_ON(size < 2);
 
-	memset(dest, 0, sizeof(struct ustr));
-	usesize = (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size;
+	usesize = min_t(size_t, ptr[size - 1], sizeof(dest->u_name));
+	usesize = min(usesize, size - 2);
 	dest->u_cmpID = ptr[0];
-	dest->u_len = ptr[size - 1];
-	memcpy(dest->u_name, ptr + 1, usesize - 1);
+	dest->u_len = usesize;
+	memcpy(dest->u_name, ptr + 1, usesize);
+	memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize);
 
 	return 0;
 }
-- 
1.5.3.7


  reply	other threads:[~2008-02-04 21:28 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-30 21:03 [PATCH 00/10] udf: cleanups marcin.slusarz
2008-01-30 21:03 ` [PATCH 01/10] udf: udf_CS0toUTF8 cleanup marcin.slusarz
2008-01-31  9:57   ` Jan Kara
2008-01-30 21:03 ` [PATCH 02/10] udf: fix udf_build_ustr marcin.slusarz
2008-01-31 10:45   ` Jan Kara
2008-01-31 19:57     ` Marcin Slusarz
2008-02-04 19:31       ` Jan Kara
2008-02-04 21:27         ` Marcin Slusarz [this message]
2008-02-05 15:29           ` Jan Kara
2008-02-05 19:17             ` Marcin Slusarz
2008-01-30 21:03 ` [PATCH 03/10] udf: udf_CS0toNLS cleanup marcin.slusarz
2008-01-31 12:23   ` Jan Kara
2008-01-30 21:03 ` [PATCH 04/10] udf: constify crc marcin.slusarz
2008-01-31 12:58   ` Jan Kara
2008-01-30 21:03 ` [PATCH 05/10] udf: simple cleanup of truncate.c marcin.slusarz
2008-01-31 13:01   ` Jan Kara
2008-01-30 21:03 ` [PATCH 06/10] udf: truncate: create function for updating of Allocation Ext Descriptor marcin.slusarz
2008-01-31 17:08   ` Jan Kara
2008-01-31 18:18     ` Marcin Slusarz
2008-01-30 21:03 ` [PATCH 07/10] udf: replace all adds to little endians variables with le*_add_cpu marcin.slusarz
2008-01-31 16:42   ` Jan Kara
2008-01-30 21:03 ` [PATCH 08/10] udf: simplify __udf_read_inode marcin.slusarz
2008-01-31 16:46   ` Jan Kara
2008-01-30 21:03 ` [PATCH 09/10] udf: replace udf_*_offset macros with functions marcin.slusarz
2008-01-31 16:48   ` Jan Kara
2008-01-30 21:04 ` [PATCH 10/10] udf: constify udf_bitmap_lookup array marcin.slusarz
2008-01-31 16:52   ` Jan Kara
2008-02-02 21:37     ` Marcin Slusarz
2008-02-04 19:15       ` Jan Kara

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080204212733.GA12562@joi \
    --to=marcin.slusarz@gmail.com \
    --cc=jack@suse.cz \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.