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