Coverage Report

Created: 2024-04-23 06:32

/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 "ltable.h"
25
#include "lundump.h"
26
#include "lzio.h"
27
28
29
#if !defined(luai_verifycode)
30
#define luai_verifycode(L,f)  /* empty */
31
#endif
32
33
34
typedef struct {
35
  lua_State *L;
36
  ZIO *Z;
37
  const char *name;
38
  Table *h;  /* list for string reuse */
39
  lu_mem offset;  /* current position relative to beginning of dump */
40
  lua_Integer nstr;  /* number of strings in the list */
41
  lu_byte fixed;  /* dump is fixed in memory */
42
} LoadState;
43
44
45
50.2k
static l_noret error (LoadState *S, const char *why) {
46
50.2k
  luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why);
47
50.2k
  luaD_throw(S->L, LUA_ERRSYNTAX);
48
50.2k
}
49
50
51
/*
52
** All high-level loads go through loadVector; you can change it to
53
** adapt to the endianness of the input
54
*/
55
348k
#define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0]))
56
57
402k
static void loadBlock (LoadState *S, void *b, size_t size) {
58
402k
  if (luaZ_read(S->Z, b, size) != 0)
59
676
    error(S, "truncated chunk");
60
401k
  S->offset += size;
61
401k
}
62
63
64
69.5k
static void loadAlign (LoadState *S, int align) {
65
69.5k
  int padding = align - (S->offset % align);
66
69.5k
  if (padding < align) {  /* apd == align means no padding */
67
53.1k
    lua_Integer paddingContent;
68
53.1k
    loadBlock(S, &paddingContent, padding);
69
53.1k
    lua_assert(S->offset % align == 0);
70
53.1k
  }
71
69.5k
}
72
73
74
0
#define getaddr(S,n,t)  cast(t *, getaddr_(S,(n) * sizeof(t)))
75
76
0
static const void *getaddr_ (LoadState *S, size_t size) {
77
0
  const void *block = luaZ_getaddr(S->Z, size);
78
0
  S->offset += size;
79
0
  if (block == NULL)
80
0
    error(S, "truncated fixed buffer");
81
0
  return block;
82
0
}
83
84
85
5.79k
#define loadVar(S,x)    loadVector(S,&x,1)
86
87
88
2.70M
static lu_byte loadByte (LoadState *S) {
89
2.70M
  int b = zgetc(S->Z);
90
2.70M
  if (b == EOZ)
91
5.67k
    error(S, "truncated chunk");
92
2.70M
  S->offset++;
93
2.70M
  return cast_byte(b);
94
2.70M
}
95
96
97
1.77M
static size_t loadVarint (LoadState *S, size_t limit) {
98
1.77M
  size_t x = 0;
99
1.77M
  int b;
100
1.77M
  limit >>= 7;
101
2.07M
  do {
102
2.07M
    b = loadByte(S);
103
2.07M
    if (x > limit)
104
0
      error(S, "integer overflow");
105
2.07M
    x = (x << 7) | (b & 0x7f);
106
2.07M
  } while ((b & 0x80) != 0);
107
1.77M
  return x;
108
1.77M
}
109
110
111
787k
static size_t loadSize (LoadState *S) {
112
787k
  return loadVarint(S, MAX_SIZET);
113
787k
}
114
115
116
987k
static int loadInt (LoadState *S) {
117
987k
  return cast_int(loadVarint(S, cast_sizet(INT_MAX)));
118
987k
}
119
120
121
2.69k
static lua_Number loadNumber (LoadState *S) {
122
2.69k
  lua_Number x;
123
2.69k
  loadVar(S, x);
124
2.69k
  return x;
125
2.69k
}
126
127
128
3.09k
static lua_Integer loadInteger (LoadState *S) {
129
3.09k
  lua_Integer x;
130
3.09k
  loadVar(S, x);
131
3.09k
  return x;
132
3.09k
}
133
134
135
/*
136
** Load a nullable string into slot 'sl' from prototype 'p'. The
137
** assignment to the slot and the barrier must be performed before any
138
** possible GC activity, to anchor the string. (Both 'loadVector' and
139
** 'luaH_setint' can call the GC.)
140
*/
141
466k
static void loadString (LoadState *S, Proto *p, TString **sl) {
142
466k
  lua_State *L = S->L;
143
466k
  TString *ts;
144
466k
  TValue sv;
145
466k
  size_t size = loadSize(S);
146
466k
  if (size == 0) {  /* no string? */
147
0
    lua_assert(*sl == NULL);  /* must be prefilled */
148
0
    return;
149
0
  }
150
466k
  else if (size == 1) {  /* previously saved string? */
151
321k
    lua_Integer idx = cast(lua_Integer, loadSize(S));  /* get its index */
152
321k
    TValue stv;
153
321k
    luaH_getint(S->h, idx, &stv);  /* get its value */
154
321k
    *sl = ts = tsvalue(&stv);
155
321k
    luaC_objbarrier(L, p, ts);
156
0
    return;  /* do not save it again */
157
321k
  }
158
144k
  else if ((size -= 2) <= LUAI_MAXSHORTLEN) {  /* short string? */
159
143k
    char buff[LUAI_MAXSHORTLEN + 1];  /* extra space for '\0' */
160
143k
    loadVector(S, buff, size + 1);  /* load string into buffer */
161
143k
    *sl = ts = luaS_newlstr(L, buff, size);  /* create string */
162
143k
    luaC_objbarrier(L, p, ts);
163
143k
  }
164
1.58k
  else if (S->fixed) {  /* for a fixed buffer, use a fixed string */
165
0
    const char *s = getaddr(S, size + 1, char);  /* get content address */
166
0
    *sl = ts = luaS_newextlstr(L, s, size, NULL, NULL);
167
0
    luaC_objbarrier(L, p, ts);
168
0
  }
169
1.58k
  else {  /* create internal copy */
170
1.58k
    *sl = ts = luaS_createlngstrobj(L, size);  /* create string */
171
1.58k
    luaC_objbarrier(L, p, ts);
172
1.58k
    loadVector(S, getlngstr(ts), size + 1);  /* load directly in final place */
173
1.58k
  }
174
  /* add string to list of saved strings */
175
143k
  S->nstr++;
176
144k
  setsvalue(L, &sv, ts);
177
144k
  luaH_setint(L, S->h, S->nstr, &sv);
178
144k
  luaC_objbarrierback(L, obj2gco(S->h), ts);
179
144k
}
180
181
182
67.6k
static void loadCode (LoadState *S, Proto *f) {
183
67.6k
  int n = loadInt(S);
184
67.6k
  loadAlign(S, sizeof(f->code[0]));
185
67.6k
  if (S->fixed) {
186
0
    f->code = getaddr(S, n, Instruction);
187
0
    f->sizecode = n;
188
0
  }
189
67.6k
  else {
190
67.6k
    f->code = luaM_newvectorchecked(S->L, n, Instruction);
191
0
    f->sizecode = n;
192
67.6k
    loadVector(S, f->code, n);
193
67.6k
  }
194
67.6k
}
195
196
197
static void loadFunction(LoadState *S, Proto *f);
198
199
200
67.6k
static void loadConstants (LoadState *S, Proto *f) {
201
67.6k
  int i;
202
67.6k
  int n = loadInt(S);
203
67.6k
  f->k = luaM_newvectorchecked(S->L, n, TValue);
204
0
  f->sizek = n;
205
248k
  for (i = 0; i < n; i++)
206
180k
    setnilvalue(&f->k[i]);
207
248k
  for (i = 0; i < n; i++) {
208
180k
    TValue *o = &f->k[i];
209
180k
    int t = loadByte(S);
210
180k
    switch (t) {
211
3.36k
      case LUA_VNIL:
212
3.36k
        setnilvalue(o);
213
3.36k
        break;
214
159
      case LUA_VFALSE:
215
159
        setbfvalue(o);
216
159
        break;
217
125
      case LUA_VTRUE:
218
125
        setbtvalue(o);
219
125
        break;
220
1.10k
      case LUA_VNUMFLT:
221
1.10k
        setfltvalue(o, loadNumber(S));
222
1.10k
        break;
223
1.39k
      case LUA_VNUMINT:
224
1.39k
        setivalue(o, loadInteger(S));
225
1.39k
        break;
226
174k
      case LUA_VSHRSTR:
227
174k
      case LUA_VLNGSTR: {
228
174k
        lua_assert(f->source == NULL);
229
174k
        loadString(S, f, &f->source);  /* use 'source' to anchor string */
230
174k
        if (f->source == NULL)
231
0
          error(S, "bad format for constant string");
232
174k
        setsvalue2n(S->L, o, f->source);  /* save it in the right place */
233
174k
        f->source = NULL;
234
174k
        break;
235
174k
      }
236
0
      default: lua_assert(0);
237
180k
    }
238
180k
  }
239
67.6k
}
240
241
242
67.6k
static void loadProtos (LoadState *S, Proto *f) {
243
67.6k
  int i;
244
67.6k
  int n = loadInt(S);
245
67.6k
  f->p = luaM_newvectorchecked(S->L, n, Proto *);
246
0
  f->sizep = n;
247
133k
  for (i = 0; i < n; i++)
248
66.1k
    f->p[i] = NULL;
249
133k
  for (i = 0; i < n; i++) {
250
66.1k
    f->p[i] = luaF_newproto(S->L);
251
66.1k
    luaC_objbarrier(S->L, f, f->p[i]);
252
0
    loadFunction(S, f->p[i]);
253
66.1k
  }
254
67.6k
}
255
256
257
/*
258
** Load the upvalues for a function. The names must be filled first,
259
** because the filling of the other fields can raise read errors and
260
** the creation of the error message can call an emergency collection;
261
** in that case all prototypes must be consistent for the GC.
262
*/
263
67.6k
static void loadUpvalues (LoadState *S, Proto *f) {
264
67.6k
  int i, n;
265
67.6k
  n = loadInt(S);
266
67.6k
  f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc);
267
0
  f->sizeupvalues = n;
268
136k
  for (i = 0; i < n; i++)  /* make array valid for GC */
269
68.7k
    f->upvalues[i].name = NULL;
270
136k
  for (i = 0; i < n; i++) {  /* following calls can raise errors */
271
68.7k
    f->upvalues[i].instack = loadByte(S);
272
68.7k
    f->upvalues[i].idx = loadByte(S);
273
68.7k
    f->upvalues[i].kind = loadByte(S);
274
68.7k
  }
275
67.6k
}
276
277
278
67.6k
static void loadDebug (LoadState *S, Proto *f) {
279
67.6k
  int i, n;
280
67.6k
  n = loadInt(S);
281
67.6k
  if (S->fixed) {
282
0
    f->lineinfo = getaddr(S, n, ls_byte);
283
0
    f->sizelineinfo = n;
284
0
  }
285
67.6k
  else {
286
67.6k
    f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte);
287
0
    f->sizelineinfo = n;
288
67.6k
    loadVector(S, f->lineinfo, n);
289
67.6k
  }
290
0
  n = loadInt(S);
291
67.6k
  if (n > 0) {
292
1.84k
    loadAlign(S, sizeof(int));
293
1.84k
    if (S->fixed) {
294
0
      f->abslineinfo = getaddr(S, n, AbsLineInfo);
295
0
      f->sizeabslineinfo = n;
296
0
    }
297
1.84k
    else {
298
1.84k
      f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo);
299
0
      f->sizeabslineinfo = n;
300
1.84k
      loadVector(S, f->abslineinfo, n);
301
1.84k
    }
302
1.84k
  }
303
0
  n = loadInt(S);
304
67.6k
  f->locvars = luaM_newvectorchecked(S->L, n, LocVar);
305
0
  f->sizelocvars = n;
306
223k
  for (i = 0; i < n; i++)
307
155k
    f->locvars[i].varname = NULL;
308
223k
  for (i = 0; i < n; i++) {
309
155k
    loadString(S, f, &f->locvars[i].varname);
310
155k
    f->locvars[i].startpc = loadInt(S);
311
155k
    f->locvars[i].endpc = loadInt(S);
312
155k
  }
313
67.6k
  n = loadInt(S);
314
67.6k
  if (n != 0)  /* does it have debug information? */
315
58.1k
    n = f->sizeupvalues;  /* must be this many */
316
136k
  for (i = 0; i < n; i++)
317
68.7k
    loadString(S, f, &f->upvalues[i].name);
318
67.6k
}
319
320
321
67.6k
static void loadFunction (LoadState *S, Proto *f) {
322
67.6k
  f->linedefined = loadInt(S);
323
67.6k
  f->lastlinedefined = loadInt(S);
324
67.6k
  f->numparams = loadByte(S);
325
67.6k
  f->flag = loadByte(S) & PF_ISVARARG;  /* get only the meaningful flags */
326
67.6k
  if (S->fixed)
327
0
    f->flag |= PF_FIXED;  /* signal that code is fixed */
328
67.6k
  f->maxstacksize = loadByte(S);
329
67.6k
  loadCode(S, f);
330
67.6k
  loadConstants(S, f);
331
67.6k
  loadUpvalues(S, f);
332
67.6k
  loadProtos(S, f);
333
67.6k
  loadString(S, f, &f->source);
334
67.6k
  loadDebug(S, f);
335
67.6k
}
336
337
338
61.2k
static void checkliteral (LoadState *S, const char *s, const char *msg) {
339
61.2k
  char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
340
61.2k
  size_t len = strlen(s);
341
61.2k
  loadVector(S, buff, len);
342
61.2k
  if (memcmp(s, buff, len) != 0)
343
40.3k
    error(S, msg);
344
61.2k
}
345
346
347
5.22k
static void fchecksize (LoadState *S, size_t size, const char *tname) {
348
5.22k
  if (loadByte(S) != size)
349
53
    error(S, luaO_pushfstring(S->L, "%s size mismatch", tname));
350
5.22k
}
351
352
353
145k
#define checksize(S,t)  fchecksize(S,sizeof(t),#t)
354
355
51.8k
static void checkHeader (LoadState *S) {
356
  /* skip 1st char (already read and checked) */
357
51.8k
  checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk");
358
51.8k
  if (loadByte(S) != LUAC_VERSION)
359
605
    error(S, "version mismatch");
360
51.2k
  if (loadByte(S) != LUAC_FORMAT)
361
2.81k
    error(S, "format mismatch");
362
48.4k
  checkliteral(S, LUAC_DATA, "corrupted chunk");
363
48.4k
  checksize(S, Instruction);
364
48.4k
  checksize(S, lua_Integer);
365
48.4k
  checksize(S, lua_Number);
366
48.4k
  if (loadInteger(S) != LUAC_INT)
367
104
    error(S, "integer format mismatch");
368
48.3k
  if (loadNumber(S) != LUAC_NUM)
369
1
    error(S, "float format mismatch");
370
48.3k
}
371
372
373
/*
374
** Load precompiled chunk.
375
*/
376
51.8k
LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) {
377
51.8k
  LoadState S;
378
51.8k
  LClosure *cl;
379
51.8k
  if (*name == '@' || *name == '=')
380
0
    S.name = name + 1;
381
51.8k
  else if (*name == LUA_SIGNATURE[0])
382
50.0k
    S.name = "binary string";
383
1.86k
  else
384
1.86k
    S.name = name;
385
51.8k
  S.L = L;
386
51.8k
  S.Z = Z;
387
51.8k
  S.fixed = fixed;
388
51.8k
  S.offset = 1;  /* fist byte was already read */
389
51.8k
  checkHeader(&S);
390
51.8k
  cl = luaF_newLclosure(L, loadByte(&S));
391
51.8k
  setclLvalue2s(L, L->top.p, cl);
392
1.58k
  luaD_inctop(L);
393
1.58k
  S.h = luaH_new(L);  /* create list of saved strings */
394
1.58k
  S.nstr = 0;
395
1.58k
  sethvalue2s(L, L->top.p, S.h);  /* anchor it */
396
1.58k
  luaD_inctop(L);
397
1.58k
  cl->p = luaF_newproto(L);
398
1.58k
  luaC_objbarrier(L, cl, cl->p);
399
0
  loadFunction(&S, cl->p);
400
1.58k
  lua_assert(cl->nupvalues == cl->p->sizeupvalues);
401
1.58k
  luai_verifycode(L, cl->p);
402
1.58k
  L->top.p--;  /* pop table */
403
1.58k
  return cl;
404
1.58k
}
405