| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <limits> |
| |
| #include "mojo/public/cpp/bindings/lib/serialization_util.h" |
| #include "mojo/public/cpp/bindings/lib/validation_context.h" |
| #include "mojo/public/cpp/system/core.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace mojo { |
| namespace test { |
| namespace { |
| |
| using Handle_Data = mojo::internal::Handle_Data; |
| using AssociatedEndpointHandle_Data = |
| mojo::internal::AssociatedEndpointHandle_Data; |
| |
| const void* ToPtr(uintptr_t ptr) { |
| return reinterpret_cast<const void*>(ptr); |
| } |
| |
| #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) |
| TEST(ValidationContextTest, ConstructorRangeOverflow) { |
| { |
| // Test memory range overflow. |
| internal::ValidationContext context( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 3000), 5000, 0, 0); |
| |
| EXPECT_FALSE(context.IsValidRange( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 3000), 1)); |
| EXPECT_FALSE(context.ClaimMemory( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 3000), 1)); |
| } |
| |
| if (sizeof(size_t) <= sizeof(uint32_t)) |
| return; |
| |
| { |
| // Test handle index range overflow. |
| size_t num_handles = |
| static_cast<size_t>(std::numeric_limits<uint32_t>::max()) + 5; |
| internal::ValidationContext context(ToPtr(0), 0, num_handles, 0); |
| |
| EXPECT_FALSE(context.ClaimHandle(Handle_Data(0))); |
| EXPECT_FALSE(context.ClaimHandle( |
| Handle_Data(std::numeric_limits<uint32_t>::max() - 1))); |
| |
| EXPECT_TRUE(context.ClaimHandle( |
| Handle_Data(internal::kEncodedInvalidHandleValue))); |
| } |
| |
| { |
| size_t num_associated_endpoint_handles = |
| static_cast<size_t>(std::numeric_limits<uint32_t>::max()) + 5; |
| internal::ValidationContext context(ToPtr(0), 0, 0, |
| num_associated_endpoint_handles); |
| |
| EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(0))); |
| EXPECT_FALSE( |
| context.ClaimAssociatedEndpointHandle(AssociatedEndpointHandle_Data( |
| std::numeric_limits<uint32_t>::max() - 1))); |
| |
| EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); |
| } |
| } |
| #endif |
| |
| TEST(ValidationContextTest, IsValidRange) { |
| { |
| internal::ValidationContext context(ToPtr(1234), 100, 0, 0); |
| |
| // Basics. |
| EXPECT_FALSE(context.IsValidRange(ToPtr(100), 5)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1230), 50)); |
| EXPECT_TRUE(context.IsValidRange(ToPtr(1234), 5)); |
| EXPECT_TRUE(context.IsValidRange(ToPtr(1240), 50)); |
| EXPECT_TRUE(context.IsValidRange(ToPtr(1234), 100)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 101)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1240), 100)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1333), 5)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(2234), 5)); |
| |
| // ClaimMemory() updates the valid range. |
| EXPECT_TRUE(context.ClaimMemory(ToPtr(1254), 10)); |
| |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 1)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1254), 10)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1263), 1)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1263), 10)); |
| EXPECT_TRUE(context.IsValidRange(ToPtr(1264), 10)); |
| EXPECT_TRUE(context.IsValidRange(ToPtr(1264), 70)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1264), 71)); |
| } |
| |
| { |
| internal::ValidationContext context(ToPtr(1234), 100, 0, 0); |
| // Should return false for empty ranges. |
| EXPECT_FALSE(context.IsValidRange(ToPtr(0), 0)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1200), 0)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 0)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1240), 0)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(2234), 0)); |
| } |
| |
| { |
| // The valid memory range is empty. |
| internal::ValidationContext context(ToPtr(1234), 0, 0, 0); |
| |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 1)); |
| EXPECT_FALSE(context.IsValidRange(ToPtr(1234), 0)); |
| } |
| |
| { |
| internal::ValidationContext context( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 2000), 1000, 0, 0); |
| |
| // Test overflow. |
| EXPECT_FALSE(context.IsValidRange( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 1500), 4000)); |
| EXPECT_FALSE(context.IsValidRange( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 1500), |
| std::numeric_limits<uint32_t>::max())); |
| |
| // This should be fine. |
| EXPECT_TRUE(context.IsValidRange( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 1500), 200)); |
| } |
| } |
| |
| TEST(ValidationContextTest, ClaimHandle) { |
| { |
| internal::ValidationContext context(ToPtr(0), 0, 10, 0); |
| |
| // Basics. |
| EXPECT_TRUE(context.ClaimHandle(Handle_Data(0))); |
| EXPECT_FALSE(context.ClaimHandle(Handle_Data(0))); |
| |
| EXPECT_TRUE(context.ClaimHandle(Handle_Data(9))); |
| EXPECT_FALSE(context.ClaimHandle(Handle_Data(10))); |
| |
| // Should fail because it is smaller than the max index that has been |
| // claimed. |
| EXPECT_FALSE(context.ClaimHandle(Handle_Data(8))); |
| |
| // Should return true for invalid handle. |
| EXPECT_TRUE(context.ClaimHandle( |
| Handle_Data(internal::kEncodedInvalidHandleValue))); |
| EXPECT_TRUE(context.ClaimHandle( |
| Handle_Data(internal::kEncodedInvalidHandleValue))); |
| } |
| |
| { |
| // No handle to claim. |
| internal::ValidationContext context(ToPtr(0), 0, 0, 0); |
| |
| EXPECT_FALSE(context.ClaimHandle(Handle_Data(0))); |
| |
| // Should still return true for invalid handle. |
| EXPECT_TRUE(context.ClaimHandle( |
| Handle_Data(internal::kEncodedInvalidHandleValue))); |
| } |
| |
| { |
| // Test the case that |num_handles| is the same value as |
| // |internal::kEncodedInvalidHandleValue|. |
| EXPECT_EQ(internal::kEncodedInvalidHandleValue, |
| std::numeric_limits<uint32_t>::max()); |
| internal::ValidationContext context( |
| ToPtr(0), 0, std::numeric_limits<uint32_t>::max(), 0); |
| |
| EXPECT_TRUE(context.ClaimHandle( |
| Handle_Data(std::numeric_limits<uint32_t>::max() - 1))); |
| EXPECT_FALSE(context.ClaimHandle( |
| Handle_Data(std::numeric_limits<uint32_t>::max() - 1))); |
| EXPECT_FALSE(context.ClaimHandle(Handle_Data(0))); |
| |
| // Should still return true for invalid handle. |
| EXPECT_TRUE(context.ClaimHandle( |
| Handle_Data(internal::kEncodedInvalidHandleValue))); |
| } |
| } |
| |
| TEST(ValidationContextTest, ClaimAssociatedEndpointHandle) { |
| { |
| internal::ValidationContext context(ToPtr(0), 0, 0, 10); |
| |
| // Basics. |
| EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(0))); |
| EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(0))); |
| |
| EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(9))); |
| EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(10))); |
| |
| // Should fail because it is smaller than the max index that has been |
| // claimed. |
| EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(8))); |
| |
| // Should return true for invalid handle. |
| EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); |
| EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); |
| } |
| |
| { |
| // No handle to claim. |
| internal::ValidationContext context(ToPtr(0), 0, 0, 0); |
| |
| EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(0))); |
| |
| // Should still return true for invalid handle. |
| EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); |
| } |
| |
| { |
| // Test the case that |num_associated_endpoint_handles| is the same value as |
| // |internal::kEncodedInvalidHandleValue|. |
| EXPECT_EQ(internal::kEncodedInvalidHandleValue, |
| std::numeric_limits<uint32_t>::max()); |
| internal::ValidationContext context(ToPtr(0), 0, 0, |
| std::numeric_limits<uint32_t>::max()); |
| |
| EXPECT_TRUE( |
| context.ClaimAssociatedEndpointHandle(AssociatedEndpointHandle_Data( |
| std::numeric_limits<uint32_t>::max() - 1))); |
| EXPECT_FALSE( |
| context.ClaimAssociatedEndpointHandle(AssociatedEndpointHandle_Data( |
| std::numeric_limits<uint32_t>::max() - 1))); |
| EXPECT_FALSE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(0))); |
| |
| // Should still return true for invalid handle. |
| EXPECT_TRUE(context.ClaimAssociatedEndpointHandle( |
| AssociatedEndpointHandle_Data(internal::kEncodedInvalidHandleValue))); |
| } |
| } |
| |
| TEST(ValidationContextTest, ClaimMemory) { |
| { |
| internal::ValidationContext context(ToPtr(1000), 2000, 0, 0); |
| |
| // Basics. |
| EXPECT_FALSE(context.ClaimMemory(ToPtr(500), 100)); |
| EXPECT_FALSE(context.ClaimMemory(ToPtr(800), 300)); |
| EXPECT_TRUE(context.ClaimMemory(ToPtr(1000), 100)); |
| EXPECT_FALSE(context.ClaimMemory(ToPtr(1099), 100)); |
| EXPECT_TRUE(context.ClaimMemory(ToPtr(1100), 200)); |
| EXPECT_FALSE(context.ClaimMemory(ToPtr(2000), 1001)); |
| EXPECT_TRUE(context.ClaimMemory(ToPtr(2000), 500)); |
| EXPECT_FALSE(context.ClaimMemory(ToPtr(2000), 500)); |
| EXPECT_FALSE(context.ClaimMemory(ToPtr(1400), 100)); |
| EXPECT_FALSE(context.ClaimMemory(ToPtr(3000), 1)); |
| EXPECT_TRUE(context.ClaimMemory(ToPtr(2500), 500)); |
| } |
| |
| { |
| // No memory to claim. |
| internal::ValidationContext context(ToPtr(10000), 0, 0, 0); |
| |
| EXPECT_FALSE(context.ClaimMemory(ToPtr(10000), 1)); |
| EXPECT_FALSE(context.ClaimMemory(ToPtr(10000), 0)); |
| } |
| |
| { |
| internal::ValidationContext context( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 1000), 500, 0, 0); |
| |
| // Test overflow. |
| EXPECT_FALSE(context.ClaimMemory( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 750), 4000)); |
| EXPECT_FALSE( |
| context.ClaimMemory(ToPtr(std::numeric_limits<uintptr_t>::max() - 750), |
| std::numeric_limits<uint32_t>::max())); |
| |
| // This should be fine. |
| EXPECT_TRUE(context.ClaimMemory( |
| ToPtr(std::numeric_limits<uintptr_t>::max() - 750), 200)); |
| } |
| } |
| |
| } // namespace |
| } // namespace test |
| } // namespace mojo |