1 /* 2 ** $Id: lundump.c $ 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 <limits.h> 14 #include <string.h> 15 16 #include "lua.h" 17 18 #include "ldebug.h" 19 #include "ldo.h" 20 #include "lfunc.h" 21 #include "lmem.h" 22 #include "lobject.h" 23 #include "lstring.h" 24 #include "lundump.h" 25 #include "lzio.h" 26 27 28 #if !defined(luai_verifycode) 29 #define luai_verifycode(L,f) /* empty */ 30 #endif 31 32 33 typedef struct { 34 lua_State *L; 35 ZIO *Z; 36 const char *name; 37 } LoadState; 38 39 40 static l_noret error (LoadState *S, const char *why) { 41 luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why); 42 luaD_throw(S->L, LUA_ERRSYNTAX); 43 } 44 45 46 /* 47 ** All high-level loads go through loadVector; you can change it to 48 ** adapt to the endianness of the input 49 */ 50 #define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0])) 51 52 static void loadBlock (LoadState *S, void *b, size_t size) { 53 if (luaZ_read(S->Z, b, size) != 0) 54 error(S, "truncated chunk"); 55 } 56 57 58 #define loadVar(S,x) loadVector(S,&x,1) 59 60 61 static lu_byte loadByte (LoadState *S) { 62 int b = zgetc(S->Z); 63 if (b == EOZ) 64 error(S, "truncated chunk"); 65 return cast_byte(b); 66 } 67 68 69 static size_t loadUnsigned (LoadState *S, size_t limit) { 70 size_t x = 0; 71 int b; 72 limit >>= 7; 73 do { 74 b = loadByte(S); 75 if (x >= limit) 76 error(S, "integer overflow"); 77 x = (x << 7) | (b & 0x7f); 78 } while ((b & 0x80) == 0); 79 return x; 80 } 81 82 83 static size_t loadSize (LoadState *S) { 84 return loadUnsigned(S, ~(size_t)0); 85 } 86 87 88 static int loadInt (LoadState *S) { 89 return cast_int(loadUnsigned(S, INT_MAX)); 90 } 91 92 93 static lua_Number loadNumber (LoadState *S) { 94 lua_Number x; 95 loadVar(S, x); 96 return x; 97 } 98 99 100 static lua_Integer loadInteger (LoadState *S) { 101 lua_Integer x; 102 loadVar(S, x); 103 return x; 104 } 105 106 107 /* 108 ** Load a nullable string into prototype 'p'. 109 */ 110 static TString *loadStringN (LoadState *S, Proto *p) { 111 lua_State *L = S->L; 112 TString *ts; 113 size_t size = loadSize(S); 114 if (size == 0) /* no string? */ 115 return NULL; 116 else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ 117 char buff[LUAI_MAXSHORTLEN]; 118 loadVector(S, buff, size); /* load string into buffer */ 119 ts = luaS_newlstr(L, buff, size); /* create string */ 120 } 121 else { /* long string */ 122 ts = luaS_createlngstrobj(L, size); /* create string */ 123 setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */ 124 luaD_inctop(L); 125 loadVector(S, getstr(ts), size); /* load directly in final place */ 126 L->top--; /* pop string */ 127 } 128 luaC_objbarrier(L, p, ts); 129 return ts; 130 } 131 132 133 /* 134 ** Load a non-nullable string into prototype 'p'. 135 */ 136 static TString *loadString (LoadState *S, Proto *p) { 137 TString *st = loadStringN(S, p); 138 if (st == NULL) 139 error(S, "bad format for constant string"); 140 return st; 141 } 142 143 144 static void loadCode (LoadState *S, Proto *f) { 145 int n = loadInt(S); 146 f->code = luaM_newvectorchecked(S->L, n, Instruction); 147 f->sizecode = n; 148 loadVector(S, f->code, n); 149 } 150 151 152 static void loadFunction(LoadState *S, Proto *f, TString *psource); 153 154 155 static void loadConstants (LoadState *S, Proto *f) { 156 int i; 157 int n = loadInt(S); 158 f->k = luaM_newvectorchecked(S->L, n, TValue); 159 f->sizek = n; 160 for (i = 0; i < n; i++) 161 setnilvalue(&f->k[i]); 162 for (i = 0; i < n; i++) { 163 TValue *o = &f->k[i]; 164 int t = loadByte(S); 165 switch (t) { 166 case LUA_VNIL: 167 setnilvalue(o); 168 break; 169 case LUA_VFALSE: 170 setbfvalue(o); 171 break; 172 case LUA_VTRUE: 173 setbtvalue(o); 174 break; 175 case LUA_VNUMFLT: 176 setfltvalue(o, loadNumber(S)); 177 break; 178 case LUA_VNUMINT: 179 setivalue(o, loadInteger(S)); 180 break; 181 case LUA_VSHRSTR: 182 case LUA_VLNGSTR: 183 setsvalue2n(S->L, o, loadString(S, f)); 184 break; 185 default: lua_assert(0); 186 } 187 } 188 } 189 190 191 static void loadProtos (LoadState *S, Proto *f) { 192 int i; 193 int n = loadInt(S); 194 f->p = luaM_newvectorchecked(S->L, n, Proto *); 195 f->sizep = n; 196 for (i = 0; i < n; i++) 197 f->p[i] = NULL; 198 for (i = 0; i < n; i++) { 199 f->p[i] = luaF_newproto(S->L); 200 luaC_objbarrier(S->L, f, f->p[i]); 201 loadFunction(S, f->p[i], f->source); 202 } 203 } 204 205 206 /* 207 ** Load the upvalues for a function. The names must be filled first, 208 ** because the filling of the other fields can raise read errors and 209 ** the creation of the error message can call an emergency collection; 210 ** in that case all prototypes must be consistent for the GC. 211 */ 212 static void loadUpvalues (LoadState *S, Proto *f) { 213 int i, n; 214 n = loadInt(S); 215 f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc); 216 f->sizeupvalues = n; 217 for (i = 0; i < n; i++) /* make array valid for GC */ 218 f->upvalues[i].name = NULL; 219 for (i = 0; i < n; i++) { /* following calls can raise errors */ 220 f->upvalues[i].instack = loadByte(S); 221 f->upvalues[i].idx = loadByte(S); 222 f->upvalues[i].kind = loadByte(S); 223 } 224 } 225 226 227 static void loadDebug (LoadState *S, Proto *f) { 228 int i, n; 229 n = loadInt(S); 230 f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte); 231 f->sizelineinfo = n; 232 loadVector(S, f->lineinfo, n); 233 n = loadInt(S); 234 f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo); 235 f->sizeabslineinfo = n; 236 for (i = 0; i < n; i++) { 237 f->abslineinfo[i].pc = loadInt(S); 238 f->abslineinfo[i].line = loadInt(S); 239 } 240 n = loadInt(S); 241 f->locvars = luaM_newvectorchecked(S->L, n, LocVar); 242 f->sizelocvars = n; 243 for (i = 0; i < n; i++) 244 f->locvars[i].varname = NULL; 245 for (i = 0; i < n; i++) { 246 f->locvars[i].varname = loadStringN(S, f); 247 f->locvars[i].startpc = loadInt(S); 248 f->locvars[i].endpc = loadInt(S); 249 } 250 n = loadInt(S); 251 for (i = 0; i < n; i++) 252 f->upvalues[i].name = loadStringN(S, f); 253 } 254 255 256 static void loadFunction (LoadState *S, Proto *f, TString *psource) { 257 f->source = loadStringN(S, f); 258 if (f->source == NULL) /* no source in dump? */ 259 f->source = psource; /* reuse parent's source */ 260 f->linedefined = loadInt(S); 261 f->lastlinedefined = loadInt(S); 262 f->numparams = loadByte(S); 263 f->is_vararg = loadByte(S); 264 f->maxstacksize = loadByte(S); 265 loadCode(S, f); 266 loadConstants(S, f); 267 loadUpvalues(S, f); 268 loadProtos(S, f); 269 loadDebug(S, f); 270 } 271 272 273 static void checkliteral (LoadState *S, const char *s, const char *msg) { 274 char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ 275 size_t len = strlen(s); 276 loadVector(S, buff, len); 277 if (memcmp(s, buff, len) != 0) 278 error(S, msg); 279 } 280 281 282 static void fchecksize (LoadState *S, size_t size, const char *tname) { 283 if (loadByte(S) != size) 284 error(S, luaO_pushfstring(S->L, "%s size mismatch", tname)); 285 } 286 287 288 #define checksize(S,t) fchecksize(S,sizeof(t),#t) 289 290 static void checkHeader (LoadState *S) { 291 /* skip 1st char (already read and checked) */ 292 checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk"); 293 if (loadByte(S) != LUAC_VERSION) 294 error(S, "version mismatch"); 295 if (loadByte(S) != LUAC_FORMAT) 296 error(S, "format mismatch"); 297 checkliteral(S, LUAC_DATA, "corrupted chunk"); 298 checksize(S, Instruction); 299 checksize(S, lua_Integer); 300 checksize(S, lua_Number); 301 if (loadInteger(S) != LUAC_INT) 302 error(S, "integer format mismatch"); 303 if (loadNumber(S) != LUAC_NUM) 304 error(S, "float format mismatch"); 305 } 306 307 308 /* 309 ** Load precompiled chunk. 310 */ 311 LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { 312 LoadState S; 313 LClosure *cl; 314 if (*name == '@' || *name == '=') 315 S.name = name + 1; 316 else if (*name == LUA_SIGNATURE[0]) 317 S.name = "binary string"; 318 else 319 S.name = name; 320 S.L = L; 321 S.Z = Z; 322 checkHeader(&S); 323 cl = luaF_newLclosure(L, loadByte(&S)); 324 setclLvalue2s(L, L->top, cl); 325 luaD_inctop(L); 326 cl->p = luaF_newproto(L); 327 luaC_objbarrier(L, cl, cl->p); 328 loadFunction(&S, cl->p, NULL); 329 lua_assert(cl->nupvalues == cl->p->sizeupvalues); 330 luai_verifycode(L, cl->p); 331 return cl; 332 } 333 334