This is the mail archive of the
libc-alpha@sourceware.cygnus.com
mailing list for the glibc project.
again a gettext crash
- To: libc-alpha at sourceware dot cygnus dot com
- Subject: again a gettext crash
- From: Bruno Haible <haible at ilog dot fr>
- Date: Fri, 5 May 2000 15:29:27 +0200 (MET DST)
Here are tweaks of small mistakes I made in the previous patches.
a. The size passed to gconv/iconv for its output buffer is larger than the
room that's really present.
b. After allocation failure for freemem, set freemem_size to 0, otherwise the
next call will think that freemem is valid and make a NULL pointer access.
c. A portability problem: Use of __alignof__ is gcc specific.
2000-05-05 Bruno Haible <haible@clisp.cons.org>
* intl/dcigettext.c (alignof): New macro.
(_nl_find_msg): Use it instead of __alignof__. Pass correct output
buffer length to __gconv/iconv. If malloc (freemem_size) fails, set
freemem_size to 0.
*** intl/dcigettext.c.bak Thu May 4 12:53:41 2000
--- intl/dcigettext.c Fri May 5 12:20:35 2000
***************
*** 110,115 ****
--- 110,123 ----
# define __libc_rwlock_unlock(NAME)
#endif
+ /* Alignment of types. */
+ #if defined __GNUC__ && __GNUC__ >= 2
+ # define alignof(TYPE) __alignof__ (TYPE)
+ #else
+ # define alignof(TYPE) \
+ ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
+ #endif
+
/* @@ end of prolog @@ */
#ifdef _LIBC
***************
*** 795,803 ****
size_t non_reversible;
int res;
res = __gconv (domain->conv,
&inbuf, inbuf + resultlen,
! &outbuf, outbuf + freemem_size,
&non_reversible);
if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
--- 804,815 ----
size_t non_reversible;
int res;
+ if (freemem_size < 4)
+ goto resize_freemem;
+
res = __gconv (domain->conv,
&inbuf, inbuf + resultlen,
! &outbuf, outbuf + freemem_size - 4,
&non_reversible);
if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
***************
*** 815,822 ****
const char *inptr = (const char *) inbuf;
size_t inleft = resultlen;
char *outptr = (char *) outbuf;
! size_t outleft = freemem_size;
if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
!= (size_t) (-1))
{
--- 827,838 ----
const char *inptr = (const char *) inbuf;
size_t inleft = resultlen;
char *outptr = (char *) outbuf;
! size_t outleft;
!
! if (freemem_size < 4)
! goto resize_freemem;
+ outleft = freemem_size - 4;
if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
!= (size_t) (-1))
{
***************
*** 831,836 ****
--- 847,853 ----
# endif
# endif
+ resize_freemem:
/* We must resize the buffer. */
freemem_size = 2 * freemem_size;
if (freemem_size < 4064)
***************
*** 838,843 ****
--- 855,861 ----
freemem = (char *) malloc (freemem_size);
if (__builtin_expect (freemem == NULL, 0))
{
+ freemem_size = 0;
__libc_lock_unlock (lock);
goto converted;
}
***************
*** 852,859 ****
/* Shrink freemem, but keep it aligned. */
freemem_size -= outbuf - freemem;
freemem = outbuf;
! freemem += freemem_size & (__alignof__ (nls_uint32) - 1);
! freemem_size = freemem_size & ~ (__alignof__ (nls_uint32) - 1);
__libc_lock_unlock (lock);
}
--- 870,877 ----
/* Shrink freemem, but keep it aligned. */
freemem_size -= outbuf - freemem;
freemem = outbuf;
! freemem += freemem_size & (alignof (nls_uint32) - 1);
! freemem_size = freemem_size & ~ (alignof (nls_uint32) - 1);
__libc_lock_unlock (lock);
}