1 /* 2 ** $Id: lundump.c,v 2.44.1.1 2017/04/19 17:20:42 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, Proto *p) { 89 lua_State *L = S->L; 90 size_t size = LoadByte(S); 91 TString *ts; 92 if (size == 0xFF) 93 LoadVar(S, size); 94 if (size == 0) 95 return NULL; 96 else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ 97 char buff[LUAI_MAXSHORTLEN]; 98 LoadVector(S, buff, size); 99 ts = luaS_newlstr(L, buff, size); 100 } 101 else { /* long string */ 102 ts = luaS_createlngstrobj(L, size); 103 setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */ 104 luaD_inctop(L); 105 LoadVector(S, getstr(ts), size); /* load directly in final place */ 106 L->top--; /* pop string */ 107 } 108 luaC_objbarrier(L, p, ts); 109 return ts; 110 } 111 112 113 static void LoadCode (LoadState *S, Proto *f) { 114 int n = LoadInt(S); 115 f->code = luaM_newvector(S->L, n, Instruction); 116 f->sizecode = n; 117 LoadVector(S, f->code, n); 118 } 119 120 121 static void LoadFunction(LoadState *S, Proto *f, TString *psource); 122 123 124 static void LoadConstants (LoadState *S, Proto *f) { 125 int i; 126 int n = LoadInt(S); 127 f->k = luaM_newvector(S->L, n, TValue); 128 f->sizek = n; 129 for (i = 0; i < n; i++) 130 setnilvalue(&f->k[i]); 131 for (i = 0; i < n; i++) { 132 TValue *o = &f->k[i]; 133 int t = LoadByte(S); 134 switch (t) { 135 case LUA_TNIL: 136 setnilvalue(o); 137 break; 138 case LUA_TBOOLEAN: 139 setbvalue(o, LoadByte(S)); 140 break; 141 case LUA_TNUMFLT: 142 setfltvalue(o, LoadNumber(S)); 143 break; 144 case LUA_TNUMINT: 145 setivalue(o, LoadInteger(S)); 146 break; 147 case LUA_TSHRSTR: 148 case LUA_TLNGSTR: 149 setsvalue2n(S->L, o, LoadString(S, f)); 150 break; 151 default: 152 lua_assert(0); 153 } 154 } 155 } 156 157 158 static void LoadProtos (LoadState *S, Proto *f) { 159 int i; 160 int n = LoadInt(S); 161 f->p = luaM_newvector(S->L, n, Proto *); 162 f->sizep = n; 163 for (i = 0; i < n; i++) 164 f->p[i] = NULL; 165 for (i = 0; i < n; i++) { 166 f->p[i] = luaF_newproto(S->L); 167 luaC_objbarrier(S->L, f, f->p[i]); 168 LoadFunction(S, f->p[i], f->source); 169 } 170 } 171 172 173 static void LoadUpvalues (LoadState *S, Proto *f) { 174 int i, n; 175 n = LoadInt(S); 176 f->upvalues = luaM_newvector(S->L, n, Upvaldesc); 177 f->sizeupvalues = n; 178 for (i = 0; i < n; i++) 179 f->upvalues[i].name = NULL; 180 for (i = 0; i < n; i++) { 181 f->upvalues[i].instack = LoadByte(S); 182 f->upvalues[i].idx = LoadByte(S); 183 } 184 } 185 186 187 static void LoadDebug (LoadState *S, Proto *f) { 188 int i, n; 189 n = LoadInt(S); 190 f->lineinfo = luaM_newvector(S->L, n, int); 191 f->sizelineinfo = n; 192 LoadVector(S, f->lineinfo, n); 193 n = LoadInt(S); 194 f->locvars = luaM_newvector(S->L, n, LocVar); 195 f->sizelocvars = n; 196 for (i = 0; i < n; i++) 197 f->locvars[i].varname = NULL; 198 for (i = 0; i < n; i++) { 199 f->locvars[i].varname = LoadString(S, f); 200 f->locvars[i].startpc = LoadInt(S); 201 f->locvars[i].endpc = LoadInt(S); 202 } 203 n = LoadInt(S); 204 for (i = 0; i < n; i++) 205 f->upvalues[i].name = LoadString(S, f); 206 } 207 208 209 static void LoadFunction (LoadState *S, Proto *f, TString *psource) { 210 f->source = LoadString(S, f); 211 if (f->source == NULL) /* no source in dump? */ 212 f->source = psource; /* reuse parent's source */ 213 f->linedefined = LoadInt(S); 214 f->lastlinedefined = LoadInt(S); 215 f->numparams = LoadByte(S); 216 f->is_vararg = LoadByte(S); 217 f->maxstacksize = LoadByte(S); 218 LoadCode(S, f); 219 LoadConstants(S, f); 220 LoadUpvalues(S, f); 221 LoadProtos(S, f); 222 LoadDebug(S, f); 223 } 224 225 226 static void checkliteral (LoadState *S, const char *s, const char *msg) { 227 char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ 228 size_t len = strlen(s); 229 LoadVector(S, buff, len); 230 if (memcmp(s, buff, len) != 0) 231 error(S, msg); 232 } 233 234 235 static void fchecksize (LoadState *S, size_t size, const char *tname) { 236 if (LoadByte(S) != size) 237 error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); 238 } 239 240 241 #define checksize(S,t) fchecksize(S,sizeof(t),#t) 242 243 static void checkHeader (LoadState *S) { 244 checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ 245 if (LoadByte(S) != LUAC_VERSION) 246 error(S, "version mismatch in"); 247 if (LoadByte(S) != LUAC_FORMAT) 248 error(S, "format mismatch in"); 249 checkliteral(S, LUAC_DATA, "corrupted"); 250 checksize(S, int); 251 checksize(S, size_t); 252 checksize(S, Instruction); 253 checksize(S, lua_Integer); 254 checksize(S, lua_Number); 255 if (LoadInteger(S) != LUAC_INT) 256 error(S, "endianness mismatch in"); 257 if (LoadNumber(S) != LUAC_NUM) 258 error(S, "float format mismatch in"); 259 } 260 261 262 /* 263 ** load precompiled chunk 264 */ 265 LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { 266 LoadState S; 267 LClosure *cl; 268 if (*name == '@' || *name == '=') 269 S.name = name + 1; 270 else if (*name == LUA_SIGNATURE[0]) 271 S.name = "binary string"; 272 else 273 S.name = name; 274 S.L = L; 275 S.Z = Z; 276 checkHeader(&S); 277 cl = luaF_newLclosure(L, LoadByte(&S)); 278 setclLvalue(L, L->top, cl); 279 luaD_inctop(L); 280 cl->p = luaF_newproto(L); 281 luaC_objbarrier(L, cl, cl->p); 282 LoadFunction(&S, cl->p, NULL); 283 lua_assert(cl->nupvalues == cl->p->sizeupvalues); 284 luai_verifycode(L, buff, cl->p); 285 return cl; 286 } 287 288