mirror of
https://gitee.com/openharmony/third_party_libsnd
synced 2024-11-26 19:40:24 +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
19
.github/workflows/action.yml
vendored
19
.github/workflows/action.yml
vendored
@ -10,6 +10,7 @@ jobs:
|
|||||||
name: [
|
name: [
|
||||||
ubuntu-gcc-autotools,
|
ubuntu-gcc-autotools,
|
||||||
ubuntu-clang-autotools,
|
ubuntu-clang-autotools,
|
||||||
|
ubuntu-gcc-ossfuzz,
|
||||||
macos-autotools,
|
macos-autotools,
|
||||||
ubuntu-gcc-cmake,
|
ubuntu-gcc-cmake,
|
||||||
ubuntu-gcc-cmake-shared,
|
ubuntu-gcc-cmake-shared,
|
||||||
@ -35,6 +36,12 @@ jobs:
|
|||||||
cxx: clang++
|
cxx: clang++
|
||||||
build-system: autotools
|
build-system: autotools
|
||||||
|
|
||||||
|
- name: ubuntu-gcc-ossfuzz
|
||||||
|
os: ubuntu-latest
|
||||||
|
cc: gcc
|
||||||
|
cxx: g++
|
||||||
|
build-system: ossfuzz
|
||||||
|
|
||||||
- name: macos-autotools
|
- name: macos-autotools
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
cc: clang
|
cc: clang
|
||||||
@ -166,7 +173,7 @@ jobs:
|
|||||||
-DVCPKG_TARGET_TRIPLET=x86-windows-static
|
-DVCPKG_TARGET_TRIPLET=x86-windows-static
|
||||||
-DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
-DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
@ -197,7 +204,7 @@ jobs:
|
|||||||
else
|
else
|
||||||
Scripts/asan-configure.sh --enable-werror && make clean all check && make distcheck
|
Scripts/asan-configure.sh --enable-werror && make clean all check && make distcheck
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Configure, build and test with CMake
|
- name: Configure, build and test with CMake
|
||||||
env:
|
env:
|
||||||
CC: ${{ matrix.cc }}
|
CC: ${{ matrix.cc }}
|
||||||
@ -209,3 +216,11 @@ jobs:
|
|||||||
cmake .. -G "${{matrix.cmake-generator}}" ${{matrix.cmake-options}}
|
cmake .. -G "${{matrix.cmake-generator}}" ${{matrix.cmake-options}}
|
||||||
cmake --build . --config Release
|
cmake --build . --config Release
|
||||||
ctest
|
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
|
pkgconfig_DATA = sndfile.pc
|
||||||
|
|
||||||
|
noinst_PROGRAMS =
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
|
||||||
test: check
|
test: check
|
||||||
@ -435,6 +437,39 @@ man/sndfile-deinterleave.1: man/sndfile-interleave.1
|
|||||||
-rm -f $@
|
-rm -f $@
|
||||||
cd $(top_srcdir)/man && $(LN_S) sndfile-interleave.1 sndfile-deinterleave.1
|
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/ #
|
# 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])])
|
[AS_HELP_STRING([--enable-test-coverage], [enable test coverage])])
|
||||||
AM_CONDITIONAL([ENABLE_TEST_COVERAGE], [test "x$enable_test_coverage" = "xyes"])
|
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 ====================================================================================
|
||||||
dnl Check types and their sizes.
|
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