Ruby  3.1.4p223 (2023-03-30 revision HEAD)
sanitizers.h
1 #ifndef INTERNAL_SANITIZERS_H /*-*-C-*-vi:se ft=c:*/
2 #define INTERNAL_SANITIZERS_H
11 #include "ruby/internal/config.h"
12 #include "internal/compilers.h" /* for __has_feature */
13 
14 #ifdef HAVE_VALGRIND_MEMCHECK_H
15 # include <valgrind/memcheck.h>
16 #endif
17 
18 #ifdef HAVE_SANITIZER_ASAN_INTERFACE_H
19 # include <sanitizer/asan_interface.h>
20 #endif
21 
22 #ifdef HAVE_SANITIZER_MSAN_INTERFACE_H
23 # if __has_feature(memory_sanitizer)
24 # include <sanitizer/msan_interface.h>
25 # endif
26 #endif
27 
28 #include "ruby/internal/stdbool.h" /* for bool */
29 #include "ruby/ruby.h" /* for VALUE */
30 
31 #if 0
32 #elif __has_feature(memory_sanitizer) && __has_feature(address_sanitizer)
33 # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
34  __attribute__((__no_sanitize__("memory, address"), __noinline__)) x
35 #elif __has_feature(address_sanitizer)
36 # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
37  __attribute__((__no_sanitize__("address"), __noinline__)) x
38 #elif defined(NO_SANITIZE_ADDRESS)
39 # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
40  NO_SANITIZE_ADDRESS(NOINLINE(x))
41 #elif defined(NO_ADDRESS_SAFETY_ANALYSIS)
42 # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
43  NO_ADDRESS_SAFETY_ANALYSIS(NOINLINE(x))
44 #else
45 # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) x
46 #endif
47 
48 #if defined(NO_SANITIZE) && RBIMPL_COMPILER_IS(GCC)
49 /* GCC warns about unknown sanitizer, which is annoying. */
50 # include "internal/warnings.h"
51 # undef NO_SANITIZE
52 # define NO_SANITIZE(x, y) \
53  COMPILER_WARNING_PUSH; \
54  COMPILER_WARNING_IGNORED(-Wattributes); \
55  __attribute__((__no_sanitize__(x))) y; \
56  COMPILER_WARNING_POP
57 #endif
58 
59 #ifndef NO_SANITIZE
60 # define NO_SANITIZE(x, y) y
61 #endif
62 
63 #if !__has_feature(address_sanitizer)
64 # define __asan_poison_memory_region(x, y)
65 # define __asan_unpoison_memory_region(x, y)
66 # define __asan_region_is_poisoned(x, y) 0
67 #endif
68 
69 #if !__has_feature(memory_sanitizer)
70 # define __msan_allocated_memory(x, y) ((void)(x), (void)(y))
71 # define __msan_poison(x, y) ((void)(x), (void)(y))
72 # define __msan_unpoison(x, y) ((void)(x), (void)(y))
73 # define __msan_unpoison_string(x) ((void)(x))
74 #endif
75 
76 #ifdef VALGRIND_MAKE_READABLE
77 # define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
78 #endif
79 
80 #ifdef VALGRIND_MAKE_WRITABLE
81 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
82 #endif
83 
84 #ifndef VALGRIND_MAKE_MEM_DEFINED
85 # define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
86 #endif
87 
88 #ifndef VALGRIND_MAKE_MEM_UNDEFINED
89 # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
90 #endif
91 
92 #ifndef MJIT_HEADER
93 
107 static inline void
108 asan_poison_memory_region(const volatile void *ptr, size_t size)
109 {
110  __msan_poison(ptr, size);
111  __asan_poison_memory_region(ptr, size);
112 }
113 
119 static inline void
120 asan_poison_object(VALUE obj)
121 {
122  MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
123  asan_poison_memory_region(ptr, SIZEOF_VALUE);
124 }
125 
126 #if !__has_feature(address_sanitizer)
127 #define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj))
128 #else
129 #define asan_poison_object_if(ptr, obj) do { \
130  if (ptr) asan_poison_object(obj); \
131  } while (0)
132 #endif
133 
141 static inline void *
142 asan_poisoned_object_p(VALUE obj)
143 {
144  MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
145  return __asan_region_is_poisoned(ptr, SIZEOF_VALUE);
146 }
147 
163 static inline void
164 asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p)
165 {
166  __asan_unpoison_memory_region(ptr, size);
167  if (malloc_p) {
168  __msan_allocated_memory(ptr, size);
169  }
170  else {
171  __msan_unpoison(ptr, size);
172  }
173 }
174 
181 static inline void
182 asan_unpoison_object(VALUE obj, bool newobj_p)
183 {
184  MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
185  asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p);
186 }
187 
188 #endif /* MJIT_HEADER */
189 
190 #endif /* INTERNAL_SANITIZERS_H */
C99 shim for <stdbool.h>
Definition: gc.c:572
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
Definition: value.h:69
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40