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. */ 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 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> 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 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