2323#include <errno.h>
2424#include <fcntl.h>
2525#include <gio/gio.h>
26+ #include <json-glib/json-glib.h>
2627#include <stdio.h>
2728#include <stdlib.h>
2829#include <string.h>
@@ -48,6 +49,9 @@ static char df_except_counter = 0;
4849static void df_fuzz_write_log (const struct df_dbus_method * method , GVariant * value );
4950static int df_exec_cmd_check (const char * cmd );
5051static int df_fuzz_call_method (const struct df_dbus_method * method , GVariant * value );
52+ static void df_fuzz_dump_reproducer (const char * bus , const char * object , const char * interface ,
53+ const char * method , const char * signature , GVariant * value ,
54+ const char * type );
5155
5256guint64 df_get_number_of_iterations (const char * signature ) {
5357 guint64 iterations = 0 ;
@@ -399,6 +403,9 @@ static int df_check_if_exited(const int pid) {
399403 assert (pid > 0 );
400404
401405 sprintf (proc_pid , "/proc/%d/status" , pid );
406+ /* FIXME: check correctly if the target responds before checking its PID,
407+ * otherwise we might miss the crash */
408+ usleep (50000 );
402409
403410 f = fopen (proc_pid , "r" );
404411 if (!f ) {
@@ -533,6 +540,8 @@ int df_fuzz_test_method(
533540 df_fuzz_write_log (method , value );
534541 }
535542
543+ df_fuzz_dump_reproducer (name , obj , intf , method -> name , method -> signature , value , "fail" );
544+
536545 df_fail (" reproducer: %sdfuzzer -v -n %s -o %s -i %s -t %s" ,
537546 ansi_yellow (), name , obj , intf , method -> name );
538547 if (buf_size_flg )
@@ -625,3 +634,74 @@ static int df_fuzz_call_method(const struct df_dbus_method *method, GVariant *va
625634
626635 return 0 ;
627636}
637+
638+ static void df_fuzz_dump_reproducer (const char * bus , const char * object , const char * interface ,
639+ const char * method , const char * signature , GVariant * value ,
640+ const char * type )
641+ {
642+ g_autoptr (JsonBuilder ) builder = NULL ;
643+ g_autoptr (JsonNode ) root = NULL ;
644+ g_autoptr (JsonGenerator ) generator = NULL ;
645+ g_autoptr (GError ) error = NULL ;
646+ g_autofree gchar * filename = NULL ;
647+
648+ /* No log dir set, don't dump anything */
649+ if (!df_log_dir )
650+ return ;
651+
652+ assert (bus );
653+ assert (object );
654+ assert (method );
655+ assert (signature );
656+ assert (value );
657+
658+ /* Generate a JSON tree
659+ *
660+ * Current structure:
661+ * {
662+ * "bus": <bus_name>,
663+ * "object": <object_name>,
664+ * "interface": <interface_name>,
665+ * "method": <method_name>,
666+ * "payload": {
667+ * "signature": <signature>,
668+ * "data": <serialized_gvariant>
669+ * }
670+ * }
671+ */
672+ builder = json_builder_new ();
673+ json_builder_begin_object (builder );
674+
675+ json_builder_set_member_name (builder , "bus" );
676+ json_builder_add_string_value (builder , bus );
677+ json_builder_set_member_name (builder , "object" );
678+ json_builder_add_string_value (builder , object );
679+ json_builder_set_member_name (builder , "interface" );
680+ json_builder_add_string_value (builder , interface );
681+ json_builder_set_member_name (builder , "method" );
682+ json_builder_add_string_value (builder , method );
683+
684+ json_builder_set_member_name (builder , "payload" );
685+ json_builder_begin_object (builder );
686+ json_builder_set_member_name (builder , "signature" );
687+ json_builder_add_string_value (builder , signature );
688+ json_builder_set_member_name (builder , "data" );
689+ json_builder_add_value (builder , json_gvariant_serialize (value ));
690+ json_builder_end_object (builder );
691+
692+ json_builder_end_object (builder );
693+
694+ /* Serialize the whole JSON tree */
695+ root = json_builder_get_root (builder );
696+ generator = json_generator_new ();
697+ json_generator_set_root (generator , root );
698+ json_generator_set_pretty (generator , TRUE);
699+
700+ /* Dump it into a file */
701+ filename = g_strdup_printf ("%s/%s-%s-%" G_GINT64_FORMAT "-%s.json" , df_log_dir ,
702+ bus , method , g_get_real_time (), type );
703+ if (!json_generator_to_file (generator , filename , & error ))
704+ df_fail ("Failed to dump reproducer into file '%s': %s\n" , filename , error -> message );
705+
706+ df_fail (" Wrote the reproducer into file '%s'\n" , filename );
707+ }
0 commit comments