This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

intl patches (4)



Too much memory is allocated by the library. For example, after

struct binding
{
  struct binding *next;
  char *dirname;
  char *codeset;
#ifdef __GNUC__
  char domainname[0];
#else
  char domainname[1];
#endif
};

the expression

               malloc (sizeof (struct binding) + len)

allocates alignof(struct binding) (four or eight) bytes too much memory on
non-GCC compilers. The right expression is

               malloc (offsetof (struct binding, domainname) + len)

The patch fixes this, and simplifies the declarations by moving the 'ZERO'
macro to an include file.

This patch doesn't cause behaviour changes in glibc.


2001-03-17  Bruno Haible  <haible@clisp.cons.org>

	* intl/gettextP.h (ZERO): New macro.
	(struct binding): Always use ZERO.
	* intl/bindtextdom.c (offsetof): Provide fallback for platforms that
	lack it, like SunOS4.
	(set_binding_values): Use offsetof, not sizeof.
	* intl/dcigettext.c (offsetof): Provide fallback for platforms that
	lack it, like SunOS4.
	(ZERO): Remove macro.
	(struct transmem_list): Use ZERO.
	(DCIGETTEXT): Use offsetof, not sizeof.

diff -r -c3 intl/gettextP.h intl/gettextP.h
*** intl/gettextP.h	Sat Mar 17 17:06:11 2001
--- intl/gettextP.h	Sat Mar 17 17:19:19 2001
***************
*** 119,124 ****
--- 119,125 ----
  };
  
  
+ /* The representation of an opened message catalog.  */
  struct loaded_domain
  {
    const char *data;
***************
*** 143,160 ****
    unsigned long int nplurals;
  };
  
  struct binding
  {
    struct binding *next;
    char *dirname;
    char *codeset;
! #ifdef __GNUC__
!   char domainname[0];
! #else
!   char domainname[1];
! #endif
  };
  
  extern int _nl_msg_cat_cntr;
  
  struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
--- 144,170 ----
    unsigned long int nplurals;
  };
  
+ /* We want to allocate a string at the end of the struct.  But ISO C
+    doesn't allow zero sized arrays.  */
+ #ifdef __GNUC__
+ # define ZERO 0
+ #else
+ # define ZERO 1
+ #endif
+ 
+ /* A set of settings bound to a message domain.  Used to store settings
+    from bindtextdomain() and bind_textdomain_codeset().  */
  struct binding
  {
    struct binding *next;
    char *dirname;
    char *codeset;
!   char domainname[ZERO];
  };
  
+ /* A counter which is incremented each time some previous translations
+    become invalid.
+    This variable is part of the external ABI of the GNU libintl.  */
  extern int _nl_msg_cat_cntr;
  
  struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
diff -r -c3 intl/bindtextdom.c intl/bindtextdom.c
*** intl/bindtextdom.c	Sat Mar 17 17:06:11 2001
--- intl/bindtextdom.c	Sat Mar 17 17:19:19 2001
***************
*** 64,69 ****
--- 64,74 ----
  # define _nl_domain_bindings _nl_domain_bindings__
  #endif
  
+ /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
+ #ifndef offsetof
+ # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+ #endif
+ 
  /* @@ end of prolog @@ */
  
  /* Contains the default location of the message catalogs.  */
***************
*** 233,239 ****
        /* We have to create a new binding.  */
        size_t len = strlen (domainname) + 1;
        struct binding *new_binding =
! 	(struct binding *) malloc (sizeof (*new_binding) + len);
  
        if (__builtin_expect (new_binding == NULL, 0))
  	goto failed;
--- 238,244 ----
        /* We have to create a new binding.  */
        size_t len = strlen (domainname) + 1;
        struct binding *new_binding =
! 	(struct binding *) malloc (offsetof (struct binding, domainname) + len);
  
        if (__builtin_expect (new_binding == NULL, 0))
  	goto failed;
diff -r -c3 intl/dcigettext.c intl/dcigettext.c
*** intl/dcigettext.c	Sat Mar 17 17:06:11 2001
--- intl/dcigettext.c	Sat Mar 17 17:20:01 2001
***************
*** 128,133 ****
--- 128,138 ----
  # define _nl_domain_bindings _nl_domain_bindings__
  #endif
  
+ /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
+ #ifndef offsetof
+ # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+ #endif
+ 
  /* @@ end of prolog @@ */
  
  #ifdef _LIBC
***************
*** 196,209 ****
  # define HAVE_LOCALE_NULL
  #endif
  
- /* We want to allocate a string at the end of the struct.  gcc makes
-    this easy.  */
- #ifdef __GNUC__
- # define ZERO 0
- #else
- # define ZERO 1
- #endif
- 
  /* This is the type used for the search tree where known translations
     are stored.  */
  struct known_translation_t
--- 201,206 ----
***************
*** 335,341 ****
  typedef struct transmem_list
  {
    struct transmem_list *next;
!   char data[0];
  } transmem_block_t;
  static struct transmem_list *transmem_list;
  #else
--- 332,338 ----
  typedef struct transmem_list
  {
    struct transmem_list *next;
!   char data[ZERO];
  } transmem_block_t;
  static struct transmem_list *transmem_list;
  #else
***************
*** 422,429 ****
  
    /* Try to find the translation among those which we found at
       some time.  */
!   search =
!     (struct known_translation_t *) alloca (sizeof (*search) + msgid_len);
    memcpy (search->msgid, msgid1, msgid_len);
    search->domainname = (char *) domainname;
    search->category = category;
--- 419,426 ----
  
    /* Try to find the translation among those which we found at
       some time.  */
!   search = (struct known_translation_t *)
! 	   alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
    memcpy (search->msgid, msgid1, msgid_len);
    search->domainname = (char *) domainname;
    search->category = category;
***************
*** 603,610 ****
  		  struct known_translation_t *newp;
  
  		  newp = (struct known_translation_t *)
! 		    malloc (sizeof (*newp) + msgid_len
! 			    + domainname_len + 1 - ZERO);
  		  if (newp != NULL)
  		    {
  		      newp->domainname =
--- 630,637 ----
  		  struct known_translation_t *newp;
  
  		  newp = (struct known_translation_t *)
! 		    malloc (offsetof (struct known_translation_t, msgid)
! 			    + msgid_len + domainname_len + 1);
  		  if (newp != NULL)
  		    {
  		      newp->domainname =


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]