|  | /* | 
|  | * Copyright 2023 Google LLC | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "include/private/base/SkAssert.h" | 
|  | #include "include/private/base/SkMalloc.h" | 
|  | #include "tests/Test.h" | 
|  |  | 
|  | #include <cstddef> | 
|  | #include <cstdint> | 
|  |  | 
|  | DEF_TEST(SkFree_SafeToPassNull, reporter) { | 
|  | // This test passes by not crashing | 
|  | sk_free(nullptr); | 
|  | } | 
|  |  | 
|  | DEF_TEST(SkCalloc_DataIsZeroInitializedAndWriteable, reporter) { | 
|  | constexpr size_t alloc_count = 100; | 
|  |  | 
|  | uint8_t* bytes = (uint8_t*) sk_calloc_throw(alloc_count); // provide num bytes directly | 
|  | SkASSERT_RELEASE(bytes != nullptr); | 
|  | for (size_t i = 0; i < alloc_count; i++) { | 
|  | REPORTER_ASSERT(reporter, bytes[i] == 0); | 
|  | bytes[i] = (uint8_t)i; | 
|  | } | 
|  | sk_free(bytes); | 
|  |  | 
|  | int32_t* ints = (int32_t*) sk_calloc_throw(alloc_count, sizeof(int32_t)); // count + elem size | 
|  | SkASSERT_RELEASE(ints != nullptr); | 
|  | for (size_t i = 0; i < alloc_count; i++) { | 
|  | REPORTER_ASSERT(reporter, ints[i] == 0); | 
|  | ints[i] = (int32_t)i; | 
|  | } | 
|  | sk_free(ints); | 
|  | } | 
|  |  | 
|  | DEF_TEST(SkMalloc_DataIsWriteable, reporter) { | 
|  | constexpr size_t alloc_count = 100; | 
|  |  | 
|  | uint8_t* bytes = (uint8_t*) sk_malloc_throw(alloc_count); // provide num bytes directly | 
|  | SkASSERT_RELEASE(bytes != nullptr); | 
|  | for (size_t i = 0; i < alloc_count; i++) { | 
|  | bytes[i] = (uint8_t)i; | 
|  | } | 
|  | sk_free(bytes); | 
|  |  | 
|  | int32_t* ints = (int32_t*) sk_malloc_throw(alloc_count, sizeof(int32_t)); // count + elem size | 
|  | SkASSERT_RELEASE(ints != nullptr); | 
|  | for (size_t i = 0; i < alloc_count; i++) { | 
|  | ints[i] = (int32_t)i; | 
|  | } | 
|  | sk_free(ints); | 
|  | } | 
|  |  | 
|  | DEF_TEST(SkRealloc_DataIsWriteableAndEventuallyFreed, reporter) { | 
|  | // Calling sk_realloc_throw with null should be treated as if it was sk_malloc_throw | 
|  | uint8_t* bytes = (uint8_t*) sk_realloc_throw(nullptr, 10); | 
|  | SkASSERT_RELEASE(bytes != nullptr); | 
|  | // Make sure those 10 bytes are writeable | 
|  | for (size_t i = 0; i < 10; i++) { | 
|  | bytes[i] = (uint8_t)i; | 
|  | } | 
|  |  | 
|  | // Make it smaller | 
|  | bytes = (uint8_t*) sk_realloc_throw(bytes, 5); | 
|  | SkASSERT_RELEASE(bytes != nullptr); | 
|  | // Make sure those 5 bytes are still writeable and contain the previous values | 
|  | for (int i = 0; i < 5; i++) { | 
|  | REPORTER_ASSERT(reporter, bytes[i] == i, "bytes[%d] != %d", i, i); | 
|  | bytes[i] = (uint8_t)i + 17; | 
|  | } | 
|  |  | 
|  | // Make it bigger | 
|  | bytes = (uint8_t*) sk_realloc_throw(bytes, 20, sizeof(uint8_t)); // count + elem size | 
|  | SkASSERT_RELEASE(bytes != nullptr); | 
|  | // Make sure the first 5 bytes are still writeable and contain the previous values | 
|  | for (int i = 0; i < 5; i++) { | 
|  | REPORTER_ASSERT(reporter, bytes[i] == (i + 17), "bytes[%d] != %d", i, i+17); | 
|  | bytes[i] = (uint8_t)i + 43; | 
|  | } | 
|  | // The next 15 bytes are uninitialized, so just make sure we can write to them. | 
|  | for (int i = 5; i < 20; i++) { | 
|  | bytes[i] = (uint8_t)i + 43; | 
|  | } | 
|  |  | 
|  | // This should free the memory and return nullptr. | 
|  | bytes = (uint8_t*) sk_realloc_throw(bytes, 0); | 
|  | REPORTER_ASSERT(reporter, bytes == nullptr); | 
|  | // We run our tests with LeakSanitizer, so if bytes is *not* freed, we should see a failure. | 
|  | } |