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