Coverage Report

Created: 2023-09-15 06:13

/src/testdir/tests/torture_test.cc
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * SPDX-License-Identifier: ISC
3
 *
4
 * Copyright 2023, Sergey Bronnikov.
5
 */
6
7
/**
8
 * Each Lua C API function has an indicator like this: [-o, +p, x],
9
 * see "4.6 – Functions and Types" in Lua Reference Manual.
10
 *
11
 * The test pushes random Lua objects to a Lua stack, runs random Lua C API
12
 * functions and checks that executed function conforms to its function
13
 * indicator.
14
 */
15
16
#include <assert.h>
17
#include <stdint.h>
18
19
#include <fuzzer/FuzzedDataProvider.h>
20
21
#if defined(__cplusplus)
22
extern "C" {
23
#endif /* defined(__cplusplus) */
24
25
#include <lua.h>
26
#include <lualib.h>
27
#include <lauxlib.h>
28
29
#if defined(__cplusplus)
30
} /* extern "C" */
31
#endif /* defined(__cplusplus) */
32
33
5.20k
#define ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]))
34
35
int max_str_len = 1;
36
37
static int
38
0
cfunction(lua_State *L) {
39
0
  lua_gettop(L);
40
0
  return 0;
41
0
}
42
43
/* void lua_pushstring(lua_State *L, const char *s); */
44
/* [-0, +1, m] */
45
static void
46
__lua_pushstring(lua_State *L, FuzzedDataProvider *fdp)
47
177
{
48
177
  auto str = fdp->ConsumeRandomLengthString(max_str_len);
49
177
  int top = lua_gettop(L);
50
177
  lua_pushstring(L, str.c_str());
51
177
  assert(lua_gettop(L) == top + 1);
52
177
}
53
54
/* void lua_pushboolean(lua_State *L, int b); */
55
/* [-0, +1, -] */
56
static void
57
__lua_pushboolean(lua_State *L, FuzzedDataProvider *fdp)
58
76
{
59
76
  uint8_t n = fdp->ConsumeIntegral<uint8_t>();
60
76
  int top = lua_gettop(L);
61
76
  lua_pushboolean(L, n);
62
76
  assert(lua_gettop(L) == top + 1);
63
76
}
64
65
/* void lua_pop(lua_State *L, int n); */
66
/* [-n, +0, -] */
67
static void
68
__lua_pop(lua_State *L, FuzzedDataProvider *fdp)
69
18
{
70
18
  int top = lua_gettop(L);
71
18
  uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
72
18
  lua_pop(L, n);
73
18
  assert(lua_gettop(L) == top - n);
74
18
}
75
76
/* int lua_isnumber(lua_State *L, int index); */
77
/* [-0, +0, -] */
78
static void
79
__lua_isnumber(lua_State *L, FuzzedDataProvider *fdp)
80
22
{
81
22
  int top = lua_gettop(L);
82
22
  uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
83
22
  lua_isnumber(L, n);
84
22
  assert(lua_gettop(L) == top);
85
22
}
86
87
/* lua_Number lua_tonumber(lua_State *L, int index); */
88
/* [-0, +0, -] */
89
static void
90
__lua_tonumber(lua_State *L, FuzzedDataProvider *fdp)
91
32
{
92
32
  int top = lua_gettop(L);
93
32
  uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
94
32
  lua_tonumber(L, n);
95
32
  assert(lua_gettop(L) == top);
96
32
}
97
98
/* int lua_checkstack(lua_State *L, int extra); */
99
/* [-0, +0, m] */
100
static void
101
__lua_checkstack(lua_State *L, FuzzedDataProvider *fdp)
102
87
{
103
87
  uint8_t n = fdp->ConsumeIntegral<uint8_t>();
104
87
  int rc = lua_checkstack(L, n);
105
87
  assert(rc != 0);
106
87
}
107
108
/* void lua_concat(lua_State *L, int n); */
109
/* [-n, +1, e] */
110
static void
111
__lua_concat(lua_State *L, FuzzedDataProvider *fdp)
112
55
{
113
55
  int top = lua_gettop(L);
114
55
  uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
115
118
  for (int i = 1; i <= n; i++) {
116
84
    int t = lua_type(L, -i);
117
84
    if (t != LUA_TNUMBER &&
118
84
        t != LUA_TSTRING)
119
21
      return;
120
84
  }
121
34
  lua_concat(L, n);
122
34
  assert(lua_gettop(L) == top - n + 1);
123
34
}
124
125
/* int lua_gettop(lua_State *L); */
126
/* [-0, +0, -] */
127
static void
128
__lua_gettop(lua_State *L, FuzzedDataProvider *fdp)
129
2
{
130
2
  int rc = lua_gettop(L);
131
2
  assert(rc >= 0);
132
2
}
133
134
/* void lua_insert(lua_State *L, int index); */
135
/* [-1, +1, -] */
136
static void
137
__lua_insert(lua_State *L, FuzzedDataProvider *fdp)
138
13
{
139
13
  int top = lua_gettop(L);
140
13
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
141
13
  lua_insert(L, index);
142
13
  assert(lua_gettop(L) == top - 1 + 1);
143
13
}
144
145
/* int lua_isboolean(lua_State *L, int index); */
146
/* [-0, +0, -] */
147
static void
148
__lua_isboolean(lua_State *L, FuzzedDataProvider *fdp)
149
8
{
150
8
  int top = lua_gettop(L);
151
8
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
152
8
  int rc = lua_isboolean(L, index);
153
8
  assert(rc == 0 || rc == 1);
154
8
}
155
156
/* int lua_iscfunction(lua_State *L, int index); */
157
/* [-0, +0, -] */
158
static void
159
__lua_iscfunction(lua_State *L, FuzzedDataProvider *fdp)
160
8
{
161
8
  int top = lua_gettop(L);
162
8
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
163
8
  int rc = lua_iscfunction(L, index);
164
8
  assert(rc == 0 || rc == 1);
165
8
}
166
167
/* int lua_isfunction(lua_State *L, int index); */
168
/* [-0, +0, -] */
169
static void
170
__lua_isfunction(lua_State *L, FuzzedDataProvider *fdp)
171
12
{
172
12
  int top = lua_gettop(L);
173
12
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
174
12
  int rc = lua_isfunction(L, index);
175
12
  assert(rc == 0 || rc == 1);
176
12
}
177
178
/* int lua_isnil(lua_State *L, int index); */
179
/* [-0, +0, -] */
180
static void
181
__lua_isnil(lua_State *L, FuzzedDataProvider *fdp)
182
9
{
183
9
  int top = lua_gettop(L);
184
9
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
185
9
  int rc = lua_isnil(L, index);
186
9
  assert(rc == 0 || rc == 1);
187
9
}
188
189
/* int lua_isnone(lua_State *L, int index); */
190
/* [-0, +0, -] */
191
static void
192
__lua_isnone(lua_State *L, FuzzedDataProvider *fdp)
193
13
{
194
13
  int top = lua_gettop(L);
195
13
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
196
13
  int rc = lua_isnone(L, index);
197
13
  assert(rc == 0 || rc == 1);
198
0
  assert(lua_gettop(L) == top);
199
13
}
200
201
/* int lua_isnoneornil(lua_State *L, int index); */
202
/* [-0, +0, -] */
203
static void
204
__lua_isnoneornil(lua_State *L, FuzzedDataProvider *fdp)
205
14
{
206
14
  int top = lua_gettop(L);
207
14
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
208
14
  lua_isnoneornil(L, index);
209
14
  assert(lua_gettop(L) == top);
210
14
}
211
212
/* int lua_isstring(lua_State *L, int index); */
213
/* [-0, +0, -] */
214
static void
215
__lua_isstring(lua_State *L, FuzzedDataProvider *fdp)
216
12
{
217
12
  int top = lua_gettop(L);
218
12
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
219
12
  int rc = lua_isstring(L, index);
220
12
  assert(rc == 0 || rc == 1);
221
12
}
222
223
/* int lua_istable(lua_State *L, int index); */
224
/* [-0, +0, -] */
225
static void
226
__lua_istable(lua_State *L, FuzzedDataProvider *fdp)
227
13
{
228
13
  int top = lua_gettop(L);
229
13
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
230
13
  int rc = lua_istable(L, index);
231
13
  assert(rc == 0 || rc == 1);
232
13
}
233
234
/* void lua_pushinteger(lua_State *L, lua_Integer n); */
235
/* [-0, +1, -] */
236
static void
237
__lua_pushinteger(lua_State *L, FuzzedDataProvider *fdp)
238
92
{
239
92
  int top = lua_gettop(L);
240
92
  uint8_t n = fdp->ConsumeIntegral<uint8_t>();
241
92
  lua_pushinteger(L, n);
242
92
  assert(lua_gettop(L) == top + 1);
243
92
}
244
245
/* void lua_pushlstring(lua_State *L, const char *s, size_t len); */
246
/* [-0, +1, m] */
247
static void
248
__lua_pushlstring(lua_State *L, FuzzedDataProvider *fdp)
249
138
{
250
138
  int top = lua_gettop(L);
251
138
  auto str = fdp->ConsumeRandomLengthString(max_str_len);
252
138
  lua_pushlstring(L, str.c_str(), str.size());
253
138
  assert(lua_gettop(L) == top + 1);
254
138
}
255
256
/* void lua_pushnil(lua_State *L); */
257
/* [-0, +1, -] */
258
static void
259
__lua_pushnil(lua_State *L, FuzzedDataProvider *fdp)
260
398
{
261
398
  int top = lua_gettop(L);
262
398
  lua_pushnil(L);
263
398
  assert(lua_gettop(L) == top + 1);
264
398
}
265
266
/* void lua_pushnumber(lua_State *L, lua_Number n); */
267
/* [-0, +1, -] */
268
static void
269
__lua_pushnumber(lua_State *L, FuzzedDataProvider *fdp)
270
142
{
271
142
  int top = lua_gettop(L);
272
142
  uint8_t n = fdp->ConsumeIntegral<uint8_t>();
273
142
  lua_pushnumber(L, n);
274
142
  assert(lua_gettop(L) == top + 1);
275
142
}
276
277
/* void lua_pushvalue(lua_State *L, int index); */
278
/* [-0, +1, -] */
279
static void
280
__lua_pushvalue(lua_State *L, FuzzedDataProvider *fdp)
281
21
{
282
21
  int top = lua_gettop(L);
283
21
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
284
21
  lua_pushvalue(L, index);
285
21
  assert(lua_gettop(L) == top + 1);
286
21
}
287
288
/* void lua_remove(lua_State *L, int index); */
289
/* [-1, +0, -] */
290
static void
291
__lua_remove(lua_State *L, FuzzedDataProvider *fdp)
292
4
{
293
4
  int top = lua_gettop(L);
294
4
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
295
4
  lua_remove(L, index);
296
4
  assert(lua_gettop(L) == top - 1);
297
4
}
298
299
/* void lua_replace(lua_State *L, int index); */
300
/* [-1, +0, -] */
301
static void
302
__lua_replace(lua_State *L, FuzzedDataProvider *fdp)
303
10
{
304
10
  int top = lua_gettop(L);
305
10
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
306
10
  lua_replace(L, index);
307
10
  assert(lua_gettop(L) == top - 1);
308
10
}
309
310
/* void lua_setglobal(lua_State *L, const char *name); */
311
/* [-1, +0, e] */
312
static void
313
__lua_setglobal(lua_State *L, FuzzedDataProvider *fdp)
314
4
{
315
4
  int top = lua_gettop(L);
316
4
  auto str = fdp->ConsumeRandomLengthString(max_str_len);
317
4
  lua_setglobal(L, str.c_str());
318
4
  assert(lua_gettop(L) == top - 1);
319
4
}
320
321
/* void lua_settop(lua_State *L, int index); */
322
/* [-?, +?, -] */
323
static void
324
__lua_settop(lua_State *L, FuzzedDataProvider *fdp)
325
11
{
326
11
  int top = lua_gettop(L);
327
11
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
328
11
  lua_settop(L, index);
329
11
  assert(lua_gettop(L) == index);
330
11
}
331
332
/* int lua_status(lua_State *L); */
333
/* [-0, +0, -] */
334
static void
335
__lua_status(lua_State *L, FuzzedDataProvider *fdp)
336
1
{
337
1
  int rc = lua_status(L);
338
1
  assert(rc == 0 || rc == LUA_YIELD);
339
1
}
340
341
/* int lua_toboolean(lua_State *L, int index); */
342
/* [-0, +0, -] */
343
static void
344
__lua_toboolean(lua_State *L, FuzzedDataProvider *fdp)
345
22
{
346
22
  int top = lua_gettop(L);
347
22
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
348
22
  int rc = lua_toboolean(L, index);
349
22
  assert(rc == 0 || rc == 1);
350
22
}
351
352
/* lua_Integer lua_tointeger(lua_State *L, int index); */
353
/* [-0, +0, -] */
354
static void
355
__lua_tointeger(lua_State *L, FuzzedDataProvider *fdp)
356
21
{
357
21
  int top = lua_gettop(L);
358
21
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
359
21
  lua_tointeger(L, index);
360
21
  assert(lua_gettop(L) == top);
361
21
}
362
363
/* const char *lua_tolstring(lua_State *L, int index, size_t *len); */
364
/* [-0, +0, m] */
365
static void
366
__lua_tolstring(lua_State *L, FuzzedDataProvider *fdp)
367
16
{
368
16
  int top = lua_gettop(L);
369
16
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
370
16
  lua_tolstring(L, index, NULL);
371
16
  assert(lua_gettop(L) == top);
372
16
}
373
374
/* const char *lua_tostring(lua_State *L, int index); */
375
/* [-0, +0, m] */
376
static void
377
__lua_tostring(lua_State *L, FuzzedDataProvider *fdp)
378
16
{
379
16
  int top = lua_gettop(L);
380
16
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
381
16
  lua_tostring(L, index);
382
16
  assert(lua_gettop(L) == top);
383
16
}
384
385
/* int lua_type(lua_State *L, int index); */
386
/* [-0, +0, -] */
387
static void
388
__lua_type(lua_State *L, FuzzedDataProvider *fdp)
389
24
{
390
24
  int top = lua_gettop(L);
391
24
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
392
24
  int type = lua_type(L, index);
393
24
  assert(type == LUA_TBOOLEAN       ||
394
24
         type == LUA_TFUNCTION      ||
395
24
         type == LUA_TLIGHTUSERDATA ||
396
24
         type == LUA_TNIL           ||
397
24
         type == LUA_TNONE          ||
398
24
         type == LUA_TNUMBER        ||
399
24
         type == LUA_TSTRING        ||
400
24
         type == LUA_TTABLE         ||
401
24
         type == LUA_TTHREAD        ||
402
24
         type == LUA_TUSERDATA);
403
0
  assert(lua_gettop(L) == top);
404
24
}
405
406
/* void lua_getglobal(lua_State *L, const char *name); */
407
/* [-0, +1, e] */
408
static void
409
__lua_getglobal(lua_State *L, FuzzedDataProvider *fdp)
410
2
{
411
2
  auto name = fdp->ConsumeRandomLengthString(max_str_len);
412
2
  int top = lua_gettop(L);
413
2
  lua_getglobal(L, name.c_str());
414
2
  assert(lua_gettop(L) == top + 1);
415
2
}
416
417
/* const char *lua_setupvalue(lua_State *L, int funcindex, int n); */
418
/* [-(0|1), +0, –] */
419
static void
420
__lua_setupvalue(lua_State *L, FuzzedDataProvider *fdp)
421
22
{
422
22
  int top = lua_gettop(L);
423
22
  int funcindex = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
424
22
  int n = fdp->ConsumeIntegral<uint8_t>();
425
22
  lua_setupvalue(L, funcindex, n);
426
22
  assert(lua_gettop(L) == top);
427
22
}
428
429
/* const char *lua_getupvalue(lua_State *L, int funcindex, int n); */
430
/* [-0, +(0|1), –] */
431
static void
432
__lua_getupvalue(lua_State *L, FuzzedDataProvider *fdp)
433
25
{
434
25
  int top = lua_gettop(L);
435
25
  int funcindex = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
436
25
  int n = fdp->ConsumeIntegral<uint8_t>();
437
25
  lua_getupvalue(L, funcindex, n);
438
25
  assert(lua_gettop(L) == top || lua_gettop(L) == top + 1);
439
25
}
440
441
/* [-0, +0, -] */
442
/* void *lua_touserdata(lua_State *L, int index); */
443
static void
444
__lua_touserdata(lua_State *L, FuzzedDataProvider *fdp)
445
12
{
446
12
  int top = lua_gettop(L);
447
12
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
448
12
  lua_touserdata(L, index);
449
12
  assert(lua_gettop(L) == top);
450
12
}
451
452
/* int lua_islightuserdata(lua_State *L, int index); */
453
/* [-0, +0, -] */
454
static void
455
__lua_islightuserdata(lua_State *L, FuzzedDataProvider *fdp)
456
5
{
457
5
  int top = lua_gettop(L);
458
5
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
459
5
  int rc = lua_islightuserdata(L, index);
460
5
  assert(rc == 0 || rc == 1);
461
5
}
462
463
/* int lua_isuserdata(lua_State *L, int index); */
464
/* [-0, +0, -] */
465
static void
466
__lua_isuserdata(lua_State *L, FuzzedDataProvider *fdp)
467
21
{
468
21
  int top = lua_gettop(L);
469
21
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
470
21
  int rc = lua_isuserdata(L, index);
471
21
  assert(rc == 0 || rc == 1);
472
21
}
473
474
/* int lua_isthread(lua_State *L, int index); */
475
/* [-0, +0, -] */
476
static void
477
__lua_isthread(lua_State *L, FuzzedDataProvider *fdp)
478
13
{
479
13
  int top = lua_gettop(L);
480
13
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
481
13
  int rc = lua_isthread(L, index);
482
13
  assert(rc == 0 || rc == 1);
483
13
}
484
485
/* int lua_pushthread(lua_State *L); */
486
/* [-0, +1, -] */
487
static void
488
__lua_pushthread(lua_State *L, FuzzedDataProvider *fdp)
489
2
{
490
2
  int top = lua_gettop(L);
491
2
  int rc = lua_pushthread(L);
492
2
  assert(rc == 1);
493
0
  assert(lua_gettop(L) == top + 1);
494
2
}
495
496
/* int lua_next(lua_State *L, int index); */
497
/* [-1, +(2|0), e] */
498
static void
499
__lua_next(lua_State *L, FuzzedDataProvider *fdp)
500
18
{
501
18
  int top = lua_gettop(L);
502
18
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
503
18
  if (!lua_istable(L, index))
504
15
    return;
505
3
  lua_pushnil(L);  /* first key */
506
3
  lua_next(L, index);
507
3
  assert(lua_gettop(L) - top - 1 <= 2);
508
3
}
509
510
/* int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar); */
511
/* [-(0|1), +(0|1|2), m] */
512
static void
513
__lua_getinfo(lua_State *L, FuzzedDataProvider *fdp)
514
1
{
515
1
  lua_Debug ar;
516
1
  lua_pushcfunction(L, cfunction);
517
  /* XXX: Choose 'what' mode randomly. */
518
1
  lua_getinfo(L, ">", &ar);
519
1
}
520
521
/* int lua_getstack(lua_State *L, int level, lua_Debug *ar); */
522
/* [-0, +0, –] */
523
static void
524
__lua_getstack(lua_State *L, FuzzedDataProvider *fdp)
525
19
{
526
19
  int top = lua_gettop(L);
527
19
  int max_stack_depth = 10;
528
19
  int level = fdp->ConsumeIntegralInRange<uint8_t>(1, max_stack_depth);
529
19
  lua_Debug ar;
530
19
  lua_getstack(L, level, &ar);
531
19
  assert(lua_gettop(L) == top);
532
19
}
533
534
/* void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n); */
535
/* [-n, +1, m] */
536
static void
537
__lua_pushcclosure(lua_State *L, FuzzedDataProvider *fdp)
538
38
{
539
  /* Maximum n is 255 in lua_pushcclosure(3). */
540
38
  int n = fdp->ConsumeIntegralInRange<uint8_t>(1, 10);
541
167
  for (int i = 1; i < n; i++)
542
129
    lua_pushnumber(L, i);
543
38
  lua_pushcclosure(L, cfunction, n);
544
38
}
545
546
/* void lua_pushcfunction(lua_State *L, lua_CFunction f); */
547
/* [-0, +1, m] */
548
static void
549
__lua_pushcfunction(lua_State *L, FuzzedDataProvider *fdp)
550
1
{
551
1
  int top = lua_gettop(L);
552
1
  lua_pushcfunction(L, cfunction);
553
1
  assert(lua_gettop(L) == top + 1);
554
1
}
555
556
/* int lua_getmetatable(lua_State *L, int index); */
557
/* [-0, +(0|1), -] */
558
static void
559
__lua_getmetatable(lua_State *L, FuzzedDataProvider *fdp)
560
17
{
561
17
  int top = lua_gettop(L);
562
17
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
563
17
  lua_getmetatable(L, index);
564
17
  assert(lua_gettop(L) - top <= 1);
565
17
}
566
567
/* void lua_newtable(lua_State *L); */
568
/* [-0, +1, m] */
569
static void
570
__lua_newtable(lua_State *L, FuzzedDataProvider *fdp)
571
892
{
572
892
  int top = lua_gettop(L);
573
892
  lua_newtable(L);
574
892
  assert(lua_gettop(L) == top + 1);
575
892
}
576
577
/* lua_State *lua_newthread(lua_State *L); */
578
/* [-0, +1, m] */
579
static void
580
__lua_newthread(lua_State *L, FuzzedDataProvider *fdp)
581
335
{
582
335
  int top = lua_gettop(L);
583
335
  lua_newthread(L);
584
335
  assert(lua_gettop(L) == top + 1);
585
335
}
586
587
/* const char *lua_typename(lua_State *L, int tp); */
588
/* [-0, +0, -] */
589
static void
590
__lua_typename(lua_State *L, FuzzedDataProvider *fdp)
591
4
{
592
4
  int top = lua_gettop(L);
593
4
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
594
4
  const char* name = lua_typename(L, index);
595
4
  assert(name);
596
0
  assert(lua_gettop(L) == top);
597
4
}
598
599
int gc_mode[] = {
600
  LUA_GCCOLLECT,
601
  LUA_GCCOUNT,
602
  LUA_GCCOUNTB,
603
  LUA_GCRESTART,
604
  LUA_GCSETPAUSE,
605
  LUA_GCSETSTEPMUL,
606
  LUA_GCSTEP,
607
  LUA_GCSTOP,
608
};
609
610
/* int lua_gc(lua_State *L, int what, int data); */
611
/* [-0, +0, e] */
612
static void
613
__lua_gc(lua_State *L, FuzzedDataProvider *fdp)
614
1.02k
{
615
1.02k
  int top = lua_gettop(L);
616
1.02k
  uint8_t idx = fdp->ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(gc_mode) - 1);
617
1.02k
  lua_gc(L, gc_mode[idx], 0);
618
1.02k
  assert(lua_gettop(L) == top);
619
1.02k
}
620
621
int hook_mode[] = {
622
  LUA_MASKCALL,
623
  LUA_MASKCOUNT,
624
  LUA_MASKLINE,
625
  LUA_MASKRET,
626
};
627
628
static void
629
Hook(lua_State *L, lua_Debug *ar)
630
0
{
631
0
  (void)L;
632
0
  (void)ar;
633
0
}
634
635
/* int lua_sethook(lua_State *L, lua_Hook f, int mask, int count); */
636
/* [-0, +0, -] */
637
static void
638
__lua_sethook(lua_State *L, FuzzedDataProvider *fdp)
639
1.00k
{
640
1.00k
  int top = lua_gettop(L);
641
1.00k
  uint8_t idx = fdp->ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(hook_mode) - 1);
642
1.00k
  lua_sethook(L, Hook, hook_mode[idx], 1);
643
1.00k
  assert(lua_gettop(L) == top);
644
1.00k
}
645
646
/* lua_Hook lua_gethook(lua_State *L); */
647
/* [-0, +0, –] */
648
static void
649
__lua_gethook(lua_State *L, FuzzedDataProvider *fdp)
650
1
{
651
1
  int top = lua_gettop(L);
652
1
  lua_gethook(L);
653
1
  assert(lua_gettop(L) == top);
654
1
}
655
656
/* int lua_gethookcount(lua_State *L); */
657
/* [-0, +0, –] */
658
static void
659
__lua_gethookcount(lua_State *L, FuzzedDataProvider *fdp)
660
2
{
661
2
  int top = lua_gettop(L);
662
2
  int hook_count = lua_gethookcount(L);
663
2
  assert(hook_count >= 0);
664
0
  assert(lua_gettop(L) == top);
665
2
}
666
667
/* int lua_gethookmask(lua_State *L); */
668
/* [-0, +0, –] */
669
static void
670
__lua_gethookmask(lua_State *L, FuzzedDataProvider *fdp)
671
3
{
672
3
  int top = lua_gettop(L);
673
3
  int hook_mask = lua_gethookmask(L);
674
3
  assert(hook_mask >= 0);
675
0
  assert(lua_gettop(L) == top);
676
3
}
677
678
/* void lua_rawget(lua_State *L, int index); */
679
/* [-1, +1, -] */
680
static void
681
__lua_rawget(lua_State *L, FuzzedDataProvider *fdp)
682
44
{
683
44
  int top = lua_gettop(L);
684
44
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
685
44
  if (!lua_istable(L, index))
686
19
    return;
687
25
  uint8_t key = fdp->ConsumeIntegral<uint8_t>();
688
25
  lua_pushnumber(L, key);
689
25
  lua_rawget(L, index);
690
  /* XXX: Wrong number of elements. */
691
  /* assert(lua_gettop(L) == top); */
692
25
}
693
694
/* void lua_rawset(lua_State *L, int index); */
695
/* [-2, +0, m] */
696
static void
697
__lua_rawset(lua_State *L, FuzzedDataProvider *fdp)
698
44
{
699
44
  int top = lua_gettop(L);
700
44
  if (top == 0)
701
0
    return;
702
44
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
703
44
  if (!lua_istable(L, index))
704
  /* if (lua_type(L, index) != LUA_TTABLE) */
705
5
    return;
706
39
  uint8_t key = fdp->ConsumeIntegral<uint8_t>();
707
39
  uint8_t value = fdp->ConsumeIntegral<uint8_t>();
708
39
  lua_pushnumber(L, value);
709
39
  lua_pushnumber(L, key);
710
39
  lua_rawset(L, index);
711
  /* XXX: Wrong number of elements. */
712
  /* assert(lua_gettop(L) == top - 2); */
713
39
}
714
715
/* void lua_rawseti(lua_State *L, int index, lua_Integer i); */
716
/* [-1, +0, m] */
717
static void
718
__lua_rawseti(lua_State *L, FuzzedDataProvider *fdp)
719
55
{
720
55
  int top = lua_gettop(L);
721
55
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
722
55
  if (!lua_istable(L, index))
723
5
    return;
724
50
  int n = fdp->ConsumeIntegral<uint8_t>();
725
50
  __lua_pushnumber(L, fdp);
726
50
  lua_rawseti(L, index, n);
727
  /* XXX: Wrong number of elements. */
728
  /* assert(lua_gettop(L) == top - 1); */
729
50
}
730
731
/* int lua_rawgeti(lua_State *L, int index, lua_Integer n); */
732
/* [-0, +1, –] */
733
static void
734
__lua_rawgeti(lua_State *L, FuzzedDataProvider *fdp)
735
43
{
736
43
  int top = lua_gettop(L);
737
43
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
738
43
  if (!lua_istable(L, index))
739
12
    return;
740
31
  int i = fdp->ConsumeIntegral<uint8_t>();
741
31
  lua_rawgeti(L, index, i);
742
31
  assert(lua_gettop(L) == top + 1);
743
31
}
744
745
typedef void
746
(*lua_func)(lua_State *L, FuzzedDataProvider *fdp);
747
748
static lua_func push_func[] = {
749
  &__lua_newtable,
750
  &__lua_newthread,
751
  &__lua_pushboolean,
752
  &__lua_pushinteger,
753
  &__lua_pushlstring,
754
  &__lua_pushnil,
755
  &__lua_pushnumber,
756
  &__lua_pushstring,
757
};
758
759
static void
760
lua_pushrandom(lua_State *L, FuzzedDataProvider *fdp)
761
2.15k
{
762
2.15k
  uint8_t idx = fdp->ConsumeIntegralInRange(0, (int)ARRAY_SIZE(push_func) - 1);
763
2.15k
  push_func[idx](L, fdp);
764
2.15k
}
765
766
/* void lua_createtable(lua_State *L, int narr, int nrec); */
767
/* [-0, +1, m] */
768
static void
769
__lua_createtable(lua_State *L, FuzzedDataProvider *fdp)
770
86
{
771
86
  int nrows = fdp->ConsumeIntegral<uint8_t>();
772
  /* XXX: Lua associative arrays. */
773
86
  lua_createtable(L, nrows, 0);
774
11.1k
  for (int i = 0; i < nrows; i++) {
775
11.0k
    lua_pushnumber(L, i);
776
11.0k
    lua_rawseti(L, -2, i + 1);
777
11.0k
  }
778
86
  assert(lua_gettop(L) != 0);
779
86
}
780
781
lua_func func[] = {
782
  &__lua_checkstack,
783
  &__lua_concat,
784
  &__lua_createtable,
785
  &__lua_gc,
786
  &__lua_getglobal,
787
  &__lua_gethook,
788
  &__lua_gethookcount,
789
  &__lua_gethookmask,
790
  &__lua_getinfo,
791
  &__lua_getmetatable,
792
  &__lua_getstack,
793
  &__lua_gettop,
794
  &__lua_getupvalue,
795
  &__lua_insert,
796
  &__lua_isboolean,
797
  &__lua_iscfunction,
798
  &__lua_isfunction,
799
  &__lua_islightuserdata,
800
  &__lua_isnil,
801
  &__lua_isnone,
802
  &__lua_isnoneornil,
803
  &__lua_isnumber,
804
  &__lua_isstring,
805
  &__lua_istable,
806
  &__lua_isthread,
807
  &__lua_isuserdata,
808
  &__lua_newtable,
809
  &__lua_newthread,
810
  &__lua_next,
811
  &__lua_pop,
812
  &__lua_pushboolean,
813
  &__lua_pushcclosure,
814
  &__lua_pushcfunction,
815
  &__lua_pushinteger,
816
  &__lua_pushlstring,
817
  &__lua_pushnil,
818
  &__lua_pushnumber,
819
  &__lua_pushstring,
820
  &__lua_pushthread,
821
  &__lua_pushvalue,
822
  &__lua_rawget,
823
  &__lua_rawgeti,
824
  &__lua_rawset,
825
  &__lua_rawseti,
826
  &__lua_remove,
827
  &__lua_replace,
828
  &__lua_setglobal,
829
  &__lua_settop,
830
  &__lua_setupvalue,
831
  &__lua_status,
832
  &__lua_toboolean,
833
  &__lua_tointeger,
834
  &__lua_tolstring,
835
  &__lua_tonumber,
836
  &__lua_tostring,
837
  &__lua_touserdata,
838
  &__lua_type,
839
  &__lua_typename,
840
};
841
842
extern "C" int
843
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
844
1.10k
{
845
1.10k
  lua_State *L = luaL_newstate();
846
1.10k
  if (L == NULL)
847
0
    return 0;
848
849
1.10k
  FuzzedDataProvider fdp(data, size);
850
1.10k
  int start_slots = 2;
851
3.32k
  for (int i = 1; i <= start_slots; i++)
852
2.21k
    if (fdp.remaining_bytes() != 0)
853
2.15k
      lua_pushrandom(L, &fdp);
854
855
1.10k
  if (lua_gettop(L) != 0 &&
856
1.10k
      fdp.remaining_bytes() != 0) {
857
1.00k
    __lua_gc(L, &fdp);
858
1.00k
    __lua_sethook(L, &fdp);
859
1.00k
    uint8_t idx = fdp.ConsumeIntegralInRange<uint8_t>(0, (int)ARRAY_SIZE(func) - 1);
860
1.00k
    func[idx](L, &fdp);
861
1.00k
  }
862
863
1.10k
  lua_settop(L, 0);
864
1.10k
  lua_close(L);
865
866
1.10k
  return 0;
867
1.10k
}