Merge "Make powerof2 macro ubsan safe"

am: 1b6517b601

Change-Id: Iec86f326ab1dd2b79cb41dd750975da7ee10474d
This commit is contained in:
Nick Kralevich 2019-03-25 20:52:59 -07:00 committed by android-build-merger
commit cdfe9d7d96
3 changed files with 60 additions and 2 deletions

View file

@ -51,8 +51,17 @@
#endif
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
/** Returns true if the argument is a power of two. */
#define powerof2(x) ((((x)-1)&(x))==0)
/*
* Returns true if the binary representation of the argument is all zeros
* or has exactly one bit set. Contrary to the macro name, this macro
* DOES NOT determine if the provided value is a power of 2. In particular,
* this function falsely returns true for powerof2(0) and some negative
* numbers.
*/
#define powerof2(x) \
({ __typeof__(x) _x = (x); \
__typeof__(x) _x2; \
__builtin_add_overflow(_x, -1, &_x2) ? 1 : ((_x2&_x) == 0 ); })
/** Returns the lesser of its two arguments. */
#define MIN(a,b) (((a)<(b))?(a):(b))

View file

@ -153,6 +153,7 @@ cc_test_library {
"sys_epoll_test.cpp",
"sys_mman_test.cpp",
"sys_msg_test.cpp",
"sys_param_test.cpp",
"sys_personality_test.cpp",
"sys_prctl_test.cpp",
"sys_procfs_test.cpp",

48
tests/sys_param_test.cpp Normal file
View file

@ -0,0 +1,48 @@
/*
* 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 <gtest/gtest.h>
#include <sys/param.h>
TEST(sys_param_test, powerof2_positives) {
ASSERT_TRUE(powerof2(1));
ASSERT_TRUE(powerof2(2));
ASSERT_TRUE(powerof2(4));
ASSERT_TRUE(powerof2(8));
ASSERT_FALSE(powerof2(3));
ASSERT_FALSE(powerof2(5));
ASSERT_FALSE(powerof2(7));
ASSERT_FALSE(powerof2(9));
ASSERT_FALSE(powerof2(10));
}
TEST(sys_param_test, powerof2_zero) {
// 0 isn't a power of 2, but for compatibility, we assume it is.
ASSERT_TRUE(powerof2(0));
uint32_t zero = 0;
ASSERT_TRUE(powerof2(zero));
}
TEST(sys_param_test, powerof2_negatives) {
// negative numbers can never be a power of 2, but for compatibility,
// we assume they can be.
int32_t min32 = INT32_MIN;
int64_t min64 = INT64_MIN;
ASSERT_TRUE(powerof2(min32));
ASSERT_FALSE(powerof2(min32 + 1));
ASSERT_TRUE(powerof2(min64));
ASSERT_FALSE(powerof2(min64 + 1));
}