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,8 @@ 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 */
402408
403409 f = fopen (proc_pid , "r" );
404410 if (!f ) {
@@ -539,6 +545,8 @@ int df_fuzz_test_method(
539545 df_fuzz_write_log (method , value );
540546 }
541547
548+ df_fuzz_dump_reproducer (name , obj , intf , method -> name , method -> signature , value , "fail" );
549+
542550 df_fail (" reproducer: %sdfuzzer -v -n %s -o %s -i %s -t %s" ,
543551 ansi_yellow (), name , obj , intf , method -> name );
544552 if (buf_size_flg )
@@ -633,3 +641,74 @@ static int df_fuzz_call_method(const struct df_dbus_method *method, GVariant *va
633641
634642 return 0 ;
635643}
644+
645+ static void df_fuzz_dump_reproducer (const char * bus , const char * object , const char * interface ,
646+ const char * method , const char * signature , GVariant * value ,
647+ const char * type )
648+ {
649+ g_autoptr (JsonBuilder ) builder = NULL ;
650+ g_autoptr (JsonNode ) root = NULL ;
651+ g_autoptr (JsonGenerator ) generator = NULL ;
652+ g_autoptr (GError ) error = NULL ;
653+ g_autofree gchar * filename = NULL ;
654+
655+ /* No log dir set, don't dump anything */
656+ if (!df_log_dir )
657+ return ;
658+
659+ assert (bus );
660+ assert (object );
661+ assert (method );
662+ assert (signature );
663+ assert (value );
664+
665+ /* Generate a JSON tree
666+ *
667+ * Current structure:
668+ * {
669+ * "bus": <bus_name>,
670+ * "object": <object_name>,
671+ * "interface": <interface_name>,
672+ * "method": <method_name>,
673+ * "payload": {
674+ * "signature": <signature>,
675+ * "data": <serialized_gvariant>
676+ * }
677+ * }
678+ */
679+ builder = json_builder_new ();
680+ json_builder_begin_object (builder );
681+
682+ json_builder_set_member_name (builder , "bus" );
683+ json_builder_add_string_value (builder , bus );
684+ json_builder_set_member_name (builder , "object" );
685+ json_builder_add_string_value (builder , object );
686+ json_builder_set_member_name (builder , "interface" );
687+ json_builder_add_string_value (builder , interface );
688+ json_builder_set_member_name (builder , "method" );
689+ json_builder_add_string_value (builder , method );
690+
691+ json_builder_set_member_name (builder , "payload" );
692+ json_builder_begin_object (builder );
693+ json_builder_set_member_name (builder , "signature" );
694+ json_builder_add_string_value (builder , signature );
695+ json_builder_set_member_name (builder , "data" );
696+ json_builder_add_value (builder , json_gvariant_serialize (value ));
697+ json_builder_end_object (builder );
698+
699+ json_builder_end_object (builder );
700+
701+ /* Serialize the whole JSON tree */
702+ root = json_builder_get_root (builder );
703+ generator = json_generator_new ();
704+ json_generator_set_root (generator , root );
705+ json_generator_set_pretty (generator , TRUE);
706+
707+ /* Dump it into a file */
708+ filename = g_strdup_printf ("%s/%s-%s-%" G_GINT64_FORMAT "-%s.json" , df_log_dir ,
709+ bus , method , g_get_real_time (), type );
710+ if (!json_generator_to_file (generator , filename , & error ))
711+ df_fail ("Failed to dump reproducer into file '%s': %s\n" , filename , error -> message );
712+
713+ df_fail (" Wrote the reproducer into file '%s'\n" , filename );
714+ }
0 commit comments