aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/nlsfuncs.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/nlsfuncs.cc')
-rw-r--r--winsup/cygwin/nlsfuncs.cc95
1 files changed, 41 insertions, 54 deletions
diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc
index b32fecc..f57465a 100644
--- a/winsup/cygwin/nlsfuncs.cc
+++ b/winsup/cygwin/nlsfuncs.cc
@@ -319,8 +319,7 @@ locale_cmp (const void *a, const void *b)
return strcmp (*la, *lb);
}
-/* Helper function to workaround reallocs which move blocks even if they shrink.
- Cygwin's realloc is not doing this, but tcsh's, for instance. All lc_foo
+/* Helper function to adjust pointers inside an lc_foo buffer. All lc_foo
structures consist entirely of pointers so they are practically pointer
arrays. What we do here is just treat the lc_foo pointers as char ** and
rebase all char * pointers within, up to the given size of the structure. */
@@ -334,6 +333,28 @@ rebase_locale_buf (const void *ptrv, const void *ptrvend, const char *newbase,
*ptrs += newbase - oldbase;
}
+/* Helper function to shrink an lc_foo buffer, adjusting pointers */
+static int
+shrink_locale_buf (const void *ptrv, const void *ptrvend,
+ char *oldbase, const char *oldend,
+ char **result)
+{
+ size_t minsize = oldend - oldbase;
+ char *tmp = (char *) malloc (minsize);
+ if (!tmp)
+ {
+ free (oldbase);
+ return -1;
+ }
+
+ memcpy (tmp, oldbase, minsize);
+ rebase_locale_buf (ptrv, ptrvend, tmp, oldbase, oldend);
+ free (oldbase);
+
+ *result = tmp;
+ return 1;
+}
+
static wchar_t *
__getlocaleinfo (wchar_t *loc, LCTYPE type, char **ptr, size_t size)
{
@@ -687,19 +708,20 @@ __set_lc_time_from_win (const char *name,
len += (wcslen (era->era_t_fmt) + 1) * sizeof (wchar_t);
len += (wcslen (era->alt_digits) + 1) * sizeof (wchar_t);
- /* Make sure data fits into the buffer */
+ /* If necessary, grow the buffer to ensure data fits into it */
if (lc_time_ptr + len > lc_time_end)
{
len = lc_time_ptr + len - new_lc_time_buf;
- char *tmp = (char *) realloc (new_lc_time_buf, len);
+ char *tmp = (char *) malloc (len);
if (!tmp)
era = NULL;
else
{
- if (tmp != new_lc_time_buf)
- rebase_locale_buf (_time_locale, _time_locale + 1, tmp,
- new_lc_time_buf, lc_time_ptr);
+ memcpy (tmp, new_lc_time_buf, MAX_TIME_BUFFER_SIZE);
+ rebase_locale_buf (_time_locale, _time_locale + 1, tmp,
+ new_lc_time_buf, lc_time_ptr);
lc_time_ptr = tmp + (lc_time_ptr - new_lc_time_buf);
+ free(new_lc_time_buf);
new_lc_time_buf = tmp;
lc_time_end = new_lc_time_buf + len;
}
@@ -752,17 +774,9 @@ __set_lc_time_from_win (const char *name,
}
}
- char *tmp = (char *) realloc (new_lc_time_buf, lc_time_ptr - new_lc_time_buf);
- if (!tmp)
- {
- free (new_lc_time_buf);
- return -1;
- }
- if (tmp != new_lc_time_buf)
- rebase_locale_buf (_time_locale, _time_locale + 1, tmp,
- new_lc_time_buf, lc_time_ptr);
- *lc_time_buf = tmp;
- return 1;
+ return shrink_locale_buf(_time_locale, _time_locale + 1,
+ new_lc_time_buf, lc_time_ptr,
+ lc_time_buf);
}
/* Called from newlib's setlocale() via __ctype_load_locale() if category
@@ -824,18 +838,9 @@ __set_lc_ctype_from_win (const char *name,
}
}
- char *tmp = (char *) realloc (new_lc_ctype_buf,
- lc_ctype_ptr - new_lc_ctype_buf);
- if (!tmp)
- {
- free (new_lc_ctype_buf);
- return -1;
- }
- if (tmp != new_lc_ctype_buf)
- rebase_locale_buf (_ctype_locale, _ctype_locale + 1, tmp,
- new_lc_ctype_buf, lc_ctype_ptr);
- *lc_ctype_buf = tmp;
- return 1;
+ return shrink_locale_buf(_ctype_locale, _ctype_locale + 1,
+ new_lc_ctype_buf, lc_ctype_ptr,
+ lc_ctype_buf);
}
/* Called from newlib's setlocale() via __numeric_load_locale() if category
@@ -900,18 +905,9 @@ __set_lc_numeric_from_win (const char *name,
_numeric_locale->codeset = lc_numeric_ptr;
lc_numeric_ptr = stpcpy (lc_numeric_ptr, charset) + 1;
- char *tmp = (char *) realloc (new_lc_numeric_buf,
- lc_numeric_ptr - new_lc_numeric_buf);
- if (!tmp)
- {
- free (new_lc_numeric_buf);
- return -1;
- }
- if (tmp != new_lc_numeric_buf)
- rebase_locale_buf (_numeric_locale, _numeric_locale + 1, tmp,
- new_lc_numeric_buf, lc_numeric_ptr);
- *lc_numeric_buf = tmp;
- return 1;
+ return shrink_locale_buf(_numeric_locale, _numeric_locale + 1,
+ new_lc_numeric_buf, lc_numeric_ptr,
+ lc_numeric_buf);
}
/* Called from newlib's setlocale() via __monetary_load_locale() if category
@@ -1039,18 +1035,9 @@ __set_lc_monetary_from_win (const char *name,
_monetary_locale->codeset = lc_monetary_ptr;
lc_monetary_ptr = stpcpy (lc_monetary_ptr, charset) + 1;
- char *tmp = (char *) realloc (new_lc_monetary_buf,
- lc_monetary_ptr - new_lc_monetary_buf);
- if (!tmp)
- {
- free (new_lc_monetary_buf);
- return -1;
- }
- if (tmp != new_lc_monetary_buf)
- rebase_locale_buf (_monetary_locale, _monetary_locale + 1, tmp,
- new_lc_monetary_buf, lc_monetary_ptr);
- *lc_monetary_buf = tmp;
- return 1;
+ return shrink_locale_buf(_monetary_locale, _monetary_locale + 1,
+ new_lc_monetary_buf, lc_monetary_ptr,
+ lc_monetary_buf);
}
extern "C" int