From 9c6a4de07a1a537eddf9bc99fe24b2acf317196c Mon Sep 17 00:00:00 2001 From: Renato Maia Date: Tue, 19 Feb 2019 08:39:02 -0300 Subject: [PATCH 1/2] Adapt standard libraries to support memories by LuaMemory. --- lbaselib.c | 11 +++++----- linit.c | 1 + liolib.c | 3 ++- lstrlib.c | 61 ++++++++++++++++++++++++++++++++++-------------------- ltablib.c | 7 ++++--- lualib.h | 3 +++ lutf8lib.c | 13 ++++++------ makefile | 5 +++-- 8 files changed, 64 insertions(+), 40 deletions(-) diff --git a/lbaselib.c b/lbaselib.c index 98602952c..838a191e0 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -19,6 +19,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "lmemlib.h" static int luaB_print (lua_State *L) { @@ -31,7 +32,7 @@ static int luaB_print (lua_State *L) { lua_pushvalue(L, -1); /* function to be called */ lua_pushvalue(L, i); /* value to print */ lua_call(L, 1, 1); - s = lua_tolstring(L, -1, &l); /* get result */ + s = luamem_tostring(L, -1, &l); /* get result */ if (s == NULL) return luaL_error(L, "'tostring' must return a string to 'print'"); if (i>1) lua_writestring("\t", 1); @@ -324,17 +325,17 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { *size = 0; return NULL; } - else if (!lua_isstring(L, -1)) - luaL_error(L, "reader function must return a string"); + else if (!luamem_isstring(L, -1)) + luaL_error(L, "reader function must return a string or memory"); lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ - return lua_tolstring(L, RESERVEDSLOT, size); + return luamem_tostring(L, RESERVEDSLOT, size); } static int luaB_load (lua_State *L) { int status; size_t l; - const char *s = lua_tolstring(L, 1, &l); + const char *s = luamem_tostring(L, 1, &l); const char *mode = luaL_optstring(L, 3, "bt"); int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ if (s != NULL) { /* loading a string? */ diff --git a/linit.c b/linit.c index 897ae3523..971297a37 100644 --- a/linit.c +++ b/linit.c @@ -50,6 +50,7 @@ static const luaL_Reg loadedlibs[] = { {LUA_MATHLIBNAME, luaopen_math}, {LUA_UTF8LIBNAME, luaopen_utf8}, {LUA_DBLIBNAME, luaopen_debug}, + {LUA_MEMLIBNAME, luaopen_memory}, #if defined(LUA_COMPAT_BITLIB) {LUA_BITLIBNAME, luaopen_bit32}, #endif diff --git a/liolib.c b/liolib.c index 8491edca3..d42867a18 100644 --- a/liolib.c +++ b/liolib.c @@ -21,6 +21,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "lmemlib.h" @@ -627,7 +628,7 @@ static int g_write (lua_State *L, FILE *f, int arg) { } else { size_t l; - const char *s = luaL_checklstring(L, arg, &l); + const char *s = luamem_checkstring(L, arg, &l); status = status && (fwrite(s, sizeof(char), l, f) == l); } } diff --git a/lstrlib.c b/lstrlib.c index 934b7db88..02d74481b 100644 --- a/lstrlib.c +++ b/lstrlib.c @@ -23,6 +23,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "lmemlib.h" /* @@ -69,7 +70,7 @@ static lua_Integer posrelat (lua_Integer pos, size_t len) { static int str_sub (lua_State *L) { size_t l; - const char *s = luaL_checklstring(L, 1, &l); + const char *s = luamem_checkstring(L, 1, &l); lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); if (start < 1) start = 1; @@ -84,7 +85,7 @@ static int str_sub (lua_State *L) { static int str_reverse (lua_State *L) { size_t l, i; luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); + const char *s = luamem_checkstring(L, 1, &l); char *p = luaL_buffinitsize(L, &b, l); for (i = 0; i < l; i++) p[i] = s[l - i - 1]; @@ -97,7 +98,7 @@ static int str_lower (lua_State *L) { size_t l; size_t i; luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); + const char *s = luamem_checkstring(L, 1, &l); char *p = luaL_buffinitsize(L, &b, l); for (i=0; i MAXSIZE / n) /* may overflow? */ return luaL_error(L, "resulting string too large"); @@ -147,7 +148,7 @@ static int str_rep (lua_State *L) { static int str_byte (lua_State *L) { size_t l; - const char *s = luaL_checklstring(L, 1, &l); + const char *s = luamem_checkstring(L, 1, &l); lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l); lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); int n, i; @@ -342,7 +343,7 @@ static const char *matchbalance (MatchState *ms, const char *s, const char *p) { if (p >= ms->p_end - 1) luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); - if (*s != *p) return NULL; + if (s >= ms->src_end || *s != *p) return NULL; else { int b = *p; int e = *(p+1); @@ -455,14 +456,15 @@ static const char *match (MatchState *ms, const char *s, const char *p) { break; } case 'f': { /* frontier? */ - const char *ep; char previous; + const char *ep; char previous, current; p += 2; if (*p != '[') luaL_error(ms->L, "missing '[' after '%%f' in pattern"); ep = classend(ms, p); /* points to what is next */ previous = (s == ms->src_init) ? '\0' : *(s - 1); + current = (s == ms->src_end) ? '\0' : *s; if (!matchbracketclass(uchar(previous), p, ep - 1) && - matchbracketclass(uchar(*s), p, ep - 1)) { + matchbracketclass(uchar(current), p, ep - 1)) { p = ep; goto init; /* return match(ms, s, ep); */ } s = NULL; /* match failed */ @@ -606,9 +608,10 @@ static void reprepstate (MatchState *ms) { static int str_find_aux (lua_State *L, int find) { size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); + const char *s = luamem_checkstring(L, 1, &ls); const char *p = luaL_checklstring(L, 2, &lp); lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); + if (!s && !ls) s = p; /* force a non-null pointer for empty memory */ if (init < 1) init = 1; else if (init > (lua_Integer)ls + 1) { /* start after string's end? */ lua_pushnil(L); /* cannot find anything */ @@ -688,7 +691,7 @@ static int gmatch_aux (lua_State *L) { static int gmatch (lua_State *L) { size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); + const char *s = luamem_checkstring(L, 1, &ls); const char *p = luaL_checklstring(L, 2, &lp); GMatchState *gm; lua_settop(L, 2); /* keep them on closure to avoid being collected */ @@ -704,7 +707,7 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { size_t l, i; lua_State *L = ms->L; - const char *news = lua_tolstring(L, 3, &l); + const char *news = luamem_tostring(L, 3, &l); for (i = 0; i < l; i++) { if (news[i] != L_ESC) luaL_addchar(b, news[i]); @@ -753,15 +756,15 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, lua_pop(L, 1); lua_pushlstring(L, s, e - s); /* keep original text */ } - else if (!lua_isstring(L, -1)) + else if (!luamem_isstring(L, -1)) luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); - luaL_addvalue(b); /* add result to accumulator */ + luamem_addvalue(b); /* add result to accumulator */ } static int str_gsub (lua_State *L) { size_t srcl, lp; - const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ + const char *src = luamem_checkstring(L, 1, &srcl); /* subject */ const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ const char *lastmatch = NULL; /* end of last match */ int tr = lua_type(L, 3); /* replacement type */ @@ -770,9 +773,11 @@ static int str_gsub (lua_State *L) { lua_Integer n = 0; /* replacement count */ MatchState ms; luaL_Buffer b; + if (!src && !srcl) src = p; /* force a non-null pointer for empty memory */ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || - tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, - "string/function/table expected"); + tr == LUA_TFUNCTION || tr == LUA_TTABLE || + luamem_ismemory(L, 3), 3, + "string/function/table/memory expected"); luaL_buffinit(L, &b); if (anchor) { p++; lp--; /* skip anchor character */ @@ -971,6 +976,15 @@ static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { luaL_addvalue(b); break; } + case LUA_TUSERDATA: { + size_t len; + int type; + const char *s = luamem_tomemoryx(L, arg, &len, NULL, &type); + if (type != LUAMEM_TNONE) { + addquoted(b, s, len); + break; + } + } default: { luaL_argerror(L, arg, "value has no literal form"); } @@ -1375,7 +1389,7 @@ static int str_pack (lua_State *L) { } case Kchar: { /* fixed-size string */ size_t len; - const char *s = luaL_checklstring(L, arg, &len); + const char *s = luamem_checkstring(L, arg, &len); luaL_argcheck(L, len <= (size_t)size, arg, "string longer than given size"); luaL_addlstring(&b, s, len); /* add string */ @@ -1385,7 +1399,7 @@ static int str_pack (lua_State *L) { } case Kstring: { /* strings with length count */ size_t len; - const char *s = luaL_checklstring(L, arg, &len); + const char *s = luamem_checkstring(L, arg, &len); luaL_argcheck(L, size >= (int)sizeof(size_t) || len < ((size_t)1 << (size * NB)), arg, "string length does not fit in given size"); @@ -1396,8 +1410,9 @@ static int str_pack (lua_State *L) { } case Kzstr: { /* zero-terminated string */ size_t len; - const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); + const char *s = luamem_checkstring(L, arg, &len); + luaL_argcheck(L, memchr(s, '\0', len) == NULL, + arg, "string contains zeros"); luaL_addlstring(&b, s, len); luaL_addchar(&b, '\0'); /* add zero at the end */ totalsize += len + 1; @@ -1477,7 +1492,7 @@ static int str_unpack (lua_State *L) { Header h; const char *fmt = luaL_checkstring(L, 1); size_t ld; - const char *data = luaL_checklstring(L, 2, &ld); + const char *data = luamem_checkstring(L, 2, &ld); size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1; int n = 0; /* number of results */ luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); diff --git a/ltablib.c b/ltablib.c index 588bf40d2..701daa303 100644 --- a/ltablib.c +++ b/ltablib.c @@ -18,6 +18,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "lmemlib.h" /* @@ -159,10 +160,10 @@ static int tmove (lua_State *L) { static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { lua_geti(L, 1, i); - if (!lua_isstring(L, -1)) + if (!luamem_isstring(L, -1)) luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", luaL_typename(L, -1), i); - luaL_addvalue(b); + luamem_addvalue(b); } @@ -170,7 +171,7 @@ static int tconcat (lua_State *L) { luaL_Buffer b; lua_Integer last = aux_getn(L, 1, TAB_R); size_t lsep; - const char *sep = luaL_optlstring(L, 2, "", &lsep); + const char *sep = luamem_optstring(L, 2, "", &lsep); lua_Integer i = luaL_optinteger(L, 3, 1); last = luaL_optinteger(L, 4, last); luaL_buffinit(L, &b); diff --git a/lualib.h b/lualib.h index c01eb9c8c..fd5bf83f5 100644 --- a/lualib.h +++ b/lualib.h @@ -47,6 +47,9 @@ LUAMOD_API int (luaopen_debug) (lua_State *L); #define LUA_LOADLIBNAME "package" LUAMOD_API int (luaopen_package) (lua_State *L); +#define LUA_MEMLIBNAME "memory" +LUAMOD_API int (luaopen_memory) (lua_State *L); + /* open all previous libraries */ LUALIB_API void (luaL_openlibs) (lua_State *L); diff --git a/lutf8lib.c b/lutf8lib.c index 6db6fd376..d50ddc396 100644 --- a/lutf8lib.c +++ b/lutf8lib.c @@ -19,6 +19,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "lmemlib.h" #define MAXUNICODE 0x10FFFF @@ -71,7 +72,7 @@ static const char *utf8_decode (const char *o, int *val) { static int utflen (lua_State *L) { int n = 0; size_t len; - const char *s = luaL_checklstring(L, 1, &len); + const char *s = luamem_checkstring(L, 1, &len); lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, @@ -99,7 +100,7 @@ static int utflen (lua_State *L) { */ static int codepoint (lua_State *L) { size_t len; - const char *s = luaL_checklstring(L, 1, &len); + const char *s = luamem_checkstring(L, 1, &len); lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); int n; @@ -159,7 +160,7 @@ static int utfchar (lua_State *L) { */ static int byteoffset (lua_State *L) { size_t len; - const char *s = luaL_checklstring(L, 1, &len); + const char *s = luamem_checkstring(L, 1, &len); lua_Integer n = luaL_checkinteger(L, 2); lua_Integer posi = (n >= 0) ? 1 : len + 1; posi = u_posrelat(luaL_optinteger(L, 3, posi), len); @@ -200,13 +201,13 @@ static int byteoffset (lua_State *L) { static int iter_aux (lua_State *L) { size_t len; - const char *s = luaL_checklstring(L, 1, &len); + const char *s = luamem_checkstring(L, 1, &len); lua_Integer n = lua_tointeger(L, 2) - 1; if (n < 0) /* first iteration? */ n = 0; /* start from here */ else if (n < (lua_Integer)len) { n++; /* skip current byte */ - while (iscont(s + n)) n++; /* and its continuations */ + while (n < (lua_Integer)len && iscont(s + n)) n++; /* and its continuations */ } if (n >= (lua_Integer)len) return 0; /* no more codepoints */ @@ -223,7 +224,7 @@ static int iter_aux (lua_State *L) { static int iter_codes (lua_State *L) { - luaL_checkstring(L, 1); + luamem_checkstring(L, 1, NULL); lua_pushcfunction(L, iter_aux); lua_pushvalue(L, 1); lua_pushinteger(L, 0); diff --git a/makefile b/makefile index 8160d4fb1..db2dafa9d 100644 --- a/makefile +++ b/makefile @@ -53,7 +53,7 @@ LOCAL = $(TESTS) $(CWARNS) -g # enable Linux goodies -MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX -DLUA_COMPAT_5_2 +MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX -DLUA_COMPAT_5_2 -I. -I$(LUAMEM) MYLDFLAGS= $(LOCAL) -Wl,-E MYLIBS= -ldl -lreadline @@ -77,7 +77,8 @@ CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ ltm.o lundump.o lvm.o lzio.o ltests.o AUX_O= lauxlib.o LIB_O= lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o lstrlib.o \ - lutf8lib.o lbitlib.o loadlib.o lcorolib.o linit.o + lutf8lib.o lbitlib.o loadlib.o lcorolib.o linit.o \ + $(LUAMEM)/lmemlib.o $(LUAMEM)/lmemmod.o LUA_T= lua LUA_O= lua.o From a3c51d3490736139c371d78d4a46e12048222cc2 Mon Sep 17 00:00:00 2001 From: Renato Maia Date: Wed, 10 Jul 2019 08:28:49 -0300 Subject: [PATCH 2/2] Fix 'unpack(z, v)' to not rely on the '\0' of Lua strings. --- lstrlib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lstrlib.c b/lstrlib.c index 02d74481b..24f89a2a2 100644 --- a/lstrlib.c +++ b/lstrlib.c @@ -1536,7 +1536,10 @@ static int str_unpack (lua_State *L) { break; } case Kzstr: { - size_t len = (int)strlen(data + pos); + size_t len; + const char *z = (const char *)memchr(data + pos, '\0', ld - pos); + luaL_argcheck(L, z, 2, "data string too short"); + len = (size_t)(z - data - pos); lua_pushlstring(L, data + pos, len); pos += len + 1; /* skip string plus final '\0' */ break;