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