Ruby: internal/sanitizers.h Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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