Coverage Report

Created: 2026-01-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/testdir/build/lua-master/source/lstate.c
Line
Count
Source
1
/*
2
** $Id: lstate.c $
3
** Global State
4
** See Copyright Notice in lua.h
5
*/
6
7
#define lstate_c
8
#define LUA_CORE
9
10
#include "lprefix.h"
11
12
13
#include <stddef.h>
14
#include <string.h>
15
16
#include "lua.h"
17
18
#include "lapi.h"
19
#include "ldebug.h"
20
#include "ldo.h"
21
#include "lfunc.h"
22
#include "lgc.h"
23
#include "llex.h"
24
#include "lmem.h"
25
#include "lstate.h"
26
#include "lstring.h"
27
#include "ltable.h"
28
#include "ltm.h"
29
30
31
32
0
#define fromstate(L)  (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
33
34
35
/*
36
** these macros allow user-specific actions when a thread is
37
** created/deleted
38
*/
39
#if !defined(luai_userstateopen)
40
444
#define luai_userstateopen(L)   ((void)L)
41
#endif
42
43
#if !defined(luai_userstateclose)
44
444
#define luai_userstateclose(L)    ((void)L)
45
#endif
46
47
#if !defined(luai_userstatethread)
48
0
#define luai_userstatethread(L,L1)  ((void)L)
49
#endif
50
51
#if !defined(luai_userstatefree)
52
0
#define luai_userstatefree(L,L1)  ((void)L)
53
#endif
54
55
56
/*
57
** set GCdebt to a new value keeping the real number of allocated
58
** objects (GCtotalobjs - GCdebt) invariant and avoiding overflows in
59
** 'GCtotalobjs'.
60
*/
61
3.66k
void luaE_setdebt (global_State *g, l_mem debt) {
62
3.66k
  l_mem tb = gettotalbytes(g);
63
3.66k
  lua_assert(tb > 0);
64
3.66k
  if (debt > MAX_LMEM - tb)
65
0
    debt = MAX_LMEM - tb;  /* will make GCtotalbytes == MAX_LMEM */
66
3.66k
  g->GCtotalbytes = tb + debt;
67
3.66k
  g->GCdebt = debt;
68
3.66k
}
69
70
71
571k
CallInfo *luaE_extendCI (lua_State *L, int err) {
72
571k
  CallInfo *ci;
73
571k
  ci = luaM_reallocvector(L, NULL, 0, 1, CallInfo);
74
571k
  if (l_unlikely(ci == NULL)) {  /* allocation failed? */
75
0
    if (err)
76
0
      luaM_error(L);  /* raise the error */
77
0
    return NULL;  /* else only report it */
78
0
  }
79
571k
  ci->next = L->ci->next;
80
571k
  ci->previous = L->ci;
81
571k
  L->ci->next = ci;
82
571k
  if (ci->next)
83
0
    ci->next->previous = ci;
84
571k
  ci->u.l.trap = 0;
85
571k
  L->nci++;
86
571k
  return ci;
87
571k
}
88
89
90
/*
91
** free all CallInfo structures not in use by a thread
92
*/
93
444
static void freeCI (lua_State *L) {
94
444
  CallInfo *ci = L->ci;
95
444
  CallInfo *next = ci->next;
96
444
  ci->next = NULL;
97
286k
  while ((ci = next) != NULL) {
98
285k
    next = ci->next;
99
285k
    luaM_free(L, ci);
100
285k
    L->nci--;
101
285k
  }
102
444
}
103
104
105
/*
106
** free half of the CallInfo structures not in use by a thread,
107
** keeping the first one.
108
*/
109
2.02k
void luaE_shrinkCI (lua_State *L) {
110
2.02k
  CallInfo *ci = L->ci->next;  /* first free CallInfo */
111
2.02k
  CallInfo *next;
112
2.02k
  if (ci == NULL)
113
1.88k
    return;  /* no extra elements */
114
285k
  while ((next = ci->next) != NULL) {  /* two extra elements? */
115
285k
    CallInfo *next2 = next->next;  /* next's next */
116
285k
    ci->next = next2;  /* remove next from the list */
117
285k
    L->nci--;
118
285k
    luaM_free(L, next);  /* free next */
119
285k
    if (next2 == NULL)
120
78
      break;  /* no more elements */
121
285k
    else {
122
285k
      next2->previous = ci;
123
285k
      ci = next2;  /* continue */
124
285k
    }
125
285k
  }
126
135
}
127
128
129
/*
130
** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS.
131
** If equal, raises an overflow error. If value is larger than
132
** LUAI_MAXCCALLS (which means it is handling an overflow) but
133
** not much larger, does not report an error (to allow overflow
134
** handling to work).
135
*/
136
1
void luaE_checkcstack (lua_State *L) {
137
1
  if (getCcalls(L) == LUAI_MAXCCALLS)
138
1
    luaG_runerror(L, "C stack overflow");
139
0
  else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11))
140
0
    luaD_errerr(L);  /* error while handling stack error */
141
1
}
142
143
144
25.4M
LUAI_FUNC void luaE_incCstack (lua_State *L) {
145
25.4M
  L->nCcalls++;
146
25.4M
  if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
147
1
    luaE_checkcstack(L);
148
25.4M
}
149
150
151
888
static void resetCI (lua_State *L) {
152
888
  CallInfo *ci = L->ci = &L->base_ci;
153
888
  ci->func.p = L->stack.p;
154
888
  setnilvalue(s2v(ci->func.p));  /* 'function' entry for basic 'ci' */
155
888
  ci->top.p = ci->func.p + 1 + LUA_MINSTACK;  /* +1 for 'function' entry */
156
888
  ci->u.c.k = NULL;
157
888
  ci->callstatus = CIST_C;
158
888
  L->status = LUA_OK;
159
888
  L->errfunc = 0;  /* stack unwind can "throw away" the error function */
160
888
}
161
162
163
444
static void stack_init (lua_State *L1, lua_State *L) {
164
444
  int i;
165
  /* initialize stack array */
166
444
  L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
167
444
  L1->tbclist.p = L1->stack.p;
168
20.4k
  for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
169
19.9k
    setnilvalue(s2v(L1->stack.p + i));  /* erase new stack */
170
444
  L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE;
171
  /* initialize first ci */
172
444
  resetCI(L1);
173
444
  L1->top.p = L1->stack.p + 1;  /* +1 for 'function' entry */
174
444
}
175
176
177
444
static void freestack (lua_State *L) {
178
444
  if (L->stack.p == NULL)
179
0
    return;  /* stack not completely built yet */
180
444
  L->ci = &L->base_ci;  /* free the entire 'ci' list */
181
444
  freeCI(L);
182
444
  lua_assert(L->nci == 0);
183
  /* free stack */
184
444
  luaM_freearray(L, L->stack.p, cast_sizet(stacksize(L) + EXTRA_STACK));
185
444
}
186
187
188
/*
189
** Create registry table and its predefined values
190
*/
191
444
static void init_registry (lua_State *L, global_State *g) {
192
  /* create registry */
193
444
  TValue aux;
194
444
  Table *registry = luaH_new(L);
195
444
  sethvalue(L, &g->l_registry, registry);
196
444
  luaH_resize(L, registry, LUA_RIDX_LAST, 0);
197
  /* registry[1] = false */
198
444
  setbfvalue(&aux);
199
444
  luaH_setint(L, registry, 1, &aux);
200
  /* registry[LUA_RIDX_MAINTHREAD] = L */
201
444
  setthvalue(L, &aux, L);
202
444
  luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &aux);
203
  /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */
204
444
  sethvalue(L, &aux, luaH_new(L));
205
444
  luaH_setint(L, registry, LUA_RIDX_GLOBALS, &aux);
206
444
}
207
208
209
/*
210
** open parts of the state that may cause memory-allocation errors.
211
*/
212
444
static void f_luaopen (lua_State *L, void *ud) {
213
444
  global_State *g = G(L);
214
444
  UNUSED(ud);
215
444
  stack_init(L, L);  /* init stack */
216
444
  init_registry(L, g);
217
444
  luaS_init(L);
218
444
  luaT_init(L);
219
444
  luaX_init(L);
220
444
  g->gcstp = 0;  /* allow gc */
221
444
  setnilvalue(&g->nilvalue);  /* now state is complete */
222
444
  luai_userstateopen(L);
223
444
}
224
225
226
/*
227
** preinitialize a thread with consistent values without allocating
228
** any memory (to avoid errors)
229
*/
230
444
static void preinit_thread (lua_State *L, global_State *g) {
231
444
  G(L) = g;
232
444
  L->stack.p = NULL;
233
444
  L->ci = NULL;
234
444
  L->nci = 0;
235
444
  L->twups = L;  /* thread has no upvalues */
236
444
  L->nCcalls = 0;
237
444
  L->errorJmp = NULL;
238
444
  L->hook = NULL;
239
444
  L->hookmask = 0;
240
444
  L->basehookcount = 0;
241
444
  L->allowhook = 1;
242
444
  resethookcount(L);
243
444
  L->openupval = NULL;
244
444
  L->status = LUA_OK;
245
444
  L->errfunc = 0;
246
444
  L->oldpc = 0;
247
444
  L->base_ci.previous = L->base_ci.next = NULL;
248
444
}
249
250
251
1.60k
lu_mem luaE_threadsize (lua_State *L) {
252
1.60k
  lu_mem sz = cast(lu_mem, sizeof(LX))
253
1.60k
            + cast_uint(L->nci) * sizeof(CallInfo);
254
1.60k
  if (L->stack.p != NULL)
255
1.60k
    sz += cast_uint(stacksize(L) + EXTRA_STACK) * sizeof(StackValue);
256
1.60k
  return sz;
257
1.60k
}
258
259
260
444
static void close_state (lua_State *L) {
261
444
  global_State *g = G(L);
262
444
  if (!completestate(g))  /* closing a partially built state? */
263
0
    luaC_freeallobjects(L);  /* just collect its objects */
264
444
  else {  /* closing a fully built state */
265
444
    resetCI(L);
266
444
    luaD_closeprotected(L, 1, LUA_OK);  /* close all upvalues */
267
444
    L->top.p = L->stack.p + 1;  /* empty the stack to run finalizers */
268
444
    luaC_freeallobjects(L);  /* collect all objects */
269
444
    luai_userstateclose(L);
270
444
  }
271
444
  luaM_freearray(L, G(L)->strt.hash, cast_sizet(G(L)->strt.size));
272
444
  freestack(L);
273
444
  lua_assert(gettotalbytes(g) == sizeof(global_State));
274
444
  (*g->frealloc)(g->ud, g, sizeof(global_State), 0);  /* free main block */
275
444
}
276
277
278
0
LUA_API lua_State *lua_newthread (lua_State *L) {
279
0
  global_State *g = G(L);
280
0
  GCObject *o;
281
0
  lua_State *L1;
282
0
  lua_lock(L);
283
0
  luaC_checkGC(L);
284
  /* create new thread */
285
0
  o = luaC_newobjdt(L, LUA_TTHREAD, sizeof(LX), offsetof(LX, l));
286
0
  L1 = gco2th(o);
287
  /* anchor it on L stack */
288
0
  setthvalue2s(L, L->top.p, L1);
289
0
  api_incr_top(L);
290
0
  preinit_thread(L1, g);
291
0
  L1->hookmask = L->hookmask;
292
0
  L1->basehookcount = L->basehookcount;
293
0
  L1->hook = L->hook;
294
0
  resethookcount(L1);
295
  /* initialize L1 extra space */
296
0
  memcpy(lua_getextraspace(L1), lua_getextraspace(mainthread(g)),
297
0
         LUA_EXTRASPACE);
298
0
  luai_userstatethread(L, L1);
299
0
  stack_init(L1, L);  /* init stack */
300
0
  lua_unlock(L);
301
0
  return L1;
302
0
}
303
304
305
0
void luaE_freethread (lua_State *L, lua_State *L1) {
306
0
  LX *l = fromstate(L1);
307
0
  luaF_closeupval(L1, L1->stack.p);  /* close all upvalues */
308
0
  lua_assert(L1->openupval == NULL);
309
0
  luai_userstatefree(L, L1);
310
0
  freestack(L1);
311
0
  luaM_free(L, l);
312
0
}
313
314
315
0
TStatus luaE_resetthread (lua_State *L, TStatus status) {
316
0
  resetCI(L);
317
0
  if (status == LUA_YIELD)
318
0
    status = LUA_OK;
319
0
  status = luaD_closeprotected(L, 1, status);
320
0
  if (status != LUA_OK)  /* errors? */
321
0
    luaD_seterrorobj(L, status, L->stack.p + 1);
322
0
  else
323
0
    L->top.p = L->stack.p + 1;
324
0
  luaD_reallocstack(L, cast_int(L->ci->top.p - L->stack.p), 0);
325
0
  return status;
326
0
}
327
328
329
0
LUA_API int lua_closethread (lua_State *L, lua_State *from) {
330
0
  TStatus status;
331
0
  lua_lock(L);
332
0
  L->nCcalls = (from) ? getCcalls(from) : 0;
333
0
  status = luaE_resetthread(L, L->status);
334
0
  if (L == from)  /* closing itself? */
335
0
    luaD_throwbaselevel(L, status);
336
0
  lua_unlock(L);
337
0
  return APIstatus(status);
338
0
}
339
340
341
444
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) {
342
444
  int i;
343
444
  lua_State *L;
344
444
  global_State *g = cast(global_State*,
345
444
                       (*f)(ud, NULL, LUA_TTHREAD, sizeof(global_State)));
346
444
  if (g == NULL) return NULL;
347
444
  L = &g->mainth.l;
348
444
  L->tt = LUA_VTHREAD;
349
444
  g->currentwhite = bitmask(WHITE0BIT);
350
444
  L->marked = luaC_white(g);
351
444
  preinit_thread(L, g);
352
444
  g->allgc = obj2gco(L);  /* by now, only object is the main thread */
353
444
  L->next = NULL;
354
444
  incnny(L);  /* main thread is always non yieldable */
355
444
  g->frealloc = f;
356
444
  g->ud = ud;
357
444
  g->warnf = NULL;
358
444
  g->ud_warn = NULL;
359
444
  g->seed = seed;
360
444
  g->gcstp = GCSTPGC;  /* no GC while building state */
361
444
  g->strt.size = g->strt.nuse = 0;
362
444
  g->strt.hash = NULL;
363
444
  setnilvalue(&g->l_registry);
364
444
  g->panic = NULL;
365
444
  g->gcstate = GCSpause;
366
444
  g->gckind = KGC_INC;
367
444
  g->gcstopem = 0;
368
444
  g->gcemergency = 0;
369
444
  g->finobj = g->tobefnz = g->fixedgc = NULL;
370
444
  g->firstold1 = g->survival = g->old1 = g->reallyold = NULL;
371
444
  g->finobjsur = g->finobjold1 = g->finobjrold = NULL;
372
444
  g->sweepgc = NULL;
373
444
  g->gray = g->grayagain = NULL;
374
444
  g->weak = g->ephemeron = g->allweak = NULL;
375
444
  g->twups = NULL;
376
444
  g->GCtotalbytes = sizeof(global_State);
377
444
  g->GCmarked = 0;
378
444
  g->GCdebt = 0;
379
444
  setivalue(&g->nilvalue, 0);  /* to signal that state is not yet built */
380
444
  setgcparam(g, PAUSE, LUAI_GCPAUSE);
381
444
  setgcparam(g, STEPMUL, LUAI_GCMUL);
382
444
  setgcparam(g, STEPSIZE, LUAI_GCSTEPSIZE);
383
444
  setgcparam(g, MINORMUL, LUAI_GENMINORMUL);
384
444
  setgcparam(g, MINORMAJOR, LUAI_MINORMAJOR);
385
444
  setgcparam(g, MAJORMINOR, LUAI_MAJORMINOR);
386
4.44k
  for (i=0; i < LUA_NUMTYPES; i++) g->mt[i] = NULL;
387
444
  if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
388
    /* memory allocation error: free partial state */
389
0
    close_state(L);
390
0
    L = NULL;
391
0
  }
392
444
  return L;
393
444
}
394
395
396
444
LUA_API void lua_close (lua_State *L) {
397
444
  lua_lock(L);
398
444
  L = mainthread(G(L));  /* only the main thread can be closed */
399
444
  close_state(L);
400
444
}
401
402
403
0
void luaE_warning (lua_State *L, const char *msg, int tocont) {
404
0
  lua_WarnFunction wf = G(L)->warnf;
405
0
  if (wf != NULL)
406
0
    wf(G(L)->ud_warn, msg, tocont);
407
0
}
408
409
410
/*
411
** Generate a warning from an error message
412
*/
413
0
void luaE_warnerror (lua_State *L, const char *where) {
414
0
  TValue *errobj = s2v(L->top.p - 1);  /* error object */
415
0
  const char *msg = (ttisstring(errobj))
416
0
                  ? getstr(tsvalue(errobj))
417
0
                  : "error object is not a string";
418
  /* produce warning "error in %s (%s)" (where, msg) */
419
0
  luaE_warning(L, "error in ", 1);
420
0
  luaE_warning(L, where, 1);
421
0
  luaE_warning(L, " (", 1);
422
0
  luaE_warning(L, msg, 1);
423
0
  luaE_warning(L, ")", 0);
424
0
}
425