From patchwork Tue Dec 3 21:05:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 16570 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id F3DDB448733 for ; Tue, 3 Dec 2019 23:07:36 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C597168B4B0; Tue, 3 Dec 2019 23:07:36 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk1-f196.google.com (mail-qk1-f196.google.com [209.85.222.196]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C4D20689C04 for ; Tue, 3 Dec 2019 23:07:29 +0200 (EET) Received: by mail-qk1-f196.google.com with SMTP id f5so4909671qkm.13 for ; Tue, 03 Dec 2019 13:07:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=gfbUHZm110FhiaATZZEMtKkHvKoyp2bNkjhfi11/yJo=; b=eU5H0/pvDmxh/MLV2DD1xlDnjnFa3NVlzDxF/9oF03p9RNsjdaNZHgxMEC7T9nfqkT y7EbDazy4aExJyn0UcWNTY9vMYE6NPASy5W3gkyKea9PNmi1YM5tUEcPxaCQIXt0uSgW kqIfa4VzDAxMIAuANls9QXjWv8Qqn/X8li0KAy/QFKPci/Ox8JwvdFUAxD9CtiRGiZyU XGxnBMCZx4G6whJ73v2irtspHl88d4VV2sy4jVI03xe15hQEkwCg+WVjxl68UhjB2N0M Em0lHJ8EzMvZgARie/5obheVN4PdK6lE4HqTxqPE/2KzCjdFSqfCyJQA5sKAvhjxPxTA YUkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gfbUHZm110FhiaATZZEMtKkHvKoyp2bNkjhfi11/yJo=; b=ZZ81q8X3s0EXcnJKady4Y7qA2PmuqqAyVwVKfPD9ZELCN+mAYd2j+PqFcffzoKUWLO 6gI/nB+zOuNzQlmlGimYfzEqZ/+J0TTeBw/pIu1I+4YPYThj/36/K8oeG1Os3H31uIGX w6yRQEgqmMcvm6v8dfc6vnIvjjUdys0xRbTbO/GZPdsmuMX4S2AyQ7XutccR3bSUJkIq ksy1AYEuy6olQkJWgQ7IH1w6vje/GX15MmOTQCaUPkUAutADiFagldHpT9jQykSt37uX bL0rmVoqZqsv9amwzVSFYvqx46rHtOGTJyCVXat5HIgBH67CnlgjEbUCwBlD5LimogIR n3bA== X-Gm-Message-State: APjAAAVrQD9U+SFxIM1+mH+JmST8SlVTcwCeQipdE3zTJF4FLndz8y34 yYKaY7oTQpLc6NQHAffLYO3El1xQ X-Google-Smtp-Source: APXvYqyJ/LYe/WhkK9oqyCNqDNNX5nlNbPXsY32Ns2qoON4V6/tGzonp2NInKQHrOnGzAbCDQhKlnQ== X-Received: by 2002:a05:620a:a92:: with SMTP id v18mr7103440qkg.261.1575407248355; Tue, 03 Dec 2019 13:07:28 -0800 (PST) Received: from localhost.localdomain ([181.23.79.171]) by smtp.gmail.com with ESMTPSA id 184sm2433270qke.73.2019.12.03.13.07.27 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Dec 2019 13:07:27 -0800 (PST) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Tue, 3 Dec 2019 18:05:41 -0300 Message-Id: <20191203210541.363-1-jamrial@gmail.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191203193108.f5rkp2om6fgptpeu@manj> References: <20191203193108.f5rkp2om6fgptpeu@manj> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2] tools: add a fuzzer tool for bitstream filters X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: James Almer --- tools/Makefile | 3 + tools/target_bsf_fuzzer.c | 153 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 tools/target_bsf_fuzzer.c diff --git a/tools/Makefile b/tools/Makefile index 370ee35416..001093105b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -5,6 +5,9 @@ TOOLS-$(CONFIG_ZLIB) += cws2fws tools/target_dec_%_fuzzer.o: tools/target_dec_fuzzer.c $(COMPILE_C) -DFFMPEG_DECODER=$* +tools/target_bsf_%_fuzzer.o: tools/target_bsf_fuzzer.c + $(COMPILE_C) -DFFMPEG_BSF=$* + tools/target_dem_fuzzer.o: tools/target_dem_fuzzer.c $(COMPILE_C) diff --git a/tools/target_bsf_fuzzer.c b/tools/target_bsf_fuzzer.c new file mode 100644 index 0000000000..f3e584fdf4 --- /dev/null +++ b/tools/target_bsf_fuzzer.c @@ -0,0 +1,153 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/imgutils.h" + +#include "libavcodec/avcodec.h" +#include "libavcodec/bsf.h" +#include "libavcodec/bytestream.h" +#include "libavcodec/internal.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +static void error(const char *err) +{ + fprintf(stderr, "%s", err); + exit(1); +} + +static AVBitStreamFilter *f = NULL; + +static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + const uint64_t fuzz_tag = FUZZ_TAG; + const uint8_t *last = data; + const uint8_t *end = data + size; + AVBSFContext *bsf = NULL; + AVPacket in, out; + uint64_t keyframes = 0; + int res; + + if (!f) { +#ifdef FFMPEG_BSF +#define BSF_SYMBOL0(BSF) ff_##BSF##_bsf +#define BSF_SYMBOL(BSF) BSF_SYMBOL0(BSF) + extern AVBitStreamFilter BSF_SYMBOL(FFMPEG_BSF); + f = &BSF_SYMBOL(FFMPEG_BSF); +#else + extern AVBitStreamFilter ff_null_bsf; + f = &ff_null_bsf; +#endif + av_log_set_level(AV_LOG_PANIC); + } + + res = av_bsf_alloc(f, &bsf); + if (res < 0) + error("Failed memory allocation"); + + if (size > 1024) { + GetByteContext gbc; + int extradata_size; + size -= 1024; + bytestream2_init(&gbc, data + size, 1024); + bsf->par_in->width = bytestream2_get_le32(&gbc); + bsf->par_in->height = bytestream2_get_le32(&gbc); + bsf->par_in->bit_rate = bytestream2_get_le64(&gbc); + bsf->par_in->bits_per_coded_sample = bytestream2_get_le32(&gbc); + + if (f->codec_ids) { + int i, id; + for (i = 0; f->codec_ids[i] != AV_CODEC_ID_NONE; i++); + id = f->codec_ids[bytestream2_get_byte(&gbc) % i]; + bsf->par_in->codec_id = id; + bsf->par_in->codec_tag = bytestream2_get_le32(&gbc); + } + + extradata_size = bytestream2_get_le32(&gbc); + + bsf->par_in->sample_rate = bytestream2_get_le32(&gbc); + bsf->par_in->channels = (unsigned)bytestream2_get_le32(&gbc) % FF_SANE_NB_CHANNELS; + bsf->par_in->block_align = bytestream2_get_le32(&gbc); + keyframes = bytestream2_get_le64(&gbc); + + if (extradata_size < size) { + bsf->par_in->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (bsf->par_in->extradata) { + bsf->par_in->extradata_size = extradata_size; + size -= bsf->par_in->extradata_size; + memcpy(bsf->par_in->extradata, data + size, bsf->par_in->extradata_size); + } + } + if (av_image_check_size(bsf->par_in->width, bsf->par_in->height, 0, bsf)) + bsf->par_in->width = bsf->par_in->height = 0; + } + + res = av_bsf_init(bsf); + if (res < 0) { + av_bsf_free(&bsf); + return 0; // Failure of av_bsf_init() does not imply that a issue was found + } + + av_init_packet(&in); + av_init_packet(&out); + out.data = NULL; + out.size = 0; + while (data < end) { + // Search for the TAG + while (data + sizeof(fuzz_tag) < end) { + if (data[0] == (fuzz_tag & 0xFF) && AV_RN64(data) == fuzz_tag) + break; + data++; + } + if (data + sizeof(fuzz_tag) > end) + data = end; + + res = av_new_packet(&in, data - last); + if (res < 0) + error("Failed memory allocation"); + memcpy(in.data, last, data - last); + in.flags = (keyframes & 1) * AV_PKT_FLAG_DISCARD + (!!(keyframes & 2)) * AV_PKT_FLAG_KEY; + keyframes = (keyframes >> 2) + (keyframes<<62); + data += sizeof(fuzz_tag); + last = data; + + while (in.size) { + res = av_bsf_send_packet(bsf, &in); + if (res < 0 && res != AVERROR(EAGAIN)) + break; + res = av_bsf_receive_packet(bsf, &out); + if (res < 0) + break; + av_packet_unref(&out); + } + av_packet_unref(&in); + } + + res = av_bsf_send_packet(bsf, NULL); + while (!res) { + res = av_bsf_receive_packet(bsf, &out); + if (res < 0) + break; + av_packet_unref(&out); + } + + av_bsf_free(&bsf); + return 0; +}