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