diff options
Diffstat (limited to 'iconv/iconv_open.c')
-rw-r--r-- | iconv/iconv_open.c | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/iconv/iconv_open.c b/iconv/iconv_open.c index fc94fa5fe0..e4fed93ecb 100644 --- a/iconv/iconv_open.c +++ b/iconv/iconv_open.c @@ -18,8 +18,10 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <alloca.h> #include <errno.h> #include <iconv.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> @@ -30,28 +32,49 @@ iconv_t iconv_open (const char *tocode, const char *fromcode) { - char *tocode_conv; - char *fromcode_conv; - size_t tocode_len; - size_t fromcode_len; - __gconv_t cd; - int res; - /* Normalize the name. We remove all characters beside alpha-numeric, '_', '-', '/', '.', and ':'. */ - tocode_len = strlen (tocode); - tocode_conv = (char *) alloca (tocode_len + 3); + size_t tocode_len = strlen (tocode) + 3; + char *tocode_conv; + bool tocode_usealloca = __libc_use_alloca (tocode_len); + if (tocode_usealloca) + tocode_conv = (char *) alloca (tocode_len); + else + { + tocode_conv = (char *) malloc (tocode_len); + if (tocode_conv == NULL) + return (iconv_t) -1; + } strip (tocode_conv, tocode); tocode = (tocode_conv[2] == '\0' && tocode[0] != '\0' ? upstr (tocode_conv, tocode) : tocode_conv); - fromcode_len = strlen (fromcode); - fromcode_conv = (char *) alloca (fromcode_len + 3); + size_t fromcode_len = strlen (fromcode) + 3; + char *fromcode_conv; + bool fromcode_usealloca = __libc_use_alloca (fromcode_len); + if (fromcode_usealloca) + fromcode_conv = (char *) alloca (fromcode_len); + else + { + fromcode_conv = (char *) malloc (fromcode_len); + if (fromcode_conv == NULL) + { + if (! tocode_usealloca) + free (tocode_conv); + return (iconv_t) -1; + } + } strip (fromcode_conv, fromcode); fromcode = (fromcode_conv[2] == '\0' && fromcode[0] != '\0' ? upstr (fromcode_conv, fromcode) : fromcode_conv); - res = __gconv_open (tocode, fromcode, &cd, 0); + __gconv_t cd; + int res = __gconv_open (tocode, fromcode, &cd, 0); + + if (! fromcode_usealloca) + free (fromcode_conv); + if (! tocode_usealloca) + free (tocode_conv); if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK) { @@ -59,7 +82,7 @@ iconv_open (const char *tocode, const char *fromcode) if (res == __GCONV_NOCONV || res == __GCONV_NODB) __set_errno (EINVAL); - return (iconv_t) -1; + cd = (iconv_t) -1; } return (iconv_t) cd; |