mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-04-24 08:00:44 +02:00
2003-02-01 Havoc Pennington <hp@pobox.com>
* dbus/dbus-break-loader.c (main): new program to find messages that break the loader. * dbus/dbus-sysdeps.c (_dbus_string_append_uint): new function * dbus/dbus-sysdeps.c (_dbus_string_save_to_file): new function * dbus/dbus-string.c (_dbus_string_set_byte): new
This commit is contained in:
parent
d8f9c46bf8
commit
e0ffb6eb14
10 changed files with 910 additions and 116 deletions
10
ChangeLog
10
ChangeLog
|
|
@ -1,3 +1,13 @@
|
|||
2003-02-01 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* dbus/dbus-break-loader.c (main): new program to find messages
|
||||
that break the loader.
|
||||
|
||||
* dbus/dbus-sysdeps.c (_dbus_string_append_uint): new function
|
||||
* dbus/dbus-sysdeps.c (_dbus_string_save_to_file): new function
|
||||
|
||||
* dbus/dbus-string.c (_dbus_string_set_byte): new
|
||||
|
||||
2003-01-31 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* dbus/dbus-message.c: refactor the test code to be more general,
|
||||
|
|
|
|||
|
|
@ -85,12 +85,16 @@ libdbus_1_la_LIBADD= $(DBUS_CLIENT_LIBS) libdbus-convenience.la
|
|||
## convention for internal symbols)
|
||||
libdbus_1_la_LDFLAGS= -export-symbols-regex "^[^_].*"
|
||||
|
||||
## FIXME it would be less annoying when hacking if we didn't have
|
||||
## to relink these test binaries, so moving them to the test/*
|
||||
## subdir would be nice.
|
||||
|
||||
## note that TESTS has special meaning (stuff to use in make check)
|
||||
## so if adding tests not to be run in make check, don't add them to
|
||||
## TESTS
|
||||
if DBUS_BUILD_TESTS
|
||||
TESTS_ENVIRONMENT=DBUS_TEST_DATA=$(top_srcdir)/test/data
|
||||
TESTS=dbus-test
|
||||
TESTS=dbus-test dbus-break-loader
|
||||
else
|
||||
TESTS=
|
||||
endif
|
||||
|
|
@ -103,3 +107,8 @@ dbus_test_SOURCES= \
|
|||
dbus-test-main.c
|
||||
|
||||
dbus_test_LDADD= $(DBUS_CLIENT_LIBS) libdbus-convenience.la libdbus-1.la
|
||||
|
||||
dbus_break_loader_SOURCES= \
|
||||
dbus-break-loader.c
|
||||
|
||||
dbus_break_loader_LDADD= $(DBUS_CLIENT_LIBS) libdbus-convenience.la libdbus-1.la
|
||||
539
dbus/dbus-break-loader.c
Normal file
539
dbus/dbus-break-loader.c
Normal file
|
|
@ -0,0 +1,539 @@
|
|||
/* -*- 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dbus-types.h"
|
||||
#include "dbus-test.h"
|
||||
#include "dbus-internals.h"
|
||||
#include "dbus-sysdeps.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>
|
||||
|
||||
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)
|
||||
{
|
||||
_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)
|
||||
{
|
||||
const char *filename_c;
|
||||
DBusResultCode result;
|
||||
|
||||
_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;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
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_byte (mutated, i,
|
||||
random_int_in_range (0, 256));
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -1225,7 +1225,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
|
|||
break;
|
||||
|
||||
default:
|
||||
_dbus_warn ("Unknown message arg type %d\n", *data);
|
||||
_dbus_verbose ("Unknown message arg type %d\n", *data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2483,11 +2483,56 @@ check_loader_results (DBusMessageLoader *loader,
|
|||
|
||||
|
||||
/**
|
||||
* Tries loading the message in the given message file.
|
||||
* The file must end in .message for our message-builder language
|
||||
* or .message-raw for a binary file to be treated as a message
|
||||
* verbatim.
|
||||
* Loads the message in the given message file.
|
||||
*
|
||||
* @param filename filename to load
|
||||
* @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
|
||||
* @param data string to load message into
|
||||
* @returns #TRUE if the message was loaded
|
||||
*/
|
||||
dbus_bool_t
|
||||
dbus_internal_do_not_use_load_message_file (const DBusString *filename,
|
||||
dbus_bool_t is_raw,
|
||||
DBusString *data)
|
||||
{
|
||||
dbus_bool_t retval;
|
||||
|
||||
retval = FALSE;
|
||||
|
||||
if (is_raw)
|
||||
{
|
||||
DBusResultCode result;
|
||||
|
||||
result = _dbus_file_get_contents (data, filename);
|
||||
if (result != DBUS_RESULT_SUCCESS)
|
||||
{
|
||||
const char *s;
|
||||
_dbus_string_get_const_data (filename, &s);
|
||||
_dbus_warn ("Could not load message file %s\n", s);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_dbus_message_data_load (data, filename))
|
||||
{
|
||||
const char *s;
|
||||
_dbus_string_get_const_data (filename, &s);
|
||||
_dbus_warn ("Could not load message file %s\n", s);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
retval = TRUE;
|
||||
|
||||
failed:
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries loading the message in the given message file
|
||||
* and verifies that DBusMessageLoader can handle it.
|
||||
*
|
||||
* @param filename filename to load
|
||||
* @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
|
||||
|
|
@ -2500,6 +2545,51 @@ dbus_internal_do_not_use_try_message_file (const DBusString *filename,
|
|||
DBusMessageValidity expected_validity)
|
||||
{
|
||||
DBusString data;
|
||||
dbus_bool_t retval;
|
||||
|
||||
retval = FALSE;
|
||||
|
||||
if (!_dbus_string_init (&data, _DBUS_INT_MAX))
|
||||
_dbus_assert_not_reached ("could not allocate string\n");
|
||||
|
||||
if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
|
||||
&data))
|
||||
goto failed;
|
||||
|
||||
retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
|
||||
|
||||
failed:
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
if (_dbus_string_get_length (&data) > 0)
|
||||
_dbus_verbose_bytes_of_string (&data, 0,
|
||||
_dbus_string_get_length (&data));
|
||||
|
||||
_dbus_string_get_const_data (filename, &s);
|
||||
_dbus_warn ("Failed message loader test on %s\n",
|
||||
s);
|
||||
}
|
||||
|
||||
_dbus_string_free (&data);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries loading the given message data.
|
||||
*
|
||||
*
|
||||
* @param data the message data
|
||||
* @param expected_validity what the message has to be like to return #TRUE
|
||||
* @returns #TRUE if the message has the expected validity
|
||||
*/
|
||||
dbus_bool_t
|
||||
dbus_internal_do_not_use_try_message_data (const DBusString *data,
|
||||
DBusMessageValidity expected_validity)
|
||||
{
|
||||
DBusMessageLoader *loader;
|
||||
dbus_bool_t retval;
|
||||
int len;
|
||||
|
|
@ -2507,46 +2597,19 @@ dbus_internal_do_not_use_try_message_file (const DBusString *filename,
|
|||
|
||||
loader = NULL;
|
||||
retval = FALSE;
|
||||
|
||||
if (!_dbus_string_init (&data, _DBUS_INT_MAX))
|
||||
_dbus_assert_not_reached ("could not allocate string\n");
|
||||
|
||||
if (is_raw)
|
||||
{
|
||||
DBusResultCode result;
|
||||
|
||||
result = _dbus_file_get_contents (&data, filename);
|
||||
if (result != DBUS_RESULT_SUCCESS)
|
||||
{
|
||||
const char *s;
|
||||
_dbus_string_get_const_data (filename, &s);
|
||||
_dbus_warn ("Could not load message file %s\n", s);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_dbus_message_data_load (&data, filename))
|
||||
{
|
||||
const char *s;
|
||||
_dbus_string_get_const_data (filename, &s);
|
||||
_dbus_warn ("Could not load message file %s\n", s);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the data one byte at a time */
|
||||
|
||||
loader = _dbus_message_loader_new ();
|
||||
|
||||
len = _dbus_string_get_length (&data);
|
||||
len = _dbus_string_get_length (data);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
DBusString *buffer;
|
||||
|
||||
_dbus_message_loader_get_buffer (loader, &buffer);
|
||||
_dbus_string_append_byte (buffer,
|
||||
_dbus_string_get_byte (&data, i));
|
||||
_dbus_string_get_byte (data, i));
|
||||
_dbus_message_loader_return_buffer (loader, buffer, 1);
|
||||
}
|
||||
|
||||
|
|
@ -2564,7 +2627,7 @@ dbus_internal_do_not_use_try_message_file (const DBusString *filename,
|
|||
DBusString *buffer;
|
||||
|
||||
_dbus_message_loader_get_buffer (loader, &buffer);
|
||||
_dbus_string_copy (&data, 0, buffer,
|
||||
_dbus_string_copy (data, 0, buffer,
|
||||
_dbus_string_get_length (buffer));
|
||||
_dbus_message_loader_return_buffer (loader, buffer, 1);
|
||||
}
|
||||
|
|
@ -2579,17 +2642,17 @@ dbus_internal_do_not_use_try_message_file (const DBusString *filename,
|
|||
|
||||
loader = _dbus_message_loader_new ();
|
||||
|
||||
len = _dbus_string_get_length (&data);
|
||||
len = _dbus_string_get_length (data);
|
||||
for (i = 0; i < len; i += 2)
|
||||
{
|
||||
DBusString *buffer;
|
||||
|
||||
_dbus_message_loader_get_buffer (loader, &buffer);
|
||||
_dbus_string_append_byte (buffer,
|
||||
_dbus_string_get_byte (&data, i));
|
||||
_dbus_string_get_byte (data, i));
|
||||
if ((i+1) < len)
|
||||
_dbus_string_append_byte (buffer,
|
||||
_dbus_string_get_byte (&data, i+1));
|
||||
_dbus_string_get_byte (data, i+1));
|
||||
_dbus_message_loader_return_buffer (loader, buffer, 1);
|
||||
}
|
||||
|
||||
|
|
@ -2602,22 +2665,9 @@ dbus_internal_do_not_use_try_message_file (const DBusString *filename,
|
|||
retval = TRUE;
|
||||
|
||||
failed:
|
||||
if (!retval)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
if (_dbus_string_get_length (&data) > 0)
|
||||
_dbus_verbose_bytes_of_string (&data, 0,
|
||||
_dbus_string_get_length (&data));
|
||||
|
||||
_dbus_string_get_const_data (filename, &s);
|
||||
_dbus_warn ("Failed message loader test on %s\n",
|
||||
s);
|
||||
}
|
||||
|
||||
if (loader)
|
||||
_dbus_message_loader_unref (loader);
|
||||
_dbus_string_free (&data);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -2648,7 +2698,7 @@ process_test_subdir (const DBusString *test_base_dir,
|
|||
_dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
|
||||
|
||||
if (!_dbus_concat_dir_and_file (&test_directory, &filename))
|
||||
_dbus_assert_not_reached ("could't allocate full path");
|
||||
_dbus_assert_not_reached ("couldn't allocate full path");
|
||||
|
||||
_dbus_string_free (&filename);
|
||||
if (!_dbus_string_init (&filename, _DBUS_INT_MAX))
|
||||
|
|
|
|||
|
|
@ -299,6 +299,59 @@ _dbus_string_lock (DBusString *str)
|
|||
}
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
set_length (DBusRealString *real,
|
||||
int new_length)
|
||||
{
|
||||
/* Note, we are setting the length without nul termination */
|
||||
|
||||
/* exceeding max length is the same as failure to allocate memory */
|
||||
if (new_length > real->max_length)
|
||||
return FALSE;
|
||||
|
||||
while (new_length >= real->allocated)
|
||||
{
|
||||
int new_allocated;
|
||||
char *new_str;
|
||||
|
||||
new_allocated = 2 + real->allocated * 2;
|
||||
if (new_allocated < real->allocated)
|
||||
return FALSE; /* overflow */
|
||||
|
||||
new_str = dbus_realloc (real->str, new_allocated);
|
||||
if (new_str == NULL)
|
||||
return FALSE;
|
||||
|
||||
real->str = new_str;
|
||||
real->allocated = new_allocated;
|
||||
|
||||
ASSERT_8_BYTE_ALIGNED (real);
|
||||
}
|
||||
|
||||
real->len = new_length;
|
||||
real->str[real->len] = '\0';
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
open_gap (int len,
|
||||
DBusRealString *dest,
|
||||
int insert_at)
|
||||
{
|
||||
if (len == 0)
|
||||
return TRUE;
|
||||
|
||||
if (!set_length (dest, dest->len + len))
|
||||
return FALSE;
|
||||
|
||||
memmove (dest->str + insert_at + len,
|
||||
dest->str + insert_at,
|
||||
dest->len - len - insert_at);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw character buffer from the string. The returned buffer
|
||||
* will be nul-terminated, but note that strings may contain binary
|
||||
|
|
@ -387,6 +440,24 @@ _dbus_string_get_const_data_len (const DBusString *str,
|
|||
*data_return = real->str + start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the byte at the given position.
|
||||
*
|
||||
* @param str the string
|
||||
* @param i the position
|
||||
* @param byte the new value
|
||||
*/
|
||||
void
|
||||
_dbus_string_set_byte (DBusString *str,
|
||||
int i,
|
||||
unsigned char byte)
|
||||
{
|
||||
DBUS_STRING_PREAMBLE (str);
|
||||
_dbus_assert (i < real->len);
|
||||
|
||||
real->str[i] = byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the byte at the given position.
|
||||
*
|
||||
|
|
@ -394,7 +465,7 @@ _dbus_string_get_const_data_len (const DBusString *str,
|
|||
* @param start the position
|
||||
* @returns the byte at that position
|
||||
*/
|
||||
char
|
||||
unsigned char
|
||||
_dbus_string_get_byte (const DBusString *str,
|
||||
int start)
|
||||
{
|
||||
|
|
@ -404,6 +475,30 @@ _dbus_string_get_byte (const DBusString *str,
|
|||
return real->str[start];
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given byte at the given position.
|
||||
*
|
||||
* @param str the string
|
||||
* @param i the position
|
||||
* @param byte the value to insert
|
||||
* @returns #TRUE on success
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_string_insert_byte (DBusString *str,
|
||||
int i,
|
||||
unsigned char byte)
|
||||
{
|
||||
DBUS_STRING_PREAMBLE (str);
|
||||
_dbus_assert (i <= real->len);
|
||||
|
||||
if (!open_gap (1, real, i))
|
||||
return FALSE;
|
||||
|
||||
real->str[i] = byte;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like _dbus_string_get_data(), but removes the
|
||||
* gotten data from the original string. The caller
|
||||
|
|
@ -493,41 +588,6 @@ _dbus_string_get_length (const DBusString *str)
|
|||
return real->len;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
set_length (DBusRealString *real,
|
||||
int new_length)
|
||||
{
|
||||
/* Note, we are setting the length without nul termination */
|
||||
|
||||
/* exceeding max length is the same as failure to allocate memory */
|
||||
if (new_length > real->max_length)
|
||||
return FALSE;
|
||||
|
||||
while (new_length >= real->allocated)
|
||||
{
|
||||
int new_allocated;
|
||||
char *new_str;
|
||||
|
||||
new_allocated = 2 + real->allocated * 2;
|
||||
if (new_allocated < real->allocated)
|
||||
return FALSE; /* overflow */
|
||||
|
||||
new_str = dbus_realloc (real->str, new_allocated);
|
||||
if (new_str == NULL)
|
||||
return FALSE;
|
||||
|
||||
real->str = new_str;
|
||||
real->allocated = new_allocated;
|
||||
|
||||
ASSERT_8_BYTE_ALIGNED (real);
|
||||
}
|
||||
|
||||
real->len = new_length;
|
||||
real->str[real->len] = '\0';
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a string longer by the given number of bytes. Checks whether
|
||||
* adding additional_length to the current length would overflow an
|
||||
|
|
@ -811,24 +871,6 @@ _dbus_string_delete (DBusString *str,
|
|||
delete (real, start, len);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
open_gap (int len,
|
||||
DBusRealString *dest,
|
||||
int insert_at)
|
||||
{
|
||||
if (len == 0)
|
||||
return TRUE;
|
||||
|
||||
if (!set_length (dest, dest->len + len))
|
||||
return FALSE;
|
||||
|
||||
memmove (dest->str + insert_at + len,
|
||||
dest->str + insert_at,
|
||||
dest->len - len - insert_at);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
copy (DBusRealString *source,
|
||||
int start,
|
||||
|
|
@ -2281,6 +2323,43 @@ _dbus_string_test (void)
|
|||
_dbus_assert (ch == 0xfffc);
|
||||
_dbus_assert (i == _dbus_string_get_length (&str));
|
||||
|
||||
_dbus_string_free (&str);
|
||||
|
||||
/* Check insert/set/get byte */
|
||||
|
||||
if (!_dbus_string_init (&str, _DBUS_INT_MAX))
|
||||
_dbus_assert_not_reached ("failed to init string");
|
||||
|
||||
if (!_dbus_string_append (&str, "Hello"))
|
||||
_dbus_assert_not_reached ("failed to append Hello");
|
||||
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
|
||||
|
||||
_dbus_string_set_byte (&str, 1, 'q');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
|
||||
|
||||
if (!_dbus_string_insert_byte (&str, 0, 255))
|
||||
_dbus_assert_not_reached ("can't insert byte");
|
||||
|
||||
if (!_dbus_string_insert_byte (&str, 2, 'Z'))
|
||||
_dbus_assert_not_reached ("can't insert byte");
|
||||
|
||||
if (!_dbus_string_insert_byte (&str, _dbus_string_get_length (&str), 'W'))
|
||||
_dbus_assert_not_reached ("can't insert byte");
|
||||
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 3) == 'q');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 4) == 'l');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 5) == 'l');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 6) == 'o');
|
||||
_dbus_assert (_dbus_string_get_byte (&str, 7) == 'W');
|
||||
|
||||
_dbus_string_free (&str);
|
||||
|
||||
/* Check append/parse int/double */
|
||||
|
|
|
|||
|
|
@ -66,8 +66,14 @@ void _dbus_string_get_const_data_len (const DBusString *str,
|
|||
const char **data_return,
|
||||
int start,
|
||||
int len);
|
||||
char _dbus_string_get_byte (const DBusString *str,
|
||||
void _dbus_string_set_byte (DBusString *str,
|
||||
int i,
|
||||
unsigned char byte);
|
||||
unsigned char _dbus_string_get_byte (const DBusString *str,
|
||||
int start);
|
||||
dbus_bool_t _dbus_string_insert_byte (DBusString *str,
|
||||
int i,
|
||||
unsigned char byte);
|
||||
dbus_bool_t _dbus_string_steal_data (DBusString *str,
|
||||
char **data_return);
|
||||
dbus_bool_t _dbus_string_steal_data_len (DBusString *str,
|
||||
|
|
@ -93,6 +99,8 @@ dbus_bool_t _dbus_string_append_len (DBusString *str,
|
|||
int len);
|
||||
dbus_bool_t _dbus_string_append_int (DBusString *str,
|
||||
long value);
|
||||
dbus_bool_t _dbus_string_append_uint (DBusString *str,
|
||||
unsigned long value);
|
||||
dbus_bool_t _dbus_string_append_double (DBusString *str,
|
||||
double value);
|
||||
dbus_bool_t _dbus_string_append_byte (DBusString *str,
|
||||
|
|
|
|||
|
|
@ -617,6 +617,44 @@ _dbus_string_append_int (DBusString *str,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an unsigned integer to a DBusString.
|
||||
*
|
||||
* @param str the string
|
||||
* @param value the integer value
|
||||
* @returns #FALSE if not enough memory or other failure.
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_string_append_uint (DBusString *str,
|
||||
unsigned long value)
|
||||
{
|
||||
/* this is wrong, but definitely on the high side. */
|
||||
#define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
|
||||
int orig_len;
|
||||
int i;
|
||||
char *buf;
|
||||
|
||||
orig_len = _dbus_string_get_length (str);
|
||||
|
||||
if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
|
||||
return FALSE;
|
||||
|
||||
_dbus_string_get_data_len (str, &buf, orig_len, MAX_ULONG_LEN);
|
||||
|
||||
snprintf (buf, MAX_ULONG_LEN, "%lu", value);
|
||||
|
||||
i = 0;
|
||||
while (*buf)
|
||||
{
|
||||
++buf;
|
||||
++i;
|
||||
}
|
||||
|
||||
_dbus_string_shorten (str, MAX_ULONG_LEN - i);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a double to a DBusString.
|
||||
*
|
||||
|
|
@ -1102,6 +1140,59 @@ _dbus_file_get_contents (DBusString *str,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a string out to a file.
|
||||
*
|
||||
* @param str the string to write out
|
||||
* @param filename the file to save string to
|
||||
* @returns result code
|
||||
*/
|
||||
DBusResultCode
|
||||
_dbus_string_save_to_file (const DBusString *str,
|
||||
const DBusString *filename)
|
||||
{
|
||||
int fd;
|
||||
int bytes_to_write;
|
||||
const char *filename_c;
|
||||
int total;
|
||||
|
||||
_dbus_string_get_const_data (filename, &filename_c);
|
||||
|
||||
fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
|
||||
0700);
|
||||
if (fd < 0)
|
||||
return _dbus_result_from_errno (errno);
|
||||
|
||||
total = 0;
|
||||
bytes_to_write = _dbus_string_get_length (str);
|
||||
|
||||
while (total < bytes_to_write)
|
||||
{
|
||||
int bytes_written;
|
||||
|
||||
bytes_written = _dbus_write (fd, str, total,
|
||||
bytes_to_write - total);
|
||||
|
||||
if (bytes_written <= 0)
|
||||
{
|
||||
DBusResultCode result;
|
||||
|
||||
result = _dbus_result_from_errno (errno); /* prior to close() */
|
||||
|
||||
_dbus_verbose ("write() failed: %s",
|
||||
_dbus_strerror (errno));
|
||||
|
||||
close (fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
total += bytes_written;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
return DBUS_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the given filename to the given directory.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -122,8 +122,10 @@ void _dbus_sleep_milliseconds (int milliseconds);
|
|||
void _dbus_get_current_time (long *tv_sec,
|
||||
long *tv_usec);
|
||||
|
||||
DBusResultCode _dbus_file_get_contents (DBusString *str,
|
||||
const DBusString *filename);
|
||||
DBusResultCode _dbus_file_get_contents (DBusString *str,
|
||||
const DBusString *filename);
|
||||
DBusResultCode _dbus_string_save_to_file (const DBusString *str,
|
||||
const DBusString *filename);
|
||||
|
||||
dbus_bool_t _dbus_concat_dir_and_file (DBusString *dir,
|
||||
const DBusString *next_component);
|
||||
|
|
|
|||
|
|
@ -43,10 +43,16 @@ dbus_bool_t _dbus_string_test (void);
|
|||
dbus_bool_t _dbus_address_test (void);
|
||||
dbus_bool_t _dbus_message_test (const char *test_data_dir);
|
||||
|
||||
void dbus_internal_do_not_use_run_tests (const char *test_data_dir);
|
||||
dbus_bool_t dbus_internal_do_not_use_try_message_file (const DBusString *filename,
|
||||
dbus_bool_t is_raw,
|
||||
DBusMessageValidity expected_validity);
|
||||
void dbus_internal_do_not_use_run_tests (const char *test_data_dir);
|
||||
dbus_bool_t dbus_internal_do_not_use_try_message_file (const DBusString *filename,
|
||||
dbus_bool_t is_raw,
|
||||
DBusMessageValidity expected_validity);
|
||||
dbus_bool_t dbus_internal_do_not_use_try_message_data (const DBusString *data,
|
||||
DBusMessageValidity expected_validity);
|
||||
dbus_bool_t dbus_internal_do_not_use_load_message_file (const DBusString *filename,
|
||||
dbus_bool_t is_raw,
|
||||
DBusString *data);
|
||||
|
||||
|
||||
/* returns FALSE on fatal failure */
|
||||
typedef dbus_bool_t (* DBusForeachMessageFileFunc) (const DBusString *filename,
|
||||
|
|
@ -55,8 +61,8 @@ typedef dbus_bool_t (* DBusForeachMessageFileFunc) (const DBusString *filename
|
|||
void *data);
|
||||
|
||||
dbus_bool_t dbus_internal_do_not_use_foreach_message_file (const char *test_data_dir,
|
||||
DBusForeachMessageFileFunc func,
|
||||
void *user_data);
|
||||
DBusForeachMessageFileFunc func,
|
||||
void *user_data);
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue