xref: /aosp_15_r20/external/cronet/base/memory/raw_ptr_asan_service.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_MEMORY_RAW_PTR_ASAN_SERVICE_H_
6 #define BASE_MEMORY_RAW_PTR_ASAN_SERVICE_H_
7 
8 #include "partition_alloc/partition_alloc_buildflags.h"
9 
10 #if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
11 #include <cstddef>
12 #include <cstdint>
13 
14 #include "base/base_export.h"
15 #include "base/compiler_specific.h"
16 #include "base/types/strong_alias.h"
17 
18 namespace base {
19 
20 using EnableDereferenceCheck =
21     base::StrongAlias<class EnableDereferenceCheckTag, bool>;
22 using EnableExtractionCheck =
23     base::StrongAlias<class EnableExtractionCheckTag, bool>;
24 using EnableInstantiationCheck =
25     base::StrongAlias<class EnableInstantiationCheckTag, bool>;
26 
27 class BASE_EXPORT RawPtrAsanService {
28  public:
29   enum class ReportType {
30     kDereference,
31     kExtraction,
32     kInstantiation,
33   };
34 
35   struct PendingReport {
36     ReportType type = ReportType::kDereference;
37     uintptr_t allocation_base = 0;
38     size_t allocation_size = 0;
39   };
40 
41   void Configure(EnableDereferenceCheck,
42                  EnableExtractionCheck,
43                  EnableInstantiationCheck);
44 
45   bool IsSupportedAllocation(void*) const;
46 
IsEnabled()47   bool IsEnabled() const { return mode_ == Mode::kEnabled; }
48 
49   ALWAYS_INLINE NO_SANITIZE(
is_dereference_check_enabled()50       "address") bool is_dereference_check_enabled() const {
51     return is_dereference_check_enabled_;
52   }
53 
54   ALWAYS_INLINE NO_SANITIZE(
is_extraction_check_enabled()55       "address") bool is_extraction_check_enabled() const {
56     return is_extraction_check_enabled_;
57   }
58 
59   ALWAYS_INLINE NO_SANITIZE(
is_instantiation_check_enabled()60       "address") bool is_instantiation_check_enabled() const {
61     return is_instantiation_check_enabled_;
62   }
63 
GetInstance()64   ALWAYS_INLINE NO_SANITIZE("address") static RawPtrAsanService& GetInstance() {
65     return instance_;
66   }
67 
68   void WarnOnDanglingExtraction(const volatile void* ptr) const;
69   void CrashOnDanglingInstantiation(const volatile void* ptr) const;
70 
71   static void SetPendingReport(ReportType type, const volatile void* ptr);
72 
73  private:
74   enum class Mode {
75     kUninitialized,
76     kDisabled,
77     kEnabled,
78   };
79 
80   uint8_t* GetShadow(void* ptr) const;
81 
82   static void MallocHook(const volatile void*, size_t);
FreeHook(const volatile void *)83   static void FreeHook(const volatile void*) {}
84   static void ErrorReportCallback(const char* report,
85                                   bool* should_exit_cleanly);
86 
87   Mode mode_ = Mode::kUninitialized;
88   bool is_dereference_check_enabled_ = false;
89   bool is_extraction_check_enabled_ = false;
90   bool is_instantiation_check_enabled_ = false;
91 
92   size_t shadow_offset_ = 0;
93 
94   static RawPtrAsanService instance_;  // Not a static local variable because
95                                        // `GetInstance()` is used in hot paths.
96 };
97 
98 }  // namespace base
99 
100 #endif  // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
101 #endif  // BASE_MEMORY_RAW_PTR_ASAN_SERVICE_H_
102