@@ -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,49 +316,70 @@ 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+
358+ argv [0 ] = "<test name>" ;
332359 const char * corpus_path = NULL ;
360+
361+ /* First key to start iteration. */
362+ lua_pushnil (L );
363+ int n_arg = 1 ;
333364 while (lua_next (L , -2 ) != 0 ) {
334- char * * argvp = realloc (argv , sizeof (char * ) * (argc + 1 ));
335- if (argvp == NULL ) {
336- free (argv );
337- luaL_error (L , "not enough memory" );
338- }
339365 const char * key = lua_tostring (L , -2 );
340366 const char * value = lua_tostring (L , -1 );
341- if (strcmp (key , "corpus" ) != 0 ) {
342- size_t arg_len = strlen (key ) + strlen (value ) + 3 ;
343- char * arg = calloc (arg_len , sizeof (char ));
344- if (!arg )
345- luaL_error (L , "not enough memory" );
346- snprintf (arg , arg_len , "-%s=%s" , key , value );
347- argvp [argc ] = arg ;
348- argc ++ ;
349- } else {
367+ if (strcmp (key , "corpus" ) == 0 ) {
350368 corpus_path = strdup (value );
369+ lua_pop (L , 1 );
370+ continue ;
351371 }
372+ size_t arg_len = strlen (key ) + strlen (value ) + 3 ;
373+ char * arg = malloc (arg_len * sizeof (* arg ));
374+ if (!arg )
375+ luaL_error (L , "not enough memory" );
376+ snprintf (arg , arg_len , "-%s=%s" , key , value );
377+ argv [n_arg ++ ] = arg ;
352378 lua_pop (L , 1 );
353- argv = argvp ;
354379 }
380+
355381 if (corpus_path ) {
356- argv [argc ] = (char * )corpus_path ;
357- argc ++ ;
358- }
359- if (argc == 0 ) {
360- argv [argc ] = "" ;
361- argc ++ ;
382+ argv [argc - 1 ] = (char * )corpus_path ;
362383 }
363384 argv [argc ] = NULL ;
364385 lua_pop (L , 1 );
@@ -373,15 +394,18 @@ luaL_fuzz(lua_State *L)
373394
374395 /* Processing a function with custom mutator. */
375396 if (!lua_isnil (L , -1 ) && (lua_isfunction (L , -1 ) == 1 )) {
376- if (load_custom_mutator_lib ())
397+ if (load_custom_mutator_lib ()) {
398+ free_argv (argc , argv );
377399 luaL_error (L , "function LLVMFuzzerCustomMutator is not available" );
400+ }
378401 luaL_set_custom_mutator (L );
379402 } else {
380403 lua_pop (L , 1 );
381404 }
382405
383406 /* Processing a function LLVMFuzzerTestOneInput. */
384407 if (lua_isfunction (L , -1 ) != 1 ) {
408+ free_argv (argc , argv );
385409 luaL_error (L , "test_one_input is not a Lua function" );
386410 }
387411 lua_setglobal (L , TEST_ONE_INPUT_FUNC );
@@ -395,12 +419,15 @@ luaL_fuzz(lua_State *L)
395419
396420 lua_getglobal (L , TEST_ONE_INPUT_FUNC );
397421 if (lua_isfunction (L , -1 ) != 1 ) {
422+ free_argv (argc , argv );
398423 luaL_error (L , "test_one_input is not defined" );
399424 }
400425 lua_pop (L , -1 );
401426
402427 set_global_lua_state (L );
403428 int rc = LLVMFuzzerRunDriver (& argc , & argv , & TestOneInput );
429+
430+ free_argv (argc , argv );
404431 luaL_cleanup (L );
405432
406433 lua_pushnumber (L , rc );
0 commit comments