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