lundump.c revision 1.5
1/* $NetBSD: lundump.c,v 1.5 2016/09/08 02:21:31 salazar Exp $ */ 2 3/* 4** Id: lundump.c,v 2.44 2015/11/02 16:09:30 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 36typedef struct { 37 lua_State *L; 38 ZIO *Z; 39 const char *name; 40} LoadState; 41 42 43static 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 55static 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 64static lu_byte LoadByte (LoadState *S) { 65 lu_byte x; 66 LoadVar(S, x); 67 return x; 68} 69 70 71static int LoadInt (LoadState *S) { 72 int x; 73 LoadVar(S, x); 74 return x; 75} 76 77 78static lua_Number LoadNumber (LoadState *S) { 79 lua_Number x; 80 LoadVar(S, x); 81 return x; 82} 83 84 85static lua_Integer LoadInteger (LoadState *S) { 86 lua_Integer x; 87 LoadVar(S, x); 88 return x; 89} 90 91 92static 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 111static 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 119static void LoadFunction(LoadState *S, Proto *f, TString *psource); 120 121 122static 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 158static 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 172static 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 186static 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 208static 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 225static 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 234static 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 242static 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*/ 264LClosure *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