lundump.c revision 1.2
1/*	$NetBSD: lundump.c,v 1.2 2014/07/19 18:38:34 lneto Exp $	*/
2
3/*
4** $Id: lundump.c,v 1.2 2014/07/19 18:38:34 lneto Exp $
5** load precompiled Lua chunks
6** See Copyright Notice in lua.h
7*/
8
9#ifndef _KERNEL
10#include <string.h>
11#endif
12
13#define lundump_c
14#define LUA_CORE
15
16#include "lua.h"
17
18#include "ldebug.h"
19#include "ldo.h"
20#include "lfunc.h"
21#include "lmem.h"
22#include "lobject.h"
23#include "lstring.h"
24#include "lundump.h"
25#include "lzio.h"
26
27
28#if !defined(luai_verifycode)
29#define luai_verifycode(L,b,f)  /* empty */
30#endif
31
32
33typedef struct {
34  lua_State *L;
35  ZIO *Z;
36  Mbuffer *b;
37  const char *name;
38} LoadState;
39
40
41static l_noret error(LoadState *S, const char *why) {
42  luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
43  luaD_throw(S->L, LUA_ERRSYNTAX);
44}
45
46
47/*
48** All high-level loads go through LoadVector; you can change it to
49** adapt to the endianness of the input
50*/
51#define LoadVector(S,b,n)	LoadBlock(S,b,(n)*sizeof((b)[0]))
52
53static void LoadBlock (LoadState *S, void *b, size_t size) {
54  if (luaZ_read(S->Z, b, size) != 0)
55    error(S, "truncated");
56}
57
58
59#define LoadVar(S,x)		LoadVector(S,&x,1)
60
61
62static lu_byte LoadByte (LoadState *S) {
63  lu_byte x;
64  LoadVar(S, x);
65  return x;
66}
67
68
69static int LoadInt (LoadState *S) {
70  int x;
71  LoadVar(S, x);
72  return x;
73}
74
75
76static lua_Number LoadNumber (LoadState *S) {
77  lua_Number x;
78  LoadVar(S, x);
79  return x;
80}
81
82
83static lua_Integer LoadInteger (LoadState *S) {
84  lua_Integer x;
85  LoadVar(S, x);
86  return x;
87}
88
89
90static TString *LoadString (LoadState *S) {
91  size_t size = LoadByte(S);
92  if (size == 0xFF)
93    LoadVar(S, size);
94  if (size == 0)
95    return NULL;
96  else {
97    char *s = luaZ_openspace(S->L, S->b, --size);
98    LoadVector(S, s, size);
99    return luaS_newlstr(S->L, s, size);
100  }
101}
102
103
104static void LoadCode (LoadState *S, Proto *f) {
105  int n = LoadInt(S);
106  f->code = luaM_newvector(S->L, n, Instruction);
107  f->sizecode = n;
108  LoadVector(S, f->code, n);
109}
110
111
112static void LoadFunction(LoadState *S, Proto *f, TString *psource);
113
114
115static void LoadConstants (LoadState *S, Proto *f) {
116  int i;
117  int n = LoadInt(S);
118  f->k = luaM_newvector(S->L, n, TValue);
119  f->sizek = n;
120  for (i = 0; i < n; i++)
121    setnilvalue(&f->k[i]);
122  for (i = 0; i < n; i++) {
123    TValue *o = &f->k[i];
124    int t = LoadByte(S);
125    switch (t) {
126    case LUA_TNIL:
127      setnilvalue(o);
128      break;
129    case LUA_TBOOLEAN:
130      setbvalue(o, LoadByte(S));
131      break;
132#ifndef _KERNEL
133    case LUA_TNUMFLT:
134      setfltvalue(o, LoadNumber(S));
135      break;
136#endif
137    case LUA_TNUMINT:
138      setivalue(o, LoadInteger(S));
139      break;
140    case LUA_TSHRSTR:
141    case LUA_TLNGSTR:
142      setsvalue2n(S->L, o, LoadString(S));
143      break;
144    default:
145      lua_assert(0);
146    }
147  }
148}
149
150
151static void LoadProtos (LoadState *S, Proto *f) {
152  int i;
153  int n = LoadInt(S);
154  f->p = luaM_newvector(S->L, n, Proto *);
155  f->sizep = n;
156  for (i = 0; i < n; i++)
157    f->p[i] = NULL;
158  for (i = 0; i < n; i++) {
159    f->p[i] = luaF_newproto(S->L);
160    LoadFunction(S, f->p[i], f->source);
161  }
162}
163
164
165static void LoadUpvalues (LoadState *S, Proto *f) {
166  int i, n;
167  n = LoadInt(S);
168  f->upvalues = luaM_newvector(S->L, n, Upvaldesc);
169  f->sizeupvalues = n;
170  for (i = 0; i < n; i++)
171    f->upvalues[i].name = NULL;
172  for (i = 0; i < n; i++) {
173    f->upvalues[i].instack = LoadByte(S);
174    f->upvalues[i].idx = LoadByte(S);
175  }
176}
177
178
179static void LoadDebug (LoadState *S, Proto *f) {
180  int i, n;
181  n = LoadInt(S);
182  f->lineinfo = luaM_newvector(S->L, n, int);
183  f->sizelineinfo = n;
184  LoadVector(S, f->lineinfo, n);
185  n = LoadInt(S);
186  f->locvars = luaM_newvector(S->L, n, LocVar);
187  f->sizelocvars = n;
188  for (i = 0; i < n; i++)
189    f->locvars[i].varname = NULL;
190  for (i = 0; i < n; i++) {
191    f->locvars[i].varname = LoadString(S);
192    f->locvars[i].startpc = LoadInt(S);
193    f->locvars[i].endpc = LoadInt(S);
194  }
195  n = LoadInt(S);
196  for (i = 0; i < n; i++)
197    f->upvalues[i].name = LoadString(S);
198}
199
200
201static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
202  f->source = LoadString(S);
203  if (f->source == NULL)  /* no source in dump? */
204    f->source = psource;  /* reuse parent's source */
205  f->linedefined = LoadInt(S);
206  f->lastlinedefined = LoadInt(S);
207  f->numparams = LoadByte(S);
208  f->is_vararg = LoadByte(S);
209  f->maxstacksize = LoadByte(S);
210  LoadCode(S, f);
211  LoadConstants(S, f);
212  LoadUpvalues(S, f);
213  LoadProtos(S, f);
214  LoadDebug(S, f);
215}
216
217
218static void checkliteral (LoadState *S, const char *s, const char *msg) {
219  char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
220  size_t len = strlen(s);
221  LoadVector(S, buff, len);
222  if (memcmp(s, buff, len) != 0)
223    error(S, msg);
224}
225
226
227static void fchecksize (LoadState *S, size_t size, const char *tname) {
228  if (LoadByte(S) != size)
229    error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname));
230}
231
232
233#define checksize(S,t)	fchecksize(S,sizeof(t),#t)
234
235static void checkHeader (LoadState *S) {
236  checkliteral(S, LUA_SIGNATURE + 1, "not a");  /* 1st char already checked */
237  if (LoadByte(S) != LUAC_VERSION)
238    error(S, "version mismatch in");
239  if (LoadByte(S) != LUAC_FORMAT)
240    error(S, "format mismatch in");
241  checkliteral(S, LUAC_DATA, "corrupted");
242  checksize(S, int);
243  checksize(S, size_t);
244  checksize(S, Instruction);
245  checksize(S, lua_Integer);
246  checksize(S, lua_Number);
247  if (LoadInteger(S) != LUAC_INT)
248    error(S, "endianness mismatch in");
249  if (LoadNumber(S) != LUAC_NUM)
250    error(S, "float format mismatch in");
251}
252
253
254/*
255** load precompiled chunk
256*/
257LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff,
258                      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  S.b = buff;
270  checkHeader(&S);
271  cl = luaF_newLclosure(L, LoadByte(&S));
272  setclLvalue(L, L->top, cl);
273  incr_top(L);
274  cl->p = luaF_newproto(L);
275  LoadFunction(&S, cl->p, NULL);
276  lua_assert(cl->nupvalues == cl->p->sizeupvalues);
277  luai_verifycode(L, buff, cl->p);
278  return cl;
279}
280
281