chromium/base/memory/safety_checks.h

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_MEMORY_SAFETY_CHECKS_H_
#define BASE_MEMORY_SAFETY_CHECKS_H_

#include <new>
#include <type_traits>

#include "base/compiler_specific.h"
#include "base/dcheck_is_on.h"
#include "partition_alloc/buildflags.h"
#include "partition_alloc/partition_alloc_constants.h"

#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
#include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h"
#endif  // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

// This header defines `ADVANCED_MEMORY_SAFETY_CHECKS()` macro.
// They can be used to specify a class/struct that is targeted to perform
// additional CHECKS across variety of memory safety mechanisms such as
// PartitionAllocator.
//   ```
//   class Foo {
//     ADVANCED_MEMORY_SAFETY_CHECKS();
//   }
//   ```
// Checks here are disabled by default because of their performance cost.
// Currently, the macro is managed by the memory safety team internally and
// you should not add / remove it manually.
//
// Additional checks here are categorized into either one of enum
// `MemorySafetyCheck`. Some of them are too costly and disabled even for
// `ADVANCED_MEMORY_SAFETY_CHECKS()` annotated types. These checks can be
// enabled by passing optional arguments to the macro.
//   ```
//   class Foo {
//     ADVANCED_MEMORY_SAFETY_CHECKS(
//       /*enable=*/ kFoo | kBar);
//   }
//   ```
// It is also possible to disable default checks for annotated types.
//   ```
//   class Foo {
//     ADVANCED_MEMORY_SAFETY_CHECKS(
//       /*enable=*/  kFoo,
//       /*disable=*/ kBaz);
//   }
//   ```

// We cannot hide things behind anonymous namespace because they are referenced
// via macro, which can be defined anywhere.
// To avoid tainting ::base namespace, define things inside this namespace.
namespace base::internal {

enum class MemorySafetyCheck : uint32_t {};

constexpr MemorySafetyCheck operator|(MemorySafetyCheck a,
                                      MemorySafetyCheck b) {}

constexpr MemorySafetyCheck operator&(MemorySafetyCheck a,
                                      MemorySafetyCheck b) {}

constexpr MemorySafetyCheck operator~(MemorySafetyCheck a) {}

// Set of checks for ADVANCED_MEMORY_SAFETY_CHECKS() annotated objects.
constexpr auto kAdvancedMemorySafetyChecks =;

// Define type traits to determine type |T|'s memory safety check status.
namespace {

// Allocator type traits.
constexpr bool ShouldUsePartitionAlloc(MemorySafetyCheck checks) {}

// Returns |partition_alloc::AllocFlags| corresponding to |checks|.
constexpr partition_alloc::AllocFlags GetAllocFlags(MemorySafetyCheck checks) {}

// Returns |partition_alloc::FreeFlags| corresponding to |checks|.
constexpr partition_alloc::FreeFlags GetFreeFlags(MemorySafetyCheck checks) {}

}  // namespace

// Public utility type traits.
get_memory_safety_checks;

is_memory_safety_checked;

// Allocator functions.
#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
ALWAYS_INLINE partition_alloc::PartitionRoot*
GetPartitionRootForMemorySafetyCheckedAllocation() {}
#endif  // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)

template <MemorySafetyCheck checks>
NOINLINE void* HandleMemorySafetyCheckedOperatorNew(std::size_t count) {}

template <MemorySafetyCheck checks>
NOINLINE void* HandleMemorySafetyCheckedOperatorNew(
    std::size_t count,
    std::align_val_t alignment) {}

template <MemorySafetyCheck checks>
NOINLINE void HandleMemorySafetyCheckedOperatorDelete(void* ptr) {}

template <MemorySafetyCheck checks>
NOINLINE void HandleMemorySafetyCheckedOperatorDelete(
    void* ptr,
    std::align_val_t alignment) {}

}  // namespace base::internal

// Macros to annotate class/struct's default memory safety check.
// ADVANCED_MEMORY_SAFETY_CHECKS(): Enable Check |kAdvancedChecks| for this
// object.
//
// Note that if you use this macro at the top of struct declaration, the
// declaration context would be left as |private|. Please switch it back to
// |public| manually if needed.
//
//   struct ObjectWithAdvancedChecks {
//     ADVANCED_MEMORY_SAFETY_CHECKS();
//   public:
//     int public_field;
//   };
#define MEMORY_SAFETY_CHECKS_INTERNAL(SPECIFIER, DEFAULT_CHECKS,               \
                                      ENABLED_CHECKS, DISABLED_CHECKS, ...)

#if DCHECK_IS_ON()
// Specify NOINLINE to display the operator on a stack trace.
// When 2 args provided, these two are passed to `ENABLED_CHECKS` and
// `DISABLED_CHECKS`. A couple of `MemorySafetyCheck::kNone` is ignored.
// When 1 arg provided, the one is passed to `ENABLED_CHECKS` and the first
// `MemorySafetyCheck::kNone` serves a default value for `DISABLED_CHECKS`.
// When 0 arg provided, both of `MemorySafetyCheck::kNone`s serve as default
// values for `ENABLED_CHECKS` and `DISABLED_CHECKS` accordingly.
#define ADVANCED_MEMORY_SAFETY_CHECKS(...)
#else
#define ADVANCED_MEMORY_SAFETY_CHECKS
#endif  // DCHECK_IS_ON()

// When a struct/class with `ADVANCED_MEMORY_SAFETY_CHECKS()` is inherited, a
// derived struct/class operator will use customized `operator new()` and
// `operator delete()` too. If a class has multiple base classes with the macro,
// a compiler may complain ambiguity between multiple `operator new()`s. On the
// other hand, if a class uses private inheritance, a compiler may report
// private `operator new()` that is making impossible to `new` that class. We
// have two utility macros to resolve these issues:
// - `INHERIT_MEMORY_SAFETY_CHECKS(BaseClass)`
//       Explicitly exports operators from given `BaseClass` to re-apply
//       checks specified in the parent class. This is the recommended option as
//       a derived class is likely to have the same characteristics to its baes
//       class. This macro accepts additional arguments to overwrite
//       `BaseClass`'s opted-in checks.
//         ```
//         INHERIT_MEMORY_SAFETY_CHECKS(BaseClass,
//           /*enable=*/  kFoo | kBar,
//           /*disable=*/ kBaz);
//         ```
// - `DEFAULT_MEMORY_SAFETY_CHECKS()`
//       Re-define default `operator new()` and `operator delete()` using
//       global operators that comes with default checks. This macro accepts
//       additional arguments to enable some checks manually.
//         ```
//         DEFAULT_MEMORY_SAFETY_CHECKS(BaseClass,
//           /*enable=*/ kFoo | kBar);
//         ```
//
// Note that if you use these macros at the top of struct declaration, the
// declaration context would be left as |private|. Please switch it back to
// |public| manually if needed.
#define INHERIT_MEMORY_SAFETY_CHECKS(BASE_CLASS, ...)

#define DEFAULT_MEMORY_SAFETY_CHECKS(...)

#endif  // BASE_MEMORY_SAFETY_CHECKS_H_