lundump.c revision 1.3
1/* $NetBSD: lundump.c,v 1.3 2015/02/02 14:03:05 lneto Exp $ */ 2 3/* 4** Id: lundump.c,v 2.41 2014/11/02 19:19:04 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 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 Mbuffer *b; 40 const char *name; 41} LoadState; 42 43 44static l_noret error(LoadState *S, const char *why) { 45 luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); 46 luaD_throw(S->L, LUA_ERRSYNTAX); 47} 48 49 50/* 51** All high-level loads go through LoadVector; you can change it to 52** adapt to the endianness of the input 53*/ 54#define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0])) 55 56static void LoadBlock (LoadState *S, void *b, size_t size) { 57 if (luaZ_read(S->Z, b, size) != 0) 58 error(S, "truncated"); 59} 60 61 62#define LoadVar(S,x) LoadVector(S,&x,1) 63 64 65static lu_byte LoadByte (LoadState *S) { 66 lu_byte x; 67 LoadVar(S, x); 68 return x; 69} 70 71 72static int LoadInt (LoadState *S) { 73 int x; 74 LoadVar(S, x); 75 return x; 76} 77 78 79static lua_Number LoadNumber (LoadState *S) { 80 lua_Number x; 81 LoadVar(S, x); 82 return x; 83} 84 85 86static lua_Integer LoadInteger (LoadState *S) { 87 lua_Integer x; 88 LoadVar(S, x); 89 return x; 90} 91 92 93static TString *LoadString (LoadState *S) { 94 size_t size = LoadByte(S); 95 if (size == 0xFF) 96 LoadVar(S, size); 97 if (size == 0) 98 return NULL; 99 else { 100 char *s = luaZ_openspace(S->L, S->b, --size); 101 LoadVector(S, s, size); 102 return luaS_newlstr(S->L, s, size); 103 } 104} 105 106 107static 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 115static void LoadFunction(LoadState *S, Proto *f, TString *psource); 116 117 118static 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#ifndef _KERNEL 136 case LUA_TNUMFLT: 137 setfltvalue(o, LoadNumber(S)); 138 break; 139#endif 140 case LUA_TNUMINT: 141 setivalue(o, LoadInteger(S)); 142 break; 143 case LUA_TSHRSTR: 144 case LUA_TLNGSTR: 145 setsvalue2n(S->L, o, LoadString(S)); 146 break; 147 default: 148 lua_assert(0); 149 } 150 } 151} 152 153 154static void LoadProtos (LoadState *S, Proto *f) { 155 int i; 156 int n = LoadInt(S); 157 f->p = luaM_newvector(S->L, n, Proto *); 158 f->sizep = n; 159 for (i = 0; i < n; i++) 160 f->p[i] = NULL; 161 for (i = 0; i < n; i++) { 162 f->p[i] = luaF_newproto(S->L); 163 LoadFunction(S, f->p[i], f->source); 164 } 165} 166 167 168static void LoadUpvalues (LoadState *S, Proto *f) { 169 int i, n; 170 n = LoadInt(S); 171 f->upvalues = luaM_newvector(S->L, n, Upvaldesc); 172 f->sizeupvalues = n; 173 for (i = 0; i < n; i++) 174 f->upvalues[i].name = NULL; 175 for (i = 0; i < n; i++) { 176 f->upvalues[i].instack = LoadByte(S); 177 f->upvalues[i].idx = LoadByte(S); 178 } 179} 180 181 182static void LoadDebug (LoadState *S, Proto *f) { 183 int i, n; 184 n = LoadInt(S); 185 f->lineinfo = luaM_newvector(S->L, n, int); 186 f->sizelineinfo = n; 187 LoadVector(S, f->lineinfo, n); 188 n = LoadInt(S); 189 f->locvars = luaM_newvector(S->L, n, LocVar); 190 f->sizelocvars = n; 191 for (i = 0; i < n; i++) 192 f->locvars[i].varname = NULL; 193 for (i = 0; i < n; i++) { 194 f->locvars[i].varname = LoadString(S); 195 f->locvars[i].startpc = LoadInt(S); 196 f->locvars[i].endpc = LoadInt(S); 197 } 198 n = LoadInt(S); 199 for (i = 0; i < n; i++) 200 f->upvalues[i].name = LoadString(S); 201} 202 203 204static void LoadFunction (LoadState *S, Proto *f, TString *psource) { 205 f->source = LoadString(S); 206 if (f->source == NULL) /* no source in dump? */ 207 f->source = psource; /* reuse parent's source */ 208 f->linedefined = LoadInt(S); 209 f->lastlinedefined = LoadInt(S); 210 f->numparams = LoadByte(S); 211 f->is_vararg = LoadByte(S); 212 f->maxstacksize = LoadByte(S); 213 LoadCode(S, f); 214 LoadConstants(S, f); 215 LoadUpvalues(S, f); 216 LoadProtos(S, f); 217 LoadDebug(S, f); 218} 219 220 221static void checkliteral (LoadState *S, const char *s, const char *msg) { 222 char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ 223 size_t len = strlen(s); 224 LoadVector(S, buff, len); 225 if (memcmp(s, buff, len) != 0) 226 error(S, msg); 227} 228 229 230static void fchecksize (LoadState *S, size_t size, const char *tname) { 231 if (LoadByte(S) != size) 232 error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); 233} 234 235 236#define checksize(S,t) fchecksize(S,sizeof(t),#t) 237 238static void checkHeader (LoadState *S) { 239 checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ 240 if (LoadByte(S) != LUAC_VERSION) 241 error(S, "version mismatch in"); 242 if (LoadByte(S) != LUAC_FORMAT) 243 error(S, "format mismatch in"); 244 checkliteral(S, LUAC_DATA, "corrupted"); 245 checksize(S, int); 246 checksize(S, size_t); 247 checksize(S, Instruction); 248 checksize(S, lua_Integer); 249 checksize(S, lua_Number); 250 if (LoadInteger(S) != LUAC_INT) 251 error(S, "endianness mismatch in"); 252 if (LoadNumber(S) != LUAC_NUM) 253 error(S, "float format mismatch in"); 254} 255 256 257/* 258** load precompiled chunk 259*/ 260LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff, 261 const char *name) { 262 LoadState S; 263 LClosure *cl; 264 if (*name == '@' || *name == '=') 265 S.name = name + 1; 266 else if (*name == LUA_SIGNATURE[0]) 267 S.name = "binary string"; 268 else 269 S.name = name; 270 S.L = L; 271 S.Z = Z; 272 S.b = buff; 273 checkHeader(&S); 274 cl = luaF_newLclosure(L, LoadByte(&S)); 275 setclLvalue(L, L->top, cl); 276 incr_top(L); 277 cl->p = luaF_newproto(L); 278 LoadFunction(&S, cl->p, NULL); 279 lua_assert(cl->nupvalues == cl->p->sizeupvalues); 280 luai_verifycode(L, buff, cl->p); 281 return cl; 282} 283 284