Coverage Report

Created: 2023-09-15 06:19

/src/testdir/build/lua-master/source/lundump.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** $Id: lundump.c $
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 <limits.h>
14
#include <string.h>
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,f)  /* empty */
30
#endif
31
32
33
typedef struct {
34
  lua_State *L;
35
  ZIO *Z;
36
  const char *name;
37
} LoadState;
38
39
40
0
static l_noret error (LoadState *S, const char *why) {
41
0
  luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why);
42
0
  luaD_throw(S->L, LUA_ERRSYNTAX);
43
0
}
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
0
#define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0]))
51
52
0
static void loadBlock (LoadState *S, void *b, size_t size) {
53
0
  if (luaZ_read(S->Z, b, size) != 0)
54
0
    error(S, "truncated chunk");
55
0
}
56
57
58
0
#define loadVar(S,x)    loadVector(S,&x,1)
59
60
61
0
static lu_byte loadByte (LoadState *S) {
62
0
  int b = zgetc(S->Z);
63
0
  if (b == EOZ)
64
0
    error(S, "truncated chunk");
65
0
  return cast_byte(b);
66
0
}
67
68
69
0
static size_t loadUnsigned (LoadState *S, size_t limit) {
70
0
  size_t x = 0;
71
0
  int b;
72
0
  limit >>= 7;
73
0
  do {
74
0
    b = loadByte(S);
75
0
    if (x >= limit)
76
0
      error(S, "integer overflow");
77
0
    x = (x << 7) | (b & 0x7f);
78
0
  } while ((b & 0x80) == 0);
79
0
  return x;
80
0
}
81
82
83
0
static size_t loadSize (LoadState *S) {
84
0
  return loadUnsigned(S, MAX_SIZET);
85
0
}
86
87
88
0
static int loadInt (LoadState *S) {
89
0
  return cast_int(loadUnsigned(S, INT_MAX));
90
0
}
91
92
93
0
static lua_Number loadNumber (LoadState *S) {
94
0
  lua_Number x;
95
0
  loadVar(S, x);
96
0
  return x;
97
0
}
98
99
100
0
static lua_Integer loadInteger (LoadState *S) {
101
0
  lua_Integer x;
102
0
  loadVar(S, x);
103
0
  return x;
104
0
}
105
106
107
/*
108
** Load a nullable string into prototype 'p'.
109
*/
110
0
static TString *loadStringN (LoadState *S, Proto *p) {
111
0
  lua_State *L = S->L;
112
0
  TString *ts;
113
0
  size_t size = loadSize(S);
114
0
  if (size == 0)  /* no string? */
115
0
    return NULL;
116
0
  else if (--size <= LUAI_MAXSHORTLEN) {  /* short string? */
117
0
    char buff[LUAI_MAXSHORTLEN];
118
0
    loadVector(S, buff, size);  /* load string into buffer */
119
0
    ts = luaS_newlstr(L, buff, size);  /* create string */
120
0
  }
121
0
  else {  /* long string */
122
0
    ts = luaS_createlngstrobj(L, size);  /* create string */
123
0
    setsvalue2s(L, L->top.p, ts);  /* anchor it ('loadVector' can GC) */
124
0
    luaD_inctop(L);
125
0
    loadVector(S, getlngstr(ts), size);  /* load directly in final place */
126
0
    L->top.p--;  /* pop string */
127
0
  }
128
0
  luaC_objbarrier(L, p, ts);
129
0
  return ts;
130
0
}
131
132
133
/*
134
** Load a non-nullable string into prototype 'p'.
135
*/
136
0
static TString *loadString (LoadState *S, Proto *p) {
137
0
  TString *st = loadStringN(S, p);
138
0
  if (st == NULL)
139
0
    error(S, "bad format for constant string");
140
0
  return st;
141
0
}
142
143
144
0
static void loadCode (LoadState *S, Proto *f) {
145
0
  int n = loadInt(S);
146
0
  f->code = luaM_newvectorchecked(S->L, n, Instruction);
147
0
  f->sizecode = n;
148
0
  loadVector(S, f->code, n);
149
0
}
150
151
152
static void loadFunction(LoadState *S, Proto *f, TString *psource);
153
154
155
0
static void loadConstants (LoadState *S, Proto *f) {
156
0
  int i;
157
0
  int n = loadInt(S);
158
0
  f->k = luaM_newvectorchecked(S->L, n, TValue);
159
0
  f->sizek = n;
160
0
  for (i = 0; i < n; i++)
161
0
    setnilvalue(&f->k[i]);
162
0
  for (i = 0; i < n; i++) {
163
0
    TValue *o = &f->k[i];
164
0
    int t = loadByte(S);
165
0
    switch (t) {
166
0
      case LUA_VNIL:
167
0
        setnilvalue(o);
168
0
        break;
169
0
      case LUA_VFALSE:
170
0
        setbfvalue(o);
171
0
        break;
172
0
      case LUA_VTRUE:
173
0
        setbtvalue(o);
174
0
        break;
175
0
      case LUA_VNUMFLT:
176
0
        setfltvalue(o, loadNumber(S));
177
0
        break;
178
0
      case LUA_VNUMINT:
179
0
        setivalue(o, loadInteger(S));
180
0
        break;
181
0
      case LUA_VSHRSTR:
182
0
      case LUA_VLNGSTR:
183
0
        setsvalue2n(S->L, o, loadString(S, f));
184
0
        break;
185
0
      default: lua_assert(0);
186
0
    }
187
0
  }
188
0
}
189
190
191
0
static void loadProtos (LoadState *S, Proto *f) {
192
0
  int i;
193
0
  int n = loadInt(S);
194
0
  f->p = luaM_newvectorchecked(S->L, n, Proto *);
195
0
  f->sizep = n;
196
0
  for (i = 0; i < n; i++)
197
0
    f->p[i] = NULL;
198
0
  for (i = 0; i < n; i++) {
199
0
    f->p[i] = luaF_newproto(S->L);
200
0
    luaC_objbarrier(S->L, f, f->p[i]);
201
0
    loadFunction(S, f->p[i], f->source);
202
0
  }
203
0
}
204
205
206
/*
207
** Load the upvalues for a function. The names must be filled first,
208
** because the filling of the other fields can raise read errors and
209
** the creation of the error message can call an emergency collection;
210
** in that case all prototypes must be consistent for the GC.
211
*/
212
0
static void loadUpvalues (LoadState *S, Proto *f) {
213
0
  int i, n;
214
0
  n = loadInt(S);
215
0
  f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc);
216
0
  f->sizeupvalues = n;
217
0
  for (i = 0; i < n; i++)  /* make array valid for GC */
218
0
    f->upvalues[i].name = NULL;
219
0
  for (i = 0; i < n; i++) {  /* following calls can raise errors */
220
0
    f->upvalues[i].instack = loadByte(S);
221
0
    f->upvalues[i].idx = loadByte(S);
222
0
    f->upvalues[i].kind = loadByte(S);
223
0
  }
224
0
}
225
226
227
0
static void loadDebug (LoadState *S, Proto *f) {
228
0
  int i, n;
229
0
  n = loadInt(S);
230
0
  f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte);
231
0
  f->sizelineinfo = n;
232
0
  loadVector(S, f->lineinfo, n);
233
0
  n = loadInt(S);
234
0
  f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo);
235
0
  f->sizeabslineinfo = n;
236
0
  for (i = 0; i < n; i++) {
237
0
    f->abslineinfo[i].pc = loadInt(S);
238
0
    f->abslineinfo[i].line = loadInt(S);
239
0
  }
240
0
  n = loadInt(S);
241
0
  f->locvars = luaM_newvectorchecked(S->L, n, LocVar);
242
0
  f->sizelocvars = n;
243
0
  for (i = 0; i < n; i++)
244
0
    f->locvars[i].varname = NULL;
245
0
  for (i = 0; i < n; i++) {
246
0
    f->locvars[i].varname = loadStringN(S, f);
247
0
    f->locvars[i].startpc = loadInt(S);
248
0
    f->locvars[i].endpc = loadInt(S);
249
0
  }
250
0
  n = loadInt(S);
251
0
  if (n != 0)  /* does it have debug information? */
252
0
    n = f->sizeupvalues;  /* must be this many */
253
0
  for (i = 0; i < n; i++)
254
0
    f->upvalues[i].name = loadStringN(S, f);
255
0
}
256
257
258
0
static void loadFunction (LoadState *S, Proto *f, TString *psource) {
259
0
  f->source = loadStringN(S, f);
260
0
  if (f->source == NULL)  /* no source in dump? */
261
0
    f->source = psource;  /* reuse parent's source */
262
0
  f->linedefined = loadInt(S);
263
0
  f->lastlinedefined = loadInt(S);
264
0
  f->numparams = loadByte(S);
265
0
  f->is_vararg = loadByte(S);
266
0
  f->maxstacksize = loadByte(S);
267
0
  loadCode(S, f);
268
0
  loadConstants(S, f);
269
0
  loadUpvalues(S, f);
270
0
  loadProtos(S, f);
271
0
  loadDebug(S, f);
272
0
}
273
274
275
0
static void checkliteral (LoadState *S, const char *s, const char *msg) {
276
0
  char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
277
0
  size_t len = strlen(s);
278
0
  loadVector(S, buff, len);
279
0
  if (memcmp(s, buff, len) != 0)
280
0
    error(S, msg);
281
0
}
282
283
284
0
static void fchecksize (LoadState *S, size_t size, const char *tname) {
285
0
  if (loadByte(S) != size)
286
0
    error(S, luaO_pushfstring(S->L, "%s size mismatch", tname));
287
0
}
288
289
290
0
#define checksize(S,t)  fchecksize(S,sizeof(t),#t)
291
292
0
static void checkHeader (LoadState *S) {
293
  /* skip 1st char (already read and checked) */
294
0
  checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk");
295
0
  if (loadByte(S) != LUAC_VERSION)
296
0
    error(S, "version mismatch");
297
0
  if (loadByte(S) != LUAC_FORMAT)
298
0
    error(S, "format mismatch");
299
0
  checkliteral(S, LUAC_DATA, "corrupted chunk");
300
0
  checksize(S, Instruction);
301
0
  checksize(S, lua_Integer);
302
0
  checksize(S, lua_Number);
303
0
  if (loadInteger(S) != LUAC_INT)
304
0
    error(S, "integer format mismatch");
305
0
  if (loadNumber(S) != LUAC_NUM)
306
0
    error(S, "float format mismatch");
307
0
}
308
309
310
/*
311
** Load precompiled chunk.
312
*/
313
0
LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
314
0
  LoadState S;
315
0
  LClosure *cl;
316
0
  if (*name == '@' || *name == '=')
317
0
    S.name = name + 1;
318
0
  else if (*name == LUA_SIGNATURE[0])
319
0
    S.name = "binary string";
320
0
  else
321
0
    S.name = name;
322
0
  S.L = L;
323
0
  S.Z = Z;
324
0
  checkHeader(&S);
325
0
  cl = luaF_newLclosure(L, loadByte(&S));
326
0
  setclLvalue2s(L, L->top.p, cl);
327
0
  luaD_inctop(L);
328
0
  cl->p = luaF_newproto(L);
329
0
  luaC_objbarrier(L, cl, cl->p);
330
0
  loadFunction(&S, cl->p, NULL);
331
0
  lua_assert(cl->nupvalues == cl->p->sizeupvalues);
332
0
  luai_verifycode(L, cl->p);
333
0
  return cl;
334
0
}
335