xref: /minix3/external/mit/lua/dist/src/lundump.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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 
36 typedef struct {
37   lua_State *L;
38   ZIO *Z;
39   Mbuffer *b;
40   const char *name;
41 } LoadState;
42 
43 
error(LoadState * S,const char * why)44 static 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 
LoadBlock(LoadState * S,void * b,size_t size)56 static 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 
LoadByte(LoadState * S)65 static lu_byte LoadByte (LoadState *S) {
66   lu_byte x;
67   LoadVar(S, x);
68   return x;
69 }
70 
71 
LoadInt(LoadState * S)72 static int LoadInt (LoadState *S) {
73   int x;
74   LoadVar(S, x);
75   return x;
76 }
77 
78 
LoadNumber(LoadState * S)79 static lua_Number LoadNumber (LoadState *S) {
80   lua_Number x;
81   LoadVar(S, x);
82   return x;
83 }
84 
85 
LoadInteger(LoadState * S)86 static lua_Integer LoadInteger (LoadState *S) {
87   lua_Integer x;
88   LoadVar(S, x);
89   return x;
90 }
91 
92 
LoadString(LoadState * S)93 static 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 
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 #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 
LoadProtos(LoadState * S,Proto * f)154 static 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 
LoadUpvalues(LoadState * S,Proto * f)168 static 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 
LoadDebug(LoadState * S,Proto * f)182 static 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 
LoadFunction(LoadState * S,Proto * f,TString * psource)204 static 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 
checkliteral(LoadState * S,const char * s,const char * msg)221 static 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 
fchecksize(LoadState * S,size_t size,const char * tname)230 static 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 
checkHeader(LoadState * S)238 static 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 */
luaU_undump(lua_State * L,ZIO * Z,Mbuffer * buff,const char * name)260 LClosure *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