diff options
author | 2012-09-25 22:12:36 -0400 | |
---|---|---|
committer | 2012-09-25 22:12:36 -0400 | |
commit | 467d1f345d635239072dca83bd44cb6e05cbb3de (patch) | |
tree | 22b7262bc6f31a46427e4835761aa63c6459d0f1 /src/textadept.c | |
parent | a8b0321908a0d8cbf15f1ae1ef45892463b88350 (diff) | |
download | textadept-467d1f345d635239072dca83bd44cb6e05cbb3de.tar.gz textadept-467d1f345d635239072dca83bd44cb6e05cbb3de.zip |
Bugfix for `string.iconv()` from Gilles Grégoire.
Sometimes the converted text will not fit into its allocated buffer.
Diffstat (limited to 'src/textadept.c')
-rw-r--r-- | src/textadept.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/src/textadept.c b/src/textadept.c index 0a04894b..9be6c5e1 100644 --- a/src/textadept.c +++ b/src/textadept.c @@ -1,5 +1,6 @@ // Copyright 2007-2012 Mitchell mitchell.att.foicica.com. See LICENSE. +#include <errno.h> #include <locale.h> #include <iconv.h> #include <stdarg.h> @@ -1421,20 +1422,27 @@ static int ltimeout(lua_State *L) { /** `string.iconv()` Lua function. */ static int lstring_iconv(lua_State *L) { - size_t text_len = 0; - char *text = (char *)luaL_checklstring(L, 1, &text_len); + size_t inbytesleft = 0; + char *inbuf = (char *)luaL_checklstring(L, 1, &inbytesleft); const char *to = luaL_checkstring(L, 2), *from = luaL_checkstring(L, 3); - int converted = FALSE; iconv_t cd = iconv_open(to, from); if (cd != (iconv_t)-1) { - char *out = malloc(text_len + 1), *outp = out; - size_t inbytesleft = text_len, outbytesleft = text_len; - if (iconv(cd, &text, &inbytesleft, &outp, &outbytesleft) != -1) - lua_pushlstring(L, out, outp - out), converted = TRUE; - free(out); - iconv_close(cd); - } - if (!converted) luaL_error(L, "conversion failed"); + char *outbuf = malloc(inbytesleft + 1), *outbufp = outbuf; + size_t outbytesleft = inbytesleft, bufsize = inbytesleft; + int n = 1; // concat this many converted strings + while (iconv(cd, &inbuf, &inbytesleft, &outbufp, &outbytesleft) == -1) + if (errno == E2BIG) { + // Buffer was too small to store converted string. Push the partially + // converted string for later concatenation. + lua_pushlstring(L, outbuf, outbufp - outbuf), n++; + outbufp = outbuf, outbytesleft = bufsize; + } else { + free(outbuf), iconv_close(cd); + luaL_error(L, "conversion failed"); + } + lua_pushlstring(L, outbuf, outbufp - outbuf), lua_concat(L, n); + free(outbuf), iconv_close(cd); + } else luaL_error(L, "invalid encoding(s)"); return 1; } |