summaryrefslogtreecommitdiff
path: root/src/lua/lundump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua/lundump.c')
-rw-r--r--src/lua/lundump.c287
1 files changed, 287 insertions, 0 deletions
diff --git a/src/lua/lundump.c b/src/lua/lundump.c
new file mode 100644
index 0000000..b08e22c
--- /dev/null
+++ b/src/lua/lundump.c
@@ -0,0 +1,287 @@
+/*
+** $Id: lundump.c,v 2.44.1.1 2017/04/19 17:20:42 roberto Exp $
+** load precompiled Lua chunks
+** See Copyright Notice in lua.h
+*/
+
+#define lundump_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
+
+#include "string.h"
+
+#include "lua.h"
+
+#include "ldebug.h"
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lstring.h"
+#include "lundump.h"
+#include "lzio.h"
+
+
+#if !defined(luai_verifycode)
+#define luai_verifycode(L,b,f) /* empty */
+#endif
+
+
+typedef struct {
+ lua_State *L;
+ ZIO *Z;
+ const char *name;
+} LoadState;
+
+
+static l_noret error(LoadState *S, const char *why) {
+ luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
+ luaD_throw(S->L, LUA_ERRSYNTAX);
+}
+
+
+/*
+** 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]))
+
+static void LoadBlock (LoadState *S, void *b, size_t size) {
+ if (luaZ_read(S->Z, b, size) != 0)
+ error(S, "truncated");
+}
+
+
+#define LoadVar(S,x) LoadVector(S,&x,1)
+
+
+static lu_byte LoadByte (LoadState *S) {
+ lu_byte x;
+ LoadVar(S, x);
+ return x;
+}
+
+
+static int LoadInt (LoadState *S) {
+ int x;
+ LoadVar(S, x);
+ return x;
+}
+
+
+static lua_Number LoadNumber (LoadState *S) {
+ lua_Number x;
+ LoadVar(S, x);
+ return x;
+}
+
+
+static lua_Integer LoadInteger (LoadState *S) {
+ lua_Integer x;
+ LoadVar(S, x);
+ return x;
+}
+
+
+static TString *LoadString (LoadState *S, Proto *p) {
+ lua_State *L = S->L;
+ size_t size = LoadByte(S);
+ TString *ts;
+ if (size == 0xFF)
+ LoadVar(S, size);
+ if (size == 0)
+ return NULL;
+ else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */
+ char buff[LUAI_MAXSHORTLEN];
+ LoadVector(S, buff, size);
+ ts = luaS_newlstr(L, buff, size);
+ }
+ else { /* long string */
+ ts = luaS_createlngstrobj(L, size);
+ 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;
+}
+
+
+static void LoadCode (LoadState *S, Proto *f) {
+ int n = LoadInt(S);
+ f->code = luaM_newvector(S->L, n, Instruction);
+ f->sizecode = n;
+ LoadVector(S, f->code, n);
+}
+
+
+static void LoadFunction(LoadState *S, Proto *f, TString *psource);
+
+
+static void LoadConstants (LoadState *S, Proto *f) {
+ int i;
+ int n = LoadInt(S);
+ f->k = luaM_newvector(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);
+ 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, f));
+ break;
+ default:
+ lua_assert(0);
+ }
+ }
+}
+
+
+static void LoadProtos (LoadState *S, Proto *f) {
+ int i;
+ int n = LoadInt(S);
+ f->p = luaM_newvector(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);
+ luaC_objbarrier(S->L, f, f->p[i]);
+ LoadFunction(S, f->p[i], f->source);
+ }
+}
+
+
+static void LoadUpvalues (LoadState *S, Proto *f) {
+ int i, n;
+ n = LoadInt(S);
+ f->upvalues = luaM_newvector(S->L, n, Upvaldesc);
+ f->sizeupvalues = n;
+ for (i = 0; i < n; i++)
+ f->upvalues[i].name = NULL;
+ for (i = 0; i < n; i++) {
+ f->upvalues[i].instack = LoadByte(S);
+ f->upvalues[i].idx = LoadByte(S);
+ }
+}
+
+
+static void LoadDebug (LoadState *S, Proto *f) {
+ int i, n;
+ n = LoadInt(S);
+ f->lineinfo = luaM_newvector(S->L, n, int);
+ f->sizelineinfo = n;
+ LoadVector(S, f->lineinfo, n);
+ n = LoadInt(S);
+ f->locvars = luaM_newvector(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);
+ f->locvars[i].startpc = LoadInt(S);
+ f->locvars[i].endpc = LoadInt(S);
+ }
+ n = LoadInt(S);
+ for (i = 0; i < n; i++)
+ f->upvalues[i].name = LoadString(S, f);
+}
+
+
+static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
+ f->source = LoadString(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);
+}
+
+
+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);
+ 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));
+}
+
+
+#define checksize(S,t) fchecksize(S,sizeof(t),#t)
+
+static void checkHeader (LoadState *S) {
+ checkliteral(S, 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);
+ 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");
+}
+
+
+/*
+** load precompiled chunk
+*/
+LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
+ LoadState S;
+ LClosure *cl;
+ if (*name == '@' || *name == '=')
+ S.name = name + 1;
+ else if (*name == LUA_SIGNATURE[0])
+ S.name = "binary string";
+ else
+ S.name = name;
+ S.L = L;
+ S.Z = Z;
+ checkHeader(&S);
+ cl = luaF_newLclosure(L, LoadByte(&S));
+ setclLvalue(L, L->top, cl);
+ luaD_inctop(L);
+ cl->p = luaF_newproto(L);
+ luaC_objbarrier(L, cl, cl->p);
+ LoadFunction(&S, cl->p, NULL);
+ lua_assert(cl->nupvalues == cl->p->sizeupvalues);
+ luai_verifycode(L, buff, cl->p);
+ return cl;
+}
+