mirror of
https://gitee.com/openharmony/third_party_libsnd
synced 2024-11-23 01:49:53 +00:00
Add ossfuzz support for libsndfile
Fixes #476 Add a fuzzer (`sndfile_fuzzer`) which can be compiled and run by the OSS-Fuzz infrastructure.
This commit is contained in:
parent
0642efd52e
commit
20c65fecd9
15
.github/workflows/action.yml
vendored
15
.github/workflows/action.yml
vendored
@ -10,6 +10,7 @@ jobs:
|
||||
name: [
|
||||
ubuntu-gcc-autotools,
|
||||
ubuntu-clang-autotools,
|
||||
ubuntu-gcc-ossfuzz,
|
||||
macos-autotools,
|
||||
ubuntu-gcc-cmake,
|
||||
ubuntu-gcc-cmake-shared,
|
||||
@ -35,6 +36,12 @@ jobs:
|
||||
cxx: clang++
|
||||
build-system: autotools
|
||||
|
||||
- name: ubuntu-gcc-ossfuzz
|
||||
os: ubuntu-latest
|
||||
cc: gcc
|
||||
cxx: g++
|
||||
build-system: ossfuzz
|
||||
|
||||
- name: macos-autotools
|
||||
os: macos-latest
|
||||
cc: clang
|
||||
@ -209,3 +216,11 @@ jobs:
|
||||
cmake .. -G "${{matrix.cmake-generator}}" ${{matrix.cmake-options}}
|
||||
cmake --build . --config Release
|
||||
ctest
|
||||
|
||||
- name: Configure, build and test with OSSFuzz
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
CXX: ${{ matrix.cxx }}
|
||||
if: startsWith(matrix.build-system,'ossfuzz')
|
||||
run: |
|
||||
./ossfuzz/ci_oss.sh
|
||||
|
35
Makefile.am
35
Makefile.am
@ -26,6 +26,8 @@ cmake_files = cmake/ClipMode.cmake cmake/FindFLAC.cmake \
|
||||
|
||||
pkgconfig_DATA = sndfile.pc
|
||||
|
||||
noinst_PROGRAMS =
|
||||
|
||||
#===============================================================================
|
||||
|
||||
test: check
|
||||
@ -435,6 +437,39 @@ man/sndfile-deinterleave.1: man/sndfile-interleave.1
|
||||
-rm -f $@
|
||||
cd $(top_srcdir)/man && $(LN_S) sndfile-interleave.1 sndfile-deinterleave.1
|
||||
|
||||
############
|
||||
# ossfuzz/ #
|
||||
############
|
||||
|
||||
if USE_OSSFUZZ_FLAG
|
||||
FUZZ_FLAG = $(LIB_FUZZING_ENGINE)
|
||||
FUZZ_LDADD =
|
||||
else
|
||||
if USE_OSSFUZZ_STATIC
|
||||
FUZZ_LDADD = $(LIB_FUZZING_ENGINE)
|
||||
FUZZ_FLAG =
|
||||
else
|
||||
FUZZ_LDADD = libstandaloneengine.la
|
||||
FUZZ_FLAG =
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_OSSFUZZERS
|
||||
noinst_PROGRAMS += \
|
||||
ossfuzz/sndfile_fuzzer
|
||||
|
||||
noinst_LTLIBRARIES += \
|
||||
ossfuzz/libstandaloneengine.la
|
||||
endif
|
||||
|
||||
ossfuzz_sndfile_fuzzer_SOURCES = ossfuzz/sndfile_fuzzer.cc
|
||||
ossfuzz_sndfile_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG)
|
||||
ossfuzz_sndfile_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static
|
||||
ossfuzz_sndfile_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD)
|
||||
|
||||
ossfuzz_libstandaloneengine_la_SOURCES = ossfuzz/standaloneengine.cc ossfuzz/testinput.h
|
||||
ossfuzz_libstandaloneengine_la_CXXFLAGS = $(AM_CXXFLAGS)
|
||||
|
||||
#############
|
||||
# programs/ #
|
||||
#############
|
||||
|
10
configure.ac
10
configure.ac
@ -163,6 +163,16 @@ AC_ARG_ENABLE([test-coverage],
|
||||
[AS_HELP_STRING([--enable-test-coverage], [enable test coverage])])
|
||||
AM_CONDITIONAL([ENABLE_TEST_COVERAGE], [test "x$enable_test_coverage" = "xyes"])
|
||||
|
||||
AC_ARG_ENABLE([ossfuzzers],
|
||||
[AS_HELP_STRING([--enable-ossfuzzers],
|
||||
[Whether to generate the fuzzers for OSS-Fuzz])],
|
||||
[have_ossfuzzers=yes], [have_ossfuzzers=no])
|
||||
AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$have_ossfuzzers" = "xyes"])
|
||||
|
||||
AC_SUBST([LIB_FUZZING_ENGINE])
|
||||
AM_CONDITIONAL([USE_OSSFUZZ_FLAG], [test "x$LIB_FUZZING_ENGINE" = "x-fsanitize=fuzzer"])
|
||||
AM_CONDITIONAL([USE_OSSFUZZ_STATIC], [test -f "$LIB_FUZZING_ENGINE"])
|
||||
|
||||
dnl ====================================================================================
|
||||
dnl Check types and their sizes.
|
||||
|
||||
|
1
ossfuzz/.gitignore
vendored
Normal file
1
ossfuzz/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
sndfile_fuzzer
|
41
ossfuzz/ci_oss.sh
Executable file
41
ossfuzz/ci_oss.sh
Executable file
@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
PROJECT_NAME=libsndfile
|
||||
|
||||
# Clone the oss-fuzz repository
|
||||
git clone https://github.com/google/oss-fuzz.git /tmp/ossfuzz
|
||||
|
||||
# TODO: Verify that the GITHUB variables below are correct for a PR
|
||||
env | grep "GITHUB_"
|
||||
|
||||
if [[ ! -d /tmp/ossfuzz/projects/${PROJECT_NAME} ]]
|
||||
then
|
||||
echo "Could not find the ${PROJECT_NAME} project in ossfuzz"
|
||||
|
||||
# Exit with a success code while the libsndfile project is not expected to exist
|
||||
# on oss-fuzz.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Work out which repo to clone from, inside Docker
|
||||
if [[ -n ${GITHUB_BASE_REF} ]]
|
||||
then
|
||||
# Pull-request branch
|
||||
REPO=${GITHUB_REPOSITORY}
|
||||
BRANCH=${GITHUB_BASE_REF}
|
||||
else
|
||||
# Push build.
|
||||
REPO=${GITHUB_REPOSITORY}
|
||||
BRANCH=${GITHUB_REF}
|
||||
fi
|
||||
|
||||
# Modify the oss-fuzz Dockerfile so that we're checking out the current branch on travis.
|
||||
sed -i "s@https://github.com/erikd/libsndfile.git@-b ${BRANCH} https://github.com/${REPO}.git@" /tmp/ossfuzz/projects/${PROJECT_NAME}/Dockerfile
|
||||
|
||||
# Try and build the fuzzers
|
||||
pushd /tmp/ossfuzz
|
||||
python infra/helper.py build_image --pull ${PROJECT_NAME}
|
||||
python infra/helper.py build_fuzzers ${PROJECT_NAME}
|
||||
popd
|
28
ossfuzz/ossfuzz.sh
Executable file
28
ossfuzz/ossfuzz.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
# This script is called by the oss-fuzz main project when compiling the fuzz
|
||||
# targets. This script is regression tested by ci_oss.sh.
|
||||
|
||||
# Save off the current folder as the build root.
|
||||
export BUILD_ROOT=$PWD
|
||||
|
||||
echo "CC: ${CC:-}"
|
||||
echo "CXX: ${CXX:-}"
|
||||
echo "LIB_FUZZING_ENGINE: ${LIB_FUZZING_ENGINE:-}"
|
||||
echo "CFLAGS: ${CFLAGS:-}"
|
||||
echo "CXXFLAGS: ${CXXFLAGS:-}"
|
||||
echo "OUT: ${OUT:-}"
|
||||
|
||||
export MAKEFLAGS+="-j$(nproc)"
|
||||
|
||||
# Install dependencies
|
||||
apt-get -y install autoconf autogen automake libasound2-dev \
|
||||
libflac-dev libogg-dev libopus-dev libtool libvorbis-dev pkg-config python
|
||||
|
||||
# Compile the fuzzer.
|
||||
./autogen.sh
|
||||
./configure --enable-werror --enable-ossfuzzers
|
||||
make V=1
|
||||
|
||||
# Copy the fuzzer to the output directory.
|
||||
cp -v ossfuzz/sndfile_fuzzer $OUT/
|
134
ossfuzz/sndfile_fuzzer.cc
Normal file
134
ossfuzz/sndfile_fuzzer.cc
Normal file
@ -0,0 +1,134 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sndfile.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sf_count_t offset;
|
||||
sf_count_t length;
|
||||
const unsigned char *data;
|
||||
} VIO_DATA;
|
||||
|
||||
static sf_count_t vfget_filelen (void *user_data)
|
||||
{
|
||||
VIO_DATA *vf = (VIO_DATA *)user_data;
|
||||
return vf->length;
|
||||
}
|
||||
|
||||
static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data)
|
||||
{
|
||||
VIO_DATA *vf = (VIO_DATA *)user_data;
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
vf->offset = offset;
|
||||
break ;
|
||||
|
||||
case SEEK_CUR:
|
||||
vf->offset = vf->offset + offset;
|
||||
break ;
|
||||
|
||||
case SEEK_END:
|
||||
vf->offset = vf->length + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return vf->offset;
|
||||
}
|
||||
|
||||
static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
VIO_DATA *vf = (VIO_DATA *)user_data;
|
||||
|
||||
if (vf->offset + count > vf->length)
|
||||
{
|
||||
count = vf->length - vf->offset;
|
||||
}
|
||||
|
||||
memcpy(ptr, vf->data + vf->offset, count);
|
||||
vf->offset += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)count;
|
||||
(void)user_data;
|
||||
|
||||
// Cannot write to this virtual file.
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sf_count_t vftell (void *user_data)
|
||||
{ VIO_DATA *vf = (VIO_DATA *)user_data;
|
||||
|
||||
return vf->offset;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
VIO_DATA vio_data;
|
||||
SF_VIRTUAL_IO vio;
|
||||
SF_INFO sndfile_info;
|
||||
SNDFILE *sndfile = NULL;
|
||||
float* read_buffer = NULL;
|
||||
|
||||
// Initialize the virtual IO structure.
|
||||
vio.get_filelen = vfget_filelen;
|
||||
vio.seek = vfseek;
|
||||
vio.read = vfread;
|
||||
vio.write = vfwrite;
|
||||
vio.tell = vftell;
|
||||
|
||||
// Initialize the VIO user data.
|
||||
vio_data.data = data;
|
||||
vio_data.length = size;
|
||||
vio_data.offset = 0;
|
||||
|
||||
memset(&sndfile_info, 0, sizeof(SF_INFO));
|
||||
|
||||
// Try and open the virtual file.
|
||||
sndfile = sf_open_virtual(&vio, SFM_READ, &sndfile_info, &vio_data);
|
||||
|
||||
if (sndfile_info.channels == 0)
|
||||
{
|
||||
// No sound channels in file.
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
else if (sndfile_info.channels > 1024 * 1024)
|
||||
{
|
||||
// Too many channels to handle.
|
||||
goto EXIT_LABEL;
|
||||
}
|
||||
|
||||
// Just the right number of channels. Create some buffer space for reading.
|
||||
read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels);
|
||||
if (read_buffer == NULL)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
while (sf_readf_float(sndfile, read_buffer, 1))
|
||||
{
|
||||
// Do nothing with the data.
|
||||
}
|
||||
|
||||
EXIT_LABEL:
|
||||
|
||||
if (sndfile != NULL)
|
||||
{
|
||||
sf_close(sndfile);
|
||||
}
|
||||
|
||||
free(read_buffer);
|
||||
|
||||
return 0;
|
||||
}
|
86
ossfuzz/standaloneengine.cc
Normal file
86
ossfuzz/standaloneengine.cc
Normal file
@ -0,0 +1,86 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "testinput.h"
|
||||
|
||||
/**
|
||||
* Main procedure for standalone fuzzing engine.
|
||||
*
|
||||
* Reads filenames from the argument array. For each filename, read the file
|
||||
* into memory and then call the fuzzing interface with the data.
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ii;
|
||||
for(ii = 1; ii < argc; ii++)
|
||||
{
|
||||
FILE *infile;
|
||||
printf("[%s] ", argv[ii]);
|
||||
|
||||
/* Try and open the file. */
|
||||
infile = fopen(argv[ii], "rb");
|
||||
if(infile)
|
||||
{
|
||||
uint8_t *buffer = NULL;
|
||||
size_t buffer_len;
|
||||
|
||||
printf("Opened.. ");
|
||||
|
||||
/* Get the length of the file. */
|
||||
fseek(infile, 0L, SEEK_END);
|
||||
buffer_len = ftell(infile);
|
||||
|
||||
/* Reset the file indicator to the beginning of the file. */
|
||||
fseek(infile, 0L, SEEK_SET);
|
||||
|
||||
/* Allocate a buffer for the file contents. */
|
||||
buffer = (uint8_t *)calloc(buffer_len, sizeof(uint8_t));
|
||||
if(buffer)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
/* Read all the text from the file into the buffer. */
|
||||
result = fread(buffer, sizeof(uint8_t), buffer_len, infile);
|
||||
|
||||
if (result == buffer_len)
|
||||
{
|
||||
printf("Read %zu bytes, fuzzing.. ", buffer_len);
|
||||
/* Call the fuzzer with the data. */
|
||||
LLVMFuzzerTestOneInput(buffer, buffer_len);
|
||||
|
||||
printf("complete !!");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Failed to read %zu bytes (result %zu)\n",
|
||||
buffer_len,
|
||||
result);
|
||||
}
|
||||
|
||||
/* Free the buffer as it's no longer needed. */
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[%s] Failed to allocate %zu bytes \n",
|
||||
argv[ii],
|
||||
buffer_len);
|
||||
}
|
||||
|
||||
/* Close the file as it's no longer needed. */
|
||||
fclose(infile);
|
||||
infile = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Failed to open the file. Maybe wrong name or wrong permissions? */
|
||||
fprintf(stderr, "[%s] Open failed. \n", argv[ii]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
3
ossfuzz/testinput.h
Normal file
3
ossfuzz/testinput.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
Loading…
Reference in New Issue
Block a user