aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormitchell <70453897+667e-11@users.noreply.github.com>2012-09-25 22:12:36 -0400
committermitchell <70453897+667e-11@users.noreply.github.com>2012-09-25 22:12:36 -0400
commit467d1f345d635239072dca83bd44cb6e05cbb3de (patch)
tree22b7262bc6f31a46427e4835761aa63c6459d0f1
parenta8b0321908a0d8cbf15f1ae1ef45892463b88350 (diff)
downloadtextadept-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.
-rw-r--r--THANKS.md1
-rw-r--r--src/textadept.c30
2 files changed, 20 insertions, 11 deletions
diff --git a/THANKS.md b/THANKS.md
index a296789c..e08a62b0 100644
--- a/THANKS.md
+++ b/THANKS.md
@@ -11,6 +11,7 @@ Textadept the amazing editor that it is today.
* Bill Meahan
* Brian Schott
* Callum Wilson
+* Gilles Grégoire
* Jay Gould
* Jeff Stone
* M Rawash
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;
}