/* * 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 #include 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. }