/* * Copyright (C) 2014 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 "safe_math.h" #include <limits> #include "gtest/gtest.h" namespace art { namespace interpreter { TEST(SafeMath, Add) { // Adding 1 overflows 0x7ff... to 0x800... aka max and min. EXPECT_EQ(SafeAdd(std::numeric_limits<int32_t>::max(), 1), std::numeric_limits<int32_t>::min()); EXPECT_EQ(SafeAdd(std::numeric_limits<int64_t>::max(), 1), std::numeric_limits<int64_t>::min()); // Vanilla arithmetic should work too. EXPECT_EQ(SafeAdd(std::numeric_limits<int32_t>::max() - 1, 1), std::numeric_limits<int32_t>::max()); EXPECT_EQ(SafeAdd(std::numeric_limits<int64_t>::max() - 1, 1), std::numeric_limits<int64_t>::max()); EXPECT_EQ(SafeAdd(std::numeric_limits<int32_t>::min() + 1, -1), std::numeric_limits<int32_t>::min()); EXPECT_EQ(SafeAdd(std::numeric_limits<int64_t>::min() + 1, -1), std::numeric_limits<int64_t>::min()); EXPECT_EQ(SafeAdd(int32_t(-1), -1), -2); EXPECT_EQ(SafeAdd(int64_t(-1), -1), -2); EXPECT_EQ(SafeAdd(int32_t(1), 1), 2); EXPECT_EQ(SafeAdd(int64_t(1), 1), 2); EXPECT_EQ(SafeAdd(int32_t(-1), 1), 0); EXPECT_EQ(SafeAdd(int64_t(-1), 1), 0); EXPECT_EQ(SafeAdd(int32_t(1), -1), 0); EXPECT_EQ(SafeAdd(int64_t(1), -1), 0); // Test sign extension of smaller operand sizes. EXPECT_EQ(SafeAdd(int32_t(1), int8_t(-1)), 0); EXPECT_EQ(SafeAdd(int64_t(1), int8_t(-1)), 0); } TEST(SafeMath, Sub) { // Subtracting 1 underflows 0x800... to 0x7ff... aka min and max. EXPECT_EQ(SafeSub(std::numeric_limits<int32_t>::min(), 1), std::numeric_limits<int32_t>::max()); EXPECT_EQ(SafeSub(std::numeric_limits<int64_t>::min(), 1), std::numeric_limits<int64_t>::max()); // Vanilla arithmetic should work too. EXPECT_EQ(SafeSub(std::numeric_limits<int32_t>::max() - 1, -1), std::numeric_limits<int32_t>::max()); EXPECT_EQ(SafeSub(std::numeric_limits<int64_t>::max() - 1, -1), std::numeric_limits<int64_t>::max()); EXPECT_EQ(SafeSub(std::numeric_limits<int32_t>::min() + 1, 1), std::numeric_limits<int32_t>::min()); EXPECT_EQ(SafeSub(std::numeric_limits<int64_t>::min() + 1, 1), std::numeric_limits<int64_t>::min()); EXPECT_EQ(SafeSub(int32_t(-1), -1), 0); EXPECT_EQ(SafeSub(int64_t(-1), -1), 0); EXPECT_EQ(SafeSub(int32_t(1), 1), 0); EXPECT_EQ(SafeSub(int64_t(1), 1), 0); EXPECT_EQ(SafeSub(int32_t(-1), 1), -2); EXPECT_EQ(SafeSub(int64_t(-1), 1), -2); EXPECT_EQ(SafeSub(int32_t(1), -1), 2); EXPECT_EQ(SafeSub(int64_t(1), -1), 2); // Test sign extension of smaller operand sizes. EXPECT_EQ(SafeAdd(int32_t(1), int8_t(-1)), 0); EXPECT_EQ(SafeAdd(int64_t(1), int8_t(-1)), 0); } TEST(SafeMath, Mul) { // Multiplying by 2 overflows 0x7ff...f to 0xfff...e aka max and -2. EXPECT_EQ(SafeMul(std::numeric_limits<int32_t>::max(), 2), -2); EXPECT_EQ(SafeMul(std::numeric_limits<int64_t>::max(), 2), -2); // Vanilla arithmetic should work too. EXPECT_EQ(SafeMul(std::numeric_limits<int32_t>::max() / 2, 2), std::numeric_limits<int32_t>::max() - 1); // -1 as LSB is lost by division. EXPECT_EQ(SafeMul(std::numeric_limits<int64_t>::max() / 2, 2), std::numeric_limits<int64_t>::max() - 1); // -1 as LSB is lost by division. EXPECT_EQ(SafeMul(std::numeric_limits<int32_t>::min() / 2, 2), std::numeric_limits<int32_t>::min()); EXPECT_EQ(SafeMul(std::numeric_limits<int64_t>::min() / 2, 2), std::numeric_limits<int64_t>::min()); EXPECT_EQ(SafeMul(int32_t(-1), -1), 1); EXPECT_EQ(SafeMul(int64_t(-1), -1), 1); EXPECT_EQ(SafeMul(int32_t(1), 1), 1); EXPECT_EQ(SafeMul(int64_t(1), 1), 1); EXPECT_EQ(SafeMul(int32_t(-1), 1), -1); EXPECT_EQ(SafeMul(int64_t(-1), 1), -1); EXPECT_EQ(SafeMul(int32_t(1), -1), -1); EXPECT_EQ(SafeMul(int64_t(1), -1), -1); // Test sign extension of smaller operand sizes. EXPECT_EQ(SafeMul(int32_t(1), int8_t(-1)), -1); EXPECT_EQ(SafeMul(int64_t(1), int8_t(-1)), -1); } } // namespace interpreter } // namespace art