1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stddef.h>
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <audio_utils/format.h>
21 #include <system/audio.h>
22 
23 /** returns true if the format is a common source or destination format.
24     memcpy_by_audio_format() allows interchange between any PCM format and the
25     "common" PCM 16 bit and PCM float formats. */
is_common_src_format(audio_format_t format)26 static bool is_common_src_format(audio_format_t format) {
27     return format == AUDIO_FORMAT_PCM_16_BIT || format == AUDIO_FORMAT_PCM_FLOAT;
28 }
29 
is_common_dst_format(audio_format_t format)30 static bool is_common_dst_format(audio_format_t format) {
31     return format == AUDIO_FORMAT_PCM_8_BIT       // Allowed for HAL to AudioRecord conversion.
32             || format == AUDIO_FORMAT_PCM_16_BIT
33             || format == AUDIO_FORMAT_PCM_FLOAT;
34 }
35 
36 const static audio_format_t formats[] = {AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_FLOAT,
37 AUDIO_FORMAT_PCM_8_BIT, AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_32_BIT,
38 AUDIO_FORMAT_PCM_8_24_BIT};
39 
40 // Initialize PCM 16 bit ramp for basic data validation (generated from PCM 8 bit data).
41 template<size_t size>
fillBuffer(const uint8_t bytes[],int16_t (& buffer)[size],size_t input_size)42 static void fillBuffer(const uint8_t bytes[], int16_t(&buffer)[size], size_t input_size)
43 {
44     if (size < input_size) {
45        input_size  = size;
46     }
47 
48     // convert to PCM 16 bit
49     memcpy_by_audio_format(
50             buffer, AUDIO_FORMAT_PCM_16_BIT,
51             bytes, AUDIO_FORMAT_PCM_8_BIT, input_size);
52 
53     uint8_t check[size];
54     memcpy_by_audio_format(
55             check, AUDIO_FORMAT_PCM_8_BIT,
56             buffer, AUDIO_FORMAT_PCM_16_BIT, input_size);
57 }
58 
LLVMFuzzerTestOneInput(const uint8_t * bytes,size_t size)59 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *bytes, size_t size) {
60   if (size < 4 || size > UINT8_MAX) {
61      return 0;
62   }
63   size_t formats_len = sizeof(formats)/sizeof(audio_format_t);
64   int src = size % formats_len;
65   int dst = formats_len - 1 - src;
66 
67   // fetch parameters
68   const audio_format_t src_encoding = formats[src];
69   const audio_format_t dst_encoding = formats[dst];
70 
71   // either source or destination (or both) need to be a common format
72   if (!is_common_src_format(src_encoding) && !is_common_dst_format(dst_encoding)) {
73       return 0;
74   }
75 
76   constexpr size_t SAMPLES = UINT8_MAX;
77   constexpr audio_format_t orig_encoding = AUDIO_FORMAT_PCM_16_BIT;
78   int16_t data[SAMPLES];
79   fillBuffer(bytes, data, size);
80 
81   // data buffer for in-place conversion (uint32_t is maximum sample size of 4 bytes)
82   uint32_t databuff[size];
83   // check buffer is used to compare out-of-place vs in-place conversion.
84   uint32_t check[size];
85 
86   // Copy original data to data buffer at src_encoding.
87   memcpy_by_audio_format(
88           databuff, src_encoding,
89           data, orig_encoding, size);
90 
91   // Convert from src encoding to dst encoding.
92   memcpy_by_audio_format(
93           check, dst_encoding,
94           databuff, src_encoding, size);
95 
96   // Check in-place is same as out-of-place conversion.
97   memcpy_by_audio_format(
98           databuff, dst_encoding,
99           databuff, src_encoding, size);
100 
101   // Go back to the original data encoding for comparison.
102   memcpy_by_audio_format(
103           databuff, orig_encoding,
104           databuff, dst_encoding, size);
105 
106   return 0;
107 }
108