diff --git a/fuzzing/gst-discoverer.c b/fuzzing/gst-discoverer.c new file mode 100644 index 0000000000..1f862aaa95 --- /dev/null +++ b/fuzzing/gst-discoverer.c @@ -0,0 +1,118 @@ +/* + * Copyright 2016 Google Inc. + * author: Edward Hervey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include + +GST_PLUGIN_STATIC_DECLARE(coreelements); +GST_PLUGIN_STATIC_DECLARE(playback); +GST_PLUGIN_STATIC_DECLARE(typefindfunctions); +GST_PLUGIN_STATIC_DECLARE(app); +GST_PLUGIN_STATIC_DECLARE(ogg); +GST_PLUGIN_STATIC_DECLARE(theora); +GST_PLUGIN_STATIC_DECLARE(vorbis); + +/* push-based discoverer fuzzing target + * + * This application can be compiled with libFuzzer to simulate + * a push-based discoverer execution. + * + * To reproduce the failing behaviour, use: + * $ gst-discoverer-1.0 pushfile:///... + * + * The goal is to cover basic usage of demuxers, parsers and + * base decoder elements. + * + * When compiling, only link the required demuxer/parser/decoder + * plugins and keep it to a limited range (ex: ogg/theora/vorbis) + * + **/ + +const guint8 *fuzztesting_data; +size_t fuzztesting_size; + +static void +appsrc_configuration (GstDiscoverer *dc, GstElement *source, gpointer data) +{ + GstBuffer *buf; + GstFlowReturn ret; + + /* Create buffer from fuzztesting_data which shouldn't be freed */ + buf = gst_buffer_new_wrapped_full (0, (gpointer) fuzztesting_data, fuzztesting_size, + 0, fuzztesting_size, NULL, NULL); + g_object_set (G_OBJECT (source), "size", fuzztesting_size, NULL); + g_signal_emit_by_name (G_OBJECT(source), "push-buffer", buf, &ret); + gst_buffer_unref (buf); +} + +int LLVMFuzzerTestOneInput(const guint8 *data, size_t size) +{ + GError *err = NULL; + GstDiscoverer *dc; + gint timeout = 10; + GstDiscovererInfo *info; + static gboolean initialized = 0; + + if (!initialized) { + /* We want critical warnings to assert so we can fix them + * But somehow it's not causing oss-fuzz to crash ... */ + g_setenv ("G_DEBUG", "fatal-criticals", TRUE); + + /* Only initialize and register plugins once */ + gst_init (NULL, NULL); + + GST_PLUGIN_STATIC_REGISTER(coreelements); + GST_PLUGIN_STATIC_REGISTER(playback); + GST_PLUGIN_STATIC_REGISTER(typefindfunctions); + GST_PLUGIN_STATIC_REGISTER(app); + GST_PLUGIN_STATIC_REGISTER(ogg); + GST_PLUGIN_STATIC_REGISTER(theora); + GST_PLUGIN_STATIC_REGISTER(vorbis); + } + + dc = gst_discoverer_new (timeout * GST_SECOND, &err); + if (G_UNLIKELY (dc == NULL)) { + g_print ("Error initializing: %s\n", err->message); + g_clear_error (&err); + exit (1); + } + + fuzztesting_data = data; + fuzztesting_size = size; + + /* Connect to source-setup signal to give the data */ + g_signal_connect (dc, "source-setup", (GCallback) appsrc_configuration, NULL); + + info = gst_discoverer_discover_uri (dc, "appsrc://", &err); + g_clear_error (&err); + if (info) + gst_discoverer_info_unref (info); + + g_object_unref (dc); + + return 0; + } +