1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sndfile.h>
6 #include <inttypes.h>
7 
8 typedef struct
9 {
10   sf_count_t offset;
11   sf_count_t length;
12   const unsigned char *data;
13 } VIO_DATA;
14 
vfget_filelen(void * user_data)15 static sf_count_t vfget_filelen (void *user_data)
16 {
17   VIO_DATA *vf = (VIO_DATA *)user_data;
18   return vf->length;
19 }
20 
vfseek(sf_count_t offset,int whence,void * user_data)21 static sf_count_t vfseek (sf_count_t offset, int whence, void *user_data)
22 {
23   VIO_DATA *vf = (VIO_DATA *)user_data;
24   sf_count_t new_offset;
25 
26   switch (whence)
27   {
28     case SEEK_SET:
29       new_offset = offset;
30       break ;
31 
32     case SEEK_CUR:
33       new_offset = vf->offset + offset;
34       break ;
35 
36     case SEEK_END:
37       new_offset = vf->length + offset;
38       break;
39 
40     default:
41       break;
42   }
43 
44   /* Ensure you can't seek outside the data */
45   if (new_offset > vf->length)
46   {
47     /* Trying to seek past the end of the data */
48     printf("vf overseek: new_offset(%" PRId64 ") > vf->length(%" PRId64 ");"
49            "  whence(%d), vf->offset(%" PRId64 "), offset(%" PRId64 ")\n",
50            new_offset, vf->length, whence, vf->offset, offset);
51     new_offset = vf->length;
52   }
53   else if (new_offset < 0)
54   {
55     /* Trying to seek before the start of the data */
56     printf("vf underseek: new_offset(%" PRId64 ") < 0;  whence(%d), vf->offset"
57            "(%" PRId64 "), vf->length(%" PRId64 "), offset(%" PRId64 ")\n",
58            new_offset, whence, vf->offset, vf->length, offset);
59     new_offset = 0;
60   }
61   vf->offset = new_offset;
62 
63   return vf->offset;
64 }
65 
vfread(void * ptr,sf_count_t count,void * user_data)66 static sf_count_t vfread (void *ptr, sf_count_t count, void *user_data)
67 {
68   VIO_DATA *vf = (VIO_DATA *)user_data;
69 
70   if (vf->offset + count > vf->length)
71   {
72     count = vf->length - vf->offset;
73   }
74 
75   memcpy(ptr, vf->data + vf->offset, count);
76   vf->offset += count;
77 
78   return count;
79 }
80 
vfwrite(const void * ptr,sf_count_t count,void * user_data)81 static sf_count_t vfwrite (const void *ptr, sf_count_t count, void *user_data)
82 {
83   (void)ptr;
84   (void)count;
85   (void)user_data;
86 
87   // Cannot write to this virtual file.
88   return 0;
89 }
90 
vftell(void * user_data)91 static sf_count_t vftell (void *user_data)
92 { VIO_DATA *vf = (VIO_DATA *)user_data;
93 
94   return vf->offset;
95 }
96 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)97 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
98 {
99   VIO_DATA vio_data;
100   SF_VIRTUAL_IO vio;
101   SF_INFO sndfile_info;
102   SNDFILE *sndfile = NULL;
103   float* read_buffer = NULL;
104 
105   // Initialize the virtual IO structure.
106   vio.get_filelen = vfget_filelen;
107   vio.seek = vfseek;
108   vio.read = vfread;
109   vio.write = vfwrite;
110   vio.tell = vftell;
111 
112   // Initialize the VIO user data.
113   vio_data.data = data;
114   vio_data.length = size;
115   vio_data.offset = 0;
116 
117   memset(&sndfile_info, 0, sizeof(SF_INFO));
118 
119   // Try and open the virtual file.
120   sndfile = sf_open_virtual(&vio, SFM_READ, &sndfile_info, &vio_data);
121 
122   if (sndfile_info.channels == 0)
123   {
124     // No sound channels in file.
125     goto EXIT_LABEL;
126   }
127   else if (sndfile_info.channels > 1024 * 1024)
128   {
129     // Too many channels to handle.
130     goto EXIT_LABEL;
131   }
132 
133   // Just the right number of channels. Create some buffer space for reading.
134   read_buffer = (float*)malloc(sizeof(float) * sndfile_info.channels);
135   if (read_buffer == NULL)
136   {
137     abort();
138   }
139 
140   while (sf_readf_float(sndfile, read_buffer, 1))
141   {
142     // Do nothing with the data.
143   }
144 
145 EXIT_LABEL:
146 
147   if (sndfile != NULL)
148   {
149     sf_close(sndfile);
150   }
151 
152   free(read_buffer);
153 
154   return 0;
155 }
156