WPILibC++ 2027.0.0-alpha-3
Loading...
Searching...
No Matches
sanitizers.h
Go to the documentation of this file.
1// Protocol Buffers - Google's data interchange format
2// Copyright 2025 Google LLC. All rights reserved.
3//
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
7
8#ifndef UPB_PORT_SANITIZERS_H_
9#define UPB_PORT_SANITIZERS_H_
10
11#include <stddef.h>
12#include <stdint.h>
13#include <stdio.h>
14
15// Must be last.
16#include "upb/port/def.inc"
17
18// Must be inside def.inc/undef.inc
19#if UPB_HWASAN
20#include <sanitizer/hwasan_interface.h>
21#endif
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27// UPB_ARENA_SIZE_HACK depends on this struct having size 1.
28typedef struct {
29 uint8_t state;
30} upb_Xsan;
31
33#if UPB_HWASAN
34 xsan->state++;
35 if (xsan->state <= UPB_HWASAN_POISON_TAG) {
36 xsan->state = UPB_HWASAN_POISON_TAG + 1;
37 }
38 return xsan->state;
39#else
40 return 0;
41#endif
42}
43
44enum {
45#if UPB_ASAN
46 UPB_PRIVATE(kUpb_Asan_GuardSize) = 32,
47#else
48 UPB_PRIVATE(kUpb_Asan_GuardSize) = 0,
49#endif
50};
51
52UPB_INLINE uint8_t UPB_PRIVATE(_upb_Xsan_GetTag)(const void *addr) {
53#if UPB_HWASAN
54 return __hwasan_get_tag_from_pointer(addr);
55#else
56 return 0;
57#endif
58}
59
61#if UPB_HWASAN || UPB_TSAN
62 xsan->state = 0;
63#endif
64}
65
66// Marks the given region as poisoned, meaning that it is not accessible until
67// it is unpoisoned.
69 size_t size) {
70#if UPB_ASAN
71 void __asan_poison_memory_region(void const volatile *addr, size_t size);
72 __asan_poison_memory_region(addr, size);
73#elif UPB_HWASAN
74 __hwasan_tag_memory(addr, UPB_HWASAN_POISON_TAG, UPB_ALIGN_MALLOC(size));
75#endif
76}
77
78UPB_INLINE void *UPB_PRIVATE(_upb_Xsan_UnpoisonRegion)(void *addr, size_t size,
79 uint8_t tag) {
80#if UPB_ASAN
81 UPB_UNUSED(tag);
82 void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
83 __asan_unpoison_memory_region(addr, size);
84 return addr;
85#elif UPB_HWASAN
86 __hwasan_tag_memory(addr, tag, UPB_ALIGN_MALLOC(size));
87 return __hwasan_tag_pointer(addr, tag);
88#else
89 UPB_UNUSED(size);
90 UPB_UNUSED(tag);
91
92 // `addr` is the pointer that will be returned from arena alloc/realloc
93 // functions. In this code-path we know it must be non-NULL, but the compiler
94 // doesn't know this unless we add a UPB_ASSUME() annotation.
95 //
96 // This will let the optimizer optimize away NULL-checks if it can see that
97 // this path was taken.
98 UPB_ASSUME(addr);
99 return addr;
100#endif
101}
102
103// Allows users to read and write to the given region, which will be considered
104// distinct from other regions and may only be accessed through the returned
105// pointer.
106//
107// `addr` must be aligned to the malloc alignment. Size may be unaligned,
108// and with ASAN we can respect `size` precisely, but with HWASAN we must
109// round `size` up to the next multiple of the malloc alignment, so the caller
110// must guarantee that rounding up `size` will not cause overlap with other
111// regions.
113 void *addr,
114 size_t size) {
115 return UPB_PRIVATE(_upb_Xsan_UnpoisonRegion)(addr, size,
116 _upb_Xsan_NextTag(xsan));
117}
118
119// Resizes the given region to a new size, *without* invalidating any existing
120// pointers to the region.
121//
122// `tagged_addr` must be a pointer that was previously returned from
123// `upb_Xsan_NewUnpoisonedRegion`. `old_size` must be the size that was
124// originally passed to `upb_Xsan_NewUnpoisonedRegion`.
126 size_t old_size,
127 size_t new_size) {
128 UPB_PRIVATE(upb_Xsan_PoisonRegion)(tagged_addr, old_size);
130 tagged_addr, new_size, UPB_PRIVATE(_upb_Xsan_GetTag)(tagged_addr));
131}
132
133// Compares two pointers and returns true if they are equal. This returns the
134// correct result even if one or both of the pointers are tagged.
135UPB_INLINE bool UPB_PRIVATE(upb_Xsan_PtrEq)(const void *a, const void *b) {
136#if UPB_HWASAN
137 return __hwasan_tag_pointer(a, 0) == __hwasan_tag_pointer(b, 0);
138#else
139 return a == b;
140#endif
141}
142
143// These annotations improve TSAN's ability to detect data races. By
144// proactively accessing a non-atomic variable at the point where it is
145// "logically" accessed, we can trigger TSAN diagnostics that might have
146// otherwise been masked by subsequent atomic operations.
147
149#if UPB_TSAN
150 // For performance we avoid using a volatile variable.
151 __asm__ volatile("" ::"r"(xsan->state));
152#endif
153}
154
156#if UPB_TSAN
157 // For performance we avoid using a volatile variable.
158 __asm__ volatile("" : "+r"(xsan->state));
159#endif
160}
161
162#ifdef __cplusplus
163} /* extern "C" */
164#endif
165
166#include "upb/port/undef.inc"
167
168#endif // UPB_PORT_SANITIZERS_H_
#define UPB_UNUSED(var)
Definition def.inc:303
#define UPB_ASSUME(expr)
Definition def.inc:319
#define UPB_ALIGN_MALLOC(size)
Definition def.inc:207
#define UPB_INLINE
Definition def.inc:144
UPB_INLINE void UPB_PRIVATE upb_Xsan_PoisonRegion(const void *addr, size_t size)
Definition sanitizers.h:68
UPB_INLINE void *UPB_PRIVATE _upb_Xsan_UnpoisonRegion(void *addr, size_t size, uint8_t tag)
Definition sanitizers.h:78
UPB_INLINE bool UPB_PRIVATE upb_Xsan_PtrEq(const void *a, const void *b)
Definition sanitizers.h:135
UPB_INLINE void *UPB_PRIVATE upb_Xsan_NewUnpoisonedRegion(upb_Xsan *xsan, void *addr, size_t size)
Definition sanitizers.h:112
UPB_INLINE uint8_t _upb_Xsan_NextTag(upb_Xsan *xsan)
Definition sanitizers.h:32
@ UPB_PRIVATE
Definition sanitizers.h:48
UPB_INLINE void *UPB_PRIVATE upb_Xsan_ResizeUnpoisonedRegion(void *tagged_addr, size_t old_size, size_t new_size)
Definition sanitizers.h:125
UPB_INLINE void UPB_PRIVATE upb_Xsan_AccessReadWrite(upb_Xsan *xsan)
Definition sanitizers.h:155
UPB_INLINE void UPB_PRIVATE upb_Xsan_AccessReadOnly(upb_Xsan *xsan)
Definition sanitizers.h:148
UPB_INLINE uint8_t UPB_PRIVATE _upb_Xsan_GetTag(const void *addr)
Definition sanitizers.h:52
UPB_INLINE void UPB_PRIVATE upb_Xsan_Init(upb_Xsan *xsan)
Definition sanitizers.h:60
Definition sanitizers.h:28
uint8_t state
Definition sanitizers.h:29