diff options
author | Mark H Weaver <mhw@netris.org> | 2019-05-06 21:11:26 -0400 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2019-05-23 17:51:36 +0200 |
commit | bd50407d1f9adc3eedd6687c9a84aa7a503b7ce1 (patch) | |
tree | f192426504933a93f0fca52afebd1e8ea67244fe /libguile/strings.c | |
parent | 2bfa4f73f188e4ad2bde22594d5173e71c1d3d2f (diff) | |
download | guile-bd50407d1f9adc3eedd6687c9a84aa7a503b7ce1.tar.gz |
Strings, i18n: Limit the use of alloca to approximately 8 kilobytes.
* libguile/i18n.c (SCM_MAX_ALLOCA): New macro.
(SCM_STRING_TO_U32_BUF): Accept an additional variable to remember
whether we used malloc to allocate the buffer. Use malloc if the
allocation size is greater than SCM_MAX_ALLOCA.
(SCM_CLEANUP_U32_BUF): New macro.
(compare_u32_strings, compare_u32_strings_ci, str_to_case): Adapt.
* libguile/strings.c (SCM_MAX_ALLOCA): New macro.
(normalize_str, unistring_escapes_to_r6rs_escapes): Use malloc if the
allocation size is greater than SCM_MAX_ALLOCA.
* test-suite/tests/i18n.test, test-suite/tests/strings.test: Add tests.
Diffstat (limited to 'libguile/strings.c')
-rw-r--r-- | libguile/strings.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/libguile/strings.c b/libguile/strings.c index e6ae5cbd5..8f6a47e29 100644 --- a/libguile/strings.c +++ b/libguile/strings.c @@ -50,6 +50,10 @@ #include "strings.h" +#ifndef SCM_MAX_ALLOCA +# define SCM_MAX_ALLOCA 4096 /* Max bytes per string to allocate via alloca */ +#endif + /* {Strings} @@ -1813,6 +1817,7 @@ static void unistring_escapes_to_r6rs_escapes (char *buf, size_t *lenp) { char *before, *after; + int malloc_p; size_t i, j; /* The worst case is if the input string contains all 4-digit hex escapes. "\uXXXX" (six characters) becomes "\xXXXX;" (seven characters) */ @@ -1820,7 +1825,8 @@ unistring_escapes_to_r6rs_escapes (char *buf, size_t *lenp) size_t nzeros, ndigits; before = buf; - after = alloca (max_out_len); + malloc_p = (max_out_len > SCM_MAX_ALLOCA); + after = malloc_p ? malloc (max_out_len) : alloca (max_out_len); i = 0; j = 0; while (i < *lenp) @@ -1878,6 +1884,8 @@ unistring_escapes_to_r6rs_escapes (char *buf, size_t *lenp) } *lenp = j; memcpy (before, after, j); + if (malloc_p) + free (after); } char * @@ -2318,28 +2326,37 @@ normalize_str (SCM string, uninorm_t form) { SCM ret; uint32_t *w_str; + uint32_t *w_norm_str; scm_t_wchar *cbuf; - size_t rlen, len = scm_i_string_length (string); + int malloc_p; + size_t norm_len, len = scm_i_string_length (string); if (scm_i_is_narrow_string (string)) { - size_t i; + size_t i, bytes; const char *buf = scm_i_string_chars (string); - - w_str = alloca (sizeof (scm_t_wchar) * (len + 1)); - + + bytes = (len + 1) * sizeof (scm_t_wchar); + malloc_p = (bytes > SCM_MAX_ALLOCA); + w_str = malloc_p ? malloc (bytes) : alloca (bytes); + for (i = 0; i < len; i ++) w_str[i] = (unsigned char) buf[i]; w_str[len] = 0; } - else - w_str = (uint32_t *) scm_i_string_wide_chars (string); + else + { + malloc_p = 0; + w_str = (uint32_t *) scm_i_string_wide_chars (string); + } - w_str = u32_normalize (form, w_str, len, NULL, &rlen); - - ret = scm_i_make_wide_string (rlen, &cbuf, 0); - u32_cpy ((uint32_t *) cbuf, w_str, rlen); - free (w_str); + w_norm_str = u32_normalize (form, w_str, len, NULL, &norm_len); + + ret = scm_i_make_wide_string (norm_len, &cbuf, 0); + u32_cpy ((uint32_t *) cbuf, w_norm_str, norm_len); + free (w_norm_str); + if (malloc_p) + free (w_str); scm_i_try_narrow_string (ret); |