/* * Copyright 2020 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 "osi/include/alarm.h" #include "osi/include/semaphore.h" #include "common/message_loop_thread.h" using base::Closure; using base::TimeDelta; using bluetooth::common::MessageLoopThread; #define MAX_CONCURRENT_ALARMS 25 #define MAX_BUFFER_LEN 4096 #define MAX_ALARM_DURATION 25 static semaphore_t* semaphore; static int cb_counter; static base::MessageLoop* message_loop_; base::MessageLoop* get_main_message_loop() { return message_loop_; } static void cb(void* data) { ++cb_counter; semaphore_post(semaphore); } void setup() { cb_counter = 0; semaphore = semaphore_new(0); } void teardown() { semaphore_free(semaphore); } alarm_t* fuzz_init_alarm(FuzzedDataProvider* dataProvider) { size_t name_len = dataProvider->ConsumeIntegralInRange(0, MAX_BUFFER_LEN); std::vector alarm_name_vect = dataProvider->ConsumeBytesWithTerminator(name_len, '\0'); char* alarm_name = alarm_name_vect.data(); // Determine if our alarm will be periodic if (dataProvider->ConsumeBool()) { return alarm_new_periodic(alarm_name); } else { return alarm_new(alarm_name); } } bool fuzz_set_alarm(alarm_t* alarm, uint64_t interval, alarm_callback_t cb, FuzzedDataProvider* dataProvider) { // Generate a random buffer (or null) void* data_buffer = nullptr; size_t buff_len = dataProvider->ConsumeIntegralInRange(1, MAX_BUFFER_LEN); if (buff_len == 0) { return false; } // allocate our space std::vector data_vector = dataProvider->ConsumeBytes(buff_len); data_buffer = data_vector.data(); // Make sure alarm is non-null if (alarm) { // Should this alarm be regular or on mloop? if (dataProvider->ConsumeBool()) { alarm_set_on_mloop(alarm, interval, cb, data_buffer); } else { alarm_set(alarm, interval, cb, data_buffer); } } return true; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { // Init our wrapper FuzzedDataProvider dataProvider(Data, Size); // Perform setup setup(); alarm_t* alarm = nullptr; // Should our alarm be valid or null? if (dataProvider.ConsumeBool()) { // Init our alarm alarm = fuzz_init_alarm(&dataProvider); } // Set up the alarm & cancel // Alarm must be non-null, or set() will trigger assert if (alarm) { if (!fuzz_set_alarm(alarm, MAX_ALARM_DURATION, cb, &dataProvider)) { return 0; } alarm_cancel(alarm); } // Check if scheduled alarm_is_scheduled(alarm); if (alarm) { // Set up another set of alarms & let these ones run int num_alarms = dataProvider.ConsumeIntegralInRange(0, MAX_CONCURRENT_ALARMS); for (int i = 0; i < num_alarms; i++) { uint64_t interval = dataProvider.ConsumeIntegralInRange(0, MAX_ALARM_DURATION); if (fuzz_set_alarm(alarm, interval, cb, &dataProvider)) { return 0; } alarm_get_remaining_ms(alarm); } // Wait for them to complete for (int i = 1; i <= num_alarms; i++) { semaphore_wait(semaphore); } } // Free the alarm object alarm_free(alarm); // dump debug data to /dev/null int debug_fd = open("/dev/null", O_RDWR); alarm_debug_dump(debug_fd); // Cleanup alarm_cleanup(); // Perform teardown teardown(); return 0; }