@@ -230,7 +230,7 @@ TestOneInput(const uint8_t* data, size_t size) {
230230 */
231231 lua_sethook (L , debug_hook , LUA_MASKCALL | LUA_MASKLINE , 0 );
232232
233- char * buf = calloc (size + 1 , sizeof (char ));
233+ char * buf = malloc (size + 1 * sizeof (* buf ));
234234 memcpy (buf , data , size );
235235 buf [size ] = '\0' ;
236236 lua_pushlstring (L , buf , size );
@@ -316,22 +316,51 @@ load_custom_mutator_lib(void) {
316316 return 0 ;
317317}
318318
319+ /* Find amount of fields in the table on the top of the stack. */
320+ NO_SANITIZE static int
321+ table_nkeys (lua_State * L )
322+ {
323+ int len = 0 ;
324+ /* Push starting `nil` for iterations. */
325+ lua_pushnil (L );
326+ while (lua_next (L , -2 ) != 0 ) {
327+ /*
328+ * Remove `value` from the stack. Keeps `key` for
329+ * the next iteration.
330+ */
331+ lua_pop (L , 1 );
332+ len ++ ;
333+ }
334+ return len ;
335+ }
336+
337+ NO_SANITIZE static void
338+ free_argv (int argc , char * * argv )
339+ {
340+ /* Free allocated argv strings and the buffer. */
341+ for (int i = 1 ; i < argc ; i ++ )
342+ free (argv [i ]);
343+ free (argv );
344+ }
345+
319346NO_SANITIZE static int
320347luaL_fuzz (lua_State * L )
321348{
322349 if (lua_istable (L , -1 ) == 0 ) {
323350 luaL_error (L , "opts is not a table" );
324351 }
325- lua_pushnil (L );
326-
327- /* Processing a table with options. */
328- int argc = 0 ;
329- char * * argv = malloc (1 * sizeof (char * ));
352+ /* 0 element -- test name. Last -- ending NULL. */
353+ int argc = table_nkeys (L ) + 1 ;
354+ char * * argv = malloc ((argc + 1 ) * sizeof (* argv ));
330355 if (!argv )
331356 luaL_error (L , "not enough memory" );
357+
332358 argv [0 ] = "<test name>" ;
333- argc ++ ;
334359 const char * corpus_path = NULL ;
360+
361+ /* First key to start iteration. */
362+ lua_pushnil (L );
363+ int n_arg = 1 ;
335364 while (lua_next (L , -2 ) != 0 ) {
336365 const char * key = lua_tostring (L , -2 );
337366 const char * value = lua_tostring (L , -1 );
@@ -340,21 +369,15 @@ luaL_fuzz(lua_State *L)
340369 lua_pop (L , 1 );
341370 continue ;
342371 }
343- char * * argvp = realloc (argv , sizeof (char * ) * (argc + 1 ));
344- if (argvp == NULL ) {
345- free (argv );
346- luaL_error (L , "not enough memory" );
347- }
348372 size_t arg_len = strlen (key ) + strlen (value ) + 3 ;
349- char * arg = calloc (arg_len , sizeof (char ));
373+ char * arg = malloc (arg_len * sizeof (* arg ));
350374 if (!arg )
351375 luaL_error (L , "not enough memory" );
352376 snprintf (arg , arg_len , "-%s=%s" , key , value );
353- argvp [argc ] = arg ;
354- argc ++ ;
355- argv = argvp ;
377+ argv [n_arg ++ ] = arg ;
356378 lua_pop (L , 1 );
357379 }
380+
358381 if (corpus_path ) {
359382 argv [argc - 1 ] = (char * )corpus_path ;
360383 }
@@ -371,15 +394,18 @@ luaL_fuzz(lua_State *L)
371394
372395 /* Processing a function with custom mutator. */
373396 if (!lua_isnil (L , -1 ) && (lua_isfunction (L , -1 ) == 1 )) {
374- if (load_custom_mutator_lib ())
397+ if (load_custom_mutator_lib ()) {
398+ free_argv (argc , argv );
375399 luaL_error (L , "function LLVMFuzzerCustomMutator is not available" );
400+ }
376401 luaL_set_custom_mutator (L );
377402 } else {
378403 lua_pop (L , 1 );
379404 }
380405
381406 /* Processing a function LLVMFuzzerTestOneInput. */
382407 if (lua_isfunction (L , -1 ) != 1 ) {
408+ free_argv (argc , argv );
383409 luaL_error (L , "test_one_input is not a Lua function" );
384410 }
385411 lua_setglobal (L , TEST_ONE_INPUT_FUNC );
@@ -393,16 +419,18 @@ luaL_fuzz(lua_State *L)
393419
394420 lua_getglobal (L , TEST_ONE_INPUT_FUNC );
395421 if (lua_isfunction (L , -1 ) != 1 ) {
422+ free_argv (argc , argv );
396423 luaL_error (L , "test_one_input is not defined" );
397424 }
398425 lua_pop (L , -1 );
399426
400427 set_global_lua_state (L );
401428 int rc = LLVMFuzzerRunDriver (& argc , & argv , & TestOneInput );
429+
430+ free_argv (argc , argv );
402431 luaL_cleanup (L );
403432
404433 lua_pushnumber (L , rc );
405-
406434 return 1 ;
407435}
408436
0 commit comments