Merge branch 'fix-double-free'

Conflicts:
	luaiconv.c
This commit is contained in:
Alexandre Erwin Ittner 2010-11-18 16:06:45 -02:00
commit 32c7b20967
3 changed files with 30 additions and 4 deletions

4
README
View File

@ -88,6 +88,10 @@ directory from package.cpath).
iconv.ERROR_INCOMPLETE
An incomplete character was found in the input sequence.
iconv.ERROR_FINALIZED
Trying to use an already-finalized converter. This usually means
that the user was tweaking the garbage collector private methods.
iconv.ERROR_UNKNOWN
There was an unknown error.

View File

@ -53,6 +53,7 @@
#define ERROR_INVALID 2
#define ERROR_INCOMPLETE 3
#define ERROR_UNKNOWN 4
#define ERROR_FINALIZED 5
@ -66,9 +67,7 @@ static void push_iconv_t(lua_State *L, iconv_t cd) {
static iconv_t get_iconv_t(lua_State *L, int i) {
if (luaL_checkudata(L, i, ICONV_TYPENAME) != NULL) {
iconv_t cd = UNBOXPTR(L, i);
if (cd == (iconv_t) NULL)
luaL_error(L, "attempt to use an invalid " ICONV_TYPENAME);
return cd;
return cd; /* May be NULL. This must be checked by the caller. */
}
luaL_argerror(L, i, lua_pushfstring(L, ICONV_TYPENAME " expected, got %s",
luaL_typename(L, i)));
@ -100,6 +99,12 @@ static int Liconv(lua_State *L) {
size_t ret = -1;
int hasone = 0;
if (cd == NULL) {
lua_pushstring(L, "");
lua_pushnumber(L, ERROR_FINALIZED);
return 2;
}
outbuf = (char*) malloc(obsize * sizeof(char));
if (outbuf == NULL) {
lua_pushstring(L, "");
@ -182,8 +187,13 @@ static int Liconvlist(lua_State *L) {
static int Liconv_close(lua_State *L) {
iconv_t cd = get_iconv_t(L, 1);
if (iconv_close(cd) == 0)
if (cd != NULL && iconv_close(cd) == 0) {
/* Mark the pointer as freed, preventing interpreter crashes
if the user forces __gc to be called twice. */
void **ptr = lua_touserdata(L, 1);
*ptr = NULL;
lua_pushboolean(L, 1); /* ok */
}
else
lua_pushnil(L); /* error */
return 1;
@ -207,6 +217,7 @@ int luaopen_iconv(lua_State *L) {
TBL_SET_INT_CONST(L, ERROR_NO_MEMORY);
TBL_SET_INT_CONST(L, ERROR_INVALID);
TBL_SET_INT_CONST(L, ERROR_INCOMPLETE);
TBL_SET_INT_CONST(L, ERROR_FINALIZED);
TBL_SET_INT_CONST(L, ERROR_UNKNOWN);
lua_pushliteral(L, "VERSION");

View File

@ -97,3 +97,14 @@ check_one(termcs, "utf8", utf8)
check_one(termcs, "utf16", utf16)
check_one(termcs, "EBCDIC-CP-ES", ebcdic)
-- The library must never crash the interpreter, even if the user tweaks
-- with the garbage collector methods.
local cd = iconv.new("iso-8859-1", "utf-8")
local _, e = cd:iconv("atenção")
assert(e == nil, "Unexpected conversion error")
local gc = getmetatable(cd).__gc
gc(cd)
local _, e = cd:iconv("atenção")
assert(e == iconv.ERROR_FINALIZED, "Failed to detect double-freed objects")
gc(cd)