2003-02-01 04:58:16 +00:00
|
|
|
/* -*- mode: C; c-file-style: "gnu" -*- */
|
|
|
|
|
/* 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 1.2
|
|
|
|
|
*
|
|
|
|
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2003-02-05 23:56:39 +00:00
|
|
|
#include <dbus/dbus.h>
|
2003-02-01 04:58:16 +00:00
|
|
|
#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>
|
|
|
|
|
|
2003-02-05 23:56:39 +00:00
|
|
|
#define DBUS_COMPILATION
|
|
|
|
|
#include <dbus/dbus-string.h>
|
|
|
|
|
#include <dbus/dbus-internals.h>
|
|
|
|
|
#include <dbus/dbus-test.h>
|
|
|
|
|
#include <dbus/dbus-marshal.h>
|
|
|
|
|
#undef DBUS_COMPILATION
|
|
|
|
|
|
2003-02-01 04:58:16 +00:00
|
|
|
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_INT_MAX) ||
|
|
|
|
|
!_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)
|
|
|
|
|
{
|
2003-02-01 05:16:31 +00:00
|
|
|
_dbus_string_append (&filename, "-exited-");
|
2003-02-01 04:58:16 +00:00
|
|
|
_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)
|
|
|
|
|
{
|
|
|
|
|
const char *filename_c;
|
|
|
|
|
DBusResultCode result;
|
|
|
|
|
|
2003-02-01 05:16:31 +00:00
|
|
|
_dbus_string_append (&filename, ".message-raw");
|
|
|
|
|
|
2003-02-01 04:58:16 +00:00
|
|
|
_dbus_string_get_const_data (&filename, &filename_c);
|
|
|
|
|
printf ("Child failed, writing %s\n",
|
|
|
|
|
filename_c);
|
|
|
|
|
|
|
|
|
|
result = _dbus_string_save_to_file (data, &filename);
|
|
|
|
|
|
|
|
|
|
if (result != DBUS_RESULT_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
fprintf (stderr, "Failed to save failed message data: %s\n",
|
|
|
|
|
dbus_result_to_string (result));
|
|
|
|
|
exit (1); /* so we can see the seed that was printed out */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
failures_this_iteration += 1;
|
|
|
|
|
|
2003-02-13 20:34:13 +00:00
|
|
|
_dbus_string_free (&filename);
|
|
|
|
|
|
2003-02-01 04:58:16 +00:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
2003-02-13 20:34:13 +00:00
|
|
|
{
|
|
|
|
|
_dbus_string_free (&filename);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2003-02-01 04:58:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_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_byte (mutated, i,
|
|
|
|
|
random_int_in_range (0, 256));
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-01 05:16:31 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
_dbus_string_get_const_data (mutated, &d);
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-01 04:58:16 +00:00
|
|
|
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,
|
2003-02-01 05:16:31 +00:00
|
|
|
randomly_remove_one_byte,
|
|
|
|
|
randomly_modify_length
|
2003-02-01 04:58:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
_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);
|
|
|
|
|
|
|
|
|
|
++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;
|
|
|
|
|
|
|
|
|
|
_dbus_string_get_const_data (filename, &filename_c);
|
|
|
|
|
|
|
|
|
|
retval = FALSE;
|
|
|
|
|
|
|
|
|
|
if (!_dbus_string_init (&orig_data, _DBUS_INT_MAX))
|
|
|
|
|
_dbus_assert_not_reached ("could not allocate string\n");
|
|
|
|
|
|
|
|
|
|
if (!_dbus_string_init (&mutated, _DBUS_INT_MAX))
|
|
|
|
|
_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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (i < 100)
|
|
|
|
|
{
|
|
|
|
|
randomly_change_one_byte (&orig_data, &mutated);
|
|
|
|
|
try_mutated_data (&mutated);
|
|
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-01 05:16:31 +00:00
|
|
|
i = 0;
|
|
|
|
|
while (i < 50)
|
|
|
|
|
{
|
|
|
|
|
randomly_modify_length (&orig_data, &mutated);
|
|
|
|
|
try_mutated_data (&mutated);
|
|
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-01 04:58:16 +00:00
|
|
|
i = 0;
|
|
|
|
|
while (i < 50)
|
|
|
|
|
{
|
|
|
|
|
randomly_remove_one_byte (&orig_data, &mutated);
|
|
|
|
|
try_mutated_data (&mutated);
|
|
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (i < 50)
|
|
|
|
|
{
|
|
|
|
|
randomly_add_one_byte (&orig_data, &mutated);
|
|
|
|
|
try_mutated_data (&mutated);
|
|
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (i < 15)
|
|
|
|
|
{
|
|
|
|
|
randomly_shorten_or_lengthen (&orig_data, &mutated);
|
|
|
|
|
try_mutated_data (&mutated);
|
|
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (i < 42)
|
|
|
|
|
{
|
|
|
|
|
randomly_do_n_things (&orig_data, &mutated, 2);
|
|
|
|
|
try_mutated_data (&mutated);
|
|
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (i < 42)
|
|
|
|
|
{
|
|
|
|
|
randomly_do_n_things (&orig_data, &mutated, 3);
|
|
|
|
|
try_mutated_data (&mutated);
|
|
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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, _DBUS_INT_MAX))
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
_dbus_string_get_const_data (&bytes, &s);
|
|
|
|
|
|
|
|
|
|
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_current_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, _DBUS_INT_MAX))
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
_dbus_string_get_const_data (&failure_dir, &failure_dir_c);
|
|
|
|
|
|
|
|
|
|
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 ("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;
|
|
|
|
|
}
|