From 842e1cc17efca17f4a91b0bc678b39a1b1b43da4 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 27 May 2020 12:24:30 -0700 Subject: [PATCH] Make systemTime() abort on bad input. There's no CHECK in libutils, sadly. Bug: http://b/157167405 Test: treehugger Change-Id: I1532bf80ba7fdafad016610be3c782b547417126 --- libutils/Android.bp | 1 + libutils/Timers.cpp | 40 +++++++++++++++++++-------------- libutils/Timers_test.cpp | 29 ++++++++++++++++++++++++ libutils/include/utils/Timers.h | 18 +++++---------- 4 files changed, 59 insertions(+), 29 deletions(-) create mode 100644 libutils/Timers_test.cpp diff --git a/libutils/Android.bp b/libutils/Android.bp index 0f7044a7e..ea39d3449 100644 --- a/libutils/Android.bp +++ b/libutils/Android.bp @@ -246,6 +246,7 @@ cc_test { "String8_test.cpp", "String16_test.cpp", "StrongPointer_test.cpp", + "Timers_test.cpp", "Unicode_test.cpp", "Vector_test.cpp", ], diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp index 1172ae784..fd3f4a957 100644 --- a/libutils/Timers.cpp +++ b/libutils/Timers.cpp @@ -20,31 +20,37 @@ #include #include +#include #include -// host linux support requires Linux 2.6.39+ +#include + +static constexpr size_t clock_id_max = 5; + +static void checkClockId(int clock) { + if (clock < 0 || clock >= clock_id_max) abort(); +} + #if defined(__linux__) -nsecs_t systemTime(int clock) -{ - static const clockid_t clocks[] = { - CLOCK_REALTIME, - CLOCK_MONOTONIC, - CLOCK_PROCESS_CPUTIME_ID, - CLOCK_THREAD_CPUTIME_ID, - CLOCK_BOOTTIME - }; - struct timespec t; - t.tv_sec = t.tv_nsec = 0; +nsecs_t systemTime(int clock) { + checkClockId(clock); + static constexpr clockid_t clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC, + CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID, + CLOCK_BOOTTIME}; + static_assert(clock_id_max == arraysize(clocks)); + timespec t = {}; clock_gettime(clocks[clock], &t); return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec; } #else -nsecs_t systemTime(int /*clock*/) -{ +nsecs_t systemTime(int clock) { + // TODO: is this ever called with anything but REALTIME on mac/windows? + checkClockId(clock); + // Clock support varies widely across hosts. Mac OS doesn't support - // CLOCK_BOOTTIME, and Windows is windows. - struct timeval t; - t.tv_sec = t.tv_usec = 0; + // CLOCK_BOOTTIME (and doesn't even have clock_gettime until 10.12). + // Windows is windows. + timeval t = {}; gettimeofday(&t, nullptr); return nsecs_t(t.tv_sec)*1000000000LL + nsecs_t(t.tv_usec)*1000LL; } diff --git a/libutils/Timers_test.cpp b/libutils/Timers_test.cpp new file mode 100644 index 000000000..ec0051e67 --- /dev/null +++ b/libutils/Timers_test.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 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 + +TEST(Timers, systemTime_invalid) { + EXPECT_EXIT(systemTime(-1), testing::KilledBySignal(SIGABRT), ""); + systemTime(SYSTEM_TIME_REALTIME); + systemTime(SYSTEM_TIME_MONOTONIC); + systemTime(SYSTEM_TIME_PROCESS); + systemTime(SYSTEM_TIME_THREAD); + systemTime(SYSTEM_TIME_BOOTTIME); + EXPECT_EXIT(systemTime(SYSTEM_TIME_BOOTTIME + 1), testing::KilledBySignal(SIGABRT), ""); +} diff --git a/libutils/include/utils/Timers.h b/libutils/include/utils/Timers.h index 54ec47489..197fc26b8 100644 --- a/libutils/include/utils/Timers.h +++ b/libutils/include/utils/Timers.h @@ -14,11 +14,7 @@ * limitations under the License. */ -// -// Timer functions. -// -#ifndef _LIBS_UTILS_TIMERS_H -#define _LIBS_UTILS_TIMERS_H +#pragma once #include #include @@ -77,11 +73,11 @@ static CONSTEXPR inline nsecs_t milliseconds(nsecs_t v) { return ms2ns(v); } static CONSTEXPR inline nsecs_t microseconds(nsecs_t v) { return us2ns(v); } enum { - SYSTEM_TIME_REALTIME = 0, // system-wide realtime clock - SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point - SYSTEM_TIME_PROCESS = 2, // high-resolution per-process clock - SYSTEM_TIME_THREAD = 3, // high-resolution per-thread clock - SYSTEM_TIME_BOOTTIME = 4 // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time + SYSTEM_TIME_REALTIME = 0, // system-wide realtime clock + SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point + SYSTEM_TIME_PROCESS = 2, // high-resolution per-process clock + SYSTEM_TIME_THREAD = 3, // high-resolution per-thread clock + SYSTEM_TIME_BOOTTIME = 4, // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time }; // return the system-time according to the specified clock @@ -104,5 +100,3 @@ int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime); #ifdef __cplusplus } // extern "C" #endif - -#endif // _LIBS_UTILS_TIMERS_H