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

tarantool / luajit / 6851160821

13 Nov 2023 02:06PM UTC coverage: 88.458% (-0.008%) from 88.466%
6851160821

push

github

igormunkin
Fix last commit.

Reported by PluMGMK.

(cherry-picked from commit 224129a8e)

The `_VMEVENTS` table, where the error handler for GC finalizers
is set, was not cleared from the stack after the initialization.
This commit adds stack cleanup.

Maxim Kokryashkin:
* added the description and the test for the problem

Part of tarantool/tarantool#9145

Reviewed-by: Sergey Kaplun <skaplun@tarantool.org>
Reviewed-by: Sergey Bronnikov <sergeyb@tarantool.org>
Signed-off-by: Igor Munkin <imun@tarantool.org>

5361 of 5976 branches covered (0.0%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

33 existing lines in 8 files now uncovered.

20551 of 23317 relevant lines covered (88.14%)

2746324.23 hits per line

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

88.07
/src/lib_aux.c
1
/*
2
** Auxiliary library for the Lua/C API.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
**
5
** Major parts taken verbatim or adapted from the Lua interpreter.
6
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7
*/
8

9
#include <errno.h>
10
#include <stdarg.h>
11
#include <stdio.h>
12

13
#define lib_aux_c
14
#define LUA_LIB
15

16
#include "lua.h"
17
#include "lauxlib.h"
18

19
#include "lj_obj.h"
20
#include "lj_err.h"
21
#include "lj_state.h"
22
#include "lj_trace.h"
23
#include "lj_lib.h"
24
#include "lj_vmevent.h"
25

26
#if LJ_TARGET_POSIX
27
#include <sys/wait.h>
28
#endif
29

30
/* -- I/O error handling -------------------------------------------------- */
31

32
LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname)
131,675✔
33
{
34
  if (stat) {
131,675✔
35
    setboolV(L->top++, 1);
131,655✔
36
    return 1;
131,655✔
37
  } else {
38
    int en = errno;  /* Lua API calls may change this value. */
20✔
39
    setnilV(L->top++);
20✔
40
    if (fname)
20✔
41
      lua_pushfstring(L, "%s: %s", fname, strerror(en));
16✔
42
    else
43
      lua_pushfstring(L, "%s", strerror(en));
4✔
44
    setintV(L->top++, en);
20✔
45
    lj_trace_abort(G(L));
20✔
46
    return 3;
20✔
47
  }
48
}
49

UNCOV
50
LUALIB_API int luaL_execresult(lua_State *L, int stat)
×
51
{
UNCOV
52
  if (stat != -1) {
×
53
#if LJ_TARGET_POSIX
54
    if (WIFSIGNALED(stat)) {
×
55
      stat = WTERMSIG(stat);
×
56
      setnilV(L->top++);
×
UNCOV
57
      lua_pushliteral(L, "signal");
×
58
    } else {
59
      if (WIFEXITED(stat))
×
60
        stat = WEXITSTATUS(stat);
×
61
      if (stat == 0)
×
UNCOV
62
        setboolV(L->top++, 1);
×
63
      else
64
        setnilV(L->top++);
×
UNCOV
65
      lua_pushliteral(L, "exit");
×
66
    }
67
#else
68
    if (stat == 0)
69
      setboolV(L->top++, 1);
70
    else
71
      setnilV(L->top++);
72
    lua_pushliteral(L, "exit");
73
#endif
74
    setintV(L->top++, stat);
×
UNCOV
75
    return 3;
×
76
  }
UNCOV
77
  return luaL_fileresult(L, 0, NULL);
×
78
}
79

80
/* -- Module registration ------------------------------------------------- */
81

82
LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
9,504✔
83
                                      const char *fname, int szhint)
84
{
85
  const char *e;
9,504✔
86
  lua_pushvalue(L, idx);
9,504✔
87
  do {
10,257✔
88
    e = strchr(fname, '.');
10,257✔
89
    if (e == NULL) e = fname + strlen(fname);
10,257✔
90
    lua_pushlstring(L, fname, (size_t)(e - fname));
10,257✔
91
    lua_rawget(L, -2);
10,257✔
92
    if (lua_isnil(L, -1)) {  /* no such field? */
10,257✔
93
      lua_pop(L, 1);  /* remove this nil */
4,242✔
94
      lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
4,244✔
95
      lua_pushlstring(L, fname, (size_t)(e - fname));
4,242✔
96
      lua_pushvalue(L, -2);
4,242✔
97
      lua_settable(L, -4);  /* set new table into field */
4,242✔
98
    } else if (!lua_istable(L, -1)) {  /* field has a non-table value? */
6,015✔
99
      lua_pop(L, 2);  /* remove table and value */
2✔
100
      return fname;  /* return problematic part of the name */
2✔
101
    }
102
    lua_remove(L, -2);  /* remove previous table */
10,255✔
103
    fname = e + 1;
10,255✔
104
  } while (*e == '.');
10,255✔
105
  return NULL;
106
}
107

108
static int libsize(const luaL_Reg *l)
109
{
110
  int size = 0;
111
  for (; l && l->name; l++) size++;
1,017✔
112
  return size;
261✔
113
}
114

115
LUALIB_API void luaL_pushmodule(lua_State *L, const char *modname, int sizehint)
275✔
116
{
117
  luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
275✔
118
  lua_getfield(L, -1, modname);
275✔
119
  if (!lua_istable(L, -1)) {
275✔
120
    lua_pop(L, 1);
271✔
121
    if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, sizehint) != NULL)
271✔
122
      lj_err_callerv(L, LJ_ERR_BADMODN, modname);
2✔
123
    lua_pushvalue(L, -1);
269✔
124
    lua_setfield(L, -3, modname);  /* _LOADED[modname] = new table. */
269✔
125
  }
126
  lua_remove(L, -2);  /* Remove _LOADED table. */
273✔
127
}
273✔
128

129
LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
509✔
130
                             const luaL_Reg *l, int nup)
131
{
132
  lj_lib_checkfpu(L);
509✔
133
  if (libname) {
509✔
134
    luaL_pushmodule(L, libname, libsize(l));
261✔
135
    lua_insert(L, -(nup + 1));  /* Move module table below upvalues. */
261✔
136
  }
137
  if (l)
509✔
138
    luaL_setfuncs(L, l, nup);
509✔
139
  else
UNCOV
140
    lua_pop(L, nup);  /* Remove upvalues. */
×
141
}
509✔
142

143
LUALIB_API void luaL_register(lua_State *L, const char *libname,
509✔
144
                              const luaL_Reg *l)
145
{
146
  luaL_openlib(L, libname, l, 0);
509✔
147
}
509✔
148

149
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
509✔
150
{
151
  luaL_checkstack(L, nup, "too many upvalues");
509✔
152
  for (; l->name; l++) {
2,270✔
153
    int i;
154
    for (i = 0; i < nup; i++)  /* Copy upvalues to the top. */
1,252✔
UNCOV
155
      lua_pushvalue(L, -nup);
×
156
    lua_pushcclosure(L, l->func, nup);
1,252✔
157
    lua_setfield(L, -(nup + 2), l->name);
1,252✔
158
  }
159
  lua_pop(L, nup);  /* Remove upvalues. */
509✔
160
}
509✔
161

162
LUALIB_API const char *luaL_gsub(lua_State *L, const char *s,
3,225✔
163
                                 const char *p, const char *r)
164
{
165
  const char *wild;
3,225✔
166
  size_t l = strlen(p);
3,225✔
167
  luaL_Buffer b;
3,225✔
168
  luaL_buffinit(L, &b);
8,981✔
169
  while ((wild = strstr(s, p)) != NULL) {
5,756✔
170
    luaL_addlstring(&b, s, (size_t)(wild - s));  /* push prefix */
2,531✔
171
    luaL_addstring(&b, r);  /* push replacement in place of pattern */
5,062✔
172
    s = wild + l;  /* continue after `p' */
2,531✔
173
  }
174
  luaL_addstring(&b, s);  /* push last suffix */
6,450✔
175
  luaL_pushresult(&b);
3,225✔
176
  return lua_tostring(L, -1);
3,225✔
177
}
178

179
/* -- Buffer handling ----------------------------------------------------- */
180

181
#define bufflen(B)        ((size_t)((B)->p - (B)->buffer))
182
#define bufffree(B)        ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
183

184
static int emptybuffer(luaL_Buffer *B)
25,772✔
185
{
186
  size_t l = bufflen(B);
25,772✔
187
  if (l == 0)
25,772✔
188
    return 0;  /* put nothing on stack */
189
  lua_pushlstring(B->L, B->buffer, l);
25,771✔
190
  B->p = B->buffer;
25,771✔
191
  B->lvl++;
25,771✔
192
  return 1;
25,771✔
193
}
194

195
static void adjuststack(luaL_Buffer *B)
196
{
197
  if (B->lvl > 1) {
198
    lua_State *L = B->L;
199
    int toget = 1;  /* number of levels to concat */
200
    size_t toplen = lua_strlen(L, -1);
201
    do {
202
      size_t l = lua_strlen(L, -(toget+1));
203
      if (!(B->lvl - toget + 1 >= LUA_MINSTACK/2 || toplen > l))
204
        break;
205
      toplen += l;
206
      toget++;
207
    } while (toget < B->lvl);
208
    lua_concat(L, toget);
209
    B->lvl = B->lvl - toget + 1;
210
  }
211
}
212

213
LUALIB_API char *luaL_prepbuffer(luaL_Buffer *B)
48✔
214
{
215
  if (emptybuffer(B))
48✔
216
    adjuststack(B);
48✔
217
  return B->buffer;
48✔
218
}
219

220
LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l)
30,625✔
221
{
222
  while (l--)
890,549✔
223
    luaL_addchar(B, *s++);
859,924✔
224
}
30,625✔
225

226
LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s)
5,756✔
227
{
228
  luaL_addlstring(B, s, strlen(s));
5,756✔
UNCOV
229
}
×
230

231
LUALIB_API void luaL_pushresult(luaL_Buffer *B)
25,714✔
232
{
233
  emptybuffer(B);
25,714✔
234
  lua_concat(B->L, B->lvl);
25,714✔
235
  B->lvl = 1;
25,714✔
236
}
25,714✔
237

238
LUALIB_API void luaL_addvalue(luaL_Buffer *B)
13,319✔
239
{
240
  lua_State *L = B->L;
13,319✔
241
  size_t vl;
13,319✔
242
  const char *s = lua_tolstring(L, -1, &vl);
13,319✔
243
  if (vl <= bufffree(B)) {  /* fit into buffer? */
13,319✔
244
    memcpy(B->p, s, vl);  /* put it there */
13,309✔
245
    B->p += vl;
13,309✔
246
    lua_pop(L, 1);  /* remove from stack */
13,309✔
247
  } else {
248
    if (emptybuffer(B))
10✔
249
      lua_insert(L, -2);  /* put buffer before new value */
10✔
250
    B->lvl++;  /* add new value into B stack */
10✔
251
    adjuststack(B);
10✔
252
  }
253
}
13,319✔
254

255
LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
26,058✔
256
{
257
  B->L = L;
26,058✔
258
  B->p = B->buffer;
26,058✔
259
  B->lvl = 0;
26,058✔
260
}
3,225✔
261

262
/* -- Reference management ------------------------------------------------ */
263

264
#define FREELIST_REF        0
265

266
/* Convert a stack index to an absolute index. */
267
#define abs_index(L, i) \
268
  ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
269

270
LUALIB_API int luaL_ref(lua_State *L, int t)
2✔
271
{
272
  int ref;
2✔
273
  t = abs_index(L, t);
2✔
274
  if (lua_isnil(L, -1)) {
2✔
275
    lua_pop(L, 1);  /* remove from stack */
×
UNCOV
276
    return LUA_REFNIL;  /* `nil' has a unique fixed reference */
×
277
  }
278
  lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */
2✔
279
  ref = (int)lua_tointeger(L, -1);  /* ref = t[FREELIST_REF] */
2✔
280
  lua_pop(L, 1);  /* remove it from stack */
2✔
281
  if (ref != 0) {  /* any free element? */
2✔
282
    lua_rawgeti(L, t, ref);  /* remove it from list */
×
UNCOV
283
    lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */
×
284
  } else {  /* no free elements */
285
    ref = (int)lua_objlen(L, t);
2✔
286
    ref++;  /* create new reference */
2✔
287
  }
288
  lua_rawseti(L, t, ref);
2✔
289
  return ref;
2✔
290
}
291

292
LUALIB_API void luaL_unref(lua_State *L, int t, int ref)
1✔
293
{
294
  if (ref >= 0) {
1✔
295
    t = abs_index(L, t);
1✔
296
    lua_rawgeti(L, t, FREELIST_REF);
1✔
297
    lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */
1✔
298
    lua_pushinteger(L, ref);
1✔
299
    lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */
1✔
300
  }
301
}
1✔
302

303
/* -- Default allocator and panic function -------------------------------- */
304

305
static int panic(lua_State *L)
3✔
306
{
307
  const char *s = lua_tostring(L, -1);
3✔
308
  fputs("PANIC: unprotected error in call to Lua API (", stderr);
3✔
309
  fputs(s ? s : "?", stderr);
3✔
310
  fputc(')', stderr); fputc('\n', stderr);
3✔
311
  fflush(stderr);
3✔
312
  return 0;
3✔
313
}
314

315
#ifndef LUAJIT_DISABLE_VMEVENT
316
static int error_finalizer(lua_State *L)
4,012✔
317
{
318
  const char *s = lua_tostring(L, -1);
4,012✔
319
  fputs("ERROR in finalizer: ", stderr);
4,012✔
320
  fputs(s ? s : "?", stderr);
4,012✔
321
  fputc('\n', stderr);
4,012✔
322
  fflush(stderr);
4,012✔
323
  return 0;
4,012✔
324
}
325
#endif
326

327
#ifdef LUAJIT_USE_SYSMALLOC
328

329
#if LJ_64 && !LJ_GC64 && !defined(LUAJIT_USE_VALGRIND)
330
#error "Must use builtin allocator for 64 bit target"
331
#endif
332

333
static void *mem_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
334
{
335
  (void)ud;
336
  (void)osize;
337
  if (nsize == 0) {
338
    free(ptr);
339
    return NULL;
340
  } else {
341
    return realloc(ptr, nsize);
342
  }
343
}
344

345
LUALIB_API lua_State *luaL_newstate(void)
346
{
347
  lua_State *L = lua_newstate(mem_alloc, NULL);
348
  if (L) {
349
    G(L)->panic = panic;
350
#ifndef LUAJIT_DISABLE_VMEVENT
351
    luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE);
352
    lua_pushcfunction(L, error_finalizer);
353
    lua_rawseti(L, -2, VMEVENT_HASH(LJ_VMEVENT_ERRFIN));
354
    G(L)->vmevmask = VMEVENT_MASK(LJ_VMEVENT_ERRFIN);
355
    L->top--;
356
#endif
357
  }
358
  return L;
359
}
360

361
#else
362

363
#include "lj_alloc.h"
364

365
LUALIB_API lua_State *luaL_newstate(void)
253✔
366
{
367
  lua_State *L;
253✔
368
  void *ud = lj_alloc_create();
253✔
369
  if (ud == NULL) return NULL;
253✔
370
#if LJ_64 && !LJ_GC64
371
  L = lj_state_newstate(lj_alloc_f, ud);
372
#else
373
  L = lua_newstate(lj_alloc_f, ud);
253✔
374
#endif
375
  if (L) {
253✔
376
    G(L)->panic = panic;
253✔
377
#ifndef LUAJIT_DISABLE_VMEVENT
378
    luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE);
253✔
379
    lua_pushcfunction(L, error_finalizer);
253✔
380
    lua_rawseti(L, -2, VMEVENT_HASH(LJ_VMEVENT_ERRFIN));
253✔
381
    G(L)->vmevmask = VMEVENT_MASK(LJ_VMEVENT_ERRFIN);
253✔
382
    L->top--;
253✔
383
#endif
384
  }
385
  return L;
386
}
387

388
#if LJ_64 && !LJ_GC64
389
LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
390
{
391
  UNUSED(f); UNUSED(ud);
392
  fputs("Must use luaL_newstate() for 64 bit target\n", stderr);
393
  return NULL;
394
}
395
#endif
396

397
#endif
398

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

© 2025 Coveralls, Inc