Coverage Report

Created: 2023-09-30 06:14

/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
6.14k
#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
187
{
48
187
  auto str = fdp->ConsumeRandomLengthString(max_str_len);
49
187
  int top = lua_gettop(L);
50
187
  lua_pushstring(L, str.c_str());
51
187
  assert(lua_gettop(L) == top + 1);
52
187
}
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
68
{
59
68
  uint8_t n = fdp->ConsumeIntegral<uint8_t>();
60
68
  int top = lua_gettop(L);
61
68
  lua_pushboolean(L, n);
62
68
  assert(lua_gettop(L) == top + 1);
63
68
}
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
20
{
70
20
  int top = lua_gettop(L);
71
20
  uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
72
20
  lua_pop(L, n);
73
20
  assert(lua_gettop(L) == top - n);
74
20
}
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
38
{
92
38
  int top = lua_gettop(L);
93
38
  uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
94
38
  lua_tonumber(L, n);
95
38
  assert(lua_gettop(L) == top);
96
38
}
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
93
{
103
93
  uint8_t n = fdp->ConsumeIntegral<uint8_t>();
104
93
  int rc = lua_checkstack(L, n);
105
93
  assert(rc != 0);
106
93
}
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
59
{
113
59
  int top = lua_gettop(L);
114
59
  uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
115
118
  for (int i = 1; i <= n; i++) {
116
85
    int t = lua_type(L, -i);
117
85
    if (t != LUA_TNUMBER &&
118
85
        t != LUA_TSTRING)
119
26
      return;
120
85
  }
121
33
  lua_concat(L, n);
122
33
  assert(lua_gettop(L) == top - n + 1);
123
33
}
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
21
{
139
21
  int top = lua_gettop(L);
140
21
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
141
21
  lua_insert(L, index);
142
21
  assert(lua_gettop(L) == top - 1 + 1);
143
21
}
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
3
{
150
3
  int top = lua_gettop(L);
151
3
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
152
3
  int rc = lua_isboolean(L, index);
153
3
  assert(rc == 0 || rc == 1);
154
3
}
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
10
{
161
10
  int top = lua_gettop(L);
162
10
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
163
10
  int rc = lua_iscfunction(L, index);
164
10
  assert(rc == 0 || rc == 1);
165
10
}
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
11
{
172
11
  int top = lua_gettop(L);
173
11
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
174
11
  int rc = lua_isfunction(L, index);
175
11
  assert(rc == 0 || rc == 1);
176
11
}
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
8
{
183
8
  int top = lua_gettop(L);
184
8
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
185
8
  int rc = lua_isnil(L, index);
186
8
  assert(rc == 0 || rc == 1);
187
8
}
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
17
{
194
17
  int top = lua_gettop(L);
195
17
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
196
17
  int rc = lua_isnone(L, index);
197
17
  assert(rc == 0 || rc == 1);
198
0
  assert(lua_gettop(L) == top);
199
17
}
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
20
{
206
20
  int top = lua_gettop(L);
207
20
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
208
20
  lua_isnoneornil(L, index);
209
20
  assert(lua_gettop(L) == top);
210
20
}
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
17
{
217
17
  int top = lua_gettop(L);
218
17
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
219
17
  int rc = lua_isstring(L, index);
220
17
  assert(rc == 0 || rc == 1);
221
17
}
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
19
{
228
19
  int top = lua_gettop(L);
229
19
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
230
19
  int rc = lua_istable(L, index);
231
19
  assert(rc == 0 || rc == 1);
232
19
}
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
89
{
239
89
  int top = lua_gettop(L);
240
89
  uint8_t n = fdp->ConsumeIntegral<uint8_t>();
241
89
  lua_pushinteger(L, n);
242
89
  assert(lua_gettop(L) == top + 1);
243
89
}
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
136
{
250
136
  int top = lua_gettop(L);
251
136
  auto str = fdp->ConsumeRandomLengthString(max_str_len);
252
136
  lua_pushlstring(L, str.c_str(), str.size());
253
136
  assert(lua_gettop(L) == top + 1);
254
136
}
255
256
/* void lua_pushnil(lua_State *L); */
257
/* [-0, +1, -] */
258
static void
259
__lua_pushnil(lua_State *L, FuzzedDataProvider *fdp)
260
424
{
261
424
  int top = lua_gettop(L);
262
424
  lua_pushnil(L);
263
424
  assert(lua_gettop(L) == top + 1);
264
424
}
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
145
{
271
145
  int top = lua_gettop(L);
272
145
  uint8_t n = fdp->ConsumeIntegral<uint8_t>();
273
145
  lua_pushnumber(L, n);
274
145
  assert(lua_gettop(L) == top + 1);
275
145
}
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
24
{
282
24
  int top = lua_gettop(L);
283
24
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
284
24
  lua_pushvalue(L, index);
285
24
  assert(lua_gettop(L) == top + 1);
286
24
}
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
15
{
293
15
  int top = lua_gettop(L);
294
15
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
295
15
  lua_remove(L, index);
296
15
  assert(lua_gettop(L) == top - 1);
297
15
}
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
8
{
304
8
  int top = lua_gettop(L);
305
8
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
306
8
  lua_replace(L, index);
307
8
  assert(lua_gettop(L) == top - 1);
308
8
}
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
14
{
326
14
  int top = lua_gettop(L);
327
14
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
328
14
  lua_settop(L, index);
329
14
  assert(lua_gettop(L) == index);
330
14
}
331
332
/* int lua_status(lua_State *L); */
333
/* [-0, +0, -] */
334
static void
335
__lua_status(lua_State *L, FuzzedDataProvider *fdp)
336
5
{
337
5
  int rc = lua_status(L);
338
5
  assert(rc == 0 || rc == LUA_YIELD);
339
5
}
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
26
{
346
26
  int top = lua_gettop(L);
347
26
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
348
26
  int rc = lua_toboolean(L, index);
349
26
  assert(rc == 0 || rc == 1);
350
26
}
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
29
{
357
29
  int top = lua_gettop(L);
358
29
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
359
29
  lua_tointeger(L, index);
360
29
  assert(lua_gettop(L) == top);
361
29
}
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
15
{
368
15
  int top = lua_gettop(L);
369
15
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
370
15
  lua_tolstring(L, index, NULL);
371
15
  assert(lua_gettop(L) == top);
372
15
}
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
26
{
379
26
  int top = lua_gettop(L);
380
26
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
381
26
  lua_tostring(L, index);
382
26
  assert(lua_gettop(L) == top);
383
26
}
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
28
{
390
28
  int top = lua_gettop(L);
391
28
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
392
28
  int type = lua_type(L, index);
393
28
  assert(type == LUA_TBOOLEAN       ||
394
28
         type == LUA_TFUNCTION      ||
395
28
         type == LUA_TLIGHTUSERDATA ||
396
28
         type == LUA_TNIL           ||
397
28
         type == LUA_TNONE          ||
398
28
         type == LUA_TNUMBER        ||
399
28
         type == LUA_TSTRING        ||
400
28
         type == LUA_TTABLE         ||
401
28
         type == LUA_TTHREAD        ||
402
28
         type == LUA_TUSERDATA);
403
0
  assert(lua_gettop(L) == top);
404
28
}
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
46
{
422
46
  int top = lua_gettop(L);
423
46
  int funcindex = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
424
46
  int n = fdp->ConsumeIntegral<uint8_t>();
425
46
  lua_setupvalue(L, funcindex, n);
426
46
  assert(lua_gettop(L) == top);
427
46
}
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
22
{
434
22
  int top = lua_gettop(L);
435
22
  int funcindex = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
436
22
  int n = fdp->ConsumeIntegral<uint8_t>();
437
22
  lua_getupvalue(L, funcindex, n);
438
22
  assert(lua_gettop(L) == top || lua_gettop(L) == top + 1);
439
22
}
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
20
{
446
20
  int top = lua_gettop(L);
447
20
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
448
20
  lua_touserdata(L, index);
449
20
  assert(lua_gettop(L) == top);
450
20
}
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
9
{
457
9
  int top = lua_gettop(L);
458
9
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
459
9
  int rc = lua_islightuserdata(L, index);
460
9
  assert(rc == 0 || rc == 1);
461
9
}
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
10
{
468
10
  int top = lua_gettop(L);
469
10
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
470
10
  int rc = lua_isuserdata(L, index);
471
10
  assert(rc == 0 || rc == 1);
472
10
}
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
11
{
479
11
  int top = lua_gettop(L);
480
11
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
481
11
  int rc = lua_isthread(L, index);
482
11
  assert(rc == 0 || rc == 1);
483
11
}
484
485
/* int lua_pushthread(lua_State *L); */
486
/* [-0, +1, -] */
487
static void
488
__lua_pushthread(lua_State *L, FuzzedDataProvider *fdp)
489
1
{
490
1
  int top = lua_gettop(L);
491
1
  int rc = lua_pushthread(L);
492
1
  assert(rc == 1);
493
0
  assert(lua_gettop(L) == top + 1);
494
1
}
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
37
{
501
37
  int top = lua_gettop(L);
502
37
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
503
37
  if (!lua_istable(L, index))
504
15
    return;
505
22
  lua_pushnil(L);  /* first key */
506
22
  lua_next(L, index);
507
22
  assert(lua_gettop(L) - top - 1 <= 2);
508
22
}
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
25
{
526
25
  int top = lua_gettop(L);
527
25
  int max_stack_depth = 10;
528
25
  int level = fdp->ConsumeIntegralInRange<uint8_t>(1, max_stack_depth);
529
25
  lua_Debug ar;
530
25
  lua_getstack(L, level, &ar);
531
25
  assert(lua_gettop(L) == top);
532
25
}
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
52
{
539
  /* Maximum n is 255 in lua_pushcclosure(3). */
540
52
  int n = fdp->ConsumeIntegralInRange<uint8_t>(1, 10);
541
219
  for (int i = 1; i < n; i++)
542
167
    lua_pushnumber(L, i);
543
52
  lua_pushcclosure(L, cfunction, n);
544
52
}
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
2
{
551
2
  int top = lua_gettop(L);
552
2
  lua_pushcfunction(L, cfunction);
553
2
  assert(lua_gettop(L) == top + 1);
554
2
}
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
36
{
561
36
  int top = lua_gettop(L);
562
36
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
563
36
  lua_getmetatable(L, index);
564
36
  assert(lua_gettop(L) - top <= 1);
565
36
}
566
567
/* void lua_newtable(lua_State *L); */
568
/* [-0, +1, m] */
569
static void
570
__lua_newtable(lua_State *L, FuzzedDataProvider *fdp)
571
1.12k
{
572
1.12k
  int top = lua_gettop(L);
573
1.12k
  lua_newtable(L);
574
1.12k
  assert(lua_gettop(L) == top + 1);
575
1.12k
}
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
471
{
582
471
  int top = lua_gettop(L);
583
471
  lua_newthread(L);
584
471
  assert(lua_gettop(L) == top + 1);
585
471
}
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
5
{
592
5
  int top = lua_gettop(L);
593
5
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
594
5
  const char* name = lua_typename(L, index);
595
5
  assert(name);
596
0
  assert(lua_gettop(L) == top);
597
5
}
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.21k
{
615
1.21k
  int top = lua_gettop(L);
616
1.21k
  uint8_t idx = fdp->ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(gc_mode) - 1);
617
1.21k
  lua_gc(L, gc_mode[idx], 0);
618
1.21k
  assert(lua_gettop(L) == top);
619
1.21k
}
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.19k
{
640
1.19k
  int top = lua_gettop(L);
641
1.19k
  uint8_t idx = fdp->ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(hook_mode) - 1);
642
1.19k
  lua_sethook(L, Hook, hook_mode[idx], 1);
643
1.19k
  assert(lua_gettop(L) == top);
644
1.19k
}
645
646
/* lua_Hook lua_gethook(lua_State *L); */
647
/* [-0, +0, –] */
648
static void
649
__lua_gethook(lua_State *L, FuzzedDataProvider *fdp)
650
3
{
651
3
  int top = lua_gettop(L);
652
3
  lua_gethook(L);
653
3
  assert(lua_gettop(L) == top);
654
3
}
655
656
/* int lua_gethookcount(lua_State *L); */
657
/* [-0, +0, –] */
658
static void
659
__lua_gethookcount(lua_State *L, FuzzedDataProvider *fdp)
660
4
{
661
4
  int top = lua_gettop(L);
662
4
  int hook_count = lua_gethookcount(L);
663
4
  assert(hook_count >= 0);
664
0
  assert(lua_gettop(L) == top);
665
4
}
666
667
/* int lua_gethookmask(lua_State *L); */
668
/* [-0, +0, –] */
669
static void
670
__lua_gethookmask(lua_State *L, FuzzedDataProvider *fdp)
671
2
{
672
2
  int top = lua_gettop(L);
673
2
  int hook_mask = lua_gethookmask(L);
674
2
  assert(hook_mask >= 0);
675
0
  assert(lua_gettop(L) == top);
676
2
}
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
46
{
683
46
  int top = lua_gettop(L);
684
46
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
685
46
  if (!lua_istable(L, index))
686
6
    return;
687
40
  uint8_t key = fdp->ConsumeIntegral<uint8_t>();
688
40
  lua_pushnumber(L, key);
689
40
  lua_rawget(L, index);
690
  /* XXX: Wrong number of elements. */
691
  /* assert(lua_gettop(L) == top); */
692
40
}
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
46
{
699
46
  int top = lua_gettop(L);
700
46
  if (top == 0)
701
0
    return;
702
46
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
703
46
  if (!lua_istable(L, index))
704
  /* if (lua_type(L, index) != LUA_TTABLE) */
705
6
    return;
706
40
  uint8_t key = fdp->ConsumeIntegral<uint8_t>();
707
40
  uint8_t value = fdp->ConsumeIntegral<uint8_t>();
708
40
  lua_pushnumber(L, value);
709
40
  lua_pushnumber(L, key);
710
40
  lua_rawset(L, index);
711
  /* XXX: Wrong number of elements. */
712
  /* assert(lua_gettop(L) == top - 2); */
713
40
}
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
67
{
720
67
  int top = lua_gettop(L);
721
67
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
722
67
  if (!lua_istable(L, index))
723
6
    return;
724
61
  int n = fdp->ConsumeIntegral<uint8_t>();
725
61
  __lua_pushnumber(L, fdp);
726
61
  lua_rawseti(L, index, n);
727
  /* XXX: Wrong number of elements. */
728
  /* assert(lua_gettop(L) == top - 1); */
729
61
}
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
46
{
736
46
  int top = lua_gettop(L);
737
46
  uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top);
738
46
  if (!lua_istable(L, index))
739
8
    return;
740
38
  int i = fdp->ConsumeIntegral<uint8_t>();
741
38
  lua_rawgeti(L, index, i);
742
38
  assert(lua_gettop(L) == top + 1);
743
38
}
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.53k
{
762
2.53k
  uint8_t idx = fdp->ConsumeIntegralInRange(0, (int)ARRAY_SIZE(push_func) - 1);
763
2.53k
  push_func[idx](L, fdp);
764
2.53k
}
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
84
{
771
84
  int nrows = fdp->ConsumeIntegral<uint8_t>();
772
  /* XXX: Lua associative arrays. */
773
84
  lua_createtable(L, nrows, 0);
774
10.6k
  for (int i = 0; i < nrows; i++) {
775
10.5k
    lua_pushnumber(L, i);
776
10.5k
    lua_rawseti(L, -2, i + 1);
777
10.5k
  }
778
84
  assert(lua_gettop(L) != 0);
779
84
}
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.30k
{
845
1.30k
  lua_State *L = luaL_newstate();
846
1.30k
  if (L == NULL)
847
0
    return 0;
848
849
1.30k
  FuzzedDataProvider fdp(data, size);
850
1.30k
  int start_slots = 2;
851
3.90k
  for (int i = 1; i <= start_slots; i++)
852
2.60k
    if (fdp.remaining_bytes() != 0)
853
2.53k
      lua_pushrandom(L, &fdp);
854
855
1.30k
  if (lua_gettop(L) != 0 &&
856
1.30k
      fdp.remaining_bytes() != 0) {
857
1.19k
    __lua_gc(L, &fdp);
858
1.19k
    __lua_sethook(L, &fdp);
859
1.19k
    uint8_t idx = fdp.ConsumeIntegralInRange<uint8_t>(0, (int)ARRAY_SIZE(func) - 1);
860
1.19k
    func[idx](L, &fdp);
861
1.19k
  }
862
863
1.30k
  lua_settop(L, 0);
864
1.30k
  lua_close(L);
865
866
1.30k
  return 0;
867
1.30k
}