Print this page
locale stuff should use libc safe lmalloc.  Other fixes from tests.

@@ -156,15 +156,15 @@
 struct locdata *
 __locdata_alloc(const char *name, size_t memsz)
 {
         struct locdata *ldata;
 
-        if ((ldata = calloc(1, sizeof (*ldata))) == NULL) {
+        if ((ldata = lmalloc(sizeof (*ldata))) == NULL) {
                 return (NULL);
         }
-        if ((ldata->l_data[0] = calloc(1, memsz)) == NULL) {
-                free(ldata);
+        if ((ldata->l_data[0] = libc_malloc(memsz)) == NULL) {
+                lfree(ldata, sizeof (*ldata));
                 errno = ENOMEM;
                 return (NULL);
         }
         (void) strlcpy(ldata->l_lname, name, sizeof (ldata->l_lname));
 

@@ -177,14 +177,14 @@
  */
 void
 __locdata_free(struct locdata *ldata)
 {
         for (int i = 0; i < NLOCDATA; i++)
-                free(ldata->l_data[i]);
+                libc_free(ldata->l_data[i]);
         if (ldata->l_map != NULL && ldata->l_map_len)
                 (void) munmap(ldata->l_map, ldata->l_map_len);
-        free(ldata);
+        lfree(ldata, sizeof (*ldata));
 }
 
 /*
  * It turns out that for performance reasons we would really like to
  * cache the most recently referenced locale data to avoid wasteful

@@ -248,21 +248,24 @@
          */
         if (loc == NULL) {
                 lmutex_unlock(&cache_lock);
                 loc = (*loaders[category])(locname);
                 lmutex_lock(&cache_lock);
-                (void) strlcpy(loc->l_lname, locname, sizeof (loc->l_lname));
+                if (loc != NULL)
+                        (void) strlcpy(loc->l_lname, locname,
+                            sizeof (loc->l_lname));
         }
 
         /*
          * Assuming we got one, update the cache, and stick us on the list
          * of loaded locale data.  We insert into the head (more recent
          * use is likely to win.)
          */
         if (loc != NULL) {
                 cache_data[category] = loc;
-                if (loc->l_next == NULL) {
+                if (!loc->l_cached) {
+                        loc->l_cached = 1;
                         loc->l_next = cat_data[category];
                         cat_data[category] = loc;
                 }
         }
 

@@ -372,11 +375,11 @@
 duplocale(locale_t src)
 {
         locale_t        loc;
         int             i;
 
-        loc = calloc(1, sizeof (*loc));
+        loc = lmalloc(sizeof (*loc));
         if (loc == NULL) {
                 return (NULL);
         }
         if (src == NULL) {
                 /* illumos extension: POSIX says LC_GLOBAL_LOCALE here */

@@ -402,12 +405,12 @@
         /*
          * We take extra care never to free a saved locale created by
          * setlocale().  This shouldn't be strictly necessary, but a little
          * extra safety doesn't hurt here.
          */
-        if ((loc != &posix_locale) && (!loc->on_list))
-                free(loc);
+        if ((loc != NULL) && (loc != &posix_locale) && (!loc->on_list))
+                lfree(loc, sizeof (*loc));
 }
 
 locale_t
 newlocale(int catmask, const char *locname, locale_t base)
 {

@@ -424,11 +427,11 @@
          * but we allow it.
          */
         if (base == NULL || base == ___global_locale) {
                 loc = duplocale(___global_locale);
         } else {
-                loc = base;
+                loc = duplocale(base);
         }
         if (loc == NULL) {
                 return (NULL);
         }
 

@@ -453,10 +456,12 @@
         loc->runelocale = loc->locdata[LC_CTYPE]->l_data[1];
         loc->messages = loc->locdata[LC_MESSAGES]->l_data[0];
         loc->monetary = loc->locdata[LC_MONETARY]->l_data[0];
         loc->numeric = loc->locdata[LC_NUMERIC]->l_data[0];
         loc->time = loc->locdata[LC_TIME]->l_data[0];
+        freelocale(base);
+
         return (mklocname(loc));
 }
 
 locale_t
 uselocale(locale_t loc)