Linking app with jpegdec

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;
}

Your problem is that source is NULL (or otherwise an invalid pointer). So creating the appsrc fails.

Can you check the debug logs to see where GStreamer is looking for plugins, and does that contain the app plugin?

Also, do the existing fuzz targets run in your setup?