summaryrefslogtreecommitdiff
path: root/iconv/iconv_open.c
diff options
context:
space:
mode:
Diffstat (limited to 'iconv/iconv_open.c')
-rw-r--r--iconv/iconv_open.c49
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;