Ruby 3.2.1p31 (2023-02-08 revision 31819e82c88c6f8ecfaeb162519bfa26a14b21fd)
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
107static inline void
108asan_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
119static inline void
120asan_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
141static inline void *
142asan_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
163static inline void
164asan_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
181static inline void
182asan_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:582
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
#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