mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2025-12-22 17:10:17 +01:00
When libdbus-1 moved to using monotonic time support for the DBUS_COOKIE_SHA1 authentication was broken, in particular interoperability with non-libdbus-1 implementations such as GDBus. The problem is that if monotonic clocks are available in the OS, _dbus_get_current_time() will not return the number of seconds since the Epoch so using it for DBUS_COOKIE_SHA1 will violate the D-Bus specification. If both peers are using libdbus-1 it's not a problem since both ends will use the wrong time and thus agree. However, if the other end is another implementation and following the spec it will not work. First, we change _dbus_get_current_time() back so it always returns time since the Epoch and we then rename it _dbus_get_real_time() to make this clear. We then introduce _dbus_get_monotonic_time() and carefully make all current users of _dbus_get_current_time() use it, if applicable. During this audit, one of the callers, _dbus_generate_uuid(), was currently using monotonic time but it was decided to make it use real time instead. Signed-off-by: David Zeuthen <davidz@redhat.com> Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=48580
764 lines
18 KiB
C
764 lines
18 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
/* dbus-break-loader.c Program to find byte streams that break the message loader
|
|
*
|
|
* Copyright (C) 2003 Red Hat Inc.
|
|
*
|
|
* Licensed under the Academic Free License version 2.1
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <dbus/dbus.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <sys/wait.h>
|
|
#include <string.h>
|
|
|
|
#define DBUS_COMPILATION
|
|
#include <dbus/dbus-string.h>
|
|
#include <dbus/dbus-internals.h>
|
|
#include <dbus/dbus-test.h>
|
|
#include <dbus/dbus-marshal-basic.h>
|
|
#undef DBUS_COMPILATION
|
|
|
|
static DBusString failure_dir;
|
|
static int total_attempts;
|
|
static int failures_this_iteration;
|
|
|
|
static int
|
|
random_int_in_range (int start,
|
|
int end)
|
|
{
|
|
/* such elegant math */
|
|
double gap;
|
|
double v_double;
|
|
int v;
|
|
|
|
if (start == end)
|
|
return start;
|
|
|
|
_dbus_assert (end > start);
|
|
|
|
gap = end - start - 1; /* -1 to not include "end" */
|
|
v_double = ((double)start) + (((double)rand ())/RAND_MAX) * gap;
|
|
if (v_double < 0.0)
|
|
v = (v_double - 0.5);
|
|
else
|
|
v = (v_double + 0.5);
|
|
|
|
if (v < start)
|
|
{
|
|
fprintf (stderr, "random_int_in_range() generated %d for range [%d,%d)\n",
|
|
v, start, end);
|
|
v = start;
|
|
}
|
|
else if (v >= end)
|
|
{
|
|
fprintf (stderr, "random_int_in_range() generated %d for range [%d,%d)\n",
|
|
v, start, end);
|
|
v = end - 1;
|
|
}
|
|
|
|
/* printf (" %d of [%d,%d)\n", v, start, end); */
|
|
|
|
return v;
|
|
}
|
|
|
|
static dbus_bool_t
|
|
try_mutated_data (const DBusString *data)
|
|
{
|
|
int pid;
|
|
|
|
total_attempts += 1;
|
|
/* printf (" attempt %d\n", total_attempts); */
|
|
|
|
pid = fork ();
|
|
|
|
if (pid < 0)
|
|
{
|
|
fprintf (stderr, "fork() failed: %s\n",
|
|
strerror (errno));
|
|
exit (1);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pid == 0)
|
|
{
|
|
/* Child, try loading the data */
|
|
if (!dbus_internal_do_not_use_try_message_data (data, _DBUS_MESSAGE_UNKNOWN))
|
|
exit (1);
|
|
else
|
|
exit (0);
|
|
}
|
|
else
|
|
{
|
|
/* Parent, wait for child */
|
|
int status;
|
|
DBusString filename;
|
|
dbus_bool_t failed;
|
|
|
|
if (waitpid (pid, &status, 0) < 0)
|
|
{
|
|
fprintf (stderr, "waitpid() failed: %s\n", strerror (errno));
|
|
exit (1);
|
|
return FALSE;
|
|
}
|
|
|
|
failed = FALSE;
|
|
|
|
if (!_dbus_string_init (&filename) ||
|
|
!_dbus_string_copy (&failure_dir, 0,
|
|
&filename, 0) ||
|
|
!_dbus_string_append_byte (&filename, '/'))
|
|
{
|
|
fprintf (stderr, "out of memory\n");
|
|
exit (1);
|
|
}
|
|
|
|
_dbus_string_append_int (&filename, total_attempts);
|
|
|
|
if (WIFEXITED (status))
|
|
{
|
|
if (WEXITSTATUS (status) != 0)
|
|
{
|
|
_dbus_string_append (&filename, "-exited-");
|
|
_dbus_string_append_int (&filename, WEXITSTATUS (status));
|
|
failed = TRUE;
|
|
}
|
|
}
|
|
else if (WIFSIGNALED (status))
|
|
{
|
|
_dbus_string_append (&filename, "signaled-");
|
|
_dbus_string_append_int (&filename, WTERMSIG (status));
|
|
failed = TRUE;
|
|
}
|
|
|
|
if (failed)
|
|
{
|
|
DBusError error;
|
|
|
|
_dbus_string_append (&filename, ".message-raw");
|
|
|
|
printf ("Child failed, writing %s\n", _dbus_string_get_const_data (&filename));
|
|
|
|
dbus_error_init (&error);
|
|
if (!_dbus_string_save_to_file (data, &filename, FALSE, &error))
|
|
{
|
|
fprintf (stderr, "Failed to save failed message data: %s\n",
|
|
error.message);
|
|
dbus_error_free (&error);
|
|
exit (1); /* so we can see the seed that was printed out */
|
|
}
|
|
|
|
failures_this_iteration += 1;
|
|
|
|
_dbus_string_free (&filename);
|
|
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
_dbus_string_free (&filename);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
_dbus_assert_not_reached ("should not be reached");
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
randomly_shorten_or_lengthen (const DBusString *orig_data,
|
|
DBusString *mutated)
|
|
{
|
|
int delta;
|
|
|
|
if (orig_data != mutated)
|
|
{
|
|
_dbus_string_set_length (mutated, 0);
|
|
|
|
if (!_dbus_string_copy (orig_data, 0, mutated, 0))
|
|
_dbus_assert_not_reached ("out of mem");
|
|
}
|
|
|
|
if (_dbus_string_get_length (mutated) == 0)
|
|
delta = random_int_in_range (0, 10);
|
|
else
|
|
delta = random_int_in_range (- _dbus_string_get_length (mutated),
|
|
_dbus_string_get_length (mutated) * 3);
|
|
|
|
if (delta < 0)
|
|
_dbus_string_shorten (mutated, - delta);
|
|
else if (delta > 0)
|
|
{
|
|
int i = 0;
|
|
|
|
i = _dbus_string_get_length (mutated);
|
|
if (!_dbus_string_lengthen (mutated, delta))
|
|
_dbus_assert_not_reached ("couldn't lengthen string");
|
|
|
|
while (i < _dbus_string_get_length (mutated))
|
|
{
|
|
_dbus_string_set_byte (mutated,
|
|
i,
|
|
random_int_in_range (0, 256));
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
randomly_change_one_byte (const DBusString *orig_data,
|
|
DBusString *mutated)
|
|
{
|
|
int i;
|
|
|
|
if (orig_data != mutated)
|
|
{
|
|
_dbus_string_set_length (mutated, 0);
|
|
|
|
if (!_dbus_string_copy (orig_data, 0, mutated, 0))
|
|
_dbus_assert_not_reached ("out of mem");
|
|
}
|
|
|
|
if (_dbus_string_get_length (mutated) == 0)
|
|
return;
|
|
|
|
i = random_int_in_range (0, _dbus_string_get_length (mutated));
|
|
|
|
_dbus_string_set_byte (mutated, i,
|
|
random_int_in_range (0, 256));
|
|
}
|
|
|
|
static void
|
|
randomly_remove_one_byte (const DBusString *orig_data,
|
|
DBusString *mutated)
|
|
{
|
|
int i;
|
|
|
|
if (orig_data != mutated)
|
|
{
|
|
_dbus_string_set_length (mutated, 0);
|
|
|
|
if (!_dbus_string_copy (orig_data, 0, mutated, 0))
|
|
_dbus_assert_not_reached ("out of mem");
|
|
}
|
|
|
|
if (_dbus_string_get_length (mutated) == 0)
|
|
return;
|
|
|
|
i = random_int_in_range (0, _dbus_string_get_length (mutated));
|
|
|
|
_dbus_string_delete (mutated, i, 1);
|
|
}
|
|
|
|
|
|
static void
|
|
randomly_add_one_byte (const DBusString *orig_data,
|
|
DBusString *mutated)
|
|
{
|
|
int i;
|
|
|
|
if (orig_data != mutated)
|
|
{
|
|
_dbus_string_set_length (mutated, 0);
|
|
|
|
if (!_dbus_string_copy (orig_data, 0, mutated, 0))
|
|
_dbus_assert_not_reached ("out of mem");
|
|
}
|
|
|
|
i = random_int_in_range (0, _dbus_string_get_length (mutated));
|
|
|
|
_dbus_string_insert_bytes (mutated, i, 1,
|
|
random_int_in_range (0, 256));
|
|
}
|
|
|
|
static void
|
|
randomly_modify_length (const DBusString *orig_data,
|
|
DBusString *mutated)
|
|
{
|
|
int i;
|
|
int byte_order;
|
|
const char *d;
|
|
dbus_uint32_t orig;
|
|
int delta;
|
|
|
|
if (orig_data != mutated)
|
|
{
|
|
_dbus_string_set_length (mutated, 0);
|
|
|
|
if (!_dbus_string_copy (orig_data, 0, mutated, 0))
|
|
_dbus_assert_not_reached ("out of mem");
|
|
}
|
|
|
|
if (_dbus_string_get_length (mutated) < 12)
|
|
return;
|
|
|
|
d = _dbus_string_get_const_data (mutated);
|
|
|
|
if (!(*d == DBUS_LITTLE_ENDIAN ||
|
|
*d == DBUS_BIG_ENDIAN))
|
|
return;
|
|
|
|
byte_order = *d;
|
|
|
|
i = random_int_in_range (4, _dbus_string_get_length (mutated) - 8);
|
|
i = _DBUS_ALIGN_VALUE (i, 4);
|
|
|
|
orig = _dbus_demarshal_uint32 (mutated, byte_order, i, NULL);
|
|
|
|
delta = random_int_in_range (-10, 10);
|
|
|
|
_dbus_marshal_set_uint32 (mutated, byte_order, i,
|
|
(unsigned) (orig + delta));
|
|
}
|
|
|
|
static void
|
|
randomly_set_extreme_ints (const DBusString *orig_data,
|
|
DBusString *mutated)
|
|
{
|
|
int i;
|
|
int byte_order;
|
|
const char *d;
|
|
dbus_uint32_t orig;
|
|
static int which = 0;
|
|
unsigned int extreme_ints[] = {
|
|
_DBUS_INT_MAX,
|
|
_DBUS_UINT_MAX,
|
|
_DBUS_INT_MAX - 1,
|
|
_DBUS_UINT_MAX - 1,
|
|
_DBUS_INT_MAX - 2,
|
|
_DBUS_UINT_MAX - 2,
|
|
_DBUS_INT_MAX - 17,
|
|
_DBUS_UINT_MAX - 17,
|
|
_DBUS_INT_MAX / 2,
|
|
_DBUS_INT_MAX / 3,
|
|
_DBUS_UINT_MAX / 2,
|
|
_DBUS_UINT_MAX / 3,
|
|
0, 1, 2, 3,
|
|
(unsigned int) -1,
|
|
(unsigned int) -2,
|
|
(unsigned int) -3
|
|
};
|
|
|
|
if (orig_data != mutated)
|
|
{
|
|
_dbus_string_set_length (mutated, 0);
|
|
|
|
if (!_dbus_string_copy (orig_data, 0, mutated, 0))
|
|
_dbus_assert_not_reached ("out of mem");
|
|
}
|
|
|
|
if (_dbus_string_get_length (mutated) < 12)
|
|
return;
|
|
|
|
d = _dbus_string_get_const_data (mutated);
|
|
|
|
if (!(*d == DBUS_LITTLE_ENDIAN ||
|
|
*d == DBUS_BIG_ENDIAN))
|
|
return;
|
|
|
|
byte_order = *d;
|
|
|
|
i = random_int_in_range (4, _dbus_string_get_length (mutated) - 8);
|
|
i = _DBUS_ALIGN_VALUE (i, 4);
|
|
|
|
orig = _dbus_demarshal_uint32 (mutated, byte_order, i, NULL);
|
|
|
|
which = random_int_in_range (0, _DBUS_N_ELEMENTS (extreme_ints));
|
|
|
|
_dbus_assert (which >= 0);
|
|
_dbus_assert (which < _DBUS_N_ELEMENTS (extreme_ints));
|
|
|
|
_dbus_marshal_set_uint32 (mutated, byte_order, i,
|
|
extreme_ints[which]);
|
|
}
|
|
|
|
static int
|
|
random_type (void)
|
|
{
|
|
const char types[] = {
|
|
DBUS_TYPE_INVALID,
|
|
DBUS_TYPE_NIL,
|
|
DBUS_TYPE_BYTE,
|
|
DBUS_TYPE_BOOLEAN,
|
|
DBUS_TYPE_INT32,
|
|
DBUS_TYPE_UINT32,
|
|
DBUS_TYPE_INT64,
|
|
DBUS_TYPE_UINT64,
|
|
DBUS_TYPE_DOUBLE,
|
|
DBUS_TYPE_STRING,
|
|
DBUS_TYPE_CUSTOM,
|
|
DBUS_TYPE_ARRAY,
|
|
DBUS_TYPE_DICT,
|
|
DBUS_TYPE_OBJECT_PATH
|
|
};
|
|
|
|
_dbus_assert (_DBUS_N_ELEMENTS (types) == DBUS_NUMBER_OF_TYPES + 1);
|
|
|
|
return types[ random_int_in_range (0, _DBUS_N_ELEMENTS (types)) ];
|
|
}
|
|
|
|
static void
|
|
randomly_change_one_type (const DBusString *orig_data,
|
|
DBusString *mutated)
|
|
{
|
|
int i;
|
|
int len;
|
|
|
|
if (orig_data != mutated)
|
|
{
|
|
_dbus_string_set_length (mutated, 0);
|
|
|
|
if (!_dbus_string_copy (orig_data, 0, mutated, 0))
|
|
_dbus_assert_not_reached ("out of mem");
|
|
}
|
|
|
|
if (_dbus_string_get_length (mutated) == 0)
|
|
return;
|
|
|
|
len = _dbus_string_get_length (mutated);
|
|
i = random_int_in_range (0, len);
|
|
|
|
/* Look for a type starting at a random location,
|
|
* and replace with a different type
|
|
*/
|
|
while (i < len)
|
|
{
|
|
int b;
|
|
b = _dbus_string_get_byte (mutated, i);
|
|
if (dbus_type_is_valid (b))
|
|
{
|
|
_dbus_string_set_byte (mutated, i, random_type ());
|
|
return;
|
|
}
|
|
++i;
|
|
}
|
|
}
|
|
|
|
static int times_we_did_each_thing[7] = { 0, };
|
|
|
|
static void
|
|
randomly_do_n_things (const DBusString *orig_data,
|
|
DBusString *mutated,
|
|
int n)
|
|
{
|
|
int i;
|
|
void (* functions[]) (const DBusString *orig_data,
|
|
DBusString *mutated) =
|
|
{
|
|
randomly_shorten_or_lengthen,
|
|
randomly_change_one_byte,
|
|
randomly_add_one_byte,
|
|
randomly_remove_one_byte,
|
|
randomly_modify_length,
|
|
randomly_set_extreme_ints,
|
|
randomly_change_one_type
|
|
};
|
|
|
|
_dbus_string_set_length (mutated, 0);
|
|
|
|
if (!_dbus_string_copy (orig_data, 0, mutated, 0))
|
|
_dbus_assert_not_reached ("out of mem");
|
|
|
|
i = 0;
|
|
while (i < n)
|
|
{
|
|
int which;
|
|
|
|
which = random_int_in_range (0, _DBUS_N_ELEMENTS (functions));
|
|
|
|
(* functions[which]) (mutated, mutated);
|
|
times_we_did_each_thing[which] += 1;
|
|
|
|
++i;
|
|
}
|
|
}
|
|
|
|
static dbus_bool_t
|
|
find_breaks_based_on (const DBusString *filename,
|
|
dbus_bool_t is_raw,
|
|
DBusMessageValidity expected_validity,
|
|
void *data)
|
|
{
|
|
DBusString orig_data;
|
|
DBusString mutated;
|
|
const char *filename_c;
|
|
dbus_bool_t retval;
|
|
int i;
|
|
|
|
filename_c = _dbus_string_get_const_data (filename);
|
|
|
|
retval = FALSE;
|
|
|
|
if (!_dbus_string_init (&orig_data))
|
|
_dbus_assert_not_reached ("could not allocate string\n");
|
|
|
|
if (!_dbus_string_init (&mutated))
|
|
_dbus_assert_not_reached ("could not allocate string\n");
|
|
|
|
if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
|
|
&orig_data))
|
|
{
|
|
fprintf (stderr, "could not load file %s\n", filename_c);
|
|
goto failed;
|
|
}
|
|
|
|
printf (" changing one random byte 100 times\n");
|
|
i = 0;
|
|
while (i < 100)
|
|
{
|
|
randomly_change_one_byte (&orig_data, &mutated);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
printf (" changing length 50 times\n");
|
|
i = 0;
|
|
while (i < 50)
|
|
{
|
|
randomly_modify_length (&orig_data, &mutated);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
printf (" removing one byte 50 times\n");
|
|
i = 0;
|
|
while (i < 50)
|
|
{
|
|
randomly_remove_one_byte (&orig_data, &mutated);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
printf (" adding one byte 50 times\n");
|
|
i = 0;
|
|
while (i < 50)
|
|
{
|
|
randomly_add_one_byte (&orig_data, &mutated);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
printf (" changing ints to boundary values 50 times\n");
|
|
i = 0;
|
|
while (i < 50)
|
|
{
|
|
randomly_set_extreme_ints (&orig_data, &mutated);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
printf (" changing typecodes 50 times\n");
|
|
i = 0;
|
|
while (i < 50)
|
|
{
|
|
randomly_change_one_type (&orig_data, &mutated);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
printf (" changing message length 15 times\n");
|
|
i = 0;
|
|
while (i < 15)
|
|
{
|
|
randomly_shorten_or_lengthen (&orig_data, &mutated);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
printf (" randomly making 2 of above modifications 42 times\n");
|
|
i = 0;
|
|
while (i < 42)
|
|
{
|
|
randomly_do_n_things (&orig_data, &mutated, 2);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
printf (" randomly making 3 of above modifications 42 times\n");
|
|
i = 0;
|
|
while (i < 42)
|
|
{
|
|
randomly_do_n_things (&orig_data, &mutated, 3);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
printf (" randomly making 4 of above modifications 42 times\n");
|
|
i = 0;
|
|
while (i < 42)
|
|
{
|
|
randomly_do_n_things (&orig_data, &mutated, 4);
|
|
try_mutated_data (&mutated);
|
|
|
|
++i;
|
|
}
|
|
|
|
retval = TRUE;
|
|
|
|
failed:
|
|
|
|
_dbus_string_free (&orig_data);
|
|
_dbus_string_free (&mutated);
|
|
|
|
/* FALSE means end the whole process */
|
|
return retval;
|
|
}
|
|
|
|
static unsigned int
|
|
get_random_seed (void)
|
|
{
|
|
DBusString bytes;
|
|
unsigned int seed;
|
|
int fd;
|
|
const char *s;
|
|
|
|
seed = 0;
|
|
|
|
if (!_dbus_string_init (&bytes))
|
|
exit (1);
|
|
|
|
fd = open ("/dev/urandom", O_RDONLY);
|
|
if (fd < 0)
|
|
goto use_fallback;
|
|
|
|
if (_dbus_read (fd, &bytes, 4) != 4)
|
|
goto use_fallback;
|
|
|
|
close (fd);
|
|
|
|
s = _dbus_string_get_const_data (&bytes);
|
|
|
|
seed = * (unsigned int*) s;
|
|
goto out;
|
|
|
|
use_fallback:
|
|
{
|
|
long tv_usec;
|
|
|
|
fprintf (stderr, "could not open/read /dev/urandom, using current time for seed\n");
|
|
|
|
_dbus_get_monotonic_time (NULL, &tv_usec);
|
|
|
|
seed = tv_usec;
|
|
}
|
|
|
|
out:
|
|
_dbus_string_free (&bytes);
|
|
|
|
return seed;
|
|
}
|
|
|
|
int
|
|
main (int argc,
|
|
char **argv)
|
|
{
|
|
const char *test_data_dir;
|
|
const char *failure_dir_c;
|
|
int total_failures_found;
|
|
|
|
if (argc > 1)
|
|
test_data_dir = argv[1];
|
|
else
|
|
{
|
|
fprintf (stderr, "Must specify a top_srcdir/test/data directory\n");
|
|
return 1;
|
|
}
|
|
|
|
total_failures_found = 0;
|
|
total_attempts = 0;
|
|
|
|
if (!_dbus_string_init (&failure_dir))
|
|
return 1;
|
|
|
|
/* so you can leave it overnight safely */
|
|
#define MAX_FAILURES 1000
|
|
|
|
while (total_failures_found < MAX_FAILURES)
|
|
{
|
|
unsigned int seed;
|
|
|
|
failures_this_iteration = 0;
|
|
|
|
seed = get_random_seed ();
|
|
|
|
_dbus_string_set_length (&failure_dir, 0);
|
|
|
|
if (!_dbus_string_append (&failure_dir, "failures-"))
|
|
return 1;
|
|
|
|
if (!_dbus_string_append_uint (&failure_dir, seed))
|
|
return 1;
|
|
|
|
failure_dir_c = _dbus_string_get_const_data (&failure_dir);
|
|
|
|
if (mkdir (failure_dir_c, 0700) < 0)
|
|
{
|
|
if (errno != EEXIST)
|
|
fprintf (stderr, "didn't mkdir %s: %s\n",
|
|
failure_dir_c, strerror (errno));
|
|
}
|
|
|
|
printf ("next seed = %u \ttotal failures %d of %d attempts\n",
|
|
seed, total_failures_found, total_attempts);
|
|
|
|
srand (seed);
|
|
|
|
if (!dbus_internal_do_not_use_foreach_message_file (test_data_dir,
|
|
find_breaks_based_on,
|
|
NULL))
|
|
{
|
|
fprintf (stderr, "fatal error iterating over message files\n");
|
|
rmdir (failure_dir_c);
|
|
return 1;
|
|
}
|
|
|
|
printf (" did %d random mutations: %d %d %d %d %d %d %d\n",
|
|
_DBUS_N_ELEMENTS (times_we_did_each_thing),
|
|
times_we_did_each_thing[0],
|
|
times_we_did_each_thing[1],
|
|
times_we_did_each_thing[2],
|
|
times_we_did_each_thing[3],
|
|
times_we_did_each_thing[4],
|
|
times_we_did_each_thing[5],
|
|
times_we_did_each_thing[6]);
|
|
|
|
printf ("Found %d failures with seed %u stored in %s\n",
|
|
failures_this_iteration, seed, failure_dir_c);
|
|
|
|
total_failures_found += failures_this_iteration;
|
|
|
|
rmdir (failure_dir_c); /* does nothing if non-empty */
|
|
}
|
|
|
|
return 0;
|
|
}
|