summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lua/src/lundump.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/lua/src/lundump.c')
-rw-r--r--3rdparty/lua/src/lundump.c276
1 files changed, 165 insertions, 111 deletions
diff --git a/3rdparty/lua/src/lundump.c b/3rdparty/lua/src/lundump.c
index 71bb1512142..5aa55c44578 100644
--- a/3rdparty/lua/src/lundump.c
+++ b/3rdparty/lua/src/lundump.c
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.c,v 2.44 2015/11/02 16:09:30 roberto Exp $
+** $Id: lundump.c $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,7 @@
#include "lprefix.h"
+#include <limits.h>
#include <string.h>
#include "lua.h"
@@ -25,7 +26,7 @@
#if !defined(luai_verifycode)
-#define luai_verifycode(L,b,f) /* empty */
+#define luai_verifycode(L,f) /* empty */
#endif
@@ -36,224 +37,276 @@ typedef struct {
} LoadState;
-static l_noret error(LoadState *S, const char *why) {
- luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
+static l_noret error (LoadState *S, const char *why) {
+ luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why);
luaD_throw(S->L, LUA_ERRSYNTAX);
}
/*
-** All high-level loads go through LoadVector; you can change it to
+** All high-level loads go through loadVector; you can change it to
** adapt to the endianness of the input
*/
-#define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0]))
+#define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0]))
-static void LoadBlock (LoadState *S, void *b, size_t size) {
+static void loadBlock (LoadState *S, void *b, size_t size) {
if (luaZ_read(S->Z, b, size) != 0)
- error(S, "truncated");
+ error(S, "truncated chunk");
}
-#define LoadVar(S,x) LoadVector(S,&x,1)
+#define loadVar(S,x) loadVector(S,&x,1)
-static lu_byte LoadByte (LoadState *S) {
- lu_byte x;
- LoadVar(S, x);
- return x;
+static lu_byte loadByte (LoadState *S) {
+ int b = zgetc(S->Z);
+ if (b == EOZ)
+ error(S, "truncated chunk");
+ return cast_byte(b);
}
-static int LoadInt (LoadState *S) {
- int x;
- LoadVar(S, x);
+static size_t loadUnsigned (LoadState *S, size_t limit) {
+ size_t x = 0;
+ int b;
+ limit >>= 7;
+ do {
+ b = loadByte(S);
+ if (x >= limit)
+ error(S, "integer overflow");
+ x = (x << 7) | (b & 0x7f);
+ } while ((b & 0x80) == 0);
return x;
}
-static lua_Number LoadNumber (LoadState *S) {
+static size_t loadSize (LoadState *S) {
+ return loadUnsigned(S, ~(size_t)0);
+}
+
+
+static int loadInt (LoadState *S) {
+ return cast_int(loadUnsigned(S, INT_MAX));
+}
+
+
+static lua_Number loadNumber (LoadState *S) {
lua_Number x;
- LoadVar(S, x);
+ loadVar(S, x);
return x;
}
-static lua_Integer LoadInteger (LoadState *S) {
+static lua_Integer loadInteger (LoadState *S) {
lua_Integer x;
- LoadVar(S, x);
+ loadVar(S, x);
return x;
}
-static TString *LoadString (LoadState *S) {
- size_t size = LoadByte(S);
- if (size == 0xFF)
- LoadVar(S, size);
- if (size == 0)
+/*
+** Load a nullable string into prototype 'p'.
+*/
+static TString *loadStringN (LoadState *S, Proto *p) {
+ lua_State *L = S->L;
+ TString *ts;
+ size_t size = loadSize(S);
+ if (size == 0) /* no string? */
return NULL;
else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */
char buff[LUAI_MAXSHORTLEN];
- LoadVector(S, buff, size);
- return luaS_newlstr(S->L, buff, size);
+ loadVector(S, buff, size); /* load string into buffer */
+ ts = luaS_newlstr(L, buff, size); /* create string */
}
else { /* long string */
- TString *ts = luaS_createlngstrobj(S->L, size);
- LoadVector(S, getstr(ts), size); /* load directly in final place */
- return ts;
+ ts = luaS_createlngstrobj(L, size); /* create string */
+ setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */
+ luaD_inctop(L);
+ loadVector(S, getstr(ts), size); /* load directly in final place */
+ L->top--; /* pop string */
}
+ luaC_objbarrier(L, p, ts);
+ return ts;
+}
+
+
+/*
+** Load a non-nullable string into prototype 'p'.
+*/
+static TString *loadString (LoadState *S, Proto *p) {
+ TString *st = loadStringN(S, p);
+ if (st == NULL)
+ error(S, "bad format for constant string");
+ return st;
}
-static void LoadCode (LoadState *S, Proto *f) {
- int n = LoadInt(S);
- f->code = luaM_newvector(S->L, n, Instruction);
+static void loadCode (LoadState *S, Proto *f) {
+ int n = loadInt(S);
+ f->code = luaM_newvectorchecked(S->L, n, Instruction);
f->sizecode = n;
- LoadVector(S, f->code, n);
+ loadVector(S, f->code, n);
}
-static void LoadFunction(LoadState *S, Proto *f, TString *psource);
+static void loadFunction(LoadState *S, Proto *f, TString *psource);
-static void LoadConstants (LoadState *S, Proto *f) {
+static void loadConstants (LoadState *S, Proto *f) {
int i;
- int n = LoadInt(S);
- f->k = luaM_newvector(S->L, n, TValue);
+ int n = loadInt(S);
+ f->k = luaM_newvectorchecked(S->L, n, TValue);
f->sizek = n;
for (i = 0; i < n; i++)
setnilvalue(&f->k[i]);
for (i = 0; i < n; i++) {
TValue *o = &f->k[i];
- int t = LoadByte(S);
+ int t = loadByte(S);
switch (t) {
- case LUA_TNIL:
- setnilvalue(o);
- break;
- case LUA_TBOOLEAN:
- setbvalue(o, LoadByte(S));
- break;
- case LUA_TNUMFLT:
- setfltvalue(o, LoadNumber(S));
- break;
- case LUA_TNUMINT:
- setivalue(o, LoadInteger(S));
- break;
- case LUA_TSHRSTR:
- case LUA_TLNGSTR:
- setsvalue2n(S->L, o, LoadString(S));
- break;
- default:
- lua_assert(0);
+ case LUA_VNIL:
+ setnilvalue(o);
+ break;
+ case LUA_VFALSE:
+ setbfvalue(o);
+ break;
+ case LUA_VTRUE:
+ setbtvalue(o);
+ break;
+ case LUA_VNUMFLT:
+ setfltvalue(o, loadNumber(S));
+ break;
+ case LUA_VNUMINT:
+ setivalue(o, loadInteger(S));
+ break;
+ case LUA_VSHRSTR:
+ case LUA_VLNGSTR:
+ setsvalue2n(S->L, o, loadString(S, f));
+ break;
+ default: lua_assert(0);
}
}
}
-static void LoadProtos (LoadState *S, Proto *f) {
+static void loadProtos (LoadState *S, Proto *f) {
int i;
- int n = LoadInt(S);
- f->p = luaM_newvector(S->L, n, Proto *);
+ int n = loadInt(S);
+ f->p = luaM_newvectorchecked(S->L, n, Proto *);
f->sizep = n;
for (i = 0; i < n; i++)
f->p[i] = NULL;
for (i = 0; i < n; i++) {
f->p[i] = luaF_newproto(S->L);
- LoadFunction(S, f->p[i], f->source);
+ luaC_objbarrier(S->L, f, f->p[i]);
+ loadFunction(S, f->p[i], f->source);
}
}
-static void LoadUpvalues (LoadState *S, Proto *f) {
+/*
+** Load the upvalues for a function. The names must be filled first,
+** because the filling of the other fields can raise read errors and
+** the creation of the error message can call an emergency collection;
+** in that case all prototypes must be consistent for the GC.
+*/
+static void loadUpvalues (LoadState *S, Proto *f) {
int i, n;
- n = LoadInt(S);
- f->upvalues = luaM_newvector(S->L, n, Upvaldesc);
+ n = loadInt(S);
+ f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc);
f->sizeupvalues = n;
- for (i = 0; i < n; i++)
+ for (i = 0; i < n; i++) /* make array valid for GC */
f->upvalues[i].name = NULL;
- for (i = 0; i < n; i++) {
- f->upvalues[i].instack = LoadByte(S);
- f->upvalues[i].idx = LoadByte(S);
+ for (i = 0; i < n; i++) { /* following calls can raise errors */
+ f->upvalues[i].instack = loadByte(S);
+ f->upvalues[i].idx = loadByte(S);
+ f->upvalues[i].kind = loadByte(S);
}
}
-static void LoadDebug (LoadState *S, Proto *f) {
+static void loadDebug (LoadState *S, Proto *f) {
int i, n;
- n = LoadInt(S);
- f->lineinfo = luaM_newvector(S->L, n, int);
+ n = loadInt(S);
+ f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte);
f->sizelineinfo = n;
- LoadVector(S, f->lineinfo, n);
- n = LoadInt(S);
- f->locvars = luaM_newvector(S->L, n, LocVar);
+ loadVector(S, f->lineinfo, n);
+ n = loadInt(S);
+ f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo);
+ f->sizeabslineinfo = n;
+ for (i = 0; i < n; i++) {
+ f->abslineinfo[i].pc = loadInt(S);
+ f->abslineinfo[i].line = loadInt(S);
+ }
+ n = loadInt(S);
+ f->locvars = luaM_newvectorchecked(S->L, n, LocVar);
f->sizelocvars = n;
for (i = 0; i < n; i++)
f->locvars[i].varname = NULL;
for (i = 0; i < n; i++) {
- f->locvars[i].varname = LoadString(S);
- f->locvars[i].startpc = LoadInt(S);
- f->locvars[i].endpc = LoadInt(S);
+ f->locvars[i].varname = loadStringN(S, f);
+ f->locvars[i].startpc = loadInt(S);
+ f->locvars[i].endpc = loadInt(S);
}
- n = LoadInt(S);
+ n = loadInt(S);
for (i = 0; i < n; i++)
- f->upvalues[i].name = LoadString(S);
+ f->upvalues[i].name = loadStringN(S, f);
}
-static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
- f->source = LoadString(S);
+static void loadFunction (LoadState *S, Proto *f, TString *psource) {
+ f->source = loadStringN(S, f);
if (f->source == NULL) /* no source in dump? */
f->source = psource; /* reuse parent's source */
- f->linedefined = LoadInt(S);
- f->lastlinedefined = LoadInt(S);
- f->numparams = LoadByte(S);
- f->is_vararg = LoadByte(S);
- f->maxstacksize = LoadByte(S);
- LoadCode(S, f);
- LoadConstants(S, f);
- LoadUpvalues(S, f);
- LoadProtos(S, f);
- LoadDebug(S, f);
+ f->linedefined = loadInt(S);
+ f->lastlinedefined = loadInt(S);
+ f->numparams = loadByte(S);
+ f->is_vararg = loadByte(S);
+ f->maxstacksize = loadByte(S);
+ loadCode(S, f);
+ loadConstants(S, f);
+ loadUpvalues(S, f);
+ loadProtos(S, f);
+ loadDebug(S, f);
}
static void checkliteral (LoadState *S, const char *s, const char *msg) {
char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
size_t len = strlen(s);
- LoadVector(S, buff, len);
+ loadVector(S, buff, len);
if (memcmp(s, buff, len) != 0)
error(S, msg);
}
static void fchecksize (LoadState *S, size_t size, const char *tname) {
- if (LoadByte(S) != size)
- error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname));
+ if (loadByte(S) != size)
+ error(S, luaO_pushfstring(S->L, "%s size mismatch", tname));
}
#define checksize(S,t) fchecksize(S,sizeof(t),#t)
static void checkHeader (LoadState *S) {
- checkliteral(S, (const char *)(LUA_SIGNATURE) + 1, "not a"); /* 1st char already checked */
- if (LoadByte(S) != LUAC_VERSION)
- error(S, "version mismatch in");
- if (LoadByte(S) != LUAC_FORMAT)
- error(S, "format mismatch in");
- checkliteral(S, LUAC_DATA, "corrupted");
- checksize(S, int);
- checksize(S, size_t);
+ /* skip 1st char (already read and checked) */
+ checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk");
+ if (loadByte(S) != LUAC_VERSION)
+ error(S, "version mismatch");
+ if (loadByte(S) != LUAC_FORMAT)
+ error(S, "format mismatch");
+ checkliteral(S, LUAC_DATA, "corrupted chunk");
checksize(S, Instruction);
checksize(S, lua_Integer);
checksize(S, lua_Number);
- if (LoadInteger(S) != LUAC_INT)
- error(S, "endianness mismatch in");
- if (LoadNumber(S) != LUAC_NUM)
- error(S, "float format mismatch in");
+ if (loadInteger(S) != LUAC_INT)
+ error(S, "integer format mismatch");
+ if (loadNumber(S) != LUAC_NUM)
+ error(S, "float format mismatch");
}
/*
-** load precompiled chunk
+** Load precompiled chunk.
*/
LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
LoadState S;
@@ -267,13 +320,14 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
S.L = L;
S.Z = Z;
checkHeader(&S);
- cl = luaF_newLclosure(L, LoadByte(&S));
- setclLvalue(L, L->top, cl);
+ cl = luaF_newLclosure(L, loadByte(&S));
+ setclLvalue2s(L, L->top, cl);
luaD_inctop(L);
cl->p = luaF_newproto(L);
- LoadFunction(&S, cl->p, NULL);
+ luaC_objbarrier(L, cl, cl->p);
+ loadFunction(&S, cl->p, NULL);
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
- luai_verifycode(L, buff, cl->p);
+ luai_verifycode(L, cl->p);
return cl;
}