1d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov/* 2d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * Copyright (C) 2013 The Android Open Source Project 3d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * 4d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * Licensed under the Apache License, Version 2.0 (the "License"); 5d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * you may not use this file except in compliance with the License. 6d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * You may obtain a copy of the License at 7d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * 8d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * http://www.apache.org/licenses/LICENSE-2.0 9d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * 10d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * Unless required by applicable law or agreed to in writing, software 11d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * distributed under the License is distributed on an "AS IS" BASIS, 12d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * See the License for the specific language governing permissions and 14d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * limitations under the License. 15d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov */ 16d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 17d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov#include <stdlib.h> 18d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov#include <string.h> 19d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov#include <sys/mman.h> 20d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 21d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov#include <gtest/gtest.h> 22d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 23d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov#include "../linker_allocator.h" 24d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 25d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov#include <unistd.h> 26d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 27d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanovnamespace { 28d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 29d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanovstruct test_struct_nominal { 30d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov void* pointer; 31d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ssize_t value; 32d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov}; 33d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 34d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov/* 35d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * this one has size below allocator cap which is 2*sizeof(void*) 36d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov */ 37d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanovstruct test_struct_small { 38d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov char dummy_str[5]; 39d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov}; 40d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 41d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov/* 42d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov * 1009 byte struct (1009 is prime) 43d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov */ 44d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanovstruct test_struct_larger { 45d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov char dummy_str[1009]; 46d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov}; 47d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 48d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanovstatic size_t kPageSize = sysconf(_SC_PAGE_SIZE); 49d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov}; 50d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 51d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy IvanovTEST(linker_allocator, test_nominal) { 52d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov LinkerAllocator<test_struct_nominal> allocator; 53d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 54d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov test_struct_nominal* ptr1 = allocator.alloc(); 55d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_TRUE(ptr1 != nullptr); 56d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov test_struct_nominal* ptr2 = allocator.alloc(); 57d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_TRUE(ptr2 != nullptr); 58d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov // they should be next to each other. 59d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_EQ(ptr1+1, ptr2); 60d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 61d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ptr1->value = 42; 62d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 63d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov allocator.free(ptr1); 64d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov allocator.free(ptr2); 65d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov} 66d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 67d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy IvanovTEST(linker_allocator, test_small) { 68d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov LinkerAllocator<test_struct_small> allocator; 69d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 70d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov char* ptr1 = reinterpret_cast<char*>(allocator.alloc()); 71d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov char* ptr2 = reinterpret_cast<char*>(allocator.alloc()); 72d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 73d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_TRUE(ptr1 != nullptr); 74d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_TRUE(ptr2 != nullptr); 75d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_EQ(ptr1+2*sizeof(void*), ptr2); 76d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov} 77d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 78d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy IvanovTEST(linker_allocator, test_larger) { 79d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov LinkerAllocator<test_struct_larger> allocator; 80d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 81d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov test_struct_larger* ptr1 = allocator.alloc(); 82d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov test_struct_larger* ptr2 = allocator.alloc(); 83d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 84d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_TRUE(ptr1 != nullptr); 85d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_TRUE(ptr2 != nullptr); 86d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 87d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_EQ(ptr1+1, ptr2); 88d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 89d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov // lets allocate until we reach next page. 90d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov size_t n = kPageSize/sizeof(test_struct_larger) + 1 - 2; 91d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 92d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov for (size_t i=0; i<n; ++i) { 93d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_TRUE(allocator.alloc() != nullptr); 94d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov } 95d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 961079406cab09090cc11e26d4ac2f1ba9c4930cdbDmitriy Ivanov test_struct_larger* ptr_to_free = allocator.alloc(); 971079406cab09090cc11e26d4ac2f1ba9c4930cdbDmitriy Ivanov ASSERT_TRUE(ptr_to_free != nullptr); 981079406cab09090cc11e26d4ac2f1ba9c4930cdbDmitriy Ivanov allocator.free(ptr1); 99d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov} 100d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 101d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanovstatic void protect_all() { 102d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov LinkerAllocator<test_struct_larger> allocator; 103d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 104d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov // number of allocs to reach the end of first page 105d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov size_t n = kPageSize/sizeof(test_struct_larger) - 1; 106d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov test_struct_larger* page1_ptr = allocator.alloc(); 107d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 108d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov for (size_t i=0; i<n; ++i) { 109d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov allocator.alloc(); 110d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov } 111d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 112d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov test_struct_larger* page2_ptr = allocator.alloc(); 113d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov allocator.protect_all(PROT_READ); 114d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov allocator.protect_all(PROT_READ | PROT_WRITE); 115d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov // check access 116d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov page2_ptr->dummy_str[23] = 27; 117d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov page1_ptr->dummy_str[13] = 11; 118d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 119d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov allocator.protect_all(PROT_READ); 120d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov fprintf(stderr, "trying to access protected page"); 121d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 122d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov // this should result in segmentation fault 123d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov page1_ptr->dummy_str[11] = 7; 124d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov} 125d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 126d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy IvanovTEST(linker_allocator, test_protect) { 127d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov testing::FLAGS_gtest_death_test_style = "threadsafe"; 128d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov ASSERT_EXIT(protect_all(), testing::KilledBySignal(SIGSEGV), "trying to access protected page"); 129d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov} 130d597d263bc32422402d4810ce4ec070f0227c2f7Dmitriy Ivanov 131