Subject: Re: CVS commit: basesrc/lib/libc/locale
To: None <tshiozak@netbsd.org>
From: enami tsugutomo <enami@sm.sony.co.jp>
List: source-changes
Date: 08/06/2002 17:13:57
Takuya SHIOZAKI <tshiozak@netbsd.org> writes:
> Module Name: basesrc
> Committed By: tshiozak
> Date: Fri Aug 2 07:12:52 UTC 2002
>
> Modified Files:
> basesrc/lib/libc/locale: setlocale.c
>
> Log Message:
> fix a bug of setlocale when changing locales with LC_ALL for the first
> argunemt and with a string containing many slashes for the second argument.
> This bug may cause setlocale() to destroy static datas.
From reading the source, there may be still/more bugs.
1) If the first category is followed by multiple slash, it may be
copied into new_categories[1]. I guess further load may fail tho.
2) If multiple slash appears later, the `locale' may goes beyond the
`r', and `len' become negative.
I've confirmed the latter actually.
enami.
Index: setlocale.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/locale/setlocale.c,v
retrieving revision 1.41
diff -c -r1.41 setlocale.c
*** setlocale.c 2002/08/03 06:12:30 1.41
--- setlocale.c 2002/08/06 07:48:13
***************
*** 153,188 ****
(void)strlcpy(new_categories[category], locale,
sizeof(new_categories[category]));
} else {
! if ((r = strchr(locale, '/')) == 0) {
! for (i = 1; i < _LC_LAST; ++i) {
! (void)strlcpy(new_categories[i], locale,
! sizeof(new_categories[i]));
}
! } else {
! for (i = 1; r[1] == '/'; ++r)
! ;
! if (!r[1])
! return (NULL); /* Hmm, just slashes... */
! do {
! if (i == _LC_LAST)
! return (NULL); /* too many slashes. */
! len = r - locale;
! if (len + 1 > sizeof(new_categories[i]))
! return (NULL); /* too long */
! (void)memcpy(new_categories[i], locale, len);
! new_categories[i][len] = '\0';
! i++;
! locale = r;
! while (*locale == '/')
! ++locale;
! while (*++r && *r != '/');
! } while (*locale);
! while (i < _LC_LAST) {
! (void)strlcpy(new_categories[i],
! new_categories[i - 1],
! sizeof(new_categories[i]));
! i++;
! }
}
}
--- 153,180 ----
(void)strlcpy(new_categories[category], locale,
sizeof(new_categories[category]));
} else {
! for (i = 1;; i++, locale = r) {
! while (*locale == '/')
! locale++;
! for (r = locale; *r && *r != '/';)
! r++;
! len = r - locale;
! if (len == 0) {
! if (i == 1)
! return (NULL); /* Hmm, just
! slashes... */
! break; /* The end of string */
}
! if (len + 1 > sizeof(new_categories[i]))
! return (NULL); /* too long */
! (void)memcpy(new_categories[i], locale, len);
! new_categories[i][len] = '\0';
! }
! while (i < _LC_LAST) {
! (void)strlcpy(new_categories[i],
! new_categories[i - 1],
! sizeof(new_categories[i]));
! i++;
}
}