[newlib-cygwin] Fix memory handling in functions called from loadlocale

Corinna Vinschen corinna@sourceware.org
Mon Aug 15 09:25:00 GMT 2016


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=1afa0fe4b35f59b7e15c446f47f1d0c2419c89f5

commit 1afa0fe4b35f59b7e15c446f47f1d0c2419c89f5
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Sat Jul 23 13:30:21 2016 +0200

    Fix memory handling in functions called from loadlocale
    
    Signed-off by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 newlib/libc/locale/lctype.c    | 16 +++++++++++----
 newlib/libc/locale/lmessages.c | 16 +++++++++++----
 newlib/libc/locale/lmonetary.c | 16 +++++++++++----
 newlib/libc/locale/lnumeric.c  | 16 +++++++++++----
 newlib/libc/locale/locale.c    | 15 +++++++++++---
 newlib/libc/locale/timelocal.c | 16 +++++++++++----
 winsup/cygwin/nlsfuncs.cc      | 44 +++++++++++++++++++++++-------------------
 7 files changed, 96 insertions(+), 43 deletions(-)

diff --git a/newlib/libc/locale/lctype.c b/newlib/libc/locale/lctype.c
index 4185a83..6e47b04 100644
--- a/newlib/libc/locale/lctype.c
+++ b/newlib/libc/locale/lctype.c
@@ -74,13 +74,21 @@ __ctype_load_locale (struct __locale_t *locale, const char *name,
 	{
 	  ctp = (struct lc_ctype_T *) calloc (1, sizeof *ctp);
 	  if (!ctp)
-	    return -1;
-	  memcpy (ctp, &ct, sizeof *ctp);
+	    {
+	      free (bufp);
+	      return -1;
+	    }
+	  *ctp = ct;
 	}
+      struct __lc_cats tmp = locale->lc_cat[LC_CTYPE];
       locale->lc_cat[LC_CTYPE].ptr = ret == 0 ? &_C_ctype_locale : ctp;
-      if (locale->lc_cat[LC_CTYPE].buf)
-	free (locale->lc_cat[LC_CTYPE].buf);
       locale->lc_cat[LC_CTYPE].buf = bufp;
+      /* If buf is not NULL, both pointers have been alloc'ed */
+      if (tmp.buf)
+	{
+	  free ((void *) tmp.ptr);
+	  free (tmp.buf);
+	}
       ret = 0;
     }
 #elif !defined (__HAVE_LOCALE_INFO_EXTENDED__)
diff --git a/newlib/libc/locale/lmessages.c b/newlib/libc/locale/lmessages.c
index cea0c94..3780ffb 100644
--- a/newlib/libc/locale/lmessages.c
+++ b/newlib/libc/locale/lmessages.c
@@ -84,13 +84,21 @@ __messages_load_locale (struct __locale_t *locale, const char *name,
 	{
 	  mep = (struct lc_messages_T *) calloc (1, sizeof *mep);
 	  if (!mep)
-	    return -1;
-	  memcpy (mep, &me, sizeof *mep);
+	    {
+	      free (bufp);
+	      return -1;
+	    }
+	  *mep = me;
 	}
+      struct __lc_cats tmp = locale->lc_cat[LC_MESSAGES];
       locale->lc_cat[LC_MESSAGES].ptr = ret == 0 ? &_C_messages_locale : mep;
-      if (locale->lc_cat[LC_MESSAGES].buf)
-	free (locale->lc_cat[LC_MESSAGES].buf);
       locale->lc_cat[LC_MESSAGES].buf = bufp;
+      /* If buf is not NULL, both pointers have been alloc'ed */
+      if (tmp.buf)
+	{
+	  free ((void *) tmp.ptr);
+	  free (tmp.buf);
+	}
       ret = 0;
     }
 #else
diff --git a/newlib/libc/locale/lmonetary.c b/newlib/libc/locale/lmonetary.c
index ab770a0..b7077a0 100644
--- a/newlib/libc/locale/lmonetary.c
+++ b/newlib/libc/locale/lmonetary.c
@@ -112,13 +112,21 @@ __monetary_load_locale (struct __locale_t *locale, const char *name ,
 	{
 	  mop = (struct lc_monetary_T *) calloc (1, sizeof *mop);
 	  if (!mop)
-	    return -1;
-	  memcpy (mop, &mo, sizeof *mop);
+	    {
+	      free (bufp);
+	      return -1;
+	    }
+	  *mop = mo;
 	}
+      struct __lc_cats tmp = locale->lc_cat[LC_MONETARY];
       locale->lc_cat[LC_MONETARY].ptr = ret == 0 ? &_C_monetary_locale : mop;
-      if (locale->lc_cat[LC_MONETARY].buf)
-	free (locale->lc_cat[LC_MONETARY].buf);
       locale->lc_cat[LC_MONETARY].buf = bufp;
+      /* If buf is not NULL, both pointers have been alloc'ed */
+      if (tmp.buf)
+	{
+	  free ((void *) tmp.ptr);
+	  free (tmp.buf);
+	}
       ret = 0;
     }
 #else
diff --git a/newlib/libc/locale/lnumeric.c b/newlib/libc/locale/lnumeric.c
index c488584..c63fd8e 100644
--- a/newlib/libc/locale/lnumeric.c
+++ b/newlib/libc/locale/lnumeric.c
@@ -74,13 +74,21 @@ __numeric_load_locale (struct __locale_t *locale, const char *name ,
 	{
 	  nmp = (struct lc_numeric_T *) calloc (1, sizeof *nmp);
 	  if (!nmp)
-	    return -1;
-	  memcpy (nmp, &nm, sizeof *nmp);
+	    {
+	      free (bufp);
+	      return -1;
+	    }
+	  *nmp = nm;
 	}
+      struct __lc_cats tmp = locale->lc_cat[LC_NUMERIC];
       locale->lc_cat[LC_NUMERIC].ptr = ret == 0 ? &_C_numeric_locale : nmp;
-      if (locale->lc_cat[LC_NUMERIC].buf)
-	free (locale->lc_cat[LC_NUMERIC].buf);
       locale->lc_cat[LC_NUMERIC].buf = bufp;
+      /* If buf is not NULL, both pointers have been alloc'ed */
+      if (tmp.buf)
+	{
+	  free ((void *) tmp.ptr);
+	  free (tmp.buf);
+	}
       ret = 0;
     }
 #else
diff --git a/newlib/libc/locale/locale.c b/newlib/libc/locale/locale.c
index 4f2d6d2..f6e9a97 100644
--- a/newlib/libc/locale/locale.c
+++ b/newlib/libc/locale/locale.c
@@ -1152,7 +1152,10 @@ error:
   for (i = 1; i < _LC_LAST; ++i)
     if (tmp_locale.lc_cat[i].buf
 	&& tmp_locale.lc_cat[i].buf != (const void *) -1)
-      _free_r (p, tmp_locale.lc_cat[i].buf);
+      {
+	_free_r (p, tmp_locale.lc_cat[i].ptr);
+	_free_r (p, tmp_locale.lc_cat[i].buf);
+      }
 #endif
 
   return NULL;
@@ -1167,7 +1170,10 @@ _freelocale_r (struct _reent *p, struct __locale_t *locobj)
 #ifdef __HAVE_LOCALE_INFO__
   for (int i = 1; i < _LC_LAST; ++i)
     if (locobj->lc_cat[i].buf)
-      _free_r (p, locobj->lc_cat[i].buf);
+      {
+	_free_r (p, locobj->lc_cat[i].ptr);
+	_free_r (p, locobj->lc_cat[i].buf);
+      }
 #endif
   _free_r (p, locobj);
 }
@@ -1212,7 +1218,10 @@ error:
 #ifdef __HAVE_LOCALE_INFO__
   while (--i > 0)
     if (tmp_locale.lc_cat[i].buf)
-      _free_r (p, tmp_locale.lc_cat[i].buf);
+      {
+	_free_r (p, tmp_locale.lc_cat[i].ptr);
+	_free_r (p, tmp_locale.lc_cat[i].buf);
+      }
 #endif
 
   return NULL;
diff --git a/newlib/libc/locale/timelocal.c b/newlib/libc/locale/timelocal.c
index d9760f0..1c869e1 100644
--- a/newlib/libc/locale/timelocal.c
+++ b/newlib/libc/locale/timelocal.c
@@ -174,13 +174,21 @@ __time_load_locale (struct __locale_t *locale, const char *name,
 	{
 	  tip = (struct lc_time_T *) calloc (1, sizeof *tip);
 	  if (!tip)
-	    return -1;
-	  memcpy (tip, &ti, sizeof *tip);
+	    {
+	      free (bufp);
+	      return -1;
+	    }
+	  *tip = ti;
 	}
+      struct __lc_cats tmp = locale->lc_cat[LC_TIME];
       locale->lc_cat[LC_TIME].ptr = ret == 0 ? &_C_time_locale : tip;
-      if (locale->lc_cat[LC_TIME].buf)
-	free (locale->lc_cat[LC_TIME].buf);
       locale->lc_cat[LC_TIME].buf = bufp;
+      /* If buf is not NULL, both pointers have been alloc'ed */
+      if (tmp.buf)
+	{
+	  free ((void *) tmp.ptr);
+	  free (tmp.buf);
+	}
       ret = 0;
     }
 #else
diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc
index 4b92626..9b19f2a 100644
--- a/winsup/cygwin/nlsfuncs.cc
+++ b/winsup/cygwin/nlsfuncs.cc
@@ -1066,6 +1066,13 @@ __set_lc_messages_from_win (const char *name,
   return 1;
 }
 
+const struct lc_collate_T _C_collate_locale =
+{
+  0,
+  __ascii_mbtowc,
+  "ASCII"
+};
+
 /* Called from newlib's setlocale() if category is LC_COLLATE.  Stores
    LC_COLLATE locale information.  This is subsequently accessed by the
    below functions strcoll, strxfrm, wcscoll, wcsxfrm. */
@@ -1073,42 +1080,39 @@ extern "C" int
 __collate_load_locale (struct __locale_t *locale, const char *name,
 		       void *f_mbtowc, const char *charset)
 {
-  const struct lc_collate_T *ccop;
   char *bufp = NULL;
+  struct lc_collate_T *cop = NULL;
 
   LCID lcid = __get_lcid_from_locale (name);
   if (lcid == (LCID) -1)
     return -1;
-  if (!lcid)
-    {
-      ccop = &_C_collate_locale;
-      bufp = NULL;
-    }
-  else
+  if (lcid)
     {
-      bufp = (char *) calloc (1, sizeof (struct lc_collate_T));
+      bufp = (char *) malloc (1);	/* dummy */
       if (!bufp)
 	return -1;
-      struct lc_collate_T *cop = (struct lc_collate_T *) bufp;
+      cop = (struct lc_collate_T *) calloc (1, sizeof (struct lc_collate_T));
+      if (!cop)
+	{
+	  free (bufp);
+	  return -1;
+	}
       cop->lcid = lcid;
       cop->mbtowc = (mbtowc_p) f_mbtowc;
       stpcpy (cop->codeset, charset);
-      ccop = (const struct lc_collate_T *) cop;
     }
-  locale->lc_cat[LC_COLLATE].ptr = ccop;
-  if (locale->lc_cat[LC_COLLATE].buf)
-    free (locale->lc_cat[LC_COLLATE].buf);
+  struct __lc_cats tmp = locale->lc_cat[LC_COLLATE];
+  locale->lc_cat[LC_COLLATE].ptr = lcid == 0 ? &_C_collate_locale : cop;
   locale->lc_cat[LC_COLLATE].buf = bufp;
+  /* If buf is not NULL, both pointers have been alloc'ed */
+  if (tmp.buf)
+    {
+      free ((void *) tmp.ptr);
+      free (tmp.buf);
+    }
   return 0;
 }
 
-const struct lc_collate_T _C_collate_locale =
-{
-  0,
-  __ascii_mbtowc,
-  "ASCII"
-};
-
 /* We use the Windows functions for locale-specific string comparison and
    transformation.  The advantage is that we don't need any files with
    collation information. */



More information about the Cygwin-cvs mailing list