/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include /** returns true if the format is a common source or destination format. memcpy_by_audio_format() allows interchange between any PCM format and the "common" PCM 16 bit and PCM float formats. */ static bool is_common_src_format(audio_format_t format) { return format == AUDIO_FORMAT_PCM_16_BIT || format == AUDIO_FORMAT_PCM_FLOAT; } static bool is_common_dst_format(audio_format_t format) { return format == AUDIO_FORMAT_PCM_8_BIT // Allowed for HAL to AudioRecord conversion. || format == AUDIO_FORMAT_PCM_16_BIT || format == AUDIO_FORMAT_PCM_FLOAT; } const static audio_format_t formats[] = {AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_FLOAT, AUDIO_FORMAT_PCM_8_BIT, AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_32_BIT, AUDIO_FORMAT_PCM_8_24_BIT}; // Initialize PCM 16 bit ramp for basic data validation (generated from PCM 8 bit data). template static void fillBuffer(const uint8_t bytes[], int16_t(&buffer)[size], size_t input_size) { if (size < input_size) { input_size = size; } // convert to PCM 16 bit memcpy_by_audio_format( buffer, AUDIO_FORMAT_PCM_16_BIT, bytes, AUDIO_FORMAT_PCM_8_BIT, input_size); uint8_t check[size]; memcpy_by_audio_format( check, AUDIO_FORMAT_PCM_8_BIT, buffer, AUDIO_FORMAT_PCM_16_BIT, input_size); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *bytes, size_t size) { if (size < 4 || size > UINT8_MAX) { return 0; } size_t formats_len = sizeof(formats)/sizeof(audio_format_t); int src = size % formats_len; int dst = formats_len - 1 - src; // fetch parameters const audio_format_t src_encoding = formats[src]; const audio_format_t dst_encoding = formats[dst]; // either source or destination (or both) need to be a common format if (!is_common_src_format(src_encoding) && !is_common_dst_format(dst_encoding)) { return 0; } constexpr size_t SAMPLES = UINT8_MAX; constexpr audio_format_t orig_encoding = AUDIO_FORMAT_PCM_16_BIT; int16_t data[SAMPLES]; fillBuffer(bytes, data, size); // data buffer for in-place conversion (uint32_t is maximum sample size of 4 bytes) uint32_t databuff[size]; // check buffer is used to compare out-of-place vs in-place conversion. uint32_t check[size]; // Copy original data to data buffer at src_encoding. memcpy_by_audio_format( databuff, src_encoding, data, orig_encoding, size); // Convert from src encoding to dst encoding. memcpy_by_audio_format( check, dst_encoding, databuff, src_encoding, size); // Check in-place is same as out-of-place conversion. memcpy_by_audio_format( databuff, dst_encoding, databuff, src_encoding, size); // Go back to the original data encoding for comparison. memcpy_by_audio_format( databuff, orig_encoding, databuff, dst_encoding, size); return 0; }