/src/testdir/tests/capi/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 | 11.5k | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) |
34 | | |
35 | | static int max_str_len = 1; |
36 | | |
37 | | static int |
38 | 60 | cfunction(lua_State *L) { |
39 | 60 | lua_gettop(L); |
40 | 60 | return 0; |
41 | 60 | } |
42 | | |
43 | 2.37k | #define TYPE_NAME_TORTURE "torture_test" |
44 | 24 | #define MT_FUNC_NAME_TORTURE "__torture" |
45 | | |
46 | | static const luaL_Reg TORTURE_meta[] = |
47 | | { |
48 | | { MT_FUNC_NAME_TORTURE, cfunction }, |
49 | | { 0, 0 } |
50 | | }; |
51 | | |
52 | | /* void lua_pushstring(lua_State *L, const char *s); */ |
53 | | /* [-0, +1, m] */ |
54 | | static void |
55 | | __lua_pushstring(lua_State *L, FuzzedDataProvider *fdp) |
56 | 155 | { |
57 | 155 | auto str = fdp->ConsumeRandomLengthString(max_str_len); |
58 | 155 | int top = lua_gettop(L); |
59 | 155 | lua_pushstring(L, str.c_str()); |
60 | 155 | assert(lua_gettop(L) == top + 1); |
61 | 155 | } |
62 | | |
63 | | /* void lua_pushboolean(lua_State *L, int b); */ |
64 | | /* [-0, +1, -] */ |
65 | | static void |
66 | | __lua_pushboolean(lua_State *L, FuzzedDataProvider *fdp) |
67 | 90 | { |
68 | 90 | uint8_t n = fdp->ConsumeIntegral<uint8_t>(); |
69 | 90 | int top = lua_gettop(L); |
70 | 90 | lua_pushboolean(L, n); |
71 | 90 | assert(lua_gettop(L) == top + 1); |
72 | 90 | } |
73 | | |
74 | | /* void lua_pop(lua_State *L, int n); */ |
75 | | /* [-n, +0, -] */ |
76 | | static void |
77 | | __lua_pop(lua_State *L, FuzzedDataProvider *fdp) |
78 | 10 | { |
79 | 10 | int top = lua_gettop(L); |
80 | 10 | uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
81 | 10 | lua_pop(L, n); |
82 | 10 | assert(lua_gettop(L) == top - n); |
83 | 10 | } |
84 | | |
85 | | /* int lua_isnumber(lua_State *L, int index); */ |
86 | | /* [-0, +0, -] */ |
87 | | static void |
88 | | __lua_isnumber(lua_State *L, FuzzedDataProvider *fdp) |
89 | 24 | { |
90 | 24 | int top = lua_gettop(L); |
91 | 24 | uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
92 | 24 | lua_isnumber(L, n); |
93 | 24 | assert(lua_gettop(L) == top); |
94 | 24 | } |
95 | | |
96 | | /* lua_Number lua_tonumber(lua_State *L, int index); */ |
97 | | /* [-0, +0, -] */ |
98 | | static void |
99 | | __lua_tonumber(lua_State *L, FuzzedDataProvider *fdp) |
100 | 9 | { |
101 | 9 | int top = lua_gettop(L); |
102 | 9 | uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
103 | 9 | lua_tonumber(L, n); |
104 | 9 | assert(lua_gettop(L) == top); |
105 | 9 | } |
106 | | |
107 | | /* lua_Number lua_tonumberx(lua_State *L, int index, int *isnum); */ |
108 | | /* [-0, +0, –] */ |
109 | | static void |
110 | | __lua_tonumberx(lua_State *L, FuzzedDataProvider *fdp) |
111 | 26 | { |
112 | 26 | int top = lua_gettop(L); |
113 | 26 | auto index = fdp->ConsumeIntegralInRange(1, top); |
114 | 26 | int isnum; |
115 | 26 | lua_tonumberx(L, index, &isnum); |
116 | 26 | assert(isnum == 0 || isnum == 1); |
117 | 26 | assert(lua_gettop(L) == top); |
118 | 26 | } |
119 | | |
120 | | /* int lua_checkstack(lua_State *L, int extra); */ |
121 | | /* [-0, +0, m] */ |
122 | | static void |
123 | | __lua_checkstack(lua_State *L, FuzzedDataProvider *fdp) |
124 | 49 | { |
125 | 49 | uint8_t n = fdp->ConsumeIntegral<uint8_t>(); |
126 | 49 | int rc = lua_checkstack(L, n); |
127 | 49 | assert(rc != 0); |
128 | 49 | } |
129 | | |
130 | | /* void lua_concat(lua_State *L, int n); */ |
131 | | /* [-n, +1, e] */ |
132 | | static void |
133 | | __lua_concat(lua_State *L, FuzzedDataProvider *fdp) |
134 | 51 | { |
135 | 51 | int top = lua_gettop(L); |
136 | 51 | uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(0, top); |
137 | 97 | for (int i = 1; i <= n; i++) { |
138 | 65 | int t = lua_type(L, -i); |
139 | 65 | if (t != LUA_TNUMBER && |
140 | 65 | t != LUA_TSTRING) |
141 | 19 | return; |
142 | 65 | } |
143 | 32 | lua_concat(L, n); |
144 | 32 | assert(lua_gettop(L) == top - n + 1); |
145 | 32 | } |
146 | | |
147 | | /* int lua_gettop(lua_State *L); */ |
148 | | /* [-0, +0, -] */ |
149 | | static void |
150 | | __lua_gettop(lua_State *L, FuzzedDataProvider *fdp) |
151 | 2 | { |
152 | 2 | int rc = lua_gettop(L); |
153 | 2 | assert(rc >= 0); |
154 | 2 | } |
155 | | |
156 | | /* void lua_insert(lua_State *L, int index); */ |
157 | | /* [-1, +1, -] */ |
158 | | static void |
159 | | __lua_insert(lua_State *L, FuzzedDataProvider *fdp) |
160 | 18 | { |
161 | 18 | int top = lua_gettop(L); |
162 | 18 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
163 | 18 | lua_insert(L, index); |
164 | 18 | assert(lua_gettop(L) == top - 1 + 1); |
165 | 18 | } |
166 | | |
167 | | /* int lua_isboolean(lua_State *L, int index); */ |
168 | | /* [-0, +0, -] */ |
169 | | static void |
170 | | __lua_isboolean(lua_State *L, FuzzedDataProvider *fdp) |
171 | 22 | { |
172 | 22 | int top = lua_gettop(L); |
173 | 22 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
174 | 22 | int rc = lua_isboolean(L, index); |
175 | 22 | assert(rc == 0 || rc == 1); |
176 | 22 | } |
177 | | |
178 | | /* int lua_iscfunction(lua_State *L, int index); */ |
179 | | /* [-0, +0, -] */ |
180 | | static void |
181 | | __lua_iscfunction(lua_State *L, FuzzedDataProvider *fdp) |
182 | 18 | { |
183 | 18 | int top = lua_gettop(L); |
184 | 18 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
185 | 18 | int rc = lua_iscfunction(L, index); |
186 | 18 | assert(rc == 0 || rc == 1); |
187 | 18 | } |
188 | | |
189 | | /* int lua_isfunction(lua_State *L, int index); */ |
190 | | /* [-0, +0, -] */ |
191 | | static void |
192 | | __lua_isfunction(lua_State *L, FuzzedDataProvider *fdp) |
193 | 20 | { |
194 | 20 | int top = lua_gettop(L); |
195 | 20 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
196 | 20 | int rc = lua_isfunction(L, index); |
197 | 20 | assert(rc == 0 || rc == 1); |
198 | 20 | } |
199 | | |
200 | | /* int lua_isnil(lua_State *L, int index); */ |
201 | | /* [-0, +0, -] */ |
202 | | static void |
203 | | __lua_isnil(lua_State *L, FuzzedDataProvider *fdp) |
204 | 20 | { |
205 | 20 | int top = lua_gettop(L); |
206 | 20 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
207 | 20 | int rc = lua_isnil(L, index); |
208 | 20 | assert(rc == 0 || rc == 1); |
209 | 20 | } |
210 | | |
211 | | /* int lua_isnone(lua_State *L, int index); */ |
212 | | /* [-0, +0, -] */ |
213 | | static void |
214 | | __lua_isnone(lua_State *L, FuzzedDataProvider *fdp) |
215 | 11 | { |
216 | 11 | int top = lua_gettop(L); |
217 | 11 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
218 | 11 | int rc = lua_isnone(L, index); |
219 | 11 | assert(rc == 0 || rc == 1); |
220 | 11 | assert(lua_gettop(L) == top); |
221 | 11 | } |
222 | | |
223 | | /* int lua_isnoneornil(lua_State *L, int index); */ |
224 | | /* [-0, +0, -] */ |
225 | | static void |
226 | | __lua_isnoneornil(lua_State *L, FuzzedDataProvider *fdp) |
227 | 20 | { |
228 | 20 | int top = lua_gettop(L); |
229 | 20 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
230 | 20 | lua_isnoneornil(L, index); |
231 | 20 | assert(lua_gettop(L) == top); |
232 | 20 | } |
233 | | |
234 | | /* int lua_isstring(lua_State *L, int index); */ |
235 | | /* [-0, +0, -] */ |
236 | | static void |
237 | | __lua_isstring(lua_State *L, FuzzedDataProvider *fdp) |
238 | 12 | { |
239 | 12 | int top = lua_gettop(L); |
240 | 12 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
241 | 12 | int rc = lua_isstring(L, index); |
242 | 12 | assert(rc == 0 || rc == 1); |
243 | 12 | } |
244 | | |
245 | | /* int lua_istable(lua_State *L, int index); */ |
246 | | /* [-0, +0, -] */ |
247 | | static void |
248 | | __lua_istable(lua_State *L, FuzzedDataProvider *fdp) |
249 | 4 | { |
250 | 4 | int top = lua_gettop(L); |
251 | 4 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
252 | 4 | int rc = lua_istable(L, index); |
253 | 4 | assert(rc == 0 || rc == 1); |
254 | 4 | } |
255 | | |
256 | | /* void lua_pushinteger(lua_State *L, lua_Integer n); */ |
257 | | /* [-0, +1, -] */ |
258 | | static void |
259 | | __lua_pushinteger(lua_State *L, FuzzedDataProvider *fdp) |
260 | 202 | { |
261 | 202 | int top = lua_gettop(L); |
262 | 202 | uint8_t n = fdp->ConsumeIntegral<uint8_t>(); |
263 | 202 | lua_pushinteger(L, n); |
264 | 202 | assert(lua_gettop(L) == top + 1); |
265 | 202 | } |
266 | | |
267 | | /* void lua_pushlstring(lua_State *L, const char *s, size_t len); */ |
268 | | /* [-0, +1, m] */ |
269 | | static void |
270 | | __lua_pushlstring(lua_State *L, FuzzedDataProvider *fdp) |
271 | 127 | { |
272 | 127 | int top = lua_gettop(L); |
273 | 127 | auto str = fdp->ConsumeRandomLengthString(max_str_len); |
274 | 127 | lua_pushlstring(L, str.c_str(), str.size()); |
275 | 127 | assert(lua_gettop(L) == top + 1); |
276 | 127 | } |
277 | | |
278 | | /* void lua_pushnil(lua_State *L); */ |
279 | | /* [-0, +1, -] */ |
280 | | static void |
281 | | __lua_pushnil(lua_State *L, FuzzedDataProvider *fdp) |
282 | 674 | { |
283 | 674 | int top = lua_gettop(L); |
284 | 674 | lua_pushnil(L); |
285 | 674 | assert(lua_gettop(L) == top + 1); |
286 | 674 | } |
287 | | |
288 | | /* void lua_pushnumber(lua_State *L, lua_Number n); */ |
289 | | /* [-0, +1, -] */ |
290 | | static void |
291 | | __lua_pushnumber(lua_State *L, FuzzedDataProvider *fdp) |
292 | 268 | { |
293 | 268 | int top = lua_gettop(L); |
294 | 268 | uint8_t n = fdp->ConsumeIntegral<uint8_t>(); |
295 | 268 | lua_pushnumber(L, n); |
296 | 268 | assert(lua_gettop(L) == top + 1); |
297 | 268 | } |
298 | | |
299 | | /* void lua_pushvalue(lua_State *L, int index); */ |
300 | | /* [-0, +1, -] */ |
301 | | static void |
302 | | __lua_pushvalue(lua_State *L, FuzzedDataProvider *fdp) |
303 | 7 | { |
304 | 7 | int top = lua_gettop(L); |
305 | 7 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
306 | 7 | lua_pushvalue(L, index); |
307 | 7 | assert(lua_gettop(L) == top + 1); |
308 | 7 | } |
309 | | |
310 | | /* void lua_remove(lua_State *L, int index); */ |
311 | | /* [-1, +0, -] */ |
312 | | static void |
313 | | __lua_remove(lua_State *L, FuzzedDataProvider *fdp) |
314 | 23 | { |
315 | 23 | int top = lua_gettop(L); |
316 | 23 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
317 | 23 | lua_remove(L, index); |
318 | 23 | assert(lua_gettop(L) == top - 1); |
319 | 23 | } |
320 | | |
321 | | /* void lua_replace(lua_State *L, int index); */ |
322 | | /* [-1, +0, -] */ |
323 | | static void |
324 | | __lua_replace(lua_State *L, FuzzedDataProvider *fdp) |
325 | 24 | { |
326 | 24 | int top = lua_gettop(L); |
327 | 24 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
328 | 24 | lua_replace(L, index); |
329 | 24 | assert(lua_gettop(L) == top - 1); |
330 | 24 | } |
331 | | |
332 | | /* void lua_setglobal(lua_State *L, const char *name); */ |
333 | | /* [-1, +0, e] */ |
334 | | static void |
335 | | __lua_setglobal(lua_State *L, FuzzedDataProvider *fdp) |
336 | 7 | { |
337 | 7 | int top = lua_gettop(L); |
338 | 7 | auto str = fdp->ConsumeRandomLengthString(max_str_len); |
339 | 7 | lua_setglobal(L, str.c_str()); |
340 | 7 | assert(lua_gettop(L) == top - 1); |
341 | 7 | } |
342 | | |
343 | | /* void lua_settop(lua_State *L, int index); */ |
344 | | /* [-?, +?, -] */ |
345 | | static void |
346 | | __lua_settop(lua_State *L, FuzzedDataProvider *fdp) |
347 | 6 | { |
348 | 6 | int top = lua_gettop(L); |
349 | 6 | int grow_slots = 2; |
350 | 6 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top + grow_slots); |
351 | 6 | lua_settop(L, index); |
352 | 6 | assert(lua_gettop(L) == index); |
353 | 6 | } |
354 | | |
355 | | /* int lua_status(lua_State *L); */ |
356 | | /* [-0, +0, -] */ |
357 | | static void |
358 | | __lua_status(lua_State *L, FuzzedDataProvider *fdp) |
359 | 5 | { |
360 | 5 | int rc = lua_status(L); |
361 | 5 | assert(rc == 0 || rc == LUA_YIELD); |
362 | 5 | } |
363 | | |
364 | | /* int lua_toboolean(lua_State *L, int index); */ |
365 | | /* [-0, +0, -] */ |
366 | | static void |
367 | | __lua_toboolean(lua_State *L, FuzzedDataProvider *fdp) |
368 | 9 | { |
369 | 9 | int top = lua_gettop(L); |
370 | 9 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
371 | 9 | int rc = lua_toboolean(L, index); |
372 | 9 | assert(rc == 0 || rc == 1); |
373 | 9 | } |
374 | | |
375 | | /* lua_Integer lua_tointeger(lua_State *L, int index); */ |
376 | | /* [-0, +0, -] */ |
377 | | static void |
378 | | __lua_tointeger(lua_State *L, FuzzedDataProvider *fdp) |
379 | 9 | { |
380 | 9 | int top = lua_gettop(L); |
381 | 9 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
382 | 9 | lua_tointeger(L, index); |
383 | 9 | assert(lua_gettop(L) == top); |
384 | 9 | } |
385 | | |
386 | | /* lua_Integer lua_tointegerx(lua_State *L, int index, int *isnum); */ |
387 | | /* [-0, +0, –] */ |
388 | | static void |
389 | | __lua_tointegerx(lua_State *L, FuzzedDataProvider *fdp) |
390 | 9 | { |
391 | 9 | int top = lua_gettop(L); |
392 | 9 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
393 | 9 | int isnum; |
394 | 9 | lua_tointegerx(L, index, &isnum); |
395 | 9 | assert(isnum == 0 || isnum == 1); |
396 | 9 | assert(lua_gettop(L) == top); |
397 | 9 | } |
398 | | |
399 | | /* const char *lua_tolstring(lua_State *L, int index, size_t *len); */ |
400 | | /* [-0, +0, m] */ |
401 | | static void |
402 | | __lua_tolstring(lua_State *L, FuzzedDataProvider *fdp) |
403 | 25 | { |
404 | 25 | int top = lua_gettop(L); |
405 | 25 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
406 | 25 | lua_tolstring(L, index, NULL); |
407 | 25 | assert(lua_gettop(L) == top); |
408 | 25 | } |
409 | | |
410 | | /* const char *lua_tostring(lua_State *L, int index); */ |
411 | | /* [-0, +0, m] */ |
412 | | static void |
413 | | __lua_tostring(lua_State *L, FuzzedDataProvider *fdp) |
414 | 9 | { |
415 | 9 | int top = lua_gettop(L); |
416 | 9 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
417 | 9 | lua_tostring(L, index); |
418 | 9 | assert(lua_gettop(L) == top); |
419 | 9 | } |
420 | | |
421 | | /* int lua_type(lua_State *L, int index); */ |
422 | | /* [-0, +0, -] */ |
423 | | static void |
424 | | __lua_type(lua_State *L, FuzzedDataProvider *fdp) |
425 | 21 | { |
426 | 21 | int top = lua_gettop(L); |
427 | 21 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
428 | 21 | int type = lua_type(L, index); |
429 | 21 | assert(type == LUA_TBOOLEAN || |
430 | 21 | type == LUA_TFUNCTION || |
431 | 21 | type == LUA_TLIGHTUSERDATA || |
432 | 21 | type == LUA_TNIL || |
433 | 21 | type == LUA_TNUMBER || |
434 | 21 | type == LUA_TSTRING || |
435 | 21 | type == LUA_TTABLE || |
436 | 21 | type == LUA_TTHREAD || |
437 | 21 | type == LUA_TUSERDATA || |
438 | 21 | type == LUA_TNONE); |
439 | 21 | assert(lua_gettop(L) == top); |
440 | 21 | } |
441 | | |
442 | | /* void lua_getglobal(lua_State *L, const char *name); */ |
443 | | /* [-0, +1, e] */ |
444 | | static void |
445 | | __lua_getglobal(lua_State *L, FuzzedDataProvider *fdp) |
446 | 1 | { |
447 | 1 | auto name = fdp->ConsumeRandomLengthString(max_str_len); |
448 | 1 | int top = lua_gettop(L); |
449 | 1 | lua_getglobal(L, name.c_str()); |
450 | 1 | assert(lua_gettop(L) == top + 1); |
451 | 1 | } |
452 | | |
453 | | /* const char *lua_setupvalue(lua_State *L, int funcindex, int n); */ |
454 | | /* [-(0|1), +0, –] */ |
455 | | static void |
456 | | __lua_setupvalue(lua_State *L, FuzzedDataProvider *fdp) |
457 | 25 | { |
458 | 25 | int top = lua_gettop(L); |
459 | 25 | int funcindex = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
460 | 25 | int n = fdp->ConsumeIntegral<uint8_t>(); |
461 | 25 | lua_setupvalue(L, funcindex, n); |
462 | 25 | assert(lua_gettop(L) == top); |
463 | 25 | } |
464 | | |
465 | | /* const char *lua_getupvalue(lua_State *L, int funcindex, int n); */ |
466 | | /* [-0, +(0|1), –] */ |
467 | | static void |
468 | | __lua_getupvalue(lua_State *L, FuzzedDataProvider *fdp) |
469 | 23 | { |
470 | 23 | int top = lua_gettop(L); |
471 | 23 | int funcindex = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
472 | 23 | int n = fdp->ConsumeIntegral<uint8_t>(); |
473 | 23 | lua_getupvalue(L, funcindex, n); |
474 | 23 | assert(lua_gettop(L) == top || lua_gettop(L) == top + 1); |
475 | 23 | } |
476 | | |
477 | | /* void *lua_touserdata(lua_State *L, int index); */ |
478 | | /* [-0, +0, -] */ |
479 | | static void |
480 | | __lua_touserdata(lua_State *L, FuzzedDataProvider *fdp) |
481 | 8 | { |
482 | 8 | int top = lua_gettop(L); |
483 | 8 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
484 | 8 | lua_touserdata(L, index); |
485 | 8 | assert(lua_gettop(L) == top); |
486 | 8 | } |
487 | | |
488 | | /* int lua_islightuserdata(lua_State *L, int index); */ |
489 | | /* [-0, +0, -] */ |
490 | | static void |
491 | | __lua_islightuserdata(lua_State *L, FuzzedDataProvider *fdp) |
492 | 16 | { |
493 | 16 | int top = lua_gettop(L); |
494 | 16 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
495 | 16 | int rc = lua_islightuserdata(L, index); |
496 | 16 | assert(rc == 0 || rc == 1); |
497 | 16 | } |
498 | | |
499 | | /* int lua_isuserdata(lua_State *L, int index); */ |
500 | | /* [-0, +0, -] */ |
501 | | static void |
502 | | __lua_isuserdata(lua_State *L, FuzzedDataProvider *fdp) |
503 | 25 | { |
504 | 25 | int top = lua_gettop(L); |
505 | 25 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
506 | 25 | int rc = lua_isuserdata(L, index); |
507 | 25 | assert(rc == 0 || rc == 1); |
508 | 25 | } |
509 | | |
510 | | /* int lua_isthread(lua_State *L, int index); */ |
511 | | /* [-0, +0, -] */ |
512 | | static void |
513 | | __lua_isthread(lua_State *L, FuzzedDataProvider *fdp) |
514 | 11 | { |
515 | 11 | int top = lua_gettop(L); |
516 | 11 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
517 | 11 | int rc = lua_isthread(L, index); |
518 | 11 | assert(rc == 0 || rc == 1); |
519 | 11 | } |
520 | | |
521 | | /* int lua_pushthread(lua_State *L); */ |
522 | | /* [-0, +1, -] */ |
523 | | static void |
524 | | __lua_pushthread(lua_State *L, FuzzedDataProvider *fdp) |
525 | 4 | { |
526 | 4 | int top = lua_gettop(L); |
527 | 4 | int rc = lua_pushthread(L); |
528 | 4 | assert(rc == 1); |
529 | 4 | assert(lua_gettop(L) == top + 1); |
530 | 4 | } |
531 | | |
532 | | /* int lua_next(lua_State *L, int index); */ |
533 | | /* [-1, +(2|0), e] */ |
534 | | static void |
535 | | __lua_next(lua_State *L, FuzzedDataProvider *fdp) |
536 | 19 | { |
537 | 19 | int top = lua_gettop(L); |
538 | 19 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
539 | 19 | if (!lua_istable(L, index)) |
540 | 9 | return; |
541 | 10 | lua_pushnil(L); /* first key */ |
542 | 10 | lua_next(L, index); |
543 | 10 | assert(lua_gettop(L) - top - 1 <= 2); |
544 | 10 | } |
545 | | |
546 | | /* int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar); */ |
547 | | /* [-(0|1), +(0|1|2), m] */ |
548 | | static void |
549 | | __lua_getinfo(lua_State *L, FuzzedDataProvider *fdp) |
550 | 1 | { |
551 | 1 | int top = lua_gettop(L); |
552 | 1 | lua_Debug ar; |
553 | 1 | lua_pushcfunction(L, cfunction); |
554 | 1 | const char *what = ">nSltufLr"; |
555 | 1 | lua_getinfo(L, what, &ar); |
556 | 1 | assert(lua_gettop(L) >= top - 1 && |
557 | 1 | lua_gettop(L) <= top + 2); |
558 | 1 | } |
559 | | |
560 | | /* int lua_getstack(lua_State *L, int level, lua_Debug *ar); */ |
561 | | /* [-0, +0, –] */ |
562 | | static void |
563 | | __lua_getstack(lua_State *L, FuzzedDataProvider *fdp) |
564 | 38 | { |
565 | 38 | int top = lua_gettop(L); |
566 | 38 | int level = fdp->ConsumeIntegral<int8_t>(); |
567 | 38 | lua_Debug ar; |
568 | 38 | lua_getstack(L, level, &ar); |
569 | 38 | assert(lua_gettop(L) == top); |
570 | 38 | } |
571 | | |
572 | | /* void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n); */ |
573 | | /* [-n, +1, m] */ |
574 | | static void |
575 | | __lua_pushcclosure(lua_State *L, FuzzedDataProvider *fdp) |
576 | 41 | { |
577 | | /* Maximum n is 255 in lua_pushcclosure(3). */ |
578 | 41 | int n = fdp->ConsumeIntegralInRange<uint8_t>(1, 10); |
579 | 195 | for (int i = 1; i < n; i++) |
580 | 154 | lua_pushnumber(L, i); |
581 | 41 | lua_pushcclosure(L, cfunction, n); |
582 | 41 | } |
583 | | |
584 | | /* void lua_pushcfunction(lua_State *L, lua_CFunction f); */ |
585 | | /* [-0, +1, m] */ |
586 | | static void |
587 | | __lua_pushcfunction(lua_State *L, FuzzedDataProvider *fdp) |
588 | 955 | { |
589 | 955 | (void)fdp; |
590 | 955 | int top = lua_gettop(L); |
591 | 955 | lua_pushcfunction(L, cfunction); |
592 | 955 | assert(lua_gettop(L) == top + 1); |
593 | 955 | } |
594 | | |
595 | | /* int lua_getmetatable(lua_State *L, int index); */ |
596 | | /* [-0, +(0|1), -] */ |
597 | | static void |
598 | | __lua_getmetatable(lua_State *L, FuzzedDataProvider *fdp) |
599 | 14 | { |
600 | 14 | int top = lua_gettop(L); |
601 | 14 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
602 | 14 | lua_getmetatable(L, index); |
603 | 14 | assert(lua_gettop(L) - top <= 1); |
604 | 14 | } |
605 | | |
606 | | /* void lua_newtable(lua_State *L); */ |
607 | | /* [-0, +1, m] */ |
608 | | static void |
609 | | __lua_newtable(lua_State *L, FuzzedDataProvider *fdp) |
610 | 1.55k | { |
611 | 1.55k | int top = lua_gettop(L); |
612 | 1.55k | lua_newtable(L); |
613 | 1.55k | assert(lua_gettop(L) == top + 1); |
614 | 1.55k | } |
615 | | |
616 | | /* lua_State *lua_newthread(lua_State *L); */ |
617 | | /* [-0, +1, m] */ |
618 | | static void |
619 | | __lua_newthread(lua_State *L, FuzzedDataProvider *fdp) |
620 | 806 | { |
621 | 806 | int top = lua_gettop(L); |
622 | 806 | lua_newthread(L); |
623 | 806 | assert(lua_gettop(L) == top + 1); |
624 | 806 | } |
625 | | |
626 | | /* const char *lua_typename(lua_State *L, int tp); */ |
627 | | /* [-0, +0, -] */ |
628 | | static void |
629 | | __lua_typename(lua_State *L, FuzzedDataProvider *fdp) |
630 | 21 | { |
631 | 21 | int top = lua_gettop(L); |
632 | 21 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
633 | 21 | const char* name = lua_typename(L, index); |
634 | 21 | assert(name); |
635 | 21 | assert(lua_gettop(L) == top); |
636 | 21 | } |
637 | | |
638 | | static int gc_mode[] = { |
639 | | LUA_GCCOLLECT, |
640 | | LUA_GCCOUNT, |
641 | | LUA_GCCOUNTB, |
642 | | LUA_GCRESTART, |
643 | | #if LUA_VERSION_NUM < 504 |
644 | | LUA_GCSETPAUSE, |
645 | | LUA_GCSETSTEPMUL, |
646 | | #endif /* LUA_VERSION_NUM */ |
647 | | LUA_GCSTEP, |
648 | | LUA_GCSTOP, |
649 | | #if LUA_VERSION_NUM > 501 |
650 | | LUA_GCISRUNNING, |
651 | | #elif LUA_VERSION_NUM > 503 |
652 | | LUA_GCGEN, |
653 | | LUA_GCINC, |
654 | | #endif /* LUA_VERSION_NUM */ |
655 | | }; |
656 | | |
657 | | /* int lua_gc(lua_State *L, int what, int data); */ |
658 | | /* [-0, +0, e] */ |
659 | | static void |
660 | | __lua_gc(lua_State *L, FuzzedDataProvider *fdp) |
661 | 2.28k | { |
662 | 2.28k | int top = lua_gettop(L); |
663 | 2.28k | uint8_t idx = fdp->ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(gc_mode) - 1); |
664 | 2.28k | #if LUA_VERSION_NUM > 503 |
665 | 2.28k | if (gc_mode[idx] == LUA_GCGEN) { |
666 | 0 | uint8_t minor_mul = fdp->ConsumeIntegral<uint8_t>(); |
667 | 0 | uint8_t major_mul = fdp->ConsumeIntegral<uint8_t>(); |
668 | 0 | lua_gc(L, LUA_GCGEN, minor_mul, major_mul); |
669 | 2.28k | } else if (gc_mode[idx] == LUA_GCINC) { |
670 | 0 | uint8_t pause = fdp->ConsumeIntegral<uint8_t>(); |
671 | 0 | uint8_t step_mul = fdp->ConsumeIntegral<uint8_t>(); |
672 | 0 | uint8_t step_size = fdp->ConsumeIntegral<uint8_t>(); |
673 | 0 | lua_gc(L, LUA_GCINC, pause, step_mul, step_size); |
674 | 0 | } else |
675 | 2.28k | lua_gc(L, gc_mode[idx], 0); |
676 | | #else |
677 | | lua_gc(L, gc_mode[idx], 0); |
678 | | #endif /* LUA_VERSION_NUM */ |
679 | 2.28k | assert(lua_gettop(L) == top); |
680 | 2.28k | } |
681 | | |
682 | | static int hook_mode[] = { |
683 | | 0, /* Additional branch in Lua. */ |
684 | | LUA_MASKCALL, |
685 | | LUA_MASKCOUNT, |
686 | | LUA_MASKLINE, |
687 | | LUA_MASKRET, |
688 | | }; |
689 | | |
690 | | static void |
691 | | Hook(lua_State *L, lua_Debug *ar) |
692 | 6 | { |
693 | 6 | (void)L; |
694 | 6 | (void)ar; |
695 | 6 | } |
696 | | |
697 | | /* int lua_sethook(lua_State *L, lua_Hook f, int mask, int count); */ |
698 | | /* [-0, +0, -] */ |
699 | | static void |
700 | | __lua_sethook(lua_State *L, FuzzedDataProvider *fdp) |
701 | 2.26k | { |
702 | 2.26k | int top = lua_gettop(L); |
703 | 2.26k | uint8_t idx = fdp->ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(hook_mode) - 1); |
704 | 2.26k | lua_sethook(L, Hook, hook_mode[idx], 1); |
705 | 2.26k | assert(lua_gettop(L) == top); |
706 | 2.26k | } |
707 | | |
708 | | /* lua_Hook lua_gethook(lua_State *L); */ |
709 | | /* [-0, +0, –] */ |
710 | | static void |
711 | | __lua_gethook(lua_State *L, FuzzedDataProvider *fdp) |
712 | 2 | { |
713 | 2 | int top = lua_gettop(L); |
714 | 2 | lua_gethook(L); |
715 | 2 | assert(lua_gettop(L) == top); |
716 | 2 | } |
717 | | |
718 | | /* int lua_gethookcount(lua_State *L); */ |
719 | | /* [-0, +0, –] */ |
720 | | static void |
721 | | __lua_gethookcount(lua_State *L, FuzzedDataProvider *fdp) |
722 | 3 | { |
723 | 3 | int top = lua_gettop(L); |
724 | 3 | int hook_count = lua_gethookcount(L); |
725 | 3 | assert(hook_count >= 0); |
726 | 3 | assert(lua_gettop(L) == top); |
727 | 3 | } |
728 | | |
729 | | /* int lua_gethookmask(lua_State *L); */ |
730 | | /* [-0, +0, –] */ |
731 | | static void |
732 | | __lua_gethookmask(lua_State *L, FuzzedDataProvider *fdp) |
733 | 2 | { |
734 | 2 | int top = lua_gettop(L); |
735 | 2 | int hook_mask = lua_gethookmask(L); |
736 | 2 | assert(hook_mask >= 0); |
737 | 2 | assert(lua_gettop(L) == top); |
738 | 2 | } |
739 | | |
740 | | /* void lua_rawget(lua_State *L, int index); */ |
741 | | /* [-1, +1, -] */ |
742 | | static void |
743 | | __lua_rawget(lua_State *L, FuzzedDataProvider *fdp) |
744 | 18 | { |
745 | 18 | int top = lua_gettop(L); |
746 | 18 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
747 | 18 | if (!lua_istable(L, index)) |
748 | 6 | return; |
749 | 12 | uint8_t key = fdp->ConsumeIntegral<uint8_t>(); |
750 | 12 | lua_pushnumber(L, key); |
751 | 12 | top = lua_gettop(L); |
752 | 12 | lua_rawget(L, index); |
753 | 12 | assert(lua_gettop(L) == top); |
754 | 12 | } |
755 | | |
756 | | /* void lua_rawset(lua_State *L, int index); */ |
757 | | /* [-2, +0, m] */ |
758 | | static void |
759 | | __lua_rawset(lua_State *L, FuzzedDataProvider *fdp) |
760 | 39 | { |
761 | 39 | int top = lua_gettop(L); |
762 | 39 | if (top == 0) |
763 | 0 | return; |
764 | 39 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
765 | 39 | if (!lua_istable(L, index)) |
766 | 6 | return; |
767 | 33 | uint8_t key = fdp->ConsumeIntegral<uint8_t>(); |
768 | 33 | uint8_t value = fdp->ConsumeIntegral<uint8_t>(); |
769 | 33 | lua_pushnumber(L, value); |
770 | 33 | lua_pushnumber(L, key); |
771 | 33 | top = lua_gettop(L); |
772 | 33 | lua_rawset(L, index); |
773 | 33 | assert(lua_gettop(L) == top - 2); |
774 | 33 | } |
775 | | |
776 | | /* void lua_rawseti(lua_State *L, int index, lua_Integer i); */ |
777 | | /* [-1, +0, m] */ |
778 | | static void |
779 | | __lua_rawseti(lua_State *L, FuzzedDataProvider *fdp) |
780 | 36 | { |
781 | 36 | int top = lua_gettop(L); |
782 | 36 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
783 | 36 | if (!lua_istable(L, index)) |
784 | 10 | return; |
785 | 26 | int n = fdp->ConsumeIntegral<uint8_t>(); |
786 | 26 | __lua_pushnumber(L, fdp); |
787 | 26 | top = lua_gettop(L); |
788 | 26 | lua_rawseti(L, index, n); |
789 | 26 | assert(lua_gettop(L) == top - 1); |
790 | 26 | } |
791 | | |
792 | | /* int lua_rawgeti(lua_State *L, int index, lua_Integer n); */ |
793 | | /* [-0, +1, –] */ |
794 | | static void |
795 | | __lua_rawgeti(lua_State *L, FuzzedDataProvider *fdp) |
796 | 27 | { |
797 | 27 | int top = lua_gettop(L); |
798 | 27 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
799 | 27 | if (!lua_istable(L, index)) |
800 | 7 | return; |
801 | 20 | int i = fdp->ConsumeIntegral<uint8_t>(); |
802 | 20 | lua_rawgeti(L, index, i); |
803 | 20 | assert(lua_gettop(L) == top + 1); |
804 | 20 | } |
805 | | |
806 | | /* int lua_equal(lua_State *L, int index1, int index2); */ |
807 | | /* [-0, +0, e] */ |
808 | | #if LUA_VERSION_NUM == 501 |
809 | | static void |
810 | | __lua_equal(lua_State *L, FuzzedDataProvider *fdp) |
811 | | { |
812 | | int top = lua_gettop(L); |
813 | | if (top < 2) |
814 | | return; |
815 | | uint8_t index1 = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
816 | | uint8_t index2 = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
817 | | lua_equal(L, index1, index2); |
818 | | assert(lua_gettop(L) == top); |
819 | | } |
820 | | #endif /* LUA_VERSION_NUM */ |
821 | | |
822 | | /* int lua_lessthan(lua_State *L, int index1, int index2); */ |
823 | | /* [-0, +0, e] */ |
824 | | #if LUA_VERSION_NUM == 501 |
825 | | static void |
826 | | __lua_lessthan(lua_State *L, FuzzedDataProvider *fdp) |
827 | | { |
828 | | int top = lua_gettop(L); |
829 | | uint8_t index1 = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
830 | | int type1 = lua_type(L, index1); |
831 | | switch (type1) { |
832 | | case LUA_TNUMBER: |
833 | | __lua_pushnumber(L, fdp); |
834 | | break; |
835 | | case LUA_TSTRING: |
836 | | __lua_pushstring(L, fdp); |
837 | | break; |
838 | | default: |
839 | | return; |
840 | | } |
841 | | int rc = lua_lessthan(L, index1, -1); |
842 | | assert(rc == 0 || rc == 1); |
843 | | } |
844 | | #endif /* LUA_VERSION_NUM */ |
845 | | |
846 | | /* size_t lua_objlen(lua_State *L, int index); */ |
847 | | /* [-0, +0, -] */ |
848 | | #if LUA_VERSION_NUM < 503 |
849 | | static void |
850 | | __lua_objlen(lua_State *L, FuzzedDataProvider *fdp) |
851 | | { |
852 | | int top = lua_gettop(L); |
853 | | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
854 | | #if LUA_VERSION_NUM == 501 |
855 | | lua_objlen(L, index); |
856 | | #else |
857 | | lua_rawlen(L, index); |
858 | | #endif /* LUA_VERSION_NUM */ |
859 | | assert(lua_gettop(L) == top); |
860 | | } |
861 | | #endif /* LUA_VERSION_NUM */ |
862 | | |
863 | | #if LUA_VERSION_NUM > 501 |
864 | | static int cmp_op[] = { |
865 | | LUA_OPEQ, |
866 | | LUA_OPLE, |
867 | | LUA_OPLT, |
868 | | }; |
869 | | #endif /* LUA_VERSION_NUM */ |
870 | | |
871 | | /* int lua_compare(lua_State *L, int index1, int index2, int op); */ |
872 | | /* [-0, +0, e] */ |
873 | | #if LUA_VERSION_NUM > 501 |
874 | | static void |
875 | | __lua_compare(lua_State *L, FuzzedDataProvider *fdp) |
876 | 111 | { |
877 | 111 | int top = lua_gettop(L); |
878 | 111 | uint8_t index1 = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
879 | 111 | uint8_t index2 = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
880 | 111 | if ((lua_type(L, index1) != LUA_TNUMBER) || |
881 | 111 | (lua_type(L, index2) != LUA_TNUMBER)) |
882 | 35 | return; |
883 | 76 | int op_idx = fdp->ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(cmp_op) - 1); |
884 | 76 | int rc = lua_compare(L, index1, index2, cmp_op[op_idx]); |
885 | 76 | assert(rc == 0 || rc == 1); |
886 | 76 | assert(lua_gettop(L) == top); |
887 | 76 | } |
888 | | #endif /* LUA_VERSION_NUM */ |
889 | | |
890 | | /* size_t lua_rawlen(lua_State *L, int index); */ |
891 | | /* [-0, +0, –] */ |
892 | | #if LUA_VERSION_NUM > 501 |
893 | | static void |
894 | | __lua_rawlen(lua_State *L, FuzzedDataProvider *fdp) |
895 | 10 | { |
896 | 10 | int top = lua_gettop(L); |
897 | 10 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
898 | 10 | lua_rawlen(L, index); |
899 | 10 | assert(lua_gettop(L) == top); |
900 | 10 | } |
901 | | #endif /* LUA_VERSION_NUM */ |
902 | | |
903 | | /* void lua_getfenv(lua_State *L, int index); */ |
904 | | /* [-0, +1, -] */ |
905 | | #if LUA_VERSION_NUM == 501 |
906 | | static void |
907 | | __lua_getfenv(lua_State *L, FuzzedDataProvider *fdp) |
908 | | { |
909 | | int top = lua_gettop(L); |
910 | | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
911 | | lua_getfenv(L, index); |
912 | | assert(lua_gettop(L) == top + 1); |
913 | | } |
914 | | #endif /* LUA_VERSION_NUM */ |
915 | | |
916 | | /* int lua_setfenv(lua_State *L, int index); */ |
917 | | /* [-1, +0, -] */ |
918 | | #if LUA_VERSION_NUM == 501 |
919 | | static void |
920 | | __lua_setfenv(lua_State *L, FuzzedDataProvider *fdp) |
921 | | { |
922 | | int top = lua_gettop(L); |
923 | | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
924 | | if (!lua_istable(L, -1)) |
925 | | return; |
926 | | lua_setfenv(L, index); |
927 | | assert(lua_gettop(L) == top - 1); |
928 | | } |
929 | | #endif /* LUA_VERSION_NUM */ |
930 | | |
931 | | /* int lua_absindex(lua_State *L, int idx); */ |
932 | | /* [-0, +0, –] */ |
933 | | #if LUA_VERSION_NUM > 501 |
934 | | static void |
935 | | __lua_absindex(lua_State *L, FuzzedDataProvider *fdp) |
936 | 20 | { |
937 | 20 | int top = lua_gettop(L); |
938 | | /* |
939 | | * One can refer to any element in the stack by using an index: |
940 | | * A positive index represents an absolute stack position |
941 | | * (starting at 1); a negative index represents an offset |
942 | | * relative to the top of the stack. |
943 | | */ |
944 | 20 | int8_t index = fdp->ConsumeIntegralInRange<int8_t>(-top, top); |
945 | 20 | int idx = lua_absindex(L, index); |
946 | 20 | assert(idx > 0); |
947 | 20 | assert(lua_gettop(L) == top); |
948 | 20 | } |
949 | | #endif /* LUA_VERSION_NUM */ |
950 | | |
951 | | #if LUA_VERSION_NUM > 501 |
952 | | static int arith_op[] = { |
953 | | LUA_OPADD, |
954 | | LUA_OPSUB, |
955 | | LUA_OPMUL, |
956 | | LUA_OPDIV, |
957 | | LUA_OPMOD, |
958 | | LUA_OPPOW, |
959 | | LUA_OPUNM, |
960 | | #if LUA_VERSION_NUM > 502 |
961 | | LUA_OPBNOT, |
962 | | LUA_OPBAND, |
963 | | LUA_OPBOR, |
964 | | LUA_OPBXOR, |
965 | | LUA_OPSHL, |
966 | | LUA_OPSHR, |
967 | | #endif /* LUA_VERSION_NUM */ |
968 | | }; |
969 | | #endif /* LUA_VERSION_NUM */ |
970 | | |
971 | | /* void lua_arith(lua_State *L, int op); */ |
972 | | /* [-(2|1), +1, e] */ |
973 | | #if LUA_VERSION_NUM > 501 |
974 | | static void |
975 | | __lua_arith(lua_State *L, FuzzedDataProvider *fdp) |
976 | 2 | { |
977 | 2 | int top = lua_gettop(L); |
978 | 2 | if ((lua_type(L, 1) != LUA_TNUMBER) || |
979 | 2 | (lua_type(L, 2) != LUA_TNUMBER)) |
980 | 2 | return; |
981 | 0 | int op_idx = fdp->ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(arith_op) - 1); |
982 | 0 | int op = arith_op[op_idx]; |
983 | | |
984 | | /* Handle division by zero. */ |
985 | 0 | lua_pushnumber(L, 0); |
986 | 0 | if ((op == LUA_OPMOD || |
987 | 0 | op == LUA_OPDIV) && lua_rawequal(L, 2, -1)) |
988 | 0 | return; |
989 | 0 | lua_pop(L, 1); |
990 | |
|
991 | 0 | lua_arith(L, op); |
992 | 0 | assert(lua_gettop(L) <= top - 1 + 1); |
993 | 0 | } |
994 | | #endif /* LUA_VERSION_NUM */ |
995 | | |
996 | | /* void lua_setmetatable(lua_State *L, int index); */ |
997 | | /* [-1, +0, –] */ |
998 | | static void |
999 | | __lua_setmetatable(lua_State *L, FuzzedDataProvider *fdp) |
1000 | 16 | { |
1001 | 16 | luaL_getmetatable(L, TYPE_NAME_TORTURE); |
1002 | 16 | int top = lua_gettop(L); |
1003 | 16 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1004 | 16 | lua_setmetatable(L, index); |
1005 | 16 | assert(lua_gettop(L) == top - 1); |
1006 | 16 | } |
1007 | | |
1008 | | /* void luaL_setmetatable(lua_State *L, const char *tname); */ |
1009 | | /* [-0, +0, –] */ |
1010 | | static void |
1011 | | __luaL_setmetatable(lua_State *L, FuzzedDataProvider *fdp) |
1012 | 8 | { |
1013 | 8 | int top = lua_gettop(L); |
1014 | 8 | luaL_setmetatable(L, TYPE_NAME_TORTURE); |
1015 | 8 | assert(lua_gettop(L) == top); |
1016 | 8 | } |
1017 | | |
1018 | | /* int lua_isyieldable(lua_State *L); */ |
1019 | | /* [-0, +0, –] */ |
1020 | | #if LUA_VERSION_NUM > 502 || defined(LUAJIT) |
1021 | | static void |
1022 | | __lua_isyieldable(lua_State *L, FuzzedDataProvider *fdp) |
1023 | 1 | { |
1024 | 1 | (void)fdp; |
1025 | 1 | int rc = lua_isyieldable(L); |
1026 | 1 | assert(rc == 0 || rc == 1); |
1027 | 1 | } |
1028 | | #endif /* LUA_VERSION_NUM */ |
1029 | | |
1030 | | /* int lua_cpcall(lua_State *L, lua_CFunction func, void *ud); */ |
1031 | | /* [-0, +(0|1), -] */ |
1032 | | #if LUA_VERSION_NUM == 501 |
1033 | | static void |
1034 | | __lua_cpcall(lua_State *L, FuzzedDataProvider *fdp) |
1035 | | { |
1036 | | int top = lua_gettop(L); |
1037 | | int rc = lua_cpcall(L, cfunction, NULL); |
1038 | | assert(rc == 0); |
1039 | | assert(lua_gettop(L) - top <= 1); |
1040 | | } |
1041 | | #endif /* LUA_VERSION_NUM */ |
1042 | | |
1043 | | /* void lua_gettable(lua_State *L, int index); */ |
1044 | | /* [-1, +1, e] */ |
1045 | | static void |
1046 | | __lua_gettable(lua_State *L, FuzzedDataProvider *fdp) |
1047 | 43 | { |
1048 | 43 | int top = lua_gettop(L); |
1049 | 43 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1050 | 43 | if (!lua_istable(L, index)) |
1051 | 4 | return; |
1052 | 39 | uint8_t key = fdp->ConsumeIntegral<uint8_t>(); |
1053 | 39 | lua_pushnumber(L, key); |
1054 | 39 | lua_gettable(L, index); |
1055 | 39 | assert(lua_gettop(L) == top + 1); |
1056 | 39 | } |
1057 | | |
1058 | | /* void lua_rotate(lua_State *L, int idx, int n); */ |
1059 | | /* [-0, +0, –] */ |
1060 | | #if LUA_VERSION_NUM > 502 |
1061 | | static void |
1062 | | __lua_rotate(lua_State *L, FuzzedDataProvider *fdp) |
1063 | 25 | { |
1064 | 25 | int top = lua_gettop(L); |
1065 | 25 | int min_n = 1; |
1066 | 25 | uint8_t idx = fdp->ConsumeIntegralInRange<uint8_t>(1, top - min_n); |
1067 | 25 | uint8_t n = fdp->ConsumeIntegralInRange<uint8_t>(1, top - idx); |
1068 | 25 | lua_rotate(L, idx, n); |
1069 | 25 | assert(lua_gettop(L) == top); |
1070 | 25 | } |
1071 | | #endif /* LUA_VERSION_NUM */ |
1072 | | |
1073 | | /* void lua_seti(lua_State *L, int index, lua_Integer n); */ |
1074 | | /* [-1, +0, e] */ |
1075 | | #if LUA_VERSION_NUM > 502 |
1076 | | static void |
1077 | | __lua_seti(lua_State *L, FuzzedDataProvider *fdp) |
1078 | 49 | { |
1079 | 49 | int top = lua_gettop(L); |
1080 | 49 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1081 | 49 | if (!lua_istable(L, index)) |
1082 | 8 | return; |
1083 | 41 | int n = fdp->ConsumeIntegral<uint8_t>(); |
1084 | 41 | __lua_pushnumber(L, fdp); |
1085 | 41 | top = lua_gettop(L); |
1086 | 41 | lua_seti(L, index, n); |
1087 | 41 | assert(lua_gettop(L) == top - 1); |
1088 | 41 | } |
1089 | | #endif /* LUA_VERSION_NUM */ |
1090 | | |
1091 | | /* int lua_geti(lua_State *L, int index, lua_Integer i); */ |
1092 | | /* [-0, +1, e] */ |
1093 | | #if LUA_VERSION_NUM > 502 |
1094 | | static void |
1095 | | __lua_geti(lua_State *L, FuzzedDataProvider *fdp) |
1096 | 51 | { |
1097 | 51 | int top = lua_gettop(L); |
1098 | 51 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1099 | 51 | if (!lua_istable(L, index)) |
1100 | 4 | return; |
1101 | 47 | int i = fdp->ConsumeIntegral<uint8_t>(); |
1102 | 47 | lua_geti(L, index, i); |
1103 | 47 | assert(lua_gettop(L) == top + 1); |
1104 | 47 | } |
1105 | | #endif /* LUA_VERSION_NUM */ |
1106 | | |
1107 | | /* void lua_getuservalue(lua_State *L, int index); */ |
1108 | | /* [-0, +1, –] */ |
1109 | | #if LUA_VERSION_NUM > 501 && LUA_VERSION_NUM < 504 |
1110 | | static void |
1111 | | __lua_getuservalue(lua_State *L, FuzzedDataProvider *fdp) |
1112 | | { |
1113 | | int top = lua_gettop(L); |
1114 | | int index = fdp->ConsumeIntegral<uint8_t>(); |
1115 | | lua_getuservalue(L, index); |
1116 | | assert(lua_gettop(L) == top + 1); |
1117 | | } |
1118 | | #endif /* LUA_VERSION_NUM */ |
1119 | | |
1120 | | /* void lua_setuservalue(lua_State *L, int index); */ |
1121 | | /* [-1, +0, –] */ |
1122 | | #if LUA_VERSION_NUM > 501 && LUA_VERSION_NUM < 504 |
1123 | | static void |
1124 | | __lua_setuservalue(lua_State *L, FuzzedDataProvider *fdp) |
1125 | | { |
1126 | | int top = lua_gettop(L); |
1127 | | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1128 | | lua_setuservalue(L, index); |
1129 | | assert(lua_gettop(L) == top); |
1130 | | } |
1131 | | #endif /* LUA_VERSION_NUM */ |
1132 | | |
1133 | | /* void lua_xmove(lua_State *from, lua_State *to, int n); */ |
1134 | | /* [-?, +?, -] */ |
1135 | | static void |
1136 | | __lua_xmove(lua_State *L, FuzzedDataProvider *fdp) |
1137 | 18 | { |
1138 | 18 | lua_State *co1 = lua_newthread(L); |
1139 | 18 | lua_State *co2 = lua_newthread(L); |
1140 | 18 | __lua_pushnumber(co1, fdp); |
1141 | 18 | lua_xmove(co1, co2, 1); |
1142 | 18 | lua_settop(co1, 0); |
1143 | 18 | lua_settop(co2, 0); |
1144 | 18 | } |
1145 | | |
1146 | | /* void lua_register(lua_State *L, const char *name, lua_CFunction f); */ |
1147 | | /* [-0, +0, e] */ |
1148 | | static void |
1149 | | __lua_register(lua_State *L, FuzzedDataProvider *fdp) |
1150 | 4 | { |
1151 | 4 | int top = lua_gettop(L); |
1152 | 4 | lua_register(L, "cfunction", cfunction); |
1153 | 4 | assert(lua_gettop(L) == top); |
1154 | 4 | } |
1155 | | |
1156 | | /** |
1157 | | * Lua 5.1: int lua_resume(lua_State *L, int narg); |
1158 | | * Lua 5.3: int lua_resume(lua_State *L, lua_State *from, int nargs); |
1159 | | * Lua 5.2: int lua_resume(lua_State *L, lua_State *from, int nargs); |
1160 | | * Lua 5.4: int lua_resume(lua_State *L, lua_State *from, int nargs, int *nresults); |
1161 | | * [-?, +?, -] |
1162 | | */ |
1163 | | static void |
1164 | | __lua_resume(lua_State *L, FuzzedDataProvider *fdp) |
1165 | 2 | { |
1166 | 2 | lua_State *co = lua_newthread(L); |
1167 | 2 | lua_pushcfunction(co, cfunction); |
1168 | 2 | int res = -1; |
1169 | | #if LUA_VERSION_NUM == 501 |
1170 | | res = lua_resume(L, 0); |
1171 | | #elif LUA_VERSION_NUM == 503 || LUA_VERSION_NUM == 502 |
1172 | | res = lua_resume(co, L, 0); |
1173 | | #else |
1174 | 2 | int nres; |
1175 | 2 | res = lua_resume(co, L, 0, &nres); |
1176 | 2 | #endif /* LUA_VERSION_NUM */ |
1177 | | /* assert(res == LUA_OK); */ |
1178 | 2 | (void)res; |
1179 | 2 | lua_settop(co, 0); |
1180 | 2 | } |
1181 | | |
1182 | | /* void lua_setfield(lua_State *L, int index, const char *k); */ |
1183 | | /* [-1, +0, e] */ |
1184 | | static void |
1185 | | __lua_setfield(lua_State *L, FuzzedDataProvider *fdp) |
1186 | 150 | { |
1187 | 150 | int top = lua_gettop(L); |
1188 | 150 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1189 | 150 | if (lua_type(L, index) != LUA_TTABLE) |
1190 | 4 | return; |
1191 | 146 | auto k = fdp->ConsumeRemainingBytesAsString(); |
1192 | 146 | lua_setfield(L, index, k.c_str()); |
1193 | 146 | assert(lua_gettop(L) == top - 1); |
1194 | 146 | } |
1195 | | |
1196 | | /* const void *lua_topointer(lua_State *L, int index); */ |
1197 | | /* [-0, +0, -] */ |
1198 | | static void |
1199 | | __lua_topointer(lua_State *L, FuzzedDataProvider *fdp) |
1200 | 14 | { |
1201 | 14 | int top = lua_gettop(L); |
1202 | 14 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1203 | 14 | const void *p = lua_topointer(L, index); |
1204 | | /* |
1205 | | * The value can be a userdata, a table, a thread, or a function; |
1206 | | * otherwise, lua_topointer returns NULL. |
1207 | | */ |
1208 | 14 | int type = lua_type(L, index); |
1209 | 14 | if (type == LUA_TUSERDATA || |
1210 | 14 | type == LUA_TTHREAD || |
1211 | 14 | type == LUA_TTABLE || |
1212 | 14 | #if LUA_VERSION_NUM > 503 || defined(LUAJIT) |
1213 | 14 | type == LUA_TSTRING || |
1214 | 14 | #endif /* LUA_VERSION_NUM */ |
1215 | 14 | type == LUA_TFUNCTION) |
1216 | 11 | assert(p); |
1217 | 3 | else |
1218 | 3 | assert(p == NULL); |
1219 | 14 | assert(lua_gettop(L) == top); |
1220 | 14 | } |
1221 | | |
1222 | | /* lua_CFunction lua_tocfunction(lua_State *L, int index); */ |
1223 | | /* [-0, +0, -] */ |
1224 | | static void |
1225 | | __lua_tocfunction(lua_State *L, FuzzedDataProvider *fdp) |
1226 | 23 | { |
1227 | 23 | int top = lua_gettop(L); |
1228 | 23 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1229 | 23 | lua_tocfunction(L, index); |
1230 | 23 | assert(lua_gettop(L) == top); |
1231 | 23 | } |
1232 | | |
1233 | | /* void lua_settable(lua_State *L, int index); */ |
1234 | | /* [-2, +0, e] */ |
1235 | | static void |
1236 | | __lua_settable(lua_State *L, FuzzedDataProvider *fdp) |
1237 | 12 | { |
1238 | 12 | int top = lua_gettop(L); |
1239 | 12 | lua_createtable(L, 0, 1); |
1240 | | |
1241 | 12 | lua_pushstring(L, "language"); |
1242 | 12 | lua_pushstring(L, "Lua"); |
1243 | 12 | lua_settable(L, -3); |
1244 | | |
1245 | 12 | assert(lua_gettop(L) == top + 1); |
1246 | 12 | } |
1247 | | |
1248 | | /* void lua_getfield(lua_State *L, int index, const char *k); */ |
1249 | | /* [-0, +1, e] */ |
1250 | | static void |
1251 | | __lua_getfield(lua_State *L, FuzzedDataProvider *fdp) |
1252 | 212 | { |
1253 | 212 | int top = lua_gettop(L); |
1254 | 212 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1255 | 212 | if (lua_type(L, index) != LUA_TTABLE) |
1256 | 8 | return; |
1257 | 204 | auto k = fdp->ConsumeRemainingBytesAsString(); |
1258 | 204 | lua_getfield(L, index, k.c_str()); |
1259 | 204 | assert(lua_gettop(L) == top + 1); |
1260 | 204 | } |
1261 | | |
1262 | | /* void *lua_newuserdata(lua_State *L, size_t size); */ |
1263 | | /* [-0, +1, m] */ |
1264 | | static void |
1265 | | __lua_newuserdata(lua_State *L, FuzzedDataProvider *fdp) |
1266 | 38 | { |
1267 | 38 | uint8_t size = fdp->ConsumeIntegral<uint8_t>(); |
1268 | 38 | lua_newuserdata(L, size); |
1269 | 38 | } |
1270 | | |
1271 | | /* const char *lua_pushfstring(lua_State *L, const char *fmt, ...); */ |
1272 | | /* [-0, +1, m] */ |
1273 | | static void |
1274 | | __lua_pushfstring(lua_State *L, FuzzedDataProvider *fdp) |
1275 | 15 | { |
1276 | 15 | int top = lua_gettop(L); |
1277 | 15 | auto arg1 = fdp->ConsumeRandomLengthString(max_str_len); |
1278 | 15 | auto arg2 = fdp->ConsumeRandomLengthString(max_str_len); |
1279 | 15 | auto arg3 = fdp->ConsumeRandomLengthString(max_str_len); |
1280 | 15 | auto arg4 = fdp->ConsumeRandomLengthString(max_str_len); |
1281 | 15 | auto arg5 = fdp->ConsumeRandomLengthString(max_str_len); |
1282 | 15 | char fmt_str[] = "%s %f %p %d %c"; |
1283 | 15 | lua_pushfstring(L, fmt_str, arg1.c_str(), arg2.c_str(), |
1284 | 15 | arg3.c_str(), arg4.c_str(), |
1285 | 15 | arg5.c_str()); |
1286 | 15 | assert(lua_gettop(L) == top + 1); |
1287 | 15 | } |
1288 | | |
1289 | | /* lua_State *lua_tothread(lua_State *L, int index); */ |
1290 | | /* [-0, +0, -] */ |
1291 | | static void |
1292 | | __lua_tothread(lua_State *L, FuzzedDataProvider *fdp) |
1293 | 19 | { |
1294 | 19 | int top = lua_gettop(L); |
1295 | 19 | uint8_t index = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1296 | 19 | lua_tothread(L, index); |
1297 | 19 | assert(lua_gettop(L) == top); |
1298 | 19 | } |
1299 | | |
1300 | | /* lua_Number luaL_checknumber(lua_State *L, int narg); */ |
1301 | | /* [-0, +0, v] */ |
1302 | | static void |
1303 | | __luaL_checknumber(lua_State *L, FuzzedDataProvider *fdp) |
1304 | 27 | { |
1305 | 27 | int top = lua_gettop(L); |
1306 | 27 | uint8_t narg = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1307 | | /* |
1308 | | * Functions called luaL_check* always raise an error |
1309 | | * if the check is not satisfied. |
1310 | | */ |
1311 | 27 | if (lua_type(L, narg) != LUA_TNUMBER) |
1312 | 26 | return; |
1313 | 1 | luaL_checknumber(L, narg); |
1314 | 1 | assert(lua_gettop(L) == top); |
1315 | 1 | } |
1316 | | |
1317 | | /* lua_Integer luaL_checkinteger(lua_State *L, int arg); */ |
1318 | | /* [-0, +0, v] */ |
1319 | | static void |
1320 | | __luaL_checkinteger(lua_State *L, FuzzedDataProvider *fdp) |
1321 | 9 | { |
1322 | 9 | int top = lua_gettop(L); |
1323 | 9 | uint8_t arg = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1324 | | /* |
1325 | | * Functions called luaL_check* always raise an error |
1326 | | * if the check is not satisfied. |
1327 | | */ |
1328 | 9 | if (lua_type(L, arg) != LUA_TNUMBER) |
1329 | 7 | return; |
1330 | 2 | luaL_checkinteger(L, arg); |
1331 | 2 | assert(lua_gettop(L) == top); |
1332 | 2 | } |
1333 | | |
1334 | | /* const char *luaL_checkstring(lua_State *L, int arg); */ |
1335 | | /* [-0, +0, v] */ |
1336 | | static void |
1337 | | __luaL_checkstring(lua_State *L, FuzzedDataProvider *fdp) |
1338 | 23 | { |
1339 | 23 | int top = lua_gettop(L); |
1340 | 23 | uint8_t arg = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1341 | | /* |
1342 | | * Functions called luaL_check* always raise an error |
1343 | | * if the check is not satisfied. |
1344 | | */ |
1345 | 23 | if (lua_type(L, arg) != LUA_TSTRING) |
1346 | 20 | return; |
1347 | 3 | luaL_checkstring(L, arg); |
1348 | 3 | assert(lua_gettop(L) == top); |
1349 | 3 | } |
1350 | | |
1351 | | /* void luaL_checktype(lua_State *L, int arg, int t); */ |
1352 | | /* [-0, +0, v] */ |
1353 | | static void |
1354 | | __luaL_checktype(lua_State *L, FuzzedDataProvider *fdp) |
1355 | 12 | { |
1356 | 12 | int top = lua_gettop(L); |
1357 | 12 | uint8_t arg = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1358 | | /* |
1359 | | * Functions called luaL_check* always raise an error |
1360 | | * if the check is not satisfied. |
1361 | | */ |
1362 | 12 | int type = lua_type(L, arg); |
1363 | 12 | luaL_checktype(L, arg, type); |
1364 | 12 | assert(lua_gettop(L) == top); |
1365 | 12 | } |
1366 | | |
1367 | | /* void luaL_checkany(lua_State *L, int arg); */ |
1368 | | /* [-0, +0, v] */ |
1369 | | static void |
1370 | | __luaL_checkany(lua_State *L, FuzzedDataProvider *fdp) |
1371 | 8 | { |
1372 | 8 | int top = lua_gettop(L); |
1373 | 8 | uint8_t arg = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1374 | | /* |
1375 | | * Functions called luaL_check* always raise an error |
1376 | | * if the check is not satisfied. |
1377 | | */ |
1378 | 8 | luaL_checkany(L, arg); |
1379 | 8 | assert(lua_gettop(L) == top); |
1380 | 8 | } |
1381 | | |
1382 | | /* int lua_getiuservalue(lua_State *L, int index, int n); */ |
1383 | | /* [-0, +1, –] */ |
1384 | | #if LUA_VERSION_NUM > 503 |
1385 | | static void |
1386 | | __lua_getiuservalue(lua_State *L, FuzzedDataProvider *fdp) |
1387 | 22 | { |
1388 | 22 | lua_newuserdatauv(L, 1, 0); |
1389 | 22 | __lua_pushnumber(L, fdp); |
1390 | 22 | int n = 1; |
1391 | 22 | lua_setiuservalue(L, -2, n); |
1392 | 22 | int top = lua_gettop(L); |
1393 | 22 | lua_getiuservalue(L, -1, n); |
1394 | 22 | assert(lua_gettop(L) == top + 1); |
1395 | 22 | } |
1396 | | #endif /* LUA_VERSION_NUM */ |
1397 | | |
1398 | | /* int lua_setiuservalue(lua_State *L, int index, int n); */ |
1399 | | /* [-1, +0, –] */ |
1400 | | #if LUA_VERSION_NUM > 503 |
1401 | | static void |
1402 | | __lua_setiuservalue(lua_State *L, FuzzedDataProvider *fdp) |
1403 | 20 | { |
1404 | 20 | __lua_newuserdata(L, fdp); |
1405 | 20 | __lua_pushnumber(L, fdp); |
1406 | 20 | uint8_t n = fdp->ConsumeIntegral<uint8_t>(); |
1407 | 20 | int top = lua_gettop(L); |
1408 | 20 | lua_setiuservalue(L, -2, n); |
1409 | 20 | assert(lua_gettop(L) == top - 1); |
1410 | 20 | } |
1411 | | #endif /* LUA_VERSION_NUM */ |
1412 | | |
1413 | | /* void *lua_upvalueid(lua_State *L, int funcindex, int n); */ |
1414 | | /* [-0, +0, –] */ |
1415 | | static void |
1416 | | __lua_upvalueid(lua_State *L, FuzzedDataProvider *fdp) |
1417 | 5 | { |
1418 | 5 | int funcindex = -1; |
1419 | 5 | lua_Debug ar; |
1420 | 5 | lua_pushcfunction(L, cfunction); |
1421 | 5 | int n = fdp->ConsumeIntegral<uint8_t>(); |
1422 | 5 | lua_setupvalue(L, funcindex, n); |
1423 | 5 | assert(lua_getinfo(L, ">u", &ar) == 1); |
1424 | 5 | if (ar.nups == 0) |
1425 | 5 | return; |
1426 | 0 | int top = lua_gettop(L); |
1427 | 0 | void *p = lua_upvalueid(L, funcindex, n); |
1428 | 0 | assert(p); |
1429 | 0 | assert(lua_gettop(L) == top); |
1430 | 0 | } |
1431 | | |
1432 | | /* int lua_rawequal(lua_State *L, int index1, int index2); */ |
1433 | | /* [-0, +0, –] */ |
1434 | | static void |
1435 | | __lua_rawequal(lua_State *L, FuzzedDataProvider *fdp) |
1436 | 41 | { |
1437 | 41 | int top = lua_gettop(L); |
1438 | 41 | if (top < 2) |
1439 | 0 | return; |
1440 | 41 | uint8_t index1 = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1441 | 41 | uint8_t index2 = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1442 | 41 | lua_rawequal(L, index1, index2); |
1443 | 41 | assert(lua_gettop(L) == top); |
1444 | 41 | } |
1445 | | |
1446 | | /* void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level); */ |
1447 | | /* [-0, +1, m] */ |
1448 | | static void |
1449 | | __luaL_traceback(lua_State *L, FuzzedDataProvider *fdp) |
1450 | 7 | { |
1451 | 7 | int top = lua_gettop(L); |
1452 | 7 | auto buf = fdp->ConsumeRandomLengthString(max_str_len); |
1453 | 7 | luaL_traceback(L, L, buf.c_str(), 1); |
1454 | 7 | assert(lua_gettop(L) == top + 1); |
1455 | 7 | } |
1456 | | |
1457 | | /* const char *lua_tolstring(lua_State *L, int index, size_t *len); */ |
1458 | | /* [-0, +0, m] */ |
1459 | | /* const char *luaL_tolstring(lua_State *L, int idx, size_t *len); */ |
1460 | | /* [-0, +1, e] */ |
1461 | | static void |
1462 | | __luaL_tolstring(lua_State *L, FuzzedDataProvider *fdp) |
1463 | 38 | { |
1464 | 38 | int top = lua_gettop(L); |
1465 | 38 | auto idx = fdp->ConsumeIntegralInRange(1, top); |
1466 | | #if LUA_VERSION_NUM < 503 |
1467 | | lua_tolstring(L, idx, NULL); |
1468 | | assert(lua_gettop(L) == top); |
1469 | | #else |
1470 | 38 | luaL_tolstring(L, idx, NULL); |
1471 | 38 | assert(lua_gettop(L) == top + 1); |
1472 | 38 | #endif /* LUA_VERSION_NUM */ |
1473 | 38 | } |
1474 | | |
1475 | | /* void lua_copy(lua_State *L, int fromidx, int toidx); */ |
1476 | | /* [-0, +0, –] */ |
1477 | | #if LUA_VERSION_NUM > 501 || defined(LUAJIT) |
1478 | | static void |
1479 | | __lua_copy(lua_State *L, FuzzedDataProvider *fdp) |
1480 | 8 | { |
1481 | 8 | int top = lua_gettop(L); |
1482 | 8 | uint8_t fromidx = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1483 | 8 | uint8_t toidx = fdp->ConsumeIntegralInRange<uint8_t>(1, top); |
1484 | 8 | if (fromidx == toidx) |
1485 | 4 | return; |
1486 | 4 | lua_copy(L, fromidx, toidx); |
1487 | 4 | assert(lua_gettop(L) == top); |
1488 | 4 | } |
1489 | | #endif /* LUA_VERSION_NUM */ |
1490 | | |
1491 | | /* void luaL_checkversion(lua_State *L); */ |
1492 | | /* [-0, +0, v] */ |
1493 | | #if LUA_VERSION_NUM > 501 |
1494 | | static void |
1495 | | __luaL_checkversion(lua_State *L, FuzzedDataProvider *fdp) |
1496 | 2 | { |
1497 | 2 | int top = lua_gettop(L); |
1498 | 2 | luaL_checkversion(L); |
1499 | 2 | assert(top == lua_gettop(L)); |
1500 | 2 | } |
1501 | | #endif /* LUA_VERSION_NUM */ |
1502 | | |
1503 | | /* size_t lua_stringtonumber(lua_State *L, const char *s); */ |
1504 | | /* [-0, +1, –] */ |
1505 | | #if LUA_VERSION_NUM > 502 |
1506 | | static void |
1507 | | __lua_stringtonumber(lua_State *L, FuzzedDataProvider *fdp) |
1508 | 25 | { |
1509 | 25 | int top = lua_gettop(L); |
1510 | 25 | auto str = fdp->ConsumeRandomLengthString(max_str_len); |
1511 | 25 | size_t sz = lua_stringtonumber(L, str.c_str()); |
1512 | 25 | if (sz == 0) { |
1513 | 24 | assert(lua_gettop(L) == top); |
1514 | 24 | } else { |
1515 | 1 | assert(lua_gettop(L) == top + 1); |
1516 | 1 | assert(lua_isnumber(L, -1) == 1); |
1517 | 1 | } |
1518 | 25 | } |
1519 | | #endif /* LUA_VERSION_NUM */ |
1520 | | |
1521 | | /* int lua_rawgetp(lua_State *L, int index, const void *p); */ |
1522 | | /* [-0, +1, –] */ |
1523 | | #if LUA_VERSION_NUM > 501 |
1524 | | static void |
1525 | | __lua_rawgetp(lua_State *L, FuzzedDataProvider *fdp) |
1526 | 26 | { |
1527 | 26 | int top = lua_gettop(L); |
1528 | 26 | auto idx = fdp->ConsumeIntegralInRange(1, top); |
1529 | 26 | if (lua_type(L, idx) != LUA_TTABLE) |
1530 | 12 | return; |
1531 | 14 | void *p = malloc(1); |
1532 | 14 | lua_rawgetp(L, idx, p); |
1533 | 14 | free(p); |
1534 | 14 | assert(lua_gettop(L) == top + 1); |
1535 | 14 | } |
1536 | | #endif /* LUA_VERSION_NUM */ |
1537 | | |
1538 | | /* void lua_len(lua_State *L, int index); */ |
1539 | | /* [-0, +1, e] */ |
1540 | | #if LUA_VERSION_NUM > 501 |
1541 | | static void |
1542 | | __lua_len(lua_State *L, FuzzedDataProvider *fdp) |
1543 | 26 | { |
1544 | 26 | int top = lua_gettop(L); |
1545 | 26 | auto idx = fdp->ConsumeIntegralInRange(1, top); |
1546 | 26 | if (lua_type(L, idx) != LUA_TTABLE && |
1547 | 26 | lua_type(L, idx) != LUA_TSTRING) |
1548 | 8 | return; |
1549 | 18 | lua_len(L, idx); |
1550 | 18 | assert(lua_gettop(L) == top + 1); |
1551 | 18 | } |
1552 | | #endif /* LUA_VERSION_NUM */ |
1553 | | |
1554 | | /* lua_Integer luaL_len(lua_State *L, int index); */ |
1555 | | /* [-0, +0, e] */ |
1556 | | #if LUA_VERSION_NUM > 501 |
1557 | | static void |
1558 | | __luaL_len(lua_State *L, FuzzedDataProvider *fdp) |
1559 | 19 | { |
1560 | 19 | int top = lua_gettop(L); |
1561 | 19 | auto index = fdp->ConsumeIntegralInRange(1, top); |
1562 | 19 | int type = lua_type(L, index); |
1563 | 19 | if (type == LUA_TFUNCTION || |
1564 | 19 | type == LUA_TTHREAD || |
1565 | 19 | type == LUA_TNUMBER || |
1566 | 19 | type == LUA_TBOOLEAN || |
1567 | 19 | type == LUA_TNIL || |
1568 | 19 | type == LUA_TUSERDATA) |
1569 | 11 | return; |
1570 | 8 | luaL_len(L, index); |
1571 | 8 | assert(lua_gettop(L) == top); |
1572 | 8 | } |
1573 | | #endif /* LUA_VERSION_NUM */ |
1574 | | |
1575 | | /* lua_Alloc lua_getallocf(lua_State *L, void **ud); */ |
1576 | | /* [-0, +0, –] */ |
1577 | | static void |
1578 | | __lua_getallocf(lua_State *L, FuzzedDataProvider *fdp) |
1579 | 4 | { |
1580 | 4 | int top = lua_gettop(L); |
1581 | 4 | void *state; |
1582 | 4 | lua_getallocf(L, &state); |
1583 | 4 | assert(lua_gettop(L) == top); |
1584 | 4 | } |
1585 | | |
1586 | | /* int luaL_ref(lua_State *L, int t); */ |
1587 | | /* [-1, +0, e] */ |
1588 | | static void |
1589 | | __luaL_ref(lua_State *L, FuzzedDataProvider *fdp) |
1590 | 26 | { |
1591 | 26 | int top = lua_gettop(L); |
1592 | 26 | auto idx = fdp->ConsumeIntegralInRange(1, top); |
1593 | 26 | if (lua_type(L, idx) != LUA_TTABLE) |
1594 | 6 | return; |
1595 | 20 | luaL_ref(L, idx); |
1596 | 20 | assert(lua_gettop(L) == top - 1); |
1597 | 20 | } |
1598 | | |
1599 | | /* void luaL_checkstack(lua_State *L, int sz, const char *msg); */ |
1600 | | /* [-0, +0, v] */ |
1601 | | static void |
1602 | | __luaL_checkstack(lua_State *L, FuzzedDataProvider *fdp) |
1603 | 1 | { |
1604 | 1 | int top = lua_gettop(L); |
1605 | 1 | int sz = top + 1; |
1606 | 1 | char err_msg[] = "shit happens"; |
1607 | 1 | luaL_checkstack(L, sz, err_msg); |
1608 | 1 | assert(lua_gettop(L) == top); |
1609 | 1 | } |
1610 | | |
1611 | | /* const lua_Number *lua_version(lua_State *L); */ |
1612 | | /* [-0, +0, v] */ |
1613 | | #if LUA_VERSION_NUM > 501 || defined(LUAJIT) |
1614 | | static void |
1615 | | __lua_version(lua_State *L, FuzzedDataProvider *fdp) |
1616 | 2 | { |
1617 | 2 | int top = lua_gettop(L); |
1618 | | #if LUA_VERSION_NUM < 504 |
1619 | | const lua_Number *v = lua_version(L); |
1620 | | assert(v); |
1621 | | #else |
1622 | 2 | lua_Number v = lua_version(L); |
1623 | 2 | assert(v != 0); |
1624 | 2 | #endif /* LUA_VERSION_NUM */ |
1625 | 2 | assert(lua_gettop(L) == top); |
1626 | 2 | } |
1627 | | #endif /* LUA_VERSION_NUM */ |
1628 | | |
1629 | | /* int luaL_getmetafield(lua_State *L, int obj, const char *e); */ |
1630 | | /* [-0, +(0|1), e] */ |
1631 | | static void |
1632 | | __luaL_getmetafield(lua_State *L, FuzzedDataProvider *fdp) |
1633 | 32 | { |
1634 | 32 | int top = lua_gettop(L); |
1635 | 32 | auto obj = fdp->ConsumeIntegralInRange(1, top); |
1636 | 32 | const char e[] = "xxx"; |
1637 | 32 | luaL_getmetafield(L, obj, e); |
1638 | 32 | assert(lua_gettop(L) == top || lua_gettop(L) == top + 1); |
1639 | 32 | } |
1640 | | |
1641 | | /* void lua_call(lua_State *L, int nargs, int nresults); */ |
1642 | | /* [-(nargs+1), +nresults, e] */ |
1643 | | static void |
1644 | | __lua_call(lua_State *L, FuzzedDataProvider *fdp) |
1645 | 49 | { |
1646 | 49 | int top = lua_gettop(L); |
1647 | | /* Function to be called. */ |
1648 | 49 | lua_pushcfunction(L, cfunction); |
1649 | 49 | int nargs = 0; |
1650 | 49 | int nresults = 0; |
1651 | 49 | lua_call(L, nargs, nresults); |
1652 | 49 | assert(lua_gettop(L) == top + nresults - nargs); |
1653 | 49 | } |
1654 | | |
1655 | | /* int lua_pcall(lua_State *L, int nargs, int nresults, int msgh); */ |
1656 | | /* [-(nargs + 1), +(nresults|1), –] */ |
1657 | | static void |
1658 | | __lua_pcall(lua_State *L, FuzzedDataProvider *fdp) |
1659 | 1 | { |
1660 | 1 | int top = lua_gettop(L); |
1661 | | /* Function to be called. */ |
1662 | 1 | lua_pushcfunction(L, cfunction); |
1663 | 1 | int nargs = 0; |
1664 | 1 | int nresults = 0; |
1665 | 1 | int res = lua_pcall(L, nargs, nresults, 0); |
1666 | 1 | assert(res == LUA_OK); |
1667 | 1 | assert(lua_gettop(L) == top + nresults - nargs); |
1668 | 1 | } |
1669 | | |
1670 | | /* int luaL_loadstring(lua_State *L, const char *s); */ |
1671 | | /* [-0, +1, m] */ |
1672 | | static void |
1673 | | __luaL_loadstring(lua_State *L, FuzzedDataProvider *fdp) |
1674 | 19 | { |
1675 | 19 | int top = lua_gettop(L); |
1676 | 19 | int res = luaL_loadstring(L, "a = a + 1"); |
1677 | 19 | assert(res == LUA_OK); |
1678 | 19 | assert(lua_gettop(L) == top + 1); |
1679 | 19 | } |
1680 | | |
1681 | | /* int luaL_callmeta(lua_State *L, int obj, const char *e); */ |
1682 | | /* [-0, +(0|1), e] */ |
1683 | | static void |
1684 | | __luaL_callmeta(lua_State *L, FuzzedDataProvider *fdp) |
1685 | 24 | { |
1686 | 24 | int top = lua_gettop(L); |
1687 | 24 | auto obj = fdp->ConsumeIntegralInRange(1, top); |
1688 | 24 | luaL_callmeta(L, obj, MT_FUNC_NAME_TORTURE); |
1689 | 24 | assert(lua_gettop(L) == top || lua_gettop(L) == top + 1); |
1690 | 24 | } |
1691 | | |
1692 | | /* void luaL_where(lua_State *L, int lvl); */ |
1693 | | /* [-0, +1, m] */ |
1694 | | static void |
1695 | | __luaL_where(lua_State *L, FuzzedDataProvider *fdp) |
1696 | 5 | { |
1697 | 5 | int top = lua_gettop(L); |
1698 | 5 | luaL_where(L, 1); |
1699 | 5 | assert(lua_gettop(L) == top + 1); |
1700 | 5 | } |
1701 | | |
1702 | | typedef void |
1703 | | (*lua_func)(lua_State *L, FuzzedDataProvider *fdp); |
1704 | | |
1705 | | static lua_func push_func[] = { |
1706 | | &__lua_newtable, |
1707 | | &__lua_newthread, |
1708 | | &__lua_pushboolean, |
1709 | | &__lua_pushcfunction, |
1710 | | &__lua_pushinteger, |
1711 | | &__lua_pushlstring, |
1712 | | &__lua_pushnil, |
1713 | | &__lua_pushnumber, |
1714 | | &__lua_pushstring, |
1715 | | }; |
1716 | | |
1717 | | static void |
1718 | | lua_pushrandom(lua_State *L, FuzzedDataProvider *fdp) |
1719 | 4.66k | { |
1720 | 4.66k | uint8_t idx = fdp->ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(push_func) - 1); |
1721 | | |
1722 | 4.66k | push_func[idx](L, fdp); |
1723 | | |
1724 | 4.66k | bool is_set_mt = fdp->ConsumeBool(); |
1725 | 4.66k | if (is_set_mt) { |
1726 | 2.07k | luaL_getmetatable(L, TYPE_NAME_TORTURE); |
1727 | 2.07k | lua_setmetatable(L, -2); |
1728 | 2.07k | } |
1729 | 4.66k | } |
1730 | | |
1731 | | /* void lua_createtable(lua_State *L, int narr, int nrec); */ |
1732 | | /* [-0, +1, m] */ |
1733 | | static void |
1734 | | __lua_createtable(lua_State *L, FuzzedDataProvider *fdp) |
1735 | 60 | { |
1736 | 60 | int nrows = fdp->ConsumeIntegral<uint8_t>(); |
1737 | | /* XXX: Lua associative arrays. */ |
1738 | 60 | lua_createtable(L, nrows, 0); |
1739 | 7.87k | for (int i = 0; i < nrows; i++) { |
1740 | 7.81k | lua_pushnumber(L, i); |
1741 | 7.81k | lua_rawseti(L, -2, i + 1); |
1742 | 7.81k | } |
1743 | 60 | assert(lua_gettop(L) != 0); |
1744 | 60 | } |
1745 | | |
1746 | | static lua_func func[] = { |
1747 | | &__lua_call, |
1748 | | &__lua_checkstack, |
1749 | | &__lua_concat, |
1750 | | &__lua_createtable, |
1751 | | &__lua_gc, |
1752 | | &__lua_getallocf, |
1753 | | &__lua_getfield, |
1754 | | &__lua_getglobal, |
1755 | | &__lua_gethook, |
1756 | | &__lua_gethookcount, |
1757 | | &__lua_gethookmask, |
1758 | | &__lua_getinfo, |
1759 | | &__lua_getmetatable, |
1760 | | &__lua_getstack, |
1761 | | &__lua_gettable, |
1762 | | &__lua_gettop, |
1763 | | &__lua_getupvalue, |
1764 | | &__lua_insert, |
1765 | | &__lua_isboolean, |
1766 | | &__lua_iscfunction, |
1767 | | &__lua_isfunction, |
1768 | | &__lua_islightuserdata, |
1769 | | &__lua_isnil, |
1770 | | &__lua_isnone, |
1771 | | &__lua_isnoneornil, |
1772 | | &__lua_isnumber, |
1773 | | &__lua_isstring, |
1774 | | &__lua_istable, |
1775 | | &__lua_isthread, |
1776 | | &__lua_isuserdata, |
1777 | | &__luaL_callmeta, |
1778 | | &__luaL_checkany, |
1779 | | &__luaL_checkinteger, |
1780 | | &__luaL_checknumber, |
1781 | | &__luaL_checkstack, |
1782 | | &__luaL_checkstring, |
1783 | | &__luaL_checktype, |
1784 | | &__luaL_getmetafield, |
1785 | | &__luaL_loadstring, |
1786 | | &__luaL_ref, |
1787 | | &__luaL_tolstring, |
1788 | | &__luaL_traceback, |
1789 | | &__luaL_where, |
1790 | | &__lua_newtable, |
1791 | | &__lua_newthread, |
1792 | | &__lua_newuserdata, |
1793 | | &__lua_next, |
1794 | | &__lua_pcall, |
1795 | | &__lua_pop, |
1796 | | &__lua_pushboolean, |
1797 | | &__lua_pushcclosure, |
1798 | | &__lua_pushcfunction, |
1799 | | &__lua_pushfstring, |
1800 | | &__lua_pushinteger, |
1801 | | &__lua_pushlstring, |
1802 | | &__lua_pushnil, |
1803 | | &__lua_pushnumber, |
1804 | | &__lua_pushstring, |
1805 | | &__lua_pushthread, |
1806 | | &__lua_pushvalue, |
1807 | | &__lua_rawequal, |
1808 | | &__lua_rawget, |
1809 | | &__lua_rawgeti, |
1810 | | &__lua_rawset, |
1811 | | &__lua_rawseti, |
1812 | | &__lua_register, |
1813 | | &__lua_remove, |
1814 | | &__lua_replace, |
1815 | | &__lua_resume, |
1816 | | &__lua_setfield, |
1817 | | &__lua_setglobal, |
1818 | | &__lua_setmetatable, |
1819 | | &__lua_settable, |
1820 | | &__lua_settop, |
1821 | | &__lua_setupvalue, |
1822 | | &__lua_status, |
1823 | | &__lua_toboolean, |
1824 | | &__lua_tocfunction, |
1825 | | &__lua_tointeger, |
1826 | | &__lua_tointegerx, |
1827 | | &__lua_tolstring, |
1828 | | &__lua_tonumber, |
1829 | | &__lua_topointer, |
1830 | | &__lua_tostring, |
1831 | | &__lua_tothread, |
1832 | | &__lua_touserdata, |
1833 | | &__lua_type, |
1834 | | &__lua_typename, |
1835 | | &__lua_upvalueid, |
1836 | | &__lua_xmove, |
1837 | | #if LUA_VERSION_NUM == 501 |
1838 | | &__lua_cpcall, |
1839 | | &__lua_equal, |
1840 | | &__lua_getfenv, |
1841 | | &__lua_lessthan, |
1842 | | &__lua_objlen, |
1843 | | &__lua_setfenv, |
1844 | | #endif /* LUA_VERSION_NUM */ |
1845 | | #if LUA_VERSION_NUM > 501 |
1846 | | &__lua_absindex, |
1847 | | &__lua_arith, |
1848 | | &__lua_compare, |
1849 | | &__lua_copy, |
1850 | | &__luaL_checkversion, |
1851 | | &__lua_len, |
1852 | | &__luaL_len, |
1853 | | &__luaL_setmetatable, |
1854 | | &__lua_rawgetp, |
1855 | | &__lua_rawlen, |
1856 | | &__lua_tonumberx, |
1857 | | &__lua_version, |
1858 | | #endif /* LUA_VERSION_NUM */ |
1859 | | #if LUA_VERSION_NUM > 502 |
1860 | | &__lua_geti, |
1861 | | &__lua_isyieldable, |
1862 | | &__lua_rotate, |
1863 | | &__lua_seti, |
1864 | | &__lua_stringtonumber, |
1865 | | #endif /* LUA_VERSION_NUM */ |
1866 | | #if LUA_VERSION_NUM > 503 |
1867 | | &__lua_getiuservalue, |
1868 | | &__lua_setiuservalue, |
1869 | | #endif /* LUA_VERSION_NUM */ |
1870 | | #if LUA_VERSION_NUM > 501 && LUA_VERSION_NUM < 504 |
1871 | | &__lua_setuservalue, |
1872 | | &__lua_getuservalue, |
1873 | | #endif /* LUA_VERSION_NUM */ |
1874 | | #ifdef LUAJIT |
1875 | | &__lua_copy, |
1876 | | &__lua_isyieldable, |
1877 | | &__luaL_setmetatable, |
1878 | | &__lua_tonumberx, |
1879 | | &__lua_version, |
1880 | | #endif /* LUAJIT */ |
1881 | | }; |
1882 | | |
1883 | | extern "C" int |
1884 | | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
1885 | 2.36k | { |
1886 | 2.36k | lua_State *L = luaL_newstate(); |
1887 | 2.36k | if (L == NULL) |
1888 | 0 | return 0; |
1889 | | |
1890 | | #if LUA_VERSION_NUM == 501 |
1891 | | luaL_register(L, TYPE_NAME_TORTURE, TORTURE_meta); |
1892 | | #else |
1893 | 2.36k | luaL_newmetatable(L, TYPE_NAME_TORTURE); |
1894 | 2.36k | luaL_setfuncs(L, TORTURE_meta, 0); |
1895 | 2.36k | #endif /* LUA_VERSION_NUM */ |
1896 | | |
1897 | 2.36k | FuzzedDataProvider fdp(data, size); |
1898 | 2.36k | int start_slots = 2; |
1899 | 7.10k | for (int i = 1; i <= start_slots; i++) |
1900 | 4.73k | if (fdp.remaining_bytes() != 0) |
1901 | 4.66k | lua_pushrandom(L, &fdp); |
1902 | | |
1903 | 2.36k | if (lua_gettop(L) != 0 && |
1904 | 2.36k | fdp.remaining_bytes() != 0) { |
1905 | 2.26k | __lua_gc(L, &fdp); |
1906 | 2.26k | __lua_sethook(L, &fdp); |
1907 | 2.26k | uint8_t idx = fdp.ConsumeIntegralInRange<uint8_t>(0, ARRAY_SIZE(func) - 1); |
1908 | 2.26k | func[idx](L, &fdp); |
1909 | 2.26k | } |
1910 | | |
1911 | 2.36k | lua_settop(L, 0); |
1912 | 2.36k | lua_close(L); |
1913 | | |
1914 | 2.36k | return 0; |
1915 | 2.36k | } |