mirror of
https://gitee.com/openharmony/third_party_libsnd
synced 2024-11-26 19:40:24 +00:00
Add new fuzzer for OSS-Fuzz (#769)
Adds a fuzzer targeting sf_read_double, sf_read_int and sf_read_short. Co-authored-by: evpobr <evpobr@gmail.com>
This commit is contained in:
parent
dc1c8c2492
commit
110e26d9c2
@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
* ID3v1 reading
|
* ID3v1 reading
|
||||||
* ID3v2 reading
|
* ID3v2 reading
|
||||||
* Seeking
|
* Seeking
|
||||||
|
* New fuzzer for OSS-Fuzz, thanks @DavidKorczynski.
|
||||||
* This `CHANGELOG.md`. All notable changes to this project will be documented in
|
* This `CHANGELOG.md`. All notable changes to this project will be documented in
|
||||||
this file. The old `NEWS` file has been renamed to `NEWS.OLD` and is no longer
|
this file. The old `NEWS` file has been renamed to `NEWS.OLD` and is no longer
|
||||||
updated.
|
updated.
|
||||||
|
@ -462,7 +462,8 @@ endif
|
|||||||
|
|
||||||
if USE_OSSFUZZERS
|
if USE_OSSFUZZERS
|
||||||
noinst_PROGRAMS += \
|
noinst_PROGRAMS += \
|
||||||
ossfuzz/sndfile_fuzzer
|
ossfuzz/sndfile_fuzzer \
|
||||||
|
ossfuzz/sndfile_alt_fuzzer
|
||||||
|
|
||||||
noinst_LTLIBRARIES += \
|
noinst_LTLIBRARIES += \
|
||||||
ossfuzz/libstandaloneengine.la
|
ossfuzz/libstandaloneengine.la
|
||||||
@ -473,6 +474,11 @@ ossfuzz_sndfile_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG)
|
|||||||
ossfuzz_sndfile_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static
|
ossfuzz_sndfile_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static
|
||||||
ossfuzz_sndfile_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD)
|
ossfuzz_sndfile_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD)
|
||||||
|
|
||||||
|
ossfuzz_sndfile_alt_fuzzer_SOURCES = ossfuzz/sndfile_alt_fuzzer.cc
|
||||||
|
ossfuzz_sndfile_alt_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG)
|
||||||
|
ossfuzz_sndfile_alt_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static
|
||||||
|
ossfuzz_sndfile_alt_fuzzer_LDADD = src/libsndfile.la $(FUZZ_LDADD)
|
||||||
|
|
||||||
ossfuzz_libstandaloneengine_la_SOURCES = ossfuzz/standaloneengine.cc ossfuzz/testinput.h
|
ossfuzz_libstandaloneengine_la_SOURCES = ossfuzz/standaloneengine.cc ossfuzz/testinput.h
|
||||||
ossfuzz_libstandaloneengine_la_CXXFLAGS = $(AM_CXXFLAGS)
|
ossfuzz_libstandaloneengine_la_CXXFLAGS = $(AM_CXXFLAGS)
|
||||||
|
|
||||||
|
@ -29,3 +29,4 @@ make V=1
|
|||||||
|
|
||||||
# Copy the fuzzer to the output directory.
|
# Copy the fuzzer to the output directory.
|
||||||
cp -v ossfuzz/sndfile_fuzzer $OUT/
|
cp -v ossfuzz/sndfile_fuzzer $OUT/
|
||||||
|
cp -v ossfuzz/sndfile_alt_fuzzer $OUT/
|
||||||
|
79
ossfuzz/sndfile_alt_fuzzer.cc
Normal file
79
ossfuzz/sndfile_alt_fuzzer.cc
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sndfile.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "sndfile_fuzz_header.h"
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||||
|
{ // One byte is needed for deciding which function to target.
|
||||||
|
if (size == 0)
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
const uint8_t decider = *data ;
|
||||||
|
data += 1 ;
|
||||||
|
size -= 1 ;
|
||||||
|
|
||||||
|
SF_INFO sndfile_info ;
|
||||||
|
VIO_DATA vio_data ;
|
||||||
|
SF_VIRTUAL_IO vio ;
|
||||||
|
SNDFILE *sndfile = NULL ;
|
||||||
|
int err = sf_init_file(data, size, &sndfile, &vio_data, &vio, &sndfile_info) ;
|
||||||
|
if (err)
|
||||||
|
goto EXIT_LABEL ;
|
||||||
|
|
||||||
|
// Just the right number of channels. Create some buffer space for reading.
|
||||||
|
switch (decider % 3)
|
||||||
|
{ case 0 :
|
||||||
|
{
|
||||||
|
short* read_buffer = NULL ;
|
||||||
|
read_buffer = (short*)malloc(sizeof(short) * size);
|
||||||
|
if (read_buffer == NULL)
|
||||||
|
abort() ;
|
||||||
|
|
||||||
|
while (sf_read_short(sndfile, read_buffer, size))
|
||||||
|
{
|
||||||
|
// Do nothing with the data.
|
||||||
|
}
|
||||||
|
free(read_buffer) ;
|
||||||
|
}
|
||||||
|
break ;
|
||||||
|
case 1 :
|
||||||
|
{
|
||||||
|
int* read_buffer = NULL ;
|
||||||
|
read_buffer = (int*)malloc(sizeof(int) * size) ;
|
||||||
|
if (read_buffer == NULL)
|
||||||
|
abort() ;
|
||||||
|
|
||||||
|
while (sf_read_int(sndfile, read_buffer, size))
|
||||||
|
{
|
||||||
|
// Do nothing with the data.
|
||||||
|
}
|
||||||
|
free(read_buffer) ;
|
||||||
|
}
|
||||||
|
break ;
|
||||||
|
case 2 :
|
||||||
|
{
|
||||||
|
double* read_buffer = NULL ;
|
||||||
|
read_buffer = (double*)malloc(sizeof(double) * size) ;
|
||||||
|
if (read_buffer == NULL)
|
||||||
|
abort() ;
|
||||||
|
|
||||||
|
while (sf_read_double(sndfile, read_buffer, size))
|
||||||
|
{
|
||||||
|
// Do nothing with the data.
|
||||||
|
}
|
||||||
|
free(read_buffer) ;
|
||||||
|
}
|
||||||
|
break ;
|
||||||
|
default :
|
||||||
|
break ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
EXIT_LABEL:
|
||||||
|
if (sndfile != NULL)
|
||||||
|
sf_close(sndfile);
|
||||||
|
|
||||||
|
return 0 ;
|
||||||
|
}
|
119
ossfuzz/sndfile_fuzz_header.h
Normal file
119
ossfuzz/sndfile_fuzz_header.h
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#ifndef SNDFILE_FUZZ_HEADER_H
|
||||||
|
#define SNDFILE_FUZZ_HEADER_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 ;
|
||||||
|
sf_count_t new_offset ;
|
||||||
|
|
||||||
|
switch (whence)
|
||||||
|
{ case SEEK_SET :
|
||||||
|
new_offset = offset ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case SEEK_CUR :
|
||||||
|
new_offset = vf->offset + offset ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
case SEEK_END :
|
||||||
|
new_offset = vf->length + offset ;
|
||||||
|
break ;
|
||||||
|
|
||||||
|
default :
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure you can't seek outside the data */
|
||||||
|
if (new_offset > vf->length)
|
||||||
|
{ /* Trying to seek past the end of the data */
|
||||||
|
printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");"
|
||||||
|
" whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n",
|
||||||
|
new_offset, vf->length, whence, vf->offset, offset) ;
|
||||||
|
new_offset = vf->length ;
|
||||||
|
}
|
||||||
|
else if (new_offset < 0)
|
||||||
|
{ /* Trying to seek before the start of the data */
|
||||||
|
printf("vf underseek: new_offset(%" PRId64 ") < 0; whence(%d), vf->offset"
|
||||||
|
"(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n",
|
||||||
|
new_offset, whence, vf->offset, vf->length, offset) ;
|
||||||
|
new_offset = 0 ;
|
||||||
|
}
|
||||||
|
vf->offset = new_offset ;
|
||||||
|
|
||||||
|
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 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sf_init_file(const uint8_t *data,
|
||||||
|
size_t size,
|
||||||
|
SNDFILE **sndfile,
|
||||||
|
VIO_DATA *vio_data,
|
||||||
|
SF_VIRTUAL_IO *vio, SF_INFO *sndfile_info)
|
||||||
|
{ 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)
|
||||||
|
return -1 ;
|
||||||
|
|
||||||
|
if (sndfile_info->channels > 1024 * 1024)
|
||||||
|
return -1 ;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -5,151 +5,35 @@
|
|||||||
#include <sndfile.h>
|
#include <sndfile.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
typedef struct
|
#include "sndfile_fuzz_header.h"
|
||||||
{
|
|
||||||
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;
|
|
||||||
sf_count_t new_offset;
|
|
||||||
|
|
||||||
switch (whence)
|
|
||||||
{
|
|
||||||
case SEEK_SET:
|
|
||||||
new_offset = offset;
|
|
||||||
break ;
|
|
||||||
|
|
||||||
case SEEK_CUR:
|
|
||||||
new_offset = vf->offset + offset;
|
|
||||||
break ;
|
|
||||||
|
|
||||||
case SEEK_END:
|
|
||||||
new_offset = vf->length + offset;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure you can't seek outside the data */
|
|
||||||
if (new_offset > vf->length)
|
|
||||||
{
|
|
||||||
/* Trying to seek past the end of the data */
|
|
||||||
printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");"
|
|
||||||
" whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n",
|
|
||||||
new_offset, vf->length, whence, vf->offset, offset);
|
|
||||||
new_offset = vf->length;
|
|
||||||
}
|
|
||||||
else if (new_offset < 0)
|
|
||||||
{
|
|
||||||
/* Trying to seek before the start of the data */
|
|
||||||
printf("vf underseek: new_offset(%" PRId64 ") < 0; whence(%d), vf->offset"
|
|
||||||
"(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n",
|
|
||||||
new_offset, whence, vf->offset, vf->length, offset);
|
|
||||||
new_offset = 0;
|
|
||||||
}
|
|
||||||
vf->offset = new_offset;
|
|
||||||
|
|
||||||
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)
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||||
{
|
{ VIO_DATA vio_data ;
|
||||||
VIO_DATA vio_data;
|
SF_VIRTUAL_IO vio ;
|
||||||
SF_VIRTUAL_IO vio;
|
SF_INFO sndfile_info ;
|
||||||
SF_INFO sndfile_info;
|
SNDFILE *sndfile = NULL ;
|
||||||
SNDFILE *sndfile = NULL;
|
float* read_buffer = NULL ;
|
||||||
float* read_buffer = NULL;
|
|
||||||
|
|
||||||
// Initialize the virtual IO structure.
|
int err = sf_init_file(data, size, &sndfile, &vio_data, &vio, &sndfile_info) ;
|
||||||
vio.get_filelen = vfget_filelen;
|
if (err)
|
||||||
vio.seek = vfseek;
|
goto EXIT_LABEL ;
|
||||||
vio.read = vfread;
|
|
||||||
vio.write = vfwrite;
|
|
||||||
vio.tell = vftell;
|
|
||||||
|
|
||||||
// Initialize the VIO user data.
|
// Just the right number of channels. Create some buffer space for reading.
|
||||||
vio_data.data = data;
|
read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels);
|
||||||
vio_data.length = size;
|
if (read_buffer == NULL)
|
||||||
vio_data.offset = 0;
|
abort() ;
|
||||||
|
|
||||||
memset(&sndfile_info, 0, sizeof(SF_INFO));
|
while (sf_readf_float(sndfile, read_buffer, 1))
|
||||||
|
{
|
||||||
// Try and open the virtual file.
|
// Do nothing with the data.
|
||||||
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:
|
EXIT_LABEL:
|
||||||
|
|
||||||
if (sndfile != NULL)
|
if (sndfile != NULL)
|
||||||
{
|
sf_close(sndfile) ;
|
||||||
sf_close(sndfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(read_buffer);
|
free(read_buffer) ;
|
||||||
|
|
||||||
return 0;
|
return 0 ;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user