Ruby 3.3.0p0 (2023-12-25 revision 5124f9ac7513eb590c37717337c430cb93caa151)
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
105static inline void
106asan_poison_memory_region(const volatile void *ptr, size_t size)
107{
108 __msan_poison(ptr, size);
109 __asan_poison_memory_region(ptr, size);
110}
111
117static inline void
118asan_poison_object(VALUE obj)
119{
120 MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
121 asan_poison_memory_region(ptr, SIZEOF_VALUE);
122}
123
124#if !__has_feature(address_sanitizer)
125#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj))
126#else
127#define asan_poison_object_if(ptr, obj) do { \
128 if (ptr) asan_poison_object(obj); \
129 } while (0)
130#endif
131
139static inline void *
140asan_poisoned_object_p(VALUE obj)
141{
142 MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
143 return __asan_region_is_poisoned(ptr, SIZEOF_VALUE);
144}
145
161static inline void
162asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p)
163{
164 __asan_unpoison_memory_region(ptr, size);
165 if (malloc_p) {
166 __msan_allocated_memory(ptr, size);
167 }
168 else {
169 __msan_unpoison(ptr, size);
170 }
171}
172
179static inline void
180asan_unpoison_object(VALUE obj, bool newobj_p)
181{
182 MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
183 asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p);
184}
185
186#endif /* INTERNAL_SANITIZERS_H */
C99 shim for <stdbool.h>
Definition gc.c:653
#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