From 938938a985c6836059b48cd61a5ee05b2b36f881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Fri, 23 Aug 2024 17:04:05 +0200 Subject: [PATCH] fuzzer_options_parser: add options parser fuzzing To improve coverage of parse_commandline.c --- fuzzers/common.h | 2 + fuzzers/fuzzer_options_parser.c | 68 +++++++++++++++++++++++++++++++++ fuzzers/meson.build | 5 +++ player/client.c | 14 ++++++- 4 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 fuzzers/fuzzer_options_parser.c diff --git a/fuzzers/common.h b/fuzzers/common.h index 2cc20308a0..90328d04f0 100644 --- a/fuzzers/common.h +++ b/fuzzers/common.h @@ -23,6 +23,8 @@ #include #include +#include + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); #define MPV_STRINGIFY_(X) #X diff --git a/fuzzers/fuzzer_options_parser.c b/fuzzers/fuzzer_options_parser.c new file mode 100644 index 0000000000..e62c16f27a --- /dev/null +++ b/fuzzers/fuzzer_options_parser.c @@ -0,0 +1,68 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#include +#include +#include + +#include "common.h" + +int mpv_initialize_opts(mpv_handle *ctx, char **options); + +#define MAX_INPUT_SIZE (1 << 20) +#define MAX_OPTS_NUM 10000 + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + char buff[MAX_INPUT_SIZE + 2]; + + if (!size || size > MAX_INPUT_SIZE) + return 0; + + memcpy(buff, data, size); + buff[size] = '\0'; + buff[size + 1] = '\0'; + + char *opts[MAX_OPTS_NUM + 1]; + char *opt = buff; + int count = 0; + while (*opt && count < MAX_OPTS_NUM) { + opts[count] = opt; + + while (*opt && !isspace(*opt)) + opt++; + + *opt = '\0'; + opt++; + + while (*opt && isspace(*opt)) + opt++; + + count++; + } + opts[count] = NULL; + + mpv_handle *ctx = mpv_create(); + if (!ctx) + exit(1); + + mpv_initialize_opts(ctx, opts); + + mpv_terminate_destroy(ctx); + + return 0; +} diff --git a/fuzzers/meson.build b/fuzzers/meson.build index f8c07ca509..2cfe5aa10e 100644 --- a/fuzzers/meson.build +++ b/fuzzers/meson.build @@ -71,4 +71,9 @@ foreach cmd : ['file', '-config-file', '-input-conf'] link_with: libmpv) endforeach +fuzzers += executable('fuzzer_options_parser', 'fuzzer_options_parser.c', + link_language: 'cpp', include_directories: incdir, + objects: libmpv.extract_all_objects(recursive: true), + dependencies: dependencies) + alias_target('fuzzers', fuzzers) diff --git a/player/client.c b/player/client.c index bcee9c4246..42b311ee5d 100644 --- a/player/client.c +++ b/player/client.c @@ -649,15 +649,25 @@ mpv_handle *mpv_create_weak_client(mpv_handle *ctx, const char *name) return new; } -int mpv_initialize(mpv_handle *ctx) +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +int mpv_initialize_opts(mpv_handle *ctx, char **options); +#else +static +#endif +int mpv_initialize_opts(mpv_handle *ctx, char **options) { lock_core(ctx); - int res = mp_initialize(ctx->mpctx, NULL) ? MPV_ERROR_INVALID_PARAMETER : 0; + int res = mp_initialize(ctx->mpctx, options) ? MPV_ERROR_INVALID_PARAMETER : 0; mp_wakeup_core(ctx->mpctx); unlock_core(ctx); return res; } +int mpv_initialize(mpv_handle *ctx) +{ + return mpv_initialize_opts(ctx, NULL); +} + // set ev->data to a new copy of the original data // (done only for message types that are broadcast) static void dup_event_data(struct mpv_event *ev)