• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 5784751762

07 Aug 2023 11:54AM UTC coverage: 84.282% (-3.1%) from 87.373%
5784751762

push

github

ligurio
setup-gcovr [TO SQUASH]

5157 of 6002 branches covered (85.92%)

Branch coverage included in aggregate %.

19632 of 23410 relevant lines covered (83.86%)

229380.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.75
/src/lj_bcread.c
1
/*
2
** Bytecode reader.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
*/
5

6
#define lj_bcread_c
7
#define LUA_CORE
8

9
#include "lj_obj.h"
10
#include "lj_gc.h"
11
#include "lj_err.h"
12
#include "lj_buf.h"
13
#include "lj_str.h"
14
#include "lj_tab.h"
15
#include "lj_bc.h"
16
#if LJ_HASFFI
17
#include "lj_ctype.h"
18
#include "lj_cdata.h"
19
#include "lualib.h"
20
#endif
21
#include "lj_lex.h"
22
#include "lj_bcdump.h"
23
#include "lj_state.h"
24
#include "lj_strfmt.h"
25
#if LJ_HASMEMPROF
26
#include "lj_memprof.h"
27
#endif
28
#if LJ_HASSYSPROF
29
#include "lj_sysprof.h"
30
#endif
31

32
/* Reuse some lexer fields for our own purposes. */
33
#define bcread_flags(ls)        ls->level
34
#define bcread_swap(ls) \
35
  ((bcread_flags(ls) & BCDUMP_F_BE) != LJ_BE*BCDUMP_F_BE)
36
#define bcread_oldtop(L, ls)        restorestack(L, ls->lastline)
37
#define bcread_savetop(L, ls, top) \
38
  ls->lastline = (BCLine)savestack(L, (top))
39

40
/* -- Input buffer handling ----------------------------------------------- */
41

42
/* Throw reader error. */
43
static LJ_NOINLINE void bcread_error(LexState *ls, ErrMsg em)
44
{
45
  lua_State *L = ls->L;
46
  const char *name = ls->chunkarg;
47
  if (*name == BCDUMP_HEAD1) name = "(binary)";
48
  else if (*name == '@' || *name == '=') name++;
49
  lj_strfmt_pushf(L, "%s: %s", name, err2msg(em));
50
  lj_err_throw(L, LUA_ERRSYNTAX);
51
}
52

53
/* Refill buffer. */
54
static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
×
55
{
56
  lua_assert(len != 0);
×
57
  if (len > LJ_MAX_BUF || ls->c < 0)
×
58
    bcread_error(ls, LJ_ERR_BCBAD);
×
59
  do {
×
60
    const char *buf;
×
61
    size_t sz;
×
62
    char *p = sbufB(&ls->sb);
×
63
    MSize n = (MSize)(ls->pe - ls->p);
×
64
    if (n) {  /* Copy remainder to buffer. */
×
65
      if (sbuflen(&ls->sb)) {  /* Move down in buffer. */
×
66
        lua_assert(ls->pe == sbufP(&ls->sb));
×
67
        if (ls->p != p) memmove(p, ls->p, n);
×
68
      } else {  /* Copy from buffer provided by reader. */
69
        p = lj_buf_need(&ls->sb, len);
×
70
        memcpy(p, ls->p, n);
×
71
      }
72
      ls->p = p;
×
73
      ls->pe = p + n;
×
74
    }
75
    setsbufP(&ls->sb, p + n);
×
76
    buf = ls->rfunc(ls->L, ls->rdata, &sz);  /* Get more data from reader. */
×
77
    if (buf == NULL || sz == 0) {  /* EOF? */
×
78
      if (need) bcread_error(ls, LJ_ERR_BCBAD);
×
79
      ls->c = -1;  /* Only bad if we get called again. */
×
80
      break;
×
81
    }
82
    if (n) {  /* Append to buffer. */
×
83
      n += (MSize)sz;
×
84
      p = lj_buf_need(&ls->sb, n < len ? len : n);
×
85
      memcpy(sbufP(&ls->sb), buf, sz);
×
86
      setsbufP(&ls->sb, p + n);
×
87
      ls->p = p;
×
88
      ls->pe = p + n;
×
89
    } else {  /* Return buffer provided by reader. */
90
      ls->p = buf;
×
91
      ls->pe = buf + sz;
×
92
    }
93
  } while (ls->p + len > ls->pe);
×
94
}
×
95

96
/* Need a certain number of bytes. */
97
static LJ_AINLINE void bcread_need(LexState *ls, MSize len)
26✔
98
{
99
  if (LJ_UNLIKELY(ls->p + len > ls->pe))
26✔
100
    bcread_fill(ls, len, 1);
×
101
}
102

103
/* Want to read up to a certain number of bytes, but may need less. */
104
static LJ_AINLINE void bcread_want(LexState *ls, MSize len)
32✔
105
{
106
  if (LJ_UNLIKELY(ls->p + len > ls->pe))
32✔
107
    bcread_fill(ls, len, 0);
×
108
}
109

110
/* Return memory block from buffer. */
111
static LJ_AINLINE uint8_t *bcread_mem(LexState *ls, MSize len)
1,755✔
112
{
113
  uint8_t *p = (uint8_t *)ls->p;
1,755✔
114
  ls->p += len;
1,755✔
115
  lua_assert(ls->p <= ls->pe);
1,755✔
116
  return p;
1,755✔
117
}
118

119
/* Copy memory block from buffer. */
120
static void bcread_block(LexState *ls, void *q, MSize len)
1,745✔
121
{
122
  memcpy(q, bcread_mem(ls, len), len);
1,745✔
123
}
124

125
/* Read byte from buffer. */
126
static LJ_AINLINE uint32_t bcread_byte(LexState *ls)
1,784✔
127
{
128
  lua_assert(ls->p < ls->pe);
1,784✔
129
  return (uint32_t)(uint8_t)*ls->p++;
1,784✔
130
}
131

132
/* Read ULEB128 value from buffer. */
133
static LJ_AINLINE uint32_t bcread_uleb128(LexState *ls)
5,278✔
134
{
135
  uint32_t v = lj_buf_ruleb128(&ls->p);
7,075✔
136
  lua_assert(ls->p <= ls->pe);
5,278✔
137
  return v;
5,278✔
138
}
139

140
/* Read top 32 bits of 33 bit ULEB128 value from buffer. */
141
static uint32_t bcread_uleb128_33(LexState *ls)
142
{
143
  const uint8_t *p = (const uint8_t *)ls->p;
144
  uint32_t v = (*p++ >> 1);
145
  if (LJ_UNLIKELY(v >= 0x40)) {
146
    int sh = -1;
147
    v &= 0x3f;
148
    do {
149
     v |= ((*p & 0x7f) << (sh += 7));
150
   } while (*p++ >= 0x80);
151
  }
152
  ls->p = (char *)p;
153
  lua_assert(ls->p <= ls->pe);
154
  return v;
155
}
156

157
/* -- Bytecode reader ----------------------------------------------------- */
158

159
/* Read debug info of a prototype. */
160
static void bcread_dbg(LexState *ls, GCproto *pt, MSize sizedbg)
9✔
161
{
162
  void *lineinfo = (void *)proto_lineinfo(pt);
9✔
163
  bcread_block(ls, lineinfo, sizedbg);
9✔
164
  /* Swap lineinfo if the endianess differs. */
165
  if (bcread_swap(ls) && pt->numline >= 256) {
9✔
166
    MSize i, n = pt->sizebc-1;
×
167
    if (pt->numline < 65536) {
×
168
      uint16_t *p = (uint16_t *)lineinfo;
×
169
      for (i = 0; i < n; i++) p[i] = (uint16_t)((p[i] >> 8)|(p[i] << 8));
×
170
    } else {
171
      uint32_t *p = (uint32_t *)lineinfo;
×
172
      for (i = 0; i < n; i++) p[i] = lj_bswap(p[i]);
×
173
    }
174
  }
175
}
9✔
176

177
/* Find pointer to varinfo. */
178
static const void *bcread_varinfo(GCproto *pt)
9✔
179
{
180
  const uint8_t *p = proto_uvinfo(pt);
9✔
181
  MSize n = pt->sizeuv;
9✔
182
  if (n) while (*p++ || --n) ;
9✔
183
  return p;
9✔
184
}
185

186
/* Read a single constant key/value of a template table. */
187
static void bcread_ktabk(LexState *ls, TValue *o)
×
188
{
189
  MSize tp = bcread_uleb128(ls);
×
190
  if (tp >= BCDUMP_KTAB_STR) {
×
191
    MSize len = tp - BCDUMP_KTAB_STR;
×
192
    const char *p = (const char *)bcread_mem(ls, len);
×
193
    setstrV(ls->L, o, lj_str_new(ls->L, p, len));
×
194
  } else if (tp == BCDUMP_KTAB_INT) {
×
195
    setintV(o, (int32_t)bcread_uleb128(ls));
×
196
  } else if (tp == BCDUMP_KTAB_NUM) {
×
197
    o->u32.lo = bcread_uleb128(ls);
×
198
    o->u32.hi = bcread_uleb128(ls);
×
199
  } else {
200
    lua_assert(tp <= BCDUMP_KTAB_TRUE);
×
201
    setpriV(o, ~tp);
×
202
  }
203
}
×
204

205
/* Read a template table. */
206
static GCtab *bcread_ktab(LexState *ls)
×
207
{
208
  MSize narray = bcread_uleb128(ls);
×
209
  MSize nhash = bcread_uleb128(ls);
×
210
  GCtab *t = lj_tab_new(ls->L, narray, hsize2hbits(nhash));
×
211
  if (narray) {  /* Read array entries. */
×
212
    MSize i;
×
213
    TValue *o = tvref(t->array);
×
214
    for (i = 0; i < narray; i++, o++)
×
215
      bcread_ktabk(ls, o);
×
216
  }
217
  if (nhash) {  /* Read hash entries. */
×
218
    MSize i;
219
    for (i = 0; i < nhash; i++) {
×
220
      TValue key;
×
221
      bcread_ktabk(ls, &key);
×
222
      lua_assert(!tvisnil(&key));
×
223
      bcread_ktabk(ls, lj_tab_set(ls->L, t, &key));
×
224
    }
225
  }
226
  return t;
×
227
}
228

229
/* Read GC constants of a prototype. */
230
static void bcread_kgc(LexState *ls, GCproto *pt, MSize sizekgc)
231
{
232
  MSize i;
233
  GCRef *kr = mref(pt->k, GCRef) - (ptrdiff_t)sizekgc;
234
  for (i = 0; i < sizekgc; i++, kr++) {
235
    MSize tp = bcread_uleb128(ls);
236
    if (tp >= BCDUMP_KGC_STR) {
237
      MSize len = tp - BCDUMP_KGC_STR;
238
      const char *p = (const char *)bcread_mem(ls, len);
239
      setgcref(*kr, obj2gco(lj_str_new(ls->L, p, len)));
240
    } else if (tp == BCDUMP_KGC_TAB) {
241
      setgcref(*kr, obj2gco(bcread_ktab(ls)));
242
#if LJ_HASFFI
243
    } else if (tp != BCDUMP_KGC_CHILD) {
244
      CTypeID id = tp == BCDUMP_KGC_COMPLEX ? CTID_COMPLEX_DOUBLE :
245
                   tp == BCDUMP_KGC_I64 ? CTID_INT64 : CTID_UINT64;
246
      CTSize sz = tp == BCDUMP_KGC_COMPLEX ? 16 : 8;
247
      GCcdata *cd = lj_cdata_new_(ls->L, id, sz);
248
      TValue *p = (TValue *)cdataptr(cd);
249
      setgcref(*kr, obj2gco(cd));
250
      p[0].u32.lo = bcread_uleb128(ls);
251
      p[0].u32.hi = bcread_uleb128(ls);
252
      if (tp == BCDUMP_KGC_COMPLEX) {
253
        p[1].u32.lo = bcread_uleb128(ls);
254
        p[1].u32.hi = bcread_uleb128(ls);
255
      }
256
#endif
257
    } else {
258
      lua_State *L = ls->L;
259
      lua_assert(tp == BCDUMP_KGC_CHILD);
260
      if (L->top <= bcread_oldtop(L, ls))  /* Stack underflow? */
261
        bcread_error(ls, LJ_ERR_BCBAD);
262
      L->top--;
263
      setgcref(*kr, obj2gco(protoV(L->top)));
264
    }
265
  }
266
}
267

268
/* Read number constants of a prototype. */
269
static void bcread_knum(LexState *ls, GCproto *pt, MSize sizekn)
270
{
271
  MSize i;
272
  TValue *o = mref(pt->k, TValue);
273
  for (i = 0; i < sizekn; i++, o++) {
274
    int isnum = (ls->p[0] & 1);
275
    uint32_t lo = bcread_uleb128_33(ls);
276
    if (isnum) {
277
      o->u32.lo = lo;
278
      o->u32.hi = bcread_uleb128(ls);
279
    } else {
280
      setintV(o, lo);
281
    }
282
  }
283
}
284

285
/* Read bytecode instructions. */
286
static void bcread_bytecode(LexState *ls, GCproto *pt, MSize sizebc)
1,736✔
287
{
288
  BCIns *bc = proto_bc(pt);
1,736✔
289
  bc[0] = BCINS_AD((pt->flags & PROTO_VARARG) ? BC_FUNCV : BC_FUNCF,
1,736✔
290
                   pt->framesize, 0);
291
  bcread_block(ls, bc+1, (sizebc-1)*(MSize)sizeof(BCIns));
1,736✔
292
  /* Swap bytecode instructions if the endianess differs. */
293
  if (bcread_swap(ls)) {
1,736✔
294
    MSize i;
295
    for (i = 1; i < sizebc; i++) bc[i] = lj_bswap(bc[i]);
×
296
  }
297
}
1,736✔
298

299
/* Read upvalue refs. */
300
static void bcread_uv(LexState *ls, GCproto *pt, MSize sizeuv)
301
{
302
  if (sizeuv) {
303
    uint16_t *uv = proto_uv(pt);
304
    bcread_block(ls, uv, sizeuv*2);
305
    /* Swap upvalue refs if the endianess differs. */
306
    if (bcread_swap(ls)) {
307
      MSize i;
308
      for (i = 0; i < sizeuv; i++)
309
        uv[i] = (uint16_t)((uv[i] >> 8)|(uv[i] << 8));
310
    }
311
  }
312
}
313

314
/* Read a prototype. */
315
GCproto *lj_bcread_proto(LexState *ls)
1,736✔
316
{
317
  GCproto *pt;
1,736✔
318
  MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept;
1,736✔
319
  MSize ofsk, ofsuv, ofsdbg;
1,736✔
320
  MSize sizedbg = 0;
1,736✔
321
  BCLine firstline = 0, numline = 0;
1,736✔
322

323
  /* Read prototype header. */
324
  flags = bcread_byte(ls);
1,736✔
325
  numparams = bcread_byte(ls);
1,736✔
326
  framesize = bcread_byte(ls);
1,736✔
327
  sizeuv = bcread_byte(ls);
1,736✔
328
  sizekgc = bcread_uleb128(ls);
1,736✔
329
  sizekn = bcread_uleb128(ls);
1,736✔
330
  sizebc = bcread_uleb128(ls) + 1;
1,736✔
331
  if (!(bcread_flags(ls) & BCDUMP_F_STRIP)) {
1,736✔
332
    sizedbg = bcread_uleb128(ls);
10✔
333
    if (sizedbg) {
10✔
334
      firstline = bcread_uleb128(ls);
9✔
335
      numline = bcread_uleb128(ls);
9✔
336
    }
337
  }
338

339
  /* Calculate total size of prototype including all colocated arrays. */
340
  sizept = (MSize)sizeof(GCproto) +
1,736✔
341
           sizebc*(MSize)sizeof(BCIns) +
1,736✔
342
           sizekgc*(MSize)sizeof(GCRef);
343
  sizept = (sizept + (MSize)sizeof(TValue)-1) & ~((MSize)sizeof(TValue)-1);
1,736✔
344
  ofsk = sizept; sizept += sizekn*(MSize)sizeof(TValue);
1,736✔
345
  ofsuv = sizept; sizept += ((sizeuv+1)&~1)*2;
1,736✔
346
  ofsdbg = sizept; sizept += sizedbg;
1,736✔
347

348
  /* Allocate prototype object and initialize its fields. */
349
  pt = (GCproto *)lj_mem_newgco(ls->L, (MSize)sizept);
1,736✔
350
  pt->gct = ~LJ_TPROTO;
1,736✔
351
  pt->numparams = (uint8_t)numparams;
1,736✔
352
  pt->framesize = (uint8_t)framesize;
1,736✔
353
  pt->sizebc = sizebc;
1,736✔
354
  setmref(pt->k, (char *)pt + ofsk);
1,736✔
355
  setmref(pt->uv, (char *)pt + ofsuv);
1,736✔
356
  pt->sizekgc = 0;  /* Set to zero until fully initialized. */
1,736✔
357
  pt->sizekn = sizekn;
1,736✔
358
  pt->sizept = sizept;
1,736✔
359
  pt->sizeuv = (uint8_t)sizeuv;
1,736✔
360
  pt->flags = (uint8_t)flags;
1,736✔
361
  pt->trace = 0;
1,736✔
362
  setgcref(pt->chunkname, obj2gco(ls->chunkname));
1,736✔
363

364
  /* Close potentially uninitialized gap between bc and kgc. */
365
  *(uint32_t *)((char *)pt + ofsk - sizeof(GCRef)*(sizekgc+1)) = 0;
1,736✔
366

367
  /* Read bytecode instructions and upvalue refs. */
368
  bcread_bytecode(ls, pt, sizebc);
1,736✔
369
  bcread_uv(ls, pt, sizeuv);
1,736✔
370

371
  /* Read constants. */
372
  bcread_kgc(ls, pt, sizekgc);
1,736✔
373
  pt->sizekgc = sizekgc;
1,736✔
374
  bcread_knum(ls, pt, sizekn);
1,736✔
375

376
  /* Read and initialize debug info. */
377
  pt->firstline = firstline;
1,736✔
378
  pt->numline = numline;
1,736✔
379
  if (sizedbg) {
1,736✔
380
    MSize sizeli = (sizebc-1) << (numline < 256 ? 0 : numline < 65536 ? 1 : 2);
9✔
381
    setmref(pt->lineinfo, (char *)pt + ofsdbg);
9✔
382
    setmref(pt->uvinfo, (char *)pt + ofsdbg + sizeli);
9✔
383
    bcread_dbg(ls, pt, sizedbg);
9✔
384
    setmref(pt->varinfo, bcread_varinfo(pt));
12✔
385
  } else {
386
    setmref(pt->lineinfo, NULL);
1,727✔
387
    setmref(pt->uvinfo, NULL);
1,727✔
388
    setmref(pt->varinfo, NULL);
1,727✔
389
  }
390

391
  /* Add a new prototype to the profiler. */
392
#if LJ_HASMEMPROF
393
  lj_memprof_add_proto(pt);
1,736✔
394
#endif
395

396
#if LJ_HASSYSPROF
397
  lj_sysprof_add_proto(pt);
1,736✔
398
#endif
399

400
  return pt;
1,736✔
401
}
402

403
/* Read and check header of bytecode dump. */
404
static int bcread_header(LexState *ls)
16✔
405
{
406
  uint32_t flags;
16✔
407
  bcread_want(ls, 3+5+5);
16✔
408
  if (bcread_byte(ls) != BCDUMP_HEAD2 ||
16✔
409
      bcread_byte(ls) != BCDUMP_HEAD3 ||
16✔
410
      bcread_byte(ls) != BCDUMP_VERSION) return 0;
16✔
411
  bcread_flags(ls) = flags = bcread_uleb128(ls);
16✔
412
  if ((flags & ~(BCDUMP_F_KNOWN)) != 0) return 0;
16✔
413
  if ((flags & BCDUMP_F_FR2) != LJ_FR2*BCDUMP_F_FR2) return 0;
16✔
414
  if ((flags & BCDUMP_F_FFI)) {
16✔
415
#if LJ_HASFFI
416
    lua_State *L = ls->L;
×
417
    if (!ctype_ctsG(G(L))) {
×
418
      ptrdiff_t oldtop = savestack(L, L->top);
×
419
      luaopen_ffi(L);  /* Load FFI library on-demand. */
×
420
      L->top = restorestack(L, oldtop);
×
421
    }
422
#else
423
    return 0;
424
#endif
425
  }
426
  if ((flags & BCDUMP_F_STRIP)) {
16✔
427
    ls->chunkname = lj_str_newz(ls->L, ls->chunkarg);
6✔
428
  } else {
429
    MSize len = bcread_uleb128(ls);
10✔
430
    bcread_need(ls, len);
10✔
431
    ls->chunkname = lj_str_new(ls->L, (const char *)bcread_mem(ls, len), len);
10✔
432
  }
433
  return 1;  /* Ok. */
434
}
435

436
/* Read a bytecode dump. */
437
GCproto *lj_bcread(LexState *ls)
16✔
438
{
439
  lua_State *L = ls->L;
16✔
440
  lua_assert(ls->c == BCDUMP_HEAD1);
16✔
441
  bcread_savetop(L, ls, L->top);
16✔
442
  lj_buf_reset(&ls->sb);
16✔
443
  /* Check for a valid bytecode dump header. */
444
  if (!bcread_header(ls))
16✔
445
    bcread_error(ls, LJ_ERR_BCFMT);
×
446
  for (;;) {  /* Process all prototypes in the bytecode dump. */
32✔
447
    GCproto *pt;
32✔
448
    MSize len;
32✔
449
    const char *startp;
32✔
450
    /* Read length. */
451
    if (ls->p < ls->pe && ls->p[0] == 0) {  /* Shortcut EOF. */
32✔
452
      ls->p++;
16✔
453
      break;
16✔
454
    }
455
    bcread_want(ls, 5);
16✔
456
    len = bcread_uleb128(ls);
16✔
457
    if (!len) break;  /* EOF */
16✔
458
    bcread_need(ls, len);
16✔
459
    startp = ls->p;
16✔
460
    pt = lj_bcread_proto(ls);
16✔
461
    if (ls->p != startp + len)
16✔
462
      bcread_error(ls, LJ_ERR_BCBAD);
×
463
    setprotoV(L, L->top, pt);
16✔
464
    incr_top(L);
16✔
465
  }
466
  if ((int32_t)(2*(uint32_t)(ls->pe - ls->p)) > 0 ||
16✔
467
      L->top-1 != bcread_oldtop(L, ls))
16✔
468
    bcread_error(ls, LJ_ERR_BCBAD);
×
469
  /* Pop off last prototype. */
470
  L->top--;
16✔
471
  return protoV(L->top);
16✔
472
}
473

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc