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