1*8e3e3a7aSWarner Losh /* 2*8e3e3a7aSWarner Losh ** $Id: lundump.c,v 2.44 2015/11/02 16:09:30 roberto Exp $ 3*8e3e3a7aSWarner Losh ** load precompiled Lua chunks 4*8e3e3a7aSWarner Losh ** See Copyright Notice in lua.h 5*8e3e3a7aSWarner Losh */ 6*8e3e3a7aSWarner Losh 7*8e3e3a7aSWarner Losh #define lundump_c 8*8e3e3a7aSWarner Losh #define LUA_CORE 9*8e3e3a7aSWarner Losh 10*8e3e3a7aSWarner Losh #include "lprefix.h" 11*8e3e3a7aSWarner Losh 12*8e3e3a7aSWarner Losh 13*8e3e3a7aSWarner Losh #include <string.h> 14*8e3e3a7aSWarner Losh 15*8e3e3a7aSWarner Losh #include "lua.h" 16*8e3e3a7aSWarner Losh 17*8e3e3a7aSWarner Losh #include "ldebug.h" 18*8e3e3a7aSWarner Losh #include "ldo.h" 19*8e3e3a7aSWarner Losh #include "lfunc.h" 20*8e3e3a7aSWarner Losh #include "lmem.h" 21*8e3e3a7aSWarner Losh #include "lobject.h" 22*8e3e3a7aSWarner Losh #include "lstring.h" 23*8e3e3a7aSWarner Losh #include "lundump.h" 24*8e3e3a7aSWarner Losh #include "lzio.h" 25*8e3e3a7aSWarner Losh 26*8e3e3a7aSWarner Losh 27*8e3e3a7aSWarner Losh #if !defined(luai_verifycode) 28*8e3e3a7aSWarner Losh #define luai_verifycode(L,b,f) /* empty */ 29*8e3e3a7aSWarner Losh #endif 30*8e3e3a7aSWarner Losh 31*8e3e3a7aSWarner Losh 32*8e3e3a7aSWarner Losh typedef struct { 33*8e3e3a7aSWarner Losh lua_State *L; 34*8e3e3a7aSWarner Losh ZIO *Z; 35*8e3e3a7aSWarner Losh const char *name; 36*8e3e3a7aSWarner Losh } LoadState; 37*8e3e3a7aSWarner Losh 38*8e3e3a7aSWarner Losh 39*8e3e3a7aSWarner Losh static l_noret error(LoadState *S, const char *why) { 40*8e3e3a7aSWarner Losh luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); 41*8e3e3a7aSWarner Losh luaD_throw(S->L, LUA_ERRSYNTAX); 42*8e3e3a7aSWarner Losh } 43*8e3e3a7aSWarner Losh 44*8e3e3a7aSWarner Losh 45*8e3e3a7aSWarner Losh /* 46*8e3e3a7aSWarner Losh ** All high-level loads go through LoadVector; you can change it to 47*8e3e3a7aSWarner Losh ** adapt to the endianness of the input 48*8e3e3a7aSWarner Losh */ 49*8e3e3a7aSWarner Losh #define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0])) 50*8e3e3a7aSWarner Losh 51*8e3e3a7aSWarner Losh static void LoadBlock (LoadState *S, void *b, size_t size) { 52*8e3e3a7aSWarner Losh if (luaZ_read(S->Z, b, size) != 0) 53*8e3e3a7aSWarner Losh error(S, "truncated"); 54*8e3e3a7aSWarner Losh } 55*8e3e3a7aSWarner Losh 56*8e3e3a7aSWarner Losh 57*8e3e3a7aSWarner Losh #define LoadVar(S,x) LoadVector(S,&x,1) 58*8e3e3a7aSWarner Losh 59*8e3e3a7aSWarner Losh 60*8e3e3a7aSWarner Losh static lu_byte LoadByte (LoadState *S) { 61*8e3e3a7aSWarner Losh lu_byte x; 62*8e3e3a7aSWarner Losh LoadVar(S, x); 63*8e3e3a7aSWarner Losh return x; 64*8e3e3a7aSWarner Losh } 65*8e3e3a7aSWarner Losh 66*8e3e3a7aSWarner Losh 67*8e3e3a7aSWarner Losh static int LoadInt (LoadState *S) { 68*8e3e3a7aSWarner Losh int x; 69*8e3e3a7aSWarner Losh LoadVar(S, x); 70*8e3e3a7aSWarner Losh return x; 71*8e3e3a7aSWarner Losh } 72*8e3e3a7aSWarner Losh 73*8e3e3a7aSWarner Losh 74*8e3e3a7aSWarner Losh static lua_Number LoadNumber (LoadState *S) { 75*8e3e3a7aSWarner Losh lua_Number x; 76*8e3e3a7aSWarner Losh LoadVar(S, x); 77*8e3e3a7aSWarner Losh return x; 78*8e3e3a7aSWarner Losh } 79*8e3e3a7aSWarner Losh 80*8e3e3a7aSWarner Losh 81*8e3e3a7aSWarner Losh static lua_Integer LoadInteger (LoadState *S) { 82*8e3e3a7aSWarner Losh lua_Integer x; 83*8e3e3a7aSWarner Losh LoadVar(S, x); 84*8e3e3a7aSWarner Losh return x; 85*8e3e3a7aSWarner Losh } 86*8e3e3a7aSWarner Losh 87*8e3e3a7aSWarner Losh 88*8e3e3a7aSWarner Losh static TString *LoadString (LoadState *S) { 89*8e3e3a7aSWarner Losh size_t size = LoadByte(S); 90*8e3e3a7aSWarner Losh if (size == 0xFF) 91*8e3e3a7aSWarner Losh LoadVar(S, size); 92*8e3e3a7aSWarner Losh if (size == 0) 93*8e3e3a7aSWarner Losh return NULL; 94*8e3e3a7aSWarner Losh else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ 95*8e3e3a7aSWarner Losh char buff[LUAI_MAXSHORTLEN]; 96*8e3e3a7aSWarner Losh LoadVector(S, buff, size); 97*8e3e3a7aSWarner Losh return luaS_newlstr(S->L, buff, size); 98*8e3e3a7aSWarner Losh } 99*8e3e3a7aSWarner Losh else { /* long string */ 100*8e3e3a7aSWarner Losh TString *ts = luaS_createlngstrobj(S->L, size); 101*8e3e3a7aSWarner Losh LoadVector(S, getstr(ts), size); /* load directly in final place */ 102*8e3e3a7aSWarner Losh return ts; 103*8e3e3a7aSWarner Losh } 104*8e3e3a7aSWarner Losh } 105*8e3e3a7aSWarner Losh 106*8e3e3a7aSWarner Losh 107*8e3e3a7aSWarner Losh static void LoadCode (LoadState *S, Proto *f) { 108*8e3e3a7aSWarner Losh int n = LoadInt(S); 109*8e3e3a7aSWarner Losh f->code = luaM_newvector(S->L, n, Instruction); 110*8e3e3a7aSWarner Losh f->sizecode = n; 111*8e3e3a7aSWarner Losh LoadVector(S, f->code, n); 112*8e3e3a7aSWarner Losh } 113*8e3e3a7aSWarner Losh 114*8e3e3a7aSWarner Losh 115*8e3e3a7aSWarner Losh static void LoadFunction(LoadState *S, Proto *f, TString *psource); 116*8e3e3a7aSWarner Losh 117*8e3e3a7aSWarner Losh 118*8e3e3a7aSWarner Losh static void LoadConstants (LoadState *S, Proto *f) { 119*8e3e3a7aSWarner Losh int i; 120*8e3e3a7aSWarner Losh int n = LoadInt(S); 121*8e3e3a7aSWarner Losh f->k = luaM_newvector(S->L, n, TValue); 122*8e3e3a7aSWarner Losh f->sizek = n; 123*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) 124*8e3e3a7aSWarner Losh setnilvalue(&f->k[i]); 125*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) { 126*8e3e3a7aSWarner Losh TValue *o = &f->k[i]; 127*8e3e3a7aSWarner Losh int t = LoadByte(S); 128*8e3e3a7aSWarner Losh switch (t) { 129*8e3e3a7aSWarner Losh case LUA_TNIL: 130*8e3e3a7aSWarner Losh setnilvalue(o); 131*8e3e3a7aSWarner Losh break; 132*8e3e3a7aSWarner Losh case LUA_TBOOLEAN: 133*8e3e3a7aSWarner Losh setbvalue(o, LoadByte(S)); 134*8e3e3a7aSWarner Losh break; 135*8e3e3a7aSWarner Losh case LUA_TNUMFLT: 136*8e3e3a7aSWarner Losh setfltvalue(o, LoadNumber(S)); 137*8e3e3a7aSWarner Losh break; 138*8e3e3a7aSWarner Losh case LUA_TNUMINT: 139*8e3e3a7aSWarner Losh setivalue(o, LoadInteger(S)); 140*8e3e3a7aSWarner Losh break; 141*8e3e3a7aSWarner Losh case LUA_TSHRSTR: 142*8e3e3a7aSWarner Losh case LUA_TLNGSTR: 143*8e3e3a7aSWarner Losh setsvalue2n(S->L, o, LoadString(S)); 144*8e3e3a7aSWarner Losh break; 145*8e3e3a7aSWarner Losh default: 146*8e3e3a7aSWarner Losh lua_assert(0); 147*8e3e3a7aSWarner Losh } 148*8e3e3a7aSWarner Losh } 149*8e3e3a7aSWarner Losh } 150*8e3e3a7aSWarner Losh 151*8e3e3a7aSWarner Losh 152*8e3e3a7aSWarner Losh static void LoadProtos (LoadState *S, Proto *f) { 153*8e3e3a7aSWarner Losh int i; 154*8e3e3a7aSWarner Losh int n = LoadInt(S); 155*8e3e3a7aSWarner Losh f->p = luaM_newvector(S->L, n, Proto *); 156*8e3e3a7aSWarner Losh f->sizep = n; 157*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) 158*8e3e3a7aSWarner Losh f->p[i] = NULL; 159*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) { 160*8e3e3a7aSWarner Losh f->p[i] = luaF_newproto(S->L); 161*8e3e3a7aSWarner Losh LoadFunction(S, f->p[i], f->source); 162*8e3e3a7aSWarner Losh } 163*8e3e3a7aSWarner Losh } 164*8e3e3a7aSWarner Losh 165*8e3e3a7aSWarner Losh 166*8e3e3a7aSWarner Losh static void LoadUpvalues (LoadState *S, Proto *f) { 167*8e3e3a7aSWarner Losh int i, n; 168*8e3e3a7aSWarner Losh n = LoadInt(S); 169*8e3e3a7aSWarner Losh f->upvalues = luaM_newvector(S->L, n, Upvaldesc); 170*8e3e3a7aSWarner Losh f->sizeupvalues = n; 171*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) 172*8e3e3a7aSWarner Losh f->upvalues[i].name = NULL; 173*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) { 174*8e3e3a7aSWarner Losh f->upvalues[i].instack = LoadByte(S); 175*8e3e3a7aSWarner Losh f->upvalues[i].idx = LoadByte(S); 176*8e3e3a7aSWarner Losh } 177*8e3e3a7aSWarner Losh } 178*8e3e3a7aSWarner Losh 179*8e3e3a7aSWarner Losh 180*8e3e3a7aSWarner Losh static void LoadDebug (LoadState *S, Proto *f) { 181*8e3e3a7aSWarner Losh int i, n; 182*8e3e3a7aSWarner Losh n = LoadInt(S); 183*8e3e3a7aSWarner Losh f->lineinfo = luaM_newvector(S->L, n, int); 184*8e3e3a7aSWarner Losh f->sizelineinfo = n; 185*8e3e3a7aSWarner Losh LoadVector(S, f->lineinfo, n); 186*8e3e3a7aSWarner Losh n = LoadInt(S); 187*8e3e3a7aSWarner Losh f->locvars = luaM_newvector(S->L, n, LocVar); 188*8e3e3a7aSWarner Losh f->sizelocvars = n; 189*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) 190*8e3e3a7aSWarner Losh f->locvars[i].varname = NULL; 191*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) { 192*8e3e3a7aSWarner Losh f->locvars[i].varname = LoadString(S); 193*8e3e3a7aSWarner Losh f->locvars[i].startpc = LoadInt(S); 194*8e3e3a7aSWarner Losh f->locvars[i].endpc = LoadInt(S); 195*8e3e3a7aSWarner Losh } 196*8e3e3a7aSWarner Losh n = LoadInt(S); 197*8e3e3a7aSWarner Losh for (i = 0; i < n; i++) 198*8e3e3a7aSWarner Losh f->upvalues[i].name = LoadString(S); 199*8e3e3a7aSWarner Losh } 200*8e3e3a7aSWarner Losh 201*8e3e3a7aSWarner Losh 202*8e3e3a7aSWarner Losh static void LoadFunction (LoadState *S, Proto *f, TString *psource) { 203*8e3e3a7aSWarner Losh f->source = LoadString(S); 204*8e3e3a7aSWarner Losh if (f->source == NULL) /* no source in dump? */ 205*8e3e3a7aSWarner Losh f->source = psource; /* reuse parent's source */ 206*8e3e3a7aSWarner Losh f->linedefined = LoadInt(S); 207*8e3e3a7aSWarner Losh f->lastlinedefined = LoadInt(S); 208*8e3e3a7aSWarner Losh f->numparams = LoadByte(S); 209*8e3e3a7aSWarner Losh f->is_vararg = LoadByte(S); 210*8e3e3a7aSWarner Losh f->maxstacksize = LoadByte(S); 211*8e3e3a7aSWarner Losh LoadCode(S, f); 212*8e3e3a7aSWarner Losh LoadConstants(S, f); 213*8e3e3a7aSWarner Losh LoadUpvalues(S, f); 214*8e3e3a7aSWarner Losh LoadProtos(S, f); 215*8e3e3a7aSWarner Losh LoadDebug(S, f); 216*8e3e3a7aSWarner Losh } 217*8e3e3a7aSWarner Losh 218*8e3e3a7aSWarner Losh 219*8e3e3a7aSWarner Losh static void checkliteral (LoadState *S, const char *s, const char *msg) { 220*8e3e3a7aSWarner Losh char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ 221*8e3e3a7aSWarner Losh size_t len = strlen(s); 222*8e3e3a7aSWarner Losh LoadVector(S, buff, len); 223*8e3e3a7aSWarner Losh if (memcmp(s, buff, len) != 0) 224*8e3e3a7aSWarner Losh error(S, msg); 225*8e3e3a7aSWarner Losh } 226*8e3e3a7aSWarner Losh 227*8e3e3a7aSWarner Losh 228*8e3e3a7aSWarner Losh static void fchecksize (LoadState *S, size_t size, const char *tname) { 229*8e3e3a7aSWarner Losh if (LoadByte(S) != size) 230*8e3e3a7aSWarner Losh error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); 231*8e3e3a7aSWarner Losh } 232*8e3e3a7aSWarner Losh 233*8e3e3a7aSWarner Losh 234*8e3e3a7aSWarner Losh #define checksize(S,t) fchecksize(S,sizeof(t),#t) 235*8e3e3a7aSWarner Losh 236*8e3e3a7aSWarner Losh static void checkHeader (LoadState *S) { 237*8e3e3a7aSWarner Losh checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ 238*8e3e3a7aSWarner Losh if (LoadByte(S) != LUAC_VERSION) 239*8e3e3a7aSWarner Losh error(S, "version mismatch in"); 240*8e3e3a7aSWarner Losh if (LoadByte(S) != LUAC_FORMAT) 241*8e3e3a7aSWarner Losh error(S, "format mismatch in"); 242*8e3e3a7aSWarner Losh checkliteral(S, LUAC_DATA, "corrupted"); 243*8e3e3a7aSWarner Losh checksize(S, int); 244*8e3e3a7aSWarner Losh checksize(S, size_t); 245*8e3e3a7aSWarner Losh checksize(S, Instruction); 246*8e3e3a7aSWarner Losh checksize(S, lua_Integer); 247*8e3e3a7aSWarner Losh checksize(S, lua_Number); 248*8e3e3a7aSWarner Losh if (LoadInteger(S) != LUAC_INT) 249*8e3e3a7aSWarner Losh error(S, "endianness mismatch in"); 250*8e3e3a7aSWarner Losh if (LoadNumber(S) != LUAC_NUM) 251*8e3e3a7aSWarner Losh error(S, "float format mismatch in"); 252*8e3e3a7aSWarner Losh } 253*8e3e3a7aSWarner Losh 254*8e3e3a7aSWarner Losh 255*8e3e3a7aSWarner Losh /* 256*8e3e3a7aSWarner Losh ** load precompiled chunk 257*8e3e3a7aSWarner Losh */ 258*8e3e3a7aSWarner Losh LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { 259*8e3e3a7aSWarner Losh LoadState S; 260*8e3e3a7aSWarner Losh LClosure *cl; 261*8e3e3a7aSWarner Losh if (*name == '@' || *name == '=') 262*8e3e3a7aSWarner Losh S.name = name + 1; 263*8e3e3a7aSWarner Losh else if (*name == LUA_SIGNATURE[0]) 264*8e3e3a7aSWarner Losh S.name = "binary string"; 265*8e3e3a7aSWarner Losh else 266*8e3e3a7aSWarner Losh S.name = name; 267*8e3e3a7aSWarner Losh S.L = L; 268*8e3e3a7aSWarner Losh S.Z = Z; 269*8e3e3a7aSWarner Losh checkHeader(&S); 270*8e3e3a7aSWarner Losh cl = luaF_newLclosure(L, LoadByte(&S)); 271*8e3e3a7aSWarner Losh setclLvalue(L, L->top, cl); 272*8e3e3a7aSWarner Losh luaD_inctop(L); 273*8e3e3a7aSWarner Losh cl->p = luaF_newproto(L); 274*8e3e3a7aSWarner Losh LoadFunction(&S, cl->p, NULL); 275*8e3e3a7aSWarner Losh lua_assert(cl->nupvalues == cl->p->sizeupvalues); 276*8e3e3a7aSWarner Losh luai_verifycode(L, buff, cl->p); 277*8e3e3a7aSWarner Losh return cl; 278*8e3e3a7aSWarner Losh } 279*8e3e3a7aSWarner Losh 280