Coverage Report

Created: 2024-04-23 06:32

/src/testdir/build/lua-master/source/lstring.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** $Id: lstring.c $
3
** String table (keeps all strings handled by Lua)
4
** See Copyright Notice in lua.h
5
*/
6
7
#define lstring_c
8
#define LUA_CORE
9
10
#include "lprefix.h"
11
12
13
#include <string.h>
14
15
#include "lua.h"
16
17
#include "ldebug.h"
18
#include "ldo.h"
19
#include "lmem.h"
20
#include "lobject.h"
21
#include "lstate.h"
22
#include "lstring.h"
23
24
25
/*
26
** Maximum size for string table.
27
*/
28
7.41k
#define MAXSTRTB  cast_int(luaM_limitN(MAX_INT, TString*))
29
30
31
/*
32
** equality for long strings
33
*/
34
1.97M
int luaS_eqlngstr (TString *a, TString *b) {
35
1.97M
  size_t len = a->u.lnglen;
36
1.97M
  lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
37
1.97M
  return (a == b) ||  /* same instance or... */
38
1.97M
    ((len == b->u.lnglen) &&  /* equal length and ... */
39
574k
     (memcmp(getlngstr(a), getlngstr(b), len) == 0));  /* equal contents */
40
1.97M
}
41
42
43
108M
unsigned luaS_hash (const char *str, size_t l, unsigned seed) {
44
108M
  unsigned int h = seed ^ cast_uint(l);
45
1.72G
  for (; l > 0; l--)
46
1.61G
    h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
47
108M
  return h;
48
108M
}
49
50
51
3.23M
unsigned luaS_hashlongstr (TString *ts) {
52
3.23M
  lua_assert(ts->tt == LUA_VLNGSTR);
53
3.23M
  if (ts->extra == 0) {  /* no hash? */
54
781k
    size_t len = ts->u.lnglen;
55
781k
    ts->hash = luaS_hash(getlngstr(ts), len, ts->hash);
56
0
    ts->extra = 1;  /* now it has its hash */
57
781k
  }
58
3.23M
  return ts->hash;
59
3.23M
}
60
61
62
30.4k
static void tablerehash (TString **vect, int osize, int nsize) {
63
30.4k
  int i;
64
8.52M
  for (i = osize; i < nsize; i++)  /* clear new elements */
65
8.49M
    vect[i] = NULL;
66
6.06M
  for (i = 0; i < osize; i++) {  /* rehash old part of the array */
67
6.03M
    TString *p = vect[i];
68
6.03M
    vect[i] = NULL;
69
11.6M
    while (p) {  /* for each string in the list */
70
5.59M
      TString *hnext = p->u.hnext;  /* save next */
71
5.59M
      unsigned int h = lmod(p->hash, nsize);  /* new position */
72
0
      p->u.hnext = vect[h];  /* chain it into array */
73
5.59M
      vect[h] = p;
74
5.59M
      p = hnext;
75
5.59M
    }
76
6.03M
  }
77
30.4k
}
78
79
80
/*
81
** Resize the string table. If allocation fails, keep the current size.
82
** (This can degrade performance, but any non-zero size should work
83
** correctly.)
84
*/
85
7.51k
void luaS_resize (lua_State *L, int nsize) {
86
7.51k
  stringtable *tb = &G(L)->strt;
87
7.51k
  int osize = tb->size;
88
7.51k
  TString **newvect;
89
7.51k
  if (nsize < osize)  /* shrinking table? */
90
99
    tablerehash(tb->hash, osize, nsize);  /* depopulate shrinking part */
91
7.51k
  newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*);
92
7.51k
  if (l_unlikely(newvect == NULL)) {  /* reallocation failed? */
93
0
    if (nsize < osize)  /* was it shrinking table? */
94
0
      tablerehash(tb->hash, nsize, osize);  /* restore to original size */
95
    /* leave table as it was */
96
0
  }
97
7.51k
  else {  /* allocation succeeded */
98
7.51k
    tb->hash = newvect;
99
7.51k
    tb->size = nsize;
100
7.51k
    if (nsize > osize)
101
7.41k
      tablerehash(newvect, osize, nsize);  /* rehash for new size */
102
7.51k
  }
103
7.51k
}
104
105
106
/*
107
** Clear API string cache. (Entries cannot be empty, so fill them with
108
** a non-collectable string.)
109
*/
110
814k
void luaS_clearcache (global_State *g) {
111
814k
  int i, j;
112
43.9M
  for (i = 0; i < STRCACHE_N; i++)
113
129M
    for (j = 0; j < STRCACHE_M; j++) {
114
86.3M
      if (iswhite(g->strcache[i][j]))  /* will entry be collected? */
115
660k
        g->strcache[i][j] = g->memerrmsg;  /* replace it with something fixed */
116
86.3M
    }
117
814k
}
118
119
120
/*
121
** Initialize the string table and the string cache
122
*/
123
22.9k
void luaS_init (lua_State *L) {
124
22.9k
  global_State *g = G(L);
125
22.9k
  int i, j;
126
22.9k
  stringtable *tb = &G(L)->strt;
127
22.9k
  tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*);
128
22.9k
  tablerehash(tb->hash, 0, MINSTRTABSIZE);  /* clear array */
129
22.9k
  tb->size = MINSTRTABSIZE;
130
  /* pre-create memory-error message */
131
22.9k
  g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
132
22.9k
  luaC_fix(L, obj2gco(g->memerrmsg));  /* it should never be collected */
133
1.24M
  for (i = 0; i < STRCACHE_N; i++)  /* fill cache with valid strings */
134
3.65M
    for (j = 0; j < STRCACHE_M; j++)
135
2.43M
      g->strcache[i][j] = g->memerrmsg;
136
22.9k
}
137
138
139
15.8M
size_t luaS_sizelngstr (size_t len, int kind) {
140
15.8M
  switch (kind) {
141
14.0M
    case LSTRREG:  /* regular long string */
142
      /* don't need 'falloc'/'ud', but need space for content */
143
14.0M
      return offsetof(TString, falloc) + (len + 1) * sizeof(char);
144
18.1k
    case LSTRFIX:  /* fixed external long string */
145
      /* don't need 'falloc'/'ud' */
146
18.1k
      return offsetof(TString, falloc);
147
1.79M
    default:  /* external long string with deallocation */
148
1.79M
      lua_assert(kind == LSTRMEM);
149
1.79M
      return sizeof(TString);
150
15.8M
  }
151
15.8M
}
152
153
154
/*
155
** creates a new string object
156
*/
157
static TString *createstrobj (lua_State *L, size_t totalsize, int tag,
158
18.2M
                              unsigned h) {
159
18.2M
  TString *ts;
160
18.2M
  GCObject *o;
161
18.2M
  o = luaC_newobj(L, tag, totalsize);
162
18.2M
  ts = gco2ts(o);
163
0
  ts->hash = h;
164
18.2M
  ts->extra = 0;
165
18.2M
  return ts;
166
18.2M
}
167
168
169
7.00M
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
170
7.00M
  size_t totalsize = luaS_sizelngstr(l, LSTRREG);
171
7.00M
  TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->seed);
172
7.00M
  ts->u.lnglen = l;
173
7.00M
  ts->shrlen = LSTRREG;  /* signals that it is a regular long string */
174
7.00M
  ts->contents = cast_charp(ts) + offsetof(TString, falloc);
175
7.00M
  ts->contents[l] = '\0';  /* ending 0 */
176
7.00M
  return ts;
177
7.00M
}
178
179
180
10.3M
void luaS_remove (lua_State *L, TString *ts) {
181
10.3M
  stringtable *tb = &G(L)->strt;
182
10.3M
  TString **p = &tb->hash[lmod(ts->hash, tb->size)];
183
11.4M
  while (*p != ts)  /* find previous element */
184
1.03M
    p = &(*p)->u.hnext;
185
10.3M
  *p = (*p)->u.hnext;  /* remove element from its list */
186
10.3M
  tb->nuse--;
187
10.3M
}
188
189
190
7.41k
static void growstrtab (lua_State *L, stringtable *tb) {
191
7.41k
  if (l_unlikely(tb->nuse == MAX_INT)) {  /* too many strings? */
192
0
    luaC_fullgc(L, 1);  /* try to free some... */
193
0
    if (tb->nuse == MAX_INT)  /* still too many? */
194
0
      luaM_error(L);  /* cannot even create a message... */
195
0
  }
196
7.41k
  if (tb->size <= MAXSTRTB / 2)  /* can grow string table? */
197
7.41k
    luaS_resize(L, tb->size * 2);
198
7.41k
}
199
200
201
/*
202
** Checks whether short string exists and reuses it or creates a new one.
203
*/
204
107M
static TString *internshrstr (lua_State *L, const char *str, size_t l) {
205
107M
  TString *ts;
206
107M
  global_State *g = G(L);
207
107M
  stringtable *tb = &g->strt;
208
107M
  unsigned int h = luaS_hash(str, l, g->seed);
209
107M
  TString **list = &tb->hash[lmod(h, tb->size)];
210
107M
  lua_assert(str != NULL);  /* otherwise 'memcmp'/'memcpy' are undefined */
211
130M
  for (ts = *list; ts != NULL; ts = ts->u.hnext) {
212
120M
    if (l == cast_uint(ts->shrlen) &&
213
120M
        (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) {
214
      /* found! */
215
96.8M
      if (isdead(g, ts))  /* dead (but not collected yet)? */
216
19.4k
        changewhite(ts);  /* resurrect it */
217
96.8M
      return ts;
218
96.8M
    }
219
120M
  }
220
  /* else must create a new string */
221
10.3M
  if (tb->nuse >= tb->size) {  /* need to grow string table? */
222
7.41k
    growstrtab(L, tb);
223
7.41k
    list = &tb->hash[lmod(h, tb->size)];  /* rehash with new size */
224
7.41k
  }
225
10.3M
  ts = createstrobj(L, sizestrshr(l), LUA_VSHRSTR, h);
226
10.3M
  ts->shrlen = cast_byte(l);
227
10.3M
  getshrstr(ts)[l] = '\0';  /* ending 0 */
228
10.3M
  memcpy(getshrstr(ts), str, l * sizeof(char));
229
0
  ts->u.hnext = *list;
230
10.3M
  *list = ts;
231
10.3M
  tb->nuse++;
232
10.3M
  return ts;
233
10.3M
}
234
235
236
/*
237
** new string (with explicit length)
238
*/
239
113M
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
240
113M
  if (l <= LUAI_MAXSHORTLEN)  /* short string? */
241
107M
    return internshrstr(L, str, l);
242
5.97M
  else {
243
5.97M
    TString *ts;
244
5.97M
    if (l_unlikely(l * sizeof(char) >= (MAX_SIZE - sizeof(TString))))
245
0
      luaM_toobig(L);
246
5.97M
    ts = luaS_createlngstrobj(L, l);
247
5.97M
    memcpy(getlngstr(ts), str, l * sizeof(char));
248
0
    return ts;
249
5.97M
  }
250
113M
}
251
252
253
/*
254
** Create or reuse a zero-terminated string, first checking in the
255
** cache (using the string address as a key). The cache can contain
256
** only zero-terminated strings, so it is safe to use 'strcmp' to
257
** check hits.
258
*/
259
11.8M
TString *luaS_new (lua_State *L, const char *str) {
260
11.8M
  unsigned int i = point2uint(str) % STRCACHE_N;  /* hash */
261
11.8M
  int j;
262
11.8M
  TString **p = G(L)->strcache[i];
263
18.6M
  for (j = 0; j < STRCACHE_M; j++) {
264
16.1M
    if (strcmp(str, getstr(p[j])) == 0)  /* hit? */
265
9.28M
      return p[j];  /* that is it */
266
16.1M
  }
267
  /* normal route */
268
5.12M
  for (j = STRCACHE_M - 1; j > 0; j--)
269
2.56M
    p[j] = p[j - 1];  /* move out last element */
270
  /* new element is first in the list */
271
2.56M
  p[0] = luaS_newlstr(L, str, strlen(str));
272
2.56M
  return p[0];
273
11.8M
}
274
275
276
925k
Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) {
277
925k
  Udata *u;
278
925k
  int i;
279
925k
  GCObject *o;
280
925k
  if (l_unlikely(s > MAX_SIZE - udatamemoffset(nuvalue)))
281
0
    luaM_toobig(L);
282
925k
  o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s));
283
925k
  u = gco2u(o);
284
0
  u->len = s;
285
925k
  u->nuvalue = nuvalue;
286
925k
  u->metatable = NULL;
287
926k
  for (i = 0; i < nuvalue; i++)
288
925k
    setnilvalue(&u->uv[i].uv);
289
925k
  return u;
290
925k
}
291
292
293
struct NewExt {
294
  int kind;
295
  const char *s;
296
   size_t len;
297
  TString *ts;  /* output */
298
};
299
300
301
904k
static void f_newext (lua_State *L, void *ud) {
302
904k
  struct NewExt *ne = cast(struct NewExt *, ud);
303
904k
  size_t size = luaS_sizelngstr(0, ne->kind);
304
904k
  ne->ts = createstrobj(L, size, LUA_VLNGSTR, G(L)->seed);
305
904k
}
306
307
308
0
static void f_pintern (lua_State *L, void *ud) {
309
0
  struct NewExt *ne = cast(struct NewExt *, ud);
310
0
  ne->ts = internshrstr(L, ne->s, ne->len);
311
0
}
312
313
314
TString *luaS_newextlstr (lua_State *L,
315
904k
            const char *s, size_t len, lua_Alloc falloc, void *ud) {
316
904k
  struct NewExt ne;
317
904k
  if (len <= LUAI_MAXSHORTLEN) {  /* short string? */
318
0
    ne.s = s; ne.len = len;
319
0
    if (!falloc)
320
0
      f_pintern(L, &ne);  /* just internalize string */
321
0
    else {
322
0
      int status = luaD_rawrunprotected(L, f_pintern, &ne);
323
0
      (*falloc)(ud, cast_voidp(s), len + 1, 0);  /* free external string */
324
0
      if (status != LUA_OK)  /* memory error? */
325
0
        luaM_error(L);  /* re-raise memory error */
326
0
    }
327
0
    return ne.ts;
328
0
  }
329
  /* "normal" case: long strings */
330
904k
  if (!falloc) {
331
9.07k
    ne.kind = LSTRFIX;
332
9.07k
    f_newext(L, &ne);  /* just create header */
333
9.07k
  }
334
895k
  else {
335
895k
    ne.kind = LSTRMEM;
336
895k
    if (luaD_rawrunprotected(L, f_newext, &ne) != LUA_OK) {  /* mem. error? */
337
0
      (*falloc)(ud, cast_voidp(s), len + 1, 0);  /* free external string */
338
0
      luaM_error(L);  /* re-raise memory error */
339
0
    }
340
895k
    ne.ts->falloc = falloc;
341
895k
    ne.ts->ud = ud;
342
895k
  }
343
904k
  ne.ts->shrlen = ne.kind;
344
904k
  ne.ts->u.lnglen = len;
345
904k
  ne.ts->contents = cast_charp(s);
346
904k
  return ne.ts;
347
904k
}
348
349