I’m writing a new fuzz harness for gstream for jpegdec. I’ve never used mason before, so this build system is a bit new to me. I could use some help figuring out how to link correctly with the meson.build. Many thanks in advance for any help.
I’m following ci/fuzzing/typefind.c as a template, and my harness is called fuzz_jpeg. Everything compiles fine (source below), but it seems that I’m not linking in the right library.
When I run the harness, I get:
./build/ci/fuzzing/fuzz_jpeg /mnt/JPEG_example_flower.jpg
Reading 36287 bytes from /mnt/JPEG_example_flower.jpg
CRITICAL ERROR : gst_bin_add_many: assertion 'GST_IS_ELEMENT (element_1)' failed
Here is the change I made to ci/fuzzing/meson.build
:
fuzz_targets = [
['gst-discoverer.c', false, ['gstreamer-pbutils-1.0']],
['fuzz_jpeg.c', false, ['libjpeg]],
['typefind.c']
]
The harness compiles fine. But I don’t think the right libraries are getting linked in, and I’m not sure what they should be. Here is what ldd shows:
$ ldd fuzz_jpeg
linux-vdso.so.1 (0x0000ffffaf2d6000)
libgstreamer-1.0.so.0 => /build/build/ci/fuzzing/./../../subprojects/gstreamer/gst/libgstreamer-1.0.so.0 (0x0000ffffaef00000)
libglib-2.0.so.0 => /build/build/ci/fuzzing/./../../subprojects/glib-2.78.3/glib/libglib-2.0.so.0 (0x0000ffffaed10000)
libgobject-2.0.so.0 => /build/build/ci/fuzzing/./../../subprojects/glib-2.78.3/gobject/libgobject-2.0.so.0 (0x0000ffffaec90000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffaeae0000)
libgmodule-2.0.so.0 => /build/build/ci/fuzzing/./../../subprojects/gstreamer/gst/../../glib-2.78.3/gmodule/libgmodule-2.0.so.0 (0x0000ffffaeab0000)
libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000ffffaea10000)
libffi.so.8 => /lib/aarch64-linux-gnu/libffi.so.8 (0x0000ffffae9e0000)
/lib/ld-linux-aarch64.so.1 (0x0000ffffaf299000)
If it helps, here is the code right now:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <locale.h>
#include <stdlib.h>
#include <glib.h>
#include <gst/gst.h>
#include <stdio.h>
static void
custom_logger (const gchar * log_domain,
GLogLevelFlags log_level, const gchar * message, gpointer unused_data)
{
if (log_level & G_LOG_LEVEL_CRITICAL) {
g_printerr ("CRITICAL ERROR : %s\n", message);
abort ();
} else if (log_level & G_LOG_LEVEL_WARNING) {
g_printerr ("WARNING : %s\n", message);
}
}
int
LLVMFuzzerTestOneInput (const guint8 * data, size_t size)
{
static gboolean initialized = FALSE;
GstElement *pipeline, *source, *jpegdec, *sink;
GstBuffer *buf;
GstFlowReturn flowret;
GstState state;
if (!initialized) {
/* We want critical warnings to assert so we can fix them */
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
g_log_set_default_handler (custom_logger, NULL);
/* Only initialize and register plugins once */
gst_init (NULL, NULL);
initialized = TRUE;
}
/* Create the pipeline */
pipeline = gst_pipeline_new (NULL);
source = gst_element_factory_make ("appsrc", NULL);
jpegdec = gst_element_factory_make ("jpegdec", NULL);
sink = gst_element_factory_make ("appsink", NULL);
gst_bin_add_many(GST_BIN (pipeline), source, jpegdec, sink, NULL);
gst_element_link_many (source, jpegdec, sink, NULL);
/* Set pipeline to READY so we can provide data to appsrc */
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
buf = gst_buffer_new_wrapped_full (0, (gpointer) data, size,
0, size, NULL, NULL);
g_object_set (G_OBJECT (source), "size", size, NULL);
g_signal_emit_by_name (G_OBJECT (source), "push-buffer", buf, &flowret);
gst_buffer_unref (buf);
/* Set pipeline to PAUSED and wait (typefind will either fail or succeed) */
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
/* wait until state change either completes or fails */
gst_element_get_state (GST_ELEMENT (pipeline), &state, NULL, -1);
/* Go back to NULL */
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
/* And release the pipeline */
gst_object_unref (pipeline);
return 0;
}