blob: 7caf59eae15d9939aaeec5e80a946c8c34456af8 [file]
/*
* Copyright 2026 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/SkAssert.h"
#include "include/private/SkTypeTraits.h"
#include "src/partition_alloc/raw_ptr.h"
#include "src/partition_alloc/raw_ref.h"
#include "tests/Test.h"
#include <memory>
#include <tuple>
#if defined(SK_USE_PARTITION_ALLOC)
#include <partition_alloc/buildflags.h>
#if PA_BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS)
#include <partition_alloc/dangling_raw_ptr_checks.h>
namespace {
class ScopedDanglingPointerTracker {
public:
ScopedDanglingPointerTracker()
: fOldDetectedFn(partition_alloc::GetDanglingRawPtrDetectedFn())
, fOldReleasedFn(partition_alloc::GetDanglingRawPtrReleasedFn()) {
gDetected = false;
gReleased = false;
partition_alloc::SetDanglingRawPtrDetectedFn([](uintptr_t) { gDetected = true; });
partition_alloc::SetDanglingRawPtrReleasedFn([](uintptr_t) { gReleased = true; });
}
~ScopedDanglingPointerTracker() {
partition_alloc::SetDanglingRawPtrDetectedFn(fOldDetectedFn);
partition_alloc::SetDanglingRawPtrReleasedFn(fOldReleasedFn);
}
bool detected() const { return gDetected; }
bool released() const { return gReleased; }
private:
static inline bool gDetected = false;
static inline bool gReleased = false;
partition_alloc::DanglingRawPtrDetectedFn* fOldDetectedFn;
partition_alloc::DanglingRawPtrReleasedFn* fOldReleasedFn;
};
} // namespace
// This test temporarily affects global PartitionAlloc state by replacing
// detection and release handlers, so it cannot run in parallel.
DEF_SERIAL_TEST(RawPtr_DanglingPointerDetected, reporter) {
ScopedDanglingPointerTracker tracker;
std::unique_ptr<int> owner = std::make_unique<int>(42);
raw_ptr<int> ptr = owner.get();
REPORTER_ASSERT(reporter, !tracker.detected());
REPORTER_ASSERT(reporter, !tracker.released());
owner.reset();
REPORTER_ASSERT(reporter, tracker.detected());
REPORTER_ASSERT(reporter, !tracker.released());
ptr = nullptr;
REPORTER_ASSERT(reporter, tracker.detected());
REPORTER_ASSERT(reporter, tracker.released());
}
#endif
#endif
DEF_TEST(RawPtr_DisableDanglingPtrDetection, reporter) {
std::unique_ptr<int> owner = std::make_unique<int>(42);
raw_ptr<int, DisableDanglingPtrDetection> ptr = owner.get();
std::ignore = ptr;
owner.reset();
}
static_assert(sk_is_trivially_relocatable<raw_ptr<int>>::value);
static_assert(sk_is_trivially_relocatable<raw_ptr<int, DisableDanglingPtrDetection>>::value);
static_assert(sk_is_trivially_relocatable<raw_ref<int>>::value);
static_assert(sk_is_trivially_relocatable<raw_ref<int, DisableDanglingPtrDetection>>::value);