Skip to content

Commit

Permalink
dfuzzer: allow specifying a custom set of input strings
Browse files Browse the repository at this point in the history
  • Loading branch information
mrc0mmand authored and evverx committed May 8, 2022
1 parent 4303074 commit ed8b9fa
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 4 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ set -e
"${dfuzzer[@]}" -s -v -n org.freedesktop.dfuzzerServer -o /org/freedesktop/dfuzzerObject -i org.freedesktop.dfuzzerInterface -t df_complex_sig_1
"${dfuzzer[@]}" -s -v -n org.freedesktop.dfuzzerServer -o /org/freedesktop/dfuzzerObject -i org.freedesktop.dfuzzerInterface -t df_complex_sig_2

# Crash on a specific string
"${dfuzzer[@]}" -s -v -n org.freedesktop.dfuzzerServer -o /org/freedesktop/dfuzzerObject -i org.freedesktop.dfuzzerInterface -t df_crash_on_leeroy
cat >inputs.txt <<'EOF'
a string
also a string
probably a string
Leeroy Jenkins
you guessed it - also a string
no way this is a string as well
EOF
"${dfuzzer[@]}" -f inputs.txt -s -v -n org.freedesktop.dfuzzerServer -o /org/freedesktop/dfuzzerObject -i org.freedesktop.dfuzzerInterface -t df_crash_on_leeroy && false
rm -f inputs.txt

sudo systemctl stop dfuzzer-test-server

# dfuzzer should return 0 by default when services it tests time out
Expand Down
8 changes: 8 additions & 0 deletions man/dfuzzer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@
unsuccessfully, fail message is printed with its return value.</para></listitem>
</varlistentry>

<varlistentry>
<term><option>-f <replaceable>FILENAME</replaceable></option></term>
<term><option>--dictionary=<replaceable>FILENAME</replaceable></option></term>

<listitem><para>Name of a file with custom dictionary whhich is used as input for fuzzed methods
before generating random data. Currently supports only strings (one per line).</para></listitem>
</varlistentry>

<varlistentry>
<term><option>-x <replaceable>ITERATIONS</replaceable></option></term>
<term><option>--max-iterations=<replaceable>ITERATIONS</replaceable></option></term>
Expand Down
13 changes: 12 additions & 1 deletion src/dfuzzer-test-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ static const gchar introspection_xml[] =
" <method name='df_variant_crash'>"
" <arg type='v' name='variant' direction='in'/>"
" </method>"
" <method name='df_crash_on_leeroy'>"
" <arg type='s' name='string' direction='in'/>"
" </method>"
" <method name='df_complex_sig_1'>"
" <arg type='i' name='in1' direction='in'/>"
" <arg type='u' name='in2' direction='in'/>"
Expand Down Expand Up @@ -114,7 +117,15 @@ static void handle_method_call(
g_printf("Sending response to Client: [%s]\n", response);
} else if (g_strcmp0(method_name, "df_crash") == 0 || g_strcmp0(method_name, "df_variant_crash") == 0)
abort();
else if (g_strcmp0(method_name, "df_hang") == 0)
else if (g_strcmp0(method_name, "df_crash_on_leeroy") == 0) {
gchar *str = NULL;

g_variant_get(parameters, "(&s)", &str);
if (g_strcmp0(str, "Leeroy Jenkins") == 0)
abort();

g_dbus_method_invocation_return_value(invocation, g_variant_new("()"));
} else if (g_strcmp0(method_name, "df_hang") == 0)
pause();
else if (g_strcmp0(method_name, "df_noreply") == 0)
return;
Expand Down
14 changes: 13 additions & 1 deletion src/dfuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "dfuzzer.h"
#include "introspection.h"
#include "fuzz.h"
#include "rand.h"
#include "util.h"


Expand Down Expand Up @@ -779,6 +780,7 @@ void df_parse_parameters(int argc, char **argv)
{ "buffer-limit", required_argument, NULL, 'b' },
{ "debug", no_argument, NULL, 'd' },
{ "command", required_argument, NULL, 'e' },
{ "string-file", required_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
{ "interface", required_argument, NULL, 'i' },
{ "list", no_argument, NULL, 'l' },
Expand All @@ -796,7 +798,7 @@ void df_parse_parameters(int argc, char **argv)
{}
};

while ((c = getopt_long(argc, argv, "n:o:i:m:b:t:e:L:x:y:I:sdvlhV", options, NULL)) >= 0) {
while ((c = getopt_long(argc, argv, "n:o:i:m:b:t:e:L:x:y:f:I:sdvlhV", options, NULL)) >= 0) {
switch (c) {
case 'n':
if (strlen(optarg) >= MAXLEN) {
Expand Down Expand Up @@ -917,6 +919,14 @@ void df_parse_parameters(int argc, char **argv)

df_max_iterations = df_min_iterations;

break;
case 'f':
r = df_rand_load_external_dictionary(optarg);
if (r < 0) {
df_fail("Error: failed to load dictionary from file '%s'\n", optarg);
exit(1);
}

break;
default: // '?'
exit(1);
Expand Down Expand Up @@ -1137,6 +1147,8 @@ void df_print_help(const char *name)
" -I --iterations=ITER Set both the minimum and maximum number of iterations to ITER\n"
" See --max-iterations= and --min-iterations= above\n"
" -e --command=COMMAND Command/script to execute after each method call.\n"
" -f --dictionary=FILENAME Name of a file with custom dictionary which is used as input\n"
" for fuzzed methods before generating random data.\n"
"\nExamples:\n\n"
"Test all methods of GNOME Shell. Be verbose.\n"
"# %1$s -v -n org.gnome.Shell\n\n"
Expand Down
51 changes: 49 additions & 2 deletions src/rand.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <gio/gio.h>
#include <stdio.h>
#include <stdlib.h>
Expand All @@ -32,6 +33,7 @@

/** Maximum buffer size for generated strings (in Bytes) */
static size_t df_buf_size;
static struct external_dictionary df_external_dictionary;

/**
* @function Initializes global flag variables and seeds pseudo-random
Expand All @@ -49,6 +51,41 @@ void df_rand_init(const long buf_size)
df_buf_size = buf_size;
}

int df_rand_load_external_dictionary(const char *filename)
{
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *line = NULL;
char **array = NULL;
size_t allocated = 0, len = 0, i = 0;
ssize_t n;

assert(filename);

f = fopen(filename, "r");
if (!f)
return df_fail_ret(-errno, "Failed to open file '%s': %m\n", filename);

while ((n = getline(&line, &len, f)) > 0) {
/* Extend the array if we're out of space */
if (i >= allocated) {
allocated += 10;
array = realloc(array, sizeof(array) * allocated);
if (!array)
return df_oom();
}

/* Drop the newline */
if (line[n - 1] == '\n')
line[n - 1] = 0;

array[i++] = TAKE_PTR(line);
}

df_external_dictionary.strings = TAKE_PTR(array);
df_external_dictionary.size = i;

return 0;
}
/**
* @return Generated pseudo-random 8-bit unsigned integer value
*/
Expand Down Expand Up @@ -281,11 +318,21 @@ int df_rand_string(gchar **buf, guint64 iteration)
_cleanup_(g_freep) gchar *ret = NULL;
size_t len;

if (iteration < G_N_ELEMENTS(test_strings)) {
/* If -f/--string-file= was used, use the loaded strings instead of the
* pre-defined ones, before generating random ones. */
if (df_external_dictionary.size > 0) {
if (iteration < df_external_dictionary.size) {
ret = strdup(df_external_dictionary.strings[iteration]);
if (!ret)
return df_fail_ret(-1, "Could not allocate memory for the random string\n");
}
} else if (iteration < G_N_ELEMENTS(test_strings)) {
ret = strdup(test_strings[iteration]);
if (!ret)
return df_fail_ret(-1, "Could not allocate memory for the random string\n");
} else {
}

if (!ret) {
/* Genearate a pseudo-random string length in interval <0, df_buf_size) */
len = (rand() * iteration) % df_buf_size;
len = CLAMP(len, 1, df_buf_size);
Expand Down
5 changes: 5 additions & 0 deletions src/rand.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,18 @@
/** Maximum length of D-Bus signature string */
#define MAXSIG 255

struct external_dictionary {
size_t size;
char **strings;
};

/**
* @function Initializes global flag variables and seeds pseudo-random
* numbers generators.
* @param buf_size Maximum buffer size for generated strings (in Bytes)
*/
void df_rand_init(const long buf_size);
int df_rand_load_external_dictionary(const char *filename);

/**
* @return Generated pseudo-random 8-bit unsigned integer value
Expand Down

0 comments on commit ed8b9fa

Please sign in to comment.